mirror of
https://github.com/xcat2/confluent.git
synced 2024-11-25 19:10:10 +00:00
Add affluent support to /networking
The /networking backend will now check for affluent on the switches and use it if possible for improved performance.
This commit is contained in:
parent
66e1d17d28
commit
48f0330568
@ -44,7 +44,7 @@ import eventlet
|
||||
from eventlet.greenpool import GreenPool
|
||||
import eventlet.semaphore
|
||||
import re
|
||||
|
||||
webclient = eventlet.import_patched('pyghmi.util.webclient')
|
||||
# The interesting OIDs are:
|
||||
# lldpLocChassisId - to cross reference (1.0.8802.1.1.2.1.3.2.0)
|
||||
# lldpLocPortId - for cross referencing.. (1.0.8802.1.1.2.1.3.7.1.3)
|
||||
@ -85,6 +85,7 @@ _neighdata = {}
|
||||
_neighbypeerid = {}
|
||||
_updatelocks = {}
|
||||
_chassisidbyswitch = {}
|
||||
_noaffluent = set([])
|
||||
|
||||
def lenovoname(idx, desc):
|
||||
if desc.isdigit():
|
||||
@ -171,21 +172,59 @@ def _init_lldp(data, iname, idx, idxtoportid, switch):
|
||||
data[iname] = {'port': iname, 'portid': str(idxtoportid[idx]),
|
||||
'chassisid': _chassisidbyswitch[switch]}
|
||||
|
||||
def _extract_neighbor_data_affluent(switch, user, password, cfm, lldpdata):
|
||||
kv = util.TLSCertVerifier(cfm, switch,
|
||||
'pubkeys.tls_hardwaremanager').verify_cert
|
||||
wc = webclient.SecureHTTPConnection(
|
||||
switch, 443, verifycallback=kv, timeout=5)
|
||||
wc.set_basic_credentials(user, password)
|
||||
neighdata = wc.grab_json_response('/affluent/lldp/all')
|
||||
chassisid = neighdata['chassis']['id']
|
||||
_chassisidbyswitch[switch] = chassisid,
|
||||
print(repr(neighdata))
|
||||
for record in neighdata['neighbors']:
|
||||
localport = record['localport']
|
||||
peerid = '{0}.{1}'.format(
|
||||
record.get('peerchassisid', '').replace(':', '-').replace('/', '-'),
|
||||
record.get('peerportid', '').replace(':', '-').replace('/', '-'),
|
||||
)
|
||||
portdata = {
|
||||
'verified': True, # It is over TLS after all
|
||||
'peerdescription': record.get('peerdescription', None),
|
||||
'peerchassisid': record['peerchassisid'],
|
||||
'peername': record['peername'],
|
||||
'switch': switch,
|
||||
'chassisid': chassisid,
|
||||
'portid': record['localport'],
|
||||
'peerportid': record['peerportid'],
|
||||
'port': record['localport'],
|
||||
'peerid': peerid,
|
||||
}
|
||||
_neighbypeerid[peerid] = portdata
|
||||
lldpdata[localport] = portdata
|
||||
neighdata[switch] = lldpdata
|
||||
|
||||
|
||||
def _extract_neighbor_data_b(args):
|
||||
"""Build LLDP data about elements connected to switch
|
||||
|
||||
args are carried as a tuple, because of eventlet convenience
|
||||
"""
|
||||
switch, password, user, force = args[:4]
|
||||
switch, password, user, cfm, force = args[:5]
|
||||
vintage = _neighdata.get(switch, {}).get('!!vintage', 0)
|
||||
now = util.monotonic_time()
|
||||
if vintage > (now - 60) and not force:
|
||||
return
|
||||
lldpdata = {'!!vintage': now}
|
||||
try:
|
||||
return _extract_neighbor_data_affluent(switch, user, password, cfm, lldpdata)
|
||||
except Exception:
|
||||
pass
|
||||
conn = snmp.Session(switch, password, user)
|
||||
sid = None
|
||||
lldpdata = {'!!vintage': now}
|
||||
for sysid in conn.walk('1.3.6.1.2.1.1.2'):
|
||||
sid = str(sysid[1][6:])
|
||||
_noaffluent.add(switch)
|
||||
idxtoifname = {}
|
||||
idxtoportid = {}
|
||||
_chassisidbyswitch[switch] = sanitize(list(
|
||||
@ -268,8 +307,8 @@ def _extract_neighbor_data(args):
|
||||
return _extract_neighbor_data_b(args)
|
||||
except Exception as e:
|
||||
yieldexc = False
|
||||
if len(args) >= 5:
|
||||
yieldexc = args[4]
|
||||
if len(args) >= 6:
|
||||
yieldexc = args[5]
|
||||
if yieldexc:
|
||||
return e
|
||||
else:
|
||||
@ -358,10 +397,3 @@ def _handle_neighbor_query(pathcomponents, configmanager):
|
||||
raise x
|
||||
return list_info(parms, listrequested)
|
||||
|
||||
|
||||
def _list_interfaces(switchname, configmanager):
|
||||
switchcreds = get_switchcreds(configmanager, (switchname,))
|
||||
switchcreds = switchcreds[0]
|
||||
conn = snmp.Session(*switchcreds)
|
||||
ifnames = netutil.get_portnamemap(conn)
|
||||
return util.natural_sort(ifnames.values())
|
@ -45,13 +45,16 @@ from eventlet.greenpool import GreenPool
|
||||
import eventlet
|
||||
import eventlet.semaphore
|
||||
import re
|
||||
webclient = eventlet.import_patched('pyghmi.util.webclient')
|
||||
|
||||
|
||||
noaffluent = set([])
|
||||
|
||||
_macmap = {}
|
||||
_apimacmap = {}
|
||||
_macsbyswitch = {}
|
||||
_nodesbymac = {}
|
||||
_switchportmap = {}
|
||||
_neighdata = {}
|
||||
vintage = None
|
||||
|
||||
|
||||
@ -127,6 +130,36 @@ def _nodelookup(switch, ifname):
|
||||
return None
|
||||
|
||||
|
||||
def _affluent_map_switch(args):
|
||||
switch, password, user, cfm = args
|
||||
kv = util.TLSCertVerifier(cfm, switch,
|
||||
'pubkeys.tls_hardwaremanager').verify_cert
|
||||
wc = webclient.SecureHTTPConnection(
|
||||
switch, 443, verifycallback=kv, timeout=5)
|
||||
wc.set_basic_credentials(user, password)
|
||||
macs = wc.grab_json_response('/affluent/macs/by-port')
|
||||
_macsbyswitch[switch] = macs
|
||||
|
||||
for iface in macs:
|
||||
nummacs = len(macs[iface])
|
||||
for mac in macs[iface]:
|
||||
if mac in _macmap:
|
||||
_macmap[mac].append((switch, iface, nummacs))
|
||||
else:
|
||||
_macmap[mac] = [(switch, iface, nummacs)]
|
||||
nodename = _nodelookup(switch, iface)
|
||||
if nodename is not None:
|
||||
if mac in _nodesbymac and _nodesbymac[mac][0] != nodename:
|
||||
# For example, listed on both a real edge port
|
||||
# and by accident a trunk port
|
||||
log.log({'error': '{0} and {1} described by ambiguous'
|
||||
' switch topology values'.format(
|
||||
nodename, _nodesbymac[mac][0])})
|
||||
_nodesbymac[mac] = (None, None)
|
||||
else:
|
||||
_nodesbymac[mac] = (nodename, nummacs)
|
||||
|
||||
|
||||
def _map_switch_backend(args):
|
||||
"""Manipulate portions of mac address map relevant to a given switch
|
||||
"""
|
||||
@ -144,13 +177,18 @@ def _map_switch_backend(args):
|
||||
# fallback if ifName is empty
|
||||
#
|
||||
global _macmap
|
||||
if len(args) == 3:
|
||||
switch, password, user = args
|
||||
if len(args) == 4:
|
||||
switch, password, user, cfm = args
|
||||
if not user:
|
||||
user = None
|
||||
else:
|
||||
switch, password = args
|
||||
user = None
|
||||
if switch not in noaffluent:
|
||||
try:
|
||||
return _affluent_map_switch(args)
|
||||
except Exception:
|
||||
pass
|
||||
haveqbridge = False
|
||||
mactobridge = {}
|
||||
conn = snmp.Session(switch, password, user)
|
||||
@ -164,6 +202,7 @@ def _map_switch_backend(args):
|
||||
*([int(x) for x in oid[-6:]])
|
||||
)
|
||||
mactobridge[macaddr] = int(bridgeport)
|
||||
noaffluent.add(switch)
|
||||
if not haveqbridge:
|
||||
for vb in conn.walk('1.3.6.1.2.1.17.4.3.1.2'):
|
||||
oid, bridgeport = vb
|
||||
|
@ -36,7 +36,7 @@ def get_switchcreds(configmanager, switches):
|
||||
'secret.hardwaremanagementuser', {}).get('value', None)
|
||||
if not user:
|
||||
user = None
|
||||
switchauth.append((switch, password, user))
|
||||
switchauth.append((switch, password, user, configmanager))
|
||||
return switchauth
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user