示例#1
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
    }
    suppress_extra_cd_dialog = False
    serial_console = None
    boot_console = None
    boot_serial = False

    if not xen_control_domain() or args.has_key('--virtual'):
        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
            xelogging.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
            xelogging.log("Forcing old partition layout via command-line")

    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
            xelogging.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 != None or answerfile_address != None or answerfile_script != 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():
                        xelogging.log(
                            "User did not confirm installation. Reboot")
                        return constants.EXIT_USER_CANCEL

                if results.has_key('extra-repos'):
                    # 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, e:
                xelogging.logException(e)
                parsing_except = e

        results['extra-repos'] += extra_repo_defs
        xelogging.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:
        xelogging.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:
                xelogging.log('INPUT ANSWER DICTIONARY')
                backend.prettyLogAnswers(results)
                xelogging.log("SCRIPTS DICTIONARY:")
                backend.prettyLogAnswers(scripts.script_dict)
                xelogging.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:
                xelogging.log("Starting actual installation")
                backend.performInstallation(results, ui, interactive)

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

                xelogging.log("The installation completed successfully.")
        else:
            xelogging.log(
                "The user aborted the installation from within the user interface."
            )
            status = constants.EXIT_USER_CANCEL
示例#2
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
示例#3
0
def select_fcoe_ifaces(answers):
    """ Display a screen that displays all network interfaces that are
    FCoE-capable and allows the user to select one or more.
    """

    conf = netutil.scanConfiguration()
    fcoe_ifaces = fcoeutil.get_dcb_capable_ifaces(True)

    if len(fcoe_ifaces) == 0:
        button = ButtonChoiceWindow(tui.screen,
                                    "FCoE Interfaces",
                                    "No DCB capable interfaces found",
                                    ['Back'],
                                    width=60)

        return

    netifs = fcoe_ifaces.keys()
    netifs.sort(lambda l, r: int(l[3:]) - int(r[3:]))

    def iface_details(context):
        tui.update_help_line([' ', ' '])

        nic = conf[context]

        table = [("Name:", nic.name), ("Driver:", nic.driver),
                 ("MAC Address:", nic.hwaddr),
                 ("Link Status:", netutil.linkUp(context) and 'Up' or 'Down')]

        snackutil.TableDialog(tui.screen, "Interface Details", *table)
        tui.screen.popHelpLine()
        return True

    # Map between soft/off and soft/hard (depending on interface property)
    def dcb_state_label(iface, state):
        if state:
            return '[soft]'
        if not fcoe_ifaces[iface]:
            return '[hard]'
        return '      '

    if 'fcoe-interfaces' not in answers:
        answers['fcoe-interfaces'] = {}

    entries = {}
    for ne in netifs:
        state = dcb_state_label(
            ne, answers['fcoe-interfaces'].get(ne, fcoe_ifaces[ne]))
        entry = "%s %s" % (ne, state)
        entries[ne] = entry

    text = TextboxReflowed(54,
                           "Select one or more interfaces to setup for FCoE.")
    buttons = ButtonBar(tui.screen, [('Ok', 'ok'), ('DCB', 'dcb'),
                                     ('Back', 'back')])
    scroll, _ = snackutil.scrollHeight(3, len(entries.keys()))
    cbt = CheckboxTree(3, scroll)
    for iface in netifs:
        cbt.append(entries[iface], iface, iface in answers['fcoe-interfaces'])

    gf = GridFormHelp(tui.screen, 'FCoE Interfaces', 'fcoeiface:info', 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.addHotKey('F5')

    tui.update_help_line([None, "<F5> more info"])

    loop = True
    while loop:
        rc = gf.run()
        if rc == 'F5':
            iface_details(cbt.getCurrent())
        elif buttons.buttonPressed(rc) == 'dcb':
            ne = cbt.getCurrent()
            new = dcb_state_label(ne, not entries[ne].endswith('[soft]'))
            entries[ne] = "%s %s" % (ne, new)
            cbt.setEntry(ne, entries[ne])
        else:
            loop = False
    tui.screen.popWindow()
    tui.screen.popHelpLine()

    button = buttons.buttonPressed(rc)

    if button == 'back':
        return

    r = dict(
        map(lambda (k): (k, entries[k].endswith('[soft]')),
            cbt.getSelection()))
    answers['fcoe-interfaces'] = r
    xelogging.log("Selected fcoe interfaces %s" % str(r))

    tui.update_help_line([' ', ' '])

    # Bring up FCoE devices
    tui.progress.showMessageDialog("Please wait", "Discovering devices...")
    result = fcoeutil.start_fcoe(answers['fcoe-interfaces'])
    xelogging.log("fcoe result %s" % str(result))
    tui.progress.clearModelessDialog()

    fail = {k: v for k, v in result.iteritems() if v != 'OK'}
    if len(fail.keys()) > 0:
        # Report any errors
        err_text = '\n'.join(
            map(lambda (x, y): "%s %s" % (x, y), fail.iteritems()))
        text = TextboxReflowed(
            60, "The following errors occured while discovering FCoE disks.")
        errs = Textbox(30, 6, err_text, scroll=len(fail.keys()) > 6)
        buttons = ButtonBar(tui.screen, [('Ok', 'ok')])

        gf = GridFormHelp(tui.screen, 'Discovery Failure', 'fipvlanfail', 1, 3)
        gf.add(text, 0, 0, padding=(0, 0, 0, 1))
        gf.add(errs, 0, 1, padding=(0, 0, 0, 1))
        gf.add(buttons, 0, 2, growx=1)
        gf.run()
        tui.screen.popWindow()

    # Get the results and build a dict of LUNs
    d = fcoeutil.get_fcoe_luns()

    luns = {}
    for k, v in d.items():
        for k2, v2 in v.items():
            for lun in v2['luns'].values():
                luns[os.path.basename(lun['device'])] = {
                    'Capacity': lun['capacity'],
                    'Description': lun['description'],
                    'Port': v2['Port Name'],
                    'VLAN': k
                }

    xelogging.log("fcoe luns discovered %s" % str(luns))

    def disk_details(context):
        tui.update_help_line([' ', ' '])
        table = [("Name:", context)]
        for label in ("VLAN", "Capacity", "Port", "Description"):
            table.append((label + ':', luns[context][label]))
        snackutil.TableDialog(tui.screen, "Disk Details", *table)
        tui.screen.popHelpLine()
        return True

    if len(luns.keys()) > 0:
        disk_list = []
        for lun in sorted(luns.keys()):
            disk_list.append(("%s - %s" % (lun, luns[lun]['Capacity']), lun))

        tui.update_help_line([None, "<F5> more info"])
        scroll, height = snackutil.scrollHeight(6, len(disk_list))
        snackutil.ListboxChoiceWindowEx(
            tui.screen,
            "FCoE Disks",
            "The following devices are now available.",
            disk_list, ['Ok'],
            45,
            scroll,
            height,
            None,
            help='fcoedisks:info',
            hotkeys={'F5': disk_details})
        tui.screen.popHelpLine()