Esempio n. 1
0
def doInteractiveLoadDriver(ui, answers):
    media = None
    address = None
    required_repo_list = []
    loaded_drivers = []

    rc = ui.init.driver_disk_sequence(answers, answers['driver-repos'])
    if rc:
        media, address = rc
        repos = answers['repos']

        # now load the drivers:
        for r in repos:
            logger.log("Processing repo %s" % r)
            try:
                r.installPackages(lambda x: (), {'root': '/'})
                answers['driver-repos'].append(str(r))

                ButtonChoiceWindow(ui.screen, "Drivers Loaded",
                                   "Loaded %s." % r.name(), ['Ok'])
            except Exception as e:
                logger.logException(e)
                ButtonChoiceWindow(
                    ui.screen, "Problem Loading Driver",
                    "Setup was unable to load the device driver.", ['Ok'])

    return media, address
Esempio n. 2
0
def parentdev_from_devpath(devpath):
    """Returns the dev number of the parent device, or None if there isn't
    one."""

    try:
        devno = os.stat(devpath).st_rdev
        major = os.major(devno)
        minor = os.minor(devno)
        syspath = '/sys/dev/block/%d:%d' % (major, minor)

        partitionpath = syspath + '/partition'
        if os.path.exists(partitionpath):
            linkpath = os.path.realpath(syspath)
            parent = os.path.dirname(linkpath)
            return dev_from_sysfs(parent)
        else:
            dm_uuidpath = syspath + '/dm/uuid'
            if os.path.exists(dm_uuidpath):
                with open(dm_uuidpath, 'r') as f:
                    dm_uuid = f.read().strip()
                if re.match('part[0-9+]-', dm_uuid):
                    parent = os.listdir(syspath + '/slaves')[0]
                    return dev_from_sysfs('%s/slaves/%s' % (syspath, parent))
    except Exception as e:
        logger.logException(e)

    # If there is no parent of the parent cannot be determined...
    return None
Esempio n. 3
0
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 as e:
            logger.log(
                "A problem occurred whilst scanning for existing installations:"
            )
            logger.logException(e)
            logger.log("This is not fatal.  Continuing anyway.")

        if inst:
            logger.log("Found an installation: %s on %s" % (str(inst), disk))
            installs.append(inst)

    return installs
Esempio n. 4
0
    def __init__(self, accessor):
        YumRepository.__init__(self, accessor)

        accessor.start()
        try:
            updatefp = accessor.openAddress(self.INFO_FILENAME)
            try:
                dom = xml.dom.minidom.parseString(updatefp.read())
            except Exception as e:
                logger.logException(e)
                raise RepoFormatError("Failed to read %s: %s" %
                                      (self.INFO_FILENAME, str(e)))
            finally:
                updatefp.close()

            assert dom.documentElement.tagName == 'update'
            self._controlpkg = dom.documentElement.getAttribute('control')
            self._identifier = dom.documentElement.getAttribute('name-label')
            self._targets = [self._controlpkg, 'update-' + self._identifier]
        except Exception as e:
            accessor.finish()
            logger.logException(e)
            raise RepoFormatError("Failed to read %s: %s" %
                                  (self.INFO_FILENAME, str(e)))

        self._parse_repodata(accessor)
        accessor.finish()
Esempio n. 5
0
def verify_source(answers, label, require_base_repo):
    cap_label = ' '.join(map(lambda a: a.capitalize(), label.split()))
    if 'source-media' in answers and 'source-address' in answers:
        media = answers['source-media']
        address = answers['source-address']
    else:
        media = 'local'
        address = ''
    done = False
    SKIP, VERIFY = range(2)
    entries = [
        ("Skip verification", SKIP),
        ("Verify %s source" % label, VERIFY),
    ]

    if media == 'local':
        text = "Would you like to test your media?"
        default = selectDefault(VERIFY, entries)
    else:
        text = "Would you like to test your %s repository?  This may cause significant network traffic." % label
        default = selectDefault(SKIP, entries)

    while not done:
        (button, entry) = ListboxChoiceWindow(tui.screen,
                                              "Verify %s Source" % cap_label,
                                              text,
                                              entries, ['Ok', 'Back'],
                                              default=default,
                                              help='vfyrepo')

        if button == 'back': return LEFT_BACKWARDS

        if entry == VERIFY:
            # we need to do the verification:
            try:
                tui.progress.showMessageDialog("Please wait",
                                               "Searching for repository...")
                repos = repository.repositoriesFromDefinition(media, address)
                tui.progress.clearModelessDialog()

                if require_base_repo and constants.MAIN_REPOSITORY_NAME not in [
                        r.identifier() for r in repos
                ]:
                    ButtonChoiceWindow(
                        tui.screen, "Error",
                        """A base installation repository was not found.  Please check the address was valid and/or that the media was inserted correctly, and try again.""",
                        ['Ok'])
                else:
                    done = interactive_source_verification(repos, label)
            except Exception as e:
                logger.logException(e)
                ButtonChoiceWindow(
                    tui.screen, "Error",
                    """Unable to access location specified.  Please check the address was valid and/or that the media was inserted correctly, and try again.""",
                    ['Ok'])
        else:
            done = True

    return RIGHT_FORWARDS
Esempio n. 6
0
 def inject_to_vif(self, vif):
     mac = get_vif_mac(vif)
     try:
         self.inject_packet(vif, mac)
         log.info('Inject IGMP query to vif:%s, mac:%s' % (vif, mac))
     except Exception as e:
         log.error('Inject IGMP query to vif:%s, mac:%s failed' % (vif, mac))
         log.logException(e)
Esempio n. 7
0
def find_installed_products():
    try:
        installed_products = findXenSourceProducts()
    except Exception as e:
        logger.log(
            "A problem occurred whilst scanning for existing installations:")
        logger.logException(e)
        logger.log("This is not fatal.  Continuing anyway.")
        installed_products = []
    return installed_products
Esempio n. 8
0
 def copy_ownership(src_root, src_path, dst_root, dst_path):
     st = os.lstat('%s/%s' % (src_root, src_path))
     try:
         new_uid = dst_uid_map[src_uid_map[st.st_uid]]
         new_gid = dst_gid_map[src_gid_map[st.st_gid]]
     except IndexError as e:
         logger.error('Failed to copy ownership')
         logger.logException(e)
         return
     if st.st_uid != new_uid or st.st_gid != new_gid:
         os.lchown('%s/%s' % (dst_root, dst_path), new_uid, new_gid)
Esempio n. 9
0
 def settingsAvailable(self):
     try:
         self.readSettings()
     except SettingsNotAvailable as text:
         logger.log("Settings unavailable: %s" % text)
         return False
     except Exception as e:
         logger.log("Settings unavailable: unhandled exception")
         logger.logException(e)
         return False
     else:
         return True
Esempio n. 10
0
def check_repo_def(definition, require_base_repo):
    """ Check that the repository source definition gives access to suitable
    repositories. """
    try:
        tui.progress.showMessageDialog("Please wait", "Searching for repository...")
        repos = repository.repositoriesFromDefinition(*definition)
        tui.progress.clearModelessDialog()
    except Exception as e:
        logger.log("Exception trying to access repository: %s" % e)
        logger.logException(e)
        tui.progress.clearModelessDialog()
        return REPOCHK_NO_ACCESS
    else:
        if len(repos) == 0:
            return REPOCHK_NO_REPO
        elif constants.MAIN_REPOSITORY_NAME not in [r.identifier() for r in repos] and require_base_repo:
            return REPOCHK_NO_BASE_REPO

    return REPOCHK_NO_ERRORS
Esempio n. 11
0
    def __init__(self, accessor):
        YumRepository.__init__(self, accessor)
        self.keyfiles = []

        accessor.start()
        try:
            treeinfo = ConfigParser.SafeConfigParser()
            treeinfofp = accessor.openAddress(self.INFO_FILENAME)
            try:
                treeinfo.readfp(treeinfofp)
            except Exception as e:
                raise RepoFormatError("Failed to read %s: %s" %
                                      (self.INFO_FILENAME, str(e)))
            finally:
                treeinfofp.close()

            if treeinfo.has_section('platform'):
                self._platform_name = treeinfo.get('platform', 'name')
                ver_str = treeinfo.get('platform', 'version')
                self._platform_version = Version.from_string(ver_str)
            if treeinfo.has_section('branding'):
                self._product_brand = treeinfo.get('branding', 'name')
                ver_str = treeinfo.get('branding', 'version')
                self._product_version = Version.from_string(ver_str)
            if treeinfo.has_section('build'):
                self._build_number = treeinfo.get('build', 'number')
            else:
                self._build_number = None
            if treeinfo.has_section('keys'):
                for _, keyfile in treeinfo.items('keys'):
                    self.keyfiles.append(keyfile)
        except Exception as e:
            accessor.finish()
            logger.logException(e)
            raise RepoFormatError("Failed to read %s: %s" %
                                  (self.INFO_FILENAME, str(e)))

        self._parse_repodata(accessor)
        accessor.finish()
Esempio n. 12
0
        def init_id_maps(src_root, dst_root):
            """ Create mappings between (username and uid), and (group and
            gid) for the source and destination roots. """
            with open(os.path.join(src_root, 'etc/passwd'), 'r') as f:
                for line in f:
                    try:
                        pwnam, _, uid, _ = line.split(':', 3)
                        src_uid_map[int(uid)] = pwnam
                    except ValueError as e:
                        logger.error('Failed to parse: ' + line)
                        logger.logException(e)

            with open(os.path.join(src_root, 'etc/group'), 'r') as f:
                for line in f:
                    try:
                        pwnam, _, gid, _ = line.split(':', 3)
                        src_gid_map[int(gid)] = pwnam
                    except ValueError as e:
                        logger.error('Failed to parse: ' + line)
                        logger.logException(e)

            with open(os.path.join(dst_root, 'etc/passwd'), 'r') as f:
                for line in f:
                    try:
                        pwnam, _, uid, _ = line.split(':', 3)
                        dst_uid_map[pwnam] = int(uid)
                    except ValueError as e:
                        logger.error('Failed to parse: ' + line)
                        logger.logException(e)

            with open(os.path.join(dst_root, 'etc/group'), 'r') as f:
                for line in f:
                    try:
                        pwnam, _, gid, _ = line.split(':', 3)
                        dst_gid_map[pwnam] = int(gid)
                    except ValueError as e:
                        logger.error('Failed to parse: ' + line)
                        logger.logException(e)
Esempio n. 13
0
def go(ui, args, answerfile_address, answerfile_script):
    extra_repo_defs = []
    results = {
        'keymap': None,
        'serial-console': None,
        'operation': init_constants.OPERATION_INSTALL,
        'boot-serial': False,
        'extra-repos': [],
        'network-backend': constants.NETWORK_BACKEND_DEFAULT,
        'root-password': ('pwdhash', '!!'),
        'create-new-partitions':
        True,  # FALSE = DOS | TRUE = GPT set via command line only with --disable-gpt
        'new-partition-layout':
        False,  # TRUE = GPT with LOG,BACKUP,ROOT,BOOT,SWAP,SR automatically set during install/upgrade
        'services': {s: None
                     for s in constants.SERVICES
                     },  # default state for services, example {'sshd': None}
    }
    suppress_extra_cd_dialog = False
    serial_console = None
    boot_console = None
    boot_serial = False

    if not xen_control_domain() or '--virtual' in args:
        hardware.useVMHardwareFunctions()

    for (opt, val) in args.items():
        if opt == "--boot-console":
            # takes precedence over --console
            if hardware.is_serialConsole(val):
                boot_console = hardware.getSerialConfig()
        elif opt == "--console":
            for console in val:
                if hardware.is_serialConsole(console):
                    serial_console = hardware.getSerialConfig()
            if hardware.is_serialConsole(val[-1]):
                boot_serial = True
        elif opt == "--keymap":
            results["keymap"] = val
            logger.log("Keymap specified on command-line: %s" % val)
        elif opt == "--extrarepo":
            extra_repo_defs += val
        elif opt == "--onecd":
            suppress_extra_cd_dialog = True
        elif opt == "--disable-gpt":
            constants.GPT_SUPPORT = False
            results["create-new-partitions"] = False
            logger.log(
                "Forcing DOS partition table and old partition layout via command-line"
            )
        elif opt == "--legacy-partitions":
            results["create-new-partitions"] = False
            logger.log("Forcing old partition layout via command-line")
        elif opt == "--cc-preparations":
            constants.CC_PREPARATIONS = True
            results['network-backend'] = constants.NETWORK_BACKEND_BRIDGE

    if boot_console and not serial_console:
        serial_console = boot_console
        boot_serial = True
    if serial_console:
        try:
            results['serial-console'] = hardware.SerialPort.from_string(
                serial_console)
            results['boot-serial'] = boot_serial
            logger.log(
                "Serial console specified on command-line: %s, default boot: %s"
                % (serial_console, boot_serial))
        except:
            pass

    interactive = True
    try:
        if os.path.isfile(constants.defaults_data_file):
            data_file = open(constants.defaults_data_file)
            try:
                defaults = json.load(data_file)
            finally:
                data_file.close()
            results.update(defaults)

        # loading an answerfile?
        assert ui is not None or answerfile_address is not None or answerfile_script is not None

        if answerfile_address and answerfile_script:
            raise RuntimeError(
                "Both answerfile and answerfile generator passed on command line."
            )

        a = None
        parsing_except = None
        if answerfile_address:
            a = answerfile.Answerfile.fetch(answerfile_address)
        elif answerfile_script:
            a = answerfile.Answerfile.generate(answerfile_script)
        if a:
            interactive = False
            results['network-hardware'] = netutil.scanConfiguration()
            try:
                results.update(a.parseScripts())
                results.update(a.processAnswerfileSetup())

                if ui and results.get('ui-confirmation-prompt', False):
                    if not ui.init.confirm_proceed():
                        logger.log("User did not confirm installation. Reboot")
                        return constants.EXIT_USER_CANCEL

                if 'extra-repos' in results:
                    # load drivers now
                    for media, address in results['extra-repos']:
                        for r in repository.repositoriesFromDefinition(
                                media, address, drivers=True):
                            r.installPackages(lambda x: (), {'root': '/'})

                if 'fcoe-interfaces' in results:
                    fcoeutil.start_fcoe(results['fcoe-interfaces'])

                util.runCmd2(util.udevsettleCmd())
                time.sleep(1)
                diskutil.mpath_part_scan()

                # ensure partitions/disks are not locked by LVM
                lvm = disktools.LVMTool()
                lvm.deactivateAll()
                del lvm

                diskutil.log_available_disks()

                results.update(a.processAnswerfile())
                results = fixMpathResults(results)
            except Exception as e:
                logger.logException(e)
                parsing_except = e

        results['extra-repos'] += extra_repo_defs
        logger.log("Driver repos: %s" % str(results['extra-repos']))

        scripts.run_scripts('installation-start')

        if parsing_except:
            raise parsing_except

        # log the modules that we loaded:
        logger.log("All needed modules should now be loaded. We have loaded:")
        util.runCmd2(["lsmod"])

        status = constants.EXIT_OK

        # how much RAM do we have?
        ram_found_mb = hardware.getHostTotalMemoryKB() / 1024
        ram_warning = ram_found_mb < constants.MIN_SYSTEM_RAM_MB
        vt_warning = not hardware.VTSupportEnabled()

        # Generate the UI sequence and populate some default
        # values in backend input.  Note that not all these screens
        # will be displayed as they have conditional to skip them at
        # the start of each function.  In future these conditionals will
        # be moved into the sequence definition and evaluated by the
        # UI dispatcher.
        aborted = False
        if ui and interactive:
            uiexit = ui.installer.runMainSequence(results, ram_warning,
                                                  vt_warning,
                                                  suppress_extra_cd_dialog)
            if uiexit == uicontroller.EXIT:
                aborted = True

        if not aborted:
            if results['install-type'] == constants.INSTALL_TYPE_RESTORE:
                logger.log('INPUT ANSWER DICTIONARY')
                backend.prettyLogAnswers(results)
                logger.log("SCRIPTS DICTIONARY:")
                backend.prettyLogAnswers(scripts.script_dict)
                logger.log("Starting actual restore")
                backup = results['backup-to-restore']
                if ui:
                    pd = tui.progress.initProgressDialog(
                        "Restoring %s" % backup,
                        "Restoring data - this may take a while...", 100)

                def progress(x):
                    if ui and pd:
                        tui.progress.displayProgressDialog(x, pd)

                restore.restoreFromBackup(backup, progress)
                if ui:
                    tui.progress.clearModelessDialog()
                    tui.progress.OKDialog(
                        "Restore",
                        "The restore operation completed successfully.")
            else:
                logger.log("Starting actual installation")
                backend.performInstallation(results, ui, interactive)

                if ui and interactive:
                    ui.installer.screens.installation_complete()

                logger.log("The installation completed successfully.")
        else:
            logger.log(
                "The user aborted the installation from within the user interface."
            )
            status = constants.EXIT_USER_CANCEL
    except Exception as e:
        try:
            # first thing to do is to get the traceback and log it:
            ex = sys.exc_info()
            err = str.join("", traceback.format_exception(*ex))
            logger.log("INSTALL FAILED.")
            logger.log("A fatal exception occurred:")
            logger.log(err)

            # run the user's scripts - an arg of "1" indicates failure
            scripts.run_scripts('installation-complete', '1')

            # collect logs where possible
            xelogging.collectLogs("/tmp")

            # now display a friendly error dialog:
            if ui:
                ui.exn_error_dialog("install-log", True, interactive)
            else:
                txt = constants.error_string(str(e), 'install-log', True)
                logger.log(txt)

            # and now on the disk if possible:
            if 'primary-disk' in results and 'primary-partnum' in results and 'logs-partnum' in results:
                backend.writeLog(results['primary-disk'],
                                 results['primary-partnum'],
                                 results['logs-partnum'])
            elif 'primary-disk' in results and 'primary-partnum' in results:
                backend.writeLog(results['primary-disk'],
                                 results['primary-partnum'], None)

            logger.log(results)
        except Exception as e:
            # Don't let logging exceptions prevent subsequent actions
            print 'Logging failed: ' + str(e)

        # exit with failure status:
        status = constants.EXIT_ERROR

    else:
        # run the user's scripts - an arg of "0" indicates success
        try:
            scripts.run_scripts('installation-complete', '0')
        except:
            pass

        # put the log in /tmp:
        xelogging.collectLogs('/tmp')

        # and now on the disk if possible:
        if 'primary-disk' in results and 'primary-partnum' in results and 'logs-partnum' in results:
            backend.writeLog(results['primary-disk'],
                             results['primary-partnum'],
                             results['logs-partnum'])
        elif 'primary-disk' in results and 'primary-partnum' in results:
            backend.writeLog(results['primary-disk'],
                             results['primary-partnum'], None)

        assert (status == constants.EXIT_OK
                or status == constants.EXIT_USER_CANCEL)

    return status
Esempio n. 14
0
def confirm_load_repo(answers, label, installed_repos):
    cap_label = ' '.join(map(lambda a: a.capitalize(), label.split()))
    if 'source-media' in answers and 'source-address' in answers:
        media = answers['source-media']
        address = answers['source-address']
    else:
        media = 'local'
        address = ''

    try:
        tui.progress.showMessageDialog("Please wait",
                                       "Searching for repository...")
        repos = repository.repositoriesFromDefinition(
            media, address, drivers=(label == 'driver'))
        tui.progress.clearModelessDialog()
    except Exception as e:
        logger.logException(e)
        ButtonChoiceWindow(
            tui.screen, "Error",
            """Unable to access location specified.  Please check the address was valid and/or that the media was inserted correctly, and try again.""",
            ['Back'])
        return LEFT_BACKWARDS

    if label != 'driver':
        repos = filter(
            lambda r: r.identifier() != constants.MAIN_REPOSITORY_NAME, repos)

    if len(repos) == 0:
        ButtonChoiceWindow(
            tui.screen, "No %s Found" % cap_label,
            """No %s compatible %ss were found at the location specified.  Please check the address was valid and/or that the media was inserted correctly, and try again."""
            % (version.PRODUCT_BRAND or version.PLATFORM_NAME, label),
            ['Back'])
        return LEFT_BACKWARDS

    USE, VERIFY, BACK = range(3)
    default_button = BACK
    if len(repos) == 1:
        text = TextboxReflowed(54, "The following %s was found:\n\n" % label)
    else:
        text = TextboxReflowed(54, "The following %ss were found:\n\n" % label)
    buttons = ButtonBar(tui.screen, [('Use', 'use'), ('Verify', 'verify'),
                                     ('Back', 'back')])
    cbt = CheckboxTree(4, scroll=1)
    for r in repos:
        if str(r) in installed_repos:
            cbt.append("%s (already installed)" % r.name(), r, False)
        else:
            cbt.append(r.name(), r, True)
            default_button = VERIFY

    gf = GridFormHelp(tui.screen, 'Load Repository', 'loadrepo', 1, 3)
    gf.add(text, 0, 0, padding=(0, 0, 0, 1))
    gf.add(cbt, 0, 1, padding=(0, 0, 0, 1))
    gf.add(buttons, 0, 2, growx=1)
    gf.draw()

    done = False
    while not done:
        gf.setCurrent(buttons.list[default_button][0])
        rc = buttons.buttonPressed(gf.run())
        selected_repos = cbt.getSelection()

        if rc in [None, 'use']:
            done = True
        elif rc == 'back':
            tui.screen.popWindow()
            return LEFT_BACKWARDS
        elif rc == 'verify' and len(selected_repos) > 0:
            if media == 'local':
                text2 = "\n\nWould you like to test your media?"
            else:
                text2 = "\n\nWould you like to test your %s repository?  This may cause significant network traffic." % label

            rc2 = ButtonChoiceWindow(tui.screen,
                                     "Repository Information",
                                     text2, ['Ok', 'Back'],
                                     width=60)
            if rc2 == 'ok' and interactive_source_verification(
                    selected_repos, label):
                default_button = USE

    tui.screen.popWindow()
    answers['repos'] = selected_repos
    return RIGHT_FORWARDS
Esempio n. 15
0
    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.
                logger.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 'manual-hostname' not in results:
                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:
            if os.path.exists(self.join_state_path('etc/chrony.conf')):
                fd = open(self.join_state_path('etc/chrony.conf'), 'r')
            else:
                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:].split()[0].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 'keymap' not in results:
                logger.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')

            if not mgmt_iface:
                logger.log('No existing management interface found.')
            elif os.path.exists(self.join_state_path(constants.NETWORK_DB)):
                logger.log(
                    'Checking %s for management interface configuration' %
                    constants.NETWORKD_DB)

                def fetchIfaceInfoFromNetworkdbAsDict(bridge, iface=None):
                    args = [
                        'chroot', self.state_fs.mount_point,
                        '/' + constants.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)

            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 as e:
                    logger.log('Scan for driver disks failed:')
                    logger.logException(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

        finally:
            self.unmount_state()

        # read bootloader config to extract various settings
        try:
            # Boot device
            self.mount_boot()
            boot_config = bootloader.Bootloader.loadExisting(
                self.boot_fs_mount)

            # Serial console
            try:
                xen_args = boot_config.menu['xe-serial'].getHypervisorArgs()
                com = [i for i in xen_args if re.match('com[0-9]+=.*', i)]
                results['serial-console'] = hardware.SerialPort.from_string(
                    com[0])
            except Exception:
                logger.log("Could not parse serial settings")

                if boot_config.serial:
                    results['serial-console'] = hardware.SerialPort(
                        boot_config.serial['port'],
                        baud=str(boot_config.serial['baud']))
            results['bootloader-location'] = boot_config.location
            if boot_config.default != 'upgrade':
                results['boot-serial'] = (boot_config.default == 'xe-serial')

            # Subset of hypervisor arguments
            xen_args = boot_config.menu[
                boot_config.default].getHypervisorArgs()

            #   - cpuid_mask
            results['host-config']['xen-cpuid-masks'] = filter(
                lambda x: x.startswith('cpuid_mask'), xen_args)

            #   - dom0_mem
            dom0_mem_arg = filter(lambda x: x.startswith('dom0_mem'), xen_args)
            (dom0_mem, dom0_mem_min,
             dom0_mem_max) = xcp.dom0.parse_mem(dom0_mem_arg[0])
            if dom0_mem:
                results['host-config']['dom0-mem'] = dom0_mem / 1024 / 1024
        except:
            pass
        self.unmount_boot()

        return results