]> git.proxmox.com Git - mirror_ifupdown2.git/blob - pkg/iface.py
execute 'up' on upper devices if ifup is called with --with-depends
[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 class ifaceJsonEncoder(json.JSONEncoder):
111 def default(self, o):
112 retconfig = {}
113 if o.config:
114 for k, v in o.config.items():
115 if len(v) == 1:
116 retconfig[k] = v[0]
117 else:
118 retconfig[k] = v
119
120 return OrderedDict({'name' : o.name,
121 'addr_method' : o.addr_method,
122 'addr_family' : o.addr_family,
123 'auto' : o.auto,
124 'config' : retconfig})
125
126 class iface():
127 """ flags """
128 # flag to indicate that the object was created from pickled state
129 PICKLED = 0x1
130
131 version = '0.1'
132
133 def __init__(self):
134 self.name = None
135 self.addr_family = None
136 self.addr_method = None
137 self.config = OrderedDict()
138 self.config_status = {}
139 self.state = ifaceState.NEW
140 self.status = ifaceStatus.UNKNOWN
141 self.flags = 0x0
142 self.priv_flags = 0x0
143 self.refcnt = 0
144 self.lowerifaces = None
145 self.upperifaces = None
146 self.auto = False
147 self.classes = []
148 self.env = None
149 self.raw_lines = []
150 self.linkstate = None
151
152 def inc_refcnt(self):
153 self.refcnt += 1
154
155 def dec_refcnt(self):
156 self.refcnt -= 1
157
158 def get_refcnt(self):
159 return self.refcnt
160
161 def set_refcnt(self, cnt):
162 self.refcnt = 0
163
164 def set_name(self, name):
165 self.name = name
166
167 def get_name(self):
168 return self.name
169
170 def set_addr_family(self, family):
171 self.addr_family = family
172
173 def get_addr_family(self):
174 return self.addr_family
175
176 def set_addr_method(self, method):
177 self.addr_method = method
178
179 def get_addr_method(self):
180 return self.addr_method
181
182 def set_config(self, config_dict):
183 self.config = config_dict
184
185 def get_config(self):
186 return self.config
187
188 def is_config_present(self):
189 addr_method = self.get_addr_method()
190 if addr_method:
191 if (addr_method.find('dhcp') != -1 or
192 addr_method.find('dhcp6') != -1):
193 return True
194 if not self.config:
195 return False
196 else:
197 return True
198
199 def get_auto(self):
200 return self.auto
201
202 def set_auto(self):
203 self.auto = True
204
205 def reset_auto(self):
206 self.auto = False
207
208 def get_classes(self):
209 return self.classes
210
211 def set_classes(self, classes):
212 """ sets interface class list to the one passed as arg """
213 self.classes = classes
214
215 def set_class(self, classname):
216 """ Appends a class to the list """
217 self.classes.append(classname)
218
219 def belongs_to_class(self, intfclass):
220 if intfclass in self.classes:
221 return True
222 return False
223
224 def set_priv_flags(self, priv_flags):
225 self.priv_flags = priv_flags
226
227 def get_priv_flags(self):
228 return self.priv_flags
229
230 def get_state(self):
231 return self.state
232
233 def get_state_str(self):
234 return ifaceState.to_str(self.state)
235
236 def set_state(self, state):
237 self.state = state
238
239 def get_status(self):
240 return self.status
241
242 def get_status_str(self):
243 return ifaceStatus.to_str(self.status)
244
245 def set_status(self, status):
246 self.status = status
247
248 def set_state_n_status(self, state, status):
249 self.state = state
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
261 def set_lowerifaces(self, dlist):
262 self.lowerifaces = dlist
263
264 def get_lowerifaces(self):
265 return self.lowerifaces
266
267 def set_upperifaces(self, dlist):
268 self.upperifaces = dlist
269
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
279
280 def set_linkstate(self, l):
281 self.linkstate = l
282
283 def get_linkstate(self):
284 return self.linkstate
285
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()
293 attr_value_list = config.get(attr_name)
294 if attr_value_list:
295 return attr_value_list[0]
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:
303 try:
304 return attr_value_list[attr_index]
305 except:
306 return None
307 return None
308
309 def get_env(self):
310 if not self.env:
311 self.generate_env()
312 return self.env
313
314 def set_env(self, env):
315 self.env = env
316
317 def generate_env(self):
318 env = {}
319 config = self.get_config()
320 env['IFACE'] = self.get_name()
321 for attr, attr_value in config.items():
322 attr_env_name = 'IF_%s' %attr.upper()
323 env[attr_env_name] = attr_value[0]
324
325 if env:
326 self.set_env(env)
327
328 def update_config(self, attr_name, attr_value):
329 if not self.config.get(attr_name):
330 self.config[attr_name] = [attr_value]
331 else:
332 self.config[attr_name].append(attr_value)
333
334 def update_config_dict(self, attrdict):
335 self.config.update(attrdict)
336
337 def update_config_with_status(self, attr_name, attr_value, attr_status=0):
338 if not attr_value:
339 attr_value = ''
340
341 if self.config.get(attr_name):
342 self.config[attr_name].append(attr_value)
343 self.config_status[attr_name].append(attr_status)
344 else:
345 self.config[attr_name] = [attr_value]
346 self.config_status[attr_name] = [attr_status]
347
348 # set global iface state
349 if attr_status:
350 self.set_status(ifaceStatus.ERROR)
351 elif self.get_status() != ifaceStatus.ERROR:
352 # Not already error, mark success
353 self.set_status(ifaceStatus.SUCCESS)
354
355 def get_config_attr_status(self, attr_name, idx=0):
356 self.config_status.get(attr_name, [])[idx]
357
358 def get_config_attr_status_str(self, attr_name, idx=0):
359 ret = self.config_status.get(attr_name, [])[idx]
360 if ret:
361 return crossmark
362 else:
363 return tickmark
364
365 def is_different(self, dstiface):
366 if self.name != dstiface.name: return True
367 if self.addr_family != dstiface.addr_family: return True
368 if self.addr_method != dstiface.addr_method: return True
369 if self.auto != dstiface.auto: return True
370 if self.classes != dstiface.classes: return True
371
372 if any(True for k in self.config if k not in dstiface.config):
373 return True
374
375 if any(True for k,v in self.config.items()
376 if v != dstiface.config.get(k)): return True
377
378 return False
379
380 def __getstate__(self):
381 odict = self.__dict__.copy()
382 del odict['state']
383 del odict['status']
384 del odict['lowerifaces']
385 del odict['upperifaces']
386 del odict['refcnt']
387 del odict['config_status']
388 del odict['flags']
389 del odict['priv_flags']
390 del odict['raw_lines']
391 del odict['linkstate']
392 del odict['env']
393 return odict
394
395 def __setstate__(self, dict):
396 self.__dict__.update(dict)
397 self.config_status = {}
398 self.state = ifaceState.NEW
399 self.status = ifaceStatus.UNKNOWN
400 self.refcnt = 0
401 self.flags = 0
402 self.lowerifaces = None
403 self.upperifaces = None
404 self.linkstate = None
405 self.env = None
406 self.priv_flags = 0
407 self.raw_lines = []
408 self.flags |= self.PICKLED
409
410 def dump_raw(self, logger):
411 indent = ' '
412 print (self.raw_lines[0])
413 for i in range(1, len(self.raw_lines)):
414 print (indent + self.raw_lines[i])
415
416 def dump(self, logger):
417 indent = '\t'
418 logger.info(self.get_name() + ' : {')
419 logger.info(indent + 'family: %s' %self.get_addr_family())
420 logger.info(indent + 'method: %s' %self.get_addr_method())
421 logger.info(indent + 'flags: %x' %self.flags)
422 logger.info(indent + 'state: %s'
423 %ifaceState.to_str(self.get_state()))
424 logger.info(indent + 'status: %s'
425 %ifaceStatus.to_str(self.get_status()))
426 logger.info(indent + 'refcnt: %d' %self.get_refcnt())
427 d = self.get_lowerifaces()
428 if d:
429 logger.info(indent + 'lowerdevs: %s' %str(d))
430 else:
431 logger.info(indent + 'lowerdevs: None')
432
433 logger.info(indent + 'config: ')
434 config = self.get_config()
435 if config:
436 logger.info(indent + indent + str(config))
437 logger.info('}')
438
439 def dump_pretty(self, with_status=False):
440 indent = '\t'
441 outbuf = ''
442 if self.get_auto():
443 outbuf += 'auto %s\n' %self.get_name()
444 outbuf += 'iface %s' %self.get_name()
445 if self.get_addr_family():
446 outbuf += ' %s' %self.get_addr_family()
447 if self.get_addr_method():
448 outbuf += ' %s' %self.get_addr_method()
449 outbuf += '\n'
450 config = self.get_config()
451 if config:
452 for cname, cvaluelist in config.items():
453 idx = 0
454 for cv in cvaluelist:
455 if with_status:
456 outbuf += indent + '%s %s %s\n' %(cname, cv,
457 self.get_config_attr_status_str(cname, idx))
458 else:
459 outbuf += indent + '%s %s\n' %(cname, cv)
460 idx += 1
461
462 print outbuf
463
464 def dump_json(self, with_status=False):
465 print json.dumps(self, cls=ifaceJsonEncoder, indent=4)