mirror of
				https://github.com/CumulusNetworks/ifupdown2.git
				synced 2024-05-06 15:54:50 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			594 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			594 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/python
 | |
| #
 | |
| # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
 | |
| # Author: Roopa Prabhu, roopa@cumulusnetworks.com
 | |
| #
 | |
| # iface --
 | |
| #    interface object
 | |
| #
 | |
| 
 | |
| """ifupdown2 network interface object
 | |
| 
 | |
| It is modeled based on the 'iface' section in /etc/network/interfaces
 | |
| file. But can be extended to include any other network interface format
 | |
| """
 | |
| 
 | |
| from collections import OrderedDict
 | |
| import logging
 | |
| import json
 | |
| 
 | |
| class ifaceType():
 | |
|     UNKNOWN = 0x0
 | |
|     IFACE = 0x1
 | |
|     BRIDGE_VLAN = 0x2
 | |
| 
 | |
| 
 | |
| class ifaceRole():
 | |
|     """ ifaceRole is used to classify the ifaceobj.role of
 | |
|         MASTER or SLAVE where there is a bond or bridge
 | |
|         with bond-slaves or bridge-ports.  A bond in a bridge
 | |
|         is both a master and slave (0x3)
 | |
|     """
 | |
|     UNKNOWN = 0x0
 | |
|     SLAVE = 0x1
 | |
|     MASTER = 0x2
 | |
| 
 | |
| class ifaceLinkKind():
 | |
|     """ ifaceLlinkKind is used to identify interfaces
 | |
|         in the ifaceobj.link_kind attribute. Dependents of the bridge or
 | |
|         bond have an ifaceobj.role attribute of SLAVE and the bridge or
 | |
|         bond itself has ifaceobj.role of MASTER.
 | |
|     """
 | |
|     UNKNOWN = 0x0
 | |
|     BRIDGE = 0x1
 | |
|     BOND = 0x2
 | |
|     VLAN = 0x4
 | |
|     VXLAN = 0x8
 | |
| 
 | |
| class ifaceLinkType():
 | |
|     LINK_UNKNOWN = 0x0
 | |
|     LINK_SLAVE = 0x1
 | |
|     LINK_MASTER = 0x2
 | |
|     LINK_NA = 0x3
 | |
| 
 | |
| class ifaceDependencyType():
 | |
|     """ Indicates type of dependency.
 | |
| 
 | |
|         This class enumerates types of dependency relationships
 | |
|         between interfaces.
 | |
| 
 | |
|         iface dependency relationships can be classified
 | |
|         into:
 | |
|          - link
 | |
|          - master/slave
 | |
| 
 | |
|         In a 'link' dependency relationship, dependency can be shared
 | |
|         between interfaces. example: swp1.100 and
 | |
|         swp1.200 can both have 'link' swp1. swp1 is also a dependency
 | |
|         of swp1.100 and swp1.200. As you can see dependency
 | |
|         swp1 is shared between swp1.100 and swp1.200.
 | |
|          
 | |
|         In a master/slave relationship like bridge and
 | |
|         its ports: eg: bridge br0 and its ports swp1 and swp2.
 | |
|         dependency swp1 and swp2 cannot be shared with any other
 | |
|         interface with the same dependency relationship.
 | |
|         ie, swp1 and swp2 cannot be in a slave relationship
 | |
|         with another interface. Understanding the dependency type is
 | |
|         required for any semantic checks between dependencies.
 | |
| 
 | |
|     """
 | |
|     UNKNOWN = 0x0
 | |
|     LINK = 0x1
 | |
|     MASTER_SLAVE = 0x2
 | |
| 
 | |
| class ifaceStatus():
 | |
|     """Enumerates iface status """
 | |
| 
 | |
|     UNKNOWN = 0x1
 | |
|     SUCCESS = 0x2
 | |
|     ERROR = 0x3
 | |
|     NOTFOUND = 0x4
 | |
| 
 | |
|     @classmethod
 | |
|     def to_str(cls, state):
 | |
|         if state == cls.UNKNOWN:
 | |
|             return 'unknown'
 | |
|         elif state == cls.SUCCESS:
 | |
|             return 'success'
 | |
|         elif state == cls.ERROR:
 | |
|             return 'error'
 | |
|         elif state == cls.NOTFOUND:
 | |
|             return 'notfound'
 | |
|     
 | |
|     @classmethod
 | |
|     def from_str(cls, state_str):
 | |
|         if state_str == 'unknown':
 | |
|             return cls.UNKNOWN
 | |
|         elif state_str == 'success':
 | |
|             return cls.SUCCESS
 | |
|         elif state_str == 'error':
 | |
|             return cls.ERROR
 | |
| 
 | |
| class ifaceState():
 | |
|     """Enumerates iface state """
 | |
| 
 | |
|     UNKNOWN = 0x1
 | |
|     NEW = 0x2
 | |
|     PRE_UP = 0x3
 | |
|     UP = 0x4
 | |
|     POST_UP = 0x5
 | |
|     PRE_DOWN = 0x6
 | |
|     DOWN = 0x7
 | |
|     POST_DOWN = 0x8
 | |
| 
 | |
|     # Pseudo states
 | |
|     QUERY_CHECKCURR = 0x9
 | |
|     QUERY_RUNNING = 0xa
 | |
| 
 | |
|     @classmethod
 | |
|     def to_str(cls, state):
 | |
|         if state == cls.UNKNOWN:
 | |
|             return 'unknown'
 | |
|         elif state == cls.NEW:
 | |
|             return 'new'
 | |
|         elif state == cls.PRE_UP:
 | |
|             return 'pre-up'
 | |
|         elif state == cls.UP:
 | |
|             return 'up'
 | |
|         elif state == cls.POST_UP:
 | |
|             return 'post-up'
 | |
|         elif state == cls.PRE_DOWN:
 | |
|             return 'pre-down'
 | |
|         elif state == cls.DOWN:
 | |
|             return 'down'
 | |
|         elif state == cls.POST_DOWN:
 | |
|             return 'post-down'
 | |
|         elif state == cls.QUERY_CHECKCURR:
 | |
|             return 'query-checkcurr'
 | |
|         elif state == cls.QUERY_RUNNING:
 | |
|             return 'query-running'
 | |
| 
 | |
|     @classmethod
 | |
|     def from_str(cls, state_str):
 | |
|         if state_str == 'unknown':
 | |
|             return cls.UNKNOWN
 | |
|         elif state_str == 'new':
 | |
|             return cls.NEW
 | |
|         elif state_str == 'pre-up':
 | |
|             return cls.PRE_UP
 | |
|         elif state_str == 'up':
 | |
|             return cls.UP
 | |
|         elif state_str == 'post-up':
 | |
|             return cls.POST_UP
 | |
|         elif state_str == 'pre-down':
 | |
|             return cls.PRE_DOWN
 | |
|         elif state_str == 'down':
 | |
|             return cls.DOWN
 | |
|         elif state_str == 'post-down':
 | |
|             return cls.POST_DOWN
 | |
|         elif state_str == 'query-checkcurr':
 | |
|             return cls.QUERY_CHECKCURR
 | |
|         elif state_str == 'query-running':
 | |
|             return cls.QUERY_RUNNING
 | |
| 
 | |
| class ifaceJsonEncoder(json.JSONEncoder):
 | |
|     def default(self, o):
 | |
|         retconfig = {}
 | |
|         if o.config:
 | |
|             retconfig = dict((k, (v[0] if len(v) == 1 else v))
 | |
|                              for k,v in o.config.items())
 | |
|         return OrderedDict({'name' : o.name,
 | |
|                             'addr_method' : o.addr_method,
 | |
|                             'addr_family' : o.addr_family,
 | |
|                             'auto' : o.auto,
 | |
|                             'config' : retconfig})
 | |
| 
 | |
| class ifaceJsonDecoder():
 | |
|     @classmethod
 | |
|     def json_to_ifaceobj(cls, ifaceattrdict):
 | |
|         ifaceattrdict['config'] = OrderedDict([(k, (v if isinstance(v, list)
 | |
|                                                 else [v]))
 | |
|                                 for k,v in ifaceattrdict.get('config',
 | |
|                                             OrderedDict()).items()])
 | |
|         return iface(attrsdict=ifaceattrdict)
 | |
| 
 | |
| class iface():
 | |
|     """ ifupdown2 iface object class
 | |
|     
 | |
|     Attributes:
 | |
|         **name**      Name of the interface 
 | |
| 
 | |
|         **addr_family**     Address family eg, inet, inet6. Can be None to
 | |
|                             indicate both address families
 | |
| 
 | |
|         **addr_method**     Address method eg, static, manual or None for
 | |
|                             static address method
 | |
| 
 | |
|         **config**          dictionary of config lines for this interface
 | |
| 
 | |
|         **state**           Configuration state of an interface as defined by
 | |
|                             ifaceState
 | |
| 
 | |
|         **status**          Configuration status of an interface as defined by
 | |
|                             ifaceStatus
 | |
| 
 | |
|         **flags**           Internal flags used by iface processing
 | |
| 
 | |
|         **priv_flags**      private flags owned by module using this class
 | |
| 
 | |
|         **module_flags**    module flags owned by module using this class
 | |
| 
 | |
|         **refcnt**          reference count, indicating number of interfaces
 | |
|                             dependent on this iface
 | |
| 
 | |
|         **lowerifaces**     list of interface names lower to this interface or
 | |
|                             this interface depends on
 | |
| 
 | |
|         **upperifaces**     list of interface names upper to this interface or
 | |
|                             the interfaces that depend on this interface 
 | |
| 
 | |
|         **auto**            True if interface belongs to the auto class
 | |
| 
 | |
|         **classes**         List of classes the interface belongs to
 | |
| 
 | |
|         **env**             shell environment the interface needs during
 | |
|                             execution
 | |
| 
 | |
|         **raw_config**      raw interface config from file
 | |
|     """
 | |
| 
 | |
|     # flag to indicate that the object was created from pickled state
 | |
|     _PICKLED = 0x00000001
 | |
|     HAS_SIBLINGS = 0x00000010
 | |
|     IFACERANGE_ENTRY = 0x00000100
 | |
|     IFACERANGE_START = 0x00001000
 | |
| 
 | |
|     version = '0.1'
 | |
| 
 | |
|     def __init__(self, attrsdict={}):
 | |
|         self._set_attrs_from_dict(attrsdict)
 | |
|         self._config_status = {}
 | |
|         """dict with config status of iface attributes"""
 | |
|         self.state = ifaceState.NEW
 | |
|         """iface state (of type ifaceState) """
 | |
|         self.status = ifaceStatus.UNKNOWN
 | |
|         """iface status (of type ifaceStatus) """
 | |
|         self.status_str = None
 | |
|         """iface status str (string representing the status) """
 | |
|         self.flags = 0x0
 | |
|         """iface flags """
 | |
|         self.priv_flags = 0x0
 | |
|         """iface module flags dictionary with module name: flags"""
 | |
|         self.module_flags = {}
 | |
|         """iface priv flags. can be used by the external object manager """
 | |
|         self.refcnt = 0
 | |
|         """iface refcnt (incremented for each dependent this interface has) """
 | |
|         self.lowerifaces = None 
 | |
|         """lower iface list (in other words: slaves of this interface """
 | |
|         self.upperifaces = None
 | |
|         """upper iface list (in other words: master of this interface """
 | |
|         self.classes = []
 | |
|         """interface classes this iface belongs to """
 | |
|         self.env = None
 | |
|         """environment variable dict required for this interface to run"""
 | |
|         self.raw_config = []
 | |
|         """interface config/attributes in raw format (eg: as it appeared in the interfaces file)"""
 | |
|         self.linkstate = None
 | |
|         """linkstate of the interface"""
 | |
|         self.type = ifaceType.UNKNOWN
 | |
|         """interface type"""
 | |
|         self.priv_data = None
 | |
|         self.role = ifaceRole.UNKNOWN
 | |
|         self.realname = None
 | |
|         self.link_type = ifaceLinkType.LINK_UNKNOWN
 | |
|         self.link_kind = ifaceLinkKind.UNKNOWN
 | |
| 
 | |
|         # The below attribute is used to disambiguate between various
 | |
|         # types of dependencies
 | |
|         self.dependency_type = ifaceDependencyType.UNKNOWN
 | |
| 
 | |
|     def _set_attrs_from_dict(self, attrdict):
 | |
|         self.auto = attrdict.get('auto', False)
 | |
|         self.name = attrdict.get('name')
 | |
|         self.addr_family = attrdict.get('addr_family')
 | |
|         self.addr_method = attrdict.get('addr_method')
 | |
|         self.config = attrdict.get('config', OrderedDict())
 | |
| 
 | |
|     def inc_refcnt(self):
 | |
|         """ increment refcnt of the interface. Usually used to indicate that
 | |
|         it has dependents """
 | |
|         self.refcnt += 1
 | |
| 
 | |
|     def dec_refcnt(self):
 | |
|         """ decrement refcnt of the interface. Usually used to indicate that
 | |
|         it has lost its dependent """
 | |
|         self.refcnt -= 1
 | |
| 
 | |
|     def is_config_present(self):
 | |
|         """ returns true if the interface has user provided config,
 | |
|         false otherwise """
 | |
|         addr_method = self.addr_method
 | |
|         if addr_method and addr_method in ['dhcp', 'dhcp6', 'loopback']:
 | |
|             return True
 | |
|         if not self.config:
 | |
|             return False
 | |
|         else:
 | |
|             return True
 | |
| 
 | |
|     def set_class(self, classname):
 | |
|         """ appends class to the interfaces class list """
 | |
|         self.classes.append(classname)
 | |
| 
 | |
|     def set_state_n_status(self, state, status):
 | |
|         """ sets state and status of an interface """
 | |
|         self.state = state
 | |
|         self.status = status
 | |
| 
 | |
|     def set_flag(self, flag):
 | |
|         self.flags |= flag
 | |
| 
 | |
|     def clear_flag(self, flag):
 | |
|         self.flags &= ~flag
 | |
| 
 | |
|     def add_to_upperifaces(self, upperifacename):
 | |
|         """ add to the list of upperifaces """
 | |
|         if self.upperifaces:
 | |
|             if upperifacename not in self.upperifaces:
 | |
|                 self.upperifaces.append(upperifacename)
 | |
|         else:
 | |
|             self.upperifaces = [upperifacename]
 | |
| 
 | |
|     def get_attr_value(self, attr_name):
 | |
|         """ add to the list of upperifaces """
 | |
|         return self.config.get(attr_name)
 | |
|     
 | |
|     def get_attr_value_first(self, attr_name):
 | |
|         """ get first value of the specified attr name """
 | |
|         attr_value_list = self.config.get(attr_name)
 | |
|         if attr_value_list:
 | |
|             return attr_value_list[0]
 | |
|         return None
 | |
| 
 | |
|     def get_attrs_value_first(self, attrs):
 | |
|         """ get first value of the first attr in the list.
 | |
|             Useful when you have multiple attrs representing the
 | |
|             same thing.
 | |
|         """
 | |
|         for attr in attrs:
 | |
|             attr_value_list = self.config.get(attr)
 | |
|             if attr_value_list:
 | |
|                 return attr_value_list[0]
 | |
|         return None
 | |
| 
 | |
|     def get_attr_value_n(self, attr_name, attr_index):
 | |
|         """ get n'th value of the specified attr name """
 | |
|         attr_value_list = self.config.get(attr_name)
 | |
|         if attr_value_list:
 | |
|             try:
 | |
|                 return attr_value_list[attr_index]
 | |
|             except:
 | |
|                 return None
 | |
|         return None
 | |
| 
 | |
|     @property
 | |
|     def get_env(self):
 | |
|         """ get shell environment variables the interface must execute in """
 | |
|         if not self.env:
 | |
|             self.generate_env()
 | |
|         return self.env
 | |
| 
 | |
|     def generate_env(self):
 | |
|         """ generate shell environment variables dict interface must execute
 | |
|         in. This is used to support legacy ifupdown scripts
 | |
|         """
 | |
|         env = {}
 | |
|         config = self.config
 | |
|         env['IFACE'] = self.name
 | |
|         for attr, attr_value in config.items():
 | |
|             attr_env_name = 'IF_%s' %attr.upper()
 | |
|             env[attr_env_name] = attr_value[0]
 | |
|         if env:
 | |
|             self.env = env
 | |
| 
 | |
|     def update_config(self, attr_name, attr_value):
 | |
|         """ add attribute name and value to the interface config """
 | |
|         self.config.setdefault(attr_name, []).append(attr_value)
 | |
| 
 | |
|     def replace_config(self, attr_name, attr_value):
 | |
|         """ add attribute name and value to the interface config """
 | |
|         self.config[attr_name] = [attr_value]
 | |
| 
 | |
|     def delete_config(self, attr_name):
 | |
|         """ add attribute name and value to the interface config """
 | |
|         try:
 | |
|             del self.config[attr_name]
 | |
|         except:
 | |
|             pass
 | |
| 
 | |
|     def update_config_dict(self, attrdict):
 | |
|         self.config.update(attrdict)
 | |
| 
 | |
|     def update_config_with_status(self, attr_name, attr_value, attr_status=0):
 | |
|         """ add attribute name and value to the interface config and also
 | |
|         update the config_status dict with status of this attribute config """
 | |
|         if not attr_value:
 | |
|             attr_value = ''
 | |
|         self.config.setdefault(attr_name, []).append(attr_value)
 | |
|         self._config_status.setdefault(attr_name, []).append(attr_status)
 | |
|         # set global iface state
 | |
|         if attr_status == 1:
 | |
|             self.status = ifaceStatus.ERROR
 | |
|         elif self.status != ifaceStatus.ERROR:
 | |
|             # Not already error, mark success
 | |
|             self.status = ifaceStatus.SUCCESS
 | |
| 
 | |
|     def check_n_update_config_with_status_many(self, ifaceobjorig, attr_names,
 | |
|                                                attr_status=0):
 | |
|         # set multiple attribute status to zero
 | |
|         # also updates status only if the attribute is present
 | |
|         for attr_name in attr_names:
 | |
|             if not ifaceobjorig.get_attr_value_first(attr_name):
 | |
|                continue
 | |
|             self.config.setdefault(attr_name, []).append('')
 | |
|             self._config_status.setdefault(attr_name, []).append(attr_status)
 | |
| 
 | |
|     def get_config_attr_status(self, attr_name, idx=0):
 | |
|         """ get status of a attribute config on this interface.
 | |
|         
 | |
|         Looks at the iface _config_status dict"""
 | |
|         return self._config_status.get(attr_name, [])[idx]
 | |
| 
 | |
|     def compare(self, dstiface):
 | |
|         """ compares iface object with iface object passed as argument
 | |
| 
 | |
|         Returns True if object self is same as dstiface and False otherwise """
 | |
| 
 | |
|         if self.name != dstiface.name: return False
 | |
|         if self.type != dstiface.type: return False
 | |
|         if self.addr_family != dstiface.addr_family: return False
 | |
|         if self.addr_method != dstiface.addr_method: return False
 | |
|         if self.auto != dstiface.auto: return False
 | |
|         if self.classes != dstiface.classes: return False
 | |
|         if len(self.config) != len(dstiface.config):
 | |
|             return False
 | |
|         if any(True for k in self.config if k not in dstiface.config):
 | |
|             return False
 | |
|         if any(True for k,v in self.config.items()
 | |
|                     if v != dstiface.config.get(k)): return False
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def __getstate__(self):
 | |
|         odict = self.__dict__.copy()
 | |
|         del odict['state']
 | |
|         del odict['status']
 | |
|         del odict['lowerifaces']
 | |
|         del odict['upperifaces']
 | |
|         del odict['refcnt']
 | |
|         del odict['_config_status']
 | |
|         del odict['flags']
 | |
|         del odict['priv_flags']
 | |
|         del odict['module_flags']
 | |
|         del odict['raw_config']
 | |
|         del odict['linkstate']
 | |
|         del odict['env']
 | |
|         del odict['link_type']
 | |
|         del odict['link_kind']
 | |
|         del odict['role']
 | |
|         del odict['dependency_type']
 | |
|         return odict
 | |
| 
 | |
|     def __setstate__(self, dict):
 | |
|         self.__dict__.update(dict)
 | |
|         self._config_status = {}
 | |
|         self.state = ifaceState.NEW
 | |
|         self.status = ifaceStatus.UNKNOWN
 | |
|         self.refcnt = 0
 | |
|         self.flags = 0
 | |
|         self.lowerifaces = None
 | |
|         self.upperifaces = None
 | |
|         self.linkstate = None
 | |
|         self.env = None
 | |
|         self.role = ifaceRole.UNKNOWN
 | |
|         self.priv_flags = 0
 | |
|         self.module_flags = {}
 | |
|         self.raw_config = []
 | |
|         self.flags |= self._PICKLED
 | |
|         self.link_type = ifaceLinkType.LINK_NA
 | |
|         self.link_kind = ifaceLinkKind.UNKNOWN
 | |
|         self.dependency_type = ifaceDependencyType.UNKNOWN
 | |
| 
 | |
|     def dump_raw(self, logger):
 | |
|         indent = '  '
 | |
|         if self.auto:
 | |
|             print ('auto %s' %self.name)
 | |
|         print (self.raw_config[0])
 | |
|         for i in range(1, len(self.raw_config)):
 | |
|             print(indent + self.raw_config[i])
 | |
|         
 | |
|     def dump(self, logger):
 | |
|         indent = '\t'
 | |
|         logger.info(self.name + ' : {')
 | |
|         logger.info(indent + 'family: %s' %self.addr_family)
 | |
|         logger.info(indent + 'method: %s' %self.addr_method)
 | |
|         logger.info(indent + 'flags: %x' %self.flags)
 | |
|         logger.info(indent + 'state: %s'
 | |
|                 %ifaceState.to_str(self.state))
 | |
|         logger.info(indent + 'status: %s'
 | |
|                 %ifaceStatus.to_str(self.status))
 | |
|         logger.info(indent + 'refcnt: %d' %self.refcnt)
 | |
|         d = self.lowerifaces
 | |
|         if d:
 | |
|             logger.info(indent + 'lowerdevs: %s' %str(d))
 | |
|         else:
 | |
|             logger.info(indent + 'lowerdevs: None')
 | |
| 
 | |
|         logger.info(indent + 'config: ')
 | |
|         config = self.config
 | |
|         if config:
 | |
|             logger.info(indent + indent + str(config))
 | |
|         logger.info('}')
 | |
| 
 | |
|     def dump_pretty(self, with_status=False,
 | |
|                     successstr='success', errorstr='error',
 | |
|                     unknownstr='unknown', use_realname=False):
 | |
|         indent = '\t'
 | |
|         outbuf = ''
 | |
|         if use_realname and self.realname:
 | |
|             name = '%s' %self.realname
 | |
|         else:
 | |
|             name = '%s' %self.name
 | |
|         if self.auto:
 | |
|             outbuf += 'auto %s\n' %name
 | |
|         ifaceline = ''
 | |
|         if self.type == ifaceType.BRIDGE_VLAN:
 | |
|             ifaceline += 'vlan %s' %name
 | |
|         else:
 | |
|             ifaceline += 'iface %s' %name
 | |
|         if self.addr_family:
 | |
|             ifaceline += ' %s' %self.addr_family
 | |
|         if self.addr_method:
 | |
|             ifaceline += ' %s' %self.addr_method
 | |
|         if with_status:
 | |
|             status_str = None
 | |
|             if (self.status == ifaceStatus.ERROR or
 | |
|                     self.status == ifaceStatus.NOTFOUND):
 | |
|                 if self.status_str:
 | |
|                     ifaceline += ' (%s)' %self.status_str
 | |
|                 status_str = errorstr
 | |
|             elif self.status == ifaceStatus.SUCCESS:
 | |
|                 status_str = successstr
 | |
|             if status_str:
 | |
|                outbuf += '{0:65} {1:>8}'.format(ifaceline, status_str) + '\n'
 | |
|             else:
 | |
|                 outbuf += ifaceline + '\n'
 | |
|             if self.status == ifaceStatus.NOTFOUND:
 | |
|                 outbuf = (outbuf.encode('utf8')
 | |
|                     if isinstance(outbuf, unicode) else outbuf)
 | |
|                 print (outbuf + '\n')
 | |
|                 return
 | |
|         else:
 | |
|             outbuf += ifaceline + '\n'
 | |
|         config = self.config
 | |
|         if config:
 | |
|             for cname, cvaluelist in config.items():
 | |
|                 idx = 0
 | |
|                 for cv in cvaluelist:
 | |
|                     if with_status:
 | |
|                         s = self.get_config_attr_status(cname, idx)
 | |
|                         if s == -1:
 | |
|                             status_str = unknownstr
 | |
|                         elif s == 1:
 | |
|                             status_str = errorstr
 | |
|                         elif s == 0:
 | |
|                             status_str = successstr
 | |
|                         outbuf += (indent + '{0:55} {1:>10}'.format(
 | |
|                                    '%s %s' %(cname, cv), status_str)) + '\n'
 | |
|                     else:
 | |
|                         outbuf += indent + '%s %s\n' %(cname, cv)
 | |
|                     idx += 1
 | |
|         if with_status:
 | |
|             outbuf = (outbuf.encode('utf8')
 | |
|                         if isinstance(outbuf, unicode) else outbuf)
 | |
|         print (outbuf)
 |