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
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)
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'])
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)
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
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)
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)
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
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
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
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
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
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
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
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
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
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
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
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
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"])
def find_fallback_nic(self, *, blacklist_drivers=None): return net.find_fallback_nic(blacklist_drivers=blacklist_drivers)