예제 #1
0
def _should_configure_on_empty_apt():
    # if no config was provided, should apt configuration be done?
    if util.system_is_snappy():
        return False, "system is snappy."
    if not (subp.which('apt-get') or subp.which('apt')):
        return False, "no apt commands."
    return True, "Apt is available."
예제 #2
0
def _create_fs(log, device, fs_type, fs_label, fs_opts=None):
    # Create filesystem
    mkfs_cmd = subp.which("mkfs.%s" % fs_type)
    if not mkfs_cmd:
        mkfs_cmd = subp.which("mk%s" % fs_type)
    if not mkfs_cmd:
        util.logexc(log,
                    "_create_fs: "
                    "cannot create filesystem type '%s': "
                    "failed to find mkfs.%s command" % (fs_type, fs_type))
        return
    try:
        if fs_opts:
            if fs_label:
                subp.subp([mkfs_cmd, '-L', fs_label, fs_opts, device])
            else:
                subp.subp([mkfs_cmd, fs_opts, device])
        else:
            if fs_label:
                subp.subp([mkfs_cmd, '-L', fs_label, device])
            else:
                subp.subp([mkfs_cmd, device])
    except Exception as e:
        util.logexc(log,
                    "_create_fs: "
                    "failed to create filesystem type '%s': %s" % (fs_type, e))
예제 #3
0
def set_route():
    # Get routes, confirm entry does not exist
    routes = netinfo.route_info()

    # If no tools exist and empty dict is returned
    if 'ipv4' not in routes:
        return

    # We only care about IPv4
    routes = routes['ipv4']

    # Searchable list
    dests = []

    # Parse each route into a more searchable format
    for route in routes:
        dests.append(route['destination'])

    gw_present = '100.64.0.0' in dests or '100.64.0.0/10' in dests
    dest_present = '169.254.169.254' in dests

    # If not IPv6 only (No link local)
    # or the route is already present
    if not gw_present or dest_present:
        return

    # Set metadata route
    if subp.which('ip'):
        subp.subp([
            'ip', 'route', 'add', '169.254.169.254/32', 'dev',
            net.find_fallback_nic()
        ])
    elif subp.which('route'):
        subp.subp(['route', 'add', '-net', '169.254.169.254/32', '100.64.0.1'])
예제 #4
0
def route_info():
    routes = {}
    if subp.which('ip'):
        # Try iproute first of all
        (iproute_out, _err) = subp.subp(["ip", "-o", "route", "list"])
        routes = _netdev_route_info_iproute(iproute_out)
    elif subp.which('netstat'):
        # Fall back to net-tools if iproute2 is not present
        (route_out, _err) = subp.subp(
            ["netstat", "--route", "--numeric", "--extend"], rcs=[0, 1])
        routes = _netdev_route_info_netstat(route_out)
    else:
        LOG.warning(
            "Could not print routes: missing 'ip' and 'netstat' commands")
    return routes
예제 #5
0
def maybe_perform_dhcp_discovery(nic=None, dhcp_log_func=None):
    """Perform dhcp discovery if nic valid and dhclient command exists.

    If the nic is invalid or undiscoverable or dhclient command is not found,
    skip dhcp_discovery and return an empty dict.

    @param nic: Name of the network interface we want to run dhclient on.
    @param dhcp_log_func: A callable accepting the dhclient output and error
        streams.
    @return: A list of dicts representing dhcp options for each lease obtained
        from the dhclient discovery if run, otherwise an empty list is
        returned.
    """
    if nic is None:
        nic = find_fallback_nic()
        if nic is None:
            LOG.debug('Skip dhcp_discovery: Unable to find fallback nic.')
            return []
    elif nic not in get_devicelist():
        LOG.debug('Skip dhcp_discovery: nic %s not found in get_devicelist.',
                  nic)
        return []
    dhclient_path = subp.which('dhclient')
    if not dhclient_path:
        LOG.debug('Skip dhclient configuration: No dhclient command found.')
        return []
    with temp_utils.tempdir(rmtree_ignore_errors=True,
                            prefix='cloud-init-dhcp-',
                            needs_exe=True) as tdir:
        # Use /var/tmp because /run/cloud-init/tmp is mounted noexec
        return dhcp_discovery(dhclient_path, nic, tdir, dhcp_log_func)
예제 #6
0
def available(target=None):
    expected = ["netplan"]
    search = ["/usr/sbin", "/sbin"]
    for p in expected:
        if not subp.which(p, search=search, target=target):
            return False
    return True
예제 #7
0
파일: rhel.py 프로젝트: rongz609/cloud-init
    def package_command(self, command, args=None, pkgs=None):
        if pkgs is None:
            pkgs = []

        if subp.which("dnf"):
            LOG.debug("Using DNF for package management")
            cmd = ["dnf"]
        else:
            LOG.debug("Using YUM for package management")
            # the '-t' argument makes yum tolerant of errors on the command
            # line with regard to packages.
            #
            # For example: if you request to install foo, bar and baz and baz
            # is installed; yum won't error out complaining that baz is already
            # installed.
            cmd = ["yum", "-t"]
        # Determines whether or not yum prompts for confirmation
        # of critical actions. We don't want to prompt...
        cmd.append("-y")

        if args and isinstance(args, str):
            cmd.append(args)
        elif args and isinstance(args, list):
            cmd.extend(args)

        cmd.append(command)

        pkglist = util.expand_package_list("%s-%s", pkgs)
        cmd.extend(pkglist)

        # Allow the output of this to flow outwards (ie not be captured)
        subp.subp(cmd, capture=False)
def handle(name, cfg, _cloud, log, _args):
    disabled = util.get_cfg_option_bool(cfg, "disable_ec2_metadata", False)
    if disabled:
        reject_cmd = None
        if subp.which('ip'):
            reject_cmd = REJECT_CMD_IP
        elif subp.which('ifconfig'):
            reject_cmd = REJECT_CMD_IF
        else:
            log.error(('Neither "route" nor "ip" command found, unable to '
                       'manipulate routing table'))
            return
        subp.subp(reject_cmd, capture=False)
    else:
        log.debug(("Skipping module named %s,"
                   " disabling the ec2 route not enabled"), name)
예제 #9
0
def openvswitch_is_installed() -> bool:
    """Return a bool indicating if Open vSwitch is installed in the system."""
    ret = bool(subp.which("ovs-vsctl"))
    if not ret:
        LOG.debug(
            "ovs-vsctl not in PATH; not detecting Open vSwitch interfaces")
    return ret
예제 #10
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
예제 #11
0
def is_encrypted(blockdev, partition) -> bool:
    """
    Check if a device is an encrypted device. blockdev should have
    a /dev/dm-* path whereas partition is something like /dev/sda1.
    """
    if not subp.which("cryptsetup"):
        LOG.debug("cryptsetup not found. Assuming no encrypted partitions")
        return False
    try:
        subp.subp(["cryptsetup", "status", blockdev])
    except subp.ProcessExecutionError as e:
        if e.exit_code == 4:
            LOG.debug("Determined that %s is not encrypted", blockdev)
        else:
            LOG.warning(
                "Received unexpected exit code %s from "
                "cryptsetup status. Assuming no encrypted partitions.",
                e.exit_code,
            )
        return False
    with suppress(subp.ProcessExecutionError):
        subp.subp(["cryptsetup", "isLuks", partition])
        LOG.debug("Determined that %s is encrypted", blockdev)
        return True
    return False
예제 #12
0
 def available(target=None) -> bool:
     """Return true if network manager can be used on this system."""
     config_present = os.path.isfile(
         subp.target_path(target, path=NM_CFG_FILE)
     )
     nmcli_present = subp.which("nmcli", target=target)
     return config_present and bool(nmcli_present)
예제 #13
0
def generate_fallback_network_config() -> dict:
    """Return network config V1 dict representing instance network config."""
    network_v1 = {
        "version":
        1,
        "config": [{
            "type": "physical",
            "name": "eth0",
            "subnets": [{
                "type": "dhcp",
                "control": "auto"
            }]
        }]
    }
    if subp.which("systemd-detect-virt"):
        try:
            virt_type, _ = subp.subp(['systemd-detect-virt'])
        except subp.ProcessExecutionError as err:
            LOG.warning(
                "Unable to run systemd-detect-virt: %s."
                " Rendering default network config.", err)
            return network_v1
        if virt_type.strip() == "kvm":  # instance.type VIRTUAL-MACHINE
            arch = util.system_info()["uname"][4]
            if arch == "ppc64le":
                network_v1["config"][0]["name"] = "enp0s5"
            elif arch == "s390x":
                network_v1["config"][0]["name"] = "enc9"
            else:
                network_v1["config"][0]["name"] = "enp5s0"
    return network_v1
예제 #14
0
def available(target=None):
    expected = ['systemctl']
    search = ['/usr/bin', '/bin']
    for p in expected:
        if not subp.which(p, search=search, target=target):
            return False
    return True
예제 #15
0
def netdev_info(empty=""):
    devs = {}
    if util.is_NetBSD():
        (ifcfg_out, _err) = subp.subp(["ifconfig", "-a"], rcs=[0, 1])
        devs = _netdev_info_ifconfig_netbsd(ifcfg_out)
    elif subp.which("ip"):
        # Try iproute first of all
        try:
            (ipaddr_out, _err) = subp.subp(["ip", "--json", "addr"])
            devs = _netdev_info_iproute_json(ipaddr_out)
        except subp.ProcessExecutionError:
            # Can be removed when "ip --json" is available everywhere
            (ipaddr_out, _err) = subp.subp(["ip", "addr", "show"])
            devs = _netdev_info_iproute(ipaddr_out)
    elif subp.which("ifconfig"):
        # Fall back to net-tools if iproute2 is not present
        (ifcfg_out, _err) = subp.subp(["ifconfig", "-a"], rcs=[0, 1])
        devs = _netdev_info_ifconfig(ifcfg_out)
    else:
        LOG.warning(
            "Could not print networks: missing 'ip' and 'ifconfig' commands")

    if empty == "":
        return devs

    recurse_types = (dict, tuple, list)

    def fill(data, new_val="", empty_vals=("", b"")):
        """Recursively replace 'empty_vals' in data (dict, tuple, list)
        with new_val"""
        if isinstance(data, dict):
            myiter = data.items()
        elif isinstance(data, (tuple, list)):
            myiter = enumerate(data)
        else:
            raise TypeError("Unexpected input to fill")

        for key, val in myiter:
            if val in empty_vals:
                data[key] = new_val
            elif isinstance(val, recurse_types):
                fill(val, new_val)

    fill(devs, new_val=empty)
    return devs
예제 #16
0
def _get_wrapper_prefix(cmd, mode):
    if isinstance(cmd, str):
        cmd = [str(cmd)]

    if (util.is_true(mode) or
        (str(mode).lower() == "auto" and cmd[0] and subp.which(cmd[0]))):
        return cmd
    else:
        return []
예제 #17
0
def handle(_name, cfg, cloud, log, args):

    if not is_key_in_nested_dict(cfg, "ssh_import_id"):
        log.debug("Skipping module named ssh-import-id, no 'ssh_import_id'"
                  " directives found.")
        return
    elif not subp.which(SSH_IMPORT_ID_BINARY):
        log.warning(
            "ssh-import-id is not installed, but module ssh_import_id is "
            "configured. Skipping module.")
        return

    # import for "user: XXXXX"
    if len(args) != 0:
        user = args[0]
        ids = []
        if len(args) > 1:
            ids = args[1:]

        import_ssh_ids(ids, user, log)
        return

    # import for cloudinit created users
    (users, _groups) = ug_util.normalize_users_groups(cfg, cloud.distro)
    elist = []
    for (user, user_cfg) in users.items():
        import_ids = []
        if user_cfg["default"]:
            import_ids = util.get_cfg_option_list(cfg, "ssh_import_id", [])
        else:
            try:
                import_ids = user_cfg["ssh_import_id"]
            except Exception:
                log.debug("User %s is not configured for ssh_import_id", user)
                continue

        try:
            import_ids = util.uniq_merge(import_ids)
            import_ids = [str(i) for i in import_ids]
        except Exception:
            log.debug("User %s is not correctly configured for ssh_import_id",
                      user)
            continue

        if not len(import_ids):
            continue

        try:
            import_ssh_ids(import_ids, user, log)
        except Exception as exc:
            util.logexc(log, "ssh-import-id failed for: %s %s", user,
                        import_ids)
            elist.append(exc)

    if len(elist):
        raise elist[0]
예제 #18
0
파일: show.py 프로젝트: delphix/cloud-init
 def __init__(self, property, parameter=None):
     self.epoch = None
     self.args = [subp.which("systemctl"), "show"]
     if parameter:
         self.args.append(parameter)
     self.args.extend(["-p", property])
     # Don't want the init of our object to break. Instead of throwing
     # an exception, set an error code that gets checked when data is
     # requested from the object
     self.failure = self.subp()
예제 #19
0
def available(target=None):
    expected = ["ifquery", "ifup", "ifdown"]
    search = ["/sbin", "/usr/sbin"]
    for p in expected:
        if not subp.which(p, search=search, target=target):
            return False
    eni = subp.target_path(target, "etc/network/interfaces")
    if not os.path.isfile(eni):
        return False

    return True
예제 #20
0
def available(target=None):
    expected = ['ifquery', 'ifup', 'ifdown']
    search = ['/sbin', '/usr/sbin']
    for p in expected:
        if not subp.which(p, search=search, target=target):
            return False
    eni = subp.target_path(target, 'etc/network/interfaces')
    if not os.path.isfile(eni):
        return False

    return True
예제 #21
0
def set_route():
    # Get routes, confirm entry does not exist
    routes = netinfo.route_info()

    # If no tools exist and empty dict is returned
    if "ipv4" not in routes:
        return

    # We only care about IPv4
    routes = routes["ipv4"]

    # Searchable list
    dests = []

    # Parse each route into a more searchable format
    for route in routes:
        dests.append(route["destination"])

    gw_present = "100.64.0.0" in dests or "100.64.0.0/10" in dests
    dest_present = "169.254.169.254" in dests

    # If not IPv6 only (No link local)
    # or the route is already present
    if not gw_present or dest_present:
        return

    # Set metadata route
    if subp.which("ip"):
        subp.subp([
            "ip",
            "route",
            "add",
            "169.254.169.254/32",
            "dev",
            net.find_fallback_nic(),
        ])
    elif subp.which("route"):
        subp.subp(["route", "add", "-net", "169.254.169.254/32", "100.64.0.1"])
예제 #22
0
def available_sysconfig(target=None):
    expected = ['ifup', 'ifdown']
    search = ['/sbin', '/usr/sbin']
    for p in expected:
        if not subp.which(p, search=search, target=target):
            return False

    expected_paths = [
        'etc/sysconfig/network-scripts/network-functions',
        'etc/sysconfig/config']
    for p in expected_paths:
        if os.path.isfile(subp.target_path(target, p)):
            return True
    return False
예제 #23
0
def maybe_install_ua_tools(cloud):
    """Install ubuntu-advantage-tools if not present."""
    if subp.which("ua"):
        return
    try:
        cloud.distro.update_package_sources()
    except Exception:
        util.logexc(LOG, "Package update failed")
        raise
    try:
        cloud.distro.install_packages(["ubuntu-advantage-tools"])
    except Exception:
        util.logexc(LOG, "Failed to install ubuntu-advantage-tools")
        raise
예제 #24
0
def available(target=None):
    # TODO: Move `uses_systemd` to a more appropriate location
    # It is imported here to avoid circular import
    from cloudinit.distros import uses_systemd

    config_present = os.path.isfile(subp.target_path(target, path=NM_CFG_FILE))
    nmcli_present = subp.which("nmcli", target=target)
    service_active = True
    if uses_systemd():
        try:
            subp.subp(["systemctl", "is-enabled", "NetworkManager.service"])
        except subp.ProcessExecutionError:
            service_active = False

    return config_present and bool(nmcli_present) and service_active
예제 #25
0
def install_ntp_client(install_func, packages=None, check_exe="ntpd"):
    """Install ntp client package if not already installed.

    @param install_func: function.  This parameter is invoked with the contents
    of the packages parameter.
    @param packages: list.  This parameter defaults to ['ntp'].
    @param check_exe: string.  The name of a binary that indicates the package
    the specified package is already installed.
    """
    if subp.which(check_exe):
        return
    if packages is None:
        packages = ["ntp"]

    install_func(packages)
예제 #26
0
def available_sysconfig(target=None):
    expected = ["ifup", "ifdown"]
    search = ["/sbin", "/usr/sbin"]
    for p in expected:
        if not subp.which(p, search=search, target=target):
            return False

    expected_paths = [
        "etc/sysconfig/network-scripts/network-functions",
        "etc/sysconfig/config",
    ]
    for p in expected_paths:
        if os.path.isfile(subp.target_path(target, p)):
            return True
    return False
예제 #27
0
def transport_vmware_guestinfo():
    rpctool = "vmware-rpctool"
    not_found = None
    if not subp.which(rpctool):
        return not_found
    cmd = [rpctool, "info-get guestinfo.ovfEnv"]
    try:
        out, _err = subp.subp(cmd)
        if out:
            return out
        LOG.debug("cmd %s exited 0 with empty stdout: %s", cmd, out)
    except subp.ProcessExecutionError as e:
        if e.exit_code != 1:
            LOG.warning("%s exited with code %d", rpctool, e.exit_code)
            LOG.debug(e)
    return not_found
예제 #28
0
def handle_random_seed_command(command, required, env=None):
    if not command and required:
        raise ValueError("no command found but required=true")
    elif not command:
        LOG.debug("no command provided")
        return

    cmd = command[0]
    if not subp.which(cmd):
        if required:
            raise ValueError(
                "command '{cmd}' not found but required=true".format(cmd=cmd))
        else:
            LOG.debug("command '%s' not found for seed_command", cmd)
            return
    subp.subp(command, env=env, capture=False)
예제 #29
0
 def lock_passwd(self, name):
     """
     Lock the password of a user, i.e., disable password logins
     """
     # passwd must use short '-l' due to SLES11 lacking long form '--lock'
     lock_tools = (['passwd', '-l', name], ['usermod', '--lock', name])
     try:
         cmd = next(tool for tool in lock_tools if subp.which(tool[0]))
     except StopIteration:
         raise RuntimeError(
             ("Unable to lock user account '%s'. No tools available. "
              "  Tried: %s.") % (name, [c[0] for c in lock_tools]))
     try:
         subp.subp(cmd)
     except Exception as e:
         util.logexc(LOG, 'Failed to disable password for user %s', name)
         raise e
예제 #30
0
def select_ntp_client(ntp_client, distro):
    """Determine which ntp client is to be used, consulting the distro
       for its preference.

    @param ntp_client: String name of the ntp client to use.
    @param distro: Distro class instance.
    @returns: Dict of the selected ntp client or {} if none selected.
    """

    # construct distro-specific ntp_client_config dict
    distro_cfg = distro_ntp_client_configs(distro.name)

    # user specified client, return its config
    if ntp_client and ntp_client != "auto":
        LOG.debug('Selected NTP client "%s" via user-data configuration',
                  ntp_client)
        return distro_cfg.get(ntp_client, {})

    # default to auto if unset in distro
    distro_ntp_client = distro.get_option("ntp_client", "auto")

    clientcfg = {}
    if distro_ntp_client == "auto":
        for client in distro.preferred_ntp_clients:
            cfg = distro_cfg.get(client)
            if subp.which(cfg.get("check_exe")):
                LOG.debug('Selected NTP client "%s", already installed',
                          client)
                clientcfg = cfg
                break

        if not clientcfg:
            client = distro.preferred_ntp_clients[0]
            LOG.debug(
                'Selected distro preferred NTP client "%s", not yet installed',
                client,
            )
            clientcfg = distro_cfg.get(client)
    else:
        LOG.debug(
            'Selected NTP client "%s" via distro system config',
            distro_ntp_client,
        )
        clientcfg = distro_cfg.get(distro_ntp_client, {})

    return clientcfg