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) 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, 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