]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown/iface.py
Fix a few more minor issues with auto and non-auto interfaces
[mirror_ifupdown2.git] / ifupdown / iface.py
CommitLineData
a6f80f0e 1#!/usr/bin/python
3e8ee54f 2#
904908bc 3# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
3e8ee54f 4# Author: Roopa Prabhu, roopa@cumulusnetworks.com
5#
6# iface --
7# interface object
8#
62ddec8b 9
10"""ifupdown2 network interface object
11
904908bc 12It is modeled based on the 'iface' section in /etc/network/interfaces
62ddec8b 13file. But can be extended to include any other network interface format
62ddec8b 14"""
15
cca03c30 16from collections import OrderedDict
d08d5f54 17import logging
2cd06f78 18import json
a6f80f0e 19
fb10449e
RP
20class ifaceStatusStrs():
21 SUCCESS = "success",
22 FAILURE = "error",
23 UNKNOWN = "unknown"
24
41febf89 25class ifaceType():
2da58137
RP
26 UNKNOWN = 0x0
27 IFACE = 0x1
28 BRIDGE_VLAN = 0x2
41febf89 29
0a3bee28
ST
30
31class ifaceRole():
32 """ ifaceRole is used to classify the ifaceobj.role of
33 MASTER or SLAVE where there is a bond or bridge
34 with bond-slaves or bridge-ports. A bond in a bridge
35 is both a master and slave (0x3)
36 """
37 UNKNOWN = 0x0
38 SLAVE = 0x1
39 MASTER = 0x2
40
a9ab1b4f 41class ifaceLinkKind():
0a3bee28
ST
42 """ ifaceLlinkKind is used to identify interfaces
43 in the ifaceobj.link_kind attribute. Dependents of the bridge or
44 bond have an ifaceobj.role attribute of SLAVE and the bridge or
45 bond itself has ifaceobj.role of MASTER.
46 """
a9ab1b4f
RP
47 UNKNOWN = 0x0
48 BRIDGE = 0x1
49 BOND = 0x2
0a3bee28
ST
50 VLAN = 0x4
51 VXLAN = 0x8
7f67f3e5 52 BRIDGE_VLAN_AWARE = 0x10
65e0c276
RP
53 BRIDGE_PORT = 0x20
54 BOND_SLAVE = 0x40
a9ab1b4f 55
c416da6a 56class ifaceLinkType():
a070c90e 57 LINK_UNKNOWN = 0x0
c416da6a
RP
58 LINK_SLAVE = 0x1
59 LINK_MASTER = 0x2
a070c90e 60 LINK_NA = 0x3
c416da6a 61
45ca0b6d
RP
62class ifaceDependencyType():
63 """ Indicates type of dependency.
64
65 This class enumerates types of dependency relationships
66 between interfaces.
67
68 iface dependency relationships can be classified
69 into:
70 - link
71 - master/slave
72
73 In a 'link' dependency relationship, dependency can be shared
74 between interfaces. example: swp1.100 and
75 swp1.200 can both have 'link' swp1. swp1 is also a dependency
76 of swp1.100 and swp1.200. As you can see dependency
77 swp1 is shared between swp1.100 and swp1.200.
78
79 In a master/slave relationship like bridge and
80 its ports: eg: bridge br0 and its ports swp1 and swp2.
81 dependency swp1 and swp2 cannot be shared with any other
82 interface with the same dependency relationship.
83 ie, swp1 and swp2 cannot be in a slave relationship
84 with another interface. Understanding the dependency type is
85 required for any semantic checks between dependencies.
86
87 """
88 UNKNOWN = 0x0
89 LINK = 0x1
90 MASTER_SLAVE = 0x2
91
a6f80f0e 92class ifaceStatus():
62ddec8b 93 """Enumerates iface status """
94
a6f80f0e 95 UNKNOWN = 0x1
96 SUCCESS = 0x2
97 ERROR = 0x3
10720a53 98 NOTFOUND = 0x4
a6f80f0e 99
100 @classmethod
101 def to_str(cls, state):
102 if state == cls.UNKNOWN:
103 return 'unknown'
104 elif state == cls.SUCCESS:
105 return 'success'
106 elif state == cls.ERROR:
107 return 'error'
739f665b 108 elif state == cls.NOTFOUND:
69f58278 109 return 'notfound'
a6f80f0e 110
111 @classmethod
112 def from_str(cls, state_str):
113 if state_str == 'unknown':
114 return cls.UNKNOWN
115 elif state_str == 'success':
116 return cls.SUCCESS
117 elif state_str == 'error':
118 return cls.ERROR
119
120class ifaceState():
62ddec8b 121 """Enumerates iface state """
a6f80f0e 122
a6f80f0e 123 UNKNOWN = 0x1
124 NEW = 0x2
125 PRE_UP = 0x3
126 UP = 0x4
127 POST_UP = 0x5
128 PRE_DOWN = 0x6
129 DOWN = 0x7
130 POST_DOWN = 0x8
131
d08d5f54 132 # Pseudo states
133 QUERY_CHECKCURR = 0x9
134 QUERY_RUNNING = 0xa
135
a6f80f0e 136 @classmethod
137 def to_str(cls, state):
138 if state == cls.UNKNOWN:
139 return 'unknown'
140 elif state == cls.NEW:
141 return 'new'
142 elif state == cls.PRE_UP:
143 return 'pre-up'
144 elif state == cls.UP:
145 return 'up'
146 elif state == cls.POST_UP:
147 return 'post-up'
148 elif state == cls.PRE_DOWN:
149 return 'pre-down'
d08d5f54 150 elif state == cls.DOWN:
151 return 'down'
a6f80f0e 152 elif state == cls.POST_DOWN:
153 return 'post-down'
d08d5f54 154 elif state == cls.QUERY_CHECKCURR:
155 return 'query-checkcurr'
156 elif state == cls.QUERY_RUNNING:
157 return 'query-running'
a6f80f0e 158
159 @classmethod
160 def from_str(cls, state_str):
161 if state_str == 'unknown':
162 return cls.UNKNOWN
163 elif state_str == 'new':
164 return cls.NEW
165 elif state_str == 'pre-up':
166 return cls.PRE_UP
167 elif state_str == 'up':
168 return cls.UP
169 elif state_str == 'post-up':
170 return cls.POST_UP
171 elif state_str == 'pre-down':
172 return cls.PRE_DOWN
d08d5f54 173 elif state_str == 'down':
174 return cls.DOWN
a6f80f0e 175 elif state_str == 'post-down':
176 return cls.POST_DOWN
d08d5f54 177 elif state_str == 'query-checkcurr':
178 return cls.QUERY_CHECKCURR
179 elif state_str == 'query-running':
180 return cls.QUERY_RUNNING
a6f80f0e 181
d08d5f54 182class ifaceJsonEncoder(json.JSONEncoder):
f012209e 183 def default(self, o):
83c1f241 184 retconfig = {}
fb10449e
RP
185 retifacedict = OrderedDict([])
186 if o.config:
f012209e
RP
187 retconfig = dict((k, (v[0] if len(v) == 1 else v))
188 for k,v in o.config.items())
189 retifacedict['name'] = o.name
190 if o.addr_method:
191 retifacedict['addr_method'] = o.addr_method
192 if o.addr_family:
193 retifacedict['addr_family'] = o.addr_family
194 retifacedict['auto'] = o.auto
195 retifacedict['config'] = retconfig
196
197 return retifacedict
198
199class ifaceJsonEncoderWithStatus(json.JSONEncoder):
200 def default(self, o):
201 retconfig = {}
202 retconfig_status = {}
203 retifacedict = OrderedDict([])
204 if o.config:
fb10449e
RP
205 for k,v in o.config.items():
206 idx = 0
207 vitem_status = []
208 for vitem in v:
209 s = o.get_config_attr_status(k, idx)
210 if s == -1:
211 status_str = ifaceStatusStrs.UNKNOWN
212 elif s == 1:
213 status_str = ifaceStatusStrs.ERROR
214 elif s == 0:
215 status_str = ifaceStatusStrs.SUCCESS
216 vitem_status.append('%s' %status_str)
217 idx += 1
218 retconfig[k] = v[0] if len(v) == 1 else v
219 retconfig_status[k] = vitem_status[0] if len(vitem_status) == 1 else vitem_status
220
221 if (o.status == ifaceStatus.NOTFOUND or
222 o.status == ifaceStatus.ERROR):
223 status = ifaceStatusStrs.ERROR
224 else:
225 status = ifaceStatusStrs.SUCCESS
226
227 retifacedict['name'] = o.name
228 if o.addr_method:
229 retifacedict['addr_method'] = o.addr_method
230 if o.addr_family:
231 retifacedict['addr_family'] = o.addr_family
232 retifacedict['auto'] = o.auto
233 retifacedict['config'] = retconfig
234 retifacedict['config_status'] = retconfig_status
235 retifacedict['status'] = status
236
237 return retifacedict
d08d5f54 238
3dcc1d0e 239class ifaceJsonDecoder():
240 @classmethod
241 def json_to_ifaceobj(cls, ifaceattrdict):
242 ifaceattrdict['config'] = OrderedDict([(k, (v if isinstance(v, list)
243 else [v]))
244 for k,v in ifaceattrdict.get('config',
245 OrderedDict()).items()])
246 return iface(attrsdict=ifaceattrdict)
247
a6f80f0e 248class iface():
904908bc 249 """ ifupdown2 iface object class
62ddec8b 250
251 Attributes:
904908bc
RP
252 **name** Name of the interface
253
254 **addr_family** Address family eg, inet, inet6. Can be None to
255 indicate both address families
256
257 **addr_method** Address method eg, static, manual or None for
258 static address method
259
260 **config** dictionary of config lines for this interface
261
262 **state** Configuration state of an interface as defined by
263 ifaceState
264
265 **status** Configuration status of an interface as defined by
266 ifaceStatus
267
268 **flags** Internal flags used by iface processing
269
270 **priv_flags** private flags owned by module using this class
271
4c773918
ST
272 **module_flags** module flags owned by module using this class
273
904908bc
RP
274 **refcnt** reference count, indicating number of interfaces
275 dependent on this iface
276
277 **lowerifaces** list of interface names lower to this interface or
278 this interface depends on
279
280 **upperifaces** list of interface names upper to this interface or
281 the interfaces that depend on this interface
282
283 **auto** True if interface belongs to the auto class
284
285 **classes** List of classes the interface belongs to
286
287 **env** shell environment the interface needs during
288 execution
289
290 **raw_config** raw interface config from file
62ddec8b 291 """
292
31a5f4c3 293 # flag to indicate that the object was created from pickled state
73c27592
RP
294 _PICKLED = 0x00000001
295 HAS_SIBLINGS = 0x00000010
296 IFACERANGE_ENTRY = 0x00000100
297 IFACERANGE_START = 0x00001000
a6f80f0e 298
37c0543d 299 version = '0.1'
300
3dcc1d0e 301 def __init__(self, attrsdict={}):
302 self._set_attrs_from_dict(attrsdict)
62ddec8b 303 self._config_status = {}
2c0ad8b3 304 """dict with config status of iface attributes"""
a6f80f0e 305 self.state = ifaceState.NEW
2c0ad8b3 306 """iface state (of type ifaceState) """
a6f80f0e 307 self.status = ifaceStatus.UNKNOWN
2c0ad8b3 308 """iface status (of type ifaceStatus) """
e1601369
RP
309 self.status_str = None
310 """iface status str (string representing the status) """
a6f80f0e 311 self.flags = 0x0
2c0ad8b3 312 """iface flags """
37c0543d 313 self.priv_flags = 0x0
4c773918
ST
314 """iface module flags dictionary with module name: flags"""
315 self.module_flags = {}
2c0ad8b3 316 """iface priv flags. can be used by the external object manager """
a6f80f0e 317 self.refcnt = 0
2c0ad8b3 318 """iface refcnt (incremented for each dependent this interface has) """
41febf89 319 self.lowerifaces = None
2c0ad8b3 320 """lower iface list (in other words: slaves of this interface """
f3215127 321 self.upperifaces = None
2c0ad8b3 322 """upper iface list (in other words: master of this interface """
a6f80f0e 323 self.classes = []
2c0ad8b3 324 """interface classes this iface belongs to """
a6f80f0e 325 self.env = None
2c0ad8b3 326 """environment variable dict required for this interface to run"""
62ddec8b 327 self.raw_config = []
2c0ad8b3 328 """interface config/attributes in raw format (eg: as it appeared in the interfaces file)"""
a6f80f0e 329 self.linkstate = None
2c0ad8b3 330 """linkstate of the interface"""
41febf89
RP
331 self.type = ifaceType.UNKNOWN
332 """interface type"""
333 self.priv_data = None
0a3bee28 334 self.role = ifaceRole.UNKNOWN
2da58137 335 self.realname = None
a070c90e 336 self.link_type = ifaceLinkType.LINK_UNKNOWN
c65c2ccd 337 self.link_kind = ifaceLinkKind.UNKNOWN
a6f80f0e 338
45ca0b6d
RP
339 # The below attribute is used to disambiguate between various
340 # types of dependencies
341 self.dependency_type = ifaceDependencyType.UNKNOWN
0532f0a3 342 self.blacklisted = False
45ca0b6d 343
3dcc1d0e 344 def _set_attrs_from_dict(self, attrdict):
345 self.auto = attrdict.get('auto', False)
346 self.name = attrdict.get('name')
347 self.addr_family = attrdict.get('addr_family')
348 self.addr_method = attrdict.get('addr_method')
349 self.config = attrdict.get('config', OrderedDict())
350
a6f80f0e 351 def inc_refcnt(self):
2c0ad8b3
RP
352 """ increment refcnt of the interface. Usually used to indicate that
353 it has dependents """
a6f80f0e 354 self.refcnt += 1
355
356 def dec_refcnt(self):
2c0ad8b3
RP
357 """ decrement refcnt of the interface. Usually used to indicate that
358 it has lost its dependent """
a6f80f0e 359 self.refcnt -= 1
360
cca03c30 361 def is_config_present(self):
2c0ad8b3
RP
362 """ returns true if the interface has user provided config,
363 false otherwise """
62ddec8b 364 addr_method = self.addr_method
2cd06f78 365 if addr_method and addr_method in ['dhcp', 'dhcp6', 'loopback']:
366 return True
fe0a57d3 367 if not self.config:
cca03c30 368 return False
fe0a57d3 369 else:
370 return True
cca03c30 371
3e8ee54f 372 def set_class(self, classname):
2c0ad8b3 373 """ appends class to the interfaces class list """
a6f80f0e 374 self.classes.append(classname)
375
31a5f4c3 376 def set_state_n_status(self, state, status):
2c0ad8b3 377 """ sets state and status of an interface """
31a5f4c3 378 self.state = state
379 self.status = status
380
a6f80f0e 381 def set_flag(self, flag):
382 self.flags |= flag
383
384 def clear_flag(self, flag):
385 self.flags &= ~flag
386
f3215127 387 def add_to_upperifaces(self, upperifacename):
2c0ad8b3 388 """ add to the list of upperifaces """
f3215127 389 if self.upperifaces:
390 if upperifacename not in self.upperifaces:
391 self.upperifaces.append(upperifacename)
392 else:
393 self.upperifaces = [upperifacename]
394
a6f80f0e 395 def get_attr_value(self, attr_name):
2c0ad8b3 396 """ add to the list of upperifaces """
62ddec8b 397 return self.config.get(attr_name)
a6f80f0e 398
399 def get_attr_value_first(self, attr_name):
2c0ad8b3 400 """ get first value of the specified attr name """
62ddec8b 401 attr_value_list = self.config.get(attr_name)
fe0a57d3 402 if attr_value_list:
a6f80f0e 403 return attr_value_list[0]
a6f80f0e 404 return None
405
679e6567
RP
406 def get_attrs_value_first(self, attrs):
407 """ get first value of the first attr in the list.
408 Useful when you have multiple attrs representing the
409 same thing.
410 """
411 for attr in attrs:
412 attr_value_list = self.config.get(attr)
413 if attr_value_list:
414 return attr_value_list[0]
415 return None
416
a6f80f0e 417 def get_attr_value_n(self, attr_name, attr_index):
2c0ad8b3 418 """ get n'th value of the specified attr name """
62ddec8b 419 attr_value_list = self.config.get(attr_name)
fe0a57d3 420 if attr_value_list:
a6f80f0e 421 try:
422 return attr_value_list[attr_index]
423 except:
424 return None
a6f80f0e 425 return None
426
62ddec8b 427 @property
a6f80f0e 428 def get_env(self):
2c0ad8b3 429 """ get shell environment variables the interface must execute in """
fe0a57d3 430 if not self.env:
a6f80f0e 431 self.generate_env()
432 return self.env
433
a6f80f0e 434 def generate_env(self):
2c0ad8b3
RP
435 """ generate shell environment variables dict interface must execute
436 in. This is used to support legacy ifupdown scripts
437 """
a6f80f0e 438 env = {}
62ddec8b 439 config = self.config
440 env['IFACE'] = self.name
a6f80f0e 441 for attr, attr_value in config.items():
442 attr_env_name = 'IF_%s' %attr.upper()
443 env[attr_env_name] = attr_value[0]
fe0a57d3 444 if env:
62ddec8b 445 self.env = env
a6f80f0e 446
739f665b 447 def update_config(self, attr_name, attr_value):
2c0ad8b3 448 """ add attribute name and value to the interface config """
62ddec8b 449 self.config.setdefault(attr_name, []).append(attr_value)
739f665b 450
d8e3554d
RP
451 def replace_config(self, attr_name, attr_value):
452 """ add attribute name and value to the interface config """
453 self.config[attr_name] = [attr_value]
454
455 def delete_config(self, attr_name):
456 """ add attribute name and value to the interface config """
457 try:
458 del self.config[attr_name]
459 except:
460 pass
461
739f665b 462 def update_config_dict(self, attrdict):
463 self.config.update(attrdict)
464
465 def update_config_with_status(self, attr_name, attr_value, attr_status=0):
2c0ad8b3
RP
466 """ add attribute name and value to the interface config and also
467 update the config_status dict with status of this attribute config """
69f58278 468 if not attr_value:
a6f80f0e 469 attr_value = ''
62ddec8b 470 self.config.setdefault(attr_name, []).append(attr_value)
471 self._config_status.setdefault(attr_name, []).append(attr_status)
69f58278 472 # set global iface state
e1601369 473 if attr_status == 1:
62ddec8b 474 self.status = ifaceStatus.ERROR
475 elif self.status != ifaceStatus.ERROR:
69f58278 476 # Not already error, mark success
62ddec8b 477 self.status = ifaceStatus.SUCCESS
69f58278 478
a070c90e 479 def check_n_update_config_with_status_many(self, ifaceobjorig, attr_names,
e1601369
RP
480 attr_status=0):
481 # set multiple attribute status to zero
482 # also updates status only if the attribute is present
483 for attr_name in attr_names:
a070c90e
RP
484 if not ifaceobjorig.get_attr_value_first(attr_name):
485 continue
e1601369
RP
486 self.config.setdefault(attr_name, []).append('')
487 self._config_status.setdefault(attr_name, []).append(attr_status)
488
69f58278 489 def get_config_attr_status(self, attr_name, idx=0):
2c0ad8b3
RP
490 """ get status of a attribute config on this interface.
491
492 Looks at the iface _config_status dict"""
62ddec8b 493 return self._config_status.get(attr_name, [])[idx]
69f58278 494
ca3f4fc7 495 def compare(self, dstiface):
2c0ad8b3 496 """ compares iface object with iface object passed as argument
ca3f4fc7 497
498 Returns True if object self is same as dstiface and False otherwise """
499
500 if self.name != dstiface.name: return False
84ca006f 501 if self.type != dstiface.type: return False
ca3f4fc7 502 if self.addr_family != dstiface.addr_family: return False
503 if self.addr_method != dstiface.addr_method: return False
504 if self.auto != dstiface.auto: return False
505 if self.classes != dstiface.classes: return False
acf92644
RP
506 if len(self.config) != len(dstiface.config):
507 return False
37c0543d 508 if any(True for k in self.config if k not in dstiface.config):
ca3f4fc7 509 return False
37c0543d 510 if any(True for k,v in self.config.items()
ca3f4fc7 511 if v != dstiface.config.get(k)): return False
512 return True
d08d5f54 513
e1601369 514
d08d5f54 515 def __getstate__(self):
516 odict = self.__dict__.copy()
517 del odict['state']
518 del odict['status']
f3215127 519 del odict['lowerifaces']
c798b0f4 520 del odict['upperifaces']
d08d5f54 521 del odict['refcnt']
62ddec8b 522 del odict['_config_status']
5c721925 523 del odict['flags']
524 del odict['priv_flags']
4c773918 525 del odict['module_flags']
62ddec8b 526 del odict['raw_config']
5c721925 527 del odict['linkstate']
528 del odict['env']
c416da6a 529 del odict['link_type']
a9ab1b4f 530 del odict['link_kind']
0a3bee28 531 del odict['role']
45ca0b6d 532 del odict['dependency_type']
0532f0a3 533 del odict['blacklisted']
d08d5f54 534 return odict
535
536 def __setstate__(self, dict):
537 self.__dict__.update(dict)
62ddec8b 538 self._config_status = {}
d08d5f54 539 self.state = ifaceState.NEW
540 self.status = ifaceStatus.UNKNOWN
541 self.refcnt = 0
5c721925 542 self.flags = 0
f3215127 543 self.lowerifaces = None
c798b0f4 544 self.upperifaces = None
d08d5f54 545 self.linkstate = None
5c721925 546 self.env = None
0a3bee28 547 self.role = ifaceRole.UNKNOWN
5c721925 548 self.priv_flags = 0
4c773918 549 self.module_flags = {}
62ddec8b 550 self.raw_config = []
551 self.flags |= self._PICKLED
f3b69969 552 self.link_type = ifaceLinkType.LINK_NA
a9ab1b4f 553 self.link_kind = ifaceLinkKind.UNKNOWN
45ca0b6d 554 self.dependency_type = ifaceDependencyType.UNKNOWN
0532f0a3 555 self.blacklisted = False
3dcc1d0e 556
a6f80f0e 557 def dump_raw(self, logger):
558 indent = ' '
53b00224 559 if self.auto:
560 print 'auto %s' %self.name
62ddec8b 561 print (self.raw_config[0])
562 for i in range(1, len(self.raw_config)):
53b00224 563 print(indent + self.raw_config[i])
a6f80f0e 564
a6f80f0e 565 def dump(self, logger):
566 indent = '\t'
62ddec8b 567 logger.info(self.name + ' : {')
568 logger.info(indent + 'family: %s' %self.addr_family)
569 logger.info(indent + 'method: %s' %self.addr_method)
31a5f4c3 570 logger.info(indent + 'flags: %x' %self.flags)
a6f80f0e 571 logger.info(indent + 'state: %s'
62ddec8b 572 %ifaceState.to_str(self.state))
a6f80f0e 573 logger.info(indent + 'status: %s'
62ddec8b 574 %ifaceStatus.to_str(self.status))
575 logger.info(indent + 'refcnt: %d' %self.refcnt)
576 d = self.lowerifaces
fe0a57d3 577 if d:
f3215127 578 logger.info(indent + 'lowerdevs: %s' %str(d))
a6f80f0e 579 else:
f3215127 580 logger.info(indent + 'lowerdevs: None')
739f665b 581
a6f80f0e 582 logger.info(indent + 'config: ')
62ddec8b 583 config = self.config
fe0a57d3 584 if config:
a6f80f0e 585 logger.info(indent + indent + str(config))
586 logger.info('}')
587
fb10449e 588 def dump_pretty(self, with_status=False, use_realname=False):
a6f80f0e 589 indent = '\t'
cca03c30 590 outbuf = ''
b48ff1a9
RP
591 if use_realname and self.realname:
592 name = '%s' %self.realname
2da58137 593 else:
b48ff1a9 594 name = '%s' %self.name
62ddec8b 595 if self.auto:
2da58137 596 outbuf += 'auto %s\n' %name
5b4d3044 597 ifaceline = ''
cb46a208 598 if self.type == ifaceType.BRIDGE_VLAN:
5b4d3044 599 ifaceline += 'vlan %s' %name
cb46a208 600 else:
5b4d3044 601 ifaceline += 'iface %s' %name
62ddec8b 602 if self.addr_family:
5b4d3044 603 ifaceline += ' %s' %self.addr_family
62ddec8b 604 if self.addr_method:
5b4d3044 605 ifaceline += ' %s' %self.addr_method
2cd06f78 606 if with_status:
5b4d3044 607 status_str = None
e1601369
RP
608 if (self.status == ifaceStatus.ERROR or
609 self.status == ifaceStatus.NOTFOUND):
610 if self.status_str:
5b4d3044 611 ifaceline += ' (%s)' %self.status_str
fb10449e 612 status_str = '[%s]' %ifaceStatusStrs.ERROR
86fc62e2 613 elif self.status == ifaceStatus.SUCCESS:
fb10449e 614 status_str = '[%s]' %ifaceStatusStrs.SUCCESS
5b4d3044
RP
615 if status_str:
616 outbuf += '{0:65} {1:>8}'.format(ifaceline, status_str) + '\n'
617 else:
618 outbuf += ifaceline + '\n'
2cd06f78 619 if self.status == ifaceStatus.NOTFOUND:
e1601369
RP
620 outbuf = (outbuf.encode('utf8')
621 if isinstance(outbuf, unicode) else outbuf)
2cd06f78 622 print outbuf + '\n'
623 return
5b4d3044
RP
624 else:
625 outbuf += ifaceline + '\n'
62ddec8b 626 config = self.config
fe0a57d3 627 if config:
eab25b7c 628 for cname, cvaluelist in config.items():
69f58278 629 idx = 0
eab25b7c 630 for cv in cvaluelist:
69f58278 631 if with_status:
86fc62e2 632 s = self.get_config_attr_status(cname, idx)
e1601369 633 if s == -1:
fb10449e 634 status_str = '[%s]' %ifaceStatusStrs.UNKNOWN
e1601369 635 elif s == 1:
fb10449e 636 status_str = '[%s]' %ifaceStatusStrs.ERROR
86fc62e2 637 elif s == 0:
fb10449e 638 status_str = '[%s]' %ifaceStatusStrs.SUCCESS
5b4d3044
RP
639 outbuf += (indent + '{0:55} {1:>10}'.format(
640 '%s %s' %(cname, cv), status_str)) + '\n'
69f58278 641 else:
642 outbuf += indent + '%s %s\n' %(cname, cv)
643 idx += 1
3dcc1d0e 644 if with_status:
645 outbuf = (outbuf.encode('utf8')
646 if isinstance(outbuf, unicode) else outbuf)
a6f80f0e 647 print outbuf