def process_ibft(ui, interactive): """ Bring up any disks that the iBFT should be attached, and reserve the NICs that it says should be used for iSCSI """ if not have_ibft(): return try: iname, target_configs = read_ibft() except: # only raise exception if user decides to proceed if ui and interactive: msg = "Found iSCSI Boot Firmware Table\n\nAttach to disks specified in iBFT?" button = ButtonChoiceWindowEx(ui.screen, "Attach iSCSI disks" , msg, ['Yes', 'No']) if button == 'no': return raise else: # Do nothing if the iBFT contains no valid targets if len(target_configs) == 0: xelogging.log("process_ibft: No valid target configs found in iBFT") return # If interactive, ask user if he wants to proceed if ui and interactive: nics = list(set([ conf.iface for conf in target_configs ])) nics.sort() msg = \ "Found iSCSI Boot Firmware Table\n\nAttach to disks specified in iBFT?\n\n" \ "This will reserve %s for iSCSI disk access. Reserved NICs are not available " \ "for use as the management interface or for use by virtual machines." % " and ".join(nics) button = ButtonChoiceWindowEx(ui.screen, "Attach iSCSI disks" , msg, ['Yes', 'No'], width=60) if button == 'no': return # Bring up the targets for conf in target_configs: # Bring up interface if conf.iface not in ibft_reserved_nics: rv = util.runCmd2(['ifconfig', conf.iface, conf.ip, 'netmask', conf.nm]) assert rv == 0 ibft_reserved_nics.append(conf.iface) xelogging.log("process_ibft: reserving %s for access to iSCSI disk" % conf.iface) # Pin tgtip to this interface if netutil.network(conf.ip, conf.nm) == netutil.network(conf.tgtip, conf.nm): rv = util.runCmd2(['ip', 'route', 'add', conf.tgtip, 'dev', conf.iface]) else: assert conf.gw rv = util.runCmd2(['ip', 'route', 'add', conf.tgtip, 'dev', conf.iface, 'via', conf.gw]) # Attach to target (this creates new nodes /dev) spec = "iscsi:%s::%d:%d:%s" % (conf.tgtip, conf.port, conf.lun, conf.iqn) try: disk = attach_rfc4173(iname, spec) except Exception as e: xelogging.log_exception(e) raise RuntimeError, "Could not attach to iSCSI LUN %s" % spec xelogging.log("process_ibft: attached iSCSI disk %s." % disk)
def findXenSourceProducts(): """Scans the host and finds XenSource product installations. Returns list of ExistingInstallation objects. Currently requires supervisor privileges due to mounting filesystems.""" installs = [] for disk in diskutil.getQualifiedDiskList(): (boot, root, state, storage, logs) = diskutil.probeDisk(disk) inst = None try: if root[0] == diskutil.INSTALL_RETAIL: inst = ExistingRetailInstallation(disk, boot[1], root[1], state[1], storage) except Exception, e: xelogging.log( "A problem occurred whilst scanning for existing installations:" ) xelogging.log_exception(e) xelogging.log("This is not fatal. Continuing anyway.") if inst: xelogging.log("Found an installation: %s on %s" % (str(inst), disk)) installs.append(inst)
def find_installed_products(): try: installed_products = findXenSourceProducts() except Exception, e: xelogging.log("A problem occurred whilst scanning for existing installations:") xelogging.log_exception(e) xelogging.log("This is not fatal. Continuing anyway.") installed_products = []
def find_installed_products(): try: installed_products = findXenSourceProducts() except Exception, e: xelogging.log( "A problem occurred whilst scanning for existing installations:") xelogging.log_exception(e) xelogging.log("This is not fatal. Continuing anyway.") installed_products = []
def findXenSourceProducts(): """Scans the host and finds XenSource product installations. Returns list of ExistingInstallation objects. Currently requires supervisor privileges due to mounting filesystems.""" installs = [] for disk in diskutil.getQualifiedDiskList(): (boot, state, storage) = diskutil.probeDisk(disk) inst = None try: if boot[0] == diskutil.INSTALL_RETAIL: inst = ExistingRetailInstallation(disk, boot[1], state[1], storage) except Exception, e: xelogging.log("A problem occurred whilst scanning for existing installations:") xelogging.log_exception(e) xelogging.log("This is not fatal. Continuing anyway.") if inst: xelogging.log("Found an installation: %s" % str(inst)) installs.append(inst)
class ExistingInstallation: def __init__(self, primary_disk, boot_device, state_device): self.primary_disk = primary_disk self.boot_device = boot_device self.state_device = state_device self.state_prefix = '' self.settings = None self.root_fs = None self._boot_fs = None self.boot_fs_mount = None def __str__(self): return "%s %s" % (self.visual_brand, self.visual_version) def mount_state(self): """ Mount main state partition on self.state_fs. """ self.state_fs = util.TempMount( self.state_device, 'state-', ) def unmount_state(self): self.state_fs.unmount() self.state_fs = None def join_state_path(self, *path): """ Construct an absolute path to a file in the main state partition. """ return os.path.join(self.state_fs.mount_point, self.state_prefix, *path) def getInventoryValue(self, k): return self.inventory[k] def isUpgradeable(self): self.mount_state() try: # CA-38459: handle missing firstboot directory e.g. Rio if not os.path.exists( self.join_state_path('etc/firstboot.d/state')): return False firstboot_files = [ f for f in os.listdir(self.join_state_path('etc/firstboot.d')) \ if f[0].isdigit() and os.stat(self.join_state_path('etc/firstboot.d', f))[stat.ST_MODE] & stat.S_IXUSR ] missing_state_files = filter( lambda x: not os.path.exists( self.join_state_path('etc/firstboot.d/state', x)), firstboot_files) result = (len(missing_state_files) == 0) if not result: xelogging.log('Upgradeability test failed:') xelogging.log(' Firstboot: ' + ', '.join(firstboot_files)) xelogging.log(' Missing state: ' + ', '.join(missing_state_files)) finally: self.unmount_state() return result def settingsAvailable(self): try: self.readSettings() except SettingsNotAvailable, text: xelogging.log("Settings unavailable: %s" % text) return False except Exception, e: xelogging.log("Settings unavailable: unhandled exception") xelogging.log_exception(e) return False
def _readSettings(self): """ Read settings from the installation, returns a results dictionary. """ results = {'host-config': {}} self.mount_state() try: # timezone: tz = None clock_file = self.join_state_path('etc/localtime') if os.path.islink(clock_file): tzfile = os.path.realpath(clock_file) if '/usr/share/zoneinfo/' in tzfile: _, tz = tzfile.split('/usr/share/zoneinfo/', 1) if not tz: # No timezone found: # Supply a default and for interactive installs prompt the user. xelogging.log('No timezone configuration found.') results['request-timezone'] = True tz = "Europe/London" results['timezone'] = tz # hostname. We will assume one was set anyway and thus write # it back into the new filesystem. If one wasn't set then this # will be localhost.localdomain, in which case the old behaviour # will persist anyway: fd = open(self.join_state_path('etc/sysconfig/network'), 'r') lines = fd.readlines() fd.close() for line in lines: if line.startswith('HOSTNAME='): results['manual-hostname'] = (True, line[9:].strip()) if os.path.exists(self.join_state_path('etc/hostname')): fd = open(self.join_state_path('etc/hostname'), 'r') line = fd.readline() results['manual-hostname'] = (True, line.strip()) fd.close() if not results.has_key('manual-hostname'): results['manual-hostname'] = (False, None) # nameservers: domain = None if not os.path.exists(self.join_state_path('etc/resolv.conf')): results['manual-nameservers'] = (False, None) else: ns = [] fd = open(self.join_state_path('etc/resolv.conf'), 'r') lines = fd.readlines() fd.close() for line in lines: if line.startswith("nameserver "): ns.append(line[11:].strip()) elif line.startswith("domain "): domain = line[8:].strip() elif line.startswith("search "): domain = line.split()[1] results['manual-nameservers'] = (True, ns) # ntp servers: fd = open(self.join_state_path('etc/ntp.conf'), 'r') lines = fd.readlines() fd.close() ntps = [] for line in lines: if line.startswith("server "): ntps.append(line[7:].strip()) results['ntp-servers'] = ntps # keyboard: keyboard_dict = {} keyboard_file = self.join_state_path('etc/sysconfig/keyboard') if os.path.exists(keyboard_file): keyboard_dict = util.readKeyValueFile(keyboard_file) keyboard_file = self.join_state_path('etc/vconsole.conf') if os.path.exists(keyboard_file): keyboard_dict.update(util.readKeyValueFile(keyboard_file)) if 'KEYMAP' in keyboard_dict: results['keymap'] = keyboard_dict['KEYMAP'] elif 'KEYTABLE' in keyboard_dict: results['keymap'] = keyboard_dict['KEYTABLE'] # Do not error here if no keymap configuration is found. # This enables upgrade to still carry state on hosts without # keymap configured: # A default keymap is assigned in the backend of this installer. if not results.has_key('keymap'): xelogging.log('No existing keymap configuration found.') # root password: fd = open(self.join_state_path('etc/passwd'), 'r') root_pwd = None for line in fd: pwent = line.split(':') if pwent[0] == 'root': root_pwd = pwent[1] break fd.close() if len(root_pwd) == 1: root_pwd = None try: fd = open(self.join_state_path('etc/shadow'), 'r') for line in fd: pwent = line.split(':') if pwent[0] == 'root': root_pwd = pwent[1] break fd.close() except: pass if not root_pwd: raise SettingsNotAvailable, "no root password found" results['root-password'] = ('pwdhash', root_pwd) # don't care about this too much. results['time-config-method'] = 'ntp' # read network configuration. We only care to find out what the # management interface is, and what its configuration was. # The dev -> MAC mapping for other devices will be preserved in the # database which is available in time for everything except the # management interface. mgmt_iface = self.getInventoryValue('MANAGEMENT_INTERFACE') networkdb_path = constants.NETWORK_DB if not os.path.exists(self.join_state_path(networkdb_path)): networkdb_path = constants.OLD_NETWORK_DB dbcache_path = constants.DBCACHE if not os.path.exists(self.join_state_path(dbcache_path)): dbcache_path = constants.OLD_DBCACHE if not mgmt_iface: xelogging.log('No existing management interface found.') elif os.path.exists(self.join_state_path(networkdb_path)): networkd_db = constants.NETWORKD_DB if not os.path.exists(self.join_state_path(networkd_db)): networkd_db = constants.OLD_NETWORKD_DB xelogging.log( 'Checking %s for management interface configuration' % networkd_db) def fetchIfaceInfoFromNetworkdbAsDict(bridge, iface=None): args = [ 'chroot', self.state_fs.mount_point, '/' + networkd_db, '-bridge', bridge ] if iface: args.extend(['-iface', iface]) rv, out = util.runCmd2(args, with_stdout=True) d = {} for line in (x.strip() for x in out.split('\n') if len(x.strip())): for key_value in line.split(" "): var = key_value.split('=', 1) d[var[0]] = var[1] return d d = fetchIfaceInfoFromNetworkdbAsDict(mgmt_iface, mgmt_iface) # For mgmt on tagged vlan, networkdb output has no value for # 'interfaces' but instead has 'parent' specified. We need # to fetch 'interfaces' of parent and use for mgmt bridge. if not d.get('interfaces') and 'parent' in d: p = fetchIfaceInfoFromNetworkdbAsDict(d['parent']) d['interfaces'] = p['interfaces'] results['net-admin-bridge'] = mgmt_iface results['net-admin-interface'] = d.get('interfaces').split( ',')[0] if_hwaddr = netutil.getHWAddr(results['net-admin-interface']) vlan = int(d['vlan']) if 'vlan' in d else None proto = d.get('mode') if proto == 'static': ip = d.get('ipaddr') netmask = d.get('netmask') gateway = d.get('gateway') dns = d.get('dns', '').split(',') if ip and netmask: results['net-admin-configuration'] = NetInterface( NetInterface.Static, if_hwaddr, ip, netmask, gateway, dns, vlan=vlan) elif proto == 'dhcp': results['net-admin-configuration'] = NetInterface( NetInterface.DHCP, if_hwaddr, vlan=vlan) else: results['net-admin-configuration'] = NetInterface( None, if_hwaddr, vlan=vlan) protov6 = d.get('modev6') if protov6 == 'static': ipv6 = d.get('ipaddrv6') gatewayv6 = d.get('gatewayv6') if ipv6: results['net-admin-configuration'].addIPv6( NetInterface.Static, ipv6, gatewayv6) elif protov6 == 'dhcp': results['net-admin-configuration'].addIPv6( NetInterface.DHCP) elif protov6 == 'autoconf': results['net-admin-configuration'].addIPv6( NetInterface.Autoconf) elif os.path.exists(self.join_state_path(dbcache_path)): xelogging.log( 'Checking %s for management network configuration' % dbcache_path) def getText(nodelist): rc = "" for node in nodelist: if node.nodeType == node.TEXT_NODE: rc = rc + node.data return rc.strip().encode() xmldoc = xml.dom.minidom.parse( self.join_state_path(dbcache_path)) pif_uid = None for node in xmldoc.documentElement.childNodes: if node.nodeType == node.ELEMENT_NODE and node.tagName == 'network': network = node else: continue # CA-50971: handle renamed networks in MNR if len(network.getElementsByTagName('bridge')) == 0 or \ len(network.getElementsByTagName('PIFs')) == 0 or \ len(network.getElementsByTagName('PIFs')[0].getElementsByTagName('PIF')) == 0: continue if getText( network.getElementsByTagName('bridge') [0].childNodes) == mgmt_iface: pif_uid = getText( network.getElementsByTagName('PIFs') [0].getElementsByTagName('PIF')[0].childNodes) break if pif_uid: for node in xmldoc.documentElement.childNodes: if node.nodeType == node.ELEMENT_NODE and node.tagName == 'pif': pif = node else: continue if pif.getAttribute('ref') == pif_uid: results['net-admin-interface'] = getText( pif.getElementsByTagName('device') [0].childNodes) results['net-admin-bridge'] = mgmt_iface results[ 'net-admin-configuration'] = NetInterface.loadFromPif( pif) break else: xelogging.log( 'Checking ifcfg files for management network configuration' ) for cfile in filter(lambda x: True in [x.startswith(y) for y in ['ifcfg-eth', 'ifcfg-bond']], \ os.listdir(self.join_state_path(constants.NET_SCR_DIR))): devcfg = util.readKeyValueFile(self.join_state_path( constants.NET_SCR_DIR, cfile), strip_quotes=False) if devcfg.has_key('DEVICE') and devcfg.has_key( 'BRIDGE') and devcfg['BRIDGE'] == mgmt_iface: brcfg = util.readKeyValueFile(self.join_state_path( constants.NET_SCR_DIR, 'ifcfg-' + devcfg['BRIDGE']), strip_quotes=False) results['net-admin-interface'] = devcfg['DEVICE'] results['net-admin-bridge'] = devcfg['BRIDGE'] # get hardware address if it was recorded, otherwise look it up: if devcfg.has_key('HWADDR'): hwaddr = devcfg['HWADDR'] elif devcfg.has_key('MACADDR'): # our bonds have a key called MACADDR instead hwaddr = devcfg['MACADDR'] else: hwaddr = netutil.getHWAddr(devcfg['DEVICE']) ifcfg = NetInterface.loadFromIfcfg( self.join_state_path(constants.NET_SCR_DIR, 'ifcfg-' + devcfg['BRIDGE'])) if not ifcfg.hwaddr: ifcfg.hwaddr = hwaddr if ifcfg.isStatic() and not ifcfg.domain and domain: ifcfg.domain = domain results['net-admin-configuration'] = ifcfg break repo_list = [] if os.path.exists( self.join_state_path(constants.INSTALLED_REPOS_DIR)): try: for repo_id in os.listdir( self.join_state_path( constants.INSTALLED_REPOS_DIR)): try: repo = repository.LegacyRepository( repository.FilesystemAccessor( self.join_state_path( constants.INSTALLED_REPOS_DIR, repo_id))) if repo.hidden() != "true": repo_list.append( (repo.identifier(), repo.name(), (repo_id != constants.MAIN_REPOSITORY_NAME))) except repository.RepoFormatError: # probably pre-XML format repo = open( self.join_state_path( constants.INSTALLED_REPOS_DIR, repo_id, repository.LegacyRepository. REPOSITORY_FILENAME)) repo_id = repo.readline().strip() repo_name = repo.readline().strip() repo.close() repo_list.append( (repo_id, repo_name, (repo_id != constants.MAIN_REPOSITORY_NAME))) except Exception, e: xelogging.log('Scan for driver disks failed:') xelogging.log_exception(e) results['repo-list'] = repo_list results['ha-armed'] = False try: db_path = "var/lib/xcp/local.db" if not os.path.exists(self.join_state_path(db_path)): db_path = "var/xapi/local.db" db = open(self.join_state_path(db_path), 'r') if db.readline().find( '<row key="ha.armed" value="true"') != -1: results['ha-armed'] = True db.close() except: pass try: network_conf = open( self.join_state_path("etc/xensource/network.conf"), 'r') network_backend = network_conf.readline().strip() network_conf.close() if network_backend == constants.NETWORK_BACKEND_BRIDGE: results[ 'network-backend'] = constants.NETWORK_BACKEND_BRIDGE elif network_backend in [ constants.NETWORK_BACKEND_VSWITCH, constants.NETWORK_BACKEND_VSWITCH_ALT ]: results[ 'network-backend'] = constants.NETWORK_BACKEND_VSWITCH else: raise SettingsNotAvailable, "unknown network backend %s" % network_backend except: pass results['master'] = None try: pt = open(self.join_state_path("etc/xensource/ptoken"), 'r') results['pool-token'] = pt.readline().strip() pt.close() pc = open(self.join_state_path("etc/xensource/pool.conf"), 'r') line = pc.readline().strip() if line.startswith('slave:'): results['master'] = line[6:] pc.close() except: pass
def _readSettings(self): """ Read settings from the installation, returns a results dictionary. """ results = {} if self.version < XENSERVER_5_6_0: raise SettingsNotAvailable, "version too old" self.mount_state() try: # timezone: tz = None clock_file = self.join_state_path("etc/sysconfig/clock") if os.path.exists(clock_file): fd = open(clock_file, "r") lines = fd.readlines() fd.close() for line in lines: if line.startswith("ZONE="): tz = line[5:].strip() if not tz: # No timezone found: # Supply a default and for interactive installs prompt the user. xelogging.log("No timezone configuration found.") results["request-timezone"] = True tz = "Europe/London" results["timezone"] = tz # hostname. We will assume one was set anyway and thus write # it back into the new filesystem. If one wasn't set then this # will be localhost.localdomain, in which case the old behaviour # will persist anyway: fd = open(self.join_state_path("etc/sysconfig/network"), "r") lines = fd.readlines() fd.close() for line in lines: if line.startswith("HOSTNAME="): results["manual-hostname"] = (True, line[9:].strip()) if not results.has_key("manual-hostname"): results["manual-hostname"] = (False, None) # nameservers: domain = None if not os.path.exists(self.join_state_path("etc/resolv.conf")): results["manual-nameservers"] = (False, None) else: ns = [] fd = open(self.join_state_path("etc/resolv.conf"), "r") lines = fd.readlines() fd.close() for line in lines: if line.startswith("nameserver "): ns.append(line[11:].strip()) elif line.startswith("domain "): domain = line[8:].strip() elif line.startswith("search "): domain = line.split()[1] results["manual-nameservers"] = (True, ns) # ntp servers: fd = open(self.join_state_path("etc/ntp.conf"), "r") lines = fd.readlines() fd.close() ntps = [] for line in lines: if line.startswith("server "): ntps.append(line[7:].strip()) results["ntp-servers"] = ntps # keyboard: keyboard_file = self.join_state_path("etc/sysconfig/keyboard") if os.path.exists(keyboard_file): fd = open(keyboard_file, "r") lines = fd.readlines() fd.close() for line in lines: if line.startswith("KEYTABLE="): results["keymap"] = line[9:].strip() # Do not error here if no keymap configuration is found. # This enables upgrade to still carry state on hosts without # keymap configured: # A default keymap is assigned in the backend of this installer. if not results.has_key("keymap"): xelogging.log("No existing keymap configuration found.") # root password: fd = open(self.join_state_path("etc/passwd"), "r") root_pwd = None for line in fd: pwent = line.split(":") if pwent[0] == "root": root_pwd = pwent[1] break fd.close() if not root_pwd: raise SettingsNotAvailable, "no root password found" results["root-password"] = ("pwdhash", root_pwd) # don't care about this too much. results["time-config-method"] = "ntp" # read network configuration. We only care to find out what the # management interface is, and what its configuration was. # The dev -> MAC mapping for other devices will be preserved in the # database which is available in time for everything except the # management interface. mgmt_iface = self.getInventoryValue("MANAGEMENT_INTERFACE") if os.path.exists(self.join_state_path(constants.DBCACHE)): def getText(nodelist): rc = "" for node in nodelist: if node.nodeType == node.TEXT_NODE: rc = rc + node.data return rc.strip().encode() xmldoc = xml.dom.minidom.parse(self.join_state_path(constants.DBCACHE)) pif_uid = None for node in xmldoc.documentElement.childNodes: if node.nodeType == node.ELEMENT_NODE and node.tagName == "network": network = node else: continue # CA-50971: handle renamed networks in MNR if ( len(network.getElementsByTagName("bridge")) == 0 or len(network.getElementsByTagName("PIFs")) == 0 or len(network.getElementsByTagName("PIFs")[0].getElementsByTagName("PIF")) == 0 ): continue if getText(network.getElementsByTagName("bridge")[0].childNodes) == mgmt_iface: pif_uid = getText( network.getElementsByTagName("PIFs")[0].getElementsByTagName("PIF")[0].childNodes ) break if pif_uid: for node in xmldoc.documentElement.childNodes: if node.nodeType == node.ELEMENT_NODE and node.tagName == "pif": pif = node else: continue if pif.getAttribute("ref") == pif_uid: results["net-admin-interface"] = getText(pif.getElementsByTagName("device")[0].childNodes) results["net-admin-bridge"] = mgmt_iface results["net-admin-configuration"] = NetInterface.loadFromPif(pif) break else: for cfile in filter( lambda x: True in [x.startswith(y) for y in ["ifcfg-eth", "ifcfg-bond"]], os.listdir(self.join_state_path(constants.NET_SCR_DIR)), ): devcfg = util.readKeyValueFile( self.join_state_path(constants.NET_SCR_DIR, cfile), strip_quotes=False ) if devcfg.has_key("DEVICE") and devcfg.has_key("BRIDGE") and devcfg["BRIDGE"] == mgmt_iface: brcfg = util.readKeyValueFile( self.join_state_path(constants.NET_SCR_DIR, "ifcfg-" + devcfg["BRIDGE"]), strip_quotes=False ) results["net-admin-interface"] = devcfg["DEVICE"] results["net-admin-bridge"] = devcfg["BRIDGE"] # get hardware address if it was recorded, otherwise look it up: if devcfg.has_key("HWADDR"): hwaddr = devcfg["HWADDR"] elif devcfg.has_key("MACADDR"): # our bonds have a key called MACADDR instead hwaddr = devcfg["MACADDR"] else: # XXX what if it's been renamed out of existence? try: hwaddr = netutil.getHWAddr(devcfg["DEVICE"]) except: hwaddr = None ifcfg = NetInterface.loadFromIfcfg( self.join_state_path(constants.NET_SCR_DIR, "ifcfg-" + devcfg["BRIDGE"]) ) if not ifcfg.hwaddr: ifcfg.hwaddr = hwaddr if ifcfg.isStatic() and not ifcfg.domain and domain: ifcfg.domain = domain results["net-admin-configuration"] = ifcfg break repo_list = [] if os.path.exists(self.join_state_path(constants.INSTALLED_REPOS_DIR)): try: for repo_id in os.listdir(self.join_state_path(constants.INSTALLED_REPOS_DIR)): try: repo = repository.Repository( repository.FilesystemAccessor( self.join_state_path(constants.INSTALLED_REPOS_DIR, repo_id) ) ) repo_list.append( (repo.identifier(), repo.name(), (repo_id != constants.MAIN_REPOSITORY_NAME)) ) except repository.RepoFormatError: # probably pre-XML format repo = open( self.join_state_path( constants.INSTALLED_REPOS_DIR, repo_id, repository.Repository.REPOSITORY_FILENAME ) ) repo_id = repo.readline().strip() repo_name = repo.readline().strip() repo.close() repo_list.append((repo_id, repo_name, (repo_id != constants.MAIN_REPOSITORY_NAME))) except Exception, e: xelogging.log("Scan for driver disks failed:") xelogging.log_exception(e) results["repo-list"] = repo_list results["ha-armed"] = False try: db = open(self.join_state_path("var/xapi/local.db"), "r") if db.readline().find('<row key="ha.armed" value="true"') != -1: results["ha-armed"] = True db.close() except: pass results["master"] = None try: pt = open(self.join_state_path("etc/xensource/ptoken"), "r") results["pool-token"] = pt.readline().strip() pt.close() pc = open(self.join_state_path("etc/xensource/pool.conf"), "r") line = pc.readline().strip() if line.startswith("slave:"): results["master"] = line[6:] pc.close() except: pass