]>
Commit | Line | Data |
---|---|---|
15ef32ea RP |
1 | #!/usr/bin/python |
2 | # | |
d486dd0d | 3 | # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved. |
15ef32ea RP |
4 | # Author: Roopa Prabhu, roopa@cumulusnetworks.com |
5 | # | |
6 | ||
d486dd0d JF |
7 | try: |
8 | from ifupdown2.ifupdown.iface import * | |
9 | from ifupdown2.ifupdown.utils import utils | |
10 | ||
11 | from ifupdown2.ifupdownaddons.cache import * | |
12 | from ifupdown2.ifupdownaddons.utilsbase import * | |
13 | except ImportError: | |
14 | from ifupdown.iface import * | |
15 | from ifupdown.utils import utils | |
16 | ||
17 | from ifupdownaddons.cache import * | |
18 | from ifupdownaddons.utilsbase import * | |
19 | ||
15ef32ea RP |
20 | |
21 | class mstpctlutil(utilsBase): | |
22 | """ This class contains helper methods to interact with mstpd using | |
23 | mstputils commands """ | |
24 | ||
bfceb635 JF |
25 | _DEFAULT_PORT_PRIO = '128' |
26 | ||
15ef32ea RP |
27 | _cache_fill_done = False |
28 | ||
29 | _bridgeattrmap = {'bridgeid' : 'bridge-id', | |
30 | 'maxage' : 'max-age', | |
31 | 'fdelay' : 'forward-delay', | |
32 | 'txholdcount' : 'tx-hold-count', | |
33 | 'maxhops' : 'max-hops', | |
34 | 'ageing' : 'ageing-time', | |
35 | 'hello' : 'hello-time', | |
36 | 'forcevers' : 'force-protocol-version'} | |
37 | ||
e3089aa8 N |
38 | _bridge_jsonAttr_map = { |
39 | 'treeprio': 'bridgeId', | |
40 | 'maxage': 'maxAge', | |
41 | 'fdelay': 'fwdDelay', | |
42 | 'txholdcount': 'txHoldCounter', | |
43 | 'maxhops': 'maxHops', | |
44 | 'ageing': 'ageingTime', | |
45 | 'hello': 'helloTime', | |
46 | 'forcevers': 'forceProtocolVersion', | |
47 | } | |
48 | ||
15ef32ea | 49 | _bridgeportattrmap = {'portadminedge' : 'admin-edge-port', |
2ca1b884 | 50 | 'portp2p' : 'admin-point-to-point', |
15ef32ea RP |
51 | 'portrestrrole' : 'restricted-role', |
52 | 'portrestrtcn' : 'restricted-TCN', | |
53 | 'bpduguard' : 'bpdu-guard-port', | |
54 | 'portautoedge' : 'auto-edge-port', | |
55 | 'portnetwork' : 'network-port', | |
22945dd6 N |
56 | 'portbpdufilter' : 'bpdufilter-port', |
57 | 'portpathcost' : 'external-port-cost', | |
58 | 'treeportcost' : 'internal-port-cost'} | |
15ef32ea RP |
59 | |
60 | def __init__(self, *args, **kargs): | |
61 | utilsBase.__init__(self, *args, **kargs) | |
62 | ||
d486dd0d JF |
63 | @classmethod |
64 | def reset(cls): | |
65 | cls._cache_fill_done = False | |
66 | ||
15ef32ea RP |
67 | def is_mstpd_running(self): |
68 | try: | |
d486dd0d | 69 | utils.exec_command('%s mstpd'%utils.pidof_cmd) |
15ef32ea RP |
70 | except: |
71 | return False | |
72 | else: | |
73 | return True | |
74 | ||
bfceb635 JF |
75 | def _extract_bridge_port_prio(self, portid): |
76 | try: | |
77 | return str(int(portid[0], 16) * 16) | |
78 | except: | |
9d3f53c6 | 79 | return mstpctlutil._DEFAULT_PORT_PRIO |
bfceb635 | 80 | |
d03b0695 | 81 | def _get_bridge_and_port_attrs_from_cache(self, bridgename): |
80d56a07 JF |
82 | attrs = MSTPAttrsCache.get(bridgename, None) |
83 | if attrs is not None: | |
9d3f53c6 JF |
84 | return attrs |
85 | mstpctl_bridgeport_attrs_dict = {} | |
86 | try: | |
d486dd0d JF |
87 | cmd = [utils.mstpctl_cmd, |
88 | 'showportdetail', bridgename, 'json'] | |
9d3f53c6 JF |
89 | output = utils.exec_commandl(cmd) |
90 | if not output: | |
80d56a07 | 91 | MSTPAttrsCache.set(bridgename, mstpctl_bridgeport_attrs_dict) |
b47ce90d | 92 | return mstpctl_bridgeport_attrs_dict |
9d3f53c6 JF |
93 | except Exception as e: |
94 | self.logger.info(str(e)) | |
95 | return mstpctl_bridgeport_attrs_dict | |
96 | try: | |
97 | mstpctl_bridge_cache = json.loads(output.strip('\n')) | |
98 | for portname in mstpctl_bridge_cache.keys(): | |
99 | for portid in mstpctl_bridge_cache[portname].keys(): | |
100 | mstpctl_bridgeport_attrs_dict[portname] = {} | |
101 | mstpctl_bridgeport_attrs_dict[portname]['treeportprio'] = self._extract_bridge_port_prio(portid) | |
102 | for jsonAttr in mstpctl_bridge_cache[portname][portid].keys(): | |
103 | jsonVal = mstpctl_bridge_cache[portname][portid][jsonAttr] | |
104 | mstpctl_bridgeport_attrs_dict[portname][jsonAttr] = str(jsonVal) | |
105 | MSTPAttrsCache.set(bridgename, mstpctl_bridgeport_attrs_dict) | |
106 | except Exception as e: | |
107 | self.logger.info('%s: cannot fetch mstpctl bridge port attributes: %s' % str(e)) | |
9d3f53c6 | 108 | |
e3089aa8 N |
109 | mstpctl_bridge_attrs_dict = {} |
110 | try: | |
d486dd0d JF |
111 | cmd = [utils.mstpctl_cmd, |
112 | 'showbridge', 'json', bridgename] | |
e3089aa8 N |
113 | output = utils.exec_commandl(cmd) |
114 | if not output: | |
115 | return mstpctl_bridge_attrs_dict | |
116 | except Exception as e: | |
117 | self.logger.info(str(e)) | |
118 | return mstpctl_bridge_attrs_dict | |
119 | try: | |
120 | mstpctl_bridge_cache = json.loads(output.strip('\n')) | |
121 | for jsonAttr in mstpctl_bridge_cache[bridgename].keys(): | |
122 | mstpctl_bridge_attrs_dict[jsonAttr] = ( | |
123 | str(mstpctl_bridge_cache[bridgename][jsonAttr])) | |
124 | mstpctl_bridge_attrs_dict['treeprio'] = '%d' %( | |
125 | int(mstpctl_bridge_attrs_dict.get('bridgeId', | |
126 | '').split('.')[0], base=16) * 4096) | |
127 | del mstpctl_bridge_attrs_dict['bridgeId'] | |
d03b0695 | 128 | MSTPAttrsCache.bridges[bridgename].update(mstpctl_bridge_attrs_dict) |
e3089aa8 N |
129 | except Exception as e: |
130 | self.logger.info('%s: cannot fetch mstpctl bridge attributes: %s' % str(e)) | |
d03b0695 | 131 | return MSTPAttrsCache.get(bridgename) |
e3089aa8 | 132 | |
9d3f53c6 | 133 | def get_bridge_ports_attrs(self, bridgename): |
d03b0695 | 134 | return self._get_bridge_and_port_attrs_from_cache(bridgename) |
9d3f53c6 JF |
135 | |
136 | def get_bridge_port_attr(self, bridgename, portname, attrname): | |
d03b0695 | 137 | attrs = self._get_bridge_and_port_attrs_from_cache(bridgename) |
9d3f53c6 JF |
138 | value = attrs.get(portname, {}).get(attrname, 'no') |
139 | if value == 'True' or value == 'true': | |
140 | return 'yes' | |
141 | return str(value) | |
142 | ||
e3089aa8 | 143 | def update_bridge_port_cache(self, bridgename, portname, attrname, value): |
9d3f53c6 | 144 | attrs = self.get_bridge_ports_attrs(bridgename) |
b47ce90d | 145 | if not attrs: |
9d3f53c6 JF |
146 | attrs = {} |
147 | if not portname in attrs: | |
148 | attrs[portname] = {} | |
149 | attrs[portname][attrname] = value | |
150 | MSTPAttrsCache.set(bridgename, attrs) | |
151 | ||
e3089aa8 N |
152 | def update_bridge_cache(self, bridgename, attrname, value): |
153 | attrs = self.get_bridge_ports_attrs(bridgename) | |
154 | if not attrs: | |
155 | attrs = {} | |
156 | attrs[attrname] = value | |
157 | MSTPAttrsCache.set(bridgename, attrs) | |
158 | ||
9d3f53c6 JF |
159 | def set_bridge_port_attr(self, bridgename, portname, attrname, value, json_attr=None): |
160 | cache_value = self.get_bridge_port_attr(bridgename, portname, json_attr) | |
161 | if cache_value and cache_value == value: | |
162 | return | |
15ef32ea | 163 | if attrname == 'treeportcost' or attrname == 'treeportprio': |
d486dd0d | 164 | utils.exec_commandl([utils.mstpctl_cmd, 'set%s' % attrname, |
9d3f53c6 | 165 | bridgename, portname, '0', value]) |
15ef32ea | 166 | else: |
d486dd0d | 167 | utils.exec_commandl([utils.mstpctl_cmd, 'set%s' % attrname, |
9d3f53c6 JF |
168 | bridgename, portname, value]) |
169 | if json_attr: | |
e3089aa8 | 170 | self.update_bridge_port_cache(bridgename, portname, json_attr, value) |
15ef32ea RP |
171 | |
172 | def get_bridge_attrs(self, bridgename): | |
173 | bridgeattrs = {} | |
174 | try: | |
e3089aa8 N |
175 | bridgeattrs = dict((k, self.get_bridge_attr(bridgename, v)) |
176 | for k,v in self._bridge_jsonAttr_map.items()) | |
15ef32ea | 177 | except Exception, e: |
2ca1b884 RP |
178 | self.logger.debug(bridgeattrs) |
179 | self.logger.debug(str(e)) | |
15ef32ea RP |
180 | pass |
181 | return bridgeattrs | |
182 | ||
183 | def get_bridge_attr(self, bridgename, attrname): | |
e3089aa8 N |
184 | if attrname == 'bridgeId': |
185 | attrname = 'treeprio' | |
d03b0695 | 186 | return self._get_bridge_and_port_attrs_from_cache(bridgename).get(attrname) |
15ef32ea RP |
187 | |
188 | def set_bridge_attr(self, bridgename, attrname, attrvalue, check=True): | |
189 | ||
190 | if check: | |
e3089aa8 N |
191 | if attrname == 'treeprio': |
192 | attrvalue_curr = self.get_bridge_attr(bridgename, attrname) | |
193 | else: | |
194 | attrvalue_curr = self.get_bridge_attr(bridgename, | |
195 | self._bridge_jsonAttr_map[attrname]) | |
15ef32ea RP |
196 | if attrvalue_curr and attrvalue_curr == attrvalue: |
197 | return | |
198 | if attrname == 'treeprio': | |
d486dd0d JF |
199 | utils.exec_commandl([utils.mstpctl_cmd, 'set%s' % attrname, |
200 | '%s' % bridgename, '0', '%s' % attrvalue], stderr=None) | |
e3089aa8 | 201 | self.update_bridge_cache(bridgename, attrname, str(attrvalue)) |
15ef32ea | 202 | else: |
d486dd0d JF |
203 | utils.exec_commandl([utils.mstpctl_cmd, 'set%s' % attrname, |
204 | '%s' % bridgename, '%s' % attrvalue], stderr=None) | |
e3089aa8 N |
205 | self.update_bridge_cache(bridgename, |
206 | self._bridge_jsonAttr_map[attrname], | |
207 | str(attrvalue)) | |
15ef32ea RP |
208 | |
209 | def set_bridge_attrs(self, bridgename, attrdict, check=True): | |
210 | for k, v in attrdict.iteritems(): | |
211 | if not v: | |
212 | continue | |
213 | try: | |
214 | self.set_bridge_attr(bridgename, k, v, check) | |
215 | except Exception, e: | |
216 | self.logger.warn('%s: %s' %(bridgename, str(e))) | |
15ef32ea RP |
217 | |
218 | def get_bridge_treeprio(self, bridgename): | |
e3089aa8 | 219 | return self.get_bridge_attr(bridgename, 'treeprio') |
15ef32ea RP |
220 | |
221 | def set_bridge_treeprio(self, bridgename, attrvalue, check=True): | |
222 | if check: | |
223 | attrvalue_curr = self.get_bridge_treeprio(bridgename) | |
224 | if attrvalue_curr and attrvalue_curr == attrvalue: | |
225 | return | |
d486dd0d JF |
226 | utils.exec_commandl([utils.mstpctl_cmd, |
227 | 'settreeprio', bridgename, '0', | |
a193d8d1 | 228 | str(attrvalue)]) |
e3089aa8 | 229 | self.update_bridge_cache(bridgename, 'treeprio', str(attrvalue)) |
15ef32ea RP |
230 | |
231 | def showbridge(self, bridgename=None): | |
232 | if bridgename: | |
d486dd0d JF |
233 | return utils.exec_command('%s showbridge %s' % |
234 | (utils.mstpctl_cmd, bridgename)) | |
15ef32ea | 235 | else: |
d486dd0d | 236 | return utils.exec_command('%s showbridge' %utils.mstpctl_cmd) |
15ef32ea RP |
237 | |
238 | def showportdetail(self, bridgename): | |
d486dd0d JF |
239 | return utils.exec_command('%s showportdetail %s' % |
240 | (utils.mstpctl_cmd, bridgename)) | |
15ef32ea RP |
241 | |
242 | def mstpbridge_exists(self, bridgename): | |
243 | try: | |
d486dd0d JF |
244 | utils.exec_command('%s showbridge %s' % |
245 | (utils.mstpctl_cmd, bridgename)) | |
15ef32ea RP |
246 | return True |
247 | except: | |
248 | return False |