]>
Commit | Line | Data |
---|---|---|
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 | 12 | It is modeled based on the 'iface' section in /etc/network/interfaces |
62ddec8b | 13 | file. But can be extended to include any other network interface format |
62ddec8b | 14 | """ |
15 | ||
cca03c30 | 16 | from collections import OrderedDict |
d08d5f54 | 17 | import logging |
2cd06f78 | 18 | import json |
a6f80f0e | 19 | |
41febf89 | 20 | class ifaceType(): |
2da58137 RP |
21 | UNKNOWN = 0x0 |
22 | IFACE = 0x1 | |
23 | BRIDGE_VLAN = 0x2 | |
41febf89 | 24 | |
a9ab1b4f RP |
25 | class ifaceLinkKind(): |
26 | UNKNOWN = 0x0 | |
27 | BRIDGE = 0x1 | |
28 | BOND = 0x2 | |
29 | ||
c416da6a | 30 | class ifaceLinkType(): |
a070c90e | 31 | LINK_UNKNOWN = 0x0 |
c416da6a RP |
32 | LINK_SLAVE = 0x1 |
33 | LINK_MASTER = 0x2 | |
a070c90e | 34 | LINK_NA = 0x3 |
c416da6a | 35 | |
a6f80f0e | 36 | class ifaceStatus(): |
62ddec8b | 37 | """Enumerates iface status """ |
38 | ||
a6f80f0e | 39 | UNKNOWN = 0x1 |
40 | SUCCESS = 0x2 | |
41 | ERROR = 0x3 | |
10720a53 | 42 | NOTFOUND = 0x4 |
a6f80f0e | 43 | |
44 | @classmethod | |
45 | def to_str(cls, state): | |
46 | if state == cls.UNKNOWN: | |
47 | return 'unknown' | |
48 | elif state == cls.SUCCESS: | |
49 | return 'success' | |
50 | elif state == cls.ERROR: | |
51 | return 'error' | |
739f665b | 52 | elif state == cls.NOTFOUND: |
69f58278 | 53 | return 'notfound' |
a6f80f0e | 54 | |
55 | @classmethod | |
56 | def from_str(cls, state_str): | |
57 | if state_str == 'unknown': | |
58 | return cls.UNKNOWN | |
59 | elif state_str == 'success': | |
60 | return cls.SUCCESS | |
61 | elif state_str == 'error': | |
62 | return cls.ERROR | |
63 | ||
64 | class ifaceState(): | |
62ddec8b | 65 | """Enumerates iface state """ |
a6f80f0e | 66 | |
a6f80f0e | 67 | UNKNOWN = 0x1 |
68 | NEW = 0x2 | |
69 | PRE_UP = 0x3 | |
70 | UP = 0x4 | |
71 | POST_UP = 0x5 | |
72 | PRE_DOWN = 0x6 | |
73 | DOWN = 0x7 | |
74 | POST_DOWN = 0x8 | |
75 | ||
d08d5f54 | 76 | # Pseudo states |
77 | QUERY_CHECKCURR = 0x9 | |
78 | QUERY_RUNNING = 0xa | |
79 | ||
a6f80f0e | 80 | @classmethod |
81 | def to_str(cls, state): | |
82 | if state == cls.UNKNOWN: | |
83 | return 'unknown' | |
84 | elif state == cls.NEW: | |
85 | return 'new' | |
86 | elif state == cls.PRE_UP: | |
87 | return 'pre-up' | |
88 | elif state == cls.UP: | |
89 | return 'up' | |
90 | elif state == cls.POST_UP: | |
91 | return 'post-up' | |
92 | elif state == cls.PRE_DOWN: | |
93 | return 'pre-down' | |
d08d5f54 | 94 | elif state == cls.DOWN: |
95 | return 'down' | |
a6f80f0e | 96 | elif state == cls.POST_DOWN: |
97 | return 'post-down' | |
d08d5f54 | 98 | elif state == cls.QUERY_CHECKCURR: |
99 | return 'query-checkcurr' | |
100 | elif state == cls.QUERY_RUNNING: | |
101 | return 'query-running' | |
a6f80f0e | 102 | |
103 | @classmethod | |
104 | def from_str(cls, state_str): | |
105 | if state_str == 'unknown': | |
106 | return cls.UNKNOWN | |
107 | elif state_str == 'new': | |
108 | return cls.NEW | |
109 | elif state_str == 'pre-up': | |
110 | return cls.PRE_UP | |
111 | elif state_str == 'up': | |
112 | return cls.UP | |
113 | elif state_str == 'post-up': | |
114 | return cls.POST_UP | |
115 | elif state_str == 'pre-down': | |
116 | return cls.PRE_DOWN | |
d08d5f54 | 117 | elif state_str == 'down': |
118 | return cls.DOWN | |
a6f80f0e | 119 | elif state_str == 'post-down': |
120 | return cls.POST_DOWN | |
d08d5f54 | 121 | elif state_str == 'query-checkcurr': |
122 | return cls.QUERY_CHECKCURR | |
123 | elif state_str == 'query-running': | |
124 | return cls.QUERY_RUNNING | |
a6f80f0e | 125 | |
d08d5f54 | 126 | class ifaceJsonEncoder(json.JSONEncoder): |
127 | def default(self, o): | |
83c1f241 | 128 | retconfig = {} |
129 | if o.config: | |
3dcc1d0e | 130 | retconfig = dict((k, (v[0] if len(v) == 1 else v)) |
131 | for k,v in o.config.items()) | |
75730152 | 132 | return OrderedDict({'name' : o.name, |
133 | 'addr_method' : o.addr_method, | |
134 | 'addr_family' : o.addr_family, | |
135 | 'auto' : o.auto, | |
83c1f241 | 136 | 'config' : retconfig}) |
d08d5f54 | 137 | |
3dcc1d0e | 138 | class ifaceJsonDecoder(): |
139 | @classmethod | |
140 | def json_to_ifaceobj(cls, ifaceattrdict): | |
141 | ifaceattrdict['config'] = OrderedDict([(k, (v if isinstance(v, list) | |
142 | else [v])) | |
143 | for k,v in ifaceattrdict.get('config', | |
144 | OrderedDict()).items()]) | |
145 | return iface(attrsdict=ifaceattrdict) | |
146 | ||
a6f80f0e | 147 | class iface(): |
904908bc | 148 | """ ifupdown2 iface object class |
62ddec8b | 149 | |
150 | Attributes: | |
904908bc RP |
151 | **name** Name of the interface |
152 | ||
153 | **addr_family** Address family eg, inet, inet6. Can be None to | |
154 | indicate both address families | |
155 | ||
156 | **addr_method** Address method eg, static, manual or None for | |
157 | static address method | |
158 | ||
159 | **config** dictionary of config lines for this interface | |
160 | ||
161 | **state** Configuration state of an interface as defined by | |
162 | ifaceState | |
163 | ||
164 | **status** Configuration status of an interface as defined by | |
165 | ifaceStatus | |
166 | ||
167 | **flags** Internal flags used by iface processing | |
168 | ||
169 | **priv_flags** private flags owned by module using this class | |
170 | ||
171 | **refcnt** reference count, indicating number of interfaces | |
172 | dependent on this iface | |
173 | ||
174 | **lowerifaces** list of interface names lower to this interface or | |
175 | this interface depends on | |
176 | ||
177 | **upperifaces** list of interface names upper to this interface or | |
178 | the interfaces that depend on this interface | |
179 | ||
180 | **auto** True if interface belongs to the auto class | |
181 | ||
182 | **classes** List of classes the interface belongs to | |
183 | ||
184 | **env** shell environment the interface needs during | |
185 | execution | |
186 | ||
187 | **raw_config** raw interface config from file | |
62ddec8b | 188 | """ |
189 | ||
31a5f4c3 | 190 | # flag to indicate that the object was created from pickled state |
73c27592 RP |
191 | _PICKLED = 0x00000001 |
192 | HAS_SIBLINGS = 0x00000010 | |
193 | IFACERANGE_ENTRY = 0x00000100 | |
194 | IFACERANGE_START = 0x00001000 | |
a6f80f0e | 195 | |
37c0543d | 196 | version = '0.1' |
197 | ||
3dcc1d0e | 198 | def __init__(self, attrsdict={}): |
199 | self._set_attrs_from_dict(attrsdict) | |
62ddec8b | 200 | self._config_status = {} |
2c0ad8b3 | 201 | """dict with config status of iface attributes""" |
a6f80f0e | 202 | self.state = ifaceState.NEW |
2c0ad8b3 | 203 | """iface state (of type ifaceState) """ |
a6f80f0e | 204 | self.status = ifaceStatus.UNKNOWN |
2c0ad8b3 | 205 | """iface status (of type ifaceStatus) """ |
e1601369 RP |
206 | self.status_str = None |
207 | """iface status str (string representing the status) """ | |
a6f80f0e | 208 | self.flags = 0x0 |
2c0ad8b3 | 209 | """iface flags """ |
37c0543d | 210 | self.priv_flags = 0x0 |
2c0ad8b3 | 211 | """iface priv flags. can be used by the external object manager """ |
a6f80f0e | 212 | self.refcnt = 0 |
2c0ad8b3 | 213 | """iface refcnt (incremented for each dependent this interface has) """ |
41febf89 | 214 | self.lowerifaces = None |
2c0ad8b3 | 215 | """lower iface list (in other words: slaves of this interface """ |
f3215127 | 216 | self.upperifaces = None |
2c0ad8b3 | 217 | """upper iface list (in other words: master of this interface """ |
a6f80f0e | 218 | self.classes = [] |
2c0ad8b3 | 219 | """interface classes this iface belongs to """ |
a6f80f0e | 220 | self.env = None |
2c0ad8b3 | 221 | """environment variable dict required for this interface to run""" |
62ddec8b | 222 | self.raw_config = [] |
2c0ad8b3 | 223 | """interface config/attributes in raw format (eg: as it appeared in the interfaces file)""" |
a6f80f0e | 224 | self.linkstate = None |
2c0ad8b3 | 225 | """linkstate of the interface""" |
41febf89 RP |
226 | self.type = ifaceType.UNKNOWN |
227 | """interface type""" | |
228 | self.priv_data = None | |
2da58137 | 229 | self.realname = None |
a070c90e | 230 | self.link_type = ifaceLinkType.LINK_UNKNOWN |
a9ab1b4f | 231 | self.link_kind = ifaceLinkKind.BRIDGE |
a6f80f0e | 232 | |
3dcc1d0e | 233 | def _set_attrs_from_dict(self, attrdict): |
234 | self.auto = attrdict.get('auto', False) | |
235 | self.name = attrdict.get('name') | |
236 | self.addr_family = attrdict.get('addr_family') | |
237 | self.addr_method = attrdict.get('addr_method') | |
238 | self.config = attrdict.get('config', OrderedDict()) | |
239 | ||
a6f80f0e | 240 | def inc_refcnt(self): |
2c0ad8b3 RP |
241 | """ increment refcnt of the interface. Usually used to indicate that |
242 | it has dependents """ | |
a6f80f0e | 243 | self.refcnt += 1 |
244 | ||
245 | def dec_refcnt(self): | |
2c0ad8b3 RP |
246 | """ decrement refcnt of the interface. Usually used to indicate that |
247 | it has lost its dependent """ | |
a6f80f0e | 248 | self.refcnt -= 1 |
249 | ||
cca03c30 | 250 | def is_config_present(self): |
2c0ad8b3 RP |
251 | """ returns true if the interface has user provided config, |
252 | false otherwise """ | |
62ddec8b | 253 | addr_method = self.addr_method |
2cd06f78 | 254 | if addr_method and addr_method in ['dhcp', 'dhcp6', 'loopback']: |
255 | return True | |
fe0a57d3 | 256 | if not self.config: |
cca03c30 | 257 | return False |
fe0a57d3 | 258 | else: |
259 | return True | |
cca03c30 | 260 | |
3e8ee54f | 261 | def set_class(self, classname): |
2c0ad8b3 | 262 | """ appends class to the interfaces class list """ |
a6f80f0e | 263 | self.classes.append(classname) |
264 | ||
31a5f4c3 | 265 | def set_state_n_status(self, state, status): |
2c0ad8b3 | 266 | """ sets state and status of an interface """ |
31a5f4c3 | 267 | self.state = state |
268 | self.status = status | |
269 | ||
a6f80f0e | 270 | def set_flag(self, flag): |
271 | self.flags |= flag | |
272 | ||
273 | def clear_flag(self, flag): | |
274 | self.flags &= ~flag | |
275 | ||
f3215127 | 276 | def add_to_upperifaces(self, upperifacename): |
2c0ad8b3 | 277 | """ add to the list of upperifaces """ |
f3215127 | 278 | if self.upperifaces: |
279 | if upperifacename not in self.upperifaces: | |
280 | self.upperifaces.append(upperifacename) | |
281 | else: | |
282 | self.upperifaces = [upperifacename] | |
283 | ||
a6f80f0e | 284 | def get_attr_value(self, attr_name): |
2c0ad8b3 | 285 | """ add to the list of upperifaces """ |
62ddec8b | 286 | return self.config.get(attr_name) |
a6f80f0e | 287 | |
288 | def get_attr_value_first(self, attr_name): | |
2c0ad8b3 | 289 | """ get first value of the specified attr name """ |
62ddec8b | 290 | attr_value_list = self.config.get(attr_name) |
fe0a57d3 | 291 | if attr_value_list: |
a6f80f0e | 292 | return attr_value_list[0] |
a6f80f0e | 293 | return None |
294 | ||
679e6567 RP |
295 | def get_attrs_value_first(self, attrs): |
296 | """ get first value of the first attr in the list. | |
297 | Useful when you have multiple attrs representing the | |
298 | same thing. | |
299 | """ | |
300 | for attr in attrs: | |
301 | attr_value_list = self.config.get(attr) | |
302 | if attr_value_list: | |
303 | return attr_value_list[0] | |
304 | return None | |
305 | ||
a6f80f0e | 306 | def get_attr_value_n(self, attr_name, attr_index): |
2c0ad8b3 | 307 | """ get n'th value of the specified attr name """ |
62ddec8b | 308 | attr_value_list = self.config.get(attr_name) |
fe0a57d3 | 309 | if attr_value_list: |
a6f80f0e | 310 | try: |
311 | return attr_value_list[attr_index] | |
312 | except: | |
313 | return None | |
a6f80f0e | 314 | return None |
315 | ||
62ddec8b | 316 | @property |
a6f80f0e | 317 | def get_env(self): |
2c0ad8b3 | 318 | """ get shell environment variables the interface must execute in """ |
fe0a57d3 | 319 | if not self.env: |
a6f80f0e | 320 | self.generate_env() |
321 | return self.env | |
322 | ||
a6f80f0e | 323 | def generate_env(self): |
2c0ad8b3 RP |
324 | """ generate shell environment variables dict interface must execute |
325 | in. This is used to support legacy ifupdown scripts | |
326 | """ | |
a6f80f0e | 327 | env = {} |
62ddec8b | 328 | config = self.config |
329 | env['IFACE'] = self.name | |
a6f80f0e | 330 | for attr, attr_value in config.items(): |
331 | attr_env_name = 'IF_%s' %attr.upper() | |
332 | env[attr_env_name] = attr_value[0] | |
fe0a57d3 | 333 | if env: |
62ddec8b | 334 | self.env = env |
a6f80f0e | 335 | |
739f665b | 336 | def update_config(self, attr_name, attr_value): |
2c0ad8b3 | 337 | """ add attribute name and value to the interface config """ |
62ddec8b | 338 | self.config.setdefault(attr_name, []).append(attr_value) |
739f665b | 339 | |
d8e3554d RP |
340 | def replace_config(self, attr_name, attr_value): |
341 | """ add attribute name and value to the interface config """ | |
342 | self.config[attr_name] = [attr_value] | |
343 | ||
344 | def delete_config(self, attr_name): | |
345 | """ add attribute name and value to the interface config """ | |
346 | try: | |
347 | del self.config[attr_name] | |
348 | except: | |
349 | pass | |
350 | ||
739f665b | 351 | def update_config_dict(self, attrdict): |
352 | self.config.update(attrdict) | |
353 | ||
354 | def update_config_with_status(self, attr_name, attr_value, attr_status=0): | |
2c0ad8b3 RP |
355 | """ add attribute name and value to the interface config and also |
356 | update the config_status dict with status of this attribute config """ | |
69f58278 | 357 | if not attr_value: |
a6f80f0e | 358 | attr_value = '' |
62ddec8b | 359 | self.config.setdefault(attr_name, []).append(attr_value) |
360 | self._config_status.setdefault(attr_name, []).append(attr_status) | |
69f58278 | 361 | # set global iface state |
e1601369 | 362 | if attr_status == 1: |
62ddec8b | 363 | self.status = ifaceStatus.ERROR |
364 | elif self.status != ifaceStatus.ERROR: | |
69f58278 | 365 | # Not already error, mark success |
62ddec8b | 366 | self.status = ifaceStatus.SUCCESS |
69f58278 | 367 | |
a070c90e | 368 | def check_n_update_config_with_status_many(self, ifaceobjorig, attr_names, |
e1601369 RP |
369 | attr_status=0): |
370 | # set multiple attribute status to zero | |
371 | # also updates status only if the attribute is present | |
372 | for attr_name in attr_names: | |
a070c90e RP |
373 | if not ifaceobjorig.get_attr_value_first(attr_name): |
374 | continue | |
e1601369 RP |
375 | self.config.setdefault(attr_name, []).append('') |
376 | self._config_status.setdefault(attr_name, []).append(attr_status) | |
377 | ||
69f58278 | 378 | def get_config_attr_status(self, attr_name, idx=0): |
2c0ad8b3 RP |
379 | """ get status of a attribute config on this interface. |
380 | ||
381 | Looks at the iface _config_status dict""" | |
62ddec8b | 382 | return self._config_status.get(attr_name, [])[idx] |
69f58278 | 383 | |
ca3f4fc7 | 384 | def compare(self, dstiface): |
2c0ad8b3 | 385 | """ compares iface object with iface object passed as argument |
ca3f4fc7 | 386 | |
387 | Returns True if object self is same as dstiface and False otherwise """ | |
388 | ||
389 | if self.name != dstiface.name: return False | |
84ca006f | 390 | if self.type != dstiface.type: return False |
ca3f4fc7 | 391 | if self.addr_family != dstiface.addr_family: return False |
392 | if self.addr_method != dstiface.addr_method: return False | |
393 | if self.auto != dstiface.auto: return False | |
394 | if self.classes != dstiface.classes: return False | |
37c0543d | 395 | if any(True for k in self.config if k not in dstiface.config): |
ca3f4fc7 | 396 | return False |
37c0543d | 397 | if any(True for k,v in self.config.items() |
ca3f4fc7 | 398 | if v != dstiface.config.get(k)): return False |
399 | return True | |
d08d5f54 | 400 | |
e1601369 | 401 | |
d08d5f54 | 402 | def __getstate__(self): |
403 | odict = self.__dict__.copy() | |
404 | del odict['state'] | |
405 | del odict['status'] | |
f3215127 | 406 | del odict['lowerifaces'] |
c798b0f4 | 407 | del odict['upperifaces'] |
d08d5f54 | 408 | del odict['refcnt'] |
62ddec8b | 409 | del odict['_config_status'] |
5c721925 | 410 | del odict['flags'] |
411 | del odict['priv_flags'] | |
62ddec8b | 412 | del odict['raw_config'] |
5c721925 | 413 | del odict['linkstate'] |
414 | del odict['env'] | |
c416da6a | 415 | del odict['link_type'] |
a9ab1b4f | 416 | del odict['link_kind'] |
d08d5f54 | 417 | return odict |
418 | ||
419 | def __setstate__(self, dict): | |
420 | self.__dict__.update(dict) | |
62ddec8b | 421 | self._config_status = {} |
d08d5f54 | 422 | self.state = ifaceState.NEW |
423 | self.status = ifaceStatus.UNKNOWN | |
424 | self.refcnt = 0 | |
5c721925 | 425 | self.flags = 0 |
f3215127 | 426 | self.lowerifaces = None |
c798b0f4 | 427 | self.upperifaces = None |
d08d5f54 | 428 | self.linkstate = None |
5c721925 | 429 | self.env = None |
430 | self.priv_flags = 0 | |
62ddec8b | 431 | self.raw_config = [] |
432 | self.flags |= self._PICKLED | |
f3b69969 | 433 | self.link_type = ifaceLinkType.LINK_NA |
a9ab1b4f | 434 | self.link_kind = ifaceLinkKind.UNKNOWN |
3dcc1d0e | 435 | |
a6f80f0e | 436 | def dump_raw(self, logger): |
437 | indent = ' ' | |
53b00224 | 438 | if self.auto: |
439 | print 'auto %s' %self.name | |
62ddec8b | 440 | print (self.raw_config[0]) |
441 | for i in range(1, len(self.raw_config)): | |
53b00224 | 442 | print(indent + self.raw_config[i]) |
a6f80f0e | 443 | |
a6f80f0e | 444 | def dump(self, logger): |
445 | indent = '\t' | |
62ddec8b | 446 | logger.info(self.name + ' : {') |
447 | logger.info(indent + 'family: %s' %self.addr_family) | |
448 | logger.info(indent + 'method: %s' %self.addr_method) | |
31a5f4c3 | 449 | logger.info(indent + 'flags: %x' %self.flags) |
a6f80f0e | 450 | logger.info(indent + 'state: %s' |
62ddec8b | 451 | %ifaceState.to_str(self.state)) |
a6f80f0e | 452 | logger.info(indent + 'status: %s' |
62ddec8b | 453 | %ifaceStatus.to_str(self.status)) |
454 | logger.info(indent + 'refcnt: %d' %self.refcnt) | |
455 | d = self.lowerifaces | |
fe0a57d3 | 456 | if d: |
f3215127 | 457 | logger.info(indent + 'lowerdevs: %s' %str(d)) |
a6f80f0e | 458 | else: |
f3215127 | 459 | logger.info(indent + 'lowerdevs: None') |
739f665b | 460 | |
a6f80f0e | 461 | logger.info(indent + 'config: ') |
62ddec8b | 462 | config = self.config |
fe0a57d3 | 463 | if config: |
a6f80f0e | 464 | logger.info(indent + indent + str(config)) |
465 | logger.info('}') | |
466 | ||
86fc62e2 | 467 | def dump_pretty(self, with_status=False, |
2da58137 | 468 | successstr='success', errorstr='error', |
fac4138b | 469 | unknownstr='unknown', use_realname=False): |
a6f80f0e | 470 | indent = '\t' |
cca03c30 | 471 | outbuf = '' |
b48ff1a9 RP |
472 | if use_realname and self.realname: |
473 | name = '%s' %self.realname | |
2da58137 | 474 | else: |
b48ff1a9 | 475 | name = '%s' %self.name |
62ddec8b | 476 | if self.auto: |
2da58137 | 477 | outbuf += 'auto %s\n' %name |
5b4d3044 | 478 | ifaceline = '' |
cb46a208 | 479 | if self.type == ifaceType.BRIDGE_VLAN: |
5b4d3044 | 480 | ifaceline += 'vlan %s' %name |
cb46a208 | 481 | else: |
5b4d3044 | 482 | ifaceline += 'iface %s' %name |
62ddec8b | 483 | if self.addr_family: |
5b4d3044 | 484 | ifaceline += ' %s' %self.addr_family |
62ddec8b | 485 | if self.addr_method: |
5b4d3044 | 486 | ifaceline += ' %s' %self.addr_method |
2cd06f78 | 487 | if with_status: |
5b4d3044 | 488 | status_str = None |
e1601369 RP |
489 | if (self.status == ifaceStatus.ERROR or |
490 | self.status == ifaceStatus.NOTFOUND): | |
491 | if self.status_str: | |
5b4d3044 RP |
492 | ifaceline += ' (%s)' %self.status_str |
493 | status_str = errorstr | |
86fc62e2 | 494 | elif self.status == ifaceStatus.SUCCESS: |
5b4d3044 RP |
495 | status_str = successstr |
496 | if status_str: | |
497 | outbuf += '{0:65} {1:>8}'.format(ifaceline, status_str) + '\n' | |
498 | else: | |
499 | outbuf += ifaceline + '\n' | |
2cd06f78 | 500 | if self.status == ifaceStatus.NOTFOUND: |
e1601369 RP |
501 | outbuf = (outbuf.encode('utf8') |
502 | if isinstance(outbuf, unicode) else outbuf) | |
2cd06f78 | 503 | print outbuf + '\n' |
504 | return | |
5b4d3044 RP |
505 | else: |
506 | outbuf += ifaceline + '\n' | |
62ddec8b | 507 | config = self.config |
fe0a57d3 | 508 | if config: |
eab25b7c | 509 | for cname, cvaluelist in config.items(): |
69f58278 | 510 | idx = 0 |
eab25b7c | 511 | for cv in cvaluelist: |
69f58278 | 512 | if with_status: |
86fc62e2 | 513 | s = self.get_config_attr_status(cname, idx) |
e1601369 | 514 | if s == -1: |
5b4d3044 | 515 | status_str = unknownstr |
e1601369 | 516 | elif s == 1: |
5b4d3044 | 517 | status_str = errorstr |
86fc62e2 | 518 | elif s == 0: |
5b4d3044 RP |
519 | status_str = successstr |
520 | outbuf += (indent + '{0:55} {1:>10}'.format( | |
521 | '%s %s' %(cname, cv), status_str)) + '\n' | |
69f58278 | 522 | else: |
523 | outbuf += indent + '%s %s\n' %(cname, cv) | |
524 | idx += 1 | |
3dcc1d0e | 525 | if with_status: |
526 | outbuf = (outbuf.encode('utf8') | |
527 | if isinstance(outbuf, unicode) else outbuf) | |
a6f80f0e | 528 | print outbuf |