Source code for ironic.drivers.modules.inspector.hooks.parse_lldp
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""LLDP Processing Hook for basic TLVs"""
import binascii
from oslo_log import log as logging
from ironic.drivers.modules.inspector.hooks import base
from ironic.drivers.modules.inspector import lldp_parsers
LOG = logging.getLogger(__name__)
[docs]
class ParseLLDPHook(base.InspectionHook):
"""Process LLDP packet fields and store them in plugin_data['parsed_lldp']
Convert binary LLDP information into a readable form. Loop through raw
LLDP TLVs and parse those from the basic management, 802.1, and 802.3 TLV
sets. Store parsed data in the plugin_data as a new parsed_lldp dictionary
with interface names as keys.
"""
def _parse_lldp_tlvs(self, tlvs, node_uuid):
"""Parse LLDP TLVs into a dictionary of name/value pairs
:param tlvs: List of raw TLVs
:param node_uuid: UUID of the node being inspected
:returns: Dictionary of name/value pairs. The LLDP user-friendly
names, e.g. "switch_port_id" are the keys.
"""
# Generate name/value pairs for each TLV supported by this plugin.
parser = lldp_parsers.LLDPBasicMgmtParser(node_uuid)
for tlv_type, tlv_value in tlvs:
try:
data = bytearray(binascii.a2b_hex(tlv_value))
except TypeError as e:
LOG.warning(
'TLV value for TLV type %(tlv_type)d is not in correct '
'format, value must be in hexadecimal: %(msg)s. Node: '
'%(node)s', {'tlv_type': tlv_type, 'msg': e,
'node': node_uuid})
continue
try:
parsed_tlv = parser.parse_tlv(tlv_type, data)
except UnicodeDecodeError as e:
LOG.warning("LLDP TLV type %(tlv_type)d from Node '%(node)s' "
"can't be decoded: %(exc)s",
{'tlv_type': tlv_type, 'exc': e,
'node': node_uuid})
continue
if parsed_tlv:
LOG.debug("Handled TLV type %d. Node: %s", tlv_type, node_uuid)
else:
LOG.debug("LLDP TLV type %d not handled. Node: %s", tlv_type,
node_uuid)
return parser.nv_dict
[docs]
def __call__(self, task, inventory, plugin_data):
"""Process LLDP data and update plugin_data with processed data"""
lldp_raw = plugin_data.get('lldp_raw') or {}
for interface in inventory['interfaces']:
if_name = interface['name']
tlvs = lldp_raw.get(if_name) or interface.get('lldp')
if tlvs is None:
LOG.warning("No LLDP Data found for interface %s of node %s",
if_name, task.node.uuid)
continue
LOG.debug("Processing LLDP Data for interface %s of node %s",
if_name, task.node.uuid)
# Store LLDP data per interface in plugin_data[parsed_lldp]
nv = self._parse_lldp_tlvs(tlvs, task.node.uuid)
if nv:
if plugin_data.get('parsed_lldp'):
plugin_data['parsed_lldp'].update({if_name: nv})
else:
plugin_data['parsed_lldp'] = {if_name: nv}