def disk_more_info(context): if not context: return True usage = 'unknown' (boot, state, storage) = diskutil.probeDisk(context) if boot[0]: usage = "%s installation" % MY_PRODUCT_BRAND elif storage[0]: usage = 'VM storage' else: # Determine disk is being used as an LVM SR with no partitioning rv, out = util.runCmd2([ 'pvs', context, '-o', 'vg_name', '--noheadings' ], with_stdout=True) if rv == 0: vg_name = out.strip() if vg_name.startswith('VG_XenStorage-'): usage = 'VM Storage' tui.update_help_line([' ', ' ']) snackutil.TableDialog(tui.screen, "Details", ("Disk:", diskutil.getHumanDiskName(context)), ("Vendor:", diskutil.getDiskDeviceVendor(context)), ("Model:", diskutil.getDiskDeviceModel(context)), ("Serial:", diskutil.getDiskSerialNumber(context)), ("Size:", diskutil.getHumanDiskSize(diskutil.getDiskDeviceSize(context))), ("Current usage:", usage)) tui.screen.popHelpLine() return True
def more_info(context): if not context: return True obj, _ = context if isinstance(obj, product.ExistingInstallation): use = "%s installation" % obj.visual_brand elif isinstance(obj, product.XenServerBackup): use = "%s backup" % obj.visual_brand else: return True date = "Unknown" if 'INSTALLATION_DATE' in obj.inventory: date = obj.inventory['INSTALLATION_DATE'] dev = "Unknown" if 'PRIMARY_DISK' in obj.inventory: pd = obj.inventory['PRIMARY_DISK'] if pd == "ToBeDetermined": dev = diskutil.getHumanDiskName(obj.primary_disk) else: dev = "%s (%s)" % (diskutil.getHumanDiskName(os.path.realpath(pd)), diskutil.getHumanDiskName(pd)) tui.update_help_line([' ', ' ']) snackutil.TableDialog(tui.screen, "Details", ("Use:", use), ("Version:", str(obj.visual_version)), ("Build:", str(obj.build)), ("Installed:", date), ("Disk:", dev)) tui.screen.popHelpLine() return True
def disk_more_info(context): if not context: return True usage = 'unknown' (boot, root, state, storage, logs) = diskutil.probeDisk(context) if root[0]: usage = "%s installation" % MY_PRODUCT_BRAND elif storage[0]: usage = 'VM storage' else: # Determine disk is being used as an LVM SR with no partitioning rv, out = util.runCmd2([ 'pvs', context, '-o', 'vg_name', '--noheadings' ], with_stdout=True) if rv == 0: vg_name = out.strip() if vg_name.startswith('VG_XenStorage-'): usage = 'VM Storage' tui.update_help_line([' ', ' ']) snackutil.TableDialog(tui.screen, "Details", ("Disk:", diskutil.getHumanDiskName(context)), ("Vendor:", diskutil.getDiskDeviceVendor(context)), ("Model:", diskutil.getDiskDeviceModel(context)), ("Serial:", diskutil.getDiskSerialNumber(context)), ("Size:", diskutil.getHumanDiskSize(diskutil.getDiskDeviceSize(context))), ("Current usage:", usage)) tui.screen.popHelpLine() return True
def more_info(context): if not context: return True obj, _ = context if isinstance(obj, product.ExistingInstallation): use = "%s installation" % MY_PRODUCT_BRAND elif isinstance(obj, product.XenServerBackup): use = "%s backup" % MY_PRODUCT_BRAND else: return True date = "Unknown" if 'INSTALLATION_DATE' in obj.inventory: date = obj.inventory['INSTALLATION_DATE'] dev = "Unknown" if 'PRIMARY_DISK' in obj.inventory: pd = obj.inventory['PRIMARY_DISK'] if pd == "ToBeDetermined": dev = diskutil.getHumanDiskName(obj.primary_disk) else: dev = "%s (%s)" % (diskutil.getHumanDiskName(os.path.realpath(pd)), diskutil.getHumanDiskName(pd)) tui.update_help_line([' ', ' ']) snackutil.TableDialog(tui.screen, "Details", ("Use:", use), ("Version:", str(obj.version)), ("Installed:", date), ("Disk:", dev)) tui.screen.popHelpLine() return True
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
def load_driver(driver_answers): tui.screen.popHelpLine() tui.update_help_line([None, ' ']) drivers = driver.doInteractiveLoadDriver(tui, driver_answers) xelogging.log(drivers) xelogging.log(driver_answers) if drivers[0]: if 'extra-repos' not in answers: answers['extra-repos'] = [] answers['extra-repos'].append(drivers) return True
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
def raid_array_ui(answers): disk_entries = sorted_disk_list() raid_disks = [de for de in disk_entries if diskutil.is_raid(de)] raid_slaves = [slave for master in raid_disks for slave in diskutil.getDeviceSlaves(master)] entries = [] for de in disk_entries: if de not in raid_slaves and de not in raid_disks: vendor, model, size = diskutil.getExtendedDiskInfo(de) string_entry = "%s - %s [%s %s]" % ( diskutil.getHumanDiskName(de), diskutil.getHumanDiskSize(size), vendor, model) entries.append((string_entry, de)) if len(entries) < 2: return SKIP_SCREEN text = TextboxReflowed(54, "Do you want to group disks in a software RAID 1 array? \n\n" + "The array will be created immediately and erase all the target disks.") buttons = ButtonBar(tui.screen, [('Create', 'create'), ('Back', 'back')]) scroll, _ = snackutil.scrollHeight(3, len(entries)) cbt = CheckboxTree(3, scroll) for (c_text, c_item) in entries: cbt.append(c_text, c_item, False) gf = GridFormHelp(tui.screen, 'RAID Array', 'guestdisk:info', 1, 4) gf.add(text, 0, 0, padding=(0, 0, 0, 1)) gf.add(cbt, 0, 1, padding=(0, 0, 0, 1)) gf.add(buttons, 0, 3, growx=1) gf.addHotKey('F5') tui.update_help_line([None, "<F5> disk info"]) loop = True while loop: rc = gf.run() if rc == 'F5': disk_more_info(cbt.getCurrent()) else: loop = False tui.screen.popWindow() tui.screen.popHelpLine() button = buttons.buttonPressed(rc) if button == 'create': selected = cbt.getSelection() txt = 'The content of the disks %s will be deleted when you activate "Ok"' % (str(selected)) title = 'RAID array creation' confirmation = snackutil.ButtonChoiceWindowEx(tui.screen, title, txt, ('Ok', 'Cancel'), 40, default=1) if confirmation == 'ok': answers['raid'] = {'/dev/md127': selected} tui.progress.showMessageDialog("Please wait", "Creating raid array...") diskutil.create_raid(answers['raid']) tui.progress.clearModelessDialog() return REPEAT_STEP
def get_local_disk(answers): diskEntries = diskutil.getQualifiedDiskList() entries = [] target_is_sr = {} for de in diskEntries: (vendor, model, size) = diskutil.getExtendedDiskInfo(de) # determine current usage target_is_sr[de] = False (boot, root, state, storage, logs) = diskutil.probeDisk(de) if storage[0]: target_is_sr[de] = True (vendor, model, size) = diskutil.getExtendedDiskInfo(de) stringEntry = "%s - %s [%s %s]" % (diskutil.getHumanDiskName(de), diskutil.getHumanDiskSize(size), vendor, model) e = (stringEntry, de) entries.append(e) # default value: default = None if 'dest-disk' in answers: default = selectDefault(answers['dest-disk'], entries) tui.update_help_line([None, "<F5> more info"]) scroll, height = snackutil.scrollHeight(4, len(entries)) (button, entry) = snackutil.ListboxChoiceWindowEx( tui.screen, "Select Device", "Please select the device to store the report on.", entries, ['Ok', 'Back'], 55, scroll, height, default, help='getlocaldisk:info', hotkeys={'F5': disk_more_info}) tui.screen.popHelpLine() if button == 'back': return uicontroller.LEFT_BACKWARDS # entry contains the 'de' part of the tuple passed in answers['dest-disk'] = entry return uicontroller.RIGHT_FORWARDS
def disk_more_info(context): if not context: return True usage = 'unknown' (boot, state, storage) = diskutil.probeDisk(context) if boot[0]: usage = "%s installation" % (PRODUCT_BRAND or PLATFORM_NAME) elif storage[0]: usage = 'VM storage' tui.update_help_line([' ', ' ']) snackutil.TableDialog(tui.screen, "Details", ("Disk:", diskutil.getHumanDiskName(context)), ("Vendor:", diskutil.getDiskDeviceVendor(context)), ("Model:", diskutil.getDiskDeviceModel(context)), ("Size:", diskutil.getHumanDiskSize(diskutil.getDiskDeviceSize(context))), ("Current usage:", usage)) tui.screen.popHelpLine() return True
def iface_details(context): tui.update_help_line([' ', ' ']) if context: nic = conf[context] table = [("Name:", nic.name), ("Driver:", nic.driver), ("MAC Address:", nic.hwaddr), ("PCI Details:", nic.pci_string)] if nic.smbioslabel != "": table.append(("BIOS Label:", nic.smbioslabel)) snackutil.TableDialog(tui.screen, "Interface Details", *table) else: netifs_all = netutil.getNetifList(include_vlan=True) details = map(lambda x: (x, netutil.ipaddr(x)), filter(netutil.interfaceUp, netifs_all)) snackutil.TableDialog(tui.screen, "Networking Details", *details) tui.screen.popHelpLine() return True
def iface_details(context): tui.update_help_line([' ', ' ']) if context: nic = conf[context] table = [ ("Name:", nic.name), ("Driver:", nic.driver), ("MAC Address:", nic.hwaddr), ("PCI Details:", nic.pci_string) ] if nic.smbioslabel != "": table.append(("BIOS Label:", nic.smbioslabel)) snackutil.TableDialog(tui.screen, "Interface Details", *table) else: details = map(lambda x: (x, netutil.ipaddr(x)), filter(netutil.interfaceUp, netifs)) snackutil.TableDialog(tui.screen, "Networking Details", *details) tui.screen.popHelpLine() return True
def disk_more_info(context): if not context: return True usage = 'unknown' (boot, root, state, storage, logs) = diskutil.probeDisk(context) if root[0]: usage = "%s installation" % (PRODUCT_BRAND or PLATFORM_NAME) elif storage[0]: usage = 'VM storage' tui.update_help_line([' ', ' ']) snackutil.TableDialog( tui.screen, "Details", ("Disk:", diskutil.getHumanDiskName(context)), ("Vendor:", diskutil.getDiskDeviceVendor(context)), ("Model:", diskutil.getDiskDeviceModel(context)), ("Size:", diskutil.getHumanDiskSize( diskutil.getDiskDeviceSize(context))), ("Current usage:", usage)) tui.screen.popHelpLine() return True
def get_local_dest(answers): partitions = diskutil.partitionsOnDisk(answers['dest-disk']) if len(partitions) == 0: answers['dest-address'] = answers['dest-disk'] elif len(partitions) == 1: answers['dest-address'] = '/dev/' + partitions[0] else: entries = [] for part in partitions: e = (part, '/dev/' + part) entries.append(e) # default value: default = None if 'dest-address' in answers: default = selectDefault(answers['dest-address'], entries) tui.update_help_line([None, "<F5> more info"]) scroll, height = snackutil.scrollHeight(4, len(entries)) (button, entry) = snackutil.ListboxChoiceWindowEx( tui.screen, "Select Device", "Please select the partition to store the report on.", entries, ['Ok', 'Back'], 55, scroll, height, default, help='getlocaldest:info', hotkeys={'F5': disk_more_info}) tui.screen.popHelpLine() if button == 'back': return uicontroller.LEFT_BACKWARDS # entry contains the 'de' part of the tuple passed in answers['dest-address'] = entry return uicontroller.RIGHT_FORWARDS
def get_local_disk(answers): diskEntries = diskutil.getQualifiedDiskList() entries = [] target_is_sr = {} for de in diskEntries: (vendor, model, size) = diskutil.getExtendedDiskInfo(de) # determine current usage target_is_sr[de] = False (boot, state, storage) = diskutil.probeDisk(de) if storage[0]: target_is_sr[de] = True (vendor, model, size) = diskutil.getExtendedDiskInfo(de) stringEntry = "%s - %s [%s %s]" % (diskutil.getHumanDiskName(de), diskutil.getHumanDiskSize(size), vendor, model) e = (stringEntry, de) entries.append(e) # default value: default = None if 'dest-disk' in answers: default = selectDefault(answers['dest-disk'], entries) tui.update_help_line([None, "<F5> more info"]) scroll, height = snackutil.scrollHeight(4, len(entries)) (button, entry) = snackutil.ListboxChoiceWindowEx( tui.screen, "Select Device", "Please select the device to store the report on.", entries, ['Ok', 'Back'], 55, scroll, height, default, help = 'getlocaldisk:info', hotkey = 'F5', hotkey_cb = disk_more_info) tui.screen.popHelpLine() if button == 'back': return uicontroller.LEFT_BACKWARDS # entry contains the 'de' part of the tuple passed in answers['dest-disk'] = entry return uicontroller.RIGHT_FORWARDS
def get_local_dest(answers): partitions = diskutil.partitionsOnDisk(answers['dest-disk']) if len(partitions) == 0: answers['dest-address'] = answers['dest-disk'] elif len(partitions) == 1: answers['dest-address'] = '/dev/' + partitions[0] else: entries = [] for part in partitions: e = (part, '/dev/' + part) entries.append(e) # default value: default = None if 'dest-address' in answers: default = selectDefault(answers['dest-address'], entries) tui.update_help_line([None, "<F5> more info"]) scroll, height = snackutil.scrollHeight(4, len(entries)) (button, entry) = snackutil.ListboxChoiceWindowEx( tui.screen, "Select Device", "Please select the partition to store the report on.", entries, ['Ok', 'Back'], 55, scroll, height, default, help = 'getlocaldest:info', hotkey = 'F5', hotkey_cb = disk_more_info) tui.screen.popHelpLine() if button == 'back': return uicontroller.LEFT_BACKWARDS # entry contains the 'de' part of the tuple passed in answers['dest-address'] = entry return uicontroller.RIGHT_FORWARDS
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()
def get_installation_type(answers): entries = [] for x in answers['upgradeable-products']: entries.append(("Upgrade %s" % str(x), (x, x.settingsAvailable()))) for b in answers['backups']: entries.append(("Restore %s from backup" % str(b), (b, None))) entries.append( ("Perform clean installation", None) ) # default value? if answers.has_key('install-type') and answers['install-type'] == constants.INSTALL_TYPE_REINSTALL: default = selectDefault(answers['installation-to-overwrite'], entries) elif answers.has_key('install-type') and answers['install-type'] == constants.INSTALL_TYPE_RESTORE: default = selectDefault(answers['backup-to-restore'], entries) else: default = None if len(answers['upgradeable-products']) > 0: text = "One or more existing product installations that can be upgraded have been detected." if len(answers['backups']) > 0: text += " In addition one or more backups have been detected." else: text = "One or more backups have been detected." text += "\n\nWhat would you like to do?" tui.update_help_line([None, "<F5> more info"]) def more_info(context): if not context: return True obj, _ = context if isinstance(obj, product.ExistingInstallation): use = "%s installation" % MY_PRODUCT_BRAND elif isinstance(obj, product.XenServerBackup): use = "%s backup" % MY_PRODUCT_BRAND else: return True date = "Unknown" if 'INSTALLATION_DATE' in obj.inventory: date = obj.inventory['INSTALLATION_DATE'] dev = "Unknown" if 'PRIMARY_DISK' in obj.inventory: pd = obj.inventory['PRIMARY_DISK'] if pd == "ToBeDetermined": dev = diskutil.getHumanDiskName(obj.primary_disk) else: dev = "%s (%s)" % (diskutil.getHumanDiskName(os.path.realpath(pd)), diskutil.getHumanDiskName(pd)) tui.update_help_line([' ', ' ']) snackutil.TableDialog(tui.screen, "Details", ("Use:", use), ("Version:", str(obj.version)), ("Installed:", date), ("Disk:", dev)) tui.screen.popHelpLine() return True (button, entry) = snackutil.ListboxChoiceWindowEx( tui.screen, "Action To Perform", text, entries, ['Ok', 'Back'], width=60, default = default, help = 'action:info', hotkey = 'F5', hotkey_cb = more_info) tui.screen.popHelpLine() if button == 'back': return LEFT_BACKWARDS if entry == None: answers['install-type'] = constants.INSTALL_TYPE_FRESH answers['preserve-settings'] = False if answers.has_key('installation-to-overwrite'): del answers['installation-to-overwrite'] elif isinstance(entry[0], product.ExistingInstallation): answers['install-type'] = constants.INSTALL_TYPE_REINSTALL answers['installation-to-overwrite'], preservable = entry answers['preserve-settings'] = preservable if 'primary-disk' not in answers: answers['primary-disk'] = answers['installation-to-overwrite'].primary_disk for k in ['guest-disks', 'default-sr-uuid']: if answers.has_key(k): del answers[k] elif isinstance(entry[0], product.XenServerBackup): answers['install-type'] = constants.INSTALL_TYPE_RESTORE answers['backup-to-restore'], _ = entry return RIGHT_FORWARDS
def welcome_screen(answers): driver_answers = {'driver-repos': []} tui.update_help_line([None, "<F9> load driver"]) def load_driver(driver_answers): tui.screen.popHelpLine() tui.update_help_line([None, ' ']) drivers = driver.doInteractiveLoadDriver(tui, driver_answers) xelogging.log(drivers) xelogging.log(driver_answers) if drivers[0]: if 'extra-repos' not in answers: answers['extra-repos'] = [] answers['extra-repos'].append(drivers) return True global loop global popup loop = True def fn9(): global loop global popup loop = True popup = 'driver' return False def fn10(): global loop global popup loop = True popup = 'storage' return False while loop: loop = False popup = None driver_answers['network-hardware'] = answers['network-hardware'] = netutil.scanConfiguration() button = snackutil.ButtonChoiceWindowEx(tui.screen, "Welcome to %s Setup" % MY_PRODUCT_BRAND, """This setup tool can be used to install or upgrade %s on your system or restore your server from backup. Installing %s will erase all data on the disks selected for use. Please make sure you have backed up any data you wish to preserve before proceeding. To load a device driver press <F9>. To setup advanced storage classes press <F10>. """ % (MY_PRODUCT_BRAND, MY_PRODUCT_BRAND), ['Ok', 'Reboot'], width = 60, help = "welcome", hotkeys = {'F9': fn9, 'F10': fn10}) if popup == 'driver': load_driver(driver_answers) tui.update_help_line([None, "<F9> load driver"]) elif popup == 'storage': tui.fcoe.select_fcoe_ifaces(answers) tui.update_help_line([None, "<F9> load driver"]) tui.screen.popHelpLine() if button == 'reboot': return EXIT xelogging.log("Waiting for partitions to appear...") util.runCmd2(util.udevsettleCmd()) time.sleep(1) diskutil.mpath_part_scan() # ensure partitions/disks are not locked by LVM lvm = LVMTool() lvm.deactivateAll() del lvm tui.progress.showMessageDialog("Please wait", "Checking for existing products...") answers['installed-products'] = product.find_installed_products() answers['upgradeable-products'] = upgrade.filter_for_upgradeable_products(answers['installed-products']) answers['backups'] = product.findXenSourceBackups() tui.progress.clearModelessDialog() diskutil.log_available_disks() # CA-41142, ensure we have at least one network interface and one disk before proceeding label = None if len(diskutil.getDiskList()) == 0: label = "No Disks" text = "hard disks" text_short = "disks" if len(answers['network-hardware'].keys()) == 0: label = "No Network Interfaces" text = "network interfaces" text_short = "interfaces" if label: text = """This host does not appear to have any %s. If %s are present you may need to load a device driver on the previous screen for them to be detected.""" % (text, text_short) ButtonChoiceWindow(tui.screen, label, text, ["Back"], width = 48) return REPEAT_STEP return RIGHT_FORWARDS
def welcome_screen(answers): driver_answers = {'loaded-drivers': [], 'driver-repos': []} tui.update_help_line([None, "<F9> load driver"]) def load_driver(driver_answers): tui.screen.popHelpLine() tui.update_help_line([None, ' ']) drivers = driver.doInteractiveLoadDriver(tui, driver_answers) xelogging.log(drivers) xelogging.log(driver_answers) if drivers[0]: if 'extra-repos' not in answers: answers['extra-repos'] = [] answers['extra-repos'].append(drivers) return True global loop loop = True def fn9(): global loop loop = True return False while loop: loop = False driver_answers['network-hardware'] = answers['network-hardware'] = netutil.scanConfiguration() button = snackutil.ButtonChoiceWindowEx(tui.screen, "Welcome to %s Setup" % MY_PRODUCT_BRAND, """This setup tool can be used to install or upgrade %s on your system or restore your server from backup. Installing %s will erase all data on the disks selected for use. Please make sure you have backed up any data you wish to preserve before proceeding. To load a device driver press <F9>. """ % (MY_PRODUCT_BRAND, MY_PRODUCT_BRAND), ['Ok', 'Reboot'], width = 60, help = "welcome", hotkey = 'F9', hotkey_cb = fn9) if loop: load_driver(driver_answers) tui.update_help_line([None, "<F9> load driver"]) tui.screen.popHelpLine() if button == 'reboot': return EXIT # CA-41142, ensure we have at least one network interface and one disk before proceeding label = None if len(diskutil.getDiskList()) == 0: label = "No Disks" text = "hard disks" text_short = "disks" if len(answers['network-hardware'].keys()) == 0: label = "No Network Interfaces" text = "network interfaces" text_short = "interfaces" if label: text = """This host does not appear to have any %s. If %s are present you may need to load a device driver on the previous screen for them to be detected.""" % (text, text_short) ButtonChoiceWindow(tui.screen, label, text, ["Back"], width = 48) return REPEAT_STEP return RIGHT_FORWARDS
def get_installation_type(answers): entries = [] for x in answers['upgradeable-products']: entries.append(("Upgrade %s" % str(x), (x, x.settingsAvailable()))) for b in answers['backups']: entries.append(("Restore %s from backup" % str(b), (b, None))) entries.append( ("Perform clean installation", None) ) # default value? if answers.has_key('install-type') and answers['install-type'] == constants.INSTALL_TYPE_REINSTALL: default = selectDefault(answers['installation-to-overwrite'], entries) elif answers.has_key('install-type') and answers['install-type'] == constants.INSTALL_TYPE_RESTORE: default = selectDefault(answers['backup-to-restore'], entries) else: default = None if len(answers['upgradeable-products']) > 0: text = "One or more existing product installations that can be upgraded have been detected." if len(answers['backups']) > 0: text += " In addition one or more backups have been detected." else: text = "One or more backups have been detected." text += "\n\nWhat would you like to do?" tui.update_help_line([None, "<F5> more info"]) def more_info(context): if not context: return True obj, _ = context if isinstance(obj, product.ExistingInstallation): use = "%s installation" % obj.visual_brand elif isinstance(obj, product.XenServerBackup): use = "%s backup" % obj.visual_brand else: return True date = "Unknown" if 'INSTALLATION_DATE' in obj.inventory: date = obj.inventory['INSTALLATION_DATE'] dev = "Unknown" if 'PRIMARY_DISK' in obj.inventory: pd = obj.inventory['PRIMARY_DISK'] if pd == "ToBeDetermined": dev = diskutil.getHumanDiskName(obj.primary_disk) else: dev = "%s (%s)" % (diskutil.getHumanDiskName(os.path.realpath(pd)), diskutil.getHumanDiskName(pd)) tui.update_help_line([' ', ' ']) snackutil.TableDialog(tui.screen, "Details", ("Use:", use), ("Version:", str(obj.visual_version)), ("Build:", str(obj.build)), ("Installed:", date), ("Disk:", dev)) tui.screen.popHelpLine() return True (button, entry) = snackutil.ListboxChoiceWindowEx( tui.screen, "Action To Perform", text, entries, ['Ok', 'Back'], width=60, default = default, help = 'action:info', hotkeys = {'F5': more_info}) tui.screen.popHelpLine() if button == 'back': return LEFT_BACKWARDS if entry == None: answers['install-type'] = constants.INSTALL_TYPE_FRESH answers['preserve-settings'] = False if answers.has_key('installation-to-overwrite'): del answers['installation-to-overwrite'] elif isinstance(entry[0], product.ExistingInstallation): answers['install-type'] = constants.INSTALL_TYPE_REINSTALL answers['installation-to-overwrite'], preservable = entry answers['preserve-settings'] = preservable if 'primary-disk' not in answers: answers['primary-disk'] = answers['installation-to-overwrite'].primary_disk for k in ['guest-disks', 'default-sr-uuid']: if answers.has_key(k): del answers[k] elif isinstance(entry[0], product.XenServerBackup): answers['install-type'] = constants.INSTALL_TYPE_RESTORE answers['backup-to-restore'], _ = entry return RIGHT_FORWARDS
def select_primary_disk(answers): button = None diskEntries = diskutil.getQualifiedDiskList() entries = [] target_is_sr = {} for de in diskEntries: (vendor, model, size) = diskutil.getExtendedDiskInfo(de) if constants.min_primary_disk_size <= diskutil.blockSizeToGBSize(size): # determine current usage target_is_sr[de] = False (boot, state, storage) = diskutil.probeDisk(de) if storage[0]: target_is_sr[de] = True (vendor, model, size) = diskutil.getExtendedDiskInfo(de) stringEntry = "%s - %s [%s %s]" % (diskutil.getHumanDiskName(de), diskutil.getHumanDiskSize(size), vendor, model) e = (stringEntry, de) entries.append(e) # we should have at least one disk if len(entries) == 0: ButtonChoiceWindow(tui.screen, "No Primary Disk", "No disk with sufficient space to install %s on was found." % MY_PRODUCT_BRAND, ['Cancel']) return EXIT # if only one disk, set default: if len(entries) == 1: answers['primary-disk'] = entries[0][1] else: # default value: default = None if answers.has_key('primary-disk'): default = selectDefault(answers['primary-disk'], entries) tui.update_help_line([None, "<F5> more info"]) scroll, height = snackutil.scrollHeight(4, len(entries)) (button, entry) = snackutil.ListboxChoiceWindowEx( tui.screen, "Select Primary Disk", """Please select the disk you would like to install %s on (disks with insufficient space are not shown). You may need to change your system settings to boot from this disk.""" % (MY_PRODUCT_BRAND), entries, ['Ok', 'Back'], 55, scroll, height, default, help = 'pridisk:info', hotkey = 'F5', hotkey_cb = disk_more_info) tui.screen.popHelpLine() # entry contains the 'de' part of the tuple passed in answers['primary-disk'] = entry if 'installation-to-overwrite' in answers: answers['target-is-sr'] = target_is_sr[answers['primary-disk']] # Warn if not all of the disk is usable. # This can happen if we are unable to use GPT because we are currently # using DOS and need to preserve some utility partitions. blocks = diskutil.getDiskDeviceSize(answers['primary-disk']) tool = PartitionTool(answers['primary-disk']) if diskutil.blockSizeToGBSize(blocks) > constants.max_primary_disk_size_dos and tool.partTableType == 'DOS': if constants.GPT_SUPPORT and tool.utilityPartitions(): val = snackutil.ButtonChoiceWindowEx(tui.screen, "Large Disk Detected", "The disk selected is larger than the %d GB limit imposed by the DOS partitioning scheme. Would you like to remove the OEM partitions that require the DOS partitioning scheme, so that the whole disk can be used?" % constants.max_primary_disk_size_dos, ['Yes', 'No'], default=1) answers['zap-utility-partitions'] = (val == 'yes') else: ButtonChoiceWindow(tui.screen, "Large Disk Detected", "The disk selected to install %s to is greater than %d GB. The partitioning scheme is limited to this value and therefore the remainder of this disk will be unavailable." % (MY_PRODUCT_BRAND, constants.max_primary_disk_size_dos), ['Ok']) if button == None: return SKIP_SCREEN if button == 'back': return LEFT_BACKWARDS return RIGHT_FORWARDS
def select_guest_disks(answers): diskEntries = diskutil.getQualifiedDiskList() # CA-38329: filter out device mapper nodes (except primary disk) as these won't exist # at XenServer boot and therefore cannot be added as physical volumes to Local SR. # Also, since the DM nodes are multipathed SANs it doesn't make sense to include them # in the "Local" SR. allowed_in_local_sr = lambda dev: (dev == answers['primary-disk']) or (not isDeviceMapperNode(dev)) diskEntries = filter(allowed_in_local_sr, diskEntries) if len(diskEntries) == 0: answers['guest-disks'] = [] return SKIP_SCREEN # set up defaults: if answers.has_key('guest-disks'): currently_selected = answers['guest-disks'] else: currently_selected = answers['primary-disk'] srtype = constants.SR_TYPE_LVM if 'sr-type' in answers: srtype = answers['sr-type'] # Make a list of entries: (text, item) entries = [] for de in diskEntries: (vendor, model, size) = diskutil.getExtendedDiskInfo(de) entry = "%s - %s [%s %s]" % (diskutil.getHumanDiskName(de), diskutil.getHumanDiskSize(size), vendor, model) entries.append((entry, de)) text = TextboxReflowed(54, "Which disks would you like to use for %s storage? \n\nOne storage repository will be created that spans the selected disks. You can choose not to prepare any storage if you wish to create an advanced configuration after installation." % BRAND_GUEST) buttons = ButtonBar(tui.screen, [('Ok', 'ok'), ('Back', 'back')]) scroll, _ = snackutil.scrollHeight(3, len(entries)) cbt = CheckboxTree(3, scroll) for (c_text, c_item) in entries: cbt.append(c_text, c_item, c_item in currently_selected) tb = Checkbox("Enable thin provisioning (Optimized storage for XenDesktop)", srtype == constants.SR_TYPE_EXT and 1 or 0) gf = GridFormHelp(tui.screen, 'Virtual Machine Storage', 'guestdisk:info', 1, 4) gf.add(text, 0, 0, padding = (0, 0, 0, 1)) gf.add(cbt, 0, 1, padding = (0, 0, 0, 1)) gf.add(tb, 0, 2, padding = (0, 0, 0, 1)) gf.add(buttons, 0, 3, growx = 1) gf.addHotKey('F5') tui.update_help_line([None, "<F5> more info"]) loop = True while loop: rc = gf.run() if rc == 'F5': disk_more_info(cbt.getCurrent()) else: loop = False tui.screen.popWindow() tui.screen.popHelpLine() button = buttons.buttonPressed(rc) if button == 'back': return LEFT_BACKWARDS answers['guest-disks'] = cbt.getSelection() answers['sr-type'] = tb.selected() and constants.SR_TYPE_EXT or constants.SR_TYPE_LVM # if the user select no disks for guest storage, check this is what # they wanted: if answers['guest-disks'] == []: button = ButtonChoiceWindow( tui.screen, "Warning", """You didn't select any disks for %s storage. Are you sure this is what you want? If you proceed, please refer to the user guide for details on provisioning storage after installation.""" % BRAND_GUEST, ['Continue', 'Back'], help = 'noguest' ) if button == 'back': return REPEAT_STEP return RIGHT_FORWARDS
def select_primary_disk(answers): button = None diskEntries = filter_out_raid_member(sorted_disk_list()) entries = [] target_is_sr = {} if answers['create-new-partitions']: min_primary_disk_size = constants.min_primary_disk_size else: min_primary_disk_size = constants.min_primary_disk_size_old for de in diskEntries: (vendor, model, size) = diskutil.getExtendedDiskInfo(de) if min_primary_disk_size <= diskutil.blockSizeToGBSize(size): # determine current usage target_is_sr[de] = False (boot, root, state, storage, logs) = diskutil.probeDisk(de) if storage[0]: target_is_sr[de] = True (vendor, model, size) = diskutil.getExtendedDiskInfo(de) stringEntry = "%s - %s [%s %s]" % (diskutil.getHumanDiskName(de), diskutil.getHumanDiskSize(size), vendor, model) e = (stringEntry, de) entries.append(e) # we should have at least one disk if len(entries) == 0: ButtonChoiceWindow(tui.screen, "No Primary Disk", "No disk with sufficient space to install %s on was found." % MY_PRODUCT_BRAND, ['Cancel']) return EXIT # if only one disk, set default: if len(entries) == 1: answers['primary-disk'] = entries[0][1] else: # default value: default = None if answers.has_key('primary-disk'): default = selectDefault(answers['primary-disk'], entries) tui.update_help_line([None, "<F5> more info"]) scroll, height = snackutil.scrollHeight(4, len(entries)) (button, entry) = snackutil.ListboxChoiceWindowEx( tui.screen, "Select Primary Disk", """Please select the disk you would like to install %s on (disks with insufficient space are not shown). You may need to change your system settings to boot from this disk.""" % (MY_PRODUCT_BRAND), entries, ['Ok', 'Software RAID', 'Back'], 55, scroll, height, default, help = 'pridisk:info', hotkeys = {'F5': disk_more_info}) tui.screen.popHelpLine() # entry contains the 'de' part of the tuple passed in answers['primary-disk'] = entry if 'installation-to-overwrite' in answers: answers['target-is-sr'] = target_is_sr[answers['primary-disk']] # Warn if not all of the disk is usable. # This can happen if we are unable to use GPT because we are currently # using DOS and need to preserve some utility partitions. blocks = diskutil.getDiskDeviceSize(answers['primary-disk']) tool = PartitionTool(answers['primary-disk']) if diskutil.blockSizeToGBSize(blocks) > constants.max_primary_disk_size_dos and tool.partTableType == 'DOS': if constants.GPT_SUPPORT and tool.utilityPartitions(): val = snackutil.ButtonChoiceWindowEx(tui.screen, "Large Disk Detected", "The disk selected is larger than the %d GB limit imposed by the DOS partitioning scheme. Would you like to remove the OEM partitions that require the DOS partitioning scheme, so that the whole disk can be used?" % constants.max_primary_disk_size_dos, ['Yes', 'No'], default=1) answers['zap-utility-partitions'] = (val == 'yes') elif not constants.GPT_SUPPORT: ButtonChoiceWindow(tui.screen, "Large Disk Detected", "The disk selected to install %s to is greater than %d GB. The partitioning scheme is limited to this value and therefore the remainder of this disk will be unavailable." % (MY_PRODUCT_BRAND, constants.max_primary_disk_size_dos), ['Ok']) if button == None: return RIGHT_FORWARDS if button == 'software raid': return raid_array_ui(answers) if button == 'back': return LEFT_BACKWARDS return RIGHT_FORWARDS
def select_netif(text, conf, offer_existing=False, default=None): """ Display a screen that displays a choice of network interfaces to the user, with 'text' as the informative text as the data, and conf being the netutil.scanConfiguration() output to be used. """ netifs = conf.keys() netifs.sort(lambda l, r: int(l[3:]) - int(r[3:])) if default not in netifs: # find first link that is up default = None for iface in netifs: if netutil.linkUp(iface): default = iface break def lentry(iface): key = iface tag = netutil.linkUp(iface) and ' ' or ' [no link]' text = "%s (%s)%s" % (iface, conf[iface].hwaddr, tag) return (text, key) def iface_details(context): tui.update_help_line([' ', ' ']) if context: nic = conf[context] table = [("Name:", nic.name), ("Driver:", nic.driver), ("MAC Address:", nic.hwaddr), ("PCI Details:", nic.pci_string)] if nic.smbioslabel != "": table.append(("BIOS Label:", nic.smbioslabel)) snackutil.TableDialog(tui.screen, "Interface Details", *table) else: netifs_all = netutil.getNetifList(include_vlan=True) details = map(lambda x: (x, netutil.ipaddr(x)), filter(netutil.interfaceUp, netifs_all)) snackutil.TableDialog(tui.screen, "Networking Details", *details) tui.screen.popHelpLine() return True def update(listbox): old = listbox.current() for item in listbox.item2key.keys(): if item: text, _ = lentry(item) listbox.replace(text, item) listbox.setCurrent(old) return True tui.update_help_line([None, "<F5> more info"]) def_iface = None if offer_existing and netutil.networkingUp(): netif_list = [("Use existing configuration", None)] else: netif_list = [] if default: def_iface = lentry(default) netif_list += [lentry(x) for x in netifs] scroll, height = snackutil.scrollHeight(6, len(netif_list)) rc, entry = snackutil.ListboxChoiceWindowEx(tui.screen, "Networking", text, netif_list, ['Ok', 'Back'], 45, scroll, height, def_iface, help='selif:info', hotkeys={'F5': iface_details}, timeout_ms=5000, timeout_cb=update) tui.screen.popHelpLine() if rc == 'back': return LEFT_BACKWARDS, None return RIGHT_FORWARDS, entry
def select_guest_disks(answers): diskEntries = filter_out_raid_member(sorted_disk_list()) # CA-38329: filter out device mapper nodes (except primary disk) as these won't exist # at XenServer boot and therefore cannot be added as physical volumes to Local SR. # Also, since the DM nodes are multipathed SANs it doesn't make sense to include them # in the "Local" SR. allowed_in_local_sr = lambda dev: (dev == answers['primary-disk']) or (not isDeviceMapperNode(dev)) diskEntries = filter(allowed_in_local_sr, diskEntries) if len(diskEntries) == 0 or constants.CC_PREPARATIONS: answers['guest-disks'] = [] return SKIP_SCREEN # set up defaults: if answers.has_key('guest-disks'): currently_selected = answers['guest-disks'] else: currently_selected = answers['primary-disk'] srtype = constants.SR_TYPE_LVM if 'sr-type' in answers: srtype = answers['sr-type'] # Make a list of entries: (text, item) entries = [] for de in diskEntries: (vendor, model, size) = diskutil.getExtendedDiskInfo(de) entry = "%s - %s [%s %s]" % (diskutil.getHumanDiskName(de), diskutil.getHumanDiskSize(size), vendor, model) entries.append((entry, de)) text = TextboxReflowed(54, "Which disks would you like to use for %s storage? \n\nOne storage repository will be created that spans the selected disks. You can choose not to prepare any storage if you wish to create an advanced configuration after installation." % BRAND_GUEST) buttons = ButtonBar(tui.screen, [('Ok', 'ok'), ('Back', 'back')]) scroll, _ = snackutil.scrollHeight(3, len(entries)) cbt = CheckboxTree(3, scroll) for (c_text, c_item) in entries: cbt.append(c_text, c_item, c_item in currently_selected) txt = "Use EXT instead of LVM for local storage repository" tb = Checkbox(txt, srtype == constants.SR_TYPE_EXT and 1 or 0) explanations = Textbox(54, 2, "LVM: block based. May be faster. Thick provisioning.\n" "EXT: file based. May be slower. Thin provisioning.") gf = GridFormHelp(tui.screen, 'Virtual Machine Storage', 'guestdisk:info', 1, 5) gf.add(text, 0, 0, padding = (0, 0, 0, 1)) gf.add(cbt, 0, 1, padding = (0, 0, 0, 1)) gf.add(tb, 0, 2, padding = (0, 0, 0, 0)) gf.add(explanations, 0, 3, padding = (0, 0, 0, 1)) gf.add(buttons, 0, 4, growx = 1) gf.addHotKey('F5') tui.update_help_line([None, "<F5> more info"]) loop = True while loop: rc = gf.run() if rc == 'F5': disk_more_info(cbt.getCurrent()) else: loop = False tui.screen.popWindow() tui.screen.popHelpLine() button = buttons.buttonPressed(rc) if button == 'back': return LEFT_BACKWARDS answers['guest-disks'] = cbt.getSelection() answers['sr-type'] = tb.selected() and constants.SR_TYPE_EXT or constants.SR_TYPE_LVM answers['sr-on-primary'] = answers['primary-disk'] in answers['guest-disks'] # if the user select no disks for guest storage, check this is what # they wanted: if answers['guest-disks'] == []: button = ButtonChoiceWindow( tui.screen, "Warning", """You didn't select any disks for %s storage. Are you sure this is what you want? If you proceed, please refer to the user guide for details on provisioning storage after installation.""" % BRAND_GUEST, ['Continue', 'Back'], help = 'noguest' ) if button == 'back': return REPEAT_STEP return RIGHT_FORWARDS
def select_netif(text, conf, offer_existing = False, default = None): """ Display a screen that displays a choice of network interfaces to the user, with 'text' as the informative text as the data, and conf being the netutil.scanConfiguration() output to be used. """ netifs = conf.keys() netifs.sort(lambda l, r: int(l[3:]) - int(r[3:])) if default not in netifs: # find first link that is up default = None for iface in netifs: if netutil.linkUp(iface): default = iface break def lentry(iface): key = iface tag = netutil.linkUp(iface) and ' ' or ' [no link]' text = "%s (%s)%s" % (iface, conf[iface].hwaddr, tag) return (text, key) def iface_details(context): tui.update_help_line([' ', ' ']) if context: nic = conf[context] table = [ ("Name:", nic.name), ("Driver:", nic.driver), ("MAC Address:", nic.hwaddr), ("PCI Details:", nic.pci_string) ] if nic.smbioslabel != "": table.append(("BIOS Label:", nic.smbioslabel)) snackutil.TableDialog(tui.screen, "Interface Details", *table) else: details = map(lambda x: (x, netutil.ipaddr(x)), filter(netutil.interfaceUp, netifs)) snackutil.TableDialog(tui.screen, "Networking Details", *details) tui.screen.popHelpLine() return True def update(listbox): old = listbox.current() for item in listbox.item2key.keys(): if item: text, _ = lentry(item) listbox.replace(text, item) listbox.setCurrent(old) return True tui.update_help_line([None, "<F5> more info"]) def_iface = None if offer_existing and netutil.networkingUp(): netif_list = [("Use existing configuration", None)] else: netif_list = [] if default: def_iface = lentry(default) netif_list += [lentry(x) for x in netifs] scroll, height = snackutil.scrollHeight(6, len(netif_list)) rc, entry = snackutil.ListboxChoiceWindowEx(tui.screen, "Networking", text, netif_list, ['Ok', 'Back'], 45, scroll, height, def_iface, help = 'selif:info', hotkey='F5', hotkey_cb=iface_details, timeout_ms=5000, timeout_cb=update) tui.screen.popHelpLine() if rc == 'back': return LEFT_BACKWARDS, None return RIGHT_FORWARDS, entry