Merge "Enable OVS LLDP inventory"
This commit is contained in:
commit
0007569a0d
@ -1,2 +1,2 @@
|
||||
SRC_DIR="sysinv"
|
||||
TIS_PATCH_VER=281
|
||||
TIS_PATCH_VER=282
|
||||
|
@ -17,3 +17,6 @@ connection=postgresql://cgts:cgtspwd@localhost/cgtsdb:
|
||||
rpc_backend = sysinv.openstack.common.rpc.impl_kombu
|
||||
rabbit_host = 192.168.204.3
|
||||
rabbit_port = 5672
|
||||
|
||||
[lldp]
|
||||
drivers=lldpd
|
||||
|
@ -72,6 +72,10 @@ systemconfig.puppet_plugins =
|
||||
032_swift = sysinv.puppet.swift:SwiftPuppet
|
||||
033_service_parameter = sysinv.puppet.service_parameter:ServiceParamPuppet
|
||||
|
||||
sysinv.agent.lldp.drivers =
|
||||
lldpd = sysinv.agent.lldp.drivers.lldpd.driver:SysinvLldpdAgentDriver
|
||||
ovs = sysinv.agent.lldp.drivers.ovs.driver:SysinvOVSAgentDriver
|
||||
|
||||
[pbr]
|
||||
autodoc_index_modules = True
|
||||
|
||||
|
@ -1,661 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2016 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# All Rights Reserved.
|
||||
#
|
||||
|
||||
""" inventory lldp Utilities and helper functions."""
|
||||
|
||||
import simplejson as json
|
||||
import subprocess
|
||||
|
||||
import threading
|
||||
|
||||
from operator import attrgetter
|
||||
|
||||
from sysinv.common import constants
|
||||
from sysinv.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Key(object):
|
||||
def __init__(self, chassisid, portid, portname):
|
||||
self.chassisid = chassisid
|
||||
self.portid = portid
|
||||
self.portname = portname
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.chassisid, self.portid, self.portname))
|
||||
|
||||
def __cmp__(self, rhs):
|
||||
return (cmp(self.chassisid, rhs.chassisid) or
|
||||
cmp(self.portid, rhs.portid) or
|
||||
cmp(self.portname, rhs.portname))
|
||||
|
||||
def __eq__(self, rhs):
|
||||
return (self.chassisid == rhs.chassisid and
|
||||
self.portid == rhs.portid and
|
||||
self.portname == rhs.portname)
|
||||
|
||||
def __ne__(self, rhs):
|
||||
return (self.chassisid != rhs.chassisid or
|
||||
self.portid != rhs.portid or
|
||||
self.portname != rhs.portname)
|
||||
|
||||
def __str__(self):
|
||||
return "%s [%s] [%s]" % (self.portname, self.chassisid, self.portid)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Key '%s'>" % str(self)
|
||||
|
||||
|
||||
class Agent(object):
|
||||
'''Class to encapsulate LLDP agent data for System Inventory'''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
'''Construct an Agent object with the given values.'''
|
||||
self.key = Key(kwargs.get(constants.LLDP_TLV_TYPE_CHASSIS_ID),
|
||||
kwargs.get(constants.LLDP_TLV_TYPE_PORT_ID),
|
||||
kwargs.get("name_or_uuid"))
|
||||
self.status = kwargs.get('status')
|
||||
self.ttl = kwargs.get(constants.LLDP_TLV_TYPE_TTL)
|
||||
self.system_name = kwargs.get(constants.LLDP_TLV_TYPE_SYSTEM_NAME)
|
||||
self.system_desc = kwargs.get(constants.LLDP_TLV_TYPE_SYSTEM_DESC)
|
||||
self.port_desc = kwargs.get(constants.LLDP_TLV_TYPE_PORT_DESC)
|
||||
self.capabilities = kwargs.get(constants.LLDP_TLV_TYPE_SYSTEM_CAP)
|
||||
self.mgmt_addr = kwargs.get(constants.LLDP_TLV_TYPE_MGMT_ADDR)
|
||||
self.dot1_lag = kwargs.get(constants.LLDP_TLV_TYPE_DOT1_LAG)
|
||||
self.dot1_vlan_names = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT1_VLAN_NAMES)
|
||||
self.dot3_max_frame = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT3_MAX_FRAME)
|
||||
self.state = None
|
||||
|
||||
def __hash__(self):
|
||||
return self.key.__hash__()
|
||||
|
||||
def __eq__(self, rhs):
|
||||
return (self.key == rhs.key)
|
||||
|
||||
def __ne__(self, rhs):
|
||||
return (self.key != rhs.key or
|
||||
self.status != rhs.status or
|
||||
self.ttl != rhs.ttl or
|
||||
self.system_name != rhs.system_name or
|
||||
self.system_desc != rhs.system_desc or
|
||||
self.port_desc != rhs.port_desc or
|
||||
self.capabilities != rhs.capabilities or
|
||||
self.mgmt_addr != rhs.mgmt_addr or
|
||||
self.dot1_lag != rhs.dot1_lag or
|
||||
self.dot1_vlan_names != rhs.dot1_vlan_names or
|
||||
self.dot3_max_frame != rhs.dot3_max_frame or
|
||||
self.state != rhs.state)
|
||||
|
||||
def __str__(self):
|
||||
return "%s: [%s] [%s] [%s], [%s], [%s], [%s], [%s], [%s]" % (
|
||||
self.key, self.status, self.system_name, self.system_desc,
|
||||
self.port_desc, self.capabilities,
|
||||
self.mgmt_addr, self.dot1_lag,
|
||||
self.dot3_max_frame)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Agent '%s'>" % str(self)
|
||||
|
||||
|
||||
class Neighbour(object):
|
||||
'''Class to encapsulate LLDP neighbour data for System Inventory'''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
'''Construct an Neighbour object with the given values.'''
|
||||
self.key = Key(kwargs.get(constants.LLDP_TLV_TYPE_CHASSIS_ID),
|
||||
kwargs.get(constants.LLDP_TLV_TYPE_PORT_ID),
|
||||
kwargs.get("name_or_uuid"))
|
||||
self.msap = kwargs.get('msap')
|
||||
self.ttl = kwargs.get(constants.LLDP_TLV_TYPE_TTL)
|
||||
self.system_name = kwargs.get(constants.LLDP_TLV_TYPE_SYSTEM_NAME)
|
||||
self.system_desc = kwargs.get(constants.LLDP_TLV_TYPE_SYSTEM_DESC)
|
||||
self.port_desc = kwargs.get(constants.LLDP_TLV_TYPE_PORT_DESC)
|
||||
self.capabilities = kwargs.get(constants.LLDP_TLV_TYPE_SYSTEM_CAP)
|
||||
self.mgmt_addr = kwargs.get(constants.LLDP_TLV_TYPE_MGMT_ADDR)
|
||||
self.dot1_port_vid = kwargs.get(constants.LLDP_TLV_TYPE_DOT1_PORT_VID)
|
||||
self.dot1_vid_digest = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT1_VID_DIGEST)
|
||||
self.dot1_mgmt_vid = kwargs.get(constants.LLDP_TLV_TYPE_DOT1_MGMT_VID)
|
||||
self.dot1_vid_digest = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT1_VID_DIGEST)
|
||||
self.dot1_mgmt_vid = kwargs.get(constants.LLDP_TLV_TYPE_DOT1_MGMT_VID)
|
||||
self.dot1_lag = kwargs.get(constants.LLDP_TLV_TYPE_DOT1_LAG)
|
||||
self.dot1_vlan_names = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT1_VLAN_NAMES)
|
||||
self.dot1_proto_vids = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT1_PROTO_VIDS)
|
||||
self.dot1_proto_ids = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT1_PROTO_IDS)
|
||||
self.dot3_mac_status = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT3_MAC_STATUS)
|
||||
self.dot3_max_frame = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT3_MAX_FRAME)
|
||||
self.dot3_power_mdi = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT3_POWER_MDI)
|
||||
|
||||
self.state = None
|
||||
|
||||
def __hash__(self):
|
||||
return self.key.__hash__()
|
||||
|
||||
def __eq__(self, rhs):
|
||||
return (self.key == rhs.key)
|
||||
|
||||
def __ne__(self, rhs):
|
||||
return (self.key != rhs.key or
|
||||
self.msap != rhs.msap or
|
||||
self.system_name != rhs.system_name or
|
||||
self.system_desc != rhs.system_desc or
|
||||
self.port_desc != rhs.port_desc or
|
||||
self.capabilities != rhs.capabilities or
|
||||
self.mgmt_addr != rhs.mgmt_addr or
|
||||
self.dot1_port_vid != rhs.dot1_port_vid or
|
||||
self.dot1_vid_digest != rhs.dot1_vid_digest or
|
||||
self.dot1_mgmt_vid != rhs.dot1_mgmt_vid or
|
||||
self.dot1_vid_digest != rhs.dot1_vid_digest or
|
||||
self.dot1_mgmt_vid != rhs.dot1_mgmt_vid or
|
||||
self.dot1_lag != rhs.dot1_lag or
|
||||
self.dot1_vlan_names != rhs.dot1_vlan_names or
|
||||
self.dot1_proto_vids != rhs.dot1_proto_vids or
|
||||
self.dot1_proto_ids != rhs.dot1_proto_ids or
|
||||
self.dot3_mac_status != rhs.dot3_mac_status or
|
||||
self.dot3_max_frame != rhs.dot3_max_frame or
|
||||
self.dot3_power_mdi != rhs.dot3_power_mdi)
|
||||
|
||||
def __str__(self):
|
||||
return "%s [%s] [%s] [%s], [%s]" % (
|
||||
self.key, self.system_name, self.system_desc,
|
||||
self.port_desc, self.capabilities)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Neighbour '%s'>" % str(self)
|
||||
|
||||
|
||||
class LLDPOperator(object):
|
||||
'''Class to encapsulate LLDP operations for System Inventory'''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._lock = threading.Lock()
|
||||
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 lldpd_get_agent_status(self):
|
||||
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"
|
||||
|
||||
def lldpd_get_attrs(self, 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,
|
||||
constants.LLDP_TLV_TYPE_CHASSIS_ID: chassis_id,
|
||||
constants.LLDP_TLV_TYPE_PORT_ID: port_id,
|
||||
constants.LLDP_TLV_TYPE_TTL: ttl,
|
||||
"msap": msap,
|
||||
constants.LLDP_TLV_TYPE_SYSTEM_NAME: system_name,
|
||||
constants.LLDP_TLV_TYPE_SYSTEM_DESC: system_desc,
|
||||
constants.LLDP_TLV_TYPE_SYSTEM_CAP: capability,
|
||||
constants.LLDP_TLV_TYPE_MGMT_ADDR: management_address,
|
||||
constants.LLDP_TLV_TYPE_PORT_DESC: port_desc,
|
||||
constants.LLDP_TLV_TYPE_DOT1_LAG: dot1_lag,
|
||||
constants.LLDP_TLV_TYPE_DOT1_PORT_VID: dot1_port_vid,
|
||||
constants.LLDP_TLV_TYPE_DOT1_VID_DIGEST: dot1_vid_digest,
|
||||
constants.LLDP_TLV_TYPE_DOT1_MGMT_VID: dot1_mgmt_vid,
|
||||
constants.LLDP_TLV_TYPE_DOT1_VLAN_NAMES: dot1_vlan_names,
|
||||
constants.LLDP_TLV_TYPE_DOT1_PROTO_VIDS: dot1_proto_vids,
|
||||
constants.LLDP_TLV_TYPE_DOT1_PROTO_IDS: dot1_proto_ids,
|
||||
constants.LLDP_TLV_TYPE_DOT3_MAC_STATUS: dot3_mac_status,
|
||||
constants.LLDP_TLV_TYPE_DOT3_MAX_FRAME: dot3_max_frame,
|
||||
constants.LLDP_TLV_TYPE_DOT3_POWER_MDI: dot3_power_mdi}
|
||||
|
||||
return attrs
|
||||
|
||||
def lldpd_has_neighbour(self, name):
|
||||
'''check if the interface has LLDP neighbours'''
|
||||
p = subprocess.check_output(["lldpcli", "-f", "keyvalue", "show",
|
||||
"neighbors", "summary", "ports", name])
|
||||
return len(p) > 0
|
||||
|
||||
def lldpd_agent_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 = Agent(**agent_attrs)
|
||||
lldp_agents.append(agent)
|
||||
|
||||
return lldp_agents
|
||||
|
||||
def lldpd_neighbour_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 = Neighbour(**neighbour_attrs)
|
||||
lldp_neighbours.append(neighbour)
|
||||
|
||||
return lldp_neighbours
|
||||
|
||||
def _do_request(self, callable):
|
||||
"""Thread safe wrapper for executing client requests.
|
||||
|
||||
"""
|
||||
|
||||
with self._lock:
|
||||
return callable()
|
||||
|
||||
def _execute_lldp_request(self, callable, snat=None):
|
||||
try:
|
||||
return self._do_request(callable)
|
||||
except Exception as e:
|
||||
LOG.error("Failed to execute LLDP request: %s", str(e))
|
||||
|
||||
def vswitch_lldp_get_status(self, admin_status):
|
||||
if admin_status == "enabled":
|
||||
status = "rx=enabled,tx=enabled"
|
||||
elif admin_status == "tx-only":
|
||||
status = "rx=disabled,tx=enabled"
|
||||
elif admin_status == "rx-only":
|
||||
status = "rx=enabled,tx=disabled"
|
||||
else:
|
||||
status = "rx=disabled,tx=disabled"
|
||||
return status
|
||||
|
||||
def vswitch_lldp_get_attrs(self, agent_neighbour_dict):
|
||||
attrs = {}
|
||||
|
||||
vswitch_to_db_dict = {'local-chassis':
|
||||
constants.LLDP_TLV_TYPE_CHASSIS_ID,
|
||||
'local-port': constants.LLDP_TLV_TYPE_PORT_ID,
|
||||
'remote-chassis':
|
||||
constants.LLDP_TLV_TYPE_CHASSIS_ID,
|
||||
'remote-port': constants.LLDP_TLV_TYPE_PORT_ID,
|
||||
'tx-ttl': constants.LLDP_TLV_TYPE_TTL,
|
||||
'rx-ttl': constants.LLDP_TLV_TYPE_TTL,
|
||||
'system-name':
|
||||
constants.LLDP_TLV_TYPE_SYSTEM_NAME,
|
||||
'system-description':
|
||||
constants.LLDP_TLV_TYPE_SYSTEM_DESC,
|
||||
'port-description':
|
||||
constants.LLDP_TLV_TYPE_PORT_DESC,
|
||||
'system-capabilities':
|
||||
constants.LLDP_TLV_TYPE_SYSTEM_CAP,
|
||||
'management-address':
|
||||
constants.LLDP_TLV_TYPE_MGMT_ADDR,
|
||||
'dot1-lag': constants.LLDP_TLV_TYPE_DOT1_LAG,
|
||||
'dot1-management-vid':
|
||||
constants.LLDP_TLV_TYPE_DOT1_MGMT_VID,
|
||||
'dot1-port-vid':
|
||||
constants.LLDP_TLV_TYPE_DOT1_PORT_VID,
|
||||
'dot1-proto-ids':
|
||||
constants.LLDP_TLV_TYPE_DOT1_PROTO_IDS,
|
||||
'dot1-proto-vids':
|
||||
constants.LLDP_TLV_TYPE_DOT1_PROTO_VIDS,
|
||||
'dot1-vid-digest':
|
||||
constants.LLDP_TLV_TYPE_DOT1_VID_DIGEST,
|
||||
'dot1-vlan-names':
|
||||
constants.LLDP_TLV_TYPE_DOT1_VLAN_NAMES,
|
||||
'dot3-lag':
|
||||
constants.LLDP_TLV_TYPE_DOT1_LAG,
|
||||
'dot3-mac-status':
|
||||
constants.LLDP_TLV_TYPE_DOT3_MAC_STATUS,
|
||||
'dot3-max-frame':
|
||||
constants.LLDP_TLV_TYPE_DOT3_MAX_FRAME,
|
||||
'dot3-power-mdi':
|
||||
constants.LLDP_TLV_TYPE_DOT3_POWER_MDI}
|
||||
|
||||
for k, v in vswitch_to_db_dict.iteritems():
|
||||
if k in agent_neighbour_dict:
|
||||
if agent_neighbour_dict[k]:
|
||||
attr = {v: agent_neighbour_dict[k]}
|
||||
else:
|
||||
attr = {v: None}
|
||||
attrs.update(attr)
|
||||
|
||||
msap = attrs[constants.LLDP_TLV_TYPE_CHASSIS_ID] \
|
||||
+ "," + attrs[constants.LLDP_TLV_TYPE_PORT_ID]
|
||||
|
||||
attr = {"name_or_uuid": agent_neighbour_dict["port-uuid"],
|
||||
"msap": msap}
|
||||
attrs.update(attr)
|
||||
|
||||
return attrs
|
||||
|
||||
def vswitch_lldp_agent_list(self):
|
||||
"""Sends a request to the vswitch requesting the full list of LLDP agent
|
||||
|
||||
entries.
|
||||
"""
|
||||
|
||||
LOG.error("vswitch_lldp_agent_list is not implemented.")
|
||||
return []
|
||||
|
||||
def vswitch_lldp_neighbour_list(self):
|
||||
"""Sends a request to the vswitch requesting the full list of LLDP
|
||||
|
||||
neighbour entries.
|
||||
"""
|
||||
|
||||
LOG.error("vswitch_lldp_neighbour_ist s not implemented.")
|
||||
return []
|
||||
|
||||
def lldp_agents_list(self, do_compute=False):
|
||||
self.agent_audit_count += 1
|
||||
if self.agent_audit_count > constants.LLDP_FULL_AUDIT_COUNT:
|
||||
LOG.debug("LLDP agent audit: triggering full sync")
|
||||
self.agent_audit_count = 0
|
||||
self.lldp_agents_clear()
|
||||
|
||||
self.previous_agents = self.current_agents
|
||||
self.current_agents = self.lldpd_agent_list()
|
||||
|
||||
if do_compute:
|
||||
self.current_agents += self.vswitch_lldp_agent_list()
|
||||
|
||||
current = set(self.current_agents)
|
||||
previous = set(self.previous_agents)
|
||||
removed = previous - current
|
||||
|
||||
agent_array = []
|
||||
for a in self.current_agents:
|
||||
agent_array.append(a)
|
||||
|
||||
if removed:
|
||||
for r in removed:
|
||||
LOG.debug("LLDP agent audit: detected removed agent")
|
||||
r.state = constants.LLDP_AGENT_STATE_REMOVED
|
||||
agent_array.append(r)
|
||||
return agent_array
|
||||
|
||||
# Check that there is actual state changes and return an empty list if
|
||||
# nothing changed.
|
||||
if self.previous_agents:
|
||||
pairs = zip(sorted(current, key=attrgetter('key')),
|
||||
sorted(previous, key=attrgetter('key')))
|
||||
if not any(x != y for x, y in pairs):
|
||||
LOG.debug("LLDP agent audit: No changes")
|
||||
return []
|
||||
|
||||
return agent_array
|
||||
|
||||
def lldp_agents_clear(self):
|
||||
self.current_agents = []
|
||||
self.previous_agents = []
|
||||
|
||||
def lldp_neighbours_list(self, do_compute=False):
|
||||
self.neighbour_audit_count += 1
|
||||
if self.neighbour_audit_count > constants.LLDP_FULL_AUDIT_COUNT:
|
||||
LOG.debug("LLDP neighbour audit: triggering full sync")
|
||||
self.neighbour_audit_count = 0
|
||||
self.lldp_neighbours_clear()
|
||||
|
||||
self.previous_neighbours = self.current_neighbours
|
||||
self.current_neighbours = self.lldpd_neighbour_list()
|
||||
|
||||
if do_compute:
|
||||
self.current_neighbours += self.vswitch_lldp_neighbour_list()
|
||||
|
||||
current = set(self.current_neighbours)
|
||||
previous = set(self.previous_neighbours)
|
||||
removed = previous - current
|
||||
|
||||
neighbour_array = []
|
||||
for n in self.current_neighbours:
|
||||
neighbour_array.append(n)
|
||||
|
||||
if removed:
|
||||
for r in removed:
|
||||
LOG.debug("LLDP neighbour audit: detected removed neighbour")
|
||||
r.state = constants.LLDP_NEIGHBOUR_STATE_REMOVED
|
||||
neighbour_array.append(r)
|
||||
return neighbour_array
|
||||
|
||||
# Check that there is actual state changes and return an empty list if
|
||||
# nothing changed.
|
||||
if self.previous_neighbours:
|
||||
pairs = zip(sorted(current, key=attrgetter('key')),
|
||||
sorted(previous, key=attrgetter('key')))
|
||||
if not any(x != y for x, y in pairs):
|
||||
LOG.debug("LLDP neighbour audit: No changes")
|
||||
return []
|
||||
|
||||
return neighbour_array
|
||||
|
||||
def lldp_neighbours_clear(self):
|
||||
self.current_neighbours = []
|
||||
self.previous_neighbours = []
|
||||
|
||||
def lldp_update_systemname(self, context, systemname, do_compute=False):
|
||||
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)
|
||||
|
||||
if do_compute:
|
||||
LOG.error("lldp_update_systemname failed due to lack of vswitch")
|
0
sysinv/sysinv/sysinv/sysinv/agent/lldp/__init__.py
Normal file
0
sysinv/sysinv/sysinv/sysinv/agent/lldp/__init__.py
Normal file
23
sysinv/sysinv/sysinv/sysinv/agent/lldp/config.py
Normal file
23
sysinv/sysinv/sysinv/sysinv/agent/lldp/config.py
Normal file
@ -0,0 +1,23 @@
|
||||
#
|
||||
# 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_config import cfg
|
||||
from oslo_utils._i18n import _
|
||||
|
||||
SYSINV_LLDP_OPTS = [
|
||||
cfg.ListOpt('drivers',
|
||||
default=['lldpd'],
|
||||
help=_("An ordered list of sysinv LLDP driver "
|
||||
"entrypoints to be loaded from the "
|
||||
"sysinv.agent namespace.")),
|
||||
]
|
||||
|
||||
cfg.CONF.register_opts(SYSINV_LLDP_OPTS, group="lldp")
|
47
sysinv/sysinv/sysinv/sysinv/agent/lldp/drivers/base.py
Normal file
47
sysinv/sysinv/sysinv/sysinv/agent/lldp/drivers/base.py
Normal file
@ -0,0 +1,47 @@
|
||||
#
|
||||
# Copyright (c) 2018 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# All Rights Reserved.
|
||||
#
|
||||
|
||||
import abc
|
||||
|
||||
import six
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class SysinvLldpDriverBase(object):
|
||||
"""Sysinv LLDP Driver Base Class."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def lldp_has_neighbour(self, name):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def lldp_update(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def lldp_agents_list(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def lldp_neighbours_list(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def lldp_agents_clear(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def lldp_neighbours_clear(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def lldp_update_systemname(self, systemname):
|
||||
pass
|
321
sysinv/sysinv/sysinv/sysinv/agent/lldp/drivers/lldpd/driver.py
Normal file
321
sysinv/sysinv/sysinv/sysinv/agent/lldp/drivers/lldpd/driver.py
Normal file
@ -0,0 +1,321 @@
|
||||
#
|
||||
# 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 sysinv.agent.lldp.drivers import base
|
||||
from sysinv.agent.lldp import plugin
|
||||
from sysinv.common import constants
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SysinvLldpdAgentDriver(base.SysinvLldpDriverBase):
|
||||
|
||||
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,
|
||||
constants.LLDP_TLV_TYPE_CHASSIS_ID: chassis_id,
|
||||
constants.LLDP_TLV_TYPE_PORT_ID: port_id,
|
||||
constants.LLDP_TLV_TYPE_TTL: ttl,
|
||||
"msap": msap,
|
||||
constants.LLDP_TLV_TYPE_SYSTEM_NAME: system_name,
|
||||
constants.LLDP_TLV_TYPE_SYSTEM_DESC: system_desc,
|
||||
constants.LLDP_TLV_TYPE_SYSTEM_CAP: capability,
|
||||
constants.LLDP_TLV_TYPE_MGMT_ADDR: management_address,
|
||||
constants.LLDP_TLV_TYPE_PORT_DESC: port_desc,
|
||||
constants.LLDP_TLV_TYPE_DOT1_LAG: dot1_lag,
|
||||
constants.LLDP_TLV_TYPE_DOT1_PORT_VID: dot1_port_vid,
|
||||
constants.LLDP_TLV_TYPE_DOT1_VID_DIGEST: dot1_vid_digest,
|
||||
constants.LLDP_TLV_TYPE_DOT1_MGMT_VID: dot1_mgmt_vid,
|
||||
constants.LLDP_TLV_TYPE_DOT1_VLAN_NAMES: dot1_vlan_names,
|
||||
constants.LLDP_TLV_TYPE_DOT1_PROTO_VIDS: dot1_proto_vids,
|
||||
constants.LLDP_TLV_TYPE_DOT1_PROTO_IDS: dot1_proto_ids,
|
||||
constants.LLDP_TLV_TYPE_DOT3_MAC_STATUS: dot3_mac_status,
|
||||
constants.LLDP_TLV_TYPE_DOT3_MAX_FRAME: dot3_max_frame,
|
||||
constants.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)
|
166
sysinv/sysinv/sysinv/sysinv/agent/lldp/drivers/ovs/driver.py
Normal file
166
sysinv/sysinv/sysinv/sysinv/agent/lldp/drivers/ovs/driver.py
Normal file
@ -0,0 +1,166 @@
|
||||
#
|
||||
# Copyright (c) 2018 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# All Rights Reserved.
|
||||
#
|
||||
|
||||
import simplejson as json
|
||||
import subprocess
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from sysinv.agent.lldp.drivers.lldpd import driver as lldpd_driver
|
||||
from sysinv.common import constants
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SysinvOVSAgentDriver(lldpd_driver.SysinvLldpdAgentDriver):
|
||||
|
||||
def run_cmd(self, cmd):
|
||||
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
p.wait()
|
||||
output, error = p.communicate()
|
||||
if p.returncode != 0:
|
||||
LOG.error("Failed to run command %s: error: %s", cmd, error)
|
||||
return None
|
||||
return output
|
||||
|
||||
def lldp_ovs_get_interface_port_map(self):
|
||||
interface_port_map = {}
|
||||
|
||||
cmd = "ovs-vsctl --timeout 10 --format json "\
|
||||
"--columns name,_uuid,interfaces list Port"
|
||||
|
||||
output = self.run_cmd(cmd)
|
||||
if not output:
|
||||
return
|
||||
|
||||
ports = json.loads(output)
|
||||
ports = ports['data']
|
||||
|
||||
for port in ports:
|
||||
port_uuid = port[1][1]
|
||||
interfaces = port[2][1]
|
||||
|
||||
if isinstance(interfaces, list):
|
||||
for interface in interfaces:
|
||||
interface_uuid = interface[1]
|
||||
interface_port_map[interface_uuid] = port_uuid
|
||||
else:
|
||||
interface_uuid = interfaces
|
||||
interface_port_map[interface_uuid] = port_uuid
|
||||
|
||||
return interface_port_map
|
||||
|
||||
def lldp_ovs_get_port_bridge_map(self):
|
||||
port_bridge_map = {}
|
||||
|
||||
cmd = "ovs-vsctl --timeout 10 --format json "\
|
||||
"--columns name,ports list Bridge"
|
||||
output = self.run_cmd(cmd)
|
||||
if not output:
|
||||
return
|
||||
|
||||
bridges = json.loads(output)
|
||||
bridges = bridges['data']
|
||||
|
||||
for bridge in bridges:
|
||||
bridge_name = bridge[0]
|
||||
port_set = bridge[1][1]
|
||||
for port in port_set:
|
||||
value = port[1]
|
||||
port_bridge_map[value] = bridge_name
|
||||
|
||||
return port_bridge_map
|
||||
|
||||
def lldp_ovs_lldp_flow_exists(self, brname, in_port):
|
||||
|
||||
cmd = "ovs-ofctl dump-flows {} in_port={},dl_dst={},dl_type={}".format(
|
||||
brname, in_port, constants.LLDP_MULTICAST_ADDRESS,
|
||||
constants.LLDP_ETHER_TYPE)
|
||||
output = self.run_cmd(cmd)
|
||||
if not output:
|
||||
return None
|
||||
|
||||
return (output.count("\n") > 1)
|
||||
|
||||
def lldp_ovs_add_flows(self, brname, in_port, out_port):
|
||||
|
||||
cmd = ("ovs-ofctl add-flow {} in_port={},dl_dst={},dl_type={},"
|
||||
"actions=output:{}".format(
|
||||
brname, in_port, constants.LLDP_MULTICAST_ADDRESS,
|
||||
constants.LLDP_ETHER_TYPE, out_port))
|
||||
output = self.run_cmd(cmd)
|
||||
if not output:
|
||||
return
|
||||
|
||||
cmd = ("ovs-ofctl add-flow {} in_port={},dl_dst={},dl_type={},"
|
||||
"actions=output:{}".format(
|
||||
brname, out_port, constants.LLDP_MULTICAST_ADDRESS,
|
||||
constants.LLDP_ETHER_TYPE, in_port))
|
||||
output = self.run_cmd(cmd)
|
||||
if not output:
|
||||
return
|
||||
|
||||
def lldp_ovs_update_flows(self):
|
||||
|
||||
port_bridge_map = self.lldp_ovs_get_port_bridge_map()
|
||||
if not port_bridge_map:
|
||||
return
|
||||
|
||||
interface_port_map = self.lldp_ovs_get_interface_port_map()
|
||||
if not interface_port_map:
|
||||
return
|
||||
|
||||
cmd = "ovs-vsctl --timeout 10 --format json "\
|
||||
"--columns name,_uuid,type,other_config list Interface"
|
||||
|
||||
output = self.run_cmd(cmd)
|
||||
if not output:
|
||||
return
|
||||
|
||||
data = json.loads(output)
|
||||
data = data['data']
|
||||
|
||||
for interface in data:
|
||||
name = interface[0]
|
||||
uuid = interface[1][1]
|
||||
type = interface[2]
|
||||
other_config = interface[3]
|
||||
|
||||
if type != 'internal':
|
||||
continue
|
||||
|
||||
config_map = other_config[1]
|
||||
for config in config_map:
|
||||
key = config[0]
|
||||
value = config[1]
|
||||
if key != 'lldp_phy_peer':
|
||||
continue
|
||||
|
||||
phy_peer = value
|
||||
brname = port_bridge_map[interface_port_map[uuid]]
|
||||
if not self.lldp_ovs_lldp_flow_exists(brname, name):
|
||||
LOG.info("Adding missing LLDP flow from %s to %s",
|
||||
name, phy_peer)
|
||||
self.lldp_ovs_add_flows(brname, name, phy_peer)
|
||||
|
||||
if not self.lldp_ovs_lldp_flow_exists(brname, value):
|
||||
LOG.info("Adding missing LLDP flow from %s to %s",
|
||||
phy_peer, name)
|
||||
self.lldp_ovs_add_flows(brname, phy_peer, name)
|
||||
|
||||
def lldp_agents_list(self):
|
||||
self.lldp_ovs_update_flows()
|
||||
return lldpd_driver.SysinvLldpdAgentDriver.lldp_agents_list(self)
|
||||
|
||||
def lldp_neighbours_list(self):
|
||||
self.lldp_ovs_update_flows()
|
||||
return lldpd_driver.SysinvLldpdAgentDriver.lldp_neighbours_list(self)
|
176
sysinv/sysinv/sysinv/sysinv/agent/lldp/manager.py
Normal file
176
sysinv/sysinv/sysinv/sysinv/agent/lldp/manager.py
Normal file
@ -0,0 +1,176 @@
|
||||
#
|
||||
# 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_config import cfg
|
||||
from oslo_log import log
|
||||
from stevedore.named import NamedExtensionManager
|
||||
from sysinv.common import exception
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
cfg.CONF.import_opt('drivers',
|
||||
'sysinv.agent.lldp.config',
|
||||
group='lldp')
|
||||
|
||||
|
||||
class SysinvLldpDriverManager(NamedExtensionManager):
|
||||
"""Implementation of Sysinv LLDP drivers."""
|
||||
|
||||
def __init__(self, namespace='sysinv.agent.lldp.drivers'):
|
||||
|
||||
# Registered sysinv lldp agent drivers, keyed by name.
|
||||
self.drivers = {}
|
||||
|
||||
# Ordered list of sysinv lldp agent drivers, defining
|
||||
# the order in which the drivers are called.
|
||||
self.ordered_drivers = []
|
||||
|
||||
names = cfg.CONF.lldp.drivers
|
||||
LOG.info("Configured sysinv LLDP agent drivers: %s", names)
|
||||
|
||||
super(SysinvLldpDriverManager, self).__init__(
|
||||
namespace,
|
||||
names,
|
||||
invoke_on_load=True,
|
||||
name_order=True)
|
||||
|
||||
LOG.info("Loaded sysinv LLDP agent drivers: %s", self.names())
|
||||
self._register_drivers()
|
||||
|
||||
def _register_drivers(self):
|
||||
"""Register all sysinv LLDP agent drivers.
|
||||
|
||||
This method should only be called once in the
|
||||
SysinvLldpDriverManager constructor.
|
||||
"""
|
||||
for ext in self:
|
||||
self.drivers[ext.name] = ext
|
||||
self.ordered_drivers.append(ext)
|
||||
LOG.info("Registered sysinv LLDP agent drivers: %s",
|
||||
[driver.name for driver in self.ordered_drivers])
|
||||
|
||||
def _call_drivers_and_return_array(self, method_name, attr=None,
|
||||
raise_orig_exc=False):
|
||||
"""Helper method for calling a method across all drivers.
|
||||
|
||||
:param method_name: name of the method to call
|
||||
:param attr: an optional attribute to provide to the drivers
|
||||
:param raise_orig_exc: whether or not to raise the original
|
||||
driver exception, or use a general one
|
||||
"""
|
||||
ret = []
|
||||
for driver in self.ordered_drivers:
|
||||
try:
|
||||
method = getattr(driver.obj, method_name)
|
||||
if attr:
|
||||
ret = ret + method(attr)
|
||||
else:
|
||||
ret = ret + method()
|
||||
except Exception as e:
|
||||
LOG.exception(e)
|
||||
LOG.error(
|
||||
"Sysinv LLDP agent driver '%(name)s' "
|
||||
"failed in %(method)s",
|
||||
{'name': driver.name, 'method': method_name}
|
||||
)
|
||||
if raise_orig_exc:
|
||||
raise
|
||||
else:
|
||||
raise exception.LLDPDriverError(
|
||||
method=method_name
|
||||
)
|
||||
return list(set(ret))
|
||||
|
||||
def _call_drivers(self, method_name, attr=None, raise_orig_exc=False):
|
||||
"""Helper method for calling a method across all drivers.
|
||||
|
||||
:param method_name: name of the method to call
|
||||
:param attr: an optional attribute to provide to the drivers
|
||||
:param raise_orig_exc: whether or not to raise the original
|
||||
driver exception, or use a general one
|
||||
"""
|
||||
for driver in self.ordered_drivers:
|
||||
try:
|
||||
method = getattr(driver.obj, method_name)
|
||||
if attr:
|
||||
return method(attr)
|
||||
else:
|
||||
return method()
|
||||
except Exception as e:
|
||||
LOG.exception(e)
|
||||
LOG.error(
|
||||
"Sysinv LLDP agent driver '%(name)s' "
|
||||
"failed in %(method)s",
|
||||
{'name': driver.name, 'method': method_name}
|
||||
)
|
||||
if raise_orig_exc:
|
||||
raise
|
||||
else:
|
||||
raise exception.LLDPDriverError(
|
||||
method=method_name
|
||||
)
|
||||
|
||||
def lldp_has_neighbour(self, name):
|
||||
try:
|
||||
return self._call_drivers("lldp_has_neighbour",
|
||||
attr=name,
|
||||
raise_orig_exc=True)
|
||||
except Exception as e:
|
||||
LOG.exception(e)
|
||||
return []
|
||||
|
||||
def lldp_update(self):
|
||||
try:
|
||||
return self._call_drivers("lldp_update",
|
||||
raise_orig_exc=True)
|
||||
except Exception as e:
|
||||
LOG.exception(e)
|
||||
return []
|
||||
|
||||
def lldp_agents_list(self):
|
||||
try:
|
||||
return self._call_drivers_and_return_array("lldp_agents_list",
|
||||
raise_orig_exc=True)
|
||||
except Exception as e:
|
||||
LOG.exception(e)
|
||||
return []
|
||||
|
||||
def lldp_neighbours_list(self):
|
||||
try:
|
||||
return self._call_drivers_and_return_array("lldp_neighbours_list",
|
||||
raise_orig_exc=True)
|
||||
except Exception as e:
|
||||
LOG.exception(e)
|
||||
return []
|
||||
|
||||
def lldp_agents_clear(self):
|
||||
try:
|
||||
return self._call_drivers("lldp_agents_clear",
|
||||
raise_orig_exc=True)
|
||||
except Exception as e:
|
||||
LOG.exception(e)
|
||||
return
|
||||
|
||||
def lldp_neighbours_clear(self):
|
||||
try:
|
||||
return self._call_drivers("lldp_neighbours_clear",
|
||||
raise_orig_exc=True)
|
||||
except Exception as e:
|
||||
LOG.exception(e)
|
||||
return
|
||||
|
||||
def lldp_update_systemname(self, systemname):
|
||||
try:
|
||||
return self._call_drivers("lldp_update_systemname",
|
||||
attr=systemname,
|
||||
raise_orig_exc=True)
|
||||
except Exception as e:
|
||||
LOG.exception(e)
|
||||
return
|
245
sysinv/sysinv/sysinv/sysinv/agent/lldp/plugin.py
Normal file
245
sysinv/sysinv/sysinv/sysinv/agent/lldp/plugin.py
Normal file
@ -0,0 +1,245 @@
|
||||
#
|
||||
# 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
|
||||
|
||||
from sysinv.agent.lldp import manager
|
||||
from sysinv.common import exception
|
||||
from sysinv.common import constants
|
||||
from sysinv.openstack.common import excutils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Key(object):
|
||||
def __init__(self, chassisid, portid, portname):
|
||||
self.chassisid = chassisid
|
||||
self.portid = portid
|
||||
self.portname = portname
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.chassisid, self.portid, self.portname))
|
||||
|
||||
def __cmp__(self, rhs):
|
||||
return (cmp(self.chassisid, rhs.chassisid) or
|
||||
cmp(self.portid, rhs.portid) or
|
||||
cmp(self.portname, rhs.portname))
|
||||
|
||||
def __eq__(self, rhs):
|
||||
return (self.chassisid == rhs.chassisid and
|
||||
self.portid == rhs.portid and
|
||||
self.portname == rhs.portname)
|
||||
|
||||
def __ne__(self, rhs):
|
||||
return (self.chassisid != rhs.chassisid or
|
||||
self.portid != rhs.portid or
|
||||
self.portname != rhs.portname)
|
||||
|
||||
def __str__(self):
|
||||
return "%s [%s] [%s]" % (self.portname, self.chassisid, self.portid)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Key '%s'>" % str(self)
|
||||
|
||||
|
||||
class Agent(object):
|
||||
'''Class to encapsulate LLDP agent data for System Inventory'''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
'''Construct an Agent object with the given values.'''
|
||||
self.key = Key(kwargs.get(constants.LLDP_TLV_TYPE_CHASSIS_ID),
|
||||
kwargs.get(constants.LLDP_TLV_TYPE_PORT_ID),
|
||||
kwargs.get("name_or_uuid"))
|
||||
self.status = kwargs.get('status')
|
||||
self.ttl = kwargs.get(constants.LLDP_TLV_TYPE_TTL)
|
||||
self.system_name = kwargs.get(constants.LLDP_TLV_TYPE_SYSTEM_NAME)
|
||||
self.system_desc = kwargs.get(constants.LLDP_TLV_TYPE_SYSTEM_DESC)
|
||||
self.port_desc = kwargs.get(constants.LLDP_TLV_TYPE_PORT_DESC)
|
||||
self.capabilities = kwargs.get(constants.LLDP_TLV_TYPE_SYSTEM_CAP)
|
||||
self.mgmt_addr = kwargs.get(constants.LLDP_TLV_TYPE_MGMT_ADDR)
|
||||
self.dot1_lag = kwargs.get(constants.LLDP_TLV_TYPE_DOT1_LAG)
|
||||
self.dot1_vlan_names = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT1_VLAN_NAMES)
|
||||
self.dot3_max_frame = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT3_MAX_FRAME)
|
||||
self.state = None
|
||||
|
||||
def __hash__(self):
|
||||
return self.key.__hash__()
|
||||
|
||||
def __eq__(self, rhs):
|
||||
return (self.key == rhs.key)
|
||||
|
||||
def __ne__(self, rhs):
|
||||
return (self.key != rhs.key or
|
||||
self.status != rhs.status or
|
||||
self.ttl != rhs.ttl or
|
||||
self.system_name != rhs.system_name or
|
||||
self.system_desc != rhs.system_desc or
|
||||
self.port_desc != rhs.port_desc or
|
||||
self.capabilities != rhs.capabilities or
|
||||
self.mgmt_addr != rhs.mgmt_addr or
|
||||
self.dot1_lag != rhs.dot1_lag or
|
||||
self.dot1_vlan_names != rhs.dot1_vlan_names or
|
||||
self.dot3_max_frame != rhs.dot3_max_frame or
|
||||
self.state != rhs.state)
|
||||
|
||||
def __str__(self):
|
||||
return "%s: [%s] [%s] [%s], [%s], [%s], [%s], [%s], [%s]" % (
|
||||
self.key, self.status, self.system_name, self.system_desc,
|
||||
self.port_desc, self.capabilities,
|
||||
self.mgmt_addr, self.dot1_lag,
|
||||
self.dot3_max_frame)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Agent '%s'>" % str(self)
|
||||
|
||||
|
||||
class Neighbour(object):
|
||||
'''Class to encapsulate LLDP neighbour data for System Inventory'''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
'''Construct an Neighbour object with the given values.'''
|
||||
self.key = Key(kwargs.get(constants.LLDP_TLV_TYPE_CHASSIS_ID),
|
||||
kwargs.get(constants.LLDP_TLV_TYPE_PORT_ID),
|
||||
kwargs.get("name_or_uuid"))
|
||||
self.msap = kwargs.get('msap')
|
||||
self.ttl = kwargs.get(constants.LLDP_TLV_TYPE_TTL)
|
||||
self.system_name = kwargs.get(constants.LLDP_TLV_TYPE_SYSTEM_NAME)
|
||||
self.system_desc = kwargs.get(constants.LLDP_TLV_TYPE_SYSTEM_DESC)
|
||||
self.port_desc = kwargs.get(constants.LLDP_TLV_TYPE_PORT_DESC)
|
||||
self.capabilities = kwargs.get(constants.LLDP_TLV_TYPE_SYSTEM_CAP)
|
||||
self.mgmt_addr = kwargs.get(constants.LLDP_TLV_TYPE_MGMT_ADDR)
|
||||
self.dot1_port_vid = kwargs.get(constants.LLDP_TLV_TYPE_DOT1_PORT_VID)
|
||||
self.dot1_vid_digest = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT1_VID_DIGEST)
|
||||
self.dot1_mgmt_vid = kwargs.get(constants.LLDP_TLV_TYPE_DOT1_MGMT_VID)
|
||||
self.dot1_vid_digest = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT1_VID_DIGEST)
|
||||
self.dot1_mgmt_vid = kwargs.get(constants.LLDP_TLV_TYPE_DOT1_MGMT_VID)
|
||||
self.dot1_lag = kwargs.get(constants.LLDP_TLV_TYPE_DOT1_LAG)
|
||||
self.dot1_vlan_names = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT1_VLAN_NAMES)
|
||||
self.dot1_proto_vids = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT1_PROTO_VIDS)
|
||||
self.dot1_proto_ids = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT1_PROTO_IDS)
|
||||
self.dot3_mac_status = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT3_MAC_STATUS)
|
||||
self.dot3_max_frame = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT3_MAX_FRAME)
|
||||
self.dot3_power_mdi = kwargs.get(
|
||||
constants.LLDP_TLV_TYPE_DOT3_POWER_MDI)
|
||||
|
||||
self.state = None
|
||||
|
||||
def __hash__(self):
|
||||
return self.key.__hash__()
|
||||
|
||||
def __eq__(self, rhs):
|
||||
return (self.key == rhs.key)
|
||||
|
||||
def __ne__(self, rhs):
|
||||
return (self.key != rhs.key or
|
||||
self.msap != rhs.msap or
|
||||
self.system_name != rhs.system_name or
|
||||
self.system_desc != rhs.system_desc or
|
||||
self.port_desc != rhs.port_desc or
|
||||
self.capabilities != rhs.capabilities or
|
||||
self.mgmt_addr != rhs.mgmt_addr or
|
||||
self.dot1_port_vid != rhs.dot1_port_vid or
|
||||
self.dot1_vid_digest != rhs.dot1_vid_digest or
|
||||
self.dot1_mgmt_vid != rhs.dot1_mgmt_vid or
|
||||
self.dot1_vid_digest != rhs.dot1_vid_digest or
|
||||
self.dot1_mgmt_vid != rhs.dot1_mgmt_vid or
|
||||
self.dot1_lag != rhs.dot1_lag or
|
||||
self.dot1_vlan_names != rhs.dot1_vlan_names or
|
||||
self.dot1_proto_vids != rhs.dot1_proto_vids or
|
||||
self.dot1_proto_ids != rhs.dot1_proto_ids or
|
||||
self.dot3_mac_status != rhs.dot3_mac_status or
|
||||
self.dot3_max_frame != rhs.dot3_max_frame or
|
||||
self.dot3_power_mdi != rhs.dot3_power_mdi)
|
||||
|
||||
def __str__(self):
|
||||
return "%s [%s] [%s] [%s], [%s]" % (
|
||||
self.key, self.system_name, self.system_desc,
|
||||
self.port_desc, self.capabilities)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Neighbour '%s'>" % str(self)
|
||||
|
||||
|
||||
class SysinvLldpPlugin():
|
||||
|
||||
"""Implementation of the Plugin."""
|
||||
|
||||
def __init__(self):
|
||||
self.manager = manager.SysinvLldpDriverManager()
|
||||
|
||||
def lldp_has_neighbour(self, name):
|
||||
try:
|
||||
return self.manager.lldp_has_neighbour(name)
|
||||
except exception.LLDPDriverError as e:
|
||||
LOG.exception(e)
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error("LLDP has neighbour failed")
|
||||
|
||||
def lldp_update(self):
|
||||
try:
|
||||
self.manager.lldp_update()
|
||||
except exception.LLDPDriverError as e:
|
||||
LOG.exception(e)
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error("LLDP update failed")
|
||||
|
||||
def lldp_agents_list(self):
|
||||
try:
|
||||
agents = self.manager.lldp_agents_list()
|
||||
except exception.LLDPDriverError as e:
|
||||
LOG.exception(e)
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error("LLDP agents list failed")
|
||||
|
||||
return agents
|
||||
|
||||
def lldp_agents_clear(self):
|
||||
try:
|
||||
self.manager.lldp_agents_clear()
|
||||
except exception.LLDPDriverError as e:
|
||||
LOG.exception(e)
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error("LLDP agents clear failed")
|
||||
|
||||
def lldp_neighbours_list(self):
|
||||
try:
|
||||
neighbours = self.manager.lldp_neighbours_list()
|
||||
except exception.LLDPDriverError as e:
|
||||
LOG.exception(e)
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error("LLDP neighbours list failed")
|
||||
|
||||
return neighbours
|
||||
|
||||
def lldp_neighbours_clear(self):
|
||||
try:
|
||||
self.manager.lldp_neighbours_clear()
|
||||
except exception.LLDPDriverError as e:
|
||||
LOG.exception(e)
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error("LLDP neighbours clear failed")
|
||||
|
||||
def lldp_update_systemname(self, systemname):
|
||||
try:
|
||||
self.manager.lldp_update_systemname(systemname)
|
||||
except exception.LLDPDriverError as e:
|
||||
LOG.exception(e)
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error("LLDP update systemname failed")
|
@ -53,7 +53,7 @@ from sysinv.agent import pv
|
||||
from sysinv.agent import lvg
|
||||
from sysinv.agent import pci
|
||||
from sysinv.agent import node
|
||||
from sysinv.agent import lldp
|
||||
from sysinv.agent.lldp import plugin as lldp_plugin
|
||||
from sysinv.common import constants
|
||||
from sysinv.common import exception
|
||||
from sysinv.common import service
|
||||
@ -138,7 +138,7 @@ class AgentManager(service.PeriodicService):
|
||||
self._ipv_operator = pv.PVOperator()
|
||||
self._ipartition_operator = partition.PartitionOperator()
|
||||
self._ilvg_operator = lvg.LVGOperator()
|
||||
self._lldp_operator = lldp.LLDPOperator()
|
||||
self._lldp_operator = lldp_plugin.SysinvLldpPlugin()
|
||||
self._iconfig_read_config_reported = None
|
||||
self._ihost_personality = None
|
||||
self._ihost_uuid = ""
|
||||
@ -363,10 +363,8 @@ class AgentManager(service.PeriodicService):
|
||||
neighbours = []
|
||||
agents = []
|
||||
|
||||
do_compute = constants.COMPUTE in self.subfunctions_list_get()
|
||||
|
||||
try:
|
||||
neighbours = self._lldp_operator.lldp_neighbours_list(do_compute)
|
||||
neighbours = self._lldp_operator.lldp_neighbours_list()
|
||||
except Exception as e:
|
||||
LOG.error("Failed to get LLDP neighbours: %s", str(e))
|
||||
|
||||
@ -408,7 +406,7 @@ class AgentManager(service.PeriodicService):
|
||||
pass
|
||||
|
||||
try:
|
||||
agents = self._lldp_operator.lldp_agents_list(do_compute)
|
||||
agents = self._lldp_operator.lldp_agents_list()
|
||||
except Exception as e:
|
||||
LOG.error("Failed to get LLDP agents: %s", str(e))
|
||||
|
||||
@ -470,7 +468,8 @@ class AgentManager(service.PeriodicService):
|
||||
subprocess.call(['ip', 'link', 'set', interface, 'up'])
|
||||
links_down.append(interface)
|
||||
LOG.info('interface %s enabled to receive LLDP PDUs' % interface)
|
||||
subprocess.call(['lldpcli', 'update'])
|
||||
self._lldp_operator.lldp_update()
|
||||
|
||||
# delay maximum 30 seconds for lldpd to receive LLDP PDU
|
||||
timeout = 0
|
||||
link_wait_for_lldp = True
|
||||
@ -478,8 +477,9 @@ class AgentManager(service.PeriodicService):
|
||||
time.sleep(5)
|
||||
timeout = timeout + 5
|
||||
link_wait_for_lldp = False
|
||||
|
||||
for link in links_down:
|
||||
if not self._lldp_operator.lldpd_has_neighbour(link):
|
||||
if not self._lldp_operator.lldp_has_neighbour(link):
|
||||
link_wait_for_lldp = True
|
||||
break
|
||||
self.host_lldp_get_and_report(context, rpcapi, host_uuid)
|
||||
@ -1261,12 +1261,10 @@ class AgentManager(service.PeriodicService):
|
||||
:param systemname: the systemname
|
||||
"""
|
||||
|
||||
do_compute = constants.COMPUTE in self.subfunctions_list_get()
|
||||
rpcapi = conductor_rpcapi.ConductorAPI(
|
||||
topic=conductor_rpcapi.MANAGER_TOPIC)
|
||||
# Update the lldp agent
|
||||
self._lldp_operator.lldp_update_systemname(context, systemname,
|
||||
do_compute)
|
||||
self._lldp_operator.lldp_update_systemname(systemname)
|
||||
# Trigger an audit to ensure the db is up to date
|
||||
self.host_lldp_get_and_report(context, rpcapi, self._ihost_uuid)
|
||||
|
||||
|
@ -566,6 +566,10 @@ class LLDPTlvExists(Conflict):
|
||||
message = _("An LLDP TLV with type %(type) already exists.")
|
||||
|
||||
|
||||
class LLDPDriverError(Conflict):
|
||||
message = _("An LLDP driver error has occurred. method=%(method)")
|
||||
|
||||
|
||||
class SDNControllerAlreadyExists(Conflict):
|
||||
message = _("An SDN Controller with uuid %(uuid)s already exists.")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user