예제 #1
0
def wait_on_network(metadata):
    # Determine whether we need to wait on the network coming online.
    wait_on_ipv4 = False
    wait_on_ipv6 = False
    if WAIT_ON_NETWORK in metadata:
        wait_on_network = metadata[WAIT_ON_NETWORK]
        if WAIT_ON_NETWORK_IPV4 in wait_on_network:
            wait_on_ipv4_val = wait_on_network[WAIT_ON_NETWORK_IPV4]
            if isinstance(wait_on_ipv4_val, bool):
                wait_on_ipv4 = wait_on_ipv4_val
            else:
                wait_on_ipv4 = util.translate_bool(wait_on_ipv4_val)
        if WAIT_ON_NETWORK_IPV6 in wait_on_network:
            wait_on_ipv6_val = wait_on_network[WAIT_ON_NETWORK_IPV6]
            if isinstance(wait_on_ipv6_val, bool):
                wait_on_ipv6 = wait_on_ipv6_val
            else:
                wait_on_ipv6 = util.translate_bool(wait_on_ipv6_val)

    # Get information about the host.
    host_info = None
    while host_info is None:
        # This loop + sleep results in two logs every second while waiting
        # for either ipv4 or ipv6 up. Do we really need to log each iteration
        # or can we log once and log on successful exit?
        host_info = get_host_info()

        network = host_info.get("network") or {}
        interfaces = network.get("interfaces") or {}
        by_ipv4 = interfaces.get("by-ipv4") or {}
        by_ipv6 = interfaces.get("by-ipv6") or {}

        if wait_on_ipv4:
            ipv4_ready = len(by_ipv4) > 0 if by_ipv4 else False
            if not ipv4_ready:
                host_info = None

        if wait_on_ipv6:
            ipv6_ready = len(by_ipv6) > 0 if by_ipv6 else False
            if not ipv6_ready:
                host_info = None

        if host_info is None:
            LOG.debug(
                "waiting on network: wait4=%s, ready4=%s, wait6=%s, ready6=%s",
                wait_on_ipv4,
                ipv4_ready,
                wait_on_ipv6,
                ipv6_ready,
            )
            time.sleep(1)

    LOG.debug("waiting on network complete")
    return host_info
def handle(name, cfg, cloud, log, _args):
    manage_hosts = util.get_cfg_option_str(cfg, "manage_etc_hosts", False)
    if util.translate_bool(manage_hosts, addons=['template']):
        (hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud)
        if not hostname:
            log.warn(("Option 'manage_etc_hosts' was set,"
                     " but no hostname was found"))
            return

        # Render from a template file
        tpl_fn_name = cloud.get_template_filename("hosts.%s" %
                                                  (cloud.distro.osfamily))
        if not tpl_fn_name:
            raise RuntimeError(("No hosts template could be"
                                " found for distro %s") %
                               (cloud.distro.osfamily))

        templater.render_to_file(tpl_fn_name, '/etc/hosts',
                                 {'hostname': hostname, 'fqdn': fqdn})

    elif manage_hosts == "localhost":
        (hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud)
        if not hostname:
            log.warn(("Option 'manage_etc_hosts' was set,"
                     " but no hostname was found"))
            return

        log.debug("Managing localhost in /etc/hosts")
        cloud.distro.update_etc_hosts(hostname, fqdn)
    else:
        log.debug(("Configuration option 'manage_etc_hosts' is not set,"
                   " not managing /etc/hosts in module %s"), name)
예제 #3
0
def install_drivers(cfg, pkg_install_func):
    if not isinstance(cfg, dict):
        raise TypeError("'drivers' config expected dict, found '%s': %s" %
                        (type_utils.obj_name(cfg), cfg))

    cfgpath = "nvidia/license-accepted"
    # Call translate_bool to ensure that we treat string values like "yes" as
    # acceptance and _don't_ treat string values like "nah" as acceptance
    # because they're True-ish
    nv_acc = util.translate_bool(util.get_cfg_by_path(cfg, cfgpath))
    if not nv_acc:
        LOG.debug("Not installing NVIDIA drivers. %s=%s", cfgpath, nv_acc)
        return

    if not subp.which("ubuntu-drivers"):
        LOG.debug("'ubuntu-drivers' command not available.  "
                  "Installing ubuntu-drivers-common")
        pkg_install_func(["ubuntu-drivers-common"])

    driver_arg = "nvidia"
    version_cfg = util.get_cfg_by_path(cfg, "nvidia/version")
    if version_cfg:
        driver_arg += ":{}".format(version_cfg)

    LOG.debug(
        "Installing and activating NVIDIA drivers (%s=%s, version=%s)",
        cfgpath,
        nv_acc,
        version_cfg if version_cfg else "latest",
    )

    # Register and set debconf selection linux/nvidia/latelink = true
    tdir = temp_utils.mkdtemp(needs_exe=True)
    debconf_file = os.path.join(tdir, "nvidia.template")
    debconf_script = os.path.join(tdir, "nvidia-debconf.sh")
    try:
        util.write_file(debconf_file, NVIDIA_DEBCONF_CONTENT)
        util.write_file(
            debconf_script,
            util.encode_text(NVIDIA_DRIVER_LATELINK_DEBCONF_SCRIPT),
            mode=0o755,
        )
        subp.subp([debconf_script, debconf_file])
    except Exception as e:
        util.logexc(LOG, "Failed to register NVIDIA debconf template: %s",
                    str(e))
        raise
    finally:
        if os.path.isdir(tdir):
            util.del_dir(tdir)

    try:
        subp.subp(["ubuntu-drivers", "install", "--gpgpu", driver_arg])
    except subp.ProcessExecutionError as exc:
        if OLD_UBUNTU_DRIVERS_STDERR_NEEDLE in exc.stderr:
            LOG.warning("the available version of ubuntu-drivers is"
                        " too old to perform requested driver installation")
        elif "No drivers found for installation." in exc.stdout:
            LOG.warning("ubuntu-drivers found no drivers for installation")
        raise
def handle(name, cfg, cloud, log, _args):
    manage_hosts = util.get_cfg_option_str(cfg, "manage_etc_hosts", False)
    if util.translate_bool(manage_hosts, addons=['template']):
        (hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud)
        if not hostname:
            log.warn(("Option 'manage_etc_hosts' was set,"
                      " but no hostname was found"))
            return

        # Render from a template file
        tpl_fn_name = cloud.get_template_filename("hosts.%s" %
                                                  (cloud.distro.osfamily))
        if not tpl_fn_name:
            raise RuntimeError(
                ("No hosts template could be"
                 " found for distro %s") % (cloud.distro.osfamily))

        templater.render_to_file(tpl_fn_name, '/etc/hosts', {
            'hostname': hostname,
            'fqdn': fqdn
        })

    elif manage_hosts == "localhost":
        (hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud)
        if not hostname:
            log.warn(("Option 'manage_etc_hosts' was set,"
                      " but no hostname was found"))
            return

        log.debug("Managing localhost in /etc/hosts")
        cloud.distro.update_etc_hosts(hostname, fqdn)
    else:
        log.debug(("Configuration option 'manage_etc_hosts' is not set,"
                   " not managing /etc/hosts in module %s"), name)
예제 #5
0
def handle(name, cfg, cloud, log, _args):
    do_migrate = util.get_cfg_option_str(cfg, "migrate", True)
    if not util.translate_bool(do_migrate):
        log.debug("Skipping module named %s, migration disabled", name)
        return
    sems_moved = _migrate_canon_sems(cloud)
    log.debug("Migrated %s semaphore files to there canonicalized names",
              sems_moved)
    _migrate_legacy_sems(cloud, log)
예제 #6
0
def handle(name, cfg, cloud, log, _args):
    do_migrate = util.get_cfg_option_str(cfg, "migrate", True)
    if not util.translate_bool(do_migrate):
        log.debug("Skipping module named %s, migration disabled", name)
        return
    sems_moved = _migrate_canon_sems(cloud)
    log.debug("Migrated %s semaphore files to there canonicalized names",
              sems_moved)
    _migrate_legacy_sems(cloud, log)
예제 #7
0
def handle(name, cfg, cloud, log, _args):
    manage_hosts = util.get_cfg_option_str(cfg, "manage_etc_hosts", False)

    hosts_fn = cloud.distro.hosts_fn

    if util.translate_bool(manage_hosts, addons=["template"]):
        if manage_hosts == "template":
            log.warning(
                "DEPRECATED: please use manage_etc_hosts: true instead of"
                " 'template'"
            )
        (hostname, fqdn, _) = util.get_hostname_fqdn(cfg, cloud)
        if not hostname:
            log.warning(
                "Option 'manage_etc_hosts' was set, but no hostname was found"
            )
            return

        # Render from a template file
        tpl_fn_name = cloud.get_template_filename(
            "hosts.%s" % (cloud.distro.osfamily)
        )
        if not tpl_fn_name:
            raise RuntimeError(
                "No hosts template could be found for distro %s"
                % (cloud.distro.osfamily)
            )

        templater.render_to_file(
            tpl_fn_name, hosts_fn, {"hostname": hostname, "fqdn": fqdn}
        )

    elif manage_hosts == "localhost":
        (hostname, fqdn, _) = util.get_hostname_fqdn(cfg, cloud)
        if not hostname:
            log.warning(
                "Option 'manage_etc_hosts' was set, but no hostname was found"
            )
            return

        log.debug("Managing localhost in %s", hosts_fn)
        cloud.distro.update_etc_hosts(hostname, fqdn)
    else:
        log.debug(
            "Configuration option 'manage_etc_hosts' is not set,"
            " not managing %s in module %s",
            hosts_fn,
            name,
        )
예제 #8
0
 def dhcp_domain(self, d, cfg):
     for item in ['dhcp4domain', 'dhcp6domain']:
         if item not in d:
             continue
         ret = str(d[item]).casefold()
         try:
             ret = util.translate_bool(ret)
             ret = 'yes' if ret else 'no'
         except ValueError:
             if ret != 'route':
                 LOG.warning('Invalid dhcp4domain value - %s', ret)
                 ret = 'no'
         if item == 'dhcp4domain':
             section = 'DHCPv4'
         else:
             section = 'DHCPv6'
         cfg.update_section(section, 'UseDomains', ret)
예제 #9
0
 def dhcp_domain(self, d, cfg):
     for item in ["dhcp4domain", "dhcp6domain"]:
         if item not in d:
             continue
         ret = str(d[item]).casefold()
         try:
             ret = util.translate_bool(ret)
             ret = "yes" if ret else "no"
         except ValueError:
             if ret != "route":
                 LOG.warning("Invalid dhcp4domain value - %s", ret)
                 ret = "no"
         if item == "dhcp4domain":
             section = "DHCPv4"
         else:
             section = "DHCPv6"
         cfg.update_section(section, "UseDomains", ret)
예제 #10
0
def _extract_preprovisioned_vm_setting(dom):
    """Read the preprovision flag from the ovf. It should not
       exist unless true."""
    platform_settings_section = find_child(
        dom.documentElement,
        lambda n: n.localName == "PlatformSettingsSection")
    if not platform_settings_section or len(platform_settings_section) == 0:
        LOG.debug("PlatformSettingsSection not found")
        return False
    platform_settings = find_child(platform_settings_section[0],
                                   lambda n: n.localName == "PlatformSettings")
    if not platform_settings or len(platform_settings) == 0:
        LOG.debug("PlatformSettings not found")
        return False
    preprovisionedVm = find_child(platform_settings[0],
                                  lambda n: n.localName == "PreprovisionedVm")
    if not preprovisionedVm or len(preprovisionedVm) == 0:
        LOG.debug("PreprovisionedVm not found")
        return False
    return util.translate_bool(preprovisionedVm[0].firstChild.nodeValue)
예제 #11
0
def handle(name, cfg, _cloud, log, _args):

    mycfg = cfg.get("grub_dpkg", cfg.get("grub-dpkg", {}))
    if not mycfg:
        mycfg = {}

    enabled = mycfg.get("enabled", True)
    if util.is_false(enabled):
        log.debug("%s disabled by config grub_dpkg/enabled=%s", name, enabled)
        return

    idevs = util.get_cfg_option_str(mycfg, "grub-pc/install_devices", None)
    if idevs is None:
        idevs = fetch_idevs(log)

    idevs_empty = mycfg.get("grub-pc/install_devices_empty")
    if idevs_empty is None:
        idevs_empty = not idevs
    elif not isinstance(idevs_empty, bool):
        log.warning(
            "DEPRECATED: grub_dpkg: grub-pc/install_devices_empty value of "
            f"'{idevs_empty}' is not boolean. Use of non-boolean values "
            "will be removed in a future version of cloud-init.")
        idevs_empty = util.translate_bool(idevs_empty)
    idevs_empty = str(idevs_empty).lower()

    # now idevs and idevs_empty are set to determined values
    # or, those set by user

    dconf_sel = ("grub-pc grub-pc/install_devices string %s\n"
                 "grub-pc grub-pc/install_devices_empty boolean %s\n" %
                 (idevs, idevs_empty))

    log.debug("Setting grub debconf-set-selections with '%s','%s'" %
              (idevs, idevs_empty))

    try:
        subp.subp(["debconf-set-selections"], dconf_sel)
    except Exception:
        util.logexc(log, "Failed to run debconf-set-selections for grub-dpkg")
def handle(name, cfg, cloud, log, _args):
    manage_hosts = util.get_cfg_option_str(cfg, "manage_etc_hosts", False)
    if util.translate_bool(manage_hosts, addons=['template']):
        (hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud)
        if not hostname:
            log.warn(("Option 'manage_etc_hosts' was set,"
                      " but no hostname was found"))
            return

        # Render from a template file
        tpl_fn_name = cloud.get_template_filename("hosts.%s" %
                                                  (cloud.distro.osfamily))
        #  out_fn = cloud.paths.join(False, '/etc/hosts')
        out_fn = '/etc/hosts'
        params = {'hostname': hostname, 'fqdn': fqdn}
        devs = netinfo.netdev_info()
        for dev, info in devs.items():
            params['dev_' + dev] = info['addr']

        templater.render_to_file(tpl_fn_name, out_fn, params)
        if not tpl_fn_name:
            raise RuntimeError(
                ("No hosts template could be"
                 " found for distro %s") % (cloud.distro.osfamily))

        #  templater.render_to_file(tpl_fn_name, '/etc/hosts',
        #  {'hostname': hostname, 'fqdn': fqdn})

    elif manage_hosts == "localhost":
        (hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud)
        if not hostname:
            log.warn(("Option 'manage_etc_hosts' was set,"
                      " but no hostname was found"))
            return

        log.debug("Managing localhost in /etc/hosts")
        cloud.distro.update_etc_hosts(hostname, fqdn)
    else:
        log.debug(("Configuration option 'manage_etc_hosts' is not set,"
                   " not managing /etc/hosts in module %s"), name)
예제 #13
0
def install_drivers(cfg, pkg_install_func):
    if not isinstance(cfg, dict):
        raise TypeError("'drivers' config expected dict, found '%s': %s" %
                        (type_utils.obj_name(cfg), cfg))

    cfgpath = 'nvidia/license-accepted'
    # Call translate_bool to ensure that we treat string values like "yes" as
    # acceptance and _don't_ treat string values like "nah" as acceptance
    # because they're True-ish
    nv_acc = util.translate_bool(util.get_cfg_by_path(cfg, cfgpath))
    if not nv_acc:
        LOG.debug("Not installing NVIDIA drivers. %s=%s", cfgpath, nv_acc)
        return

    if not util.which('ubuntu-drivers'):
        LOG.debug("'ubuntu-drivers' command not available.  "
                  "Installing ubuntu-drivers-common")
        pkg_install_func(['ubuntu-drivers-common'])

    driver_arg = 'nvidia'
    version_cfg = util.get_cfg_by_path(cfg, 'nvidia/version')
    if version_cfg:
        driver_arg += ':{}'.format(version_cfg)

    LOG.debug("Installing NVIDIA drivers (%s=%s, version=%s)", cfgpath, nv_acc,
              version_cfg if version_cfg else 'latest')

    try:
        util.subp(['ubuntu-drivers', 'install', '--gpgpu', driver_arg])
    except util.ProcessExecutionError as exc:
        if OLD_UBUNTU_DRIVERS_STDERR_NEEDLE in exc.stderr:
            LOG.warning('the available version of ubuntu-drivers is'
                        ' too old to perform requested driver installation')
        elif 'No drivers found for installation.' in exc.stdout:
            LOG.warning('ubuntu-drivers found no drivers for installation')
        raise
예제 #14
0
def handle(name, cfg, _cloud, log, args):
    if len(args) != 0:
        resize_root = args[0]
    else:
        resize_root = util.get_cfg_option_str(cfg, "resize_rootfs", True)

    if not util.translate_bool(resize_root, addons=[NOBLOCK]):
        log.debug("Skipping module named %s, resizing disabled", name)
        return

    # TODO(harlowja) is the directory ok to be used??
    resize_root_d = util.get_cfg_option_str(cfg, "resize_rootfs_tmp", "/run")
    util.ensure_dir(resize_root_d)

    # TODO(harlowja): allow what is to be resized to be configurable??
    resize_what = "/"
    result = util.get_mount_info(resize_what, log)
    if not result:
        log.warn("Could not determine filesystem type of %s", resize_what)
        return

    (devpth, fs_type, mount_point) = result

    # Ensure the path is a block device.
    info = "dev=%s mnt_point=%s path=%s" % (devpth, mount_point, resize_what)
    log.debug("resize_info: %s" % info)

    container = util.is_container()

    if (devpth == "/dev/root" and not os.path.exists(devpth) and
        not container):
        devpth = rootdev_from_cmdline(util.get_cmdline())
        if devpth is None:
            log.warn("Unable to find device '/dev/root'")
            return
        log.debug("Converted /dev/root to '%s' per kernel cmdline", devpth)

    try:
        statret = os.stat(devpth)
    except OSError as exc:
        if container and exc.errno == errno.ENOENT:
            log.debug("Device '%s' did not exist in container. "
                      "cannot resize: %s" % (devpth, info))
        elif exc.errno == errno.ENOENT:
            log.warn("Device '%s' did not exist. cannot resize: %s" %
                     (devpth, info))
        else:
            raise exc
        return

    if not stat.S_ISBLK(statret.st_mode) and not stat.S_ISCHR(statret.st_mode):
        if container:
            log.debug("device '%s' not a block device in container."
                      " cannot resize: %s" % (devpth, info))
        else:
            log.warn("device '%s' not a block device. cannot resize: %s" %
                     (devpth, info))
        return

    resizer = None
    fstype_lc = fs_type.lower()
    for (pfix, root_cmd) in RESIZE_FS_PREFIXES_CMDS:
        if fstype_lc.startswith(pfix):
            resizer = root_cmd
            break

    if not resizer:
        log.warn("Not resizing unknown filesystem type %s for %s",
                 fs_type, resize_what)
        return

    resize_cmd = resizer(resize_what, devpth)
    log.debug("Resizing %s (%s) using %s", resize_what, fs_type,
              ' '.join(resize_cmd))

    if resize_root == NOBLOCK:
        # Fork to a child that will run
        # the resize command
        util.fork_cb(
            util.log_time(logfunc=log.debug, msg="backgrounded Resizing",
                func=do_resize, args=(resize_cmd, log)))
    else:
        util.log_time(logfunc=log.debug, msg="Resizing",
            func=do_resize, args=(resize_cmd, log))

    action = 'Resized'
    if resize_root == NOBLOCK:
        action = 'Resizing (via forking)'
    log.debug("%s root filesystem (type=%s, val=%s)", action, fs_type,
              resize_root)
예제 #15
0
def handle(name, cfg, _cloud, log, args):
    if len(args) != 0:
        resize_root = args[0]
    else:
        resize_root = util.get_cfg_option_str(cfg, "resize_rootfs", True)
    validate_cloudconfig_schema(cfg, schema)
    if not util.translate_bool(resize_root, addons=[NOBLOCK]):
        log.debug("Skipping module named %s, resizing disabled", name)
        return

    # TODO(harlowja): allow what is to be resized to be configurable??
    resize_what = "/"
    result = util.get_mount_info(resize_what, log)
    if not result:
        log.warning("Could not determine filesystem type of %s", resize_what)
        return

    (devpth, fs_type, mount_point) = result

    # if we have a zfs then our device path at this point
    # is the zfs label. For example: vmzroot/ROOT/freebsd
    # we will have to get the zpool name out of this
    # and set the resize_what variable to the zpool
    # so the _resize_zfs function gets the right attribute.
    if fs_type == 'zfs':
        zpool = devpth.split('/')[0]
        devpth = util.get_device_info_from_zpool(zpool)
        if not devpth:
            return  # could not find device from zpool
        resize_what = zpool

    info = "dev=%s mnt_point=%s path=%s" % (devpth, mount_point, resize_what)
    log.debug("resize_info: %s" % info)

    devpth = maybe_get_writable_device_path(devpth, info, log)
    if not devpth:
        return  # devpath was not a writable block device

    resizer = None
    if can_skip_resize(fs_type, resize_what, devpth):
        log.debug("Skip resize filesystem type %s for %s",
                  fs_type, resize_what)
        return

    fstype_lc = fs_type.lower()
    for (pfix, root_cmd) in RESIZE_FS_PREFIXES_CMDS:
        if fstype_lc.startswith(pfix):
            resizer = root_cmd
            break

    if not resizer:
        log.warning("Not resizing unknown filesystem type %s for %s",
                    fs_type, resize_what)
        return

    resize_cmd = resizer(resize_what, devpth)
    log.debug("Resizing %s (%s) using %s", resize_what, fs_type,
              ' '.join(resize_cmd))

    if resize_root == NOBLOCK:
        # Fork to a child that will run
        # the resize command
        util.fork_cb(
            util.log_time, logfunc=log.debug, msg="backgrounded Resizing",
            func=do_resize, args=(resize_cmd, log))
    else:
        util.log_time(logfunc=log.debug, msg="Resizing",
                      func=do_resize, args=(resize_cmd, log))

    action = 'Resized'
    if resize_root == NOBLOCK:
        action = 'Resizing (via forking)'
    log.debug("%s root filesystem (type=%s, val=%s)", action, fs_type,
              resize_root)
예제 #16
0
def handle(name, cfg, _cloud, log, args):
    if len(args) != 0:
        resize_root = args[0]
    else:
        resize_root = util.get_cfg_option_str(cfg, "resize_rootfs", True)
    validate_cloudconfig_schema(cfg, schema)
    if not util.translate_bool(resize_root, addons=[NOBLOCK]):
        log.debug("Skipping module named %s, resizing disabled", name)
        return

    # TODO(harlowja): allow what is to be resized to be configurable??
    resize_what = "/"
    result = util.get_mount_info(resize_what, log)
    if not result:
        log.warn("Could not determine filesystem type of %s", resize_what)
        return

    (devpth, fs_type, mount_point) = result

    # if we have a zfs then our device path at this point
    # is the zfs label. For example: vmzroot/ROOT/freebsd
    # we will have to get the zpool name out of this
    # and set the resize_what variable to the zpool
    # so the _resize_zfs function gets the right attribute.
    if fs_type == 'zfs':
        zpool = devpth.split('/')[0]
        devpth = util.get_device_info_from_zpool(zpool)
        if not devpth:
            return  # could not find device from zpool
        resize_what = zpool

    info = "dev=%s mnt_point=%s path=%s" % (devpth, mount_point, resize_what)
    log.debug("resize_info: %s" % info)

    devpth = maybe_get_writable_device_path(devpth, info, log)
    if not devpth:
        return  # devpath was not a writable block device

    resizer = None
    if can_skip_resize(fs_type, resize_what, devpth):
        log.debug("Skip resize filesystem type %s for %s",
                  fs_type, resize_what)
        return

    fstype_lc = fs_type.lower()
    for (pfix, root_cmd) in RESIZE_FS_PREFIXES_CMDS:
        if fstype_lc.startswith(pfix):
            resizer = root_cmd
            break

    if not resizer:
        log.warn("Not resizing unknown filesystem type %s for %s",
                 fs_type, resize_what)
        return

    resize_cmd = resizer(resize_what, devpth)
    log.debug("Resizing %s (%s) using %s", resize_what, fs_type,
              ' '.join(resize_cmd))

    if resize_root == NOBLOCK:
        # Fork to a child that will run
        # the resize command
        util.fork_cb(
            util.log_time, logfunc=log.debug, msg="backgrounded Resizing",
            func=do_resize, args=(resize_cmd, log))
    else:
        util.log_time(logfunc=log.debug, msg="Resizing",
                      func=do_resize, args=(resize_cmd, log))

    action = 'Resized'
    if resize_root == NOBLOCK:
        action = 'Resizing (via forking)'
    log.debug("%s root filesystem (type=%s, val=%s)", action, fs_type,
              resize_root)
예제 #17
0
def handle(name, cfg, _cloud, log, args):
    if len(args) != 0:
        resize_enabled = args[0]
    else:
        resize_enabled = util.get_cfg_option_str(cfg, "resizefs_enabled", True)

        # Warn about the old-style configuration
        resize_rootfs_option = util.get_cfg_option_str(cfg, "resize_rootfs")
        if resize_rootfs_option:
            log.warning("""The resize_rootfs option is deprecated, please use
                        resizefs_enabled instead!""")
            resize_enabled = resize_rootfs_option

    # Renamed to schema_vyos to pass build tests without modifying upstream
    validate_cloudconfig_schema(cfg, schema_vyos)
    if not util.translate_bool(resize_enabled, addons=[NOBLOCK]):
        log.debug("Skipping module named %s, resizing disabled", name)
        return

    # Get list of partitions to resize
    resize_what = util.get_cfg_option_list(cfg, "resizefs_list",
                                           RESIZEFS_LIST_DEFAULT)
    log.debug("Filesystems to resize: %s", resize_what)

    # Resize all filesystems from resize_what
    for resize_item in resize_what:

        result = util.get_mount_info(resize_item, log)
        if not result:
            log.warning("Could not determine filesystem type of %s",
                        resize_item)
            return

        (devpth, fs_type, mount_point) = result

        # if we have a zfs then our device path at this point
        # is the zfs label. For example: vmzroot/ROOT/freebsd
        # we will have to get the zpool name out of this
        # and set the resize_item variable to the zpool
        # so the _resize_zfs function gets the right attribute.
        if fs_type == 'zfs':
            zpool = devpth.split('/')[0]
            devpth = util.get_device_info_from_zpool(zpool)
            if not devpth:
                return  # could not find device from zpool
            resize_item = zpool

        info = "dev=%s mnt_point=%s path=%s" % (devpth, mount_point,
                                                resize_item)
        log.debug("resize_info: %s" % info)

        devpth = maybe_get_writable_device_path(devpth, info, log)
        if not devpth:
            return  # devpath was not a writable block device

        resizer = None
        if can_skip_resize(fs_type, resize_item, devpth):
            log.debug("Skip resize filesystem type %s for %s", fs_type,
                      resize_item)
            return

        fstype_lc = fs_type.lower()
        for (pfix, root_cmd) in RESIZE_FS_PREFIXES_CMDS:
            if fstype_lc.startswith(pfix):
                resizer = root_cmd
                break

        if not resizer:
            log.warning("Not resizing unknown filesystem type %s for %s",
                        fs_type, resize_item)
            return

        resize_cmd = resizer(resize_item, devpth)
        log.debug("Resizing %s (%s) using %s", resize_item, fs_type,
                  ' '.join(resize_cmd))

        if resize_enabled == NOBLOCK:
            # Fork to a child that will run
            # the resize command
            util.fork_cb(util.log_time,
                         logfunc=log.debug,
                         msg="backgrounded Resizing",
                         func=do_resize,
                         args=(resize_cmd, log))
        else:
            util.log_time(logfunc=log.debug,
                          msg="Resizing",
                          func=do_resize,
                          args=(resize_cmd, log))

        action = 'Resized'
        if resize_enabled == NOBLOCK:
            action = 'Resizing (via forking)'
        log.debug("%s filesystem on %s (type=%s, val=%s)", action, resize_item,
                  fs_type, resize_enabled)
예제 #18
0
def handle(name, cfg, _cloud, log, args):
    if len(args) != 0:
        resize_root = args[0]
    else:
        resize_root = util.get_cfg_option_str(cfg, "resize_rootfs", True)

    if not util.translate_bool(resize_root, addons=[NOBLOCK]):
        log.debug("Skipping module named %s, resizing disabled", name)
        return

    # TODO(harlowja) is the directory ok to be used??
    resize_root_d = util.get_cfg_option_str(cfg, "resize_rootfs_tmp", "/run")
    util.ensure_dir(resize_root_d)

    # TODO(harlowja): allow what is to be resized to be configurable??
    resize_what = "/"
    result = util.get_mount_info(resize_what, log)
    if not result:
        log.warn("Could not determine filesystem type of %s", resize_what)
        return

    (devpth, fs_type, mount_point) = result

    info = "dev=%s mnt_point=%s path=%s" % (devpth, mount_point, resize_what)
    log.debug("resize_info: %s" % info)

    container = util.is_container()

    # Ensure the path is a block device.
    if (devpth == "/dev/root" and not os.path.exists(devpth)
            and not container):
        devpth = util.rootdev_from_cmdline(util.get_cmdline())
        if devpth is None:
            log.warn("Unable to find device '/dev/root'")
            return
        log.debug("Converted /dev/root to '%s' per kernel cmdline", devpth)

    try:
        statret = os.stat(devpth)
    except OSError as exc:
        if container and exc.errno == errno.ENOENT:
            log.debug(
                "Device '%s' did not exist in container. "
                "cannot resize: %s", devpth, info)
        elif exc.errno == errno.ENOENT:
            log.warn("Device '%s' did not exist. cannot resize: %s", devpth,
                     info)
        else:
            raise exc
        return

    if not os.access(devpth, os.W_OK):
        if container:
            log.debug("'%s' not writable in container. cannot resize: %s",
                      devpth, info)
        else:
            log.warn("'%s' not writable. cannot resize: %s", devpth, info)
        return

    if not stat.S_ISBLK(statret.st_mode) and not stat.S_ISCHR(statret.st_mode):
        if container:
            log.debug("device '%s' not a block device in container."
                      " cannot resize: %s" % (devpth, info))
        else:
            log.warn("device '%s' not a block device. cannot resize: %s" %
                     (devpth, info))
        return

    resizer = None
    if can_skip_resize(fs_type, resize_what, devpth):
        log.debug("Skip resize filesystem type %s for %s", fs_type,
                  resize_what)
        return

    fstype_lc = fs_type.lower()
    for (pfix, root_cmd) in RESIZE_FS_PREFIXES_CMDS:
        if fstype_lc.startswith(pfix):
            resizer = root_cmd
            break

    if not resizer:
        log.warn("Not resizing unknown filesystem type %s for %s", fs_type,
                 resize_what)
        return

    resize_cmd = resizer(resize_what, devpth)
    log.debug("Resizing %s (%s) using %s", resize_what, fs_type,
              ' '.join(resize_cmd))

    if resize_root == NOBLOCK:
        # Fork to a child that will run
        # the resize command
        util.fork_cb(util.log_time,
                     logfunc=log.debug,
                     msg="backgrounded Resizing",
                     func=do_resize,
                     args=(resize_cmd, log))
    else:
        util.log_time(logfunc=log.debug,
                      msg="Resizing",
                      func=do_resize,
                      args=(resize_cmd, log))

    action = 'Resized'
    if resize_root == NOBLOCK:
        action = 'Resizing (via forking)'
    log.debug("%s root filesystem (type=%s, val=%s)", action, fs_type,
              resize_root)
예제 #19
0
def handle(name, cfg, _cloud, log, args):
    if len(args) != 0:
        resize_root = args[0]
    else:
        resize_root = util.get_cfg_option_str(cfg, "resize_rootfs", True)
    validate_cloudconfig_schema(cfg, schema)
    if not util.translate_bool(resize_root, addons=[NOBLOCK]):
        log.debug("Skipping module named %s, resizing disabled", name)
        return

    # TODO(harlowja): allow what is to be resized to be configurable??
    resize_what = "/"
    result = util.get_mount_info(resize_what, log)
    if not result:
        log.warn("Could not determine filesystem type of %s", resize_what)
        return

    (devpth, fs_type, mount_point) = result

    info = "dev=%s mnt_point=%s path=%s" % (devpth, mount_point, resize_what)
    log.debug("resize_info: %s" % info)

    devpth = maybe_get_writable_device_path(devpth, info, log)
    if not devpth:
        return  # devpath was not a writable block device

    resizer = None
    if can_skip_resize(fs_type, resize_what, devpth):
        log.debug("Skip resize filesystem type %s for %s", fs_type,
                  resize_what)
        return

    fstype_lc = fs_type.lower()
    for (pfix, root_cmd) in RESIZE_FS_PREFIXES_CMDS:
        if fstype_lc.startswith(pfix):
            resizer = root_cmd
            break

    if not resizer:
        log.warn("Not resizing unknown filesystem type %s for %s", fs_type,
                 resize_what)
        return

    resize_cmd = resizer(resize_what, devpth)
    log.debug("Resizing %s (%s) using %s", resize_what, fs_type,
              ' '.join(resize_cmd))

    if resize_root == NOBLOCK:
        # Fork to a child that will run
        # the resize command
        util.fork_cb(util.log_time,
                     logfunc=log.debug,
                     msg="backgrounded Resizing",
                     func=do_resize,
                     args=(resize_cmd, log))
    else:
        util.log_time(logfunc=log.debug,
                      msg="Resizing",
                      func=do_resize,
                      args=(resize_cmd, log))

    action = 'Resized'
    if resize_root == NOBLOCK:
        action = 'Resizing (via forking)'
    log.debug("%s root filesystem (type=%s, val=%s)", action, fs_type,
              resize_root)