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
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
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()