def test_from_json_defroute(self): data = '{"type": "interface", "name": "em1", "use_dhcp": true}' interface1 = objects.object_from_json(json.loads(data)) data = """{ "type": "interface", "name": "em1", "use_dhcp": true, "defroute": false } """ interface2 = objects.object_from_json(json.loads(data)) self.assertTrue(interface1.defroute) self.assertFalse(interface2.defroute)
def test_from_json_with_addresses(self): data = """{ "type": "interface", "name": "em1", "use_dhcp": false, "mtu": 1501, "addresses": [{ "ip_netmask": "192.0.2.1/24" }], "routes": [{ "next_hop": "192.0.2.1", "ip_netmask": "192.0.2.1/24" }] } """ interface = objects.object_from_json(json.loads(data)) self.assertEqual("em1", interface.name) self.assertEqual(False, interface.use_dhcp) self.assertEqual(False, interface.use_dhcpv6) self.assertEqual(1501, interface.mtu) address1 = interface.v4_addresses()[0] self.assertEqual("192.0.2.1", address1.ip) self.assertEqual("255.255.255.0", address1.netmask) route1 = interface.routes[0] self.assertEqual("192.0.2.1", route1.next_hop) self.assertEqual("192.0.2.1/24", route1.ip_netmask)
def test_from_json_dhcp(self): data = '{"type": "vlan", "device": "em1", "vlan_id": 16,' \ '"use_dhcp": true}' vlan = objects.object_from_json(json.loads(data)) self.assertEqual("em1", vlan.device) self.assertEqual(16, vlan.vlan_id) self.assertEqual(True, vlan.use_dhcp)
def test_from_json_primary_interface(self): data = """{ "type": "ovs_bridge", "name": "br-foo", "use_dhcp": true, "members": [ { "type": "interface", "name": "em1", "primary": "true" }, { "type": "interface", "name": "em2" }] } """ bridge = objects.object_from_json(json.loads(data)) self.assertEqual("br-foo", bridge.name) self.assertEqual(True, bridge.use_dhcp) self.assertEqual("em1", bridge.primary_interface_name) interface1 = bridge.members[0] self.assertEqual("em1", interface1.name) self.assertEqual(True, interface1.ovs_port) self.assertEqual(True, interface1.primary) self.assertEqual("br-foo", interface1.bridge_name) interface2 = bridge.members[1] self.assertEqual("em2", interface2.name) self.assertEqual(True, interface2.ovs_port) self.assertEqual("br-foo", interface2.bridge_name)
def test_from_json(self): data = """{ "type": "ovs_bridge", "name": "br-foo", "members": [{ "type": "ovs_tunnel", "name": "tun0", "tunnel_type": "gre", "ovs_options": [ "remote_ip=192.168.1.1" ], "ovs_extra": [ "ovs extra" ] }] } """ bridge = objects.object_from_json(json.loads(data)) self.assertEqual("br-foo", bridge.name) tun0 = bridge.members[0] self.assertEqual("tun0", tun0.name) self.assertFalse(tun0.ovs_port) self.assertEqual("br-foo", tun0.bridge_name) self.assertEqual("gre", tun0.tunnel_type) self.assertEqual( ["options:remote_ip=192.168.1.1"], tun0.ovs_options) self.assertEqual( ["ovs extra"], tun0.ovs_extra)
def test_from_json_dhcp_with_nic1_nic2(self): def test_numbered_nics(): return {"nic1": "em1", "nic2": "em2"} self.stubs.Set(objects, '_numbered_nics', test_numbered_nics) data = """{ "type": "ovs_bond", "name": "bond1", "use_dhcp": true, "members": [ { "type": "interface", "name": "nic1" }, { "type": "interface", "name": "nic2" } ] } """ bridge = objects.object_from_json(json.loads(data)) self.assertEqual("bond1", bridge.name) self.assertEqual(True, bridge.use_dhcp) interface1 = bridge.members[0] self.assertEqual("em1", interface1.name) interface2 = bridge.members[1] self.assertEqual("em2", interface2.name)
def test_from_json_dhcp_nic1(self): def test_numbered_nics(): return {"nic1": "em3"} self.stubs.Set(objects, '_numbered_nics', test_numbered_nics) data = '{"type": "interface", "name": "nic1", "use_dhcp": true}' interface = objects.object_from_json(json.loads(data)) self.assertEqual("em3", interface.name) self.assertEqual(True, interface.use_dhcp)
def test_from_json_dns_servers(self): data = """{ "type": "interface", "name": "em1", "use_dhcp": true, "dns_servers": ["1.2.3.4"] } """ interface1 = objects.object_from_json(json.loads(data)) self.assertEqual(["1.2.3.4"], interface1.dns_servers)
def test_from_json_dhclient_args(self): data = """{ "type": "interface", "name": "em1", "use_dhcp": true, "dhclient_args": "--foobar" } """ interface1 = objects.object_from_json(json.loads(data)) self.assertEqual("--foobar", interface1.dhclient_args)
def test_from_json_dhcp_nic1(self): def test_numbered_nics(): return {"nic1": "em4"} self.stubs.Set(objects, '_numbered_nics', test_numbered_nics) data = '{"type": "vlan", "device": "nic1", "vlan_id": 16,' \ '"use_dhcp": true}' vlan = objects.object_from_json(json.loads(data)) self.assertEqual("em4", vlan.device) self.assertEqual(16, vlan.vlan_id) self.assertEqual(True, vlan.use_dhcp)
def test_interface_from_json(self): data = """{ "type": "ivs_bridge", "members": [{ "type": "interface", "name": "nic2" }] } """ bridge = objects.object_from_json(json.loads(data)) self.assertEqual("ivs", bridge.name) interface1 = bridge.members[0] self.assertEqual("nic2", interface1.name) self.assertEqual(False, interface1.ovs_port) self.assertEqual("ivs", interface1.ivs_bridge_name)
def main(argv=sys.argv): opts = parse_opts(argv) configure_logger(opts.verbose, opts.debug) logger.info('Using config file at: %s' % opts.config_file) iface_array = [] provider = None if opts.provider: if opts.provider == 'ifcfg': provider = impl_ifcfg.IfcfgNetConfig() elif opts.provider == 'eni': provider = impl_eni.ENINetConfig() elif opts.provider == 'iproute': provider = impl_iproute.IPRouteNetConfig() else: logger.error('Invalid provider specified.') return 1 else: if os.path.exists('/etc/sysconfig/network-scripts/'): provider = impl_ifcfg.IfcfgNetConfig() elif os.path.exists('/etc/network/'): provider = impl_eni.ENINetConfig() else: logger.error('Unable to set provider for this operating system.') return 1 if os.path.exists(opts.config_file): with open(opts.config_file) as cf: iface_array = yaml.load(cf.read()).get("network_config") logger.debug('network_config JSON: %s' % str(iface_array)) else: logger.error('No config file exists at: %s' % opts.config_file) return 1 if not isinstance(iface_array, list): logger.error('No interfaces defined in config: %s' % opts.config_file) return 1 for iface_json in iface_array: obj = objects.object_from_json(iface_json) provider.add_object(obj) files_changed = provider.apply(noop=opts.noop, cleanup=opts.cleanup) if opts.noop: for location, data in files_changed.iteritems(): print "File: %s\n" % location print data print "----" return 0
def test_from_json_dhcp(self): data = """{ "type": "linux_bridge", "name": "br-foo", "use_dhcp": true, "members": [{ "type": "interface", "name": "em1" }] } """ bridge = objects.object_from_json(json.loads(data)) self.assertEqual("br-foo", bridge.name) self.assertTrue(bridge.use_dhcp) interface1 = bridge.members[0] self.assertEqual("em1", interface1.name) self.assertFalse(interface1.ovs_port) self.assertEqual("br-foo", interface1.linux_bridge_name)
def test_from_json_dhcp_with_nic1(self): def test_numbered_nics(): return {"nic1": "em5"} self.stubs.Set(objects, '_numbered_nics', test_numbered_nics) data = """{ "type": "ovs_bridge", "name": "br-foo", "use_dhcp": true, "members": [{ "type": "interface", "name": "nic1" }] } """ bridge = objects.object_from_json(json.loads(data)) self.assertEqual("br-foo", bridge.name) self.assertEqual(True, bridge.use_dhcp) interface1 = bridge.members[0] self.assertEqual("em5", interface1.name) self.assertEqual(True, interface1.ovs_port) self.assertEqual("br-foo", interface1.bridge_name)
def test_from_json_dhcp(self): data = """{ "type": "ovs_bond", "name": "bond1", "use_dhcp": true, "members": [ { "type": "interface", "name": "em1" }, { "type": "interface", "name": "em2" } ] } """ bridge = objects.object_from_json(json.loads(data)) self.assertEqual("bond1", bridge.name) self.assertEqual(True, bridge.use_dhcp) interface1 = bridge.members[0] self.assertEqual("em1", interface1.name) interface2 = bridge.members[1] self.assertEqual("em2", interface2.name)
def test_from_json_dhcp(self): data = """{ "type": "linux_bond", "name": "bond1", "use_dhcp": true, "members": [ { "type": "interface", "name": "em1" }, { "type": "interface", "name": "em2" } ] } """ bridge = objects.object_from_json(json.loads(data)) self.assertEqual("bond1", bridge.name) self.assertTrue(bridge.use_dhcp) interface1 = bridge.members[0] self.assertEqual("em1", interface1.name) interface2 = bridge.members[1] self.assertEqual("em2", interface2.name)
def main(argv=sys.argv, main_logger=None): opts = parse_opts(argv) if not main_logger: main_logger = common.configure_logger(log_file=not opts.noop) common.logger_level(main_logger, opts.verbose, opts.debug) main_logger.info(f"Using config file at: {opts.config_file}") iface_array = [] configure_sriov = False sriovpf_member_of_bond_ovs_port_list = [] provider = None if opts.provider: if opts.provider == 'ifcfg': provider = impl_ifcfg.IfcfgNetConfig(noop=opts.noop, root_dir=opts.root_dir) elif opts.provider == 'eni': provider = impl_eni.ENINetConfig(noop=opts.noop, root_dir=opts.root_dir) elif opts.provider == 'iproute': provider = impl_iproute.IPRouteNetConfig(noop=opts.noop, root_dir=opts.root_dir) else: main_logger.error("Invalid provider specified.") return 1 else: if os.path.exists('%s/etc/sysconfig/network-scripts/' % opts.root_dir): provider = impl_ifcfg.IfcfgNetConfig(noop=opts.noop, root_dir=opts.root_dir) elif os.path.exists('%s/etc/network/' % opts.root_dir): provider = impl_eni.ENINetConfig(noop=opts.noop, root_dir=opts.root_dir) else: main_logger.error("Unable to set provider for this operating " "system.") return 1 # Read the interface mapping file, if it exists # This allows you to override the default network naming abstraction # mappings by specifying a specific nicN->name or nicN->MAC mapping if os.path.exists(opts.mapping_file): main_logger.info(f"Using mapping file at: {opts.mapping_file}") with open(opts.mapping_file) as cf: iface_map = yaml.safe_load(cf.read()) iface_mapping = iface_map.get("interface_mapping") main_logger.debug(f"interface_mapping: {iface_mapping}") persist_mapping = opts.persist_mapping main_logger.debug(f"persist_mapping: {persist_mapping}") else: main_logger.info("Not using any mapping file.") iface_mapping = None persist_mapping = False # If --interfaces is specified, either return the real name of the # interfaces specified, or return the map of all nic abstractions/names. if opts.interfaces is not None: reported_nics = {} mapped_nics = objects.mapped_nics(iface_mapping) retval = 0 if len(opts.interfaces) > 0: for requested_nic in opts.interfaces: found = False # Check to see if requested iface is a mapped NIC name. if requested_nic in mapped_nics: reported_nics[requested_nic] = mapped_nics[requested_nic] found = True # Check to see if the requested iface is a real NIC name if requested_nic in mapped_nics.values(): if found is True: # Name matches alias and real NIC # (return the mapped NIC, but warn of overlap). main_logger.warning(f"{requested_nic} overlaps with " "real NIC name.") else: reported_nics[requested_nic] = requested_nic found = True if not found: retval = 1 if reported_nics: main_logger.debug("Interface mapping requested for interface: " "%s" % reported_nics.keys()) else: main_logger.debug("Interface mapping requested for all interfaces") reported_nics = mapped_nics # Return the report on the mapped NICs. If all NICs were found, exit # cleanly, otherwise exit with status 1. main_logger.debug("Interface report requested, exiting after report.") print(json.dumps(reported_nics)) return retval # Read config file containing network configs to apply if os.path.exists(opts.config_file): try: with open(opts.config_file) as cf: iface_array = yaml.safe_load(cf.read()).get("network_config") main_logger.debug(f"network_config: {iface_array}") except IOError: main_logger.error(f"Error reading file: {opts.config_file}") return 1 else: main_logger.error(f"No config file exists at: {opts.config_file}") return 1 if not isinstance(iface_array, list): main_logger.error("No interfaces defined in config: " f"{opts.config_file}") return 1 for iface_json in iface_array: if iface_json.get('type') != 'route_table': iface_json.update({'nic_mapping': iface_mapping}) iface_json.update({'persist_mapping': persist_mapping}) validation_errors = validator.validate_config(iface_array) if validation_errors: if opts.exit_on_validation_errors: main_logger.error('\n'.join(validation_errors)) return 1 else: main_logger.warning('\n'.join(validation_errors)) # Look for the presence of SriovPF types in the first parse of the json # if SriovPFs exists then PF devices needs to be configured so that the VF # devices are created. # The VFs will not be available now and an exception # SriovVfNotFoundException will be raised while fetching the device name. # After the first parse the SR-IOV PF devices would be configured and the # VF devices would be created. # In the second parse, all other objects shall be added for iface_json in iface_array: try: obj = objects.object_from_json(iface_json) except utils.SriovVfNotFoundException: continue if isinstance(obj, objects.SriovPF): configure_sriov = True provider.add_object(obj) elif hasattr(obj, 'members') and obj.members is not None: if check_configure_sriov(obj): configure_sriov = True provider.add_object(obj) sriovpf_member_of_bond_ovs_port_list.extend( get_sriovpf_member_of_bond_ovs_port(obj)) # After reboot, shared_block for pf interface in switchdev mode will be # missing in case IPv6 is enabled on the slaves of the bond and that bond # is an ovs port. This is due to the fact that OVS assumes another entity # manages the slaves. # So as a workaround for that case we are disabling IPv6 over pfs so that # OVS creates the shared_blocks ingress if sriovpf_member_of_bond_ovs_port_list: disable_ipv6_for_netdevs(sriovpf_member_of_bond_ovs_port_list) if configure_sriov: # Apply the ifcfgs for PFs now, so that NM_CONTROLLED=no is applied # for each of the PFs before configuring the numvfs for the PF device. # This step allows the network manager to unmanage the created VFs. # In the second parse, when these ifcfgs for PFs are encountered, # os-net-config skips the ifup <ifcfg-pfs>, since the ifcfgs for PFs # wouldn't have changed. pf_files_changed = provider.apply(cleanup=opts.cleanup, activate=not opts.no_activate) if not opts.noop: restart_ovs = bool(sriovpf_member_of_bond_ovs_port_list) # Avoid ovs restart for os-net-config re-runs, which will # dirupt the offload configuration if os.path.exists(utils._SRIOV_CONFIG_SERVICE_FILE): restart_ovs = False utils.configure_sriov_pfs( execution_from_cli=True, restart_openvswitch=restart_ovs) for iface_json in iface_array: # All objects other than the sriov_pf will be added here. # The VFs are expected to be available now and an exception # SriovVfNotFoundException shall be raised if not available. try: obj = objects.object_from_json(iface_json) except utils.SriovVfNotFoundException: if not opts.noop: raise if not isinstance(obj, objects.SriovPF): provider.add_object(obj) if configure_sriov and not opts.noop: utils.configure_sriov_vfs() files_changed = provider.apply(cleanup=opts.cleanup, activate=not opts.no_activate) if opts.noop: if configure_sriov: files_changed.update(pf_files_changed) for location, data in files_changed.items(): print("File: %s\n" % location) print(data) print("----") if opts.detailed_exit_codes and len(files_changed) > 0: return 2 return 0
def main(argv=sys.argv): opts = parse_opts(argv) configure_logger(opts.verbose, opts.debug) logger.info('Using config file at: %s' % opts.config_file) iface_array = [] configure_sriov = False provider = None if opts.provider: if opts.provider == 'ifcfg': provider = impl_ifcfg.IfcfgNetConfig(noop=opts.noop, root_dir=opts.root_dir) elif opts.provider == 'eni': provider = impl_eni.ENINetConfig(noop=opts.noop, root_dir=opts.root_dir) elif opts.provider == 'iproute': provider = impl_iproute.IPRouteNetConfig(noop=opts.noop, root_dir=opts.root_dir) else: logger.error('Invalid provider specified.') return 1 else: if os.path.exists('%s/etc/sysconfig/network-scripts/' % opts.root_dir): provider = impl_ifcfg.IfcfgNetConfig(noop=opts.noop, root_dir=opts.root_dir) elif os.path.exists('%s/etc/network/' % opts.root_dir): provider = impl_eni.ENINetConfig(noop=opts.noop, root_dir=opts.root_dir) else: logger.error('Unable to set provider for this operating system.') return 1 # Read the interface mapping file, if it exists # This allows you to override the default network naming abstraction # mappings by specifying a specific nicN->name or nicN->MAC mapping if os.path.exists(opts.mapping_file): logger.info('Using mapping file at: %s' % opts.mapping_file) with open(opts.mapping_file) as cf: iface_map = yaml.safe_load(cf.read()) iface_mapping = iface_map.get("interface_mapping") logger.debug('interface_mapping JSON: %s' % str(iface_mapping)) persist_mapping = opts.persist_mapping logger.debug('persist_mapping: %s' % persist_mapping) else: logger.info('Not using any mapping file.') iface_mapping = None persist_mapping = False # If --interfaces is specified, either return the real name of the # interfaces specified, or return the map of all nic abstractions/names. if opts.interfaces is not None: reported_nics = {} mapped_nics = objects.mapped_nics(iface_mapping) retval = 0 if len(opts.interfaces) > 0: for requested_nic in opts.interfaces: found = False # Check to see if requested iface is a mapped NIC name. if requested_nic in mapped_nics: reported_nics[requested_nic] = mapped_nics[requested_nic] found = True # Check to see if the requested iface is a real NIC name if requested_nic in mapped_nics.values(): if found is True: # Name matches alias and real NIC # (return the mapped NIC, but warn of overlap). logger.warning('"%s" overlaps with real NIC name.' % (requested_nic)) else: reported_nics[requested_nic] = requested_nic found = True if not found: retval = 1 if reported_nics: logger.debug("Interface mapping requested for interface: " "%s" % reported_nics.keys()) else: logger.debug("Interface mapping requested for all interfaces") reported_nics = mapped_nics # Return the report on the mapped NICs. If all NICs were found, exit # cleanly, otherwise exit with status 1. logger.debug("Interface report requested, exiting after report.") print(reported_nics) return retval # Read config file containing network configs to apply if os.path.exists(opts.config_file): try: with open(opts.config_file) as cf: iface_array = yaml.safe_load(cf.read()).get("network_config") logger.debug('network_config JSON: %s' % str(iface_array)) except IOError: logger.error("Error reading file: %s" % opts.config_file) return 1 else: logger.error('No config file exists at: %s' % opts.config_file) return 1 if not isinstance(iface_array, list): logger.error('No interfaces defined in config: %s' % opts.config_file) return 1 for iface_json in iface_array: if iface_json.get('type') != 'route_table': iface_json.update({'nic_mapping': iface_mapping}) iface_json.update({'persist_mapping': persist_mapping}) validation_errors = validator.validate_config(iface_array) if validation_errors: if opts.exit_on_validation_errors: logger.error('\n'.join(validation_errors)) return 1 else: logger.warning('\n'.join(validation_errors)) # Look for the presence of SriovPF types in the first parse of the json # if SriovPFs exists then PF devices needs to be configured so that the VF # devices are created. # The VFs will not be available now and an exception # SriovVfNotFoundException will be raised while fetching the device name. # After the first parse the SR-IOV PF devices would be configured and the # VF devices would be created. # In the second parse, all other objects shall be added for iface_json in iface_array: try: obj = objects.object_from_json(iface_json) except utils.SriovVfNotFoundException: continue if isinstance(obj, objects.SriovPF): configure_sriov = True provider.add_object(obj) elif hasattr(obj, 'members') and obj.members is not None: if check_configure_sriov(obj): configure_sriov = True provider.add_object(obj) if configure_sriov: # Apply the ifcfgs for PFs now, so that NM_CONTROLLED=no is applied # for each of the PFs before configuring the numvfs for the PF device. # This step allows the network manager to unmanage the created VFs. # In the second parse, when these ifcfgs for PFs are encountered, # os-net-config skips the ifup <ifcfg-pfs>, since the ifcfgs for PFs # wouldn't have changed. pf_files_changed = provider.apply(cleanup=opts.cleanup, activate=not opts.no_activate) if not opts.noop: utils.configure_sriov_pfs() for iface_json in iface_array: # All objects other than the sriov_pf will be added here. # The VFs are expected to be available now and an exception # SriovVfNotFoundException shall be raised if not available. try: obj = objects.object_from_json(iface_json) except utils.SriovVfNotFoundException: if not opts.noop: raise if not isinstance(obj, objects.SriovPF): provider.add_object(obj) if configure_sriov and not opts.noop: utils.configure_sriov_vfs() files_changed = provider.apply(cleanup=opts.cleanup, activate=not opts.no_activate) if opts.noop: if configure_sriov: files_changed.update(pf_files_changed) for location, data in files_changed.items(): print("File: %s\n" % location) print(data) print("----") if opts.detailed_exit_codes and len(files_changed) > 0: return 2 return 0
def main(argv=sys.argv): opts = parse_opts(argv) configure_logger(opts.verbose, opts.debug) logger.info('Using config file at: %s' % opts.config_file) if opts.mapping_file: logger.info('Using mapping file at: %s' % opts.mapping_file) iface_array = [] provider = None if opts.provider: if opts.provider == 'ifcfg': provider = impl_ifcfg.IfcfgNetConfig(noop=opts.noop, root_dir=opts.root_dir) elif opts.provider == 'eni': provider = impl_eni.ENINetConfig(noop=opts.noop, root_dir=opts.root_dir) elif opts.provider == 'iproute': provider = impl_iproute.IPRouteNetConfig(noop=opts.noop, root_dir=opts.root_dir) else: logger.error('Invalid provider specified.') return 1 else: if os.path.exists('%s/etc/sysconfig/network-scripts/' % opts.root_dir): provider = impl_ifcfg.IfcfgNetConfig(noop=opts.noop, root_dir=opts.root_dir) elif os.path.exists('%s/etc/network/' % opts.root_dir): provider = impl_eni.ENINetConfig(noop=opts.noop, root_dir=opts.root_dir) else: logger.error('Unable to set provider for this operating system.') return 1 # Read config file containing network configs to apply if os.path.exists(opts.config_file): with open(opts.config_file) as cf: iface_array = yaml.load(cf.read()).get("network_config") logger.debug('network_config JSON: %s' % str(iface_array)) else: logger.error('No config file exists at: %s' % opts.config_file) return 1 if not isinstance(iface_array, list): logger.error('No interfaces defined in config: %s' % opts.config_file) return 1 # Read the interface mapping file, if it exists # This allows you to override the default network naming abstraction # mappings by specifying a specific nicN->name or nicN->MAC mapping if os.path.exists(opts.mapping_file): with open(opts.mapping_file) as cf: iface_map = yaml.load(cf.read()) iface_mapping = iface_map.get("interface_mapping") logger.debug('interface_mapping JSON: %s' % str(iface_mapping)) persist_mapping = opts.persist_mapping logger.debug('persist_mapping: %s' % persist_mapping) else: iface_mapping = None persist_mapping = False for iface_json in iface_array: iface_json.update({'nic_mapping': iface_mapping}) iface_json.update({'persist_mapping': persist_mapping}) validation_errors = validator.validate_config(iface_array) if validation_errors: if opts.exit_on_validation_errors: logger.error('\n'.join(validation_errors)) return 1 else: logger.warning('\n'.join(validation_errors)) for iface_json in iface_array: obj = objects.object_from_json(iface_json) provider.add_object(obj) files_changed = provider.apply(cleanup=opts.cleanup, activate=not opts.no_activate) if opts.noop: for location, data in files_changed.items(): print("File: %s\n" % location) print(data) print("----") if opts.detailed_exit_codes and len(files_changed) > 0: return 2 return 0
def test_from_json_dhcp(self): data = '{"type": "interface", "name": "em1", "use_dhcp": true}' interface = objects.object_from_json(json.loads(data)) self.assertEqual("em1", interface.name) self.assertEqual(True, interface.use_dhcp)
def generate_ifcfg_activate_ports(): """Generate ifcfg and restart ports. :returns: an object of IfcfgNetConfig, a list of ivs physical uplinks, and a list of ivs internal ports. """ provider = impl_ifcfg.IfcfgNetConfig(noop=True, root_dir='') intfs = [] if os.path.exists(NET_CONF_PATH): try: json_data = open(NET_CONF_PATH).read() intfs = jsonutils.loads(json_data).get("network_config") except: LOG.error('Fail to load file at: %s' % NET_CONF_PATH) return 1 for intf in intfs: obj = objects.object_from_json(intf) provider.add_object(obj) # store the route on physical nics route_dict = {} # store the ovs internal port ifcfg internal_port_dict = {} internal_ports = [] # store uplink ifcfg phy_link_dict = {} uplinks = [] for intf, data in provider.interface_data.iteritems(): # ivs does not need bond if "bond" in intf: match = re.search('BOND_IFACES="(.+?)"', data) if match: uplinks = match.group(1).split() continue # if route is assigned to physical port if ("vlan" not in intf and "ivs" not in intf): route_data = provider.route_data.get(intf, '') route_path = provider.root_dir + impl_ifcfg.route_config_path(intf) route_dict[route_path] = route_data intf_path = provider.root_dir + impl_ifcfg.ifcfg_config_path(intf) # update data for internal port if "TYPE=OVSIntPort" in data: # delete all lines starts with OVS_ d = re.sub("OVS_.*?\n", '', data, flags=re.DOTALL) # replace all ovs with ivs d = re.sub("ovs", 'ivs', d, flags=re.DOTALL) # replace all OVS with IVS d = re.sub("OVS", 'IVS', d, flags=re.DOTALL) internal_port_dict[intf_path] = d internal_ports.append(intf) else: # update data for physical port phy_link_dict[intf_path] = data # make sure noop is turned off for ifdown and ifup provider.noop = False # write route for location, data in route_dict.iteritems(): provider.write_config(location, data) # write internal port config for location, data in internal_port_dict.iteritems(): provider.write_config(location, data) # write physical ports config, restart uplinks for uplink in uplinks: provider.ifdown(uplink) for location, data in phy_link_dict.iteritems(): provider.write_config(location, data) for uplink in uplinks: provider.ifup(uplink) LOG.info("IVS uplinks: %s" % ','.join(uplinks)) LOG.info("IVS internal_ports %s" % ','.join(internal_ports)) return provider, uplinks, internal_ports
def test_from_json_dhcp(self): data = '{"type": "interface", "name": "em1", "use_dhcp": true}' interface = objects.object_from_json(json.loads(data)) self.assertEqual("em1", interface.name) self.assertTrue(interface.use_dhcp)
def apply(self): self.configure_logger(self.verbose, self.debug) logger.info('Using config: %s' % self.network_config) iface_array = [] configure_sriov = False provider = None if self.provider: if self.provider == 'ifcfg': provider = impl_ifcfg.IfcfgNetConfig(noop=self.noop, root_dir=self.root_dir) elif self.provider == 'eni': provider = impl_eni.ENINetConfig(noop=self.noop, root_dir=self.root_dir) elif self.provider == 'iproute': provider = impl_iproute.IPRouteNetConfig( noop=self.noop, root_dir=self.root_dir) else: logger.error('Invalid provider specified.') return 1 else: ifcfg_dir = "/etc/sysconfig/network-scripts/" if os.path.exists('%s%s' % (self.root_dir, ifcfg_dir)): provider = impl_ifcfg.IfcfgNetConfig(noop=self.noop, root_dir=self.root_dir) elif os.path.exists('%s/etc/network/' % self.root_dir): provider = impl_eni.ENINetConfig(noop=self.noop, root_dir=self.root_dir) else: logger.error('Unable to set provider for this \ operating system.') return 1 iface_array = self.network_config if not isinstance(iface_array, list): logger.error('No interfaces defined in config: %s' % self.network_config) return 1 validation_errors = validator.validate_config(iface_array) if validation_errors: if self.exit_on_validation_errors: logger.error('\n'.join(validation_errors)) return 1 else: logger.warning('\n'.join(validation_errors)) # Look for the presence of SriovPF types in the first parse of the json # if SriovPFs exists then PF devices needs to be configured so that the # VF devices are created. # The VFs will not be available now and an exception # SriovVfNotFoundException will be raised while fetching the device # name. # After the first parse the SR-IOV PF devices would be configured and # the VF devices would be created. # In the second parse, all other objects shall be added for iface_json in iface_array: try: obj = objects.object_from_json(iface_json) except utils.SriovVfNotFoundException: continue if isinstance(obj, objects.SriovPF): configure_sriov = True provider.add_object(obj) elif hasattr(obj, 'members') and obj.members is not None: if check_configure_sriov(obj): configure_sriov = True provider.add_object(obj) if configure_sriov: # Apply the ifcfgs for PFs now, so that NM_CONTROLLED=no is applied # for each of the PFs before configuring the numvfs for the PF # device. # This step allows the network manager to unmanage the created VFs. # In the second parse, when these ifcfgs for PFs are encountered, # os-net-config skips the ifup <ifcfg-pfs>, since the ifcfgs for # PFs wouldn't have changed. pf_files_changed = provider.apply(cleanup=self.cleanup, activate=not self.no_activate) if not self.noop: utils.configure_sriov_pfs() for iface_json in iface_array: # All objects other than the sriov_pf will be added here. # The VFs are expected to be available now and an exception # SriovVfNotFoundException shall be raised if not available. try: obj = objects.object_from_json(iface_json) except utils.SriovVfNotFoundException: if not self.noop: raise if not isinstance(obj, objects.SriovPF): provider.add_object(obj) if configure_sriov and not self.noop: utils.configure_sriov_vfs() files_changed = provider.apply(cleanup=self.cleanup, activate=not self.no_activate) logger.info("files_changed: %s" % [k for k, v in files_changed.items()]) if self.noop: if configure_sriov: files_changed.update(pf_files_changed) for location, data in files_changed.items(): print("File: %s\n" % location) print(data) print("----") if self.detailed_exit_codes and len(files_changed) > 0: return 2 return 0
def main(argv=sys.argv): opts = parse_opts(argv) configure_logger(opts.verbose, opts.debug) logger.info('Using config file at: %s' % opts.config_file) if opts.mapping_file: logger.info('Using mapping file at: %s' % opts.mapping_file) iface_array = [] provider = None if opts.provider: if opts.provider == 'ifcfg': provider = impl_ifcfg.IfcfgNetConfig(noop=opts.noop, root_dir=opts.root_dir) elif opts.provider == 'eni': provider = impl_eni.ENINetConfig(noop=opts.noop, root_dir=opts.root_dir) elif opts.provider == 'iproute': provider = impl_iproute.IPRouteNetConfig(noop=opts.noop, root_dir=opts.root_dir) else: logger.error('Invalid provider specified.') return 1 else: if os.path.exists('%s/etc/sysconfig/network-scripts/' % opts.root_dir): provider = impl_ifcfg.IfcfgNetConfig(noop=opts.noop, root_dir=opts.root_dir) elif os.path.exists('%s/etc/network/' % opts.root_dir): provider = impl_eni.ENINetConfig(noop=opts.noop, root_dir=opts.root_dir) else: logger.error('Unable to set provider for this operating system.') return 1 # Read config file containing network configs to apply if os.path.exists(opts.config_file): with open(opts.config_file) as cf: iface_array = yaml.load(cf.read()).get("network_config") logger.debug('network_config JSON: %s' % str(iface_array)) else: logger.error('No config file exists at: %s' % opts.config_file) return 1 if not isinstance(iface_array, list): logger.error('No interfaces defined in config: %s' % opts.config_file) return 1 # Read the interface mapping file, if it exists # This allows you to override the default network naming abstraction # mappings by specifying a specific nicN->name or nicN->MAC mapping if os.path.exists(opts.mapping_file): with open(opts.mapping_file) as cf: iface_map = yaml.load(cf.read()) iface_mapping = iface_map.get("interface_mapping") logger.debug('interface_mapping JSON: %s' % str(iface_mapping)) persist_mapping = opts.persist_mapping logger.debug('persist_mapping: %s' % persist_mapping) else: iface_mapping = None persist_mapping = False for iface_json in iface_array: iface_json.update({'nic_mapping': iface_mapping}) iface_json.update({'persist_mapping': persist_mapping}) obj = objects.object_from_json(iface_json) provider.add_object(obj) files_changed = provider.apply(cleanup=opts.cleanup, activate=not opts.no_activate) if opts.noop: for location, data in files_changed.iteritems(): print("File: %s\n" % location) print(data) print("----") if opts.detailed_exit_codes and len(files_changed) > 0: return 2 return 0