322 lines
11 KiB
Python
322 lines
11 KiB
Python
#
|
|
# Copyright (c) 2018 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
|
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# All Rights Reserved.
|
|
#
|
|
|
|
from oslo_log import log as logging
|
|
|
|
import simplejson as json
|
|
import subprocess
|
|
|
|
from inventory.agent.lldp.drivers import base
|
|
from inventory.agent.lldp import plugin
|
|
from inventory.common import k_lldp
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class InventoryLldpdAgentDriver(base.InventoryLldpDriverBase):
|
|
|
|
def __init__(self, **kwargs):
|
|
self.client = ""
|
|
self.agents = []
|
|
self.neighbours = []
|
|
self.current_neighbours = []
|
|
self.previous_neighbours = []
|
|
self.current_agents = []
|
|
self.previous_agents = []
|
|
self.agent_audit_count = 0
|
|
self.neighbour_audit_count = 0
|
|
|
|
def initialize(self):
|
|
self.__init__()
|
|
|
|
@staticmethod
|
|
def _lldpd_get_agent_status():
|
|
json_obj = json
|
|
p = subprocess.Popen(["lldpcli", "-f", "json", "show",
|
|
"configuration"],
|
|
stdout=subprocess.PIPE)
|
|
data = json_obj.loads(p.communicate()[0])
|
|
|
|
configuration = data['configuration'][0]
|
|
config = configuration['config'][0]
|
|
rx_only = config['rx-only'][0]
|
|
|
|
if rx_only.get("value") == "no":
|
|
return "rx=enabled,tx=enabled"
|
|
else:
|
|
return "rx=enabled,tx=disabled"
|
|
|
|
@staticmethod
|
|
def _lldpd_get_attrs(iface):
|
|
name_or_uuid = None
|
|
chassis_id = None
|
|
system_name = None
|
|
system_desc = None
|
|
capability = None
|
|
management_address = None
|
|
port_desc = None
|
|
dot1_lag = None
|
|
dot1_port_vid = None
|
|
dot1_vid_digest = None
|
|
dot1_mgmt_vid = None
|
|
dot1_vlan_names = None
|
|
dot1_proto_vids = None
|
|
dot1_proto_ids = None
|
|
dot3_mac_status = None
|
|
dot3_max_frame = None
|
|
dot3_power_mdi = None
|
|
ttl = None
|
|
attrs = {}
|
|
|
|
# Note: dot1_vid_digest, dot1_mgmt_vid are not currently supported
|
|
# by the lldpd daemon
|
|
|
|
name_or_uuid = iface.get("name")
|
|
chassis = iface.get("chassis")[0]
|
|
port = iface.get("port")[0]
|
|
|
|
if not chassis.get('id'):
|
|
return attrs
|
|
chassis_id = chassis['id'][0].get("value")
|
|
|
|
if not port.get('id'):
|
|
return attrs
|
|
port_id = port["id"][0].get("value")
|
|
|
|
if not port.get('ttl'):
|
|
return attrs
|
|
ttl = port['ttl'][0].get("value")
|
|
|
|
if chassis.get("name"):
|
|
system_name = chassis['name'][0].get("value")
|
|
|
|
if chassis.get("descr"):
|
|
system_desc = chassis['descr'][0].get("value")
|
|
|
|
if chassis.get("capability"):
|
|
capability = ""
|
|
for cap in chassis["capability"]:
|
|
if cap.get("enabled"):
|
|
if capability:
|
|
capability += ", "
|
|
capability += cap.get("type").lower()
|
|
|
|
if chassis.get("mgmt-ip"):
|
|
management_address = ""
|
|
for addr in chassis["mgmt-ip"]:
|
|
if management_address:
|
|
management_address += ", "
|
|
management_address += addr.get("value").lower()
|
|
|
|
if port.get("descr"):
|
|
port_desc = port["descr"][0].get("value")
|
|
|
|
if port.get("link-aggregation"):
|
|
dot1_lag_supported = port["link-aggregation"][0].get("supported")
|
|
dot1_lag_enabled = port["link-aggregation"][0].get("enabled")
|
|
dot1_lag = "capable="
|
|
if dot1_lag_supported:
|
|
dot1_lag += "y,"
|
|
else:
|
|
dot1_lag += "n,"
|
|
dot1_lag += "enabled="
|
|
if dot1_lag_enabled:
|
|
dot1_lag += "y"
|
|
else:
|
|
dot1_lag += "n"
|
|
|
|
if port.get("auto-negotiation"):
|
|
port_auto_neg_support = port["auto-negotiation"][0].get(
|
|
"supported")
|
|
port_auto_neg_enabled = port["auto-negotiation"][0].get("enabled")
|
|
dot3_mac_status = "auto-negotiation-capable="
|
|
if port_auto_neg_support:
|
|
dot3_mac_status += "y,"
|
|
else:
|
|
dot3_mac_status += "n,"
|
|
dot3_mac_status += "auto-negotiation-enabled="
|
|
if port_auto_neg_enabled:
|
|
dot3_mac_status += "y,"
|
|
else:
|
|
dot3_mac_status += "n,"
|
|
advertised = ""
|
|
if port.get("auto-negotiation")[0].get("advertised"):
|
|
for adv in port["auto-negotiation"][0].get("advertised"):
|
|
if advertised:
|
|
advertised += ", "
|
|
type = adv.get("type").lower()
|
|
if adv.get("hd") and not adv.get("fd"):
|
|
type += "hd"
|
|
elif adv.get("fd"):
|
|
type += "fd"
|
|
advertised += type
|
|
dot3_mac_status += advertised
|
|
|
|
if port.get("mfs"):
|
|
dot3_max_frame = port["mfs"][0].get("value")
|
|
|
|
if port.get("power"):
|
|
power_mdi_support = port["power"][0].get("supported")
|
|
power_mdi_enabled = port["power"][0].get("enabled")
|
|
power_mdi_devicetype = port["power"][0].get("device-type")[0].get(
|
|
"value")
|
|
power_mdi_pairs = port["power"][0].get("pairs")[0].get("value")
|
|
power_mdi_class = port["power"][0].get("class")[0].get("value")
|
|
dot3_power_mdi = "power-mdi-supported="
|
|
if power_mdi_support:
|
|
dot3_power_mdi += "y,"
|
|
else:
|
|
dot3_power_mdi += "n,"
|
|
dot3_power_mdi += "power-mdi-enabled="
|
|
if power_mdi_enabled:
|
|
dot3_power_mdi += "y,"
|
|
else:
|
|
dot3_power_mdi += "n,"
|
|
if power_mdi_support and power_mdi_enabled:
|
|
dot3_power_mdi += "device-type=" + power_mdi_devicetype
|
|
dot3_power_mdi += ",pairs=" + power_mdi_pairs
|
|
dot3_power_mdi += ",class=" + power_mdi_class
|
|
|
|
vlans = None
|
|
if iface.get("vlan"):
|
|
vlans = iface.get("vlan")
|
|
|
|
if vlans:
|
|
dot1_vlan_names = ""
|
|
for vlan in vlans:
|
|
if vlan.get("pvid"):
|
|
dot1_port_vid = vlan.get("vlan-id")
|
|
continue
|
|
if dot1_vlan_names:
|
|
dot1_vlan_names += ", "
|
|
dot1_vlan_names += vlan.get("value")
|
|
|
|
ppvids = None
|
|
if iface.get("ppvids"):
|
|
ppvids = iface.get("ppvid")
|
|
|
|
if ppvids:
|
|
dot1_proto_vids = ""
|
|
for ppvid in ppvids:
|
|
if dot1_proto_vids:
|
|
dot1_proto_vids += ", "
|
|
dot1_proto_vids += ppvid.get("value")
|
|
|
|
pids = None
|
|
if iface.get("pi"):
|
|
pids = iface.get('pi')
|
|
dot1_proto_ids = ""
|
|
for id in pids:
|
|
if dot1_proto_ids:
|
|
dot1_proto_ids += ", "
|
|
dot1_proto_ids += id.get("value")
|
|
|
|
msap = chassis_id + "," + port_id
|
|
|
|
attrs = {"name_or_uuid": name_or_uuid,
|
|
k_lldp.LLDP_TLV_TYPE_CHASSIS_ID: chassis_id,
|
|
k_lldp.LLDP_TLV_TYPE_PORT_ID: port_id,
|
|
k_lldp.LLDP_TLV_TYPE_TTL: ttl,
|
|
"msap": msap,
|
|
k_lldp.LLDP_TLV_TYPE_SYSTEM_NAME: system_name,
|
|
k_lldp.LLDP_TLV_TYPE_SYSTEM_DESC: system_desc,
|
|
k_lldp.LLDP_TLV_TYPE_SYSTEM_CAP: capability,
|
|
k_lldp.LLDP_TLV_TYPE_MGMT_ADDR: management_address,
|
|
k_lldp.LLDP_TLV_TYPE_PORT_DESC: port_desc,
|
|
k_lldp.LLDP_TLV_TYPE_DOT1_LAG: dot1_lag,
|
|
k_lldp.LLDP_TLV_TYPE_DOT1_PORT_VID: dot1_port_vid,
|
|
k_lldp.LLDP_TLV_TYPE_DOT1_VID_DIGEST: dot1_vid_digest,
|
|
k_lldp.LLDP_TLV_TYPE_DOT1_MGMT_VID: dot1_mgmt_vid,
|
|
k_lldp.LLDP_TLV_TYPE_DOT1_VLAN_NAMES: dot1_vlan_names,
|
|
k_lldp.LLDP_TLV_TYPE_DOT1_PROTO_VIDS: dot1_proto_vids,
|
|
k_lldp.LLDP_TLV_TYPE_DOT1_PROTO_IDS: dot1_proto_ids,
|
|
k_lldp.LLDP_TLV_TYPE_DOT3_MAC_STATUS: dot3_mac_status,
|
|
k_lldp.LLDP_TLV_TYPE_DOT3_MAX_FRAME: dot3_max_frame,
|
|
k_lldp.LLDP_TLV_TYPE_DOT3_POWER_MDI: dot3_power_mdi}
|
|
|
|
return attrs
|
|
|
|
def lldp_has_neighbour(self, name):
|
|
p = subprocess.check_output(["lldpcli", "-f", "keyvalue", "show",
|
|
"neighbors", "summary", "ports", name])
|
|
return len(p) > 0
|
|
|
|
def lldp_update(self):
|
|
subprocess.call(['lldpcli', 'update'])
|
|
|
|
def lldp_agents_list(self):
|
|
json_obj = json
|
|
lldp_agents = []
|
|
|
|
p = subprocess.Popen(["lldpcli", "-f", "json", "show", "interface",
|
|
"detail"], stdout=subprocess.PIPE)
|
|
data = json_obj.loads(p.communicate()[0])
|
|
|
|
lldp = data['lldp'][0]
|
|
|
|
if not lldp.get('interface'):
|
|
return lldp_agents
|
|
|
|
for iface in lldp['interface']:
|
|
agent_attrs = self._lldpd_get_attrs(iface)
|
|
status = self._lldpd_get_agent_status()
|
|
agent_attrs.update({"status": status})
|
|
agent = plugin.Agent(**agent_attrs)
|
|
lldp_agents.append(agent)
|
|
|
|
return lldp_agents
|
|
|
|
def lldp_agents_clear(self):
|
|
self.current_agents = []
|
|
self.previous_agents = []
|
|
|
|
def lldp_neighbours_list(self):
|
|
json_obj = json
|
|
lldp_neighbours = []
|
|
p = subprocess.Popen(["lldpcli", "-f", "json", "show", "neighbor",
|
|
"detail"], stdout=subprocess.PIPE)
|
|
data = json_obj.loads(p.communicate()[0])
|
|
|
|
lldp = data['lldp'][0]
|
|
|
|
if not lldp.get('interface'):
|
|
return lldp_neighbours
|
|
|
|
for iface in lldp['interface']:
|
|
neighbour_attrs = self._lldpd_get_attrs(iface)
|
|
neighbour = plugin.Neighbour(**neighbour_attrs)
|
|
lldp_neighbours.append(neighbour)
|
|
|
|
return lldp_neighbours
|
|
|
|
def lldp_neighbours_clear(self):
|
|
self.current_neighbours = []
|
|
self.previous_neighbours = []
|
|
|
|
def lldp_update_systemname(self, systemname):
|
|
p = subprocess.Popen(["lldpcli", "-f", "json", "show", "chassis"],
|
|
stdout=subprocess.PIPE)
|
|
data = json.loads(p.communicate()[0])
|
|
|
|
local_chassis = data['local-chassis'][0]
|
|
chassis = local_chassis['chassis'][0]
|
|
name = chassis.get('name', None)
|
|
if name is None or not name[0].get("value"):
|
|
return
|
|
name = name[0]
|
|
|
|
hostname = name.get("value").partition(':')[0]
|
|
|
|
newname = hostname + ":" + systemname
|
|
|
|
p = subprocess.Popen(["lldpcli", "configure", "system", "hostname",
|
|
newname], stdout=subprocess.PIPE)
|