1
0
mirror of https://github.com/CumulusNetworks/ifupdown2.git synced 2024-05-06 15:54:50 +00:00
Files
CumulusNetworks-ifupdown2/ifupdownaddons/mstpctlutil.py
Nikhil d03b0695e0 addons: mstpctl: ifquery -c --with-default, ignore mstpctl default attributes when stp is off
Ticket: CM-13779
Reviewed By: roopa, satish, julien
Testing Done: testing the config given in the CM

mstpctl showportdetail <bridge> command won't output anything when
bridge-stp is off, therefore ignore mstpctl default attributes during
ifquery -c --with-defaults

This patch also consistently updates bridge and bridge port cache
at the same time.
Earlier bridge and bridge port cache were not consistent
because of the early return condition
    attrs = MSTPAttrsCache.get(bridgename)
        if attrs:
            return attrs
If either of bridge port cache and bridge cache is updated, function used to
return inconsistent cache values

Signed-off-by: Nikhil Gajendrakumar <nikhil@cumulusnetworks.com>
2017-01-20 10:42:05 -08:00

233 lines
9.6 KiB
Python

#!/usr/bin/python
#
# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
# Author: Roopa Prabhu, roopa@cumulusnetworks.com
#
from cache import MSTPAttrsCache
from utilsbase import *
from ifupdown.iface import *
from ifupdown.utils import utils
from cache import *
import json
class mstpctlutil(utilsBase):
""" This class contains helper methods to interact with mstpd using
mstputils commands """
_DEFAULT_PORT_PRIO = '128'
_cache_fill_done = False
_bridgeattrmap = {'bridgeid' : 'bridge-id',
'maxage' : 'max-age',
'fdelay' : 'forward-delay',
'txholdcount' : 'tx-hold-count',
'maxhops' : 'max-hops',
'ageing' : 'ageing-time',
'hello' : 'hello-time',
'forcevers' : 'force-protocol-version'}
_bridge_jsonAttr_map = {
'treeprio': 'bridgeId',
'maxage': 'maxAge',
'fdelay': 'fwdDelay',
'txholdcount': 'txHoldCounter',
'maxhops': 'maxHops',
'ageing': 'ageingTime',
'hello': 'helloTime',
'forcevers': 'forceProtocolVersion',
}
_bridgeportattrmap = {'portadminedge' : 'admin-edge-port',
'portp2p' : 'admin-point-to-point',
'portrestrrole' : 'restricted-role',
'portrestrtcn' : 'restricted-TCN',
'bpduguard' : 'bpdu-guard-port',
'portautoedge' : 'auto-edge-port',
'portnetwork' : 'network-port',
'portbpdufilter' : 'bpdufilter-port',
'portpathcost' : 'external-port-cost',
'treeportcost' : 'internal-port-cost'}
def __init__(self, *args, **kargs):
utilsBase.__init__(self, *args, **kargs)
def is_mstpd_running(self):
try:
utils.exec_command('/bin/pidof mstpd')
except:
return False
else:
return True
def _extract_bridge_port_prio(self, portid):
try:
return str(int(portid[0], 16) * 16)
except:
return mstpctlutil._DEFAULT_PORT_PRIO
def _get_bridge_and_port_attrs_from_cache(self, bridgename):
attrs = MSTPAttrsCache.get(bridgename)
if attrs:
return attrs
mstpctl_bridgeport_attrs_dict = {}
try:
cmd = ['/sbin/mstpctl', 'showportdetail', bridgename, 'json']
output = utils.exec_commandl(cmd)
if not output:
return mstpctl_bridgeport_attrs_dict
except Exception as e:
self.logger.info(str(e))
return mstpctl_bridgeport_attrs_dict
try:
mstpctl_bridge_cache = json.loads(output.strip('\n'))
for portname in mstpctl_bridge_cache.keys():
for portid in mstpctl_bridge_cache[portname].keys():
mstpctl_bridgeport_attrs_dict[portname] = {}
mstpctl_bridgeport_attrs_dict[portname]['treeportprio'] = self._extract_bridge_port_prio(portid)
for jsonAttr in mstpctl_bridge_cache[portname][portid].keys():
jsonVal = mstpctl_bridge_cache[portname][portid][jsonAttr]
mstpctl_bridgeport_attrs_dict[portname][jsonAttr] = str(jsonVal)
MSTPAttrsCache.set(bridgename, mstpctl_bridgeport_attrs_dict)
except Exception as e:
self.logger.info('%s: cannot fetch mstpctl bridge port attributes: %s' % str(e))
mstpctl_bridge_attrs_dict = {}
try:
cmd = ['/sbin/mstpctl', 'showbridge', 'json', bridgename]
output = utils.exec_commandl(cmd)
if not output:
return mstpctl_bridge_attrs_dict
except Exception as e:
self.logger.info(str(e))
return mstpctl_bridge_attrs_dict
try:
mstpctl_bridge_cache = json.loads(output.strip('\n'))
for jsonAttr in mstpctl_bridge_cache[bridgename].keys():
mstpctl_bridge_attrs_dict[jsonAttr] = (
str(mstpctl_bridge_cache[bridgename][jsonAttr]))
mstpctl_bridge_attrs_dict['treeprio'] = '%d' %(
int(mstpctl_bridge_attrs_dict.get('bridgeId',
'').split('.')[0], base=16) * 4096)
del mstpctl_bridge_attrs_dict['bridgeId']
MSTPAttrsCache.bridges[bridgename].update(mstpctl_bridge_attrs_dict)
except Exception as e:
self.logger.info('%s: cannot fetch mstpctl bridge attributes: %s' % str(e))
return MSTPAttrsCache.get(bridgename)
def get_bridge_ports_attrs(self, bridgename):
return self._get_bridge_and_port_attrs_from_cache(bridgename)
def get_bridge_port_attr(self, bridgename, portname, attrname):
attrs = self._get_bridge_and_port_attrs_from_cache(bridgename)
value = attrs.get(portname, {}).get(attrname, 'no')
if value == 'True' or value == 'true':
return 'yes'
return str(value)
def update_bridge_port_cache(self, bridgename, portname, attrname, value):
attrs = self.get_bridge_ports_attrs(bridgename)
if not attrs:
attrs = {}
if not portname in attrs:
attrs[portname] = {}
attrs[portname][attrname] = value
MSTPAttrsCache.set(bridgename, attrs)
def update_bridge_cache(self, bridgename, attrname, value):
attrs = self.get_bridge_ports_attrs(bridgename)
if not attrs:
attrs = {}
attrs[attrname] = value
MSTPAttrsCache.set(bridgename, attrs)
def set_bridge_port_attr(self, bridgename, portname, attrname, value, json_attr=None):
cache_value = self.get_bridge_port_attr(bridgename, portname, json_attr)
if cache_value and cache_value == value:
return
if attrname == 'treeportcost' or attrname == 'treeportprio':
utils.exec_commandl(['/sbin/mstpctl', 'set%s' % attrname,
bridgename, portname, '0', value])
else:
utils.exec_commandl(['/sbin/mstpctl', 'set%s' % attrname,
bridgename, portname, value])
if json_attr:
self.update_bridge_port_cache(bridgename, portname, json_attr, value)
def get_bridge_attrs(self, bridgename):
bridgeattrs = {}
try:
bridgeattrs = dict((k, self.get_bridge_attr(bridgename, v))
for k,v in self._bridge_jsonAttr_map.items())
except Exception, e:
self.logger.debug(bridgeattrs)
self.logger.debug(str(e))
pass
return bridgeattrs
def get_bridge_attr(self, bridgename, attrname):
if attrname == 'bridgeId':
attrname = 'treeprio'
return self._get_bridge_and_port_attrs_from_cache(bridgename).get(attrname)
def set_bridge_attr(self, bridgename, attrname, attrvalue, check=True):
if check:
if attrname == 'treeprio':
attrvalue_curr = self.get_bridge_attr(bridgename, attrname)
else:
attrvalue_curr = self.get_bridge_attr(bridgename,
self._bridge_jsonAttr_map[attrname])
if attrvalue_curr and attrvalue_curr == attrvalue:
return
if attrname == 'treeprio':
utils.exec_commandl(['/sbin/mstpctl', 'set%s' % attrname,
'%s' % bridgename, '0', '%s' % attrvalue],
stdout=False, stderr=None)
self.update_bridge_cache(bridgename, attrname, str(attrvalue))
else:
utils.exec_commandl(['/sbin/mstpctl', 'set%s' % attrname,
'%s' % bridgename, '%s' % attrvalue],
stdout=False, stderr=None)
self.update_bridge_cache(bridgename,
self._bridge_jsonAttr_map[attrname],
str(attrvalue))
def set_bridge_attrs(self, bridgename, attrdict, check=True):
for k, v in attrdict.iteritems():
if not v:
continue
try:
self.set_bridge_attr(bridgename, k, v, check)
except Exception, e:
self.logger.warn('%s: %s' %(bridgename, str(e)))
def get_bridge_treeprio(self, bridgename):
return self.get_bridge_attr(bridgename, 'treeprio')
def set_bridge_treeprio(self, bridgename, attrvalue, check=True):
if check:
attrvalue_curr = self.get_bridge_treeprio(bridgename)
if attrvalue_curr and attrvalue_curr == attrvalue:
return
utils.exec_commandl(['/sbin/mstpctl', 'settreeprio', bridgename, '0',
str(attrvalue)])
self.update_bridge_cache(bridgename, 'treeprio', str(attrvalue))
def showbridge(self, bridgename=None):
if bridgename:
return utils.exec_command('/sbin/mstpctl showbridge %s' % bridgename)
else:
return utils.exec_command('/sbin/mstpctl showbridge')
def showportdetail(self, bridgename):
return utils.exec_command('/sbin/mstpctl showportdetail %s' % bridgename)
def mstpbridge_exists(self, bridgename):
try:
utils.exec_command('mstpctl showbridge %s' % bridgename, stdout=False)
return True
except:
return False