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