Exemplo n.º 1
0
    def network_config(self):
        """
        Configure networking according to data received from the
        metadata API.
        """
        if self._network_config is None:
            LOG.warning(
                "Found None as cached _network_config. Resetting to %s",
                sources.UNSET,
            )
            self._network_config = sources.UNSET

        if self._network_config != sources.UNSET:
            return self._network_config

        if self._fallback_interface is None:
            self._fallback_interface = net.find_fallback_nic()

        netcfg = {"type": "physical", "name": "%s" % self._fallback_interface}
        subnets = [{"type": "dhcp4"}]
        if 'ipv6' in self.metadata:
            if self.metadata["ipv6"]:
                subnets += [
                    {
                        "type": "static",
                        "address": "%s" % self.metadata["ipv6"]["address"],
                        "gateway": "%s" % self.metadata["ipv6"]["gateway"],
                        "netmask": "%s" % self.metadata["ipv6"]["netmask"],
                    }
                ]
        netcfg["subnets"] = subnets
        self._network_config = {"version": 1, "config": [netcfg]}
        return self._network_config
Exemplo n.º 2
0
def maybe_perform_dhcp_discovery(nic=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.
    @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 = util.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)
Exemplo n.º 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'])
Exemplo n.º 4
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.")
            raise NoDHCPLeaseInterfaceError()
    elif nic not in get_devicelist():
        LOG.debug("Skip dhcp_discovery: nic %s not found in get_devicelist.",
                  nic)
        raise NoDHCPLeaseInterfaceError()
    dhclient_path = subp.which("dhclient")
    if not dhclient_path:
        LOG.debug("Skip dhclient configuration: No dhclient command found.")
        raise NoDHCPLeaseMissingDhclientError()
    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)
Exemplo n.º 5
0
    def get_data(self):
        if not on_hetzner():
            return False
        nic = cloudnet.find_fallback_nic()
        with cloudnet.EphemeralIPv4Network(nic, "169.254.0.1", 16,
                                           "169.254.255.255"):
            md = hc_helper.read_metadata(self.metadata_address,
                                         timeout=self.timeout,
                                         sec_between=self.wait_retry,
                                         retries=self.retries)
            ud = hc_helper.read_userdata(self.userdata_address,
                                         timeout=self.timeout,
                                         sec_between=self.wait_retry,
                                         retries=self.retries)

        self.userdata_raw = ud
        self.metadata_full = md
        """hostname is name provided by user at launch.  The API enforces
        it is a valid hostname, but it is not guaranteed to be resolvable
        in dns or fully qualified."""
        self.metadata['instance-id'] = md['instance-id']
        self.metadata['local-hostname'] = md['hostname']
        self.metadata['network-config'] = md.get('network-config', None)
        self.metadata['public-keys'] = md.get('public-keys', None)
        self.vendordata_raw = md.get("vendor_data", None)

        return True
Exemplo n.º 6
0
def maybe_perform_dhcp_discovery(nic=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.
    @return: A dict of dhcp options from the dhclient discovery if run,
        otherwise an empty dict 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 = util.which('dhclient')
    if not dhclient_path:
        LOG.debug('Skip dhclient configuration: No dhclient command found.')
        return {}
    with util.tempdir(prefix='cloud-init-dhcp-') as tmpdir:
        return dhcp_discovery(dhclient_path, nic, tmpdir)
Exemplo n.º 7
0
def maybe_perform_dhcp_discovery(nic=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.
    @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 = util.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)
Exemplo n.º 8
0
    def network_config(self):
        """
        Configure networking according to data received from the
        metadata API.
        """
        if self._network_config is None:
            LOG.warning(
                'Found None as cached _network_config. '
                'Resetting to %s', sources.UNSET)
            self._network_config = sources.UNSET

        if self._network_config != sources.UNSET:
            return self._network_config

        if self._fallback_interface is None:
            self._fallback_interface = net.find_fallback_nic()

        netcfg = {'type': 'physical', 'name': '%s' % self._fallback_interface}
        subnets = [{'type': 'dhcp4'}]
        if self.metadata['ipv6']:
            subnets += [{
                'type': 'static',
                'address': '%s' % self.metadata['ipv6']['address'],
                'gateway': '%s' % self.metadata['ipv6']['gateway'],
                'netmask': '%s' % self.metadata['ipv6']['netmask'],
            }]
        netcfg['subnets'] = subnets
        self._network_config = {'version': 1, 'config': [netcfg]}
        return self._network_config
    def _get_data(self):
        if not self._is_platform_viable():
            return False

        self.system_uuid = _read_system_uuid()

        # network may be configured if iscsi root.  If that is the case
        # then read_initramfs_config will return non-None.
        if _is_iscsi_root():
            data = read_opc_metadata()
        else:
            with dhcp.EphemeralDHCPv4(net.find_fallback_nic()):
                data = read_opc_metadata()

        self._crawled_metadata = data

        self.metadata = {
            "availability-zone": data["ociAdName"],
            "instance-id": data["id"],
            "launch-index": 0,
            "local-hostname": data["hostname"],
            "name": data["displayName"],
        }

        if "metadata" in data:
            user_data = data["metadata"].get("user_data")
            if user_data:
                self.userdata_raw = base64.b64decode(user_data)
            self.metadata["public_keys"] = data["metadata"].get(
                "ssh_authorized_keys")

        return True
Exemplo n.º 10
0
    def get_data(self):
        if not on_hetzner():
            return False
        nic = cloudnet.find_fallback_nic()
        with cloudnet.EphemeralIPv4Network(nic, "169.254.0.1", 16,
                                           "169.254.255.255"):
            md = hc_helper.read_metadata(self.metadata_address,
                                         timeout=self.timeout,
                                         sec_between=self.wait_retry,
                                         retries=self.retries)
            ud = hc_helper.read_userdata(self.userdata_address,
                                         timeout=self.timeout,
                                         sec_between=self.wait_retry,
                                         retries=self.retries)

        # Hetzner cloud does not support binary user-data. So here, do a
        # base64 decode of the data if we can. The end result being that a
        # user can provide base64 encoded (possibly gzipped) data as user-data.
        #
        # The fallout is that in the event of b64 encoded user-data,
        # /var/lib/cloud-init/cloud-config.txt will not be identical to the
        # user-data provided.  It will be decoded.
        self.userdata_raw = hc_helper.maybe_b64decode(ud)
        self.metadata_full = md

        # hostname is name provided by user at launch.  The API enforces it is
        # a valid hostname, but it is not guaranteed to be resolvable in dns or
        # fully qualified.
        self.metadata['instance-id'] = md['instance-id']
        self.metadata['local-hostname'] = md['hostname']
        self.metadata['network-config'] = md.get('network-config', None)
        self.metadata['public-keys'] = md.get('public-keys', None)
        self.vendordata_raw = md.get("vendor_data", None)

        return True
Exemplo n.º 11
0
    def get_data(self):
        if not on_hetzner():
            return False
        nic = cloudnet.find_fallback_nic()
        with cloudnet.EphemeralIPv4Network(nic, "169.254.0.1", 16,
                                           "169.254.255.255"):
            md = hc_helper.read_metadata(
                self.metadata_address, timeout=self.timeout,
                sec_between=self.wait_retry, retries=self.retries)
            ud = hc_helper.read_userdata(
                self.userdata_address, timeout=self.timeout,
                sec_between=self.wait_retry, retries=self.retries)

        self.userdata_raw = ud
        self.metadata_full = md

        """hostname is name provided by user at launch.  The API enforces
        it is a valid hostname, but it is not guaranteed to be resolvable
        in dns or fully qualified."""
        self.metadata['instance-id'] = md['instance-id']
        self.metadata['local-hostname'] = md['hostname']
        self.metadata['network-config'] = md.get('network-config', None)
        self.metadata['public-keys'] = md.get('public-keys', None)
        self.vendordata_raw = md.get("vendor_data", None)

        return True
Exemplo n.º 12
0
 def fallback_interface(self):
     """Determine the network interface used during local network config."""
     if self._fallback_interface is None:
         self._fallback_interface = net.find_fallback_nic()
         if self._fallback_interface is None:
             LOG.warning("Did not find a fallback interface on %s.",
                         self.cloud_name)
     return self._fallback_interface
Exemplo n.º 13
0
    def _get_data(self):
        (on_hetzner, serial) = get_hcloud_data()

        if not on_hetzner:
            return False

        try:
            with EphemeralDHCPv4(
                    iface=net.find_fallback_nic(),
                    connectivity_url_data={
                        "url": BASE_URL_V1 + "/metadata/instance-id",
                    },
            ):
                md = hc_helper.read_metadata(
                    self.metadata_address,
                    timeout=self.timeout,
                    sec_between=self.wait_retry,
                    retries=self.retries,
                )
                ud = hc_helper.read_userdata(
                    self.userdata_address,
                    timeout=self.timeout,
                    sec_between=self.wait_retry,
                    retries=self.retries,
                )
        except (NoDHCPLeaseError) as e:
            LOG.error("Bailing, DHCP Exception: %s", e)
            raise

        # Hetzner cloud does not support binary user-data. So here, do a
        # base64 decode of the data if we can. The end result being that a
        # user can provide base64 encoded (possibly gzipped) data as user-data.
        #
        # The fallout is that in the event of b64 encoded user-data,
        # /var/lib/cloud-init/cloud-config.txt will not be identical to the
        # user-data provided.  It will be decoded.
        self.userdata_raw = hc_helper.maybe_b64decode(ud)
        self.metadata_full = md

        # hostname is name provided by user at launch.  The API enforces it is
        # a valid hostname, but it is not guaranteed to be resolvable in dns or
        # fully qualified.
        self.metadata["instance-id"] = md["instance-id"]
        self.metadata["local-hostname"] = md["hostname"]
        self.metadata["network-config"] = md.get("network-config", None)
        self.metadata["public-keys"] = md.get("public-keys", None)
        self.vendordata_raw = md.get("vendor_data", None)

        # instance-id and serial from SMBIOS should be identical
        if self.get_instance_id() != serial:
            raise RuntimeError(
                "SMBIOS serial does not match instance ID from metadata")

        return True
Exemplo n.º 14
0
    def _get_data(self):
        (is_upcloud, server_uuid) = self._get_sysinfo()

        # only proceed if we know we are on UpCloud
        if not is_upcloud:
            return False

        LOG.info("Running on UpCloud. server_uuid=%s", server_uuid)

        if self.perform_dhcp_setup:  # Setup networking in init-local stage.
            try:
                LOG.debug("Finding a fallback NIC")
                nic = cloudnet.find_fallback_nic()
                LOG.debug("Discovering metadata via DHCP interface %s", nic)
                with EphemeralDHCPv4(nic):
                    md = util.log_time(
                        logfunc=LOG.debug,
                        msg="Reading from metadata service",
                        func=self._read_metadata,
                    )
            except (NoDHCPLeaseError, sources.InvalidMetaDataException) as e:
                util.logexc(LOG, str(e))
                return False
        else:
            try:
                LOG.debug(
                    "Discovering metadata without DHCP-configured networking"
                )
                md = util.log_time(
                    logfunc=LOG.debug,
                    msg="Reading from metadata service",
                    func=self._read_metadata,
                )
            except sources.InvalidMetaDataException as e:
                util.logexc(LOG, str(e))
                LOG.info(
                    "No DHCP-enabled interfaces available, "
                    "unable to fetch metadata for %s",
                    server_uuid,
                )
                return False

        self.metadata_full = md
        self.metadata["instance-id"] = md.get("instance_id", server_uuid)
        self.metadata["local-hostname"] = md.get("hostname")
        self.metadata["network"] = md.get("network")
        self.metadata["public-keys"] = md.get("public_keys")
        self.metadata["availability_zone"] = md.get("region", "default")
        self.vendordata_raw = md.get("vendor_data", None)
        self.userdata_raw = md.get("user_data", None)

        return True
Exemplo n.º 15
0
 def fallback_interface(self):
     if self._fallback_interface is None:
         # fallback_nic was used at one point, so restored objects may
         # have an attribute there. respect that if found.
         _legacy_fbnic = getattr(self, 'fallback_nic', None)
         if _legacy_fbnic:
             self._fallback_interface = _legacy_fbnic
             self.fallback_nic = None
         else:
             self._fallback_interface = net.find_fallback_nic()
             if self._fallback_interface is None:
                 LOG.warning("Did not find a fallback interface on EC2.")
     return self._fallback_interface
Exemplo n.º 16
0
    def _get_data(self):
        if not on_scaleway():
            return False

        if self._fallback_interface is None:
            self._fallback_interface = net.find_fallback_nic()
        try:
            with EphemeralDHCPv4(self._fallback_interface):
                util.log_time(logfunc=LOG.debug,
                              msg='Crawl of metadata service',
                              func=self._crawl_metadata)
        except (NoDHCPLeaseError) as e:
            util.logexc(LOG, str(e))
            return False
        return True
Exemplo n.º 17
0
    def _get_data(self):
        if not on_scaleway():
            return False

        if self._fallback_interface is None:
            self._fallback_interface = net.find_fallback_nic()
        try:
            with EphemeralDHCPv4(self._fallback_interface):
                util.log_time(
                    logfunc=LOG.debug, msg='Crawl of metadata service',
                    func=self._crawl_metadata)
        except (NoDHCPLeaseError) as e:
            util.logexc(LOG, str(e))
            return False
        return True
Exemplo n.º 18
0
    def _get_data(self):
        if not self._is_platform_viable():
            return False

        self.system_uuid = _read_system_uuid()

        # network may be configured if iscsi root.  If that is the case
        # then read_initramfs_config will return non-None.
        fetch_vnics_data = self.ds_cfg.get(
            "configure_secondary_nics",
            BUILTIN_DS_CONFIG["configure_secondary_nics"],
        )
        network_context = noop()
        if not _is_iscsi_root():
            network_context = dhcp.EphemeralDHCPv4(
                iface=net.find_fallback_nic(),
                connectivity_url_data={
                    "url": METADATA_PATTERN.format(version=2, path="instance"),
                    "headers": V2_HEADERS,
                },
            )
        with network_context:
            fetched_metadata = read_opc_metadata(
                fetch_vnics_data=fetch_vnics_data)

        data = self._crawled_metadata = fetched_metadata.instance_data
        self.metadata_address = METADATA_ROOT.format(
            version=fetched_metadata.version)
        self._vnics_data = fetched_metadata.vnics_data

        self.metadata = {
            "availability-zone": data["ociAdName"],
            "instance-id": data["id"],
            "launch-index": 0,
            "local-hostname": data["hostname"],
            "name": data["displayName"],
        }

        if "metadata" in data:
            user_data = data["metadata"].get("user_data")
            if user_data:
                self.userdata_raw = base64.b64decode(user_data)
            self.metadata["public_keys"] = data["metadata"].get(
                "ssh_authorized_keys")

        return True
Exemplo n.º 19
0
    def _get_data(self):
        if not self._is_platform_viable():
            return False

        # network may be configured if iscsi root.  If that is the case
        # then read_initramfs_config will return non-None.
        if _is_iscsi_root():
            data = self.crawl_metadata()
        else:
            with dhcp.EphemeralDHCPv4(net.find_fallback_nic()):
                data = self.crawl_metadata()

        self._crawled_metadata = data
        vdata = data['2013-10-17']

        self.userdata_raw = vdata.get('user_data')
        self.system_uuid = vdata['system_uuid']

        vd = vdata.get('vendor_data')
        if vd:
            self.vendordata_pure = vd
            try:
                self.vendordata_raw = sources.convert_vendordata(vd)
            except ValueError as e:
                LOG.warning("Invalid content in vendor-data: %s", e)
                self.vendordata_raw = None

        mdcopies = ('public_keys', )
        md = dict([(k, vdata['meta_data'].get(k)) for k in mdcopies
                   if k in vdata['meta_data']])

        mdtrans = (
            # oracle meta_data.json name, cloudinit.datasource.metadata name
            ('availability_zone', 'availability-zone'),
            ('hostname', 'local-hostname'),
            ('launch_index', 'launch-index'),
            ('uuid', 'instance-id'),
        )
        for dsname, ciname in mdtrans:
            if dsname in vdata['meta_data']:
                md[ciname] = vdata['meta_data'][dsname]

        self.metadata = md
        return True
Exemplo n.º 20
0
    def network_config(self):
        """
        Configure networking according to data received from the
        metadata API.
        """
        if self._network_config:
            return self._network_config

        if self._fallback_interface is None:
            self._fallback_interface = net.find_fallback_nic()

        netcfg = {'type': 'physical', 'name': '%s' % self._fallback_interface}
        subnets = [{'type': 'dhcp4'}]
        if self.metadata['ipv6']:
            subnets += [{'type': 'static',
                         'address': '%s' % self.metadata['ipv6']['address'],
                         'gateway': '%s' % self.metadata['ipv6']['gateway'],
                         'netmask': '%s' % self.metadata['ipv6']['netmask'],
                         }]
        netcfg['subnets'] = subnets
        self._network_config = {'version': 1, 'config': [netcfg]}
        return self._network_config
Exemplo n.º 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"])
Exemplo n.º 22
0
 def find_fallback_nic(self, *, blacklist_drivers=None):
     return net.find_fallback_nic(blacklist_drivers=blacklist_drivers)