diff --git a/glean/cmd.py b/glean/cmd.py index e58c694..d87011c 100644 --- a/glean/cmd.py +++ b/glean/cmd.py @@ -314,6 +314,289 @@ def write_redhat_interfaces(interfaces, sys_interfaces, distro): return files_to_write +def _write_networkd_interface(name, interfaces, files_struct=dict()): + vlans = [] + for interface in interfaces: + iname = name + # if vlan set interface name to vlan format + if 'vlan_id' in interface: + iname = name + '-vlan' + str(interface['vlan_id']) + vlans.append(iname) + network_file = '/etc/systemd/network/{name}.network'.format(name=iname) + if network_file not in files_struct: + files_struct[network_file] = dict() + if '[Match]' not in files_struct[network_file]: + files_struct[network_file]['[Match]'] = list() + files_struct[network_file]['[Match]'].append( + 'MACAddress={mac_address}'.format( + mac_address=interface['mac_address'] + ) + ) + files_struct[network_file]['[Match]'].append( + 'Name={name}'.format(name=iname) + ) + # define network if needed (basically always) + if ((interface['type'] in ['ipv4_dhcp', 'ipv6_slaac', + 'ipv6_dhcpv6_stateful', 'manual', 'ipv4', 'ipv6']) or + ('vlan_id' in interface) or + ('bond_mode' in interface)): + if '[Network]' not in files_struct[network_file]: + files_struct[network_file]['[Network]'] = list() + # dhcp network, set to yes if both dhcp6 and dhcp4 are set + if interface['type'] == 'ipv4_dhcp': + if 'DHCP=ipv6' in files_struct[network_file]['[Network]']: + files_struct[network_file]['[Network]'].append('DHCP=yes') + else: + files_struct[network_file]['[Network]'].append('DHCP=ipv4') + if interface['type'] == 'ipv6_dhcpv6_stateful': + if 'DHCP=ipv4' in files_struct[network_file]['[Network]']: + files_struct[network_file]['[Network]'].append('DHCP=yes') + else: + files_struct[network_file]['[Network]'].append('DHCP=ipv6') + # slaac can start dhcp6 if the associated RA option is sent to server + if interface['type'] == 'ipv6_slaac': + # we are accepting slaac now, remove the disabling of slaac + if 'IPv6AcceptRA=no' in files_struct[network_file]['[Network]']: + files_struct[network_file]['[Network]'].remove( + 'IPv6AcceptRA=no' + ) + files_struct[network_file]['[Network]'].append('IPv6AcceptRA=yes') + else: + # only disbale slaac if slac is not already enabled + if 'IPv6AcceptRA=yes' not in \ + files_struct[network_file]['[Network]']: + files_struct[network_file]['[Network]'].append( + 'IPv6AcceptRA=no' + ) + # vlan network + + # static network + if interface['type'] in ['ipv4', 'ipv6']: + if 'addresses' not in files_struct[network_file]: + files_struct[network_file]['addresses'] = list() + if interface['type'] == 'ipv4': + files_struct[network_file]['addresses'].append( + 'Address={address}/{cidr}'.format( + address=interface['ip_address'], + cidr=utils.ipv4_netmask_length(interface['netmask']) + ) + ) + if interface['type'] == 'ipv6': + files_struct[network_file]['addresses'].append( + 'Address={address}/{cidr}'.format( + address=interface['ip_address'], + cidr=utils.ipv6_netmask_length(interface['netmask']) + ) + ) + # routes + if 'routes' in interface: + if 'routes' not in files_struct[network_file]: + files_struct[network_file]['routes'] = list() + for route in interface['routes']: + route_destination = None + route_gateway = None + if 'network' in route: + if 'v6' in interface['type']: + cidr = utils.ipv6_netmask_length(route['netmask']) + else: + cidr = utils.ipv4_netmask_length(route['netmask']) + route_destination = 'Destination={network}/{cidr}'.format( + network=route['network'], cidr=cidr + ) + if 'gateway' in route: + route_gateway = 'Gateway={gateway}'.format( + gateway=route['gateway'] + ) + # add route as a dictionary to the routes list + files_struct[network_file]['routes'].append({ + 'route': route_destination, + 'gw': route_gateway + }) + + # create netdev files + if 'bond_mode' or 'vlan_id' in interface: + netdev_file = \ + '/etc/systemd/network/{name}.netdev'.format(name=iname) + if netdev_file not in files_struct: + files_struct[netdev_file] = dict() + if '[NetDev]' not in files_struct[netdev_file]: + files_struct[netdev_file]['[NetDev]'] = list() + files_struct[netdev_file]['[NetDev]'].append( + 'Name={name}'.format(name=iname) + ) + if 'mac_address' in interface: + files_struct[netdev_file]['[NetDev]'].append( + 'MACAddress={mac_address}'.format( + mac_address=interface['mac_address'] + ) + ) + if 'vlan_id' in interface: + files_struct[netdev_file]['[NetDev]'].append('Kind=vlan') + files_struct[netdev_file]['[VLAN]'] = list() + files_struct[netdev_file]['[VLAN]'].append( + 'Id={id}'.format(id=interface['vlan_id']) + ) + if 'bond_mode' in interface: + files_struct[netdev_file]['[NetDev]'].append('Kind=bond') + files_struct[netdev_file]['[Bond]'] = list() + files_struct[netdev_file]['[Bond]'].append( + 'Mode={bond_mode}'.format(bond_mode=interface['bond_mode']) + ) + files_struct[netdev_file]['[Bond]'].append( + 'LACPTransmitRate=fast' + ) + if 'slaves' in interface: + for slave in interface['slaves']: + slave_net_file = \ + '/etc/systemd/network/{name}.network'.format( + name=slave + ) + if slave_net_file not in files_struct: + files_struct[slave_net_file] = dict() + if '[Network]' not in files_struct[slave_net_file]: + files_struct[slave_net_file]['[Network]'] = list() + files_struct[slave_net_file]['[Network]'].append( + 'Bond={name}'.format(name=iname) + ) + if 'bond_xmit_hash_policy' in interface: + files_struct[netdev_file]['[Bond]'].append( + 'TransmitHashPolicy={bond_xmit_hash_policy}'.format( + bond_xmit_hash_policy=interface[ + 'bond_xmit_hash_policy' + ] + ) + ) + if 'bond_miimon' in interface: + files_struct[netdev_file]['[Bond]'].append( + 'MIIMonitorSec={milliseconds}'.format( + milliseconds=interface['bond_miimon'] + ) + ) + + # vlan mapping sucks (forward and reverse) + if vlans: + netdev = vlans[0].split('-')[0] + vlan_master_file = \ + '/etc/systemd/network/{name}.network'.format(name=netdev) + if vlan_master_file not in files_struct: + files_struct[vlan_master_file] = dict() + if '[Network]' not in files_struct[vlan_master_file]: + files_struct[vlan_master_file]['[Network]'] = list() + for vlan in vlans: + files_struct[vlan_master_file]['[Network]'].append('VLAN=' + vlan) + vlan_file = '/etc/systemd/network/{name}.network'.format(name=vlan) + if vlan_file not in files_struct: + files_struct[vlan_file] = dict() + if '[Network]' not in files_struct[vlan_file]: + files_struct[vlan_file]['[Network]'] = list() + files_struct[vlan_file]['[Network]'].append('VLAN=' + vlan) + + return files_struct + + +def write_networkd_interfaces(interfaces, sys_interfaces): + files_to_write = dict() + gen_intfs = {} + files_struct = dict() + # Sort the interfaces by id so that we'll have consistent output order + for iname, interface in sorted( + interfaces.items(), key=lambda x: x[1]['id']): + # sys_interfaces is pruned by --interface; if one of the + # raw_macs (or, *the* MAC for single interfaces) does not + # match as one of the interfaces we want configured, skip + raw_macs = interface.get('raw_macs', [interface['mac_address']]) + if not set(sys_interfaces).intersection(set(raw_macs)): + continue + + if 'bond_mode' in interface: + interface['slaves'] = [ + sys_interfaces[mac] for mac in interface['raw_macs']] + + if 'raw_macs' in interface: + key = tuple(interface['raw_macs']) + if key not in gen_intfs: + gen_intfs[key] = [] + gen_intfs[key].append(interface) + else: + key = (interface['mac_address'],) + if key not in gen_intfs: + gen_intfs[key] = [] + gen_intfs[key].append(interface) + + for raw_macs, interfs in gen_intfs.items(): + if len(raw_macs) == 1: + interface_name = sys_interfaces[raw_macs[0]] + else: + # It is possible our interface does not have a link, so + # fall back to interface id. + interface_name = next( + intf.get('link', intf['id']) for intf in interfs + if 'bond_mode' in intf) + files_struct = _write_networkd_interface( + interface_name, interfs, files_struct) + + for mac, iname in sorted( + sys_interfaces.items(), key=lambda x: x[1]): + if _exists_gentoo_interface(iname): + # This interface already has a config file, move on + log.debug("%s already has config file, skipping" % iname) + continue + if (mac,) in gen_intfs: + # We have a config drive config, move on + log.debug("%s configured via config-drive" % mac) + continue + interface = {'type': 'ipv4_dhcp', 'mac_address': mac} + files_struct = _write_networkd_interface( + iname, [interface], files_struct) + + for networkd_file in files_struct: + file_contents = '# Automatically generated, do not edit\n' + if '[Match]' in files_struct[networkd_file]: + file_contents += '[Match]\n' + for line in sorted(set(files_struct[networkd_file]['[Match]'])): + file_contents += line + file_contents += '\n' + file_contents += '\n' + if '[Network]' in files_struct[networkd_file]: + file_contents += '[Network]\n' + for line in sorted(set(files_struct[networkd_file]['[Network]'])): + file_contents += line + file_contents += '\n' + file_contents += '\n' + if 'addresses' in files_struct[networkd_file]: + for address in files_struct[networkd_file]['addresses']: + file_contents += '[Address]\n' + file_contents += address + '\n\n' + if 'routes' in files_struct[networkd_file]: + for route in files_struct[networkd_file]['routes']: + file_contents += '[Route]\n' + if route['route'] is not None: + file_contents += route['route'] + '\n' + if route['gw'] is not None: + file_contents += route['gw'] + '\n' + file_contents += '\n' + if '[NetDev]' in files_struct[networkd_file]: + file_contents += '[NetDev]\n' + for line in sorted(set(files_struct[networkd_file]['[NetDev]'])): + file_contents += line + file_contents += '\n' + file_contents += '\n' + if '[VLAN]' in files_struct[networkd_file]: + file_contents += '[VLAN]\n' + for line in sorted(set(files_struct[networkd_file]['[VLAN]'])): + file_contents += line + file_contents += '\n' + file_contents += '\n' + if '[Bond]' in files_struct[networkd_file]: + file_contents += '[Bond]\n' + for line in sorted(set(files_struct[networkd_file]['[Bond]'])): + file_contents += line + file_contents += '\n' + file_contents += '\n' + files_to_write['{path}'.format(path=networkd_file)] = file_contents + return files_to_write + + def _exists_gentoo_interface(name): file_to_check = '/etc/conf.d/net.{name}'.format(name=name) return os.path.exists(file_to_check) @@ -773,6 +1056,10 @@ def write_static_network_info( files_to_write.update( write_gentoo_interfaces(interfaces, sys_interfaces) ) + elif args.distro in 'networkd': + files_to_write.update( + write_networkd_interfaces(interfaces, sys_interfaces) + ) else: return False diff --git a/glean/init/glean-networkd.service b/glean/init/glean-networkd.service new file mode 100644 index 0000000..38bdcbf --- /dev/null +++ b/glean/init/glean-networkd.service @@ -0,0 +1,13 @@ +[Unit] +Description=Glean system configuration +Before=systemd-networkd.service +Requires=systemd-networkd.service + +[Service] +Type=oneshot +User=root +ExecStart=%%GLEANSH_PATH%%/glean.sh --distro networkd +RemainAfterExit=true + +[Install] +WantedBy=multi-user.target diff --git a/glean/install.py b/glean/install.py index 7ff8d4d..8d9aaaa 100755 --- a/glean/install.py +++ b/glean/install.py @@ -95,7 +95,6 @@ def main(): if os.path.exists('/etc/gentoo-release'): log.info('installing openrc services') install('glean.openrc', '/etc/init.d/glean') - subprocess.call(['rc-update', 'add', 'glean', 'boot']) # Needs to check for the presence of systemd and systemctl # as apparently some packages may stage systemd init files # when systemd is not present. @@ -111,11 +110,19 @@ def main(): log.info("Installing systemd services") log.info("glean.sh in %s" % p) - install( - 'glean@.service', - '/usr/lib/systemd/system/glean@.service', - mode='0644', - replacements={'GLEANSH_PATH': p}) + if os.path.exists('/etc/gentoo-release'): + install( + 'glean-networkd.service', + '/lib/systemd/system/glean.service', + mode='0644', + replacements={'GLEANSH_PATH': p}) + subprocess.call(['systemctl', 'enable', 'glean.service']) + else: + install( + 'glean@.service', + '/usr/lib/systemd/system/glean@.service', + mode='0644', + replacements={'GLEANSH_PATH': p}) install( 'glean-udev.rules', '/etc/udev/rules.d/99-glean.rules', @@ -123,12 +130,8 @@ def main(): elif os.path.exists('/etc/init'): log.info("Installing upstart services") install('glean.conf', '/etc/init/glean.conf') - elif os.path.exists('/etc/gentoo-release'): - # If installing on Gentoo and if systemd or upstart is not - # detected, then prevent the installation of sysv init scripts - # on Gentoo, which would overwrite the OpenRC init scripts as - # the sysv init script uses the same path. - pass + elif os.path.exists('/sbin/rc-update'): + subprocess.call(['rc-update', 'add', 'glean', 'boot']) else: log.info("Installing sysv services") install('glean.init', '/etc/init.d/glean') diff --git a/glean/tests/fixtures/test/hp.networkd.network.out b/glean/tests/fixtures/test/hp.networkd.network.out new file mode 100644 index 0000000..94a1985 --- /dev/null +++ b/glean/tests/fixtures/test/hp.networkd.network.out @@ -0,0 +1,30 @@ +### Write /etc/systemd/network/eth0.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:01:62:86 +Name=eth0 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no + +### Write /etc/systemd/network/eth1.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:05:7b:06 +Name=eth1 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no + +### Write /etc/systemd/network/eth3.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:12:a4:bb +Name=eth3 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no + diff --git a/glean/tests/fixtures/test/liberty.networkd.network.out b/glean/tests/fixtures/test/liberty.networkd.network.out new file mode 100644 index 0000000..957fbeb --- /dev/null +++ b/glean/tests/fixtures/test/liberty.networkd.network.out @@ -0,0 +1,209 @@ +### Write /etc/resolv.conf +nameserver 72.3.128.241 +nameserver 72.3.128.240 +### Write /etc/systemd/network/eth0.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:01:62:86 +Name=eth0 + +[Network] +IPv6AcceptRA=no + +[Address] +Address=23.253.229.154/24 + +[Route] +Destination=0.0.0.0/0 +Gateway=23.253.229.1 + +### Write /etc/systemd/network/eth1.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:05:7b:06 +Name=eth1 + +[Network] +IPv6AcceptRA=no + +[Address] +Address=10.208.169.118/19 + +[Route] +Destination=10.176.0.0/12 +Gateway=10.208.160.1 + +[Route] +Destination=10.208.0.0/12 +Gateway=10.208.160.1 + +### Write /etc/systemd/network/eth3.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:12:a4:bb +Name=eth3 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no + +### Write /etc/systemd/network/eth4.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:12:a4:bc +Name=eth4 + +[Network] +IPv6AcceptRA=no +VLAN=eth4-vlan25 +VLAN=eth4-vlan26 + +### Write /etc/systemd/network/eth4-vlan25.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:12:a4:bc +Name=eth4-vlan25 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no +VLAN=eth4-vlan25 + +### Write /etc/systemd/network/eth4-vlan25.netdev +# Automatically generated, do not edit +[NetDev] +Kind=vlan +MACAddress=bc:76:4e:12:a4:bc +Name=eth4-vlan25 + +[VLAN] +Id=25 + +### Write /etc/systemd/network/eth4-vlan26.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:12:a4:bd +Name=eth4-vlan26 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no +VLAN=eth4-vlan26 + +### Write /etc/systemd/network/eth4-vlan26.netdev +# Automatically generated, do not edit +[NetDev] +Kind=vlan +MACAddress=bc:76:4e:12:a4:bd +Name=eth4-vlan26 + +[VLAN] +Id=26 + +### Write /etc/systemd/network/eth5.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:05:7b:13 +Name=eth5 + +[Network] +Bond=bond0 +IPv6AcceptRA=no + +### Write /etc/systemd/network/eth6.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:05:7b:14 +Name=eth6 + +[Network] +Bond=bond0 +IPv6AcceptRA=no + +### Write /etc/systemd/network/bond0.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:05:7b:13 +Name=bond0 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no + +### Write /etc/systemd/network/bond0.netdev +# Automatically generated, do not edit +[NetDev] +Kind=bond +MACAddress=bc:76:4e:05:7b:13 +Name=bond0 + +[Bond] +LACPTransmitRate=fast +MIIMonitorSec=100 +Mode=802.3ad +TransmitHashPolicy=layer3+4 + +### Write /etc/systemd/network/eth7.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:05:7b:15 +Name=eth7 + +[Network] +Bond=bond1 +IPv6AcceptRA=no + +### Write /etc/systemd/network/eth8.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:05:7b:16 +Name=eth8 + +[Network] +Bond=bond1 +IPv6AcceptRA=no + +### Write /etc/systemd/network/bond1.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:05:7b:15 +Name=bond1 + +[Network] +IPv6AcceptRA=no +VLAN=bond1-vlan27 + +### Write /etc/systemd/network/bond1.netdev +# Automatically generated, do not edit +[NetDev] +Kind=bond +MACAddress=bc:76:4e:05:7b:15 +Name=bond1 + +[Bond] +LACPTransmitRate=fast +MIIMonitorSec=100 +Mode=802.3ad +TransmitHashPolicy=layer3+4 + +### Write /etc/systemd/network/bond1-vlan27.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:12:a4:be +Name=bond1-vlan27 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no +VLAN=bond1-vlan27 + +### Write /etc/systemd/network/bond1-vlan27.netdev +# Automatically generated, do not edit +[NetDev] +Kind=vlan +MACAddress=bc:76:4e:12:a4:be +Name=bond1-vlan27 + +[VLAN] +Id=27 + diff --git a/glean/tests/fixtures/test/nokey.networkd.network.out b/glean/tests/fixtures/test/nokey.networkd.network.out new file mode 100644 index 0000000..94a1985 --- /dev/null +++ b/glean/tests/fixtures/test/nokey.networkd.network.out @@ -0,0 +1,30 @@ +### Write /etc/systemd/network/eth0.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:01:62:86 +Name=eth0 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no + +### Write /etc/systemd/network/eth1.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:05:7b:06 +Name=eth1 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no + +### Write /etc/systemd/network/eth3.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:12:a4:bb +Name=eth3 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no + diff --git a/glean/tests/fixtures/test/rax-iad.networkd.network.out b/glean/tests/fixtures/test/rax-iad.networkd.network.out new file mode 100644 index 0000000..5d53562 --- /dev/null +++ b/glean/tests/fixtures/test/rax-iad.networkd.network.out @@ -0,0 +1,50 @@ +### Write /etc/resolv.conf +nameserver 69.20.0.196 +nameserver 69.20.0.164 +### Write /etc/systemd/network/eth0.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:20:d7:2f +Name=eth0 + +[Network] +IPv6AcceptRA=no + +[Address] +Address=146.20.110.113/24 + +[Address] +Address=2001:4802:7807:103:be76:4eff:fe20:d72f/64 + +[Route] +Destination=0.0.0.0/0 +Gateway=146.20.110.1 + +[Route] +Destination=::/0 +Gateway=fe80::def + +[Route] +Destination=fd30::/48 +Gateway=fe80::f001 + +### Write /etc/systemd/network/eth1.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:20:d7:33 +Name=eth1 + +[Network] +IPv6AcceptRA=no + +[Address] +Address=10.210.32.174/19 + +[Route] +Destination=10.176.0.0/12 +Gateway=10.210.32.1 + +[Route] +Destination=10.208.0.0/12 +Gateway=10.210.32.1 + diff --git a/glean/tests/fixtures/test/rax.networkd.network.out b/glean/tests/fixtures/test/rax.networkd.network.out new file mode 100644 index 0000000..9139e5a --- /dev/null +++ b/glean/tests/fixtures/test/rax.networkd.network.out @@ -0,0 +1,49 @@ +### Write /etc/resolv.conf +nameserver 72.3.128.241 +nameserver 72.3.128.240 +### Write /etc/systemd/network/eth0.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:01:62:86 +Name=eth0 + +[Network] +IPv6AcceptRA=no + +[Address] +Address=23.253.229.154/24 + +[Route] +Destination=0.0.0.0/0 +Gateway=23.253.229.1 + +### Write /etc/systemd/network/eth1.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:05:7b:06 +Name=eth1 + +[Network] +IPv6AcceptRA=no + +[Address] +Address=10.208.169.118/19 + +[Route] +Destination=10.176.0.0/12 +Gateway=10.208.160.1 + +[Route] +Destination=10.208.0.0/12 +Gateway=10.208.160.1 + +### Write /etc/systemd/network/eth3.network +# Automatically generated, do not edit +[Match] +MACAddress=bc:76:4e:12:a4:bb +Name=eth3 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no + diff --git a/glean/tests/test_glean.py b/glean/tests/test_glean.py index fbcfed3..75d9b15 100644 --- a/glean/tests/test_glean.py +++ b/glean/tests/test_glean.py @@ -30,7 +30,7 @@ sample_data_path = os.path.join( os.path.dirname(os.path.realpath(__file__)), 'fixtures') distros = ['Ubuntu', 'Debian', 'Fedora', 'RedHat', 'CentOS', 'Gentoo', - 'openSUSE'] + 'openSUSE', 'networkd'] styles = ['hp', 'rax', 'rax-iad', 'liberty', 'nokey'] ips = {'hp': '127.0.1.1', 'rax': '23.253.229.154', @@ -81,8 +81,10 @@ class TestGlean(base.BaseTestCase): # them in file_handle_mocks{} so we can assert they were # called later mock_dirs = ('/etc/network', '/etc/sysconfig/network-scripts', - '/etc/conf.d', '/etc/init.d', '/etc/sysconfig/network') - mock_files = ('/etc/resolv.conf', '/etc/hostname', '/etc/hosts') + '/etc/conf.d', '/etc/init.d', '/etc/sysconfig/network', + '/etc/systemd/network') + mock_files = ('/etc/resolv.conf', '/etc/hostname', '/etc/hosts', + '/bin/systemctl') if (path.startswith(mock_dirs) or path in mock_files): try: mock_handle = self.file_handle_mocks[path] @@ -126,14 +128,16 @@ class TestGlean(base.BaseTestCase): if path in ('/etc/sysconfig/network-scripts/ifcfg-eth2', '/etc/network/interfaces.d/eth2.cfg', '/etc/conf.d/net.eth2', - '/etc/sysconfig/network/ifcfg-eth2'): + '/etc/sysconfig/network/ifcfg-eth2', + '/etc/systemd/network/eth2.network'): # Pretend this file exists, we need to test skipping # pre-existing config files return True elif (path.startswith(('/etc/sysconfig/network-scripts/', '/etc/sysconfig/network/', '/etc/network/interfaces.d/', - '/etc/conf.d/'))): + '/etc/conf.d/', + '/etc/systemd/network/'))): # Don't check the host os's network config return False return real_path_exists(path) diff --git a/glean/utils.py b/glean/utils.py index a5a59e4..eee8b6f 100644 --- a/glean/utils.py +++ b/glean/utils.py @@ -29,3 +29,13 @@ def ipv6_netmask_length(netmask): except: raise SyntaxError('Bad Netmask') return count + + +# code to convert netmask ip to cidr number +# https://stackoverflow.com/a/43885814 +def ipv4_netmask_length(netmask): + ''' + :param netmask: netmask ip addr (eg: 255.255.255.0) + :return: equivalent cidr number to given netmask ip (eg: 24) + ''' + return sum([bin(int(x)).count('1') for x in netmask.split('.')])