]>
Commit | Line | Data |
---|---|---|
a6f80f0e | 1 | #!/usr/bin/python |
3e8ee54f | 2 | # |
3 | # Copyright 2013. Cumulus Networks, Inc. | |
4 | # Author: Roopa Prabhu, roopa@cumulusnetworks.com | |
5 | # | |
6 | # iface -- | |
7 | # interface object | |
8 | # | |
cca03c30 | 9 | from collections import OrderedDict |
d08d5f54 | 10 | #from json import * |
551a3627 | 11 | import json |
d08d5f54 | 12 | import logging |
a6f80f0e | 13 | |
d08d5f54 | 14 | tickmark = ' (' + u'\u2713'.encode('utf8') + ')' |
15 | crossmark = ' (' + u'\u2717'.encode('utf8') + ')' | |
a6f80f0e | 16 | |
d08d5f54 | 17 | class ifaceFlags(): |
a6f80f0e | 18 | NONE = 0x1 |
19 | FOLLOW_DEPENDENTS = 0x2 | |
20 | ||
21 | class ifaceStatus(): | |
a6f80f0e | 22 | """iface status """ |
23 | UNKNOWN = 0x1 | |
24 | SUCCESS = 0x2 | |
25 | ERROR = 0x3 | |
10720a53 | 26 | NOTFOUND = 0x4 |
a6f80f0e | 27 | |
28 | @classmethod | |
29 | def to_str(cls, state): | |
30 | if state == cls.UNKNOWN: | |
31 | return 'unknown' | |
32 | elif state == cls.SUCCESS: | |
33 | return 'success' | |
34 | elif state == cls.ERROR: | |
35 | return 'error' | |
739f665b | 36 | elif state == cls.NOTFOUND: |
37 | return 'not found' | |
a6f80f0e | 38 | |
39 | @classmethod | |
40 | def from_str(cls, state_str): | |
41 | if state_str == 'unknown': | |
42 | return cls.UNKNOWN | |
43 | elif state_str == 'success': | |
44 | return cls.SUCCESS | |
45 | elif state_str == 'error': | |
46 | return cls.ERROR | |
47 | ||
48 | class ifaceState(): | |
49 | ||
50 | """ iface states """ | |
51 | UNKNOWN = 0x1 | |
52 | NEW = 0x2 | |
53 | PRE_UP = 0x3 | |
54 | UP = 0x4 | |
55 | POST_UP = 0x5 | |
56 | PRE_DOWN = 0x6 | |
57 | DOWN = 0x7 | |
58 | POST_DOWN = 0x8 | |
59 | ||
d08d5f54 | 60 | # Pseudo states |
61 | QUERY_CHECKCURR = 0x9 | |
62 | QUERY_RUNNING = 0xa | |
63 | ||
a6f80f0e | 64 | @classmethod |
65 | def to_str(cls, state): | |
66 | if state == cls.UNKNOWN: | |
67 | return 'unknown' | |
68 | elif state == cls.NEW: | |
69 | return 'new' | |
70 | elif state == cls.PRE_UP: | |
71 | return 'pre-up' | |
72 | elif state == cls.UP: | |
73 | return 'up' | |
74 | elif state == cls.POST_UP: | |
75 | return 'post-up' | |
76 | elif state == cls.PRE_DOWN: | |
77 | return 'pre-down' | |
d08d5f54 | 78 | elif state == cls.DOWN: |
79 | return 'down' | |
a6f80f0e | 80 | elif state == cls.POST_DOWN: |
81 | return 'post-down' | |
d08d5f54 | 82 | elif state == cls.QUERY_CHECKCURR: |
83 | return 'query-checkcurr' | |
84 | elif state == cls.QUERY_RUNNING: | |
85 | return 'query-running' | |
a6f80f0e | 86 | |
87 | @classmethod | |
88 | def from_str(cls, state_str): | |
89 | if state_str == 'unknown': | |
90 | return cls.UNKNOWN | |
91 | elif state_str == 'new': | |
92 | return cls.NEW | |
93 | elif state_str == 'pre-up': | |
94 | return cls.PRE_UP | |
95 | elif state_str == 'up': | |
96 | return cls.UP | |
97 | elif state_str == 'post-up': | |
98 | return cls.POST_UP | |
99 | elif state_str == 'pre-down': | |
100 | return cls.PRE_DOWN | |
d08d5f54 | 101 | elif state_str == 'down': |
102 | return cls.DOWN | |
a6f80f0e | 103 | elif state_str == 'post-down': |
104 | return cls.POST_DOWN | |
d08d5f54 | 105 | elif state_str == 'query-checkcurr': |
106 | return cls.QUERY_CHECKCURR | |
107 | elif state_str == 'query-running': | |
108 | return cls.QUERY_RUNNING | |
a6f80f0e | 109 | |
110 | ||
d08d5f54 | 111 | class ifaceJsonEncoder(json.JSONEncoder): |
112 | def default(self, o): | |
83c1f241 | 113 | retconfig = {} |
114 | if o.config: | |
115 | for k, v in o.config.items(): | |
116 | if len(v) == 1: | |
117 | retconfig[k] = v[0] | |
118 | else: | |
119 | retconfig[k] = v | |
120 | ||
75730152 | 121 | return OrderedDict({'name' : o.name, |
122 | 'addr_method' : o.addr_method, | |
123 | 'addr_family' : o.addr_family, | |
124 | 'auto' : o.auto, | |
83c1f241 | 125 | 'config' : retconfig}) |
d08d5f54 | 126 | |
a6f80f0e | 127 | class iface(): |
128 | """ config flags """ | |
129 | AUTO = 0x1 | |
130 | HOT_PLUG = 0x2 | |
131 | ||
37c0543d | 132 | version = '0.1' |
133 | ||
a6f80f0e | 134 | def __init__(self): |
135 | self.name = None | |
136 | self.addr_family = None | |
137 | self.addr_method = None | |
cca03c30 | 138 | self.config = OrderedDict() |
a6f80f0e | 139 | self.state = ifaceState.NEW |
140 | self.status = ifaceStatus.UNKNOWN | |
d08d5f54 | 141 | self.errstr = '' |
a6f80f0e | 142 | self.flags = 0x0 |
37c0543d | 143 | self.priv_flags = 0x0 |
a6f80f0e | 144 | self.refcnt = 0 |
f3215127 | 145 | self.lowerifaces = None |
146 | self.upperifaces = None | |
a6f80f0e | 147 | self.auto = False |
148 | self.classes = [] | |
149 | self.env = None | |
150 | self.config_current = {} | |
151 | self.raw_lines = [] | |
152 | self.linkstate = None | |
153 | ||
154 | def inc_refcnt(self): | |
a6f80f0e | 155 | self.refcnt += 1 |
156 | ||
157 | def dec_refcnt(self): | |
158 | self.refcnt -= 1 | |
159 | ||
160 | def get_refcnt(self): | |
161 | return self.refcnt | |
162 | ||
163 | def set_refcnt(self, cnt): | |
164 | self.refcnt = 0 | |
165 | ||
166 | def set_name(self, name): | |
167 | self.name = name | |
168 | ||
169 | def get_name(self): | |
170 | return self.name | |
171 | ||
172 | def set_addr_family(self, family): | |
173 | self.addr_family = family | |
174 | ||
175 | def get_addr_family(self): | |
176 | return self.addr_family | |
177 | ||
178 | def set_addr_method(self, method): | |
179 | self.addr_method = method | |
180 | ||
181 | def get_addr_method(self): | |
182 | return self.addr_method | |
183 | ||
184 | def set_config(self, config_dict): | |
185 | self.config = config_dict | |
186 | ||
187 | def get_config(self): | |
188 | return self.config | |
189 | ||
cca03c30 | 190 | def is_config_present(self): |
37c0543d | 191 | addr_method = self.get_addr_method() |
192 | if addr_method is not None: | |
193 | if (addr_method.find('dhcp') != -1 or | |
194 | addr_method.find('dhcp6') != -1): | |
195 | return True | |
196 | ||
cca03c30 | 197 | if self.config is None: |
198 | return False | |
199 | ||
200 | return (len(self.config) != 0) | |
201 | ||
a6f80f0e | 202 | def set_config_current(self, config_current): |
203 | self.config_current = config_current | |
204 | ||
205 | def get_config_current(self): | |
206 | return self.config_current | |
207 | ||
208 | def get_auto(self): | |
209 | return self.auto | |
210 | ||
211 | def set_auto(self): | |
212 | self.auto = True | |
213 | ||
214 | def reset_auto(self): | |
215 | self.auto = False | |
216 | ||
217 | def get_classes(self): | |
218 | return self.classes | |
219 | ||
3e8ee54f | 220 | def set_classes(self, classes): |
221 | """ sets interface class list to the one passed as arg """ | |
222 | self.classes = classes | |
223 | ||
224 | def set_class(self, classname): | |
225 | """ Appends a class to the list """ | |
a6f80f0e | 226 | self.classes.append(classname) |
227 | ||
228 | def belongs_to_class(self, intfclass): | |
229 | if intfclass in self.classes: | |
230 | return True | |
231 | ||
232 | return False | |
233 | ||
a6f80f0e | 234 | def get_state(self): |
235 | return self.state | |
236 | ||
237 | def get_state_str(self): | |
238 | return ifaceState.to_str(self.state) | |
239 | ||
240 | def set_state(self, state): | |
241 | self.state = state | |
242 | ||
243 | def get_status(self): | |
244 | return self.status | |
245 | ||
246 | def get_status_str(self): | |
247 | return ifaceStatus.to_str(self.status) | |
248 | ||
249 | def set_status(self, status): | |
250 | self.status = status | |
251 | ||
252 | def state_str_to_hex(self, state_str): | |
253 | return self.state_str_map.get(state_str) | |
254 | ||
255 | def set_flag(self, flag): | |
256 | self.flags |= flag | |
257 | ||
258 | def clear_flag(self, flag): | |
259 | self.flags &= ~flag | |
260 | ||
f3215127 | 261 | def set_lowerifaces(self, dlist): |
262 | self.lowerifaces = dlist | |
a6f80f0e | 263 | |
f3215127 | 264 | def get_lowerifaces(self): |
265 | return self.lowerifaces | |
a6f80f0e | 266 | |
f3215127 | 267 | def set_upperifaces(self, dlist): |
268 | self.upperifaces = dlist | |
739f665b | 269 | |
f3215127 | 270 | def add_to_upperifaces(self, upperifacename): |
271 | if self.upperifaces: | |
272 | if upperifacename not in self.upperifaces: | |
273 | self.upperifaces.append(upperifacename) | |
274 | else: | |
275 | self.upperifaces = [upperifacename] | |
276 | ||
277 | def get_upperifaces(self): | |
278 | return self.upperifaces | |
739f665b | 279 | |
a6f80f0e | 280 | def set_linkstate(self, l): |
281 | self.linkstate = l | |
282 | ||
283 | def get_linkstate(self): | |
284 | return self.linkstate | |
285 | ||
a6f80f0e | 286 | def get_attr_value(self, attr_name): |
287 | config = self.get_config() | |
288 | ||
289 | return config.get(attr_name) | |
290 | ||
291 | def get_attr_value_first(self, attr_name): | |
292 | config = self.get_config() | |
a6f80f0e | 293 | attr_value_list = config.get(attr_name) |
294 | if attr_value_list is not None: | |
295 | return attr_value_list[0] | |
a6f80f0e | 296 | return None |
297 | ||
298 | def get_attr_value_n(self, attr_name, attr_index): | |
299 | config = self.get_config() | |
300 | ||
301 | attr_value_list = config.get(attr_name) | |
302 | if attr_value_list is not None: | |
303 | try: | |
304 | return attr_value_list[attr_index] | |
305 | except: | |
306 | return None | |
307 | ||
308 | return None | |
309 | ||
310 | def get_env(self): | |
311 | if self.env is None or len(self.env) == 0: | |
312 | self.generate_env() | |
313 | return self.env | |
314 | ||
315 | def set_env(self, env): | |
316 | self.env = env | |
317 | ||
318 | def generate_env(self): | |
319 | env = {} | |
320 | config = self.get_config() | |
321 | env['IFACE'] = self.get_name() | |
322 | for attr, attr_value in config.items(): | |
323 | attr_env_name = 'IF_%s' %attr.upper() | |
324 | env[attr_env_name] = attr_value[0] | |
325 | ||
326 | if len(env) > 0: | |
327 | self.set_env(env) | |
328 | ||
739f665b | 329 | def update_config(self, attr_name, attr_value): |
330 | if self.config.get(attr_name) is None: | |
331 | self.config[attr_name] = [attr_value] | |
332 | else: | |
333 | self.config[attr_name].append(attr_value) | |
334 | ||
335 | def update_config_dict(self, attrdict): | |
336 | self.config.update(attrdict) | |
337 | ||
338 | def update_config_with_status(self, attr_name, attr_value, attr_status=0): | |
a6f80f0e | 339 | if attr_value is None: |
340 | attr_value = '' | |
d08d5f54 | 341 | if attr_status: |
eab25b7c | 342 | self.set_status(ifaceStatus.ERROR) |
d08d5f54 | 343 | new_attr_value = '%s (%s)' %(attr_value, crossmark) |
eab25b7c | 344 | else: |
d08d5f54 | 345 | new_attr_value = '%s (%s)' %(attr_value, tickmark) |
eab25b7c | 346 | if self.get_status() != ifaceStatus.ERROR: |
347 | self.set_status(ifaceStatus.SUCCESS) | |
348 | if self.config.get(attr_name) is not None: | |
d08d5f54 | 349 | self.config[attr_name].append(new_attr_value) |
eab25b7c | 350 | else: |
d08d5f54 | 351 | self.config[attr_name] = [new_attr_value] |
a6f80f0e | 352 | |
37c0543d | 353 | def is_different(self, dstiface): |
354 | if self.name != dstiface.name: return True | |
355 | if self.addr_family != dstiface.addr_family: return True | |
356 | if self.addr_method != dstiface.addr_method: return True | |
357 | if self.auto != dstiface.auto: return True | |
358 | if self.classes != dstiface.classes: return True | |
359 | ||
360 | if any(True for k in self.config if k not in dstiface.config): | |
361 | return True | |
362 | ||
363 | if any(True for k,v in self.config.items() | |
364 | if v != dstiface.config.get(k)): return True | |
365 | ||
37c0543d | 366 | return False |
d08d5f54 | 367 | |
368 | def __getstate__(self): | |
369 | odict = self.__dict__.copy() | |
370 | del odict['state'] | |
371 | del odict['status'] | |
f3215127 | 372 | del odict['lowerifaces'] |
d08d5f54 | 373 | del odict['refcnt'] |
374 | ||
375 | return odict | |
376 | ||
377 | def __setstate__(self, dict): | |
378 | self.__dict__.update(dict) | |
379 | self.state = ifaceState.NEW | |
380 | self.status = ifaceStatus.UNKNOWN | |
381 | self.refcnt = 0 | |
f3215127 | 382 | self.lowerifaces = None |
d08d5f54 | 383 | self.linkstate = None |
37c0543d | 384 | |
a6f80f0e | 385 | def dump_raw(self, logger): |
386 | indent = ' ' | |
387 | print (self.raw_lines[0]) | |
388 | for i in range(1, len(self.raw_lines)): | |
389 | print (indent + self.raw_lines[i]) | |
390 | ||
a6f80f0e | 391 | def dump(self, logger): |
392 | indent = '\t' | |
393 | logger.info(self.get_name() + ' : {') | |
394 | logger.info(indent + 'family: %s' %self.get_addr_family()) | |
395 | logger.info(indent + 'method: %s' %self.get_addr_method()) | |
396 | logger.info(indent + 'state: %s' | |
397 | %ifaceState.to_str(self.get_state())) | |
398 | logger.info(indent + 'status: %s' | |
399 | %ifaceStatus.to_str(self.get_status())) | |
400 | logger.info(indent + 'refcnt: %d' %self.get_refcnt()) | |
f3215127 | 401 | d = self.get_lowerdevs() |
a6f80f0e | 402 | if d is not None: |
f3215127 | 403 | logger.info(indent + 'lowerdevs: %s' %str(d)) |
a6f80f0e | 404 | else: |
f3215127 | 405 | logger.info(indent + 'lowerdevs: None') |
739f665b | 406 | |
a6f80f0e | 407 | logger.info(indent + 'config: ') |
408 | config = self.get_config() | |
409 | if config is not None: | |
410 | logger.info(indent + indent + str(config)) | |
411 | logger.info('}') | |
412 | ||
d08d5f54 | 413 | def dump_pretty(self): |
a6f80f0e | 414 | indent = '\t' |
cca03c30 | 415 | outbuf = '' |
416 | if self.get_auto(): | |
417 | outbuf += 'auto %s\n' %self.get_name() | |
418 | outbuf += 'iface %s' %self.get_name() | |
a6f80f0e | 419 | if self.get_addr_family() is not None: |
420 | outbuf += ' %s' %self.get_addr_family() | |
421 | ||
422 | if self.get_addr_method() is not None: | |
423 | outbuf += ' %s' %self.get_addr_method() | |
424 | ||
425 | outbuf += '\n' | |
426 | ||
427 | config = self.get_config() | |
428 | if config is not None: | |
eab25b7c | 429 | for cname, cvaluelist in config.items(): |
430 | for cv in cvaluelist: | |
431 | outbuf += indent + '%s' %cname + ' %s\n' %cv | |
a6f80f0e | 432 | |
a6f80f0e | 433 | print outbuf |
551a3627 | 434 | |
d08d5f54 | 435 | def dump_json(self): |
75730152 | 436 | print json.dumps(self, cls=ifaceJsonEncoder, indent=4) |