]> git.proxmox.com Git - mirror_ifupdown2.git/blob - pkg/iface.py
cleanup state manager + remove some dead code
[mirror_ifupdown2.git] / pkg / iface.py
1 #!/usr/bin/python
2 #
3 # Copyright 2013. Cumulus Networks, Inc.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
5 #
6 # iface --
7 # interface object
8 #
9 from collections import OrderedDict
10 #from json import *
11 import json
12 import logging
13
14 tickmark = ' (' + u'\u2713'.encode('utf8') + ')'
15 crossmark = ' (' + u'\u2717'.encode('utf8') + ')'
16
17 class ifaceFlags():
18 NONE = 0x1
19 FOLLOW_DEPENDENTS = 0x2
20
21 class ifaceStatus():
22 """iface status """
23 UNKNOWN = 0x1
24 SUCCESS = 0x2
25 ERROR = 0x3
26 NOTFOUND = 0x4
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'
36 elif state == cls.NOTFOUND:
37 return 'notfound'
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
60 # Pseudo states
61 QUERY_CHECKCURR = 0x9
62 QUERY_RUNNING = 0xa
63
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'
78 elif state == cls.DOWN:
79 return 'down'
80 elif state == cls.POST_DOWN:
81 return 'post-down'
82 elif state == cls.QUERY_CHECKCURR:
83 return 'query-checkcurr'
84 elif state == cls.QUERY_RUNNING:
85 return 'query-running'
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
101 elif state_str == 'down':
102 return cls.DOWN
103 elif state_str == 'post-down':
104 return cls.POST_DOWN
105 elif state_str == 'query-checkcurr':
106 return cls.QUERY_CHECKCURR
107 elif state_str == 'query-running':
108 return cls.QUERY_RUNNING
109
110
111 class ifaceJsonEncoder(json.JSONEncoder):
112 def default(self, o):
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
121 return OrderedDict({'name' : o.name,
122 'addr_method' : o.addr_method,
123 'addr_family' : o.addr_family,
124 'auto' : o.auto,
125 'config' : retconfig})
126
127 class iface():
128 """ flags """
129 # flag to indicate that the object was created from pickled state
130 PICKLED = 0x1
131
132 version = '0.1'
133
134 def __init__(self):
135 self.name = None
136 self.addr_family = None
137 self.addr_method = None
138 self.config = OrderedDict()
139 self.config_status = {}
140 self.state = ifaceState.NEW
141 self.status = ifaceStatus.UNKNOWN
142 self.errstr = ''
143 self.flags = 0x0
144 self.priv_flags = 0x0
145 self.refcnt = 0
146 self.lowerifaces = None
147 self.upperifaces = None
148 self.auto = False
149 self.classes = []
150 self.env = None
151 self.config_current = {}
152 self.raw_lines = []
153 self.linkstate = None
154
155 def inc_refcnt(self):
156 self.refcnt += 1
157
158 def dec_refcnt(self):
159 self.refcnt -= 1
160
161 def get_refcnt(self):
162 return self.refcnt
163
164 def set_refcnt(self, cnt):
165 self.refcnt = 0
166
167 def set_name(self, name):
168 self.name = name
169
170 def get_name(self):
171 return self.name
172
173 def set_addr_family(self, family):
174 self.addr_family = family
175
176 def get_addr_family(self):
177 return self.addr_family
178
179 def set_addr_method(self, method):
180 self.addr_method = method
181
182 def get_addr_method(self):
183 return self.addr_method
184
185 def set_config(self, config_dict):
186 self.config = config_dict
187
188 def get_config(self):
189 return self.config
190
191 def is_config_present(self):
192 addr_method = self.get_addr_method()
193 if addr_method:
194 if (addr_method.find('dhcp') != -1 or
195 addr_method.find('dhcp6') != -1):
196 return True
197 if not self.config:
198 return False
199 else:
200 return True
201
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
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 """
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
234 def set_priv_flags(self, priv_flags):
235 self.priv_flags = priv_flags
236
237 def get_priv_flags(self):
238 return self.priv_flags
239
240 def get_state(self):
241 return self.state
242
243 def get_state_str(self):
244 return ifaceState.to_str(self.state)
245
246 def set_state(self, state):
247 self.state = state
248
249 def get_status(self):
250 return self.status
251
252 def get_status_str(self):
253 return ifaceStatus.to_str(self.status)
254
255 def set_status(self, status):
256 self.status = status
257
258 def set_state_n_status(self, state, status):
259 self.state = state
260 self.status = status
261
262 def state_str_to_hex(self, state_str):
263 return self.state_str_map.get(state_str)
264
265 def set_flag(self, flag):
266 self.flags |= flag
267
268 def clear_flag(self, flag):
269 self.flags &= ~flag
270
271 def set_lowerifaces(self, dlist):
272 self.lowerifaces = dlist
273
274 def get_lowerifaces(self):
275 return self.lowerifaces
276
277 def set_upperifaces(self, dlist):
278 self.upperifaces = dlist
279
280 def add_to_upperifaces(self, upperifacename):
281 if self.upperifaces:
282 if upperifacename not in self.upperifaces:
283 self.upperifaces.append(upperifacename)
284 else:
285 self.upperifaces = [upperifacename]
286
287 def get_upperifaces(self):
288 return self.upperifaces
289
290 def set_linkstate(self, l):
291 self.linkstate = l
292
293 def get_linkstate(self):
294 return self.linkstate
295
296 def get_attr_value(self, attr_name):
297 config = self.get_config()
298
299 return config.get(attr_name)
300
301 def get_attr_value_first(self, attr_name):
302 config = self.get_config()
303 attr_value_list = config.get(attr_name)
304 if attr_value_list:
305 return attr_value_list[0]
306 return None
307
308 def get_attr_value_n(self, attr_name, attr_index):
309 config = self.get_config()
310
311 attr_value_list = config.get(attr_name)
312 if attr_value_list:
313 try:
314 return attr_value_list[attr_index]
315 except:
316 return None
317 return None
318
319 def get_env(self):
320 if not self.env:
321 self.generate_env()
322 return self.env
323
324 def set_env(self, env):
325 self.env = env
326
327 def generate_env(self):
328 env = {}
329 config = self.get_config()
330 env['IFACE'] = self.get_name()
331 for attr, attr_value in config.items():
332 attr_env_name = 'IF_%s' %attr.upper()
333 env[attr_env_name] = attr_value[0]
334
335 if env:
336 self.set_env(env)
337
338 def update_config(self, attr_name, attr_value):
339 if not self.config.get(attr_name):
340 self.config[attr_name] = [attr_value]
341 else:
342 self.config[attr_name].append(attr_value)
343
344 def update_config_dict(self, attrdict):
345 self.config.update(attrdict)
346
347 def update_config_with_status(self, attr_name, attr_value, attr_status=0):
348 if not attr_value:
349 attr_value = ''
350
351 if self.config.get(attr_name):
352 self.config[attr_name].append(attr_value)
353 self.config_status[attr_name].append(attr_status)
354 else:
355 self.config[attr_name] = [attr_value]
356 self.config_status[attr_name] = [attr_status]
357
358 # set global iface state
359 if attr_status:
360 self.set_status(ifaceStatus.ERROR)
361 elif self.get_status() != ifaceStatus.ERROR:
362 # Not already error, mark success
363 self.set_status(ifaceStatus.SUCCESS)
364
365 def get_config_attr_status(self, attr_name, idx=0):
366 self.config_status.get(attr_name, [])[idx]
367
368 def get_config_attr_status_str(self, attr_name, idx=0):
369 ret = self.config_status.get(attr_name, [])[idx]
370 if ret:
371 return crossmark
372 else:
373 return tickmark
374
375 def is_different(self, dstiface):
376 if self.name != dstiface.name: return True
377 if self.addr_family != dstiface.addr_family: return True
378 if self.addr_method != dstiface.addr_method: return True
379 if self.auto != dstiface.auto: return True
380 if self.classes != dstiface.classes: return True
381
382 if any(True for k in self.config if k not in dstiface.config):
383 return True
384
385 if any(True for k,v in self.config.items()
386 if v != dstiface.config.get(k)): return True
387
388 return False
389
390 def __getstate__(self):
391 odict = self.__dict__.copy()
392 del odict['state']
393 del odict['status']
394 del odict['lowerifaces']
395 del odict['refcnt']
396 return odict
397
398 def __setstate__(self, dict):
399 self.__dict__.update(dict)
400 self.state = ifaceState.NEW
401 self.status = ifaceStatus.UNKNOWN
402 self.refcnt = 0
403 self.lowerifaces = None
404 self.linkstate = None
405 self.flags |= self.PICKLED
406
407 def dump_raw(self, logger):
408 indent = ' '
409 print (self.raw_lines[0])
410 for i in range(1, len(self.raw_lines)):
411 print (indent + self.raw_lines[i])
412
413 def dump(self, logger):
414 indent = '\t'
415 logger.info(self.get_name() + ' : {')
416 logger.info(indent + 'family: %s' %self.get_addr_family())
417 logger.info(indent + 'method: %s' %self.get_addr_method())
418 logger.info(indent + 'flags: %x' %self.flags)
419 logger.info(indent + 'state: %s'
420 %ifaceState.to_str(self.get_state()))
421 logger.info(indent + 'status: %s'
422 %ifaceStatus.to_str(self.get_status()))
423 logger.info(indent + 'refcnt: %d' %self.get_refcnt())
424 d = self.get_lowerifaces()
425 if d:
426 logger.info(indent + 'lowerdevs: %s' %str(d))
427 else:
428 logger.info(indent + 'lowerdevs: None')
429
430 logger.info(indent + 'config: ')
431 config = self.get_config()
432 if config:
433 logger.info(indent + indent + str(config))
434 logger.info('}')
435
436 def dump_pretty(self, with_status=False):
437 indent = '\t'
438 outbuf = ''
439 if self.get_auto():
440 outbuf += 'auto %s\n' %self.get_name()
441 outbuf += 'iface %s' %self.get_name()
442 if self.get_addr_family():
443 outbuf += ' %s' %self.get_addr_family()
444 if self.get_addr_method():
445 outbuf += ' %s' %self.get_addr_method()
446 outbuf += '\n'
447 config = self.get_config()
448 if config:
449 for cname, cvaluelist in config.items():
450 idx = 0
451 for cv in cvaluelist:
452 if with_status:
453 outbuf += indent + '%s %s %s\n' %(cname, cv,
454 self.get_config_attr_status_str(cname, idx))
455 else:
456 outbuf += indent + '%s %s\n' %(cname, cv)
457 idx += 1
458
459 print outbuf
460
461 def dump_json(self, with_status=False):
462 print json.dumps(self, cls=ifaceJsonEncoder, indent=4)