mirror of
https://github.com/xcat2/confluent.git
synced 2024-11-25 19:10:10 +00:00
Try to put the brakes on too many mac discovery attempts
In various scenarios, too many macs on a port can be a sign of trouble. For example, a chained SMM configuration with head on switch port, or incorrectly pointing a nodes net attributes at a switch uplink port, or defining SMMs without any nodes, causing XCCs to think they are rackmount. This sets some sanity value for avoiding problems. This is of course a mitigation, invalid scenarios could still run afoul of the limits, but it should catch a large chunk of offending scenarios.
This commit is contained in:
parent
0b0f325240
commit
76bfb29d60
@ -634,7 +634,17 @@ def get_nodename(cfg, handler, info):
|
||||
_map_unique_ids()
|
||||
nodename = nodes_by_uuid.get(curruuid, None)
|
||||
if not nodename: # as a last resort, search switch for info
|
||||
nodename = macmap.find_node_by_mac(info['hwaddr'], cfg)
|
||||
nodename, macinfo = macmap.find_nodeinfo_by_mac(info['hwaddr'], cfg)
|
||||
if (nodename and
|
||||
not handler.discoverable_by_switch(macinfo['maccount'])):
|
||||
if handler.devname == 'SMM':
|
||||
errorstr = 'Attempt to discover SMM by switch, but chained ' \
|
||||
'topology or incorrect net attributes detected, ' \
|
||||
'which is not compatible with switch discovery ' \
|
||||
'of SMM, nodename would have been ' \
|
||||
'{0}'.format(nodename)
|
||||
log.log({'error': errorstr})
|
||||
return None
|
||||
return nodename
|
||||
|
||||
|
||||
|
@ -19,6 +19,10 @@ webclient = eventlet.import_patched('pyghmi.util.webclient')
|
||||
class NodeHandler(object):
|
||||
https_supported = True
|
||||
is_enclosure = False
|
||||
devname = ''
|
||||
maxmacs = 2 # reasonable default, allowing for common scenario of
|
||||
# shared nic in theory, but blocking enclosure managers
|
||||
# and uplink ports
|
||||
|
||||
def __init__(self, info, configmanager):
|
||||
self._certfailreason = None
|
||||
@ -50,9 +54,10 @@ class NodeHandler(object):
|
||||
def preconfig(self):
|
||||
return
|
||||
|
||||
@property
|
||||
def discoverable_by_switch(self):
|
||||
return True
|
||||
def discoverable_by_switch(self, macs):
|
||||
# Given the number of macs sharing the port, is this handler
|
||||
# appropriate?
|
||||
return macs <= self.maxmacs
|
||||
|
||||
def _savecert(self, certificate):
|
||||
self._fp = certificate
|
||||
|
@ -26,6 +26,7 @@ def fixuuid(baduuid):
|
||||
class NodeHandler(bmchandler.NodeHandler):
|
||||
is_enclosure = True
|
||||
devname = 'SMM'
|
||||
maxmacs = 5 # support an enclosure, but try to avoid catching daisy chain
|
||||
|
||||
def scan(self):
|
||||
# the UUID is in a weird order, fix it up to match
|
||||
|
@ -229,33 +229,32 @@ def _map_switch_backend(args):
|
||||
_macsbyswitch[switch][ifname] = [mac]
|
||||
nodename = _nodelookup(switch, ifname)
|
||||
if nodename is not None:
|
||||
if mac in _nodesbymac and _nodesbymac[mac] != nodename:
|
||||
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]
|
||||
)})
|
||||
_nodesbymac[mac] = None
|
||||
' switch topology values'.format(
|
||||
nodename, _nodesbymac[mac][0])})
|
||||
_nodesbymac[mac] = (None, None)
|
||||
else:
|
||||
_nodesbymac[mac] = nodename
|
||||
_nodesbymac[mac] = (nodename, maccounts[ifname])
|
||||
|
||||
|
||||
switchbackoff = 30
|
||||
|
||||
|
||||
def find_node_by_mac(mac, configmanager):
|
||||
def find_nodeinfo_by_mac(mac, configmanager):
|
||||
now = util.monotonic_time()
|
||||
if vintage and (now - vintage) < 90 and mac in _nodesbymac:
|
||||
return _nodesbymac[mac]
|
||||
return _nodesbymac[mac][0], {'maccount': _nodesbymac[mac][1]}
|
||||
# do not actually sweep switches more than once every 30 seconds
|
||||
# however, if there is an update in progress, wait on it
|
||||
for _ in update_macmap(configmanager,
|
||||
vintage and (now - vintage) < switchbackoff):
|
||||
if mac in _nodesbymac:
|
||||
return _nodesbymac[mac]
|
||||
return _nodesbymac[mac][0], {'maccount': _nodesbymac[mac][1]}
|
||||
# If update_mac bailed out, still check one last time
|
||||
return _nodesbymac.get(mac, None)
|
||||
return _nodesbymac.get(mac, (None, {'maccount': 0}))
|
||||
|
||||
|
||||
mapupdating = eventlet.semaphore.Semaphore()
|
||||
@ -456,7 +455,7 @@ def dump_macinfo(macaddr):
|
||||
raise exc.NotFoundException(
|
||||
'{0} not found in mac table of '
|
||||
'any known switches'.format(macaddr))
|
||||
return _dump_locations(info, macaddr, _nodesbymac.get(macaddr, None))
|
||||
return _dump_locations(info, macaddr, _nodesbymac.get(macaddr, (None,))[0])
|
||||
|
||||
|
||||
def rescan(cfg):
|
||||
|
Loading…
Reference in New Issue
Block a user