Beispiel #1
0
def multipath_assert_supported():
    """ Determine if the runtime system supports multipath.
    returns: True if system supports multipath
    raises: RuntimeError: if system does not support multipath
    """
    missing_progs = [
        p for p in ('multipath', 'multipathd') if not util.which(p)
    ]
    if missing_progs:
        raise RuntimeError("Missing multipath utils: %s" %
                           ','.join(missing_progs))
Beispiel #2
0
def install_missing_packages(cfg, target):
    ''' describe which operation types will require specific packages

    'custom_config_key': {
         'pkg1': ['op_name_1', 'op_name_2', ...]
     }
    '''

    installed_packages = util.get_installed_packages(target)
    needed_packages = set([
        pkg for pkg in detect_required_packages(cfg)
        if pkg not in installed_packages
    ])

    arch_packages = {
        's390x': [('s390-tools', 'zipl')],
    }

    for pkg, cmd in arch_packages.get(platform.machine(), []):
        if not util.which(cmd, target=target):
            if pkg not in needed_packages:
                needed_packages.add(pkg)

    # Filter out ifupdown network packages on netplan enabled systems.
    has_netplan = ('nplan' in installed_packages
                   or 'netplan.io' in installed_packages)
    if 'ifupdown' not in installed_packages and has_netplan:
        drops = set(['bridge-utils', 'ifenslave', 'vlan'])
        if needed_packages.union(drops):
            LOG.debug("Skipping install of %s.  Not needed on netplan system.",
                      needed_packages.union(drops))
            needed_packages = needed_packages.difference(drops)

    if needed_packages:
        to_add = list(sorted(needed_packages))
        state = util.load_command_environment()
        with events.ReportEventStack(
                name=state.get('report_stack_prefix'),
                reporting_enabled=True,
                level="INFO",
                description="Installing packages on target system: " +
                str(to_add)):
            util.install_packages(to_add, target=target)
Beispiel #3
0
def stop_all_unused_multipath_devices():
    """
    Stop all unused multipath devices.
    """
    multipath = util.which('multipath')

    # Command multipath is not available only when multipath-tools package
    # is not installed. Nothing needs to be done in this case because system
    # doesn't create multipath devices without this package installed and we
    # have nothing to stop.
    if not multipath:
        return

    # Command multipath -F flushes all unused multipath device maps
    cmd = [multipath, '-F']
    try:
        # unless multipath cleared *everything* it will exit with 1
        util.subp(cmd, rcs=[0, 1])
    except util.ProcessExecutionError as e:
        LOG.warn("Failed to stop multipath devices: %s", e)
Beispiel #4
0
def zfs_assert_supported():
    """ Determine if the runtime system supports zfs.
    returns: True if system supports zfs
    raises: RuntimeError: if system does not support zfs
    """
    arch = util.get_platform_arch()
    if arch in ZFS_UNSUPPORTED_ARCHES:
        raise RuntimeError("zfs is not supported on architecture: %s" % arch)

    release = util.lsb_release()['codename']
    if release in ZFS_UNSUPPORTED_RELEASES:
        raise RuntimeError("zfs is not supported on release: %s" % release)

    if 'zfs' not in get_supported_filesystems():
        try:
            util.load_kernel_module('zfs')
        except util.ProcessExecutionError as err:
            raise RuntimeError("Failed to load 'zfs' kernel module: %s" % err)

    missing_progs = [p for p in ('zpool', 'zfs') if not util.which(p)]
    if missing_progs:
        raise RuntimeError("Missing zfs utils: %s" % ','.join(missing_progs))
Beispiel #5
0
def netconfig_passthrough_available(target, feature='NETWORK_CONFIG_V2'):
    """
    Determine if curtin can pass v2 network config to in target cloud-init
    """
    LOG.debug('Checking in-target cloud-init for feature: %s', feature)
    with util.ChrootableTarget(target) as in_chroot:

        cloudinit = util.which('cloud-init', target=target)
        if not cloudinit:
            LOG.warning('Target does not have cloud-init installed')
            return False

        available = False
        try:
            out, _ = in_chroot.subp([cloudinit, 'features'], capture=True)
            available = feature in out.splitlines()
        except util.ProcessExecutionError:
            # we explicitly don't dump the exception as this triggers
            # vmtest failures when parsing the installation log file
            LOG.warning("Failed to probe cloudinit features")
            return False

        LOG.debug('cloud-init feature %s available? %s', feature, available)
        return available
Beispiel #6
0
def mkfs(path, fstype, strict=False, label=None, uuid=None, force=False):
    """Make filesystem on block device with given path using given fstype and
       appropriate flags for filesystem family.

       Filesystem uuid and label can be passed in as kwargs. By default no
       label or uuid will be used. If a filesystem label is too long curtin
       will raise a ValueError if the strict flag is true or will truncate
       it to the maximum possible length.

       If a flag is not supported by a filesystem family mkfs will raise a
       ValueError if the strict flag is true or silently ignore it otherwise.

       Force can be specified to force the mkfs command to continue even if it
       finds old data or filesystems on the partition.
       """

    if path is None:
        raise ValueError("invalid block dev path '%s'" % path)
    if not os.path.exists(path):
        raise ValueError("'%s': no such file or directory" % path)

    fs_family = specific_to_family.get(fstype, fstype)
    mkfs_cmd = mkfs_commands.get(fstype)
    if not mkfs_cmd:
        raise ValueError("unsupported fs type '%s'" % fstype)

    if util.which(mkfs_cmd) is None:
        raise ValueError("need '%s' but it could not be found" % mkfs_cmd)

    cmd = [mkfs_cmd]

    # use device logical block size to ensure properly formated filesystems
    (logical_bsize, physical_bsize) = block.get_blockdev_sector_size(path)
    if logical_bsize > 512:
        lbs_str = ('size={}'.format(logical_bsize)
                   if fs_family == "xfs" else str(logical_bsize))
        cmd.extend(
            get_flag_mapping("sectorsize",
                             fs_family,
                             param=lbs_str,
                             strict=strict))

        if fs_family == 'fat':
            # mkfs.vfat doesn't calculate this right for non-512b sector size
            # lp:1569576 , d-i uses the same setting.
            cmd.extend(["-s", "1"])

    if force:
        cmd.extend(get_flag_mapping("force", fs_family, strict=strict))
    if label is not None:
        limit = label_length_limits.get(fs_family)
        if len(label) > limit:
            if strict:
                raise ValueError("length of fs label for '%s' exceeds max \
                                 allowed for fstype '%s'. max is '%s'" %
                                 (path, fstype, limit))
            else:
                label = label[:limit]
        cmd.extend(
            get_flag_mapping("label", fs_family, param=label, strict=strict))

    # If uuid is not specified, generate one and try to use it
    if uuid is None:
        uuid = str(uuid4())
    cmd.extend(get_flag_mapping("uuid", fs_family, param=uuid, strict=strict))

    if fs_family == "fat":
        fat_size = fstype.strip(string.ascii_letters)
        if fat_size in ["12", "16", "32"]:
            cmd.extend(
                get_flag_mapping("fatsize",
                                 fs_family,
                                 param=fat_size,
                                 strict=strict))

    cmd.append(path)
    util.subp(cmd, capture=True)

    # if fs_family does not support specifying uuid then use blkid to find it
    # if blkid is unable to then just return None for uuid
    if fs_family not in family_flag_mappings['uuid']:
        try:
            uuid = block.blkid()[path]['UUID']
        except Exception:
            pass

    # return uuid, may be none if it could not be specified and blkid could not
    # find it
    return uuid
Beispiel #7
0
def apply_kexec(kexec, target):
    """
    load kexec kernel from target dir, similar to /etc/init.d/kexec-load
    kexec:
     mode: on
    """
    grubcfg = "boot/grub/grub.cfg"
    target_grubcfg = os.path.join(target, grubcfg)

    if kexec is None or kexec.get("mode") != "on":
        return False

    if not isinstance(kexec, dict):
        raise TypeError("kexec is not a dict.")

    if not util.which('kexec'):
        util.install_packages('kexec-tools')

    if not os.path.isfile(target_grubcfg):
        raise ValueError("%s does not exist in target" % grubcfg)

    with open(target_grubcfg, "r") as fp:
        default = 0
        menu_lines = []

        # get the default grub boot entry number and menu entry line numbers
        for line_num, line in enumerate(fp, 1):
            if re.search(r"\bset default=\"[0-9]+\"\b", " %s " % line):
                default = int(re.sub(r"[^0-9]", '', line))
            if re.search(r"\bmenuentry\b", " %s " % line):
                menu_lines.append(line_num)

        if not menu_lines:
            LOG.error("grub config file does not have a menuentry\n")
            return False

        # get the begin and end line numbers for default menuentry section,
        # using end of file if it's the last menuentry section
        begin = menu_lines[default]
        if begin != menu_lines[-1]:
            end = menu_lines[default + 1] - 1
        else:
            end = line_num

        fp.seek(0)
        lines = fp.readlines()
        kernel = append = initrd = ""

        for i in range(begin, end):
            if 'linux' in lines[i].split():
                split_line = shlex.split(lines[i])
                kernel = os.path.join(target, split_line[1])
                append = "--append=" + ' '.join(split_line[2:])
            if 'initrd' in lines[i].split():
                split_line = shlex.split(lines[i])
                initrd = "--initrd=" + os.path.join(target, split_line[1])

        if not kernel:
            LOG.error("grub config file does not have a kernel\n")
            return False

        LOG.debug("kexec -l %s %s %s" % (kernel, append, initrd))
        util.subp(args=['kexec', '-l', kernel, append, initrd])
        return True
Beispiel #8
0
 def test_custom_path_target_set(self):
     self.exe_list = ["/target/usr/bin2/fuzz"]
     found = util.which("fuzz",
                        search=["/bin1", "/usr/bin2"],
                        target="/target")
     self.assertEqual(found, "/usr/bin2/fuzz")
Beispiel #9
0
def check_executable(cmdname, pkg):
    if not which(cmdname):
        raise MissingDeps("Missing program '%s'." % cmdname, pkg)
Beispiel #10
0
 def test_custom_path_target_unset(self):
     self.exe_list = ["/usr/bin2/fuzz"]
     self.assertEqual(util.which("fuzz", search=["/bin1", "/usr/bin2"]),
                      "/usr/bin2/fuzz")
Beispiel #11
0
 def test_no_program_target_set(self):
     self.exe_list = ["/usr/bin/ls"]
     self.assertEqual(util.which("fuzz"), None)
Beispiel #12
0
 def test_target_set(self):
     self.exe_list = ["/foo/bin/ls"]
     self.assertEqual(util.which("ls", target="/foo"), "/bin/ls")
Beispiel #13
0
 def test_no_program_target_none(self):
     self.exe_list = []
     self.assertEqual(util.which("fuzz"), None)
Beispiel #14
0
 def test_target_none(self):
     self.exe_list = ["/usr/bin/ls"]
     self.assertEqual(util.which("ls"), "/usr/bin/ls")