Esempio n. 1
0
 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
            }
Esempio n. 3
0
    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
Esempio n. 4
0
    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
Esempio n. 5
0
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()
Esempio n. 6
0
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)
Esempio n. 7
0
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()
Esempio n. 8
0
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)
Esempio n. 9
0
    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
Esempio n. 10
0
    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)
Esempio n. 11
0
    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)
Esempio n. 12
0
    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)
Esempio n. 13
0
    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)
Esempio n. 14
0
    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
Esempio n. 15
0
    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}
Esempio n. 17
0
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))
Esempio n. 18
0
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))
Esempio n. 19
0
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))
Esempio n. 20
0
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))