def _systemctl(*args): cmd = [_SYSTEMCTL.cmd] cmd.extend(args) rc, out, err = commands.execCmd(cmd, raw=True) if rc != 0: raise cmdutils.Error(cmd=cmd, rc=rc, out=out, err=err) return out
def sparsify(src_vol, tmp_vol, dst_vol, src_format=None, dst_format=None): """ Sparsify the 'src_vol' volume (src_format) to 'dst_vol' volume (dst_format) using libguestfs virt-sparsify src_vol: path of base volume tmp_vol: path of temporary volume created with src_vol as backing volume dst_vol: path of destination volume src_format: format of base volume ('raw' or `qcow2') src_format: format of destination volume ('raw' or `qcow2') """ cmd = [_VIRTSPARSIFY.cmd, '--tmp', 'prebuilt:' + tmp_vol] if src_format: cmd.extend(("--format", src_format)) if dst_format: cmd.extend(("--convert", dst_format)) cmd.extend((src_vol, dst_vol)) rc, out, err = commands.execCmd(cmd) if rc != 0: raise cmdutils.Error(cmd, rc, out, err)
def _multipath_status(): cmd = [EXT_DMSETUP, "status", "--target", "multipath"] rc, out, err = misc.execCmd(cmd, raw=True) if rc != 0: raise cmdutils.Error(cmd, rc, out, err) res = {} lines = out.decode("utf-8").splitlines() for line in lines: try: guid, paths = line.split(":", 1) except ValueError: # TODO check if this output is relevant if len(lines) != 1: raise # return an empty dict when status output is: No devices found return res statuses = [] for m in PATH_STATUS_RE.finditer(paths): major_minor, status = m.groups() name = device_name(major_minor) statuses.append(PathStatus(name, status)) res[guid] = statuses return res
def resize_map(name): """ Invoke multipathd to resize a device Must run as root Raises Error if multipathd failed to resize the map. """ if os.geteuid() != 0: return supervdsm.getProxy().multipath_resize_map(name) log.debug("Resizing map %r", name) cmd = [_MULTIPATHD.cmd, "resize", "map", name] with utils.stopwatch("Resized map %r" % name, log=log): p = commands.start(cmd, sudo=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = commands.communicate(p) out = out.decode("utf-8") err = err.decode("utf-8") # multipathd reports some errors using non-zero exit code and # stderr (need to be root), but the command may return 0, and # the result is reported using stdout. if p.returncode != 0 or out != "ok\n": e = cmdutils.Error(cmd, p.returncode, out, err) raise Error("Resizing map {!r} failed: {}".format(name, e))
def attach(self): if self._path is not None: raise AssertionError("Device is attached: %s" % self) cmd = ["losetup", "--find", "--show", self._backing_file] rc, out, err = commands.execCmd(cmd, raw=True) if rc != 0: raise cmdutils.Error(cmd, rc, out, err) self._path = out.strip().decode("ascii")
def _run_command(args): cmd = [_SYSCTL.cmd] cmd.extend(args) rc, out, err = commands.execCmd(cmd, raw=True) if rc != 0: raise cmdutils.Error(cmd, rc, out, err) return out
def verify_pattern(path, format, offset=512, len=1024, pattern=5): read_cmd = 'read -P %d -s 0 -l %d %d %d' % (pattern, len, offset, len) cmd = ['qemu-io', '-f', format, '-c', read_cmd, path] rc, out, err = commands.execCmd(cmd, raw=True) if rc != 0 or err != b"": raise cmdutils.Error(cmd, rc, out, err) if b"Pattern verification failed" in out: raise VerificationError( "Verification of volume %s failed. Pattern 0x%x not found at " "offset %s" % (path, pattern, offset))
def _run(self, args, data=None): rc, out, err = commands.execCmd( args, data=data, raw=True, # We do tiny io, no need to run this on another CPU. resetCpuAffinity=False) if rc != 0: # Do not spam the log with received binary data raise cmdutils.Error(args, rc, "[suppressed]", err) return out
def verify_pattern(path, format, offset=512, len=1024, pattern=5): read_cmd = 'read -P %d -s 0 -l %d %d %d' % (pattern, len, offset, len) cmd = ['qemu-io', '-f', format, '-c', read_cmd, path] rc, out, err = commands.execCmd(cmd, raw=True) # Older qemu-io (2.10) used to exit with zero exit code and "Pattern # verification" error in stdout. In 2.12, non-zero code is returned when # pattern verification fails. if b"Pattern verification failed" in out: raise VerificationError( "Verification of volume %s failed. Pattern 0x%x not found at " "offset %s" % (path, pattern, offset)) if rc != 0 or err != b"": raise cmdutils.Error(cmd, rc, out, err)
def sparsify_inplace(vol_path): """ Sparsify the volume in place (without copying from an input disk to an output disk) :param vol_path: path to the volume """ cmd = [_VIRTSPARSIFY.cmd, '--machine-readable', '--in-place', vol_path] rc, out, err = commands.execCmd(cmd) if rc != 0: raise cmdutils.Error(cmd, rc, out, err)
def sysprep(vol_paths): """ Run virt-sysprep on the list of volumes :param vol_paths: list of volume paths """ cmd = [_VIRTSYSPREP.cmd] for vol_path in vol_paths: cmd.extend(('-a', vol_path)) rc, out, err = commands.execCmd(cmd) if rc != 0: raise cmdutils.Error(cmd, rc, out, err)
def discard(device): """ Discards a block device. Arguments: device (str): The path to the block device to discard. Raises: cmdutils.Error if an error has occurred in blkdiscard. """ cmd = [_blkdiscard.cmd] cmd.append(device) rc, out, err = commands.execCmd(cmd) if rc != 0: raise cmdutils.Error(cmd, rc, out, err)
def _run_check(): """ Check the devices file. As, according to LVM developers, the behavior of this functionality is not entirely or strictly well defined yet, we don't raise any exception if the check finds issues in devices file, but only log a waring with found issues. """ cmd = [constants.EXT_LVM, 'lvmdevices', "--check"] p = commands.start(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = commands.communicate(p) if p.returncode == 0 and err: log.warning("Found following issues in LVM devices file: %s", err) if p.returncode != 0: raise cmdutils.Error(cmd, p.returncode, out, err)
def get(pid): """ Get the affinity of a process, by its <pid>, using taskset command. We assume all threads of the process have the same affinity, because this is the only usecase VDSM cares about - and requires. Return a frozenset of ints, each one being a cpu indices on which the process can run. Example: frozenset([0, 1, 2, 3]) Raise cmdutils.Error on failure. """ command = [constants.EXT_TASKSET, '--pid', str(pid)] rc, out, err = commands.execCmd(command, resetCpuAffinity=False) if rc != 0: raise cmdutils.Error(command, rc, out, err) return _cpu_set_from_output(out[-1])
def _run_vgimportdevices(vg): """ Import underlying devices of provided VG into LVM devices file. Import is done using vgimportdevices command. vgimportdevices takes into account existing lvm filter, so if some devices are excluded by the filter, such devices won't be imported. If the filter is wrong, we may miss some devices. To avoid such situation, set the filter to enable all the devices. """ cmd = [ constants.EXT_LVM, 'vgimportdevices', vg, '--config', 'devices { use_devicesfile = 1 filter = ["a|.*|"] }' ] p = commands.start(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = commands.communicate(p) if p.returncode == 0 and err: log.warning("Command %s succeeded with warnings: %s", cmd, err) if p.returncode != 0: raise cmdutils.Error(cmd, p.returncode, out, err)
def set(pid, cpu_set, all_tasks=False): """ Set the affinity of a process, by its <pid>, using taskset command. if all_tasks evaluates to True, set the affinity for all threads of the target process. <cpu_set> must be an iterable whose items are ints which represent cpu indices, on which the process will be allowed to run; the format is the same as what the get() function returns. Raise cmdutils.Error on failure. """ command = [constants.EXT_TASKSET] if all_tasks: command.append("--all-tasks") command.extend( ('--pid', '--cpu-list', ','.join(str(i) for i in cpu_set), str(pid))) rc, out, err = commands.execCmd(command, resetCpuAffinity=False) if rc != 0: raise cmdutils.Error(command, rc, out, err)
def detach(self): if self._path is None: raise AssertionError("Device is detached: %s" % self) cmd = ["losetup", "--detach", self._path] rc, out, err = commands.execCmd(cmd, raw=True) if rc != 0: raise cmdutils.Error(cmd, rc, out, err) self._path = None # After deactivating lvs backed by loop device, we get tons of udev # events. We must wait for the events or we may get stale lvs that # would fail the next tests. # # $ udevadm monitor -u # ... # UDEV [314195.642497] remove /devices/virtual/block/dm-4 (block) # UDEV [314195.643032] remove /devices/virtual/block/dm-4 (block) # UDEV [314195.653214] remove /devices/virtual/bdi/253:4 (bdi) # UDEV [314195.664478] remove /devices/virtual/block/dm-5 (block) # UDEV [314195.664863] remove /devices/virtual/block/dm-5 (block) # UDEV [314195.674426] remove /devices/virtual/bdi/253:5 (bdi) # UDEV [314195.807277] change /devices/virtual/block/loop0 (block) udevadm.settle(5)
def _finalize(self, out, err): """ Update operation state after underlying process has terminated. Raises: `exception.ActionStopped` if the command was aborted `cmdutils.Error` if the command failed `RuntimeError` if operation state is invalid """ rc = self._proc.returncode log.debug(cmdutils.retcode_log_line(rc, err)) with self._lock: self._proc = None if self._state == ABORTING: self._state = ABORTED raise exception.ActionStopped elif self._state == RUNNING: self._state = TERMINATED if rc != 0: raise cmdutils.Error(self._cmd, rc, out, err) else: raise RuntimeError("Invalid state: %s" % self)
def _run_cmd(cmd, cwd=None): rc, out, err = commands.execCmd(cmd, raw=True, cwd=cwd) if rc != 0: raise cmdutils.Error(cmd, rc, out, err) return out
def test_format(self): # Should not raise str(cmdutils.Error(["cmd"], 1, "out\n", "err\n"))
def qemuimg_failure(*args, **kwargs): raise cmdutils.Error("code", "out", "err", "qemuimg failure")
def failure(*args, **kwargs): raise cmdutils.Error("code", "out", "err", "Fail amend")
def write_pattern(path, format, offset=512, len=1024, pattern=5): write_cmd = 'write -P %d %d %d' % (pattern, offset, len) cmd = ['qemu-io', '-f', format, '-c', write_cmd, path] rc, out, err = commands.execCmd(cmd, raw=True) if rc != 0: raise cmdutils.Error(cmd, rc, out, err)
def run(args, input=None, cwd=None, env=None, sudo=False, setsid=False, nice=None, ioclass=None, ioclassdata=None, reset_cpu_affinity=True): """ Starts a command communicate with it, and wait until the command terminates. Ensures that the command is killed if an unexpected error is raised. args are logged when command starts, and are included in the exception if a command has failed. If args contain sensitive information that should not be logged, such as passwords, they must be wrapped with ProtectedPassword. The child process stdout and stderr are always buffered. If you have special needs, such as running the command without buffering stdout, or create a pipeline of several commands, use the lower level start() function. Arguments: args (list): Command arguments input (bytes): Data to send to the command via stdin. cwd (str): working directory for the child process env (dict): environment of the new child process sudo (bool): if set to True, run the command via sudo nice (int): if not None, run the command via nice command with the specified nice value ioclass (int): if not None, run the command with the ionice command using specified ioclass value. ioclassdata (int): if ioclass is set, the scheduling class data. 0-7 are valid data (priority levels). reset_cpu_affinity (bool): Run the command via the taskset command, allowing the child process to run on all cpus (default True). Returns: The command output (bytes) Raises: OSError if the command could not start. cmdutils.Error if the command terminated with a non-zero exit code. utils.TerminatingFailure if command could not be terminated. """ p = start(args, stdin=subprocess.PIPE if input else None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd, env=env, sudo=sudo, setsid=setsid, nice=nice, ioclass=ioclass, ioclassdata=ioclassdata, reset_cpu_affinity=reset_cpu_affinity) with terminating(p): out, err = p.communicate(input) log.debug(cmdutils.retcode_log_line(p.returncode, err)) if p.returncode != 0: raise cmdutils.Error(args, p.returncode, out, err) return out
def failure(*args, **kwargs): raise cmdutils.Error("code", "out", "err", "Fail bitmap operation")