]> git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdown2/ifupdown/iface.py
bb095358997223f4a84431a0723de0aa9906ad44
[mirror_ifupdown2.git] / ifupdown2 / ifupdown / iface.py
1 #!/usr/bin/python
2 #
3 # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
5 #
6 # iface --
7 # interface object
8 #
9
10 """ifupdown2 network interface object
11
12 It is modeled based on the 'iface' section in /etc/network/interfaces
13 file. But can be extended to include any other network interface format
14 """
15
16 import json
17
18 from collections import OrderedDict
19
20
21 class ifaceStatusUserStrs():
22 """ This class declares strings user can see during an ifquery --check
23 for example. These strings can be overridden by user defined strings from
24 config file """
25 SUCCESS = "success",
26 FAILURE = "error",
27 UNKNOWN = "unknown"
28
29 class ifaceType():
30 UNKNOWN = 0x00
31 IFACE = 0x01
32 BRIDGE_VLAN = 0x10
33
34 class ifaceRole():
35 """ ifaceRole is used to classify the ifaceobj.role of
36 MASTER or SLAVE where there is a bond or bridge
37 with bond-slaves or bridge-ports. A bond in a bridge
38 is both a master and slave (0x3)
39 """
40 UNKNOWN = 0x00
41 SLAVE = 0x01
42 MASTER = 0x10
43
44 class ifaceLinkKind():
45 """ ifaceLlinkKind is used to identify interfaces
46 in the ifaceobj.link_kind attribute. Dependents of the bridge or
47 bond have an ifaceobj.role attribute of SLAVE and the bridge or
48 bond itself has ifaceobj.role of MASTER.
49 """
50 UNKNOWN = 0x0000000
51 BRIDGE = 0x0000001
52 BOND = 0x0000010
53 VLAN = 0x0000100
54 VXLAN = 0x0001000
55 VRF = 0x0010000
56 BATMAN_ADV = 0x0100000
57 # to indicate logical interface created by an external entity.
58 # the 'kind' of which ifupdown2 does not really understand
59 OTHER = 0x1000000
60
61 @classmethod
62 def to_str(cls, kind):
63 if kind == cls.BRIDGE:
64 return "bridge"
65 elif kind == cls.BOND:
66 return "bond"
67 elif kind == cls.VLAN:
68 return "vlan"
69 elif kind == cls.VXLAN:
70 return "vxlan"
71 elif kind == cls.VRF:
72 return "vrf"
73
74 class ifaceLinkPrivFlags():
75 """ This corresponds to kernel netdev->priv_flags
76 and can be BRIDGE_PORT, BOND_SLAVE etc """
77 UNKNOWN = 0x00000
78 BRIDGE_PORT = 0x00001
79 BOND_SLAVE = 0x00010
80 VRF_SLAVE = 0x00100
81 BRIDGE_VLAN_AWARE = 0x01000
82 BRIDGE_VXLAN = 0x10000
83 ADDRESS_VIRTUAL_SLAVE = 0x100000
84 LOOPBACK = 0x1000000
85 KEEP_LINK_DOWN = 0x10000000
86
87 @classmethod
88 def get_str(cls, flag):
89 if flag == cls.UNKNOWN:
90 return 'unknown'
91 elif flag == cls.BRIDGE_PORT:
92 return 'bridge port'
93 elif flag == cls.BOND_SLAVE:
94 return 'bond slave'
95 elif flag == cls.VRF_SLAVE:
96 return 'vrf slave'
97 elif flag == cls.BRIDGE_VLAN_AWARE:
98 return 'vlan aware bridge'
99 elif flag == cls.BRIDGE_VXLAN:
100 return 'vxlan bridge'
101
102 @classmethod
103 def get_all_str(cls, flags):
104 str = ''
105 if flags & cls.BRIDGE_PORT:
106 str += 'bridgeport '
107 if flags & cls.BOND_SLAVE:
108 str += 'bondslave '
109 if flags & cls.VRF_SLAVE:
110 str += 'vrfslave '
111 if flags & cls.BRIDGE_VLAN_AWARE:
112 str += 'vlanawarebridge '
113 if flags & cls.BRIDGE_VXLAN:
114 str += 'vxlanbridge '
115 return str
116
117 class ifaceLinkType():
118 LINK_UNKNOWN = 0x0
119 LINK_SLAVE = 0x1
120 LINK_MASTER = 0x2
121 LINK_NA = 0x3
122
123 class VlanProtocols():
124 # Picked ID values from
125 # http://www.microhowto.info/howto/configure_an_ethernet_interface_as_a_qinq_vlan_trunk.html
126 ETHERTYPES_TO_ID = {
127 '802.1Q' : '0x8100',
128 '802.1AD' : '0x88a8',
129 }
130 ID_TO_ETHERTYPES = {
131 '0x8100' : '802.1Q',
132 '0x88a8' : '802.1AD',
133 }
134
135 class ifaceDependencyType():
136 """ Indicates type of dependency.
137
138 This class enumerates types of dependency relationships
139 between interfaces.
140
141 iface dependency relationships can be classified
142 into:
143 - link
144 - master/slave
145
146 In a 'link' dependency relationship, dependency can be shared
147 between interfaces. example: swp1.100 and
148 swp1.200 can both have 'link' swp1. swp1 is also a dependency
149 of swp1.100 and swp1.200. As you can see dependency
150 swp1 is shared between swp1.100 and swp1.200.
151
152 In a master/slave relationship like bridge and
153 its ports: eg: bridge br0 and its ports swp1 and swp2.
154 dependency swp1 and swp2 cannot be shared with any other
155 interface with the same dependency relationship.
156 ie, swp1 and swp2 cannot be in a slave relationship
157 with another interface. Understanding the dependency type is
158 required for any semantic checks between dependencies.
159
160 """
161 UNKNOWN = 0x0
162 LINK = 0x1
163 MASTER_SLAVE = 0x2
164
165 class ifaceStatus():
166 """Enumerates iface status """
167
168 UNKNOWN = 0x1
169 SUCCESS = 0x2
170 WARNING = 0x3
171 ERROR = 0x4
172 NOTFOUND = 0x5
173
174 @classmethod
175 def to_str(cls, state):
176 if state == cls.UNKNOWN:
177 return 'unknown'
178 elif state == cls.SUCCESS:
179 return 'success'
180 elif state == cls.ERROR:
181 return 'error'
182 elif state == cls.NOTFOUND:
183 return 'notfound'
184
185 @classmethod
186 def from_str(cls, state_str):
187 if state_str == 'unknown':
188 return cls.UNKNOWN
189 elif state_str == 'success':
190 return cls.SUCCESS
191 elif state_str == 'error':
192 return cls.ERROR
193
194 class ifaceState():
195 """Enumerates iface state """
196
197 UNKNOWN = 0x1
198 NEW = 0x2
199 PRE_UP = 0x3
200 UP = 0x4
201 POST_UP = 0x5
202 PRE_DOWN = 0x6
203 DOWN = 0x7
204 POST_DOWN = 0x8
205
206 # Pseudo states
207 QUERY_CHECKCURR = 0x9
208 QUERY_RUNNING = 0xa
209
210 @classmethod
211 def to_str(cls, state):
212 if state == cls.UNKNOWN:
213 return 'unknown'
214 elif state == cls.NEW:
215 return 'new'
216 elif state == cls.PRE_UP:
217 return 'pre-up'
218 elif state == cls.UP:
219 return 'up'
220 elif state == cls.POST_UP:
221 return 'post-up'
222 elif state == cls.PRE_DOWN:
223 return 'pre-down'
224 elif state == cls.DOWN:
225 return 'down'
226 elif state == cls.POST_DOWN:
227 return 'post-down'
228 elif state == cls.QUERY_CHECKCURR:
229 return 'query-checkcurr'
230 elif state == cls.QUERY_RUNNING:
231 return 'query-running'
232
233 @classmethod
234 def from_str(cls, state_str):
235 if state_str == 'unknown':
236 return cls.UNKNOWN
237 elif state_str == 'new':
238 return cls.NEW
239 elif state_str == 'pre-up':
240 return cls.PRE_UP
241 elif state_str == 'up':
242 return cls.UP
243 elif state_str == 'post-up':
244 return cls.POST_UP
245 elif state_str == 'pre-down':
246 return cls.PRE_DOWN
247 elif state_str == 'down':
248 return cls.DOWN
249 elif state_str == 'post-down':
250 return cls.POST_DOWN
251 elif state_str == 'query-checkcurr':
252 return cls.QUERY_CHECKCURR
253 elif state_str == 'query-running':
254 return cls.QUERY_RUNNING
255
256 class ifaceJsonEncoder(json.JSONEncoder):
257 def default(self, o):
258 retconfig = {}
259 retifacedict = OrderedDict([])
260 if o.config:
261 retconfig = dict((k, (v[0] if len(v) == 1 else v))
262 for k,v in o.config.items())
263 retifacedict['name'] = o.name
264 if o.addr_method:
265 if 'inet' in o.addr_family and 'dhcp' in o.addr_method:
266 retifacedict['addr_method'] = 'dhcp'
267 else:
268 retifacedict['addr_method'] = o.addr_method
269 if o.addr_family:
270 if len(o.addr_family) > 1:
271 retifacedict['addr_family'] = o.addr_family
272 else:
273 retifacedict['addr_family'] = ' '.join(o.addr_family)
274 retifacedict['auto'] = o.auto
275 retifacedict['config'] = retconfig
276
277 return retifacedict
278
279 class ifaceJsonEncoderWithStatus(json.JSONEncoder):
280 def default(self, o):
281 retconfig = {}
282 retconfig_status = {}
283 retifacedict = OrderedDict([])
284 if o.config:
285 for k,v in o.config.items():
286 idx = 0
287 vitem_status = []
288 for vitem in v:
289 s = o.get_config_attr_status(k, idx)
290 if s == 1:
291 status_str = ifaceStatusUserStrs.ERROR
292 elif s == 0:
293 status_str = ifaceStatusUserStrs.SUCCESS
294 else:
295 status_str = ifaceStatusUserStrs.UNKNOWN
296 vitem_status.append('%s' %status_str)
297 idx += 1
298 retconfig[k] = v[0] if len(v) == 1 else v
299 retconfig_status[k] = vitem_status[0] if len(vitem_status) == 1 else vitem_status
300
301 if (o.status == ifaceStatus.NOTFOUND or
302 o.status == ifaceStatus.ERROR):
303 status = ifaceStatusUserStrs.ERROR
304 else:
305 status = ifaceStatusUserStrs.SUCCESS
306
307 retifacedict['name'] = o.name
308 if o.addr_method:
309 retifacedict['addr_method'] = o.addr_method
310 if o.addr_family:
311 if len(o.addr_family) > 1:
312 retifacedict['addr_family'] = o.addr_family
313 else:
314 retifacedict['addr_family'] = ' '.join(o.addr_family)
315 retifacedict['auto'] = o.auto
316 retifacedict['config'] = retconfig
317 retifacedict['config_status'] = retconfig_status
318 retifacedict['status'] = status
319
320 return retifacedict
321
322 class ifaceJsonDecoder():
323 @classmethod
324 def json_to_ifaceobj(cls, ifaceattrdict):
325 ifaceattrdict['config'] = OrderedDict([(k, (v if isinstance(v, list)
326 else [v.strip()]))
327 for k,v in ifaceattrdict.get('config',
328 OrderedDict()).items()])
329 return iface(attrsdict=ifaceattrdict)
330
331 class iface():
332 """ ifupdown2 iface object class
333 Attributes:
334 **name** Name of the interface
335
336 **addr_family** Address family eg, inet, inet6. Can be None to
337 indicate both address families
338
339 **addr_method** Address method eg, static, manual or None for
340 static address method
341
342 **config** dictionary of config lines for this interface
343
344 **state** Configuration state of an interface as defined by
345 ifaceState
346
347 **status** Configuration status of an interface as defined by
348 ifaceStatus
349
350 **flags** Internal flags used by iface processing
351
352 **priv_flags** private flags owned by module using this class
353
354 **module_flags** module flags owned by module using this class
355
356 **refcnt** reference count, indicating number of interfaces
357 dependent on this iface
358
359 **lowerifaces** list of interface names lower to this interface or
360 this interface depends on
361
362 **upperifaces** list of interface names upper to this interface or
363 the interfaces that depend on this interface
364
365 **auto** True if interface belongs to the auto class
366
367 **classes** List of classes the interface belongs to
368
369 **env** shell environment the interface needs during
370 execution
371
372 **raw_config** raw interface config from file
373 """
374
375 # flag to indicate that the object was created from pickled state
376 # XXX: Move these flags into a separate iface flags class
377 _PICKLED = 0x00000001
378 HAS_SIBLINGS = 0x00000010
379 IFACERANGE_ENTRY = 0x00000100
380 IFACERANGE_START = 0x00001000
381 OLDEST_SIBLING = 0x00010000
382 YOUNGEST_SIBLING = 0x00100000
383
384 version = '0.1'
385
386 def __init__(self, attrsdict={}):
387 self.addr_family = []
388
389 self._set_attrs_from_dict(attrsdict)
390 self._config_status = {}
391 """dict with config status of iface attributes"""
392 self.state = ifaceState.NEW
393 """iface state (of type ifaceState) """
394 self.status = ifaceStatus.UNKNOWN
395 """iface status (of type ifaceStatus) """
396 self.status_str = None
397 """iface status str (string representing the status) """
398 self.flags = 0x0
399 """iface flags """
400 self.priv_flags = None
401 """iface module flags dictionary with module name: flags"""
402 self.module_flags = {}
403 """iface priv flags. can be used by the external object manager """
404 self.refcnt = 0
405 """iface refcnt (incremented for each dependent this interface has) """
406 self.lowerifaces = None
407 """lower iface list (in other words: slaves of this interface """
408 self.upperifaces = None
409 """upper iface list (in other words: master of this interface """
410 self.classes = []
411 """interface classes this iface belongs to """
412 self.env = None
413 """environment variable dict required for this interface to run"""
414 self.raw_config = []
415 """interface config/attributes in raw format (eg: as it appeared in the interfaces file)"""
416 self.linkstate = None
417 """linkstate of the interface"""
418 self.type = ifaceType.UNKNOWN
419 """interface type"""
420 self.priv_data = None
421 self.role = ifaceRole.UNKNOWN
422 self.realname = None
423 self.link_type = ifaceLinkType.LINK_UNKNOWN
424 self.link_kind = ifaceLinkKind.UNKNOWN
425 self.link_privflags = ifaceLinkPrivFlags.UNKNOWN
426
427 # The below attribute is used to disambiguate between various
428 # types of dependencies
429 self.dependency_type = ifaceDependencyType.UNKNOWN
430 self.blacklisted = False
431
432 def _set_attrs_from_dict(self, attrdict):
433 self.auto = attrdict.get('auto', False)
434 self.name = attrdict.get('name')
435 self.addr_method = attrdict.get('addr_method')
436 self.config = attrdict.get('config', OrderedDict())
437
438 addr_family = attrdict.get('addr_family')
439 if addr_family:
440 self.addr_family.append(addr_family)
441
442 def inc_refcnt(self):
443 """ increment refcnt of the interface. Usually used to indicate that
444 it has dependents """
445 self.refcnt += 1
446
447 def dec_refcnt(self):
448 """ decrement refcnt of the interface. Usually used to indicate that
449 it has lost its dependent """
450 self.refcnt -= 1
451
452 def is_config_present(self):
453 """ returns true if the interface has user provided config,
454 false otherwise """
455 addr_method = self.addr_method
456 if addr_method and addr_method in ['dhcp', 'dhcp6', 'loopback']:
457 return True
458 if not self.config:
459 return False
460 else:
461 return True
462
463 def set_class(self, classname):
464 """ appends class to the interfaces class list """
465 self.classes.append(classname)
466
467 def set_state_n_status(self, state, status):
468 """ sets state and status of an interface """
469 self.state = state
470 if status > self.status:
471 self.status = status
472
473 def set_status(self, status):
474 """ sets status of an interface """
475 if status > self.status:
476 self.status = status
477
478 def set_flag(self, flag):
479 self.flags |= flag
480
481 def clear_flag(self, flag):
482 self.flags &= ~flag
483
484 def add_to_upperifaces(self, upperifacename):
485 """ add to the list of upperifaces """
486 if self.upperifaces:
487 if upperifacename not in self.upperifaces:
488 self.upperifaces.append(upperifacename)
489 else:
490 self.upperifaces = [upperifacename]
491
492 def add_to_lowerifaces(self, lowerifacename):
493 """ add to the list of lowerifaces """
494 if self.lowerifaces:
495 if lowerifacename not in self.lowerifaces:
496 self.lowerifaces.append(lowerifacename)
497 else:
498 self.lowerifaces = [lowerifacename]
499
500 def get_attr_value(self, attr_name):
501 """ add to the list of upperifaces """
502 return self.config.get(attr_name)
503
504 def get_attr_value_first(self, attr_name):
505 """ get first value of the specified attr name """
506 attr_value_list = self.config.get(attr_name)
507 if attr_value_list:
508 return attr_value_list[0]
509 return None
510
511 def get_attrs_value_first(self, attrs):
512 """ get first value of the first attr in the list.
513 Useful when you have multiple attrs representing the
514 same thing.
515 """
516 for attr in attrs:
517 attr_value_list = self.config.get(attr)
518 if attr_value_list:
519 return attr_value_list[0]
520 return None
521
522 def get_attr_value_n(self, attr_name, attr_index):
523 """ get n'th value of the specified attr name """
524 attr_value_list = self.config.get(attr_name)
525 if attr_value_list:
526 try:
527 return attr_value_list[attr_index]
528 except:
529 return None
530 return None
531
532 def get_env(self):
533 """ get shell environment variables the interface must execute in """
534 if not self.env:
535 self.generate_env()
536 return self.env
537
538 def generate_env(self):
539 """ generate shell environment variables dict interface must execute
540 in. This is used to support legacy ifupdown scripts
541 """
542 env = {}
543 config = self.config
544 env['IFACE'] = self.name
545 for attr, attr_value in config.items():
546 attr_env_name = 'IF_%s' %attr.upper().replace("-", "_")
547 env[attr_env_name] = attr_value[0]
548 self.env = env
549
550 def update_config(self, attr_name, attr_value):
551 """ add attribute name and value to the interface config """
552 self.config.setdefault(attr_name, []).append(attr_value)
553
554 def replace_config(self, attr_name, attr_value):
555 """ add attribute name and value to the interface config """
556 self.config[attr_name] = [attr_value]
557
558 def delete_config(self, attr_name):
559 """ add attribute name and value to the interface config """
560 try:
561 del self.config[attr_name]
562 except:
563 pass
564
565 def update_config_dict(self, attrdict):
566 self.config.update(attrdict)
567
568 def update_config_with_status(self, attr_name, attr_value, attr_status=0):
569 """ add attribute name and value to the interface config and also
570 update the config_status dict with status of this attribute config """
571 if not attr_value:
572 attr_value = ''
573 self.config.setdefault(attr_name, []).append(attr_value)
574 self._config_status.setdefault(attr_name, []).append(attr_status)
575 # set global iface state
576 if attr_status == 1:
577 self.status = ifaceStatus.ERROR
578 elif self.status != ifaceStatus.ERROR:
579 # Not already error, mark success
580 self.status = ifaceStatus.SUCCESS
581
582 def check_n_update_config_with_status_many(self, ifaceobjorig, attr_names,
583 attr_status=0):
584 # set multiple attribute status to zero
585 # also updates status only if the attribute is present
586 for attr_name in attr_names:
587 if not ifaceobjorig.get_attr_value_first(attr_name):
588 continue
589 self.config.setdefault(attr_name, []).append('')
590 self._config_status.setdefault(attr_name, []).append(attr_status)
591
592 def get_config_attr_status(self, attr_name, idx=0):
593 """ get status of a attribute config on this interface.
594
595 Looks at the iface _config_status dict"""
596 return self._config_status.get(attr_name, [])[idx]
597
598 def compare(self, dstiface):
599 """ compares iface object with iface object passed as argument
600
601 Returns True if object self is same as dstiface and False otherwise """
602
603 if self.name != dstiface.name: return False
604 if self.type != dstiface.type: return False
605 if self.addr_family != dstiface.addr_family: return False
606 if self.addr_method != dstiface.addr_method: return False
607 if self.auto != dstiface.auto: return False
608 if self.classes != dstiface.classes: return False
609 if len(self.config) != len(dstiface.config):
610 return False
611 if any(True for k in self.config if k not in dstiface.config):
612 return False
613 if any(True for k,v in self.config.items()
614 if v != dstiface.config.get(k)): return False
615 return True
616
617 def squash(self, newifaceobj):
618 """ This squashes the iface object """
619 for attrname, attrlist in newifaceobj.config.iteritems():
620 # if allready present add it to the list
621 # else add it to the end of the dictionary
622 # We need to maintain order.
623 if self.config.get(attrname):
624 self.config[attrname].extend(attrlist)
625 else:
626 self.config.update([(attrname, attrlist)])
627 # we now support inet and inet6 together
628 self.addr_family.extend(newifaceobj.addr_family)
629 # if auto %ifacename is not part of the first stanza
630 # we need to squash it
631 if not self.auto and newifaceobj.auto:
632 self.auto = True
633
634 def __getstate__(self):
635 odict = self.__dict__.copy()
636 del odict['state']
637 del odict['status']
638 del odict['lowerifaces']
639 del odict['upperifaces']
640 del odict['refcnt']
641 del odict['_config_status']
642 del odict['flags']
643 del odict['priv_flags']
644 del odict['module_flags']
645 del odict['raw_config']
646 del odict['linkstate']
647 del odict['env']
648 del odict['link_type']
649 del odict['link_kind']
650 del odict['link_privflags']
651 del odict['role']
652 del odict['dependency_type']
653 del odict['blacklisted']
654 return odict
655
656 def __setstate__(self, dict):
657 self.__dict__.update(dict)
658 self._config_status = {}
659 self.state = ifaceState.NEW
660 self.status = ifaceStatus.UNKNOWN
661 self.refcnt = 0
662 self.flags = 0
663 self.lowerifaces = None
664 self.upperifaces = None
665 self.linkstate = None
666 self.env = None
667 self.role = ifaceRole.UNKNOWN
668 self.priv_flags = None
669 self.module_flags = {}
670 self.raw_config = []
671 self.flags |= self._PICKLED
672 self.link_type = ifaceLinkType.LINK_NA
673 self.link_kind = ifaceLinkKind.UNKNOWN
674 self.link_privflags = ifaceLinkPrivFlags.UNKNOWN
675 self.dependency_type = ifaceDependencyType.UNKNOWN
676 self.blacklisted = False
677
678 def dump_raw(self, logger):
679 indent = ' '
680 if self.auto:
681 print 'auto %s' %self.name
682 print (self.raw_config[0])
683 for i in range(1, len(self.raw_config)):
684 print(indent + self.raw_config[i])
685
686 def dump(self, logger):
687 indent = '\t'
688 logger.info(self.name + ' : {')
689 logger.info(indent + 'family: %s' % ' '.join(self.addr_family))
690 logger.info(indent + 'method: %s' %self.addr_method)
691 logger.info(indent + 'flags: %x' %self.flags)
692 logger.info(indent + 'state: %s'
693 %ifaceState.to_str(self.state))
694 logger.info(indent + 'status: %s'
695 %ifaceStatus.to_str(self.status))
696 logger.info(indent + 'refcnt: %d' %self.refcnt)
697 d = self.lowerifaces
698 if d:
699 logger.info(indent + 'lowerdevs: %s' %str(d))
700 else:
701 logger.info(indent + 'lowerdevs: None')
702
703 d = self.upperifaces
704 if d:
705 logger.info(indent + 'upperdevs: %s' %str(d))
706 else:
707 logger.info(indent + 'upperdevs: None')
708
709 logger.info(indent + 'config: ')
710 config = self.config
711 if config:
712 logger.info(indent + indent + str(config))
713 logger.info('}')
714
715 def _dump_pretty(self, family, first, addr_method, with_status=False, use_realname=False):
716 indent = '\t'
717 outbuf = ''
718 if use_realname and self.realname:
719 name = '%s' %self.realname
720 else:
721 name = '%s' %self.name
722 if self.auto:
723 outbuf += 'auto %s\n' %name
724 ifaceline = ''
725 if self.type == ifaceType.BRIDGE_VLAN:
726 ifaceline += 'vlan %s' %name
727 else:
728 ifaceline += 'iface %s' %name
729 if family:
730 ifaceline += ' %s' % family
731 if addr_method:
732 ifaceline += ' %s' % addr_method
733 if with_status:
734 status_str = None
735 if (self.status == ifaceStatus.ERROR or
736 self.status == ifaceStatus.NOTFOUND):
737 if self.status_str:
738 ifaceline += ' (%s)' %self.status_str
739 status_str = '[%s]' %ifaceStatusUserStrs.ERROR
740 elif self.status == ifaceStatus.SUCCESS:
741 status_str = '[%s]' %ifaceStatusUserStrs.SUCCESS
742 if status_str:
743 outbuf += '{0:65} {1:>8}'.format(ifaceline, status_str) + '\n'
744 else:
745 outbuf += ifaceline + '\n'
746 if self.status == ifaceStatus.NOTFOUND:
747 outbuf = (outbuf.encode('utf8')
748 if isinstance(outbuf, unicode) else outbuf)
749 print outbuf + '\n'
750 return
751 else:
752 outbuf += ifaceline + '\n'
753 config = self.config
754 if config and first:
755 for cname, cvaluelist in config.items():
756 idx = 0
757 for cv in cvaluelist:
758 status_str = None
759 if with_status:
760 s = self.get_config_attr_status(cname, idx)
761 if s == -1:
762 status_str = '[%s]' %ifaceStatusUserStrs.UNKNOWN
763 elif s == 1:
764 status_str = '[%s]' %ifaceStatusUserStrs.ERROR
765 elif s == 0:
766 status_str = '[%s]' %ifaceStatusUserStrs.SUCCESS
767 if status_str:
768 outbuf += (indent + '{0:55} {1:>10}'.format(
769 '%s %s' %(cname, cv), status_str)) + '\n'
770 else:
771 outbuf += indent + '%s %s\n' %(cname, cv)
772 idx += 1
773 if with_status:
774 outbuf = (outbuf.encode('utf8')
775 if isinstance(outbuf, unicode) else outbuf)
776 print outbuf
777
778 def dump_pretty(self, with_status=False, use_realname=False):
779 if not self.addr_family:
780 self._dump_pretty(None, True,
781 self.addr_method,
782 with_status=with_status,
783 use_realname=use_realname)
784 else:
785 # To allow both inet and inet6 on an interface we changed the
786 # addr_family attribute, it's now a list. Depending on how
787 # stanzas were squashed (and what command was used ie. ifquery -r)
788 # we want to dump the ifaceobj as usual but we will output an
789 # empty stanza for each additional addr_family. The config will
790 # only be displayed once, in the first stanza. Example:
791 # $ ifquery eth0 -r
792 # auto etho
793 # iface eth0 inet dhcp
794 # config...
795 #
796 # auto eth0
797 # iface eth0 inet6 dhcp
798 # $
799 first = True
800 for family in self.addr_family:
801 addr_method = self.addr_method
802 # We need to make sure we display 'dhcp' for inet family.
803 # In some cases it might take the value 'dhcp6' even if it has
804 # both inet and inet6 addr_family
805 if addr_method and family == 'inet' and 'dhcp' in addr_method:
806 addr_method = 'dhcp'
807 self._dump_pretty(family, first,
808 addr_method=addr_method,
809 with_status=with_status,
810 use_realname=use_realname)
811 first = False