def get_metadata_from_imds(fallback_nic, retries): """Query Azure's network metadata service, returning a dictionary. If network is not up, setup ephemeral dhcp on fallback_nic to talk to the IMDS. For more info on IMDS: https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service @param fallback_nic: String. The name of the nic which requires active network in order to query IMDS. @param retries: The number of retries of the IMDS_URL. @return: A dict of instance metadata containing compute and network info. """ kwargs = { 'logfunc': LOG.debug, 'msg': 'Crawl of Azure Instance Metadata Service (IMDS)', 'func': _get_metadata_from_imds, 'args': (retries, ) } if net.is_up(fallback_nic): return util.log_time(**kwargs) else: with EphemeralDHCPv4(fallback_nic): return util.log_time(**kwargs)
def test_is_up_false(self): """is_up is False if sys/net/devname/operstate is 'down' or invalid.""" for state in ['down', 'incomprehensible']: write_file(os.path.join(self.sysdir, 'eth0', 'operstate'), state) self.assertFalse(net.is_up('eth0'))
def test_is_up_true(self): """is_up is True if sys/net/devname/operstate is 'up' or 'unknown'.""" for state in ['up', 'unknown']: write_file(os.path.join(self.sysdir, 'eth0', 'operstate'), state) self.assertTrue(net.is_up('eth0'))
def crawl_metadata(self): """Walk all instance metadata sources returning a dict on success. @return: A dictionary of any metadata content for this instance. @raise: InvalidMetaDataException when the expected metadata service is unavailable, broken or disabled. """ crawled_data = {} # azure removes/ejects the cdrom containing the ovf-env.xml # file on reboot. So, in order to successfully reboot we # need to look in the datadir and consider that valid ddir = self.ds_cfg['data_dir'] candidates = [self.seed_dir] if os.path.isfile(REPROVISION_MARKER_FILE): candidates.insert(0, "IMDS") candidates.extend(list_possible_azure_ds_devs()) if ddir: candidates.append(ddir) found = None reprovision = False for cdev in candidates: try: if cdev == "IMDS": ret = None reprovision = True elif cdev.startswith("/dev/"): if util.is_FreeBSD(): ret = util.mount_cb(cdev, load_azure_ds_dir, mtype="udf", sync=False) else: ret = util.mount_cb(cdev, load_azure_ds_dir) else: ret = load_azure_ds_dir(cdev) except NonAzureDataSource: continue except BrokenAzureDataSource as exc: msg = 'BrokenAzureDataSource: %s' % exc raise sources.InvalidMetaDataException(msg) except util.MountFailedError: LOG.warning("%s was not mountable", cdev) continue perform_reprovision = reprovision or self._should_reprovision(ret) if perform_reprovision: if util.is_FreeBSD(): msg = "Free BSD is not supported for PPS VMs" LOG.error(msg) raise sources.InvalidMetaDataException(msg) ret = self._reprovision() imds_md = get_metadata_from_imds(self.fallback_interface, retries=10) (md, userdata_raw, cfg, files) = ret self.seed = cdev crawled_data.update({ 'cfg': cfg, 'files': files, 'metadata': util.mergemanydict([md, { 'imds': imds_md }]), 'userdata_raw': userdata_raw }) found = cdev LOG.debug("found datasource in %s", cdev) break if not found: raise sources.InvalidMetaDataException('No Azure metadata found') if found == ddir: LOG.debug("using files cached in %s", ddir) seed = _get_random_seed() if seed: crawled_data['metadata']['random_seed'] = seed crawled_data['metadata']['instance-id'] = util.read_dmi_data( 'system-uuid') if perform_reprovision: LOG.info("Reporting ready to Azure after getting ReprovisionData") use_cached_ephemeral = (net.is_up(self.fallback_interface) and getattr(self, '_ephemeral_dhcp_ctx', None)) if use_cached_ephemeral: self._report_ready(lease=self._ephemeral_dhcp_ctx.lease) self._ephemeral_dhcp_ctx.clean_network() # Teardown ephemeral else: with EphemeralDHCPv4() as lease: self._report_ready(lease=lease) return crawled_data
def is_up(self, devname: DeviceName) -> bool: return net.is_up(devname)
def test_is_up_false(self): """is_up is False if sys/net/devname/operstate is 'down' or invalid.""" for state in ['down', 'incomprehensible']: write_file(os.path.join(self.sysdir, 'eth0', 'operstate'), state) self.assertFalse(net.is_up('eth0'))
def test_is_up_true(self): """is_up is True if sys/net/devname/operstate is 'up' or 'unknown'.""" for state in ['up', 'unknown']: write_file(os.path.join(self.sysdir, 'eth0', 'operstate'), state) self.assertTrue(net.is_up('eth0'))