]> git.proxmox.com Git - mirror_ifupdown2.git/blobdiff - pkg/iface.py
execute 'up' on upper devices if ifup is called with --with-depends
[mirror_ifupdown2.git] / pkg / iface.py
index a9b217d0eb7340e8302c1ffae1552dc7e943504b..3ea64894eb4eed5162c5bccfedccacd3497f9770 100644 (file)
@@ -6,17 +6,19 @@
 # iface --
 #    interface object
 #
-
-import logging
+from collections import OrderedDict
+#from json import *
 import json
+import logging
 
-class ifaceFlags():
+tickmark = ' (' + u'\u2713'.encode('utf8') + ')'
+crossmark = ' (' + u'\u2717'.encode('utf8') + ')'
 
+class ifaceFlags():
     NONE = 0x1
     FOLLOW_DEPENDENTS = 0x2
 
 class ifaceStatus():
-
     """iface status """
     UNKNOWN = 0x1
     SUCCESS = 0x2
@@ -31,6 +33,8 @@ class ifaceStatus():
             return 'success'
         elif state == cls.ERROR:
             return 'error'
+        elif state == cls.NOTFOUND:
+            return 'notfound'
     
     @classmethod
     def from_str(cls, state_str):
@@ -53,6 +57,10 @@ class ifaceState():
     DOWN = 0x7
     POST_DOWN = 0x8
 
+    # Pseudo states
+    QUERY_CHECKCURR = 0x9
+    QUERY_RUNNING = 0xa
+
     @classmethod
     def to_str(cls, state):
         if state == cls.UNKNOWN:
@@ -67,8 +75,14 @@ class ifaceState():
             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):
@@ -84,36 +98,58 @@ class ifaceState():
             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:
+            for k, v in o.config.items():
+                if len(v) == 1:
+                    retconfig[k] = v[0]
+                else:
+                    retconfig[k] = v
+
+        return OrderedDict({'name' : o.name,
+                            'addr_method' : o.addr_method,
+                            'addr_family' : o.addr_family,
+                            'auto' : o.auto,
+                            'config' : retconfig})
 
 class iface():
-    """ config flags """
-    AUTO = 0x1
-    HOT_PLUG = 0x2
+    """ flags """
+    # flag to indicate that the object was created from pickled state
+    PICKLED = 0x1
+
+    version = '0.1'
 
-    
     def __init__(self):
         self.name = None
         self.addr_family = None
         self.addr_method = None
-        self.config = {}
-        self.children = []
+        self.config = OrderedDict()
+        self.config_status = {}
         self.state = ifaceState.NEW
         self.status = ifaceStatus.UNKNOWN
         self.flags = 0x0
+        self.priv_flags = 0x0
         self.refcnt = 0
-        self.dependents = None
+        self.lowerifaces = None
+        self.upperifaces = None
         self.auto = False
         self.classes = []
         self.env = None
-        self.config_current = {}
         self.raw_lines = []
         self.linkstate = None
 
     def inc_refcnt(self):
-        #print 'inside inc_refcnt = %d' %self.refcnt
         self.refcnt += 1
 
     def dec_refcnt(self):
@@ -149,11 +185,16 @@ class iface():
     def get_config(self):
         return self.config
 
-    def set_config_current(self, config_current):
-        self.config_current = config_current
-
-    def get_config_current(self):
-        return self.config_current
+    def is_config_present(self):
+        addr_method = self.get_addr_method()
+        if addr_method:
+            if (addr_method.find('dhcp') != -1 or
+                    addr_method.find('dhcp6') != -1):
+                return True
+        if not self.config:
+            return False
+        else:
+            return True
 
     def get_auto(self):
         return self.auto
@@ -178,11 +219,13 @@ class iface():
     def belongs_to_class(self, intfclass):
         if intfclass in self.classes:
             return True
-
         return False
 
-    def add_child(self, child_iface_obj):
-        self.children.append(child_iface_obj)
+    def set_priv_flags(self, priv_flags):
+        self.priv_flags = priv_flags
+
+    def get_priv_flags(self):
+        return self.priv_flags
 
     def get_state(self):
         return self.state
@@ -202,6 +245,10 @@ class iface():
     def set_status(self, status):
         self.status = status
 
+    def set_state_n_status(self, state, status):
+        self.state = state
+        self.status = status
+
     def state_str_to_hex(self, state_str):
         return self.state_str_map.get(state_str)
 
@@ -211,11 +258,24 @@ class iface():
     def clear_flag(self, flag):
         self.flags &= ~flag
 
-    def set_dependents(self, dlist):
-        self.dependents = dlist
+    def set_lowerifaces(self, dlist):
+        self.lowerifaces = dlist
 
-    def get_dependents(self):
-        return self.dependents
+    def get_lowerifaces(self):
+        return self.lowerifaces
+
+    def set_upperifaces(self, dlist):
+        self.upperifaces = dlist
+
+    def add_to_upperifaces(self, upperifacename):
+        if self.upperifaces:
+            if upperifacename not in self.upperifaces:
+                self.upperifaces.append(upperifacename)
+        else:
+            self.upperifaces = [upperifacename]
+
+    def get_upperifaces(self):
+        return self.upperifaces
 
     def set_linkstate(self, l):
         self.linkstate = l
@@ -230,27 +290,24 @@ class iface():
     
     def get_attr_value_first(self, attr_name):
         config = self.get_config()
-
         attr_value_list = config.get(attr_name)
-        if attr_value_list is not None:
+        if attr_value_list:
             return attr_value_list[0]
-
         return None
 
     def get_attr_value_n(self, attr_name, attr_index):
         config = self.get_config()
 
         attr_value_list = config.get(attr_name)
-        if attr_value_list is not None:
+        if attr_value_list:
             try:
                 return attr_value_list[attr_index]
             except:
                 return None
-
         return None
 
     def get_env(self):
-        if self.env is None or len(self.env) == 0:
+        if not self.env:
             self.generate_env()
         return self.env
 
@@ -265,33 +322,91 @@ class iface():
             attr_env_name = 'IF_%s' %attr.upper()
             env[attr_env_name] = attr_value[0]
 
-        if len(env) > 0:
+        if env:
             self.set_env(env)
 
-    def update_config(self, attr_name, attr_value, attr_status=0):
-        if attr_value is None:
+    def update_config(self, attr_name, attr_value):
+        if not self.config.get(attr_name):
+            self.config[attr_name] = [attr_value]
+        else:
+            self.config[attr_name].append(attr_value)
+
+    def update_config_dict(self, attrdict):
+        self.config.update(attrdict)
+
+    def update_config_with_status(self, attr_name, attr_value, attr_status=0):
+        if not attr_value:
             attr_value = ''
 
-        if attr_status != 0:
-            self.set_status(ifaceStatus.ERROR)
-        else:
-            if self.get_status() != ifaceStatus.ERROR:
-                self.set_status(ifaceStatus.SUCCESS)
-        if self.config.get(attr_name) is not None:
+        if self.config.get(attr_name):
             self.config[attr_name].append(attr_value)
+            self.config_status[attr_name].append(attr_status)
         else:
             self.config[attr_name] = [attr_value]
+            self.config_status[attr_name] = [attr_status]
+
+        # set global iface state
+        if attr_status:
+            self.set_status(ifaceStatus.ERROR)
+        elif self.get_status() != ifaceStatus.ERROR:
+            # Not already error, mark success
+            self.set_status(ifaceStatus.SUCCESS)
 
-        """ XXX: If status needs to be encoded in the query string
-        if attr_status == 0:
-            self.set_status(attr
-            attr_status_str = ''
-        elif attr_status == 0:
-            attr_status_str = ' (success)'
-        elif attr_status != 0:
-            attr_status_str = ' (error)'
-        self.config[attr_name] = attr_value + attr_status_str """
+    def get_config_attr_status(self, attr_name, idx=0):
+        self.config_status.get(attr_name, [])[idx]
 
+    def get_config_attr_status_str(self, attr_name, idx=0):
+        ret = self.config_status.get(attr_name, [])[idx]
+        if ret:
+            return crossmark
+        else:
+            return tickmark
+
+    def is_different(self, dstiface):
+        if self.name != dstiface.name: return True
+        if self.addr_family != dstiface.addr_family: return True
+        if self.addr_method != dstiface.addr_method: return True
+        if self.auto != dstiface.auto: return True
+        if self.classes != dstiface.classes: return True
+
+        if any(True for k in self.config if k not in dstiface.config):
+            return True
+
+        if any(True for k,v in self.config.items()
+                    if v != dstiface.config.get(k)): return True
+
+        return False
+
+    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['raw_lines']
+        del odict['linkstate']
+        del odict['env']
+        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.priv_flags = 0
+        self.raw_lines = []
+        self.flags |= self.PICKLED
+        
     def dump_raw(self, logger):
         indent = '  '
         print (self.raw_lines[0])
@@ -303,45 +418,48 @@ class iface():
         logger.info(self.get_name() + ' : {')
         logger.info(indent + 'family: %s' %self.get_addr_family())
         logger.info(indent + 'method: %s' %self.get_addr_method())
+        logger.info(indent + 'flags: %x' %self.flags)
         logger.info(indent + 'state: %s'
                 %ifaceState.to_str(self.get_state()))
         logger.info(indent + 'status: %s'
                 %ifaceStatus.to_str(self.get_status()))
         logger.info(indent + 'refcnt: %d' %self.get_refcnt())
-        d = self.get_dependents()
-        if d is not None:
-            logger.info(indent + 'dependents: %s' %str(d))
+        d = self.get_lowerifaces()
+        if d:
+            logger.info(indent + 'lowerdevs: %s' %str(d))
         else:
-            logger.info(indent + 'dependents: None')
+            logger.info(indent + 'lowerdevs: None')
 
         logger.info(indent + 'config: ')
         config = self.get_config()
-        if config is not None:
+        if config:
             logger.info(indent + indent + str(config))
         logger.info('}')
 
-    def dump_pretty(self, logger):
+    def dump_pretty(self, with_status=False):
         indent = '\t'
-        outbuf = 'iface %s' %self.get_name()
-        if self.get_addr_family() is not None:
+        outbuf = ''
+        if self.get_auto():
+            outbuf += 'auto %s\n' %self.get_name()
+        outbuf += 'iface %s' %self.get_name()
+        if self.get_addr_family():
             outbuf += ' %s' %self.get_addr_family()
-
-        if self.get_addr_method() is not None:
+        if self.get_addr_method():
             outbuf += ' %s' %self.get_addr_method()
-
         outbuf += '\n'
-
         config = self.get_config()
-        if config is not None:
+        if config:
             for cname, cvaluelist in config.items():
+                idx = 0
                 for cv in cvaluelist:
-                    outbuf += indent + '%s' %cname + ' %s\n' %cv
-
-        #outbuf += ('%s' %indent + '%s' %self.get_state_str() +
-        #                ' %s' %self.get_status_str())
+                    if with_status:
+                        outbuf += indent + '%s %s %s\n' %(cname, cv,
+                                    self.get_config_attr_status_str(cname, idx))
+                    else:
+                        outbuf += indent + '%s %s\n' %(cname, cv)
+                    idx += 1
 
         print outbuf
 
-
-    def dump_json(self, logger):
-        json.dumps(self)
+    def dump_json(self, with_status=False):
+        print json.dumps(self, cls=ifaceJsonEncoder, indent=4)