def test_get_devicelist_raise_oserror(self): """get_devicelist raise any non-ENOENT OSerror.""" error = OSError('Can not do it') error.errno = errno.EPERM # Set non-ENOENT self.m_sys_path.side_effect = error with self.assertRaises(OSError) as context_manager: net.get_devicelist() exception = context_manager.exception self.assertEqual('Can not do it', str(exception))
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 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, 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_link_local_nic(distro): nics = [ f for f in cloudnet.get_devicelist() if distro.networking.is_physical(f) ] if not nics: return None return min(nics, key=lambda d: cloudnet.read_sys_net_int(d, "ifindex"))
def _net_setup_link(self, run=False): """To ensure device link properties are applied, we poke udev to re-evaluate networkd .link files and call the setup_link udev builtin command """ if not run: LOG.debug("netplan net_setup_link postcmd disabled") return setup_lnk = ['udevadm', 'test-builtin', 'net_setup_link'] for cmd in [setup_lnk + [SYS_CLASS_NET + iface] for iface in get_devicelist() if os.path.islink(SYS_CLASS_NET + iface)]: util.subp(cmd, capture=True)
def network_config(self): """Generate a network config like net.generate_fallback_network() with the following execptions. 1. Probe the drivers of the net-devices present and inject them in the network configuration under params: driver: <driver> value 2. If the driver value is 'mlx4_core', the control mode should be set to manual. The device will be later used to build a bond, for now we want to ensure the device gets named but does not break any network configuration """ blacklist = ['mlx4_core'] if not self._network_config: LOG.debug('Azure: generating fallback configuration') # generate a network config, blacklist picking any mlx4_core devs netconfig = net.generate_fallback_config( blacklist_drivers=blacklist, config_driver=True) # if we have any blacklisted devices, update the network_config to # include the device, mac, and driver values, but with no ip # config; this ensures udev rules are generated but won't affect # ip configuration bl_found = 0 for bl_dev in [ dev for dev in net.get_devicelist() if net.device_driver(dev) in blacklist ]: bl_found += 1 cfg = { 'type': 'physical', 'name': 'vf%d' % bl_found, 'mac_address': net.get_interface_mac(bl_dev), 'params': { 'driver': net.device_driver(bl_dev), 'device_id': net.device_devid(bl_dev), }, } netconfig['config'].append(cfg) self._network_config = netconfig return self._network_config
def assign_ipv4_link_local(nic=None): """Bring up NIC using an address using link-local (ip4LL) IPs. On DigitalOcean, the link-local domain is per-droplet routed, so there is no risk of collisions. However, to be more safe, the ip4LL address is random. """ if not nic: for cdev in sorted(cloudnet.get_devicelist()): if cloudnet.is_physical(cdev): nic = cdev LOG.debug("assigned nic '%s' for link-local discovery", nic) break if not nic: raise RuntimeError("unable to find interfaces to access the" "meta-data server. This droplet is broken.") addr = "169.254.{0}.{1}/16".format(random.randint(1, 168), random.randint(0, 255)) ip_addr_cmd = ['ip', 'addr', 'add', addr, 'dev', nic] ip_link_cmd = ['ip', 'link', 'set', 'dev', nic, 'up'] if not util.which('ip'): raise RuntimeError("No 'ip' command available to configure ip4LL " "address") try: (result, _err) = util.subp(ip_addr_cmd) LOG.debug("assigned ip4LL address '%s' to '%s'", addr, nic) (result, _err) = util.subp(ip_link_cmd) LOG.debug("brought device '%s' up", nic) except Exception: util.logexc( LOG, "ip4LL address assignment of '%s' to '%s' failed." " Droplet networking will be broken", addr, nic) raise return nic
def assign_ipv4_link_local(nic=None): """Bring up NIC using an address using link-local (ip4LL) IPs. On DigitalOcean, the link-local domain is per-droplet routed, so there is no risk of collisions. However, to be more safe, the ip4LL address is random. """ if not nic: for cdev in sorted(cloudnet.get_devicelist()): if cloudnet.is_physical(cdev): nic = cdev LOG.debug("assigned nic '%s' for link-local discovery", nic) break if not nic: raise RuntimeError("unable to find interfaces to access the" "meta-data server. This droplet is broken.") addr = "169.254.{0}.{1}/16".format(random.randint(1, 168), random.randint(0, 255)) ip_addr_cmd = ['ip', 'addr', 'add', addr, 'dev', nic] ip_link_cmd = ['ip', 'link', 'set', 'dev', nic, 'up'] if not util.which('ip'): raise RuntimeError("No 'ip' command available to configure ip4LL " "address") try: (result, _err) = util.subp(ip_addr_cmd) LOG.debug("assigned ip4LL address '%s' to '%s'", addr, nic) (result, _err) = util.subp(ip_link_cmd) LOG.debug("brought device '%s' up", nic) except Exception: util.logexc(LOG, "ip4LL address assignment of '%s' to '%s' failed." " Droplet networking will be broken", addr, nic) raise return nic
def get_first_physical_interface(): devs = [f for f in cloudnet.get_devicelist() if cloudnet.is_physical(f)] if not devs: raise RuntimeError("No interfaces find to configure link-local address") return min(devs, key=lambda d: cloudnet.read_sys_net_int(d, 'ifindex'))
def test_get_devicelist_lists_any_subdirectories_in_sys_net(self): """get_devicelist returns a directory listing for SYS_CLASS_NET.""" write_file(os.path.join(self.sysdir, 'eth0', 'operstate'), 'up') write_file(os.path.join(self.sysdir, 'eth1', 'operstate'), 'up') self.assertItemsEqual(['eth0', 'eth1'], net.get_devicelist())
def test_get_devicelist_empty_with_no_devices_in_sys_net(self): """get_devicelist returns empty directoty listing for SYS_CLASS_NET.""" self.assertEqual([], net.get_devicelist())
def test_get_devicelist_empty_without_sys_net(self): """get_devicelist returns empty list when missing SYS_CLASS_NET.""" self.m_sys_path.return_value = 'idontexist' self.assertEqual([], net.get_devicelist())
def get_link_local_nic(): nics = [f for f in cloudnet.get_devicelist() if cloudnet.is_physical(f)] if not nics: return None return min(nics, key=lambda d: cloudnet.read_sys_net_int(d, 'ifindex'))
def get_devicelist(self) -> list: return net.get_devicelist()