Пример #1
0
def _systemctl_cmd_target(cmd, target):
    """
    Run a systemctl cmd on a target.  Returns True/False.
    """
    retries = 5
    delay = 2

    # TODO: warn that target is null?
    if not target:
        return False

    cmd = "systemctl {} {}".format(cmd, target)

    # Try a _few_ times, with a small sleep.
    _rc, _stdout, _stderr = _run(cmd)
    while retries and _rc != 0:
        _rc, _stdout, _stderr = _run(cmd)
        retries -= 1
        time.sleep(delay)

    if _rc != 0:
        log.error("Failed to {} target {}.".format(cmd, target))
        return False

    return True
Пример #2
0
def _rchattr(op, path, attrs, rec, omit, rets):
    """
    Yet another helper for the whole chattr story.  Recursively applies op and
    attrs to paths which are not present in the omit list.

    Returns a dictionary of { path: True/False, ... } entries representing the
    succesful/not successful application of op and attrs.
    """
    # Basic non recursive case.  Set attrs for a given path, if it's not in the omit list.
    if not rec:
        if path not in omit:
            cmd = "chattr {} {}{} {}".format(
                '-d' if os.path.isdir(path) else '', op, attrs, path)
            _rc, _stdout, _stderr = _run(cmd)
            rets[path] = _rc == 0
            return _rc == 0
        else:
            log.warn(("Refusing to apply '{}' attrs to '{}' which is also in"
                      "the omit list {}.".format(attrs, path, omit)))
            rets[path] = False
            return False
    # The fun case.
    else:
        # If our path is a directory, compute it's contents in an absolute form.
        if os.path.isdir(path):
            path_contents = ["{}/{}".format(path, e) for e in os.listdir(path)]
            # Leaf directory with no contents, and not to be omitted.
            if not path_contents and path not in omit:
                dir_opt = '-d' if os.path.isdir(path) else ''
                cmd = "chattr {} {}{} {}".format(dir_opt, op, attrs, path)
                _rc, _stdout, _stderr = _run(cmd)
                rets[path] = _rc == 0
            # There are paths present in path_contents, process those.
            else:
                # For each path that is not in the omit list, recurse.
                for _pathname in path_contents:
                    if _pathname not in omit:
                        _rchattr(op, _pathname, attrs, rec, omit, rets)
                # Now process our non-leaf directory.
                # TODO: I have a feeling we should check this after the isdir()
                # and not process it or it's children.
                if path not in omit:
                    # Finally add the path
                    dir_opt = '-d' if os.path.isdir(path) else ''
                    cmd = "chattr {} {}{} {}".format(dir_opt, op, attrs, path)
                    _rc, _stdout, _stderr = _run(cmd)
                    rets[path] = _rc == 0
        # Path is a file.
        else:
            if path not in omit:
                dir_opt = '-d' if os.path.isdir(path) else ''
                cmd = "chattr {} {}{} {}".format(dir_opt, op, attrs, path)
                _rc, _stdout, _stderr = _run(cmd)
                rets[path] = _rc == 0
Пример #3
0
def btrfs_subvol_exists(subvol='', **kwargs):
    """
    Determine if subvol, of the form @/foo/bar exists as a btrfs subvolume.  The
    subvolume need not be mounted.

    Returns True/False.  Returns False for empty subvolumes.
    """
    if not subvol:
        return False

    # If the subvol is mounted somewhere, it obviously exists.
    if btrfs_get_mountpoints_of_subvol(subvol):
        return True

    # If it isn't mounted, we have no idea the mountpoint to use in the below
    # list, so just default to /
    cmd = "btrfs subvolume list /"
    _rc, _stdout, _stderr = _run(cmd)

    if _rc == 0 and _stdout:
        subvols = _stdout.split('\n')
        for subvol in subvols:
            if subvol.endswith("path {}".format(subvol)):
                return True

    # Haven't found it.
    return False
Пример #4
0
def _mount_osd(osd_dev, osd_mountpoint):
    """
    Activate the OSD defined by osd_dev.  Returns True/False
    """
    _rc = 0
    if get_mountpoint(osd_mountpoint) != osd_mountpoint:
        cmd = "mount {} {}".format(osd_dev, osd_mountpoint)
        _rc, _stdout, _stderr = _run(cmd)

    return _rc == 0
Пример #5
0
def _unmount_osd(osd_mountpoint):
    """
    Unmount the OSD defined by osd_mountpoint.  Returns True/False.
    """
    _rc = 0
    if get_mountpoint(osd_mountpoint) == osd_mountpoint:
        cmd = "umount {}".format(osd_mountpoint)
        _rc, _stdout, _stderr = _run(cmd)

    return _rc == 0
Пример #6
0
def ping_cmd(host):
    '''
    Ping a host with 1 packet and return the result

    CLI Example:
    .. code-block:: bash
        sudo salt 'node' multi.ping_cmd <hostname>|<ip>
    '''
    cmd = ["/usr/bin/ping", "-c1", "-q", "-W1", host]
    retcode, stdout, stderr = _run(cmd)
    return host, retcode, stdout, stderr
Пример #7
0
def users(realm='default', contains=None):
    """
    Return the list of users for a realm.
    """
    cmd = "radosgw-admin user list --rgw-realm={}".format(realm)
    retcode, stdout, _ = _run(cmd)
    if retcode != '0':
        if contains:
            return [item for item in json.loads(stdout) if contains in item]
        return json.loads(stdout)
    return []
Пример #8
0
def jumbo_ping_cmd(host):
    '''
    Ping a host with 1 packet and return the result

    CLI Example:
    .. code-block:: bash
        sudo salt 'node' multi.ping_cmd <hostname>|<ip>
    '''
    cmd = ["/usr/bin/ping", "-Mdo", "-s8972", "-c1", "-q", "-W1", host]
    log.debug('ping_cmd hostname={}'.format(host))
    retcode, stdout, stderr = _run(cmd)
    return host, retcode, stdout, stderr
Пример #9
0
def btrfs_get_default_subvol(path='', **kwargs):
    """
    Returns the default subvolume (in the form @/foo/bar) of a given path or None on error.
    """
    cmd = "btrfs subvolume get-default {}".format(path)
    _rc, _stdout, _stderr = _run(cmd)

    if _rc == 0 and _stdout:
        # _stdout example: ID 259 gen 35248 top level 258 path @/.snapshots/1/snapshot
        # Return only the subvol
        return _stdout.split()[-1]

    return None
Пример #10
0
def _mv_contents(path, new_path):
    """
    Try to move the contents of path to tmp_path.  Return True/False.

    NOTE: Invoking `mv` as shutil.move() was not preserving ownership metadata.
    """
    for entry in os.listdir(path):
        cmd = "mv {}/{} {}".format(path, entry, new_path)
        _rc, _stdout, _stderr = _run(cmd)
        if _rc != 0:
            return False

    return True
Пример #11
0
def _kernel_pkg():
    """
    Return the package of the running kernel
    """
    kernel = open('/proc/cmdline').read()
    log.debug("/proc/cmdline: {}".format(kernel))

    query = _query_command(_boot_image(kernel))
    if query:
        log.debug("query: {}".format(query))
        _, stdout, _ = _run(query)
        package = stdout

        log.info("package: {}".format(package))
        return package
    return
Пример #12
0
def get_uuid(dev_path='', **kwargs):
    """
    Determine the UUID of a given dev_path (ie. /dev/sdb2).

    Returns the UUID of dev, or None on error.

    NOTE: Simplified form of original found in osd.py
    """
    pathname = "/dev/disk/by-uuid"

    cmd = "find -L {} -samefile {}".format(pathname, dev_path)
    _rc, _stdout, _stderr = _run(cmd)

    if _rc == 0 and _stdout:
        return os.path.basename(_stdout)
    else:
        log.error("Failed to determine uuid of '{}'.".format(dev_path))
        return None
Пример #13
0
def iperf_client_cmd(server, cpu=0, port=5200):
    '''
    Use iperf to test minion to server

    CLI Example:
    .. code-block:: bash
    salt 'node' multi.iperf_client_cmd <server_name/ip>
            cpu=<which_cpu_core default 0> port=<default 5200>
    '''
    if IPERF_PATH is None or not server:
        if not server:
            return [LOCALHOST_NAME, 2, "0", "Server name is empty"]
        else:
            return [
                LOCALHOST_NAME, 2, "0",
                "iperf3 not found in path, please install"
            ]
    iperf_cmd = [
        "/usr/bin/iperf3", "-fm", "-A" + str(cpu), "-t10", "-c" + server,
        "-p" + str(port)
    ]
    log.debug('iperf_client_cmd: cmd {}'.format(iperf_cmd))
    retcode, stdout, stderr = _run(iperf_cmd)
    return server, retcode, stdout, stderr
Пример #14
0
def get_attrs(path='', **kwargs):
    """
    Obtains the raw output of `lsattr` on a given path.

    Returns the attrs string after having stripped off the path, or None on error
    or if path is empty.  If path is a directory, it does not recursively follow
    all child paths.

    # TODO: Any use in adding a recursive flag and dumping output into a list?
    """
    # TODO: Should we warn if the path doesn't exist, or quietly return None?
    if not os.path.exists(path):
        return None

    cmd = ("lsattr -d {}".format(path)
           if os.path.isdir(path) else "lsattr {}".format(path))
    _rc, _stdout, _stderr = _run(cmd)

    if _rc == 0 and _stdout:
        return _stdout.split()[0]
    else:
        log.error("Failed to determine attrs for '{}': stderr: '{}'".format(
            path, _stderr))
        return None
Пример #15
0
def btrfs_mount_subvol(subvol='', path='', **kwargs):
    """
    Given a subvolume in the form "@/path/to/subvol", mount it atop of path.  If
    path does not exist, log an error and abort.  If path is already a mountpoint
    for for subvol, skip.  If path is a mountpoint for something other than path,
    abort.  Refuse to mount a subvol with a differing path (ie. refuse to mount
    @/var/lib/foo atop of /var/lib/bar).

    CAUTION: No checks are performed whether path contains existing data!
    NOTE: Does not touch /etc/fstab, for that, _add_fstab_entry().

    Returns True/False.
    """
    if not subvol or not path:
        log.error("Unable to mount subvolume '{}' onto '{}'.".format(
            subvol, path))
        return False

    # Grab the mount info for path.
    mount_info = get_mount_info(path)
    if not mount_info:
        log.error(("Unable to mount subvolume '{}' onto '{}': no mount "
                   "information obtained.".format(subvol, path)))
        return False

    # Grab device info to confirm this is a btrfs filesystem.
    dev_info = get_device_info(mount_info['mountpoint'])
    if not dev_info:
        log.error(("Unable to mount subvolume '{}' onto '{}': no filesystem "
                   "information obtained.".format(subvol, path)))
        return False
    if dev_info['fstype'] != 'btrfs':
        log.error(
            "Unable to mount subvolume '{}' onto '{}': invalid filesystem type ({})."
            .format(subvol, path, dev_info['fstype']))
        return False

    # Subvol should exist!
    if not btrfs_subvol_exists(subvol):
        log.error(("Unable to mount subvolume '{}' onto '{}': '{}' does not "
                   "exist.".format(subvol, path, subvol)))
        return False

    # Path should exist!
    if not os.path.exists(path):
        log.error(("Unable to mount subvolume '{}' onto '{}': '{}' does not "
                   "exist.".format(subvol, path, path)))
        return False

    # Begin mounting process.

    # If path == mountpoint, then we already have a subvolume mounted on this path.
    if path == mount_info['mountpoint']:
        # our path is a mountpoint, run some basic checks
        if path in btrfs_get_mountpoints_of_subvol(subvol):
            log.warn(("Subvolume '{}' is already mounted onto "
                      "'{}'.".format(subvol, path)))
            return True
        else:
            # Another subvolume is mounted on path, output which
            log.error(("Unable to mount subvolume '{}' onto '{}': a different "
                       "subvolume ({}) is already "
                       "mounted.".format(
                           subvol, path,
                           _get_mount_opt('subvol', mount_info['opts']))))
            return False
    else:
        # TODO: Should we prevent the same subvolume being mounted on multiple
        # different directories?  btrfs is happy to mount the same subvolume
        # onto multiple directories, so let's not limit  this behaviour.  If
        # needed, we can always check the current subvol of the path, and if
        # it isn't the default subvol (via btrfs_get_default_subvol()), we
        # could assume a subvol is already mounted and log an error/return
        # False.
        pass

    # Finally mount!
    cmd = "mount '/dev/{}' '{}' -t btrfs -o subvol={}".format(
        dev_info['part_dev'], path, subvol)
    _rc, _stdout, _stderr = _run(cmd)
    if _rc != 0:
        log.error(("Failed to mount subvolume '{}' onto '{}': stderr: "
                   "'{}'.".format(subvol, path, _stderr)))
        return False

    log.warn(("Successfully mounted subvolume '{}' onto "
              "'{}'.".format(subvol, path)))
    return True
Пример #16
0
def btrfs_create_subvol(subvol='', dev_info=None, **kwargs):
    """
    Create a btrfs subvolume for the given subvol.  Expected subvol to be of the
    form @/foo/bar.  dev_info is either passed (when called directly) or queried
    by stripping off the '@' from the subvol in order to query the path.

    Return True/False.
    """
    ret = True
    tmp_dir = None

    if not subvol:
        log.error("Unable to create subvolume '{}'.".format(subvol))
        return False

    # Check if subvol already exists.
    if btrfs_subvol_exists(subvol):
        log.warn("Subvolume '{}' already exists.".format(subvol))
        return True

    # If we didn't get dev_info (because we're being called directly from the command
    # line), we _assume_ that the subvol path will ultimately be mounted onto a matching
    # path, so _try_ to get the device information by converting subvol to it's corresponding
    # path (ie. by stripping the leading '@').
    if not dev_info:
        dev_info = get_device_info(get_mountpoint(subvol[1:]))

    if not dev_info:
        log.error(("Unable to create subvolume '{}': failed to get device "
                   "information for '{}'".format(subvol, subvol[1:])))
        return False

    if dev_info['fstype'] != 'btrfs':
        log.error(("Unable to create subvolume '{}': invalid filesystem type "
                   "({}).".format(subvol, dev_info['fstype'])))
        return False

    # Get the partition of the mountpoint of the path.
    part_path = "/dev/{}".format(dev_info['part_dev'])

    # Create a unique tmp directory.
    try:
        tmp_dir = tempfile.mkdtemp()
    # pylint: disable=bare-except
    except:
        log.error(("Unable to create subvolume '{}': failed to create "
                   "temporary directory.".format(subvol)))
        return False

    # Mount tmpdir.
    cmd = "mount -t btrfs -o subvolid=0 '{}' '{}'".format(part_path, tmp_dir)
    _rc, _stdout, _stderr = _run(cmd)
    if _rc != 0:
        log.error("Failed to mount '{}' with subvolid=0 on '{}'.".format(
            part_path, tmp_dir))
        ret = False

    if ret:
        # Create the subvol.
        cmd = "btrfs subvolume create '{}/{}'".format(tmp_dir, subvol)
        _rc, _stdout, _stderr = _run(cmd)
        if _rc != 0:
            log.error("Failed to create subvolume '{}' on '{}'.".format(
                subvol, part_path))
            ret = False

    # Cleanup tmp_dir.  Don't touch ret here, just log any errors.
    if os.path.exists(tmp_dir):
        cmd = "umount '{}'".format(tmp_dir)
        _rc, _stdout, _stderr = _run(cmd)
        if _rc != 0:
            log.error("Failed to unmount '{}'.".format(tmp_dir))
        try:
            shutil.rmtree(tmp_dir)
        # pylint: disable=bare-except
        except:
            log.error("Failed to remove '{}'.".format(tmp_dir))

    if not ret:
        # We failed somewhere, so take care of removing the subvolume, etc.
        # TODO: there is a bug with subvolume deletes
        # (https://bugzilla.opensuse.org/show_bug.cgi?id=957198)
        # so no more cleanup can be dont at this point.
        log.error("Failed to create subvolume '{}'.".format(subvol))
    else:
        log.warn("Successfully created subvolume '{}'.".format(subvol))

    return ret