def _build_mpath_topology(self): with open("/etc/multipath.conf") as conf: log.debug("/etc/multipath.conf contents:") map(lambda line: log.debug(line.rstrip()), conf) log.debug("(end of /etc/multipath.conf)") self._mpath_topology = parseMultipathOutput( iutil.execWithCapture("multipath", ["-d",])) self._mpath_topology.update(parseMultipathOutput( iutil.execWithCapture("multipath", ["-ll",]))) delete_keys = [] for (mp, disks) in self._mpath_topology.items(): # single device mpath is not really an mpath, eliminate them: if len(disks) < 2: log.info("MultipathTopology: not a multipath: %s" % disks) delete_keys.append(mp) continue # some usb cardreaders use multiple lun's (for different slots) and # report a fake disk serial which is the same for all the lun's # (#517603). find those mpaths and eliminate them: only_non_usbs = [d for d in disks if self._devmap[d].get("ID_USB_DRIVER") != "usb-storage"] if len(only_non_usbs) == 0: log.info("DeviceToppology: found multi lun usb " "mass storage device: %s" % disks) delete_keys.append(mp) map(lambda key: self._mpath_topology.pop(key), delete_keys)
def testExecCaptureNonZeroFatal(self): import iutil try: argv = ["-c", "import sys; sys.exit(3);"] iutil.execWithCapture(sys.executable, argv, root=None, fatal=True) except RuntimeError, ex: self.assertIn("return code: 3", str(ex))
def exec_with_capture_test(self): """Test execWithCapture.""" # check some output is returned self.assertGreater(len(iutil.execWithCapture("ls", ["--help"])), 0) # check no output is returned self.assertEqual(len(iutil.execWithCapture("true", [])), 0)
def exec_with_capture_test(self): """Test execWithCapture.""" # check some output is returned self.assertGreater(len(iutil.execWithCapture('ls', ['--help'])), 0) # check no output is returned self.assertEqual(len(iutil.execWithCapture('true', [])), 0)
def shutdownServer(): """Try to shutdown any running XVNC server Why is this function on the module level and not in the VncServer class ? As the server needs to be killed from the exit handler, it would have to somehow get to the VncServer instance. Like this, it can just kill it by calling a function of the vnc module. """ try: iutil.execWithCapture("killall", [XVNC_BINARY_NAME]) log.info("The XVNC server has been shut down.") except OSError as e: log.error("Shutdown of the XVNC server failed with exception:\n%s", e)
def exec_with_capture_empty_test(self): """Test execWithCapture with no output""" # check that the output is an empty string self.assertEqual( iutil.execWithCapture("/bin/sh", ["-c", "exit 0"]), "")
def lvs(vg_name): args = ["lvs", "--noheadings", "--nosuffix"] + \ ["--units", "m"] + \ ["-o", "lv_name,lv_uuid,lv_size,lv_attr"] + \ config_args + \ [vg_name] buf = iutil.execWithCapture("lvm", args, stderr="/dev/tty5") lvs = {} for line in buf.splitlines(): line = line.strip() if not line: continue (name, uuid, size, attr) = line.split() lvs[name] = {"size": size, "uuid": uuid, "attr": attr} if not lvs: raise LVMError(_("lvs failed for %s" % vg_name)) return lvs
def minSize(self): """ The minimum filesystem size in megabytes. """ if self._minInstanceSize is None: # we try one time to determine the minimum size. size = self._minSize if self.exists and os.path.exists(self.device): minSize = None buf = iutil.execWithCapture(self.resizefsProg, ["-m", self.device], stderr = "/dev/tty5") for l in buf.split("\n"): if not l.startswith("Minsize"): continue try: min = l.split(":")[1].strip() minSize = int(min) + 250 except Exception, e: minSize = None log.warning("Unable to parse output for minimum size on %s: %s" %(self.device, e)) if minSize is None: log.warning("Unable to discover minimum size of filesystem " "on %s" %(self.device,)) else: size = minSize self._minInstanceSize = size
def pvinfo(device): """ If the PV was created with '--metadacopies 0', lvm will do some scanning of devices to determine from their metadata which VG this PV belongs to. pvs -o pv_name,pv_mda_count,vg_name,vg_uuid --config \ 'devices { scan = "/dev" filter = ["a/loop0/", "r/.*/"] }' """ #cfg = "'devices { scan = \"/dev\" filter = [\"a/%s/\", \"r/.*/\"] }'" args = ["pvs", "--noheadings"] + \ ["--units", "m"] + \ ["-o", "pv_name,pv_mda_count,vg_name,vg_uuid"] + \ config_args + \ [device] rc = iutil.execWithCapture("lvm", args, stderr = "/dev/tty5") vals = rc.split() if not vals: raise LVMError("pvinfo failed for %s" % device) # don't raise an exception if pv is not a part of any vg pv_name = vals[0] try: vg_name, vg_uuid = vals[2], vals[3] except IndexError: vg_name, vg_uuid = "", "" info = {'pv_name': pv_name, 'vg_name': vg_name, 'vg_uuid': vg_uuid} return info
def pvinfo(device): """ If the PV was created with '--metadacopies 0', lvm will do some scanning of devices to determine from their metadata which VG this PV belongs to. pvs -o pv_name,pv_mda_count,vg_name,vg_uuid --config \ 'devices { scan = "/dev" filter = ["a/loop0/", "r/.*/"] }' """ #cfg = "'devices { scan = \"/dev\" filter = [\"a/%s/\", \"r/.*/\"] }'" args = ["pvs", "--noheadings"] + \ ["--units", "m"] + \ ["-o", "pv_name,pv_mda_count,vg_name,vg_uuid"] + \ config_args + \ [device] rc = iutil.execWithCapture("lvm", args, stderr="/dev/tty5") vals = rc.split() if not vals: raise LVMError("pvinfo failed for %s" % device) # don't raise an exception if pv is not a part of any vg pv_name = vals[0] try: vg_name, vg_uuid = vals[2], vals[3] except IndexError: vg_name, vg_uuid = "", "" info = {'pv_name': pv_name, 'vg_name': vg_name, 'vg_uuid': vg_uuid} return info
def minSize(self): """ The minimum filesystem size in megabytes. """ if self._minInstanceSize is None: # we try one time to determine the minimum size. size = self._minSize if self.exists and os.path.exists(self.device): minSize = None buf = iutil.execWithCapture(self.resizefsProg, ["-m", self.device], stderr="/dev/tty5") for l in buf.split("\n"): if not l.startswith("Minsize"): continue try: min = l.split(":")[1].strip() minSize = int(min) + 250 except Exception, e: minSize = None log.warning( "Unable to parse output for minimum size on %s: %s" % (self.device, e)) if minSize is None: log.warning( "Unable to discover minimum size of filesystem " "on %s" % (self.device, )) else: size = minSize self._minInstanceSize = size
def minSize(self): """ Minimum size for this filesystem in MB. """ if self._minInstanceSize is None: # try once in the beginning to get the minimum size for an # existing filesystem. size = self._minSize blockSize = None if self.exists and os.path.exists(self.device): # get block size buf = iutil.execWithCapture(self.infofsProg, ["-h", self.device], stderr="/dev/tty5") for line in buf.splitlines(): if line.startswith("Block size:"): blockSize = int(line.split(" ")[-1]) break if blockSize is None: raise FSError("failed to get block size for %s filesystem " "on %s" % (self.mountType, self.device)) # get minimum size according to resize2fs buf = iutil.execWithCapture(self.resizefsProg, ["-P", self.device], stderr="/dev/tty5") for line in buf.splitlines(): if "minimum size of the filesystem:" not in line: continue # line will look like: # Estimated minimum size of the filesystem: 1148649 # # NOTE: The minimum size reported is in blocks. Convert # to bytes, then megabytes, and finally round up. (text, sep, minSize) = line.partition(": ") size = long(minSize) * blockSize size = math.ceil(size / 1024.0 / 1024.0) break if size is None: log.warning("failed to get minimum size for %s filesystem " "on %s" % (self.mountType, self.device)) self._minInstanceSize = size return self._minInstanceSize
def modulesWithPaths(): mods = [] for modline in open("/proc/modules", "r"): modName = modline.split(" ", 1)[0] modInfo = iutil.execWithCapture("modinfo", ["-F", "filename", modName]).splitlines() modPaths = [line.strip() for line in modInfo if line != ""] mods.extend(modPaths) return mods
def exec_with_capture_no_stderr_test(self): """Test execWithCapture with no stderr""" with tempfile.NamedTemporaryFile(mode="w+t") as testscript: testscript.write( """#!/bin/sh echo "output" echo "error" >&2 """ ) testscript.flush() # check that only the output is captured self.assertEqual(iutil.execWithCapture("/bin/sh", [testscript.name], filter_stderr=True), "output\n") # check that both output and error are captured self.assertEqual(iutil.execWithCapture("/bin/sh", [testscript.name]), "output\nerror\n")
def modulesWithPaths(): mods = [] for modline in open("/proc/modules", "r"): modName = modline.split(" ", 1)[0] modInfo = iutil.execWithCapture( "modinfo", ["-F", "filename", modName]).splitlines() modPaths = [line.strip() for line in modInfo if line != ""] mods.extend(modPaths) return mods
def exec_with_capture_no_stderr_test(self): """Test execWithCapture with no stderr""" with tempfile.NamedTemporaryFile(mode="w+t") as testscript: testscript.write("""#!/bin/sh echo "output" echo "error" >&2 """) testscript.flush() # check that only the output is captured self.assertEqual( iutil.execWithCapture("/bin/sh", [testscript.name], filter_stderr=True), "output\n") # check that both output and error are captured self.assertEqual(iutil.execWithCapture("/bin/sh", [testscript.name]), "output\nerror\n")
def ifaceForHostIP(host): route = iutil.execWithCapture("ip", ["route", "get", "to", host]) if not route: log.error("Could not get interface for route to %s", host) return "" routeInfo = route.split() if routeInfo[0] != host or len(routeInfo) < 5 or "dev" not in routeInfo or routeInfo.index("dev") > 3: log.error('Unexpected "ip route get to %s" reply: %s', host, routeInfo) return "" return routeInfo[routeInfo.index("dev") + 1]
def _get_backing_devnums_from_map(map_name): ret = [] buf = iutil.execWithCapture( "dmsetup", ["info", "--columns", "--noheadings", "-o", "devnos_used", map_name], stderr="/dev/tty5") dev_nums = buf.split() for dev_num in dev_nums: (major, colon, minor) = dev_num.partition(":") ret.append((int(major), int(minor))) return ret
def writeZipl(self, instRoot, bl, kernelList, chainList, defaultDev, justConfigFile): rootDev = self.storage.rootDevice cf = '/etc/zipl.conf' self.perms = 0600 if os.access (instRoot + cf, os.R_OK): self.perms = os.stat(instRoot + cf)[0] & 0777 os.rename(instRoot + cf, instRoot + cf + '.rpmsave') f = open(instRoot + cf, "w+") f.write('[defaultboot]\n') if self.timeout: f.write('timeout=%d\n' % self.timeout) f.write('default=' + kernelList[0][0] + '\n') f.write('target=%s\n' % (self.kernelLocation)) cfPath = "/boot/" for (label, longlabel, version) in kernelList: kernelTag = "-" + version kernelFile = "%svmlinuz%s" % (cfPath, kernelTag) initrd = self.makeInitrd(kernelTag, instRoot) f.write('[%s]\n' % (label)) f.write('\timage=%s\n' % (kernelFile)) if initrd: f.write('\tramdisk=%s%s\n' %(self.kernelLocation, initrd)) realroot = rootDev.fstabSpec f.write('\tparameters="root=%s' %(realroot,)) if bl.args.get(): f.write(' %s' % (bl.args.get())) f.write('"\n') f.close() if not justConfigFile: rc = iutil.execWithCapture("zipl", [], root = instRoot, stderr = "/dev/stderr") for line in rc.splitlines(): if line.startswith("Preparing boot device: "): # Output here may look like: # Preparing boot device: dasdb (0200). # Preparing boot device: dasdl. # We want to extract the device name and pass that. fields = line[23:].split() self.setDevice(fields[0].replace('.', '')) return 0
def writeZipl(self, instRoot, bl, kernelList, chainList, defaultDev, justConfigFile): rootDev = self.storage.rootDevice cf = '/etc/zipl.conf' self.perms = 0600 if os.access(instRoot + cf, os.R_OK): self.perms = os.stat(instRoot + cf)[0] & 0777 os.rename(instRoot + cf, instRoot + cf + '.rpmsave') f = open(instRoot + cf, "w+") f.write('[defaultboot]\n') if self.timeout: f.write('timeout=%d\n' % self.timeout) f.write('default=' + kernelList[0][0] + '\n') f.write('target=%s\n' % (self.kernelLocation)) cfPath = "/boot/" for (label, longlabel, version) in kernelList: kernelTag = "-" + version kernelFile = "%svmlinuz%s" % (cfPath, kernelTag) initrd = self.makeInitrd(kernelTag, instRoot) f.write('[%s]\n' % (label)) f.write('\timage=%s\n' % (kernelFile)) if initrd: f.write('\tramdisk=%s%s\n' % (self.kernelLocation, initrd)) realroot = rootDev.fstabSpec f.write('\tparameters="root=%s' % (realroot, )) if bl.args.get(): f.write(' %s' % (bl.args.get())) f.write('"\n') f.close() if not justConfigFile: rc = iutil.execWithCapture("zipl", [], root=instRoot, stderr="/dev/stderr") for line in rc.splitlines(): if line.startswith("Preparing boot device: "): # Output here may look like: # Preparing boot device: dasdb (0200). # Preparing boot device: dasdl. # We want to extract the device name and pass that. fields = line[23:].split() self.setDevice(fields[0].replace('.', '')) return 0
def ifaceForHostIP(host): route = iutil.execWithCapture("ip", ["route", "get", "to", host]) if not route: log.error("Could not get interface for route to %s", host) return "" routeInfo = route.split() if routeInfo[0] != host or len(routeInfo) < 5 or \ "dev" not in routeInfo or routeInfo.index("dev") > 3: log.error('Unexpected "ip route get to %s" reply: %s', host, routeInfo) return "" return routeInfo[routeInfo.index("dev") + 1]
def lvorigin(vg_name, lv_name): args = ["lvs", "--noheadings", "-o", "origin"] + \ config_args + \ ["%s/%s" % (vg_name, lv_name)] buf = iutil.execWithCapture("lvm", args, stderr="/dev/tty5") try: origin = buf.splitlines()[0].strip() except IndexError: origin = '' return origin
def _startEDD(self, intf = None): rc = iutil.execWithCapture("/usr/libexec/fcoe/fcoe_edd.sh", [ "-i" ], stderr="/dev/tty5") if not rc.startswith("NIC="): log.info("No FCoE EDD info found: %s" % rc.rstrip()) return (key, val) = rc.strip().split("=", 1) if val not in isys.getDeviceProperties(): log.error("Unknown FCoE NIC found in EDD: %s, ignoring" % val) return log.info("FCoE NIC found in EDD: %s" % val) self.addSan(val, dcb=True, auto_vlan=True, intf=intf)
def _startEDD(self, intf=None): rc = iutil.execWithCapture("/usr/libexec/fcoe/fcoe_edd.sh", ["-i"], stderr="/dev/tty5") if not rc.startswith("NIC="): log.info("No FCoE EDD info found: %s" % rc.rstrip()) return (key, val) = rc.split("=", 1) if val not in isys.getDeviceProperties(): log.error("Unknown FCoE NIC found in EDD: %s, ignoring" % val) return log.info("FCoE NIC found in EDD: %s" % val) self.addSan(val, dcb=True, intf=intf)
def vginfo(vg_name): args = ["vgs", "--noheadings", "--nosuffix"] + \ ["--units", "m"] + \ ["-o", "uuid,size,free,extent_size,extent_count,free_count,pv_count"] + \ config_args + \ [vg_name] buf = iutil.execWithCapture("lvm", args, stderr="/dev/tty5") info = buf.split() if len(info) != 7: raise LVMError(_("vginfo failed for %s" % vg_name)) d = {} (d['uuid'], d['size'], d['free'], d['pe_size'], d['pe_count'], d['pe_free'], d['pv_count']) = info return d
def dm_node_from_name(map_name): dm_node = block.getDmNodeFromName(map_name) if dm_node is not None: return dm_node devnum = iutil.execWithCapture( "dmsetup", ["info", "--columns", "--noheadings", "-o", "devno", map_name], stderr="/dev/tty5") (major, sep, minor) = devnum.strip().partition(":") if not sep: raise DMError("dm device does not exist") dm_node = "dm-%d" % int(minor) log.debug("dm_node_from_name(%s) returning '%s'" % (map_name, dm_node)) return dm_node
def name_from_dm_node(dm_node): name = block.getNameFromDmNode(dm_node) if name is not None: return name st = os.stat("/dev/%s" % dm_node) major = os.major(st.st_rdev) minor = os.minor(st.st_rdev) name = iutil.execWithCapture("dmsetup", [ "info", "--columns", "--noheadings", "-o", "name", "-j", str(major), "-m", str(minor) ], stderr="/dev/tty5") log.debug("name_from_dm(%s) returning '%s'" % (dm_node, name.strip())) return name.strip()
def vginfo(vg_name): args = ["vgs", "--noheadings", "--nosuffix"] + \ ["--units", "m"] + \ ["-o", "uuid,size,free,extent_size,extent_count,free_count,pv_count"] + \ config_args + \ [vg_name] buf = iutil.execWithCapture("lvm", args, stderr="/dev/tty5") info = buf.split() if len(info) != 7: raise LVMError(_("vginfo failed for %s" % vg_name)) d = {} (d['uuid'],d['size'],d['free'],d['pe_size'], d['pe_count'],d['pe_free'],d['pv_count']) = info return d
def mdexamine(device): vars = iutil.execWithCapture("mdadm", ["--examine", "--brief", device], stderr="/dev/tty5").split() info = {} if vars: try: info["device"] = vars[1] vars = vars[2:] except IndexError: return {} for var in vars: (name, equals, value) = var.partition("=") if not equals: continue info[name.lower()] = value.strip() return info
def write(self): if self.desktop: with open(ROOT_PATH + "/etc/sysconfig/desktop", "w") as f: f.write("DESKTOP=%s\n" % self.desktop) if not os.path.isdir(ROOT_PATH + '/etc/systemd/system'): log.warning("there is no /etc/systemd/system directory, cannot update default.target!") return default_target = ROOT_PATH + '/etc/systemd/system/default.target' if os.path.islink(default_target): os.unlink(default_target) sd_prefix = iutil.execWithCapture( "pkg-config", ["--variable=prefix", "systemd"]).strip() if not sd_prefix: sd_prefix = "/usr" # assume /usr in Gentoo/Sabayon os.symlink('%s/lib/systemd/system/%s' % ( sd_prefix, RUNLEVELS[self.runlevel]), default_target)
def nmcli_dev_list_callback(): """Callback to get info about network devices.""" return iutil.execWithCapture("nmcli", ["device", "show"])
def lsblk_callback(): """Callback to get info about block devices.""" return iutil.execWithCapture("lsblk", ["--perms", "--fs", "--bytes"])
def _getExistingSize(self): """ Determine the size of this filesystem. Filesystem must exist. Each filesystem varies, but the general procedure is to run the filesystem dump or info utility and read the block size and number of blocks for the filesystem and compute megabytes from that. The loop that reads the output from the infofsProg is meant to be simple, but take in to account variations in output. The general procedure: 1) Capture output from infofsProg. 2) Iterate over each line of the output: a) Trim leading and trailing whitespace. b) Break line into fields split on ' ' c) If line begins with any of the strings in _existingSizeFields, start at the end of fields and take the first one that converts to a long. Store this in the values list. d) Repeat until the values list length equals the _existingSizeFields length. 3) If the length of the values list equals the length of _existingSizeFields, compute the size of this filesystem by multiplying all of the values together to get bytes, then convert to megabytes. Return this value. 4) If we were unable to capture all fields, return 0. The caller should catch exceptions from this method. Any exception raised indicates a need to change the fields we are looking for, the command to run and arguments, or something else. If you catch an exception from this method, assume the filesystem cannot be resized. """ size = self._size if self.infofsProg and self.mountable and self.exists and not size: try: values = [] argv = self._defaultInfoOptions + [ self.device ] buf = iutil.execWithCapture(self.infofsProg, argv, stderr="/dev/tty5") for line in buf.splitlines(): found = False line = line.strip() tmp = line.split(' ') tmp.reverse() for field in self._existingSizeFields: if line.startswith(field): for subfield in tmp: try: values.append(long(subfield)) found = True break except ValueError: continue if found: break if len(values) == len(self._existingSizeFields): break if len(values) != len(self._existingSizeFields): return 0 size = 1 for value in values: size *= value # report current size as megabytes size = math.floor(size / 1024.0 / 1024.0) except Exception as e: log.error("failed to obtain size of filesystem on %s: %s" % (self.device, e)) return size
def _getRandomUUID(self): uuid = iutil.execWithCapture("uuidgen", []).strip() return uuid
def identifyMultipaths(devices): # this function does a couple of things # 1) identifies multipath disks # 2) sets their ID_FS_TYPE to multipath_member # 3) removes the individual members of an mpath's partitions # sample input with multipath pair [sdb,sdc] # [sr0, sda, sda1, sdb, sdb1, sdb2, sdc, sdc1, sdd, sdd1, sdd2] # sample output: # [sda, sdd], [[sdb, sdc]], [sr0, sda1, sdd1, sdd2]] log.info("devices to scan for multipath: %s" % [d['name'] for d in devices]) topology = parseMultipathOutput(iutil.execWithCapture("multipath", ["-d",])) # find the devices that aren't in topology, and add them into it... topodevs = reduce(lambda x,y: x.union(y), topology.values(), set()) for name in set([d['name'] for d in devices]).difference(topodevs): topology[name] = [name] devmap = {} non_disk_devices = {} for d in devices: if not udev_device_is_disk(d): non_disk_devices[d['name']] = d log.info("adding %s to non_disk_device list" % (d['name'],)) continue devmap[d['name']] = d singlepath_disks = [] multipaths = [] for name, disks in topology.items(): if len(disks) == 1: if not non_disk_devices.has_key(disks[0]): log.info("adding %s to singlepath_disks" % (disks[0],)) singlepath_disks.append(devmap[disks[0]]) else: # some usb cardreaders use multiple lun's (for different slots) # and report a fake disk serial which is the same for all the # lun's (#517603) all_usb = True # see if we've got any non-disk devices on our mpath list. # If so, they're probably false-positives. non_disks = False for disk in disks: d = devmap[disk] if d.get("ID_USB_DRIVER") != "usb-storage": all_usb = False if (not devmap.has_key(disk)) and non_disk_devices.has_key(disk): log.warning("non-disk device %s is part of an mpath" % (disk,)) non_disks = True if all_usb: log.info("adding multi lun usb mass storage device to singlepath_disks: %s" % (disks,)) singlepath_disks.extend([devmap[d] for d in disks]) continue if non_disks: for disk in disks: if devmap.has_key(disk): del devmap[disk] if topology.has_key(disk): del topology[disk] continue log.info("found multipath set: %s" % (disks,)) for disk in disks: d = devmap[disk] log.info("adding %s to multipath_disks" % (disk,)) d["ID_FS_TYPE"] = "multipath_member" d["ID_MPATH_NAME"] = name multipaths.append([devmap[d] for d in disks]) non_disk_serials = {} for name,device in non_disk_devices.items(): serial = udev_device_get_serial(device) non_disk_serials.setdefault(serial, []) non_disk_serials[serial].append(device) for mpath in multipaths: for serial in [d.get('ID_SERIAL_SHORT') for d in mpath]: if non_disk_serials.has_key(serial): log.info("filtering out non disk devices [%s]" % [d['name'] for d in non_disk_serials[serial]]) for name in [d['name'] for d in non_disk_serials[serial]]: if non_disk_devices.has_key(name): del non_disk_devices[name] partition_devices = [] for device in non_disk_devices.values(): partition_devices.append(device) # this is the list of devices we want to keep from the original # device list, but we want to maintain its original order. singlepath_disks = filter(lambda d: d in devices, singlepath_disks) #multipaths = filter(lambda d: d in devices, multipaths) partition_devices = filter(lambda d: d in devices, partition_devices) mpathStr = "[" for mpath in multipaths: mpathStr += str([d['name'] for d in mpath]) mpathStr += "]" s = "(%s, %s, %s)" % ([d['name'] for d in singlepath_disks], \ mpathStr, \ [d['name'] for d in partition_devices]) log.info("devices post multipath scan: %s" % s) return (singlepath_disks, multipaths, partition_devices)
def _getExistingSize(self): """ Determine the size of this filesystem. Filesystem must exist. Each filesystem varies, but the general procedure is to run the filesystem dump or info utility and read the block size and number of blocks for the filesystem and compute megabytes from that. The loop that reads the output from the infofsProg is meant to be simple, but take in to account variations in output. The general procedure: 1) Capture output from infofsProg. 2) Iterate over each line of the output: a) Trim leading and trailing whitespace. b) Break line into fields split on ' ' c) If line begins with any of the strings in _existingSizeFields, start at the end of fields and take the first one that converts to a long. Store this in the values list. d) Repeat until the values list length equals the _existingSizeFields length. 3) If the length of the values list equals the length of _existingSizeFields, compute the size of this filesystem by multiplying all of the values together to get bytes, then convert to megabytes. Return this value. 4) If we were unable to capture all fields, return 0. The caller should catch exceptions from this method. Any exception raised indicates a need to change the fields we are looking for, the command to run and arguments, or something else. If you catch an exception from this method, assume the filesystem cannot be resized. """ size = self._size if self.infofsProg and self.mountable and self.exists and not size: try: values = [] argv = self._defaultInfoOptions + [self.device] buf = iutil.execWithCapture(self.infofsProg, argv, stderr="/dev/tty5") for line in buf.splitlines(): found = False line = line.strip() tmp = line.split(' ') tmp.reverse() for field in self._existingSizeFields: if line.startswith(field): for subfield in tmp: try: values.append(long(subfield)) found = True break except ValueError: continue if found: break if len(values) == len(self._existingSizeFields): break if len(values) != len(self._existingSizeFields): return 0 size = 1 for value in values: size *= value # report current size as megabytes size = math.floor(size / 1024.0 / 1024.0) except Exception as e: log.error("failed to obtain size of filesystem on %s: %s" % (self.device, e)) return size
def startup(self, intf, exclusiveDisks, zeroMbr): """ Look for any unformatted DASDs in the system and offer the user the option for format them with dasdfmt or exit the installer. """ if self.started: return self.started = True out = "/dev/tty5" err = "/dev/tty5" if not iutil.isS390(): return log.info("Checking for unformatted DASD devices:") for device in os.listdir("/sys/block"): if not device.startswith("dasd"): continue statusfile = "/sys/block/%s/device/status" % (device, ) if not os.path.isfile(statusfile): continue f = open(statusfile, "r") status = f.read().strip() f.close() if status in ["unformatted"] and device not in exclusiveDisks: bypath = deviceNameToDiskByPath(device) if not bypath: bypath = "/dev/" + device log.info(" %s (%s) status is %s, needs dasdfmt" % ( device, bypath, status, )) self._dasdlist.append((device, bypath)) if not len(self._dasdlist): log.info(" no unformatted DASD devices found") return askUser = True if zeroMbr: askUser = False elif not intf and not zeroMbr: log.info(" non-interactive kickstart install without zerombr " "command, unable to run dasdfmt, exiting installer") sys.exit(0) c = len(self._dasdlist) if intf and askUser: devs = '' for dasd, bypath in self._dasdlist: devs += "%s\n" % (bypath, ) rc = intf.questionInitializeDASD(c, devs) if rc == 1: log.info(" not running dasdfmt, continuing installation") return # gather total cylinder count argv = ["-t", "-v"] + self.commonArgv for dasd, bypath in self._dasdlist: buf = iutil.execWithCapture(self.dasdfmt, argv + ["/dev/" + dasd], stderr=err) for line in buf.splitlines(): if line.startswith("Drive Geometry: "): # line will look like this: # Drive Geometry: 3339 Cylinders * 15 Heads = 50085 Tracks cyls = long(filter(lambda s: s, line.split(' '))[2]) self.totalCylinders += cyls break # format DASDs argv = ["-P"] + self.commonArgv update = self._updateProgressWindow title = P_("Formatting DASD Device", "Formatting DASD Devices", c) msg = P_("Preparing %d DASD device for use with Linux..." % c, "Preparing %d DASD devices for use with Linux..." % c, c) if intf: if self.totalCylinders: pw = intf.progressWindow(title, msg, 1.0) else: pw = intf.progressWindow(title, msg, 100, pulse=True) for dasd, bypath in self._dasdlist: log.info("Running dasdfmt on %s" % (bypath, )) arglist = argv + ["/dev/" + dasd] try: if intf and self.totalCylinders: ret = iutil.execWithCallback(self.dasdfmt, arglist, stdout=out, stderr=err, callback=update, callback_data=pw, echo=False) rc = ret.rc elif intf: ret = iutil.execWithPulseProgress(self.dasdfmt, arglist, stdout=out, stderr=err, progress=pw) rc = ret.rc else: rc = iutil.execWithRedirect(self.dasdfmt, arglist, stdout=out, stderr=err) except Exception as e: raise DasdFormatError(e, bypath) if rc: raise DasdFormatError("dasdfmt failed: %s" % rc, bypath) if intf: pw.pop()
def startup(self, intf, exclusiveDisks, zeroMbr): """ Look for any unformatted DASDs in the system and offer the user the option for format them with dasdfmt or exit the installer. """ if self.started: return self.started = True out = "/dev/tty5" err = "/dev/tty5" if not iutil.isS390(): return log.info("Checking for unformatted DASD devices:") for device in os.listdir("/sys/block"): if not device.startswith("dasd"): continue statusfile = "/sys/block/%s/device/status" % (device,) if not os.path.isfile(statusfile): continue f = open(statusfile, "r") status = f.read().strip() f.close() if status in ["unformatted"] and device not in exclusiveDisks: bypath = deviceNameToDiskByPath(device) if not bypath: bypath = "/dev/" + device log.info(" %s (%s) status is %s, needs dasdfmt" % (device, bypath, status,)) self._dasdlist.append((device, bypath)) if not len(self._dasdlist): log.info(" no unformatted DASD devices found") return askUser = True if zeroMbr: askUser = False elif not intf and not zeroMbr: log.info(" non-interactive kickstart install without zerombr " "command, unable to run dasdfmt, exiting installer") sys.exit(0) c = len(self._dasdlist) if intf and askUser: devs = '' for dasd, bypath in self._dasdlist: devs += "%s\n" % (bypath,) rc = intf.questionInitializeDASD(c, devs) if rc == 1: log.info(" not running dasdfmt, continuing installation") return # gather total cylinder count argv = ["-t", "-v"] + self.commonArgv for dasd, bypath in self._dasdlist: buf = iutil.execWithCapture(self.dasdfmt, argv + ["/dev/" + dasd], stderr=err) for line in buf.splitlines(): if line.startswith("Drive Geometry: "): # line will look like this: # Drive Geometry: 3339 Cylinders * 15 Heads = 50085 Tracks cyls = long(filter(lambda s: s, line.split(' '))[2]) self.totalCylinders += cyls break # format DASDs argv = ["-P"] + self.commonArgv update = self._updateProgressWindow title = P_("Formatting DASD Device", "Formatting DASD Devices", c) msg = P_("Preparing %d DASD device for use with Linux..." % c, "Preparing %d DASD devices for use with Linux..." % c, c) if intf: if self.totalCylinders: pw = intf.progressWindow(title, msg, 1.0) else: pw = intf.progressWindow(title, msg, 100, pulse=True) for dasd, bypath in self._dasdlist: log.info("Running dasdfmt on %s" % (bypath,)) arglist = argv + ["/dev/" + dasd] try: if intf and self.totalCylinders: ret = iutil.execWithCallback(self.dasdfmt, arglist, stdout=out, stderr=err, callback=update, callback_data=pw, echo=False) rc = ret.rc elif intf: ret = iutil.execWithPulseProgress(self.dasdfmt, arglist, stdout=out, stderr=err, progress=pw) rc = ret.rc else: rc = iutil.execWithRedirect(self.dasdfmt, arglist, stdout=out, stderr=err) except Exception as e: raise DasdFormatError(e, bypath) if rc: raise DasdFormatError("dasdfmt failed: %s" % rc, bypath) if intf: pw.pop()
def flush_mpaths(): iutil.execWithRedirect("multipath", ["-F"]) check_output = iutil.execWithCapture("multipath", ["-ll"]).strip() if check_output: log.error("multipath: some devices could not be flushed")