]>
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): |
b47ce90d | 82 | attrs = MSTPAttrsCache.get(bridgename) |
9d3f53c6 JF |
83 | if attrs: |
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: | |
b47ce90d | 91 | return mstpctl_bridgeport_attrs_dict |
9d3f53c6 JF |
92 | except Exception as e: |
93 | self.logger.info(str(e)) | |
94 | return mstpctl_bridgeport_attrs_dict | |
95 | try: | |
96 | mstpctl_bridge_cache = json.loads(output.strip('\n')) | |
97 | for portname in mstpctl_bridge_cache.keys(): | |
98 | for portid in mstpctl_bridge_cache[portname].keys(): | |
99 | mstpctl_bridgeport_attrs_dict[portname] = {} | |
100 | mstpctl_bridgeport_attrs_dict[portname]['treeportprio'] = self._extract_bridge_port_prio(portid) | |
101 | for jsonAttr in mstpctl_bridge_cache[portname][portid].keys(): | |
102 | jsonVal = mstpctl_bridge_cache[portname][portid][jsonAttr] | |
103 | mstpctl_bridgeport_attrs_dict[portname][jsonAttr] = str(jsonVal) | |
104 | MSTPAttrsCache.set(bridgename, mstpctl_bridgeport_attrs_dict) | |
105 | except Exception as e: | |
106 | self.logger.info('%s: cannot fetch mstpctl bridge port attributes: %s' % str(e)) | |
9d3f53c6 | 107 | |
e3089aa8 N |
108 | mstpctl_bridge_attrs_dict = {} |
109 | try: | |
d486dd0d JF |
110 | cmd = [utils.mstpctl_cmd, |
111 | 'showbridge', 'json', bridgename] | |
e3089aa8 N |
112 | output = utils.exec_commandl(cmd) |
113 | if not output: | |
114 | return mstpctl_bridge_attrs_dict | |
115 | except Exception as e: | |
116 | self.logger.info(str(e)) | |
117 | return mstpctl_bridge_attrs_dict | |
118 | try: | |
119 | mstpctl_bridge_cache = json.loads(output.strip('\n')) | |
120 | for jsonAttr in mstpctl_bridge_cache[bridgename].keys(): | |
121 | mstpctl_bridge_attrs_dict[jsonAttr] = ( | |
122 | str(mstpctl_bridge_cache[bridgename][jsonAttr])) | |
123 | mstpctl_bridge_attrs_dict['treeprio'] = '%d' %( | |
124 | int(mstpctl_bridge_attrs_dict.get('bridgeId', | |
125 | '').split('.')[0], base=16) * 4096) | |
126 | del mstpctl_bridge_attrs_dict['bridgeId'] | |
d03b0695 | 127 | MSTPAttrsCache.bridges[bridgename].update(mstpctl_bridge_attrs_dict) |
e3089aa8 N |
128 | except Exception as e: |
129 | self.logger.info('%s: cannot fetch mstpctl bridge attributes: %s' % str(e)) | |
d03b0695 | 130 | return MSTPAttrsCache.get(bridgename) |
e3089aa8 | 131 | |
9d3f53c6 | 132 | def get_bridge_ports_attrs(self, bridgename): |
d03b0695 | 133 | return self._get_bridge_and_port_attrs_from_cache(bridgename) |
9d3f53c6 JF |
134 | |
135 | def get_bridge_port_attr(self, bridgename, portname, attrname): | |
d03b0695 | 136 | attrs = self._get_bridge_and_port_attrs_from_cache(bridgename) |
9d3f53c6 JF |
137 | value = attrs.get(portname, {}).get(attrname, 'no') |
138 | if value == 'True' or value == 'true': | |
139 | return 'yes' | |
140 | return str(value) | |
141 | ||
e3089aa8 | 142 | def update_bridge_port_cache(self, bridgename, portname, attrname, value): |
9d3f53c6 | 143 | attrs = self.get_bridge_ports_attrs(bridgename) |
b47ce90d | 144 | if not attrs: |
9d3f53c6 JF |
145 | attrs = {} |
146 | if not portname in attrs: | |
147 | attrs[portname] = {} | |
148 | attrs[portname][attrname] = value | |
149 | MSTPAttrsCache.set(bridgename, attrs) | |
150 | ||
e3089aa8 N |
151 | def update_bridge_cache(self, bridgename, attrname, value): |
152 | attrs = self.get_bridge_ports_attrs(bridgename) | |
153 | if not attrs: | |
154 | attrs = {} | |
155 | attrs[attrname] = value | |
156 | MSTPAttrsCache.set(bridgename, attrs) | |
157 | ||
9d3f53c6 JF |
158 | def set_bridge_port_attr(self, bridgename, portname, attrname, value, json_attr=None): |
159 | cache_value = self.get_bridge_port_attr(bridgename, portname, json_attr) | |
160 | if cache_value and cache_value == value: | |
161 | return | |
15ef32ea | 162 | if attrname == 'treeportcost' or attrname == 'treeportprio': |
d486dd0d | 163 | utils.exec_commandl([utils.mstpctl_cmd, 'set%s' % attrname, |
9d3f53c6 | 164 | bridgename, portname, '0', value]) |
15ef32ea | 165 | else: |
d486dd0d | 166 | utils.exec_commandl([utils.mstpctl_cmd, 'set%s' % attrname, |
9d3f53c6 JF |
167 | bridgename, portname, value]) |
168 | if json_attr: | |
e3089aa8 | 169 | self.update_bridge_port_cache(bridgename, portname, json_attr, value) |
15ef32ea RP |
170 | |
171 | def get_bridge_attrs(self, bridgename): | |
172 | bridgeattrs = {} | |
173 | try: | |
e3089aa8 N |
174 | bridgeattrs = dict((k, self.get_bridge_attr(bridgename, v)) |
175 | for k,v in self._bridge_jsonAttr_map.items()) | |
15ef32ea | 176 | except Exception, e: |
2ca1b884 RP |
177 | self.logger.debug(bridgeattrs) |
178 | self.logger.debug(str(e)) | |
15ef32ea RP |
179 | pass |
180 | return bridgeattrs | |
181 | ||
182 | def get_bridge_attr(self, bridgename, attrname): | |
e3089aa8 N |
183 | if attrname == 'bridgeId': |
184 | attrname = 'treeprio' | |
d03b0695 | 185 | return self._get_bridge_and_port_attrs_from_cache(bridgename).get(attrname) |
15ef32ea RP |
186 | |
187 | def set_bridge_attr(self, bridgename, attrname, attrvalue, check=True): | |
188 | ||
189 | if check: | |
e3089aa8 N |
190 | if attrname == 'treeprio': |
191 | attrvalue_curr = self.get_bridge_attr(bridgename, attrname) | |
192 | else: | |
193 | attrvalue_curr = self.get_bridge_attr(bridgename, | |
194 | self._bridge_jsonAttr_map[attrname]) | |
15ef32ea RP |
195 | if attrvalue_curr and attrvalue_curr == attrvalue: |
196 | return | |
197 | if attrname == 'treeprio': | |
d486dd0d JF |
198 | utils.exec_commandl([utils.mstpctl_cmd, 'set%s' % attrname, |
199 | '%s' % bridgename, '0', '%s' % attrvalue], stderr=None) | |
e3089aa8 | 200 | self.update_bridge_cache(bridgename, attrname, str(attrvalue)) |
15ef32ea | 201 | else: |
d486dd0d JF |
202 | utils.exec_commandl([utils.mstpctl_cmd, 'set%s' % attrname, |
203 | '%s' % bridgename, '%s' % attrvalue], stderr=None) | |
e3089aa8 N |
204 | self.update_bridge_cache(bridgename, |
205 | self._bridge_jsonAttr_map[attrname], | |
206 | str(attrvalue)) | |
15ef32ea RP |
207 | |
208 | def set_bridge_attrs(self, bridgename, attrdict, check=True): | |
209 | for k, v in attrdict.iteritems(): | |
210 | if not v: | |
211 | continue | |
212 | try: | |
213 | self.set_bridge_attr(bridgename, k, v, check) | |
214 | except Exception, e: | |
215 | self.logger.warn('%s: %s' %(bridgename, str(e))) | |
15ef32ea RP |
216 | |
217 | def get_bridge_treeprio(self, bridgename): | |
e3089aa8 | 218 | return self.get_bridge_attr(bridgename, 'treeprio') |
15ef32ea RP |
219 | |
220 | def set_bridge_treeprio(self, bridgename, attrvalue, check=True): | |
221 | if check: | |
222 | attrvalue_curr = self.get_bridge_treeprio(bridgename) | |
223 | if attrvalue_curr and attrvalue_curr == attrvalue: | |
224 | return | |
d486dd0d JF |
225 | utils.exec_commandl([utils.mstpctl_cmd, |
226 | 'settreeprio', bridgename, '0', | |
a193d8d1 | 227 | str(attrvalue)]) |
e3089aa8 | 228 | self.update_bridge_cache(bridgename, 'treeprio', str(attrvalue)) |
15ef32ea RP |
229 | |
230 | def showbridge(self, bridgename=None): | |
231 | if bridgename: | |
d486dd0d JF |
232 | return utils.exec_command('%s showbridge %s' % |
233 | (utils.mstpctl_cmd, bridgename)) | |
15ef32ea | 234 | else: |
d486dd0d | 235 | return utils.exec_command('%s showbridge' %utils.mstpctl_cmd) |
15ef32ea RP |
236 | |
237 | def showportdetail(self, bridgename): | |
d486dd0d JF |
238 | return utils.exec_command('%s showportdetail %s' % |
239 | (utils.mstpctl_cmd, bridgename)) | |
15ef32ea RP |
240 | |
241 | def mstpbridge_exists(self, bridgename): | |
242 | try: | |
d486dd0d JF |
243 | utils.exec_command('%s showbridge %s' % |
244 | (utils.mstpctl_cmd, bridgename)) | |
15ef32ea RP |
245 | return True |
246 | except: | |
247 | return False |