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