def collect(cls, what): fname = cls.location[what] try: # send signal to generate the configuration file pid = util.read_file(cls.location['pid']) os.kill(int(pid), cls._signal[what]) # shoud look for file size change ? sleep(0.2) return util.read_file(fname) except Exception: name = cls._name[what] raise VRRPError(f'VRRP {name} is not available') finally: if os.path.exists(fname): os.remove(fname)
def test_ip_options(self): """ test IP options like arp """ if not self._test_ip: return None for interface in self._interfaces: arp_tmo = '300' path = self._base_path + [interface] for option in self._options.get(interface, []): self.session.set(path + option.split()) # Options self.session.set(path + ['ip', 'arp-cache-timeout', arp_tmo]) self.session.set(path + ['ip', 'disable-arp-filter']) self.session.set(path + ['ip', 'enable-arp-accept']) self.session.set(path + ['ip', 'enable-arp-announce']) self.session.set(path + ['ip', 'enable-arp-ignore']) self.session.set(path + ['ip', 'enable-proxy-arp']) self.session.set(path + ['ip', 'proxy-arp-pvlan']) self.session.set(path + ['ip', 'source-validation', 'loose']) self.session.commit() for interface in self._interfaces: tmp = read_file( f'/proc/sys/net/ipv4/neigh/{interface}/base_reachable_time_ms' ) self.assertEqual(tmp, str( (int(arp_tmo) * 1000))) # tmo value is in milli seconds tmp = read_file( f'/proc/sys/net/ipv4/conf/{interface}/arp_filter') self.assertEqual('0', tmp) tmp = read_file( f'/proc/sys/net/ipv4/conf/{interface}/arp_accept') self.assertEqual('1', tmp) tmp = read_file( f'/proc/sys/net/ipv4/conf/{interface}/arp_announce') self.assertEqual('1', tmp) tmp = read_file( f'/proc/sys/net/ipv4/conf/{interface}/arp_ignore') self.assertEqual('1', tmp) tmp = read_file( f'/proc/sys/net/ipv4/conf/{interface}/proxy_arp') self.assertEqual('1', tmp) tmp = read_file( f'/proc/sys/net/ipv4/conf/{interface}/proxy_arp_pvlan') self.assertEqual('1', tmp) tmp = read_file( f'/proc/sys/net/ipv4/conf/{interface}/rp_filter') self.assertEqual('2', tmp)
def get_dhcp6c_config_value(interface, key): tmp = read_file(dhcp6c_config_file.format(interface)) tmp = re.findall(r'\n?{}\s+(.*)'.format(key), tmp) out = [] for item in tmp: out.append(item.replace(';','')) return out
def test_add_address_single(self): """ derived method to check if member interfaces are enslaved properly """ super().test_add_address_single() for interface in self._interfaces: slaves = read_file( f'/sys/class/net/{interface}/bonding/slaves').split() self.assertListEqual(slaves, self._members)
def get_full_version_data(fname=version_file): version_data = get_version_data(fname) # Get system architecture (well, kernel architecture rather) version_data['system_arch'], _ = popen('uname -m', stderr=DEVNULL) hypervisor, code = popen('hvinfo', stderr=DEVNULL) if code == 1: # hvinfo returns 1 if it cannot detect any hypervisor version_data['system_type'] = 'bare metal' else: version_data['system_type'] = f"{hypervisor} guest" # Get boot type, it can be livecd, installed image, or, possible, a system installed # via legacy "install system" mechanism # In installed images, the squashfs image file is named after its image version, # while on livecd it's just "filesystem.squashfs", that's how we tell a livecd boot # from an installed image boot_via = "installed image" if run(""" grep -e '^overlay.*/filesystem.squashfs' /proc/mounts >/dev/null""" ) == 0: boot_via = "livecd" elif run(""" grep '^overlay /' /proc/mounts >/dev/null """) != 0: boot_via = "legacy non-image installation" version_data['boot_via'] = boot_via # Get hardware details from DMI dmi = '/sys/class/dmi/id' version_data['hardware_vendor'] = read_file(dmi + '/sys_vendor', 'Unknown') version_data['hardware_model'] = read_file(dmi + '/product_name', 'Unknown') # These two assume script is run as root, normal users can't access those files subsystem = '/sys/class/dmi/id/subsystem/id' version_data['hardware_serial'] = read_file(subsystem + '/product_serial', 'Unknown') version_data['hardware_uuid'] = read_file(subsystem + '/product_uuid', 'Unknown') return version_data
def disabled(cls): if not os.path.exists(cls.location['vyos']): return [] disabled = [] config = json.loads(util.read_file(cls.location['vyos'])) # add disabled groups to the list for group in config['vrrp_groups']: if group['disable']: disabled.append([ group['name'], group['interface'], group['vrid'], 'DISABLED', '' ]) # return list with disabled instances return disabled
def get_config_value(key): tmp = read_file(SNMPD_CONF) tmp = re.findall(r'\n?{}\s+(.*)'.format(key), tmp) return tmp[0]
def apply(vrf_config): # Documentation # # - https://github.com/torvalds/linux/blob/master/Documentation/networking/vrf.txt # - https://github.com/Mellanox/mlxsw/wiki/Virtual-Routing-and-Forwarding-(VRF) # - https://github.com/Mellanox/mlxsw/wiki/L3-Tunneling # - https://netdevconf.info/1.1/proceedings/slides/ahern-vrf-tutorial.pdf # - https://netdevconf.info/1.2/slides/oct6/02_ahern_what_is_l3mdev_slides.pdf # set the default VRF global behaviour bind_all = vrf_config['bind_to_all'] if read_file('/proc/sys/net/ipv4/tcp_l3mdev_accept') != bind_all: _cmd(f'sysctl -wq net.ipv4.tcp_l3mdev_accept={bind_all}') _cmd(f'sysctl -wq net.ipv4.udp_l3mdev_accept={bind_all}') for vrf in vrf_config['vrf_remove']: name = vrf['name'] if os.path.isdir(f'/sys/class/net/{name}'): _cmd( f'sudo ip -4 route del vrf {name} unreachable default metric 4278198272' ) _cmd( f'sudo ip -6 route del vrf {name} unreachable default metric 4278198272' ) _cmd(f'ip link delete dev {name}') for vrf in vrf_config['vrf_add']: name = vrf['name'] table = vrf['table'] if not os.path.isdir(f'/sys/class/net/{name}'): # For each VRF apart from your default context create a VRF # interface with a separate routing table _cmd(f'ip link add {name} type vrf table {table}') # Start VRf _cmd(f'ip link set dev {name} up') # The kernel Documentation/networking/vrf.txt also recommends # adding unreachable routes to the VRF routing tables so that routes # afterwards are taken. _cmd( f'ip -4 route add vrf {name} unreachable default metric 4278198272' ) _cmd( f'ip -6 route add vrf {name} unreachable default metric 4278198272' ) # set VRF description for e.g. SNMP monitoring Interface(name).set_alias(vrf['description']) # Linux routing uses rules to find tables - routing targets are then # looked up in those tables. If the lookup got a matching route, the # process ends. # # TL;DR; first table with a matching entry wins! # # You can see your routing table lookup rules using "ip rule", sadly the # local lookup is hit before any VRF lookup. Pinging an addresses from the # VRF will usually find a hit in the local table, and never reach the VRF # routing table - this is usually not what you want. Thus we will # re-arrange the tables and move the local lookup furhter down once VRFs # are enabled. # get current preference on local table local_pref = [ r.get('priority') for r in list_rules() if r.get('table') == 'local' ][0] # change preference when VRFs are enabled and local lookup table is default if not local_pref and vrf_config['vrf_add']: for af in ['-4', '-6']: _cmd(f'ip {af} rule add pref 32765 table local') _cmd(f'ip {af} rule del pref 0') # return to default lookup preference when no VRF is configured if not vrf_config['vrf_add']: for af in ['-4', '-6']: _cmd(f'ip {af} rule add pref 0 table local') _cmd(f'ip {af} rule del pref 32765') # clean out l3mdev-table rule if present if 1000 in [ r.get('priority') for r in list_rules() if r.get('priority') == 1000 ]: _cmd(f'ip {af} rule del pref 1000') return None
def get_name_servers(): resolv_conf = util.read_file(RESOLV_CONF) return re.findall(r'\n?nameserver\s+(.*)', resolv_conf)
def get_config_value(intf, key): tmp = read_file(f'/run/wpa_supplicant/{intf}.conf') tmp = re.findall(r'\n?{}=(.*)'.format(key), tmp) return tmp[0]
def get_config_value(key): tmp = read_file(RADVD_CONF) tmp = re.findall(r'\n?{}\s+(.*)'.format(key), tmp) return tmp[0].split()[0].replace(';', '')
def get_config_value(key): tmp = read_file(DDCLIENT_CONF) tmp = re.findall(r'\n?{}=+(.*)'.format(key), tmp) tmp = tmp[0].rstrip(',') return tmp
def test_pppoe_dhcpv6pd(self): """ Check if PPPoE dialer can be configured with DHCPv6-PD """ address = '1' sla_id = '0' sla_len = '8' for interface in self._interfaces: self.session.set(base_path + [interface, 'authentication', 'user', 'vyos']) self.session.set(base_path + [interface, 'authentication', 'password', 'vyos']) self.session.set(base_path + [interface, 'default-route', 'none']) self.session.set(base_path + [interface, 'no-peer-dns']) self.session.set( base_path + [interface, 'source-interface', self._source_interface]) self.session.set(base_path + [interface, 'ipv6', 'enable']) # prefix delegation stuff dhcpv6_pd_base = base_path + [ interface, 'dhcpv6-options', 'pd', '0' ] self.session.set(dhcpv6_pd_base + ['length', '56']) self.session.set( dhcpv6_pd_base + ['interface', self._source_interface, 'address', address]) self.session.set( dhcpv6_pd_base + ['interface', self._source_interface, 'sla-id', sla_id]) # commit changes self.session.commit() # verify "normal" PPPoE value - 1492 is default MTU tmp = get_config_value(interface, 'mtu')[1] self.assertEqual(tmp, '1492') tmp = get_config_value(interface, 'user')[1].replace('"', '') self.assertEqual(tmp, 'vyos') tmp = get_config_value(interface, 'password')[1].replace('"', '') self.assertEqual(tmp, 'vyos') for param in ['+ipv6', 'ipv6cp-use-ipaddr']: tmp = get_config_value(interface, param)[0] self.assertEqual(tmp, param) # verify DHCPv6 prefix delegation # will return: ['delegation', '::/56 infinity;'] tmp = get_dhcp6c_config_value( interface, 'prefix')[1].split()[0] # mind the whitespace self.assertEqual(tmp, '::/56') tmp = get_dhcp6c_config_value(interface, 'prefix-interface')[0].split()[0] self.assertEqual(tmp, self._source_interface) tmp = get_dhcp6c_config_value(interface, 'ifid')[0] self.assertEqual(tmp, address) tmp = get_dhcp6c_config_value(interface, 'sla-id')[0] self.assertEqual(tmp, sla_id) tmp = get_dhcp6c_config_value(interface, 'sla-len')[0] self.assertEqual(tmp, sla_len) # Check if ppp process is running in the interface in question running = False for p in process_iter(): if "pppd" in p.name(): running = True self.assertTrue(running) # We can not check if wide-dhcpv6 process is running as it is started # after the PPP interface gets a link to the ISP - but we can see if # it would be started by the scripts tmp = read_file(f'/etc/ppp/ipv6-up.d/1000-vyos-pppoe-{interface}') tmp = re.findall(f'systemctl start dhcp6c@{interface}.service', tmp) self.assertTrue(tmp)