def restore_file(src_base, f, d=None): if not d: d = f src = os.path.join(src_base, f) dst = os.path.join(mounts['root'], d) if os.path.exists(src): xelogging.log("Restoring /%s" % f) util.assertDir(os.path.dirname(dst)) if os.path.isdir(src): util.runCmd2(['cp', '-a', src, os.path.dirname(dst)]) else: util.runCmd2(['cp', '-a', src, dst]) abs_f = os.path.join('/', f) abs_d = os.path.join('/', d) copy_ownership(src_base, abs_f, mounts['root'], abs_d) for dirpath, dirnames, filenames in os.walk(src): for i in dirnames + filenames: src_path = os.path.join(dirpath, i)[len(src_base):] dst_path = os.path.join(abs_d, src_path[len(abs_f) + 1:]) copy_ownership(src_base, src_path, mounts['root'], dst_path) else: xelogging.log( "WARNING: /%s did not exist in the backup image." % f)
def modprobe(module, params=""): xelogging.log("Loading module %s" % " ".join([module, params])) rc = util.runCmd2(["modprobe", module, params]) if rc != 0: xelogging.log("(Failed.)") return rc
def run_script(script, stage, *args): xelogging.log("Running script for stage %s: %s %s" % (stage, script, ' '.join(args))) util.assertDir(constants.SCRIPTS_DIR) fd, local_name = tempfile.mkstemp(prefix = stage, dir = constants.SCRIPTS_DIR) try: util.fetchFile(script, local_name) # check the interpreter fh = os.fdopen(fd) fh.seek(0) line = fh.readline(40) fh.close() except: raise RuntimeError, "Unable to fetch script %s" % script if not line.startswith('#!'): raise RuntimeError, "Missing interpreter in %s." % script interp = line[2:].split() if interp[0] == '/usr/bin/env': if len (interp) < 2 or interp[1] not in ['python']: raise RuntimeError, "Invalid interpreter %s in %s." % (interp[1], script) elif interp[0] not in ['/bin/sh', '/bin/bash', '/usr/bin/python']: raise RuntimeError, "Invalid interpreter %s in %s." % (interp[0], script) cmd = [local_name] cmd.extend(args) os.chmod(local_name, stat.S_IRUSR | stat.S_IXUSR) os.environ['XS_STAGE'] = stage rc, out, err = util.runCmd2(cmd, with_stdout = True, with_stderr = True) xelogging.log("Script returned %d" % rc) # keep script, will be collected in support tarball return rc, out, err
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: xelogging.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: xelogging.logException(e) ButtonChoiceWindow( ui.screen, "Problem Loading Driver", "Setup was unable to load the device driver.", ['Ok']) return media, address
def bindMount(source, mountpoint): xelogging.log("Bind mounting %s to %s" % (source, mountpoint)) cmd = ['/bin/mount', '--bind', source, mountpoint] rc, out, err = runCmd2(cmd, with_stdout=True, with_stderr=True) if rc != 0: raise MountFailureException, "out: '%s' err: '%s'" % (out, err)
def check(self, fast=False, progress=lambda x: ()): """ Check a package against it's known checksum, or if fast is specified, just check that the package exists. """ if fast: return self.repository.accessor().access(self.name) else: try: xelogging.log("Validating package %s" % self.name) namefp = self.repository.accessor().openAddress(self.name) m = hashlib.sha256() data = '' total_read = 0 while True: data = namefp.read(10485760) total_read += len(data) if data == '': break else: m.update(data) progress(total_read / (self.size / 100)) namefp.close() calculated = m.hexdigest() valid = (self.sha256sum == calculated) return valid except Exception, e: return False
def modprobe_file(module, remove=True, params="", name=None): INSMOD = "/sbin/insmod" if remove and module_present(module): # Try to remove the module if already loaded rc = util.runCmd2(["rmmod", module]) if rc != 0: raise RuntimeError, "Unable to replace module %s which is already loaded. Please see the documentation for instructions of how to blacklist it." % module # First use modinfo to find out what the dependants of the # module are and modprobe them: # # deps will initially look like 'depends: x,y,z' rc, out = util.runCmd2(["modinfo", module], with_stdout=True) if rc != 0: raise RuntimeError, "Error interrogating module." [deps] = filter(lambda x: x.startswith("depends:"), out.split("\n")) deps = deps[9:].strip() if deps != "": deps = deps.split(",") for dep in deps: if not module_present(dep): modprobe(dep) xelogging.log("Inserting module %s %s (%s)" % (module, params, name)) rc = util.runCmd2([INSMOD, module, params]) if rc != 0: xelogging.log("(Failed.)") return rc
def processAnswerfile(self): """ Downloads an answerfile from 'location' -- this is in the URL format used by fetchFile in the util module (which also permits fetching over NFS). Returns answers ready for the backend to process. """ xelogging.log("Importing XML answerfile.") # fresh install or upgrade? install_type = self.nodelist.getAttribute("mode") if install_type in ['', 'fresh']: results = self.parseFreshInstall() elif install_type == "reinstall": results = self.parseReinstall() elif install_type == "upgrade": results = self.parseUpgrade() nb_nodes = self.nodelist.getElementsByTagName('network-backend') if len(nb_nodes) == 1: network_backend = getText(nb_nodes[0].childNodes) 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 AnswerfileError, "Specified Network backend type \"%s\" unknown." % network_backend else: results['network-backend'] = constants.NETWORK_BACKEND_DEFAULT return results
def log_available_disks(): disks = getQualifiedDiskList() # make sure we have discovered at least one disk and # at least one network interface: if len(disks) == 0: xelogging.log("No disks found on this host.") else: # make sure that we have enough disk space: xelogging.log("Found disks: %s" % str(disks)) diskSizes = [getDiskDeviceSize(x) for x in disks] diskSizesGB = [blockSizeToGBSize(x) for x in diskSizes] xelogging.log("Disk sizes: %s" % str(diskSizesGB)) old_dom0disks = filter( lambda x: constants.min_primary_disk_size_old <= x, diskSizesGB) if len(old_dom0disks) == 0: xelogging.log( "Unable to find a suitable disk (with a size greater than %dGB) to install to." % constants.min_primary_disk_size_old) dom0disks = filter(lambda x: constants.min_primary_disk_size <= x, diskSizesGB) if len(dom0disks) == 0: xelogging.log( "Unable to find a suitable disk (with a size greater than %dGB) to install to." % constants.min_primary_disk_size)
def exn_error_dialog(logname, with_hd, interactive = True): if screen: _, exn, _ = sys.exc_info() exn_str = str(exn) text = constants.error_string(exn_str, logname, with_hd) bb = ButtonBar(screen, ['Reboot']) t = TextboxReflowed(50, text, maxHeight = screen.height - 13) screen.pushHelpLine(" Press <Enter> to reboot.") g = GridFormHelp(screen, "Error occurred", None, 1, 2) g.add(t, 0, 0, padding = (0, 0, 0, 1)) g.add(bb, 0, 1, growx = 1) g.addHotKey("F2") if not interactive: g.setTimer(constants.AUTO_EXIT_TIMER) result = g.runOnce() screen.popHelpLine() # did they press the secret F2 key that activates debugging # features? if result == "F2": traceback_dialog() else: xelogging.log("A text UI error dialog was requested, but the UI has not been initialized yet.")
def exn_error_dialog(logname, with_hd, interactive=True): if screen: _, exn, _ = sys.exc_info() exn_str = str(exn) text = constants.error_string(exn_str, logname, with_hd) bb = ButtonBar(screen, ['Reboot']) t = TextboxReflowed(50, text, maxHeight=screen.height - 13) screen.pushHelpLine(" Press <Enter> to reboot.") g = GridFormHelp(screen, "Error occurred", None, 1, 2) g.add(t, 0, 0, padding=(0, 0, 0, 1)) g.add(bb, 0, 1, growx=1) g.addHotKey("F2") if not interactive: g.setTimer(constants.AUTO_EXIT_TIMER) result = g.runOnce() screen.popHelpLine() # did they press the secret F2 key that activates debugging # features? if result == "F2": traceback_dialog() else: xelogging.log( "A text UI error dialog was requested, but the UI has not been initialized yet." )
def parseExistingInstallation(self): results = {} if len(self.nodelist.getElementsByTagName('existing-installation')) == 0: raise AnswerfileError, "No existing installation specified." ei = getText(self.nodelist.getElementsByTagName('existing-installation')[0].childNodes) if ei.startswith('iscsi:'): # ei is a rfc4173 spec identifying a LUN in the iBFT. # We should be logged into this already. # Convert this spec into a disk location. disk = diskutil.rfc4173_to_disk(ei) else: disk = normalize_disk(ei) # If answerfile names a multipath replace with the master! master = disktools.getMpathMaster(disk) if master: disk = master results['primary-disk'] = disk installations = product.findXenSourceProducts() installations = filter(lambda x: x.primary_disk == disk or diskutil.idFromPartition(x.primary_disk) == disk, installations) if len(installations) == 0: raise AnswerfileError, "Could not locate the installation specified to be reinstalled." elif len(installations) > 1: xelogging.log("Warning: multiple paths detected - recommend use of --device_mapper_multipath=yes") xelogging.log("Warning: selecting 1st path from %s" % str(map(lambda x: x.primary_disk, installations))) results['installation-to-overwrite'] = installations[0] return results
def run_script(script, stage, *args): xelogging.log("Running script for stage %s: %s %s" % (stage, script, " ".join(args))) util.assertDir(constants.SCRIPTS_DIR) fd, local_name = tempfile.mkstemp(prefix=stage, dir=constants.SCRIPTS_DIR) try: util.fetchFile(script, local_name) # check the interpreter fh = os.fdopen(fd) fh.seek(0) line = fh.readline(40) fh.close() except: raise RuntimeError, "Unable to fetch script %s" % script if not line.startswith("#!"): raise RuntimeError, "Missing interpreter in %s." % script interp = line[2:].split() if interp[0] == "/usr/bin/env": if len(interp) < 2 or interp[1] not in ["python"]: raise RuntimeError, "Invalid interpreter %s in." % (interp[1], script) elif interp[0] not in ["/bin/sh", "/bin/bash", "/usr/bin/python"]: raise RuntimeError, "Invalid interpreter %s in %s." % (interp[0], script) cmd = [local_name] cmd.extend(args) os.chmod(local_name, stat.S_IRUSR | stat.S_IXUSR) os.environ["XS_STAGE"] = stage rc, out, err = util.runCmd2(cmd, with_stdout=True, with_stderr=True) xelogging.log("Script returned %d" % rc) # keep script, will be collected in support tarball return rc, out, err
def restoreFromBackup(backup, progress=lambda x: ()): """ Restore files from backup_partition to the root partition on disk. Call progress with a value between 0 and 100. Re-install bootloader. Fails if backup is not same version as the CD in use.""" disk = backup.root_disk tool = PartitionTool(disk) _, boot_partnum, primary_partnum, backup_partnum, logs_partnum, swap_partnum, _ = backend.inspectTargetDisk( disk, None, [], constants.PRESERVE_IF_UTILITY, True, True) backup_version = backup.version limit_version = product.THIS_PLATFORM_VERSION logs_partition = tool.getPartition(logs_partnum) boot_partition = tool.getPartition(boot_partnum) root_partition = partitionDevice(disk, primary_partnum) backup_fs = util.TempMount(backup.partition, 'backup-', options=['ro']) inventory = util.readKeyValueFile(os.path.join(backup_fs.mount_point, constants.INVENTORY_FILE), strip_quotes=True) backup_partition_layout = [] if 'PARTITION_LAYOUT' in inventory: # Present from XS 7.0 backup_partition_layout = inventory['PARTITION_LAYOUT'].split(',') backup_fs.unmount() (boot, _, _, _, logs) = diskutil.probeDisk(disk) xelogging.log("BACKUP DISK PARTITION LAYOUT: %s" % backup_partition_layout) if not logs[0] and boot[ 0] and not backup_partition_layout: # From 7.x (no new layout - yes Boot partition) to 6.x restoreWithoutRepartButUEFI(backup, progress) else: doRestore(backup, progress, backup_partition_layout, logs[0])
def bindMount(source, mountpoint): xelogging.log("Bind mounting %s to %s" % (source, mountpoint)) cmd = [ '/bin/mount', '--bind', source, mountpoint] rc, out, err = runCmd2(cmd, with_stdout=True, with_stderr=True) if rc != 0: raise MountFailureException, "out: '%s' err: '%s'" % (out, err)
def probeDisk(device, justInstall = False): """Examines device and reports the apparent presence of a XenServer installation and/or related usage Returns a tuple (boot, state, storage) Where: boot is a tuple of None, INSTALL_RETAIL and the partition device state is a tuple of True or False and the partition device storage is a tuple of None, STORAGE_LVM or STORAGE_EXT3 and the partition device """ boot = (None, None) state = (False, None) storage = (None, None) possible_srs = [] tool = PartitionTool(device) for num, part in tool.iteritems(): label = None part_device = tool._partitionDevice(num) if part['id'] == tool.ID_LINUX: try: label = readExtPartitionLabel(part_device) except: pass if part['active']: if part['id'] == tool.ID_LINUX: # probe for retail if label and label.startswith('root-'): boot = (INSTALL_RETAIL, part_device) state = (True, part_device) if tool.partitions.has_key(num+2): # George Retail and earlier didn't use the correct id for SRs possible_srs = [num+2] else: if part['id'] == tool.ID_LINUX_LVM: if num not in possible_srs: possible_srs.append(num) if not justInstall: lv_tool = len(possible_srs) and LVMTool() for num in possible_srs: part_device = tool._partitionDevice(num) if lv_tool.isPartitionConfig(part_device): state = (True, part_device) elif lv_tool.isPartitionSR(part_device): pv = lv_tool.deviceToPVOrNone(part_device) if pv is not None and pv['vg_name'].startswith(lv_tool.VG_EXT_SR_PREFIX): # odd 'ext3 in an LV' SR storage = (STORAGE_EXT3, part_device) else: storage = (STORAGE_LVM, part_device) xelogging.log('Probe of '+device+' found boot='+str(boot)+' state='+str(state)+' storage='+str(storage)) return (boot, state, storage)
def main(args): ui = tui xelogging.log("Starting user interface") ui.init_ui() status = go(ui, args, None, None) xelogging.log("Shutting down user interface") ui.end_ui() return status
def wait_for_multipathd(): for i in range(0,120): if mpath_cli_is_working(): return time.sleep(1) msg = "Unable to contact Multipathd daemon" xelogging.log(msg) raise Exception(msg)
def main(args): ui = tui xelogging.log("Starting user interface") ui.init_ui() status = go(ui, args) xelogging.log("Shutting down user interface") ui.end_ui() return status
def find_installed_products(): try: installed_products = findXenSourceProducts() except Exception, e: xelogging.log("A problem occurred whilst scanning for existing installations:") xelogging.log_exception(e) xelogging.log("This is not fatal. Continuing anyway.") installed_products = []
def find_installed_products(): try: installed_products = findXenSourceProducts() except Exception, e: xelogging.log( "A problem occurred whilst scanning for existing installations:") xelogging.log_exception(e) xelogging.log("This is not fatal. Continuing anyway.") installed_products = []
def getMpathNodes(): nodes = [] rv, out = util.runCmd2(["dmsetup", "ls", "--target", "multipath", "--exec", "ls"], with_stdout=True) xelogging.log("multipath devs: %s" % out) lines = out.strip().split("\n") for line in lines: if line.startswith("/dev/"): nodes.append(line) return nodes
def parseKeymap(self): results = {} keymap_nodes = self.nodelist.getElementsByTagName('keymap') if len(keymap_nodes) == 1: results['keymap'] = getText(keymap_nodes[0].childNodes) else: xelogging.log("No keymap specified in answer file: defaulting to 'us'") results['keymap'] = "us" return results
def findRepositoriesOnMedia(drivers=False): """ Returns a list of repositories available on local media. """ static_device_patterns = ['sd*', 'scd*', 'sr*', 'xvd*', 'nvme*n*'] static_devices = [] for pattern in static_device_patterns: static_devices.extend( map(os.path.basename, glob.glob('/sys/block/' + pattern))) removable_devices = diskutil.getRemovableDeviceList() removable_devices = filter(lambda x: not x.startswith('fd'), removable_devices) parent_devices = [] partitions = [] for dev in removable_devices + static_devices: if os.path.exists("/dev/%s" % dev): if os.path.exists("/sys/block/%s" % dev): dev_partitions = diskutil.partitionsOnDisk(dev) if len(dev_partitions) > 0: partitions.extend( [x for x in dev_partitions if x not in partitions]) else: if dev not in parent_devices: parent_devices.append(dev) else: if dev not in parent_devices: parent_devices.append(dev) da = None repos = [] try: for check in parent_devices + partitions: device_path = "/dev/%s" % check xelogging.log("Looking for repositories: %s" % device_path) if os.path.exists(device_path): da = DeviceAccessor(device_path) try: da.start() except util.MountFailureException: da = None continue else: if drivers: repo = da.findDriverRepository() else: repo = da.findRepository() if repo: repos.append(repo) da.finish() da = None finally: if da: da.finish() return repos
def fetch(location): xelogging.log("Fetching answerfile from %s" % location) util.fetchFile(location, ANSWERFILE_PATH) try: xmldoc = xml.dom.minidom.parse(ANSWERFILE_PATH) except: raise AnswerfileException, "Answerfile is incorrectly formatted." return Answerfile(xmldoc)
def umount(mountpoint, force = False): xelogging.log("Unmounting %s (force = %s)" % (mountpoint, force)) cmd = ['/bin/umount', '-d'] # -d option also removes the loop device (if present) if force: cmd.append('-f') cmd.append(mountpoint) rc = runCmd2(cmd) return rc
def execute(self, answers): assert type(self.predicates) == list assert False not in [callable(x) for x in self.predicates] assert callable(self.fn) if False not in [x(answers) for x in self.predicates]: xelogging.log("Displaying screen %s" % self.fn) return self.fn(answers, *self.args) else: xelogging.log("Not displaying screen %s due to predicate return false." % self.fn) return SKIP_SCREEN
def have_ibft(): """ Determine if an iBFT is present """ rv = util.runCmd2([ '/sbin/modprobe', 'iscsi_ibft' ]) if rv: raise RuntimeError, "/sbin/modprobe iscsi_ibft failed" if os.path.isdir("%s/initiator" % sysfs_ibft_dir): xelogging.log("process_ibft: iBFT found.") return True xelogging.log("process_ibft: No iBFT found.") return False
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 read_ibft(): """ Read in the iBFT (iSCSI Boot Firmware Table) from /sys/firmware/ibft/ and return an initiator name and a list of target configs. """ flags = int(open("%s/initiator/flags" % sysfs_ibft_dir).read()) if (flags & 3) != 3: xelogging.log("process_ibft: Initiator block in iBFT not valid or not selected.") return try: iname = open("%s/initiator/initiator-name" % sysfs_ibft_dir).read() except: raise RuntimeError, "No initiator name in iBFT" targets = [ d for d in os.listdir(sysfs_ibft_dir) if d.startswith("target") ] netdevs = [ (d, open('/sys/class/net/%s/address' % d).read().strip()) for d in os.listdir('/sys/class/net') if d.startswith('eth') ] target_configs = [] for d in targets: flags = int(open("%s/%s/flags" % (sysfs_ibft_dir,d)).read()) if (flags & 3) != 3: xelogging.log("process_ibft: %s block in iBFT not valid or not selected." %d) continue # Find out details of target tgtip = open("%s/%s/ip-addr" % (sysfs_ibft_dir,d)).read().strip() lun = open("%s/%s/lun" % (sysfs_ibft_dir,d)).read().strip() lun = reduce(lambda total,i: (total*10)+int(lun[7-i]), range(8)) nicid = open("%s/%s/nic-assoc" % (sysfs_ibft_dir,d)).read().strip() nicid = int(nicid) port = open("%s/%s/port" % (sysfs_ibft_dir,d)).read().strip() port = int(port) iqn = open("%s/%s/target-name" % (sysfs_ibft_dir,d)).read().strip() # Find out details of NIC used with this target hwaddr = open("%s/ethernet%d/mac" % (sysfs_ibft_dir,nicid)).read().strip() ip = open("%s/ethernet%d/ip-addr" % (sysfs_ibft_dir,nicid)).read().strip() if not os.path.isfile("%s/ethernet%d/gateway" % (sysfs_ibft_dir,nicid)): gw = None else: gw = open("%s/ethernet%d/gateway" % (sysfs_ibft_dir,nicid)).read().strip() nm = open("%s/ethernet%d/subnet-mask" % (sysfs_ibft_dir,nicid)).read().strip() flags = int(open("%s/ethernet%d/flags" % (sysfs_ibft_dir,nicid)).read()) assert (flags & 3) == 3 mac = open('%s/ethernet%d/mac' % (sysfs_ibft_dir,nicid)).read().strip() try: iface = filter(lambda pair: pair[1] == mac, netdevs)[0][0] except: raise RuntimeError, "Found mac %s in iBFT but cannot find matching NIC" % mac target_configs.append(Struct(iface=iface, ip=ip, nm=nm, gw=gw, tgtip=tgtip, port=port, lun=lun, iqn=iqn)) return iname, target_configs
def read_ibft(): """ Read in the iBFT (iSCSI Boot Firmware Table) from /sys/firmware/ibft/ and return an initiator name and a list of target configs. """ flags = int(open("%s/initiator/flags" % sysfs_ibft_dir).read()) if (flags & 3) != 3: xelogging.log("process_ibft: Initiator block in iBFT not valid or not selected.") return try: iname = open("%s/initiator/initiator-name" % sysfs_ibft_dir).read() except: raise RuntimeError, "No initiator name in iBFT" targets = [ d for d in os.listdir(sysfs_ibft_dir) if d.startswith("target") ] netdevs = [ (d, open('/sys/class/net/%s/address' % d).read().strip()) for d in os.listdir('/sys/class/net') if d.startswith('eth') ] target_configs = [] for d in targets: flags = int(open("%s/%s/flags" % (sysfs_ibft_dir,d)).read()) if (flags & 3) != 3: xelogging.log("process_ibft: %s block in iBFT not valid or not selected." %d) continue # Find out details of target tgtip = open("%s/%s/ip-addr" % (sysfs_ibft_dir,d)).read().strip() lun = open("%s/%s/lun" % (sysfs_ibft_dir,d)).read().strip() lun = reduce(lambda total,i: (total*10)+int(lun[7-i]), range(8)) nicid = open("%s/%s/nic-assoc" % (sysfs_ibft_dir,d)).read().strip() nicid = int(nicid) port = open("%s/%s/port" % (sysfs_ibft_dir,d)).read().strip() port = int(port) iqn = open("%s/%s/target-name" % (sysfs_ibft_dir,d)).read().strip() # Find out details of NIC used with this target hwaddr = open("%s/ethernet%d/mac" % (sysfs_ibft_dir,nicid)).read().strip() ip = open("%s/ethernet%d/ip-addr" % (sysfs_ibft_dir,nicid)).read().strip() if not os.path.isfile("%s/ethernet%d/gateway" % (sysfs_ibft_dir,nicid)): gw = None else: gw = open("%s/ethernet%d/gateway" % (sysfs_ibft_dir,nicid)).read().strip() nm = open("%s/ethernet%d/subnet-mask" % (sysfs_ibft_dir,nicid)).read().strip() flags = int(open("%s/ethernet%d/flags" % (sysfs_ibft_dir,nicid)).read()) assert (flags & 3) == 3 mac = open('%s/ethernet%d/mac' % (sysfs_ibft_dir,nicid)).read().strip() try: iface = filter(lambda pair: pair[1] == mac, netdevs)[0][0] except: raise RuntimeError, "Found mac %s in iBFT but cannot find matching NIC" target_configs.append(Struct(iface=iface, ip=ip, nm=nm, gw=gw, tgtip=tgtip, port=port, lun=lun, iqn=iqn)) return iname, target_configs
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, e: xelogging.log("Exception trying to access repository: %s" % e) tui.progress.clearModelessDialog() return REPOCHK_NO_ACCESS
def umount(mountpoint, force=False): xelogging.log("Unmounting %s (force = %s)" % (mountpoint, force)) cmd = ['/bin/umount', '-d'] # -d option also removes the loop device (if present) if force: cmd.append('-f') cmd.append(mountpoint) rc = runCmd2(cmd) return rc
def processAnswerfileSetup(self): """Process enough of the answerfile so that disks can be made available for inspection.""" xelogging.log("Processing XML answerfile setup.") results = {} results.update(self.parseDriverSource()) results.update(self.parseFCoEInterface()) results.update(self.parseUIConfirmationPrompt()) return results
def __init__(self, location = None, xmldoc = None): assert location != None or xmldoc != None if location: xelogging.log("Fetching answerfile from %s" % location) util.fetchFile(location, constants.ANSWERFILE_PATH) try: xmldoc = xml.dom.minidom.parse(constants.ANSWERFILE_PATH) except: raise AnswerfileError, "Answerfile is incorrectly formatted." self.nodelist = xmldoc.documentElement
def doInteractiveLoadDriver(ui, answers): media = None address = None required_repo_list = [] loaded_drivers = [] rc = ui.init.driver_disk_sequence(answers, answers['driver-repos'], answers['loaded-drivers']) if rc: media, address = rc repos = answers['repos'] compat_driver = False # now load the drivers: for r in repos: xelogging.log("Processing repo %s" % r) for p in r: if p.type.startswith('driver') and p.is_loadable(): compat_driver = True if p.load() == 0: loaded_drivers.append(p.name) if r not in required_repo_list: required_repo_list.append(r) else: ButtonChoiceWindow( ui.screen, "Problem Loading Driver", "Setup was unable to load the device driver %s." % p.name, ['Ok'] ) if not compat_driver: ButtonChoiceWindow( ui.screen, "No Compatible Drivers", "Setup was unable to find any drivers compatible with this version of %s." % (PRODUCT_BRAND or PLATFORM_NAME), ['Ok'] ) elif len(loaded_drivers) > 0: answers['loaded-drivers'] += loaded_drivers answers['driver-repos'] += map(lambda r: str(r), required_repo_list) text = "The following drivers were successfully loaded:\n\n" for dr in loaded_drivers: text += " * %s\n" % dr ButtonChoiceWindow( ui.screen, "Drivers Loaded", text, ['Ok']) return media, address, required_repo_list
def restore_file(src_base, f, d = None): if not d: d = f src = os.path.join(src_base, f) dst = os.path.join(mounts['root'], d) if os.path.exists(src): xelogging.log("Restoring /%s" % f) if os.path.isdir(src): util.runCmd2(['cp', '-rp', src, os.path.dirname(dst)]) else: util.assertDir(os.path.dirname(dst)) util.runCmd2(['cp', '-p', src, dst]) else: xelogging.log("WARNING: /%s did not exist in the backup image." % f)
def parseExistingInstallation(self): results = {} inst = getElementsByTagName(self.top_node, ['existing-installation'], mandatory=True) disk = normalize_disk(getText(inst[0])) xelogging.log("Normalized disk: %s" % disk) disk = disktools.getMpathMasterOrDisk(disk) xelogging.log('Primary disk: ' + disk) results['primary-disk'] = disk installations = product.findXenSourceProducts() installations = filter( lambda x: x.primary_disk == disk or diskutil.idFromPartition( x.primary_disk) == disk, installations) if len(installations) == 0: raise AnswerfileException, "Could not locate the installation specified to be reinstalled." elif len(installations) > 1: # FIXME non-multipath case? xelogging.log( "Warning: multiple paths detected - recommend use of --device_mapper_multipath=yes" ) xelogging.log("Warning: selecting 1st path from %s" % str(map(lambda x: x.primary_disk, installations))) results['installation-to-overwrite'] = installations[0] return results
def set_boot_config(installer_dir): try: config = bootloader.Bootloader.loadExisting() default = config.menu[config.default] if 'upgrade' in config.menu_order: config.remove('upgrade') else: config.commit( os.path.join(installer_dir, os.path.basename(config.src_file))) pif = get_mgmt_config() xen_args = ['dom0_mem=752M'] xen_args.extend( filter(lambda x: x.startswith('com') or x.startswith('console='), default.hypervisor_args.split())) kernel_args = filter( lambda x: x.startswith('console=') or x.startswith('xencons='), default.kernel_args.split()) kernel_args.extend(['install', 'answerfile=file:///answerfile']) if pif['ip_configuration_mode'] == 'Static': config_str = "static;ip=%s;netmask=%s" % (pif['IP'], pif['netmask']) if 'gateway' in pif: config_str += ";gateway=" + pif['gateway'] if 'DNS' in pif: config_str += ";dns=" + ','.join(pif['DNS']) kernel_args.extend([ 'network_device=' + pif['MAC'], 'network_config=static;' + config_str ]) else: kernel_args.append('network_device=' + pif['MAC']) e = bootloader.MenuEntry(installer_dir + '/xen.gz', ' '.join(xen_args), installer_dir + '/vmlinuz', ' '.join(kernel_args), installer_dir + '/upgrade.img', 'Rolling pool upgrade') config.append('upgrade', e) config.default = 'upgrade' xelogging.log("Writing updated bootloader config") config.commit() except: return False return True
def mpath_enable(): global use_mpath assert 0 == util.runCmd2(['modprobe','dm-multipath']) # This creates maps for all disks at start of day (because -e is ommitted) assert 0 == util.runCmd2('multipathd -d &> /var/log/multipathd &') wait_for_multipathd() # CA-48440: Cope with lost udev events add_mpath_udev_rule() util.runCmd2(["multipathd","-k"], inputtext="reconfigure") # Tell DM to create partition nodes for newly created mpath devices assert 0 == createMpathPartnodes() xelogging.log("created multipath device(s)"); use_mpath = True
def parseBootloader(self): results = {} keymap_nodes = self.nodelist.getElementsByTagName('bootloader') if len(keymap_nodes) == 1: location = keymap_nodes[0].getAttribute("location").lower() if location == 'partition': results['bootloader-location'] = 'partition' elif location in [ 'mbr', '' ]: results['bootloader-location'] = 'mbr' else: xelogging.log("Unknown bootloader location %s specified in answer file" % location) else: xelogging.log("No bootloader-location specified in answer file.") return results
def partitionTable(self): cmd = [self.SGDISK, "--print", self.device] try: out = self.cmdWrap(cmd) except: # invalid partition table - return empty partition table return {} matchWarning = re.compile("Found invalid GPT and valid MBR; converting MBR to GPT format.") matchHeader = re.compile("Number\s+Start \(sector\)\s+End \(sector\)\s+Size\s+Code\s+Name") matchPartition = re.compile( "^\s+(\d+)\s+(\d+)\s+(\d+)\s+([\d.]+\s+\w+)\s+([0-9A-F]{4})\s+(\w.*)?$" ) # num start end sz typecode name matchActive = re.compile(".*\(legacy BIOS bootable\)") matchId = re.compile("^Partition GUID code: ([0-9A-F\-]+) ") partitions = {} lines = out.split("\n") gotHeader = False for line in lines: if not line.strip(): continue if not gotHeader: if matchWarning.match(line): xelogging.log("Warning: GPTPartitionTool found DOS partition table on device %s" % self.device) elif matchHeader.match(line): gotHeader = True else: matches = matchPartition.match(line) if not matches: raise Exception("Could not parse sgdisk output line: %s" % line) number = int(matches.group(1)) start = int(matches.group(2)) _end = int(matches.group(3)) size = _end + 1 - start partitions[number] = {"start": int(matches.group(2)), "size": size} # For each partition determine the active state. # By active we mean "BIOS bootable" for number in partitions: out = self.cmdWrap([self.SGDISK, "--attributes=%d:show" % number, self.device]) partitions[number]["active"] = matchActive.match(out) and True or False out = self.cmdWrap([self.SGDISK, "--info=%d" % number, self.device]) for line in out.split("\n"): m = matchId.match(line) if m: partitions[number]["id"] = m.group(1) assert partitions[number].has_key("id") return partitions
def fetchFile(source, dest): cleanup_dirs = [] try: # if it's NFS, then mount the NFS server then treat like # file://: if source[:4] == 'nfs:': # work out the components: [_, server, path] = source.split(':') if server[:2] != '//': raise InvalidSource("Did not start {ftp,http,file,nfs}://") server = server[2:] dirpart = os.path.dirname(path) if dirpart[0] != '/': raise InvalidSource( "Directory part of NFS path was not an absolute path.") filepart = os.path.basename(path) xelogging.log( "Split nfs path into server: %s, directory: %s, file: %s." % (server, dirpart, filepart)) # make a mountpoint: mntpoint = tempfile.mkdtemp(dir='/tmp', prefix='fetchfile-nfs-') mount('%s:%s' % (server, dirpart), mntpoint, fstype="nfs", options=['ro']) cleanup_dirs.append(mntpoint) source = 'file://%s/%s' % (mntpoint, filepart) if source[:5] == 'http:' or \ source[:6] == 'https:' or \ source[:5] == 'file:' or \ source[:4] == 'ftp:': # This something that can be fetched using urllib2: fd = urllib2.urlopen(source) fd_dest = open(dest, 'w') shutil.copyfileobj(fd, fd_dest) fd_dest.close() fd.close() else: raise InvalidSource("Unknown source type.") finally: for d in cleanup_dirs: umount(d) os.rmdir(d)
def dump(self): output = "Sector size : " + str(self.sectorSize) + "\n" output += "Sector extent : " + str(self.sectorExtent) + " sectors\n" output += "Sector last usable : " + str(self.sectorLastUsable) + "\n" output += "Sector first usable : " + str(self.sectorFirstUsable) + "\n" output += "Partition size and start addresses in sectors:\n" for number, partition in sorted(self.origPartitions.iteritems()): output += "Old partition " + str(number) + ":" for k, v in sorted(partition.iteritems()): output += " " + k + "=" + ((k == "id") and hex(v) or str(v)) output += "\n" for number, partition in sorted(self.partitions.iteritems()): output += "New partition " + str(number) + ":" for k, v in sorted(partition.iteritems()): output += " " + k + "=" + ((k == "id") and hex(v) or str(v)) output += "\n" xelogging.log(output)
def get_boot_files(accessor, dest_dir): done = True accessor.start() for f in boot_files: try: xelogging.log("Fetching "+f) inf = accessor.openAddress(f) if dest_dir: outf = open(os.path.join(dest_dir, os.path.basename(f)), 'w') outf.writelines(inf) outf.close() inf.close() except: done = False break accessor.finish() return done
def get_boot_files(accessor, dest_dir): done = True accessor.start() for f in boot_files: try: xelogging.log("Fetching " + f) inf = accessor.openAddress(f) if dest_dir: outf = open(os.path.join(dest_dir, os.path.basename(f)), 'w') outf.writelines(inf) outf.close() inf.close() except: done = False break accessor.finish() return done
def processAnswerfile(self): xelogging.log("Processing XML answerfile for %s." % self.operation) if self.operation == 'installation': install_type = getStrAttribute(self.top_node, ['mode'], default = 'fresh') if install_type == "fresh": results = self.parseFreshInstall() elif install_type == "reinstall": results = self.parseReinstall() elif install_type == "upgrade": results = self.parseUpgrade() else: raise AnswerfileException, "Unknown mode, %s" % install_type results.update(self.parseCommon()) elif self.operation == 'restore': results = self.parseRestore() return results
def parse_arg(arg): """ Takes list from the code which parses the installer commandline. Returns a tupe: (Target eth name, Static/Dynamic, Method of id, Val of id) or None if the parse was not successful """ split = arg.split(":", 2) if len(split) != 3: xelogging.log("Invalid device mapping '%s' - Ignoring" % arg) return None eth, sd, val = split if RX_ETH.match(eth) is None: xelogging.log("'%s' is not a valid device name - Ignoring" % eth) return None if sd not in ['s', 'd']: xelogging.log("'%s' is not valid to distinguish between static/dynamic rules" % sd) return None else: if sd == 's': sd = DEV_STATIC else: sd = DEV_DYNAMIC if len(val) < 3: xelogging.log("'%s' is not a valid mapping target - Ignoring" % val) return None if val[0] == '"' and val[-1] == '"': return (eth, sd, METH_LABEL, val[1:-1]) elif RX_MAC.match(val) is not None: return (eth, sd, METH_MAC, val.lower()) elif RX_PCI.match(val) is not None: return (eth, sd, METH_PCI, val.lower()) elif RX_PPN.match(val) is not None: return (eth, sd, METH_PPN, val) else: xelogging.log("'%s' is not a recognised mapping target - Ignoring" % val) return None
def mount(dev, mountpoint, options = None, fstype = None): xelogging.log("Mounting %s to %s, options = %s, fstype = %s" % (dev, mountpoint, options, fstype)) cmd = ['/bin/mount'] if options: assert type(options) == list if fstype: cmd += ['-t', fstype] if options: cmd += ['-o', ",".join(options)] cmd.append(dev) cmd.append(mountpoint) rc, out, err = runCmd2(cmd, with_stdout=True, with_stderr=True) if rc != 0: raise MountFailureException, "out: '%s' err: '%s'" % (out, err)
def runCmd2(command, with_stdout=False, with_stderr=False, inputtext=None): cmd = subprocess.Popen(command, bufsize=1, stdin=(inputtext and subprocess.PIPE or None), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=isinstance(command, str), close_fds=True) # if inputtext: # (out, err) = cmd.communicate(inputtext) # rv = cmd.returncode # else: # (stdout, stderr) = (cmd.stdout, cmd.stderr) # for line in stdout: # out += line # for line in stderr: # err += line # rv = cmd.wait() # the above has a deadlock condition. # The following should suffice in all cases (out, err) = cmd.communicate(inputtext) rv = cmd.returncode l = "ran %s; rc %d" % (str(command), rv) if inputtext: l += " with input %s" % inputtext if out != "": l += "\nSTANDARD OUT:\n" + out if err != "": l += "\nSTANDARD ERROR:\n" + err xelogging.log(l) if with_stdout and with_stderr: return rv, out, err elif with_stdout: return rv, out elif with_stderr: return rv, err return rv
def confirm_erase_volume_groups(answers): problems = diskutil.findProblematicVGs(answers['guest-disks']) if len(problems) == 0: return SKIP_SCREEN if len(problems) == 1: xelogging.log("Problematic VGs: %s" % problems) affected = "The volume group affected is %s. Are you sure you wish to continue?" % problems[0] elif len(problems) > 1: affected = "The volume groups affected are %s. Are you sure you wish to continue?" % generalui.makeHumanList(problems) button = ButtonChoiceWindow(tui.screen, "Conflicting LVM Volume Groups", """Some or all of the disks you selected to install %s onto contain parts of LVM volume groups. Proceeding with the installation will cause these volume groups to be deleted. %s""" % (MY_PRODUCT_BRAND, affected), ['Continue', 'Back'], width=60, help = 'erasevg') if button == 'back': return LEFT_BACKWARDS return RIGHT_FORWARDS
def mount(dev, mountpoint, options=None, fstype=None): xelogging.log("Mounting %s to %s, options = %s, fstype = %s" % (dev, mountpoint, options, fstype)) cmd = ['/bin/mount'] if options: assert type(options) == list if fstype: cmd += ['-t', fstype] if options: cmd += ['-o', ",".join(options)] cmd.append(dev) cmd.append(mountpoint) rc, out, err = runCmd2(cmd, with_stdout=True, with_stderr=True) if rc != 0: raise MountFailureException, "out: '%s' err: '%s'" % (out, err)
def main(args): xcp.logger.openLog(sys.stdout) xelogging.openLog(sys.stdout) dest_url = None answer_device = 'all' answer_config = 'dhcp' init_network = False reboot = False xelogging.log("Command line args: %s" % str(args)) for (opt, val) in args.items(): if opt in ['--answerfile_device', '--network_device']: answer_device = val.lower() init_network = True elif opt == '--network_config': answer_config = val.lower() elif opt == "--reboot": reboot = True elif opt == "--dest": dest_url = val if init_network: configureNetworking(answer_device, answer_config) # probe for XS installations insts = product.findXenSourceProducts() if len(insts) == 0: xcp.logger.log("No installations found.") return if not dest_url: xcp.logger.log("Destination directory not specified.") return for inst in insts: xcp.logger.log(str(inst)) bugtool(inst, dest_url) return reboot
def installKeys(self, root): if len(self.keyfiles) == 0: return keysdir = os.path.join(root, 'etc', 'firstboot.d', 'data', 'keys') if not os.path.exists(keysdir): os.makedirs(keysdir, 0755) self._accessor.start() try: for keyfile in self.keyfiles: infh = self._accessor.openAddress(keyfile) outfh = open(os.path.join(keysdir, os.path.basename(keyfile)), "w") outfh.write(infh.read()) outfh.close() infh.close() except Exception as e: xelogging.log(str(e)) self._accessor.finish() raise ErrorInstallingPackage("Error installing key files") self._accessor.finish()