def test_is_valid_mac(self): self.assertTrue(netutils.is_valid_mac("52:54:00:cf:2d:31")) self.assertTrue(netutils.is_valid_mac(u"52:54:00:cf:2d:31")) self.assertFalse(netutils.is_valid_mac("127.0.0.1")) self.assertFalse(netutils.is_valid_mac("not:a:mac:address")) self.assertFalse(netutils.is_valid_mac("52-54-00-cf-2d-31")) self.assertFalse(netutils.is_valid_mac("aa bb cc dd ee ff")) self.assertTrue(netutils.is_valid_mac("AA:BB:CC:DD:EE:FF")) self.assertFalse(netutils.is_valid_mac("AA BB CC DD EE FF")) self.assertFalse(netutils.is_valid_mac("AA-BB-CC-DD-EE-FF"))
def _get_lldp_processed_patch(self, name, item, lldp_proc_data, port, node_info): if 'lldp_processed' not in lldp_proc_data: return value = lldp_proc_data['lldp_processed'].get(name) if value: # Only accept mac address for chassis ID if (item == SWITCH_ID_ITEM_NAME and not netutils.is_valid_mac(value)): LOG.info("Skipping switch_id since it's not a MAC: %s", value, node_info=node_info) return if (not CONF.processing.overwrite_existing and item in port.local_link_connection): return return { 'op': 'add', 'path': '/local_link_connection/%s' % item, 'value': value }
def before_processing(self, node_info): """Validate information about network interfaces.""" bmc_address = node_info.get('ipmi_address') compat = conf.getboolean('discoverd', 'ports_for_inactive_interfaces') if 'interfaces' not in node_info and 'macs' in node_info: LOG.warning('Using "macs" field is deprecated, please ' 'update your discovery ramdisk') node_info['interfaces'] = { 'dummy%d' % i: {'mac': m} for i, m in enumerate(node_info['macs'])} compat = True valid_interfaces = { n: iface for n, iface in node_info['interfaces'].items() if (netutils.is_valid_mac(iface.get('mac')) and (compat or iface.get('ip'))) } valid_macs = [iface['mac'] for iface in valid_interfaces.values()] if valid_interfaces != node_info['interfaces']: LOG.warning( 'The following interfaces were invalid or not eligible in ' 'introspection data for node with BMC %(ipmi_address)s and ' 'were excluded: %(invalid)s', {'invalid': {n: iface for n, iface in node_info['interfaces'].items() if n not in valid_interfaces}, 'ipmi_address': bmc_address}) LOG.info('Eligible interfaces are %s', valid_interfaces) node_info['interfaces'] = valid_interfaces node_info['macs'] = valid_macs
def _get_interfaces(self, data=None): """Convert inventory to a dict with interfaces. :return: dict interface name -> dict with keys 'mac' and 'ip' """ result = {} inventory = utils.get_inventory(data) pxe_mac = utils.get_pxe_mac(data) for iface in inventory['interfaces']: name = iface.get('name') mac = iface.get('mac_address') ip = iface.get('ipv4_address') client_id = iface.get('client_id') if not name: LOG.error('Malformed interface record: %s', iface, data=data) continue if not mac: LOG.debug('Skipping interface %s without link information', name, data=data) continue if not netutils.is_valid_mac(mac): LOG.warning( 'MAC %(mac)s for interface %(name)s is ' 'not valid, skipping', { 'mac': mac, 'name': name }, data=data) continue mac = mac.lower() LOG.debug( 'Found interface %(name)s with MAC "%(mac)s", ' 'IP address "%(ip)s" and client_id "%(client_id)s"', { 'name': name, 'mac': mac, 'ip': ip, 'client_id': client_id }, data=data) result[name] = { 'ip': ip, 'mac': mac, 'client_id': client_id, 'pxe': (mac == pxe_mac) } return result
def validate_and_normalize_mac(address): """Validate a MAC address and return normalized form. Checks whether the supplied MAC address is formally correct and normalize it to all lower case. :param address: MAC address to be validated and normalized. :returns: Normalized and validated MAC address. :raises: InvalidMAC If the MAC address is not valid. """ if not netutils.is_valid_mac(address): raise exception.InvalidMAC(mac=address) return address.lower()
def add_portgroup_filter(query, value): """Adds a portgroup-specific filter to a query. Filters results by address, if supplied value is a valid MAC address. Otherwise attempts to filter results by identity. :param query: Initial query to add filter to. :param value: Value for filtering results by. :return: Modified query. """ if netutils.is_valid_mac(value): return query.filter_by(address=value) else: return add_identity_filter(query, value)
def add_port_filter(query, value): """Adds a port-specific filter to a query. Filters results by address, if supplied value is a valid MAC address. Otherwise attempts to filter results by identity. :param query: Initial query to add filter to. :param value: Value for filtering results by. :return: Modified query. """ if netutils.is_valid_mac(value): return query.filter_by(address=value) else: return add_identity_filter(query, value)
def _get_interfaces(self, data=None): """Convert inventory to a dict with interfaces. :return: dict interface name -> dict with keys 'mac' and 'ip' """ result = {} inventory = utils.get_inventory(data) pxe_mac = utils.get_pxe_mac(data) for iface in inventory['interfaces']: name = iface.get('name') mac = iface.get('mac_address') ipv4_address = iface.get('ipv4_address') ipv6_address = iface.get('ipv6_address') # NOTE(kaifeng) ipv6 address may in the form of fd00::1%enp2s0, # which is not supported by netaddr, remove the suffix if exists. if ipv6_address and '%' in ipv6_address: ipv6_address = ipv6_address.split('%')[0] ip = ipv4_address or ipv6_address client_id = iface.get('client_id') if not name: LOG.error('Malformed interface record: %s', iface, data=data) continue if not mac: LOG.debug('Skipping interface %s without link information', name, data=data) continue if not netutils.is_valid_mac(mac): LOG.warning('MAC %(mac)s for interface %(name)s is ' 'not valid, skipping', {'mac': mac, 'name': name}, data=data) continue mac = mac.lower() LOG.debug('Found interface %(name)s with MAC "%(mac)s", ' 'IP address "%(ip)s" and client_id "%(client_id)s"', {'name': name, 'mac': mac, 'ip': ip, 'client_id': client_id}, data=data) result[name] = {'ip': ip, 'mac': mac, 'client_id': client_id, 'pxe': (mac == pxe_mac)} return result
def do_set_static_ip(self, line): args = line.split() ip_mac = dict( itertools.izip_longest(args[::2], args[1::2], fillvalue='')) ipaddr = ip_mac.get('--ip') macaddr = ip_mac.get('--mac') # Some sanity check. if (not ipaddr or not macaddr or not utils.is_valid_ipv4(ipaddr) or not netutils.is_valid_mac(macaddr)): print('Invalid input parameters.\n' 'Usage:' ' set_static_ip --mac <mac address> --ip <ip address>') return self.set_static_ip_address(ipaddr, macaddr)
def get(cls, context, port_id): """Find a port. Find a port based on its id or uuid or MAC address and return a Port object. :param port_id: the id *or* uuid *or* MAC address of a port. :returns: a :class:`Port` object. :raises: InvalidIdentity """ if strutils.is_int_like(port_id): return cls.get_by_id(context, port_id) elif uuidutils.is_uuid_like(port_id): return cls.get_by_uuid(context, port_id) elif netutils.is_valid_mac(port_id): return cls.get_by_address(context, port_id) else: raise exception.InvalidIdentity(identity=port_id)
def get(cls, context, portgroup_ident): """Find a portgroup based on its id, uuid, name or address. :param portgroup_ident: The id, uuid, name or address of a portgroup. :param context: Security context :returns: A :class:`Portgroup` object. :raises: InvalidIdentity """ if strutils.is_int_like(portgroup_ident): return cls.get_by_id(context, portgroup_ident) elif uuidutils.is_uuid_like(portgroup_ident): return cls.get_by_uuid(context, portgroup_ident) elif netutils.is_valid_mac(portgroup_ident): return cls.get_by_address(context, portgroup_ident) elif utils.is_valid_logical_name(portgroup_ident): return cls.get_by_name(context, portgroup_ident) else: raise exception.InvalidIdentity(identity=portgroup_ident)
def before_processing(self, node_info): """Validate information about network interfaces.""" bmc_address = node_info.get('ipmi_address') compat = conf.getboolean('discoverd', 'ports_for_inactive_interfaces') if 'interfaces' not in node_info and 'macs' in node_info: LOG.warning('Using "macs" field is deprecated, please ' 'update your discovery ramdisk') node_info['interfaces'] = { 'dummy%d' % i: { 'mac': m } for i, m in enumerate(node_info['macs']) } compat = True valid_interfaces = { n: iface for n, iface in node_info['interfaces'].items() if (netutils.is_valid_mac(iface.get('mac')) and ( compat or iface.get('ip'))) } valid_macs = [iface['mac'] for iface in valid_interfaces.values()] if valid_interfaces != node_info['interfaces']: LOG.warning( 'The following interfaces were invalid or not eligible in ' 'introspection data for node with BMC %(ipmi_address)s and ' 'were excluded: %(invalid)s', { 'invalid': { n: iface for n, iface in node_info['interfaces'].items() if n not in valid_interfaces }, 'ipmi_address': bmc_address }) LOG.info('Eligible interfaces are %s', valid_interfaces) node_info['interfaces'] = valid_interfaces node_info['macs'] = valid_macs
def _get_interfaces(self, data=None): """Convert inventory to a dict with interfaces. :return: dict interface name -> dict with keys 'mac' and 'ip' """ result = {} inventory = utils.get_inventory(data) for iface in inventory['interfaces']: name = iface.get('name') mac = iface.get('mac_address') ip = iface.get('ipv4_address') if not name: LOG.error(_LE('Malformed interface record: %s'), iface, data=data) continue if not mac: LOG.debug('Skipping interface %s without link information', name, data=data) continue if not netutils.is_valid_mac(mac): LOG.warning(_LW('MAC %(mac)s for interface %(name)s is ' 'not valid, skipping'), {'mac': mac, 'name': name}, data=data) continue mac = mac.lower() LOG.debug('Found interface %(name)s with MAC "%(mac)s" and ' 'IP address "%(ip)s"', {'name': name, 'mac': mac, 'ip': ip}, data=data) result[name] = {'ip': ip, 'mac': mac} return result
def _get_lldp_processed_patch(self, name, item, lldp_proc_data, port, node_info): if 'lldp_processed' not in lldp_proc_data: return value = lldp_proc_data['lldp_processed'].get(name) if value: # Only accept mac address for chassis ID if (item == SWITCH_ID_ITEM_NAME and not netutils.is_valid_mac(value)): LOG.info("Skipping switch_id since it's not a MAC: %s", value, node_info=node_info) return if (not CONF.processing.overwrite_existing and item in port.local_link_connection): return return {'op': 'add', 'path': '/local_link_connection/%s' % item, 'value': value}
def validate_nodes(nodes_list): """Validate all nodes list. :param nodes_list: The list of nodes to register. :raises: InvalidNode on one or more invalid nodes """ failures = [] unique_ids = set() names = set() macs = set() for index, node in enumerate(nodes_list): # Remove any comment node.pop("_comment", None) handler = _find_node_handler(node) try: handler.validate(node) except exception.InvalidNode as exc: failures.append((index, exc)) for port in node.get('ports', ()): if not netutils.is_valid_mac(port['address']): failures.append((index, 'MAC address %s is invalid' % port['address'])) if port['address'] in macs: failures.append( (index, 'MAC %s is not unique' % port['address'])) else: macs.add(port['address']) unique_id = handler.unique_id_from_fields(node) if unique_id: if unique_id in unique_ids: failures.append( (index, "Node identified by %s is already present" % unique_id)) else: unique_ids.add(unique_id) if node.get('name'): if node['name'] in names: failures.append( (index, 'Name "%s" is not unique' % node['name'])) else: names.add(node['name']) if node.get('platform') and not node.get('arch'): failures.append( (index, 'You have specified a platform without an architecture')) try: capabilities_to_dict(node.get('capabilities')) except (ValueError, TypeError): failures.append( (index, 'Invalid capabilities: %s' % node.get('capabilities'))) if node.get('root_device') is not None: if not isinstance(node['root_device'], dict): failures.append( (index, 'Invalid root device: expected dict, got %s' % node['root_device'])) for field in node: converted = handler.convert_key(field) if (converted is None and field not in _NON_DRIVER_FIELDS and field not in _SPECIAL_NON_DRIVER_FIELDS): failures.append((index, 'Unknown field %s' % field)) if failures: raise exception.InvalidNode( '\n'.join('node #%d: %s' % tpl for tpl in failures))
def validate_nodes(nodes_list): """Validate all nodes list. :param nodes_list: The list of nodes to register. :raises: InvalidNode on one or more invalid nodes """ failures = [] unique_ids = set() names = set() macs = set() for index, node in enumerate(nodes_list): # Remove any comment node.pop("_comment", None) handler = _find_node_handler(node) try: handler.validate(node) except exception.InvalidNode as exc: failures.append((index, exc)) for mac in node.get('mac', ()): if not netutils.is_valid_mac(mac): failures.append((index, 'MAC address %s is invalid' % mac)) if mac in macs: failures.append( (index, 'MAC %s is not unique' % mac)) else: macs.add(mac) unique_id = handler.unique_id_from_fields(node) if unique_id: if unique_id in unique_ids: failures.append( (index, "Node identified by %s is already present" % unique_id)) else: unique_ids.add(unique_id) if node.get('name'): if node['name'] in names: failures.append( (index, 'Name "%s" is not unique' % node['name'])) else: names.add(node['name']) try: capabilities_to_dict(node.get('capabilities')) except (ValueError, TypeError): failures.append( (index, 'Invalid capabilities: %s' % node.get('capabilities'))) for field in node: converted = handler.convert_key(field) if (converted is None and field not in _NON_DRIVER_FIELDS and field not in ('mac', 'pm_type')): failures.append((index, 'Unknown field %s' % field)) if failures: raise exception.InvalidNode( '\n'.join('node #%d: %s' % tpl for tpl in failures))
def validate_nodes(nodes_list): """Validate all nodes list. :param nodes_list: The list of nodes to register. :raises: InvalidNode on one or more invalid nodes """ failures = [] unique_ids = set() names = set() macs = set() for index, node in enumerate(nodes_list): # Remove any comment node.pop("_comment", None) handler = _find_node_handler(node) try: handler.validate(node) except exception.InvalidNode as exc: failures.append((index, exc)) for port in node.get('ports', ()): if not netutils.is_valid_mac(port['address']): failures.append( (index, 'MAC address %s is invalid' % port['address'])) if port['address'] in macs: failures.append( (index, 'MAC %s is not unique' % port['address'])) else: macs.add(port['address']) unique_id = handler.unique_id_from_fields(node) if unique_id: if unique_id in unique_ids: failures.append( (index, "Node identified by %s is already present" % unique_id)) else: unique_ids.add(unique_id) if node.get('name'): if node['name'] in names: failures.append( (index, 'Name "%s" is not unique' % node['name'])) else: names.add(node['name']) if node.get('platform') and not node.get('arch'): failures.append( (index, 'You have specified a platform without an architecture')) try: capabilities_to_dict(node.get('capabilities')) except (ValueError, TypeError): failures.append( (index, 'Invalid capabilities: %s' % node.get('capabilities'))) if node.get('root_device') is not None: if not isinstance(node['root_device'], dict): failures.append( (index, 'Invalid root device: expected dict, got %s' % node['root_device'])) for field in node: converted = handler.convert_key(field) if (converted is None and field not in _NON_DRIVER_FIELDS and field not in _SPECIAL_NON_DRIVER_FIELDS): failures.append((index, 'Unknown field %s' % field)) if failures: raise exception.InvalidNode('\n'.join('node #%d: %s' % tpl for tpl in failures))
def validate_nodes(nodes_list): """Validate all nodes list. :param nodes_list: The list of nodes to register. :raises: InvalidNode on one or more invalid nodes """ failures = [] unique_ids = set() names = set() macs = set() for index, node in enumerate(nodes_list): # Remove any comment node.pop("_comment", None) handler = _find_node_handler(node) try: handler.validate(node) except exception.InvalidNode as exc: failures.append((index, exc)) for mac in node.get('mac', ()): if not netutils.is_valid_mac(mac): failures.append((index, 'MAC address %s is invalid' % mac)) if mac in macs: failures.append((index, 'MAC %s is not unique' % mac)) else: macs.add(mac) unique_id = handler.unique_id_from_fields(node) if unique_id: if unique_id in unique_ids: failures.append( (index, "Node identified by %s is already present" % unique_id)) else: unique_ids.add(unique_id) if node.get('name'): if node['name'] in names: failures.append( (index, 'Name "%s" is not unique' % node['name'])) else: names.add(node['name']) try: capabilities_to_dict(node.get('capabilities')) except (ValueError, TypeError): failures.append( (index, 'Invalid capabilities: %s' % node.get('capabilities'))) for field in node: converted = handler.convert_key(field) if (converted is None and field not in _NON_DRIVER_FIELDS and field not in ('mac', 'pm_type')): failures.append((index, 'Unknown field %s' % field)) if failures: raise exception.InvalidNode('\n'.join('node #%d: %s' % tpl for tpl in failures))