]> git.proxmox.com Git - mirror_ifupdown2.git/blobdiff - pkg/ifupdownmain.py
prefix ethtool attributes with "link-" to be compatible with
[mirror_ifupdown2.git] / pkg / ifupdownmain.py
index 1a8084c5b0328010fbdd4604a5f6b2685f048edd..67c1d81b705921eefd67ac0b060c9c0f948fdb61 100644 (file)
@@ -13,6 +13,8 @@ import imp
 import pprint
 import logging
 import sys, traceback
+import copy
+import json
 from statemanager import *
 from networkinterfaces import *
 from iface import *
@@ -22,371 +24,485 @@ from collections import OrderedDict
 from graph import *
 from sets import Set
 
-class ifupdownMain():
+_tickmark = u'\u2713'
+_crossmark = u'\u2717'
+_success_sym = _tickmark
+_error_sym = _crossmark
+
+class ifupdownMain(ifupdownBase):
+    """ ifupdown2 main class """
 
     # Flags
-    NODEPENDS = False
+    WITH_DEPENDS = False
     ALL = False
-    STATE_CHECK = False
+    COMPAT_EXEC_SCRIPTS = False
+    STATEMANAGER_ENABLE = True
+    STATEMANAGER_UPDATE = True
+    ADDONS_ENABLE = False
+
+    # priv flags to mark iface objects
+    BUILTIN = 0x1
+    NOCONFIG = 0x2
 
-    modules_dir='/etc/network'
-    builtin_modules_dir='/usr/share/ifupdownaddons'
+    scripts_dir='/etc/network'
+    addon_modules_dir='/usr/share/ifupdownaddons'
+    addon_modules_configfile='/var/lib/ifupdownaddons/addons.conf'
 
     # iface dictionary in the below format:
     # { '<ifacename>' : [<ifaceobject1>, <ifaceobject2> ..] }
     # eg:
-    # { 'swp1' : [<ifaceobject1>, <ifaceobject2> ..] }
+    # { 'swp1' : [<iface swp1>, <iface swp2> ..] }
     #
     # Each ifaceobject corresponds to a configuration block for
     # that interface
+    # The value in the dictionary is a list because the network
+    # interface configuration file supports more than one iface section
+    # in the interfaces file
     ifaceobjdict = OrderedDict()
 
-
     # iface dictionary representing the curr running state of an iface
     # in the below format:
     # {'<ifacename>' : <ifaceobject>}
     ifaceobjcurrdict = OrderedDict()
 
-    # Dictionary representing operation, sub operation and modules
-    # for every sub operation
-    operations = { 'up' :
-                    OrderedDict([('pre-up', OrderedDict({})),
-                                 ('up' , OrderedDict({})),
-                                 ('post-up' , OrderedDict({}))]),
-                   'down' :
-                    OrderedDict([('pre-down', OrderedDict({})),
-                                 ('down' , OrderedDict({})),
-                                 ('post-down' , OrderedDict({}))])}
-
-
-    def __init__(self, force=False, dryrun=False, nowait=False,
-                 perfmode=False, nodepends=False, njobs=1):
+    # Dictionary representing operation and modules
+    # for every operation
+    module_ops = OrderedDict([('pre-up', []),
+                              ('up' , []),
+                              ('post-up' , []),
+                              ('query-checkcurr', []),
+                              ('query-running', []),
+                              ('query-dependency', []),
+                              ('query', []),
+                              ('query-raw', []),
+                              ('pre-down', []),
+                              ('down' , []),
+                              ('post-down' , [])])
+
+    # For old style /etc/network/ bash scripts
+    script_ops = OrderedDict([('pre-up', []),
+                                    ('up' , []),
+                                    ('post-up' , []),
+                                    ('pre-down', []),
+                                    ('down' , []),
+                                    ('post-down' , [])])
+
+    # Handlers for ops that ifupdown2 owns
+    def run_up(self, ifaceobj):
+        ifacename = ifaceobj.name
+        if self.link_exists(ifacename):
+            self.link_up(ifacename)
+
+    def run_down(self, ifaceobj):
+        ifacename = ifaceobj.name
+        if self.link_exists(ifacename):
+            self.link_down(ifacename)
+
+    # ifupdown object interface operation handlers
+    ops_handlers = OrderedDict([('up', run_up),
+                                ('down', run_down)])
+
+    def run_sched_ifaceobj_posthook(self, ifaceobj, op):
+        if ((ifaceobj.priv_flags & self.BUILTIN) or
+            (ifaceobj.priv_flags & self.NOCONFIG)):
+            return
+        if self.STATEMANAGER_UPDATE:
+            self.statemanager.ifaceobj_sync(ifaceobj, op)
+
+    # ifupdown object interface scheduler pre and posthooks
+    sched_hooks = {'posthook' : run_sched_ifaceobj_posthook}
+
+    def __init__(self, config={},
+                 force=False, dryrun=False, nowait=False,
+                 perfmode=False, withdepends=False, njobs=1,
+                 cache=False, addons_enable=True, statemanager_enable=True,
+                 interfacesfile='/etc/network/interfaces',
+                 interfacesfileiobuf=None,
+                 interfacesfileformat='native'):
         self.logger = logging.getLogger('ifupdown')
-
         self.FORCE = force
         self.DRYRUN = dryrun
         self.NOWAIT = nowait
         self.PERFMODE = perfmode
-        self.NODEPENDS = nodepends
+        self.WITH_DEPENDS = withdepends
+        self.STATEMANAGER_ENABLE = statemanager_enable
+        self.CACHE = cache
+        self.interfacesfile = interfacesfile
+        self.interfacesfileiobuf = interfacesfileiobuf
+        self.interfacesfileformat = interfacesfileformat
+        self.config = config
+        self.logger.debug(self.config)
+
+        # Can be used to provide hints for caching
+        self.CACHE_FLAGS = 0x0
+        self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
+        self.ADDONS_ENABLE = addons_enable
 
         self.ifaces = OrderedDict()
         self.njobs = njobs
         self.pp = pprint.PrettyPrinter(indent=4)
-        self.load_modules_builtin(self.builtin_modules_dir)
-        self.load_modules(self.modules_dir)
-
-        try:
-            self.statemanager = stateManager()
-            self.statemanager.read_saved_state()
-        except Exception, e:
-            # XXX Maybe we should continue by ignoring old state
-            self.logger.warning('error reading state (%s)' %str(e))
-            raise
-
-    def get_subops(self, op):
-        """ Returns sub-operation list """
-        return self.operations.get(op).keys()
+        self.modules = OrderedDict({})
+        self.module_attrs = {}
+        
+        self.load_addon_modules(self.addon_modules_dir)
+        if self.COMPAT_EXEC_SCRIPTS:
+            self.load_scripts(self.scripts_dir)
+        self.dependency_graph = OrderedDict({})
 
-    def compat_conv_op_to_mode(self, op):
-        """ Returns old op name to work with existing scripts """
-        if op == 'up':
-            return 'start'
-        elif op == 'down':
-            return 'stop'
+        if self.STATEMANAGER_ENABLE:
+            try:
+                self.statemanager = stateManager()
+                self.statemanager.read_saved_state()
+            except Exception, e:
+                # XXX Maybe we should continue by ignoring old state
+                self.logger.warning('error reading state (%s)' %str(e))
+                raise
         else:
-            return op
-
-    def set_force(self, force):
-        """ Set force flag. """
-        if force == True:
-            self.logger.debug('setting force to true')
-        self.FORCE = force
-
-    def get_force(self):
-        """ return force flag. """
-        return self.FORCE
-
-    def set_dryrun(self, dryrun):
-        if dryrun == True:
-            self.logger.debug('setting dryrun to true')
-        self.DRYRUN = dryrun
-
-    def get_dryrun(self):
-        return self.DRYRUN
-
-    def set_perfmode(self, perfmode):
-        if perfmode == True:
-            self.logger.debug('setting perfmode to true')
-        self.PERFMODE = perfmode
-
-    def get_perfmode(self):
-        return self.PERFMODE
-
-    def set_nowait(self, nowait):
-        if nowait == True:
-            self.logger.debug('setting dryrun to true')
-        self.NOWAIT = nowait
-
-    def get_nowait(self):
-        return self.NOWAIT
+            self.STATEMANAGER_UPDATE = False
 
-    def set_njobs(self, njobs):
-        self.logger.debug('setting njobs to %d' %njobs)
-        self.njobs = njobs
-
-    def get_njobs(self):
-        return self.njobs
-
-    def get_nodepends(self):
-        return self.NODEPENDS
-
-    def set_nodepends(self, nodepends):
-        self.logger.debug('setting nodepends to true')
-        self.NODEPENDS = nodepends
-
-    def set_iface_state(self, ifaceobj, state, status):
-        ifaceobj.set_state(state)
-        ifaceobj.set_status(status)
-        self.statemanager.update_iface_state(ifaceobj)
-
-    def get_iface_objs(self, ifacename):
+    def get_ifaceobjs(self, ifacename):
         return self.ifaceobjdict.get(ifacename)
 
-    def get_iface_obj_first(self, ifacename):
-        ifaceobjs = self.get_iface_objs(ifacename)
-        if ifaceobjs is not None:
+    def get_ifaceobj_first(self, ifacename):
+        ifaceobjs = self.get_ifaceobjs(ifacename)
+        if ifaceobjs:
             return ifaceobjs[0]
         return None
 
+    def get_ifacenames(self):
+        return self.ifaceobjdict.keys()
+
     def get_iface_obj_last(self, ifacename):
         return self.ifaceobjdict.get(ifacename)[-1]
 
-    def create_ifaceobjcurr(self, ifacename):
-        ifaceobj = self.get_ifaceobjcurr(ifacename)
-        if ifaceobj is not None:
-            return ifaceobj
-
+    def create_n_save_ifaceobj(self, ifacename, priv_flags=None,
+                               increfcnt=False):
+        """ creates a iface object and adds it to the iface dictionary """
         ifaceobj = iface()
-        ifaceobj.set_name(ifacename)
-        self.ifaceobjcurrdict[ifacename] = ifaceobj
-
+        ifaceobj.name = ifacename
+        ifaceobj.priv_flags = priv_flags
+        ifaceobj.auto = True
+        if increfcnt:
+            ifaceobj.inc_refcnt()
+        self.ifaceobjdict[ifacename] = [ifaceobj]
         return ifaceobj
 
-    def get_ifaceobjcurr(self, ifacename):
-        return self.ifaceobjcurrdict.get(ifacename)
-
-    def get_iface_status(self, ifacename):
-        ifaceobjs = self.get_iface_objs(ifacename)
-        for i in ifaceobjs:
-            if i.get_status() != ifaceStatus.SUCCESS:
-                return i.get_status()
+    def create_n_save_ifaceobjcurr(self, ifaceobj):
+        """ creates a copy of iface object and adds it to the iface
+            dict containing current iface objects 
+        """
+        ifaceobjcurr = iface()
+        ifaceobjcurr.name = ifaceobj.name
+        ifaceobjcurr.lowerifaces = ifaceobj.lowerifaces
+        ifaceobjcurr.priv_flags = ifaceobj.priv_flags
+        ifaceobjcurr.auto = ifaceobj.auto
+        self.ifaceobjcurrdict.setdefault(ifaceobj.name,
+                                     []).append(ifaceobjcurr)
+        return ifaceobjcurr
+
+    def get_ifaceobjcurr(self, ifacename, idx=0):
+        ifaceobjlist = self.ifaceobjcurrdict.get(ifacename)
+        if not ifaceobjlist:
+            return None
+        if not idx:
+            return ifaceobjlist
+        else:
+            return ifaceobjlist[idx]
 
-        return ifaceStatus.SUCCESS
+    def get_ifaceobjrunning(self, ifacename):
+        return self.ifaceobjrunningdict.get(ifacename)
 
     def get_iface_refcnt(self, ifacename):
+        """ Return iface ref count """
         max = 0
-        ifaceobjs = self.get_iface_objs(ifacename)
+        ifaceobjs = self.get_ifaceobjs(ifacename)
+        if not ifaceobjs:
+            return 0
         for i in ifaceobjs:
-            if i.get_refcnt() > max:
-                max = i.get_refcnt()
+            if i.refcnt > max:
+                max = i.refcnt
         return max
 
-    def create_fake_vlan_iface(self, vlan_ifname, op):
-        """ creates and returns a fake vlan iface object.
-
-        This was added to support creation of simple vlan devices without any
-        user specified configuration.
-
+    def is_iface_builtin_byname(self, ifacename):
+        """ Returns true if iface name is a builtin interface.
+        
+        A builtin interface is an interface which ifupdown understands.
+        The following are currently considered builtin ifaces:
+            - vlan interfaces in the format <ifacename>.<vlanid>
         """
+        return '.' in ifacename
 
-        # XXX: Ideally this should be a call-back into the vlan module.
-        vlan_iface_obj = iface()
-        vlan_iface_obj.set_name(vlan_ifname)
-
-        return vlan_iface_obj
-
-    def is_vlan_device(self, ifacename):
-        """ Returns true if iface name is a vlan interface.
-        
-        only supports vlan interfaces of the format <ifacename>.<vlanid>
+    def is_ifaceobj_builtin(self, ifaceobj):
+        """ Returns true if iface name is a builtin interface.
         
+        A builtin interface is an interface which ifupdown understands.
+        The following are currently considered builtin ifaces:
+            - vlan interfaces in the format <ifacename>.<vlanid>
         """
-        if (re.search(r'\.', ifacename, 0) is not None):
-            return True
-        return False
+        return (ifaceobj.priv_flags & self.BUILTIN)
 
-    def preprocess_dependency_list(self, dlist, op):
+    def is_ifaceobj_noconfig(self, ifaceobj):
+        """ Returns true if iface object did not have a user defined config.
+       
+        These interfaces appear only when they are dependents of interfaces
+        which have user defined config
+        """
+        return (ifaceobj.priv_flags & self.NOCONFIG)
+
+    def is_iface_noconfig(self, ifacename):
+        """ Returns true if iface has no config """
+
+        ifaceobj = self.get_ifaceobj_first(ifacename)
+        if not ifaceobj: return True
+        return self.is_ifaceobj_noconfig(ifaceobj)
+
+    def preprocess_dependency_list(self, upperifacename, dlist, ops):
+        """ We go through the dependency list and
+            delete or add interfaces from the interfaces dict by
+            applying the following rules:
+                if flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is True:
+                    we only consider devices whose configuration was
+                    specified in the network interfaces file. We delete
+                    any interface whose config was not specified except
+                    for vlan devices. vlan devices get special treatment.
+                    Even if they are not present they are created and added
+                    to the ifacesdict
+                elif flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is False:
+                    we create objects for all dependent devices that are not
+                    present in the ifacesdict
+        """
         del_list = []
 
-        self.logger.debug('pre-processing dependency list: %s' %list(dlist))
         for d in dlist:
-            dilist = self.get_iface_objs(d)
-            if dilist == None:
-                if self.is_vlan_device(d) == True:
-                    vlan_iface_obj = self.create_fake_vlan_iface(d, op)
-
-                    # Add face vlan device to ifaceobjdict dict
-                    vlan_iface_obj.inc_refcnt()
-                    self.save_iface(vlan_iface_obj)
+            dilist = self.get_ifaceobjs(d)
+            if not dilist:
+                if self.is_iface_builtin_byname(d):
+                    self.create_n_save_ifaceobj(d, self.BUILTIN | self.NOCONFIG,
+                            True).add_to_upperifaces(upperifacename)
+                elif not self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG:
+                    self.create_n_save_ifaceobj(d, self.NOCONFIG,
+                            True).add_to_upperifaces(upperifacename)
                 else:
-                    # Remove the device from the list
                     del_list.append(d)
             else:
                 for di in dilist:
                     di.inc_refcnt()
+                    di.add_to_upperifaces(upperifacename)
 
         for d in del_list:
             dlist.remove(d)
 
-        self.logger.debug('After Processing dependency list: %s'
-            %list(dlist))
-
-
-    def get_dependents(self, ifaceobj, op):
+    def query_dependents(self, ifaceobj, ops):
         """ Gets iface dependents by calling into respective modules """
         dlist = None
 
-        self.logger.debug('%s: ' %ifaceobj.get_name() + 'getting dependency')
-
         # Get dependents for interface by querying respective modules
-        subopdict = self.operations.get(op)
-        for subop, mdict in subopdict.items():
-            for mname, mdata  in mdict.items():
-                if mdata.get('ftype') == 'pmodule':
-                    module = mdata.get('module')
-                    if (hasattr(module,
-                        'get_dependent_ifacenames') == False):
+        for mname, module in self.modules.items():
+            module = self.modules.get(mname)
+            try:
+                if ops[0] == 'query-running':
+                    if (not hasattr(module,
+                        'get_dependent_ifacenames_running')):
+                        continue
+                    dlist = module.get_dependent_ifacenames_running(ifaceobj)
+                else:
+                    if (not hasattr(module, 'get_dependent_ifacenames')):
                         continue
                     dlist = module.get_dependent_ifacenames(ifaceobj,
-                                    self.ifaceobjdict.keys())
-                    if dlist is not None:
-                        self.logger.debug('%s: ' %ifaceobj.get_name() +
-                                'got dependency list: %s' %str(dlist))
-                        break
-
+                                        self.ifaceobjdict.keys())
+            except Exception, e:
+                self.logger.warn('%s: error getting dependent interfaces (%s)'
+                        %(ifaceobj.name, str(e)))
+                dlist = None
+                pass
+            if dlist:
+                break
         return dlist
 
-    def generate_dependency_info(self, ifacenames, dependency_graph, op):
+    def populate_dependency_info(self, ops, ifacenames=None):
         """ recursive function to generate iface dependency info """
 
-        self.logger.debug('generating dependency info for %s' %str(ifacenames))
+        if not ifacenames:
+            ifacenames = self.ifaceobjdict.keys()
 
         iqueue = deque(ifacenames)
         while iqueue:
             i = iqueue.popleft()
-
             # Go through all modules and find dependent ifaces
             dlist = None
-            ifaceobj = self.get_iface_obj_first(i)
-            if ifaceobj is None
+            ifaceobj = self.get_ifaceobj_first(i)
+            if not ifaceobj
                 continue
-
-            dlist = ifaceobj.get_dependents()
-            if dlist is None:
-                dlist = self.get_dependents(ifaceobj, op)
+            dlist = ifaceobj.lowerifaces
+            if not dlist:
+                dlist = self.query_dependents(ifaceobj, ops)
             else:
                 continue
+            if dlist:
+                self.preprocess_dependency_list(ifaceobj.name,
+                                                dlist, ops)
+                ifaceobj.lowerifaces = dlist
+                [iqueue.append(d) for d in dlist]
+            if not self.dependency_graph.get(i):
+                self.dependency_graph[i] = dlist
+
+    def _save_iface(self, ifaceobj):
+        currentifaceobjlist = self.ifaceobjdict.get(ifaceobj.name)
+        if not currentifaceobjlist:
+           self.ifaceobjdict[ifaceobj.name]= [ifaceobj]
+           return
+        if ifaceobj.compare(currentifaceobjlist[0]):
+            self.logger.warn('duplicate interface %s found' %ifaceobj.name)
+            return
+        currentifaceobjlist[0].flags |= iface.HAS_SIBLINGS
+        ifaceobj.flags |= iface.HAS_SIBLINGS
+        self.ifaceobjdict[ifaceobj.name].append(ifaceobj)
 
-            if dlist is not None:
-                self.preprocess_dependency_list(dlist, op)
-                ifaceobj.set_dependents(dlist)
-                for d in dlist:
-                    iqueue.append(d)
-
-            if dependency_graph.get(i) is None:
-                dependency_graph[i] = dlist
-
-    def is_valid_state_transition(self, ifname, to_be_state):
-        return self.statemanager.is_valid_state_transition(ifname,
-                to_be_state)
+    def _iface_configattr_syntax_checker(self, attrname, attrval):
+        for m, mdict in self.module_attrs.items():
+            if not mdict:
+                continue
+            attrsdict = mdict.get('attrs')
+            try:
+                if attrsdict.get(attrname):
+                    return True
+            except AttributeError:
+                pass
+        return False
 
-    def save_iface(self, ifaceobj):
-        if self.ifaceobjdict.get(ifaceobj.get_name()) is None:
-            self.ifaceobjdict[ifaceobj.get_name()] = [ifaceobj]
-        else:
-            self.ifaceobjdict[ifaceobj.get_name()].append(ifaceobj)
+    def _ifaceobj_syntax_checker(self, ifaceobj):
+        err = False
+        for attrname in ifaceobj.config:
+            found = False
+            for k, v in self.module_attrs.items():
+                if v and v.get('attrs', {}).get(attrname):
+                    found = True
+                    break
+            if not found:
+                err = True
+                self.logger.warn('%s: unsupported attribute \'%s\'' %attrname) 
+                continue
+        return err
 
-    def read_default_iface_config(self):
+    def read_iface_config(self):
         """ Reads default network interface config /etc/network/interfaces. """
-        nifaces = networkInterfaces()
-        nifaces.subscribe('iface_found', self.save_iface)
+        nifaces = networkInterfaces(self.interfacesfile,
+                        self.interfacesfileiobuf,
+                        self.interfacesfileformat,
+                        template_engine=self.config.get('template_engine'),
+                template_lookuppath=self.config.get('template_lookuppath'))
+        nifaces.subscribe('iface_found', self._save_iface)
+        nifaces.subscribe('validateifaceattr',
+                          self._iface_configattr_syntax_checker)
+        nifaces.subscribe('validateifaceobj', self._ifaceobj_syntax_checker)
         nifaces.load()
 
-    def read_iface_config(self):
-        return self.read_default_iface_config()
-
     def read_old_iface_config(self):
-        """ Reads the saved iface config instead of default iface config. """
-
-        # Read it from the statemanager
-        self.ifaceobjdict = self.statemanager.get_ifaceobjdict()
-
-
-    def save_module(self, mkind, msubkind, mname, mftype, module):
-        """ saves a module into internal module dict for later use.
-        
-        mtype - pre-up.d, post-up.d and so on
-        mftype - pmodule (python module), bashscript (bash script)
-        
-        """
-
-        mmetadata = self.operations[mkind][msubkind].get(mname)
-        if mmetadata is None or mmetadata.get('ftype') != 'pmodule':
-            mmetadata = {}
-            mmetadata['ftype'] = mftype
-            mmetadata['module'] = module
-            self.operations[mkind][msubkind][mname] = mmetadata
-
-            self.logger.debug('saved module %s' %mkind +
-                             ' %s' %mname + ' %s' %mftype)
-        else:
-            self.logger.info('ignoring module %s' %mkind + ' %s' %msubkind +
-                        ' %s' %mname + ' of type %s' %mftype)
-
-
-    def load_modules_builtin(self, modules_dir):
+        """ Reads the saved iface config instead of default iface config.
+        And saved iface config is already read by the statemanager """
+        self.ifaceobjdict = copy.deepcopy(self.statemanager.ifaceobjdict)
+
+    def _load_addon_modules_config(self):
+        """ Load addon modules config file """
+
+        with open(self.addon_modules_configfile, 'r') as f:
+            lines = f.readlines()
+            for l in lines:
+                litems = l.rstrip(' \n').split(',')
+                operation = litems[0]
+                mname = litems[1]
+                self.module_ops[operation].append(mname)
+
+    def load_addon_modules(self, modules_dir):
         """ load python modules from modules_dir
 
         Default modules_dir is /usr/share/ifupdownmodules
 
         """
-
         self.logger.info('loading builtin modules from %s' %modules_dir)
-
+        self._load_addon_modules_config()
         if not modules_dir in sys.path:
-                sys.path.append(modules_dir)
+            sys.path.append(modules_dir)
         try:
-            module_list = os.listdir(modules_dir)
-            for module in module_list:
-                if re.search('.*\.pyc', module, 0) != None:
-                    continue
-
-                mname, mext = os.path.splitext(module)
-                if mext is not None and mext == '.py':
-                    self.logger.info('loading ' + modules_dir + '/' + module)
-                    try:
-                        m = __import__(mname)
-                        mclass = getattr(m, mname)
-                    except:
-                        raise
-
-                    minstance = mclass(force=self.get_force(),
-                                       dryrun=self.get_dryrun(),
-                                       nowait=self.get_nowait(),
-                                       perfmode=self.get_perfmode())
-                    ops = minstance.get_ops()
-                    for op in ops:
-                        if re.search('up', op) is not None:
-                            self.save_module('up', op, mname, 'pmodule',
-                                             minstance)
-                        else:
-                            self.save_module('down', op, mname, 'pmodule',
-                                             minstance)
+            for op, mlist in self.module_ops.items():
+                for mname in mlist:
+                    if self.modules.get(mname):
+                        continue
+                    mpath = modules_dir + '/' + mname + '.py'
+                    if os.path.exists(mpath):
+                        try:
+                            m = __import__(mname)
+                            mclass = getattr(m, mname)
+                        except:
+                            raise
+                        minstance = mclass(force=self.FORCE,
+                                        dryrun=self.DRYRUN,
+                                        nowait=self.NOWAIT,
+                                        perfmode=self.PERFMODE,
+                                        cache=self.CACHE,
+                                        cacheflags=self.CACHE_FLAGS)
+                        self.modules[mname] = minstance
+                        try:
+                            self.module_attrs[mname] = minstance.get_modinfo()
+                        except:
+                            pass
         except: 
             raise
 
+        # Assign all modules to query operations
+        self.module_ops['query-checkcurr'] = self.modules.keys()
+        self.module_ops['query-running'] = self.modules.keys()
+        self.module_ops['query-dependency'] = self.modules.keys()
+        self.module_ops['query'] = self.modules.keys()
+        self.module_ops['query-raw'] = self.modules.keys()
 
-    def load_modules(self, modules_dir):
+
+    def _modules_help(self):
+        """ Prints addon modules supported syntax """
+
+        indent = '  '
+        for m, mdict in self.module_attrs.items():
+            if not mdict:
+                continue
+            print('%s: %s' %(m, mdict.get('mhelp')))
+            attrdict = mdict.get('attrs')
+            if not attrdict:
+                continue
+            try:
+                for attrname, attrvaldict in attrdict.items():
+                    if attrvaldict.get('compat', False):
+                        continue
+                    print('%s%s' %(indent, attrname))
+                    print('%shelp: %s' %(indent + '  ',
+                          attrvaldict.get('help', '')))
+                    print ('%srequired: %s' %(indent + '  ',
+                            attrvaldict.get('required', False)))
+                    default = attrvaldict.get('default')
+                    if default:
+                        print('%sdefault: %s' %(indent + '  ', default))
+
+                    validrange = attrvaldict.get('validrange')
+                    if validrange:
+                        print('%svalidrange: %s-%s'
+                              %(indent + '  ', validrange[0], validrange[1]))
+
+                    validvals = attrvaldict.get('validvals')
+                    if validvals:
+                        print('%svalidvals: %s'
+                              %(indent + '  ', ','.join(validvals)))
+
+                    examples = attrvaldict.get('example')
+                    if not examples:
+                        continue
+
+                    print '%sexample:' %(indent + '  ')
+                    for e in examples:
+                        print '%s%s' %(indent + '    ', e)
+            except:
+                pass
+            print ''
+            
+    def load_scripts(self, modules_dir):
         """ loading user modules from /etc/network/.
 
         Note that previously loaded python modules override modules found
@@ -394,317 +510,499 @@ class ifupdownMain():
 
         """
 
-        self.logger.info('loading user modules from %s' %modules_dir)
-        for op, subops in self.operations.items():
-            for subop in subops.keys():
-                msubdir = modules_dir + '/if-%s.d' %subop
-                self.logger.info('loading modules under %s ...' %msubdir)
-                try:
-                    module_list = os.listdir(msubdir)
-                    for module in module_list:
-                        if re.search('.*\.pyc', module, 0) != None:
-                            continue
-
-                        mname, mext = os.path.splitext(module)
-                        if mext is not None and mext == '.py':
-                            self.logger.debug('loading ' + msubdir + '/' + module)
-                            try:
-                                m = imp.load_source(module,
-                                        msubdir + '/' + module)
-                                mclass = getattr(m, mname)
-                            except:
-                                raise
-                            minstance = mclass()
-                            self.save_module(op, subop, mname, 'pmodule',
-                                                minstance)
-                        else:
-                            self.save_module(op, subop, mname, 'script',
+        self.logger.info('looking for user scripts under %s' %modules_dir)
+        for op, mlist in self.script_ops.items():
+            msubdir = modules_dir + '/if-%s.d' %op
+            self.logger.info('loading scripts under %s ...' %msubdir)
+            try:
+                module_list = os.listdir(msubdir)
+                for module in module_list:
+                    if  self.modules.get(module) is not None:
+                        continue
+                    self.script_ops[op].append(
                                     msubdir + '/' + module)
-                except: 
-                    raise
-
-        #self.logger.debug('modules ...')
-        #self.pp.pprint(self.operations)
-
-        # For query, we add a special entry, basically use all 'up' modules
-        self.operations['query'] = self.operations.get('up')
-
-
-    def conv_iface_namelist_to_objlist(self, intf_list):
-        for intf in intf_list:
-            iface_obj = self.get_iface(intf)
-            if iface_obj == None:
-                raise ifupdownInvalidValue('no iface %s', intf)
-
-            iface_objs.append(iface_obj)
-
-        return iface_objs
-
-
-    def run_without_dependents(self, op, ifacenames):
-        ifaceSched = ifaceScheduler(force=self.FORCE)
-
-        self.logger.debug('run_without_dependents for op %s' %op +
-                ' for %s' %str(ifacenames))
-
-        if ifacenames == None:
-            raise ifupdownInvalidValue('no interfaces found')
-
-        return ifaceSched.run_iface_list(self, ifacenames, op)
-
-
-    def run_with_dependents(self, op, ifacenames):
-        dependency_graph = {}
-        ret = 0
-        self.logger.debug('run_with_dependents for op %s'
-                          %op + ' for %s' %str(ifacenames))
-
-        ifaceSched = ifaceScheduler()
-
-        if ifacenames is None:
-            ifacenames = self.ifaceobjdict.keys()
-
-        # generate dependency graph of interfaces
-        self.generate_dependency_info(ifacenames, dependency_graph, op)
-
-        if self.logger.isEnabledFor(logging.DEBUG) == True:
-            self.logger.debug('dependency graph:')
-            self.pp.pprint(dependency_graph)
-
-        if self.njobs > 1:
-            ret = ifaceSched.run_iface_dependency_graph_parallel(self,
-                        dependency_graph, op)
-        else:
-            ret = ifaceSched.run_iface_dependency_graph(self, dependency_graph,
-                        op)
-
-        return ret
-
-
-    def validate_ifaces(self, ifacenames):
+            except: 
+                # continue reading
+                pass
+
+    def _sched_ifaces(self, ifacenames, ops):
+        self.logger.debug('scheduling \'%s\' for %s'
+                          %(str(ops), str(ifacenames)))
+
+        self._pretty_print_ordered_dict('dependency graph',
+                    self.dependency_graph)
+        return ifaceScheduler.sched_ifaces(self, ifacenames, ops,
+                        dependency_graph=self.dependency_graph,
+                        order=ifaceSchedulerFlags.INORDER
+                            if 'down' in ops[0]
+                                else ifaceSchedulerFlags.POSTORDER,
+                        followdependents=True if self.WITH_DEPENDS else False)
+
+    def _validate_ifaces(self, ifacenames):
         """ validates interface list for config existance.
        
         returns -1 if one or more interface not found. else, returns 0
 
         """
-
         err_iface = ''
         for i in ifacenames:
-            ifaceobjs = self.get_iface_objs(i)
-            if ifaceobjs is None:
+            ifaceobjs = self.get_ifaceobjs(i)
+            if not ifaceobjs:
                 err_iface += ' ' + i
+        if err_iface:
+            raise Exception('cannot find interfaces:%s' %err_iface)
+        return True
 
-        if len(err_iface) != 0:
-            self.logger.error('did not find interfaces: %s' %err_iface)
-            return -1
-
-        return 0
-
-
-    def iface_whitelisted(self, auto, allow_classes, excludepats, ifacename):
+    def _iface_whitelisted(self, auto, allow_classes, excludepats, ifacename):
         """ Checks if interface is whitelisted depending on set of parameters.
 
-
         interfaces are checked against the allow_classes and auto lists.
 
         """
 
-        # If the interface matches
-        if excludepats is not None and len(excludepats) > 0:
+        if excludepats:
             for e in excludepats:
-                if re.search(e, ifacename) is not None:
+                if re.search(e, ifacename):
                     return False
-
-        ifaceobjs = self.get_iface_objs(ifacename)
-        if ifaceobjs is None:
+        ifaceobjs = self.get_ifaceobjs(ifacename)
+        if not ifaceobjs:
             self.logger.debug('iface %s' %ifacename + ' not found')
             return False
-
         # We check classes first
-        if allow_classes is not None and len(allow_classes) > 0:
+        if allow_classes:
             for i in ifaceobjs:
-                if (len(i.get_classes()) > 0):
+                if i.classes:
                     common = Set([allow_classes]).intersection(
-                                Set(i.get_classes()))
-                    if len(common) > 0:
+                                Set(i.classes))
+                    if common:
                         return True
             return False
-
-        if auto == True:
+        if auto:
             for i in ifaceobjs:
-                if i.get_auto() == True:
+                if i.auto:
                     return True
             return False
-
         return True
 
-    def generate_running_env(self, ifaceobj, op):
-        """ Generates a dictionary with env variables required for an interface.
-
-        Used to support script execution for interfaces.
+    def _compat_conv_op_to_mode(self, op):
+        """ Returns old op name to work with existing scripts """
+        if op == 'pre-up':
+            return 'start'
+        elif op == 'pre-down':
+            return 'stop'
+        else:
+            return op
 
+    def generate_running_env(self, ifaceobj, op):
+        """ Generates a dictionary with env variables required for
+        an interface. Used to support script execution for interfaces.
         """
 
         cenv = None
-        iface_env = ifaceobj.get_env()
-        if iface_env is not None:
+        iface_env = ifaceobj.env
+        if iface_env:
             cenv = os.environ
-            if cenv is not None:
+            if cenv:
                 cenv.update(iface_env)
             else:
                 cenv = iface_env
-
-            cenv['MODE'] = self.compat_conv_op_to_mode(op)
-
+            cenv['MODE'] = self._compat_conv_op_to_mode(op)
         return cenv
 
+    def _save_state(self):
+        if not self.STATEMANAGER_ENABLE or not self.STATEMANAGER_UPDATE:
+            return
+        try:
+            # Update persistant iface states
+            self.statemanager.save_state()
+        except Exception, e:
+            if self.logger.isEnabledFor(logging.DEBUG):
+                t = sys.exc_info()[2]
+                traceback.print_tb(t)
+                self.logger.warning('error saving state (%s)' %str(e))
 
-    def run(self, op, auto=False, allow_classes=None,
-            ifacenames=None, query_state=None, excludepats=None,
-            format=None):
-        """ main ifupdown run method """
+    def up(self, ops, auto=False, allow_classes=None, ifacenames=None,
+           excludepats=None, printdependency=None, syntaxcheck=False):
+        """ up an interface """
 
-        if auto == True:
-            self.logger.debug('setting flag ALL')
+        if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False
+        if auto:
             self.ALL = True
+            self.WITH_DEPENDS = True
+        try:
+            self.read_iface_config()
+        except Exception:
+            raise
+
+        # If only syntax check was requested, return here
+        if syntaxcheck:
+            return
+
+        if ifacenames:
+            # If iface list is given by the caller, always check if iface
+            # is present
+            self._validate_ifaces(ifacenames)
+
+        # if iface list not given by user, assume all from config file
+        if not ifacenames: ifacenames = self.ifaceobjdict.keys()
+
+        # filter interfaces based on auto and allow classes
+        filtered_ifacenames = [i for i in ifacenames
+                               if self._iface_whitelisted(auto, allow_classes,
+                                                excludepats, i)]
+        if not filtered_ifacenames:
+            raise Exception('no ifaces found matching given allow lists')
+
+        if printdependency:
+            self.populate_dependency_info(ops, filtered_ifacenames)
+            self.print_dependency(filtered_ifacenames, printdependency)
+            return
+        else:
+            self.populate_dependency_info(ops)
+
+        try:
+            self._sched_ifaces(filtered_ifacenames, ops)
+        finally:
+            if not self.DRYRUN and self.ADDONS_ENABLE:
+                self._save_state()
+
+    def down(self, ops, auto=False, allow_classes=None, ifacenames=None,
+             excludepats=None, printdependency=None, usecurrentconfig=False):
+        """ down an interface """
 
-        # Only read new iface config for 'up'
-        # operations. For 'downs' we only rely on
-        # old state
-        if op == 'up' or op == 'query':
+        if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False
+        if auto:
+            self.ALL = True
+            self.WITH_DEPENDS = True
+        # For down we need to look at old state, unless usecurrentconfig
+        # is set
+        if (not usecurrentconfig and self.STATEMANAGER_ENABLE and
+                    self.statemanager.ifaceobjdict):
+            # Since we are using state manager objects,
+            # skip the updating of state manager objects
+            self.logger.debug('Looking at old state ..')
+            self.read_old_iface_config()
+        else:
+            # If no old state available 
             try:
                 self.read_iface_config()
             except Exception, e:
-                raise
+                raise Exception('error reading iface config (%s)' %str(e))
+        if ifacenames:
+            # If iface list is given by the caller, always check if iface
+            # is present
+            try:
+               self._validate_ifaces(ifacenames)
+            except Exception, e:
+               raise Exception('%s' %str(e) +
+                       ' (interface was probably never up ?)')
+
+        # if iface list not given by user, assume all from config file
+        if not ifacenames: ifacenames = self.ifaceobjdict.keys()
+
+        # filter interfaces based on auto and allow classes
+        filtered_ifacenames = [i for i in ifacenames
+                               if self._iface_whitelisted(auto, allow_classes,
+                                                excludepats, i)]
+        if not filtered_ifacenames:
+            raise Exception('no ifaces found matching given allow lists')
+
+        if printdependency:
+            self.populate_dependency_info(ops, filtered_ifacenames)
+            self.print_dependency(filtered_ifacenames, printdependency)
+            return
         else:
-            # for down we need to look at old state
-            self.logger.debug('down op, looking at old state ..')
-
-            if len(self.statemanager.get_ifaceobjdict()) > 0:
-                self.read_old_iface_config()
-            elif self.FORCE == True:
-                # If no old state available 
-                self.logger.info('old state not available. Force option ' +
-                        'set. Loading new iface config file')
-                try:
-                    self.read_iface_config()
-                except Exception, e:
-                    raise Exception('error reading iface config (%s)' %str(e))
-            else:
-                raise Exception('old state not available...aborting.' +
-                        ' try running with --force option')
+            self.populate_dependency_info(ops)
+
+        try:
+            self._sched_ifaces(filtered_ifacenames, ops)
+        finally:
+            if not self.DRYRUN and self.ADDONS_ENABLE:
+                self._save_state()
+
+    def query(self, ops, auto=False, allow_classes=None, ifacenames=None,
+              excludepats=None, printdependency=None,
+              format='native'):
+        """ query an interface """
 
+        if self.STATEMANAGER_ENABLE and ops[0] == 'query-savedstate':
+            return self.statemanager.dump_pretty(ifacenames)
 
-        if ifacenames is not None:
+        self.STATEMANAGER_UPDATE = False
+        if auto:
+            self.logger.debug('setting flag ALL')
+            self.ALL = True
+            self.WITH_DEPENDS = True
+
+        if ops[0] == 'query-syntax':
+            self._modules_help()
+            return
+        elif ops[0] == 'query-running':
+            # create fake devices to all dependents that dont have config
+            map(lambda i: self.create_n_save_ifaceobj(i, self.NOCONFIG),
+                    ifacenames)
+        else:
+            try:
+                self.read_iface_config()
+            except Exception:
+                raise
+
+        if ifacenames and ops[0] != 'query-running':
             # If iface list is given, always check if iface is present
-           if self.validate_ifaces(ifacenames) != 0:
-               raise Exception('all or some interfaces not found')
+           self._validate_ifaces(ifacenames)
 
         # if iface list not given by user, assume all from config file
-        if ifacenames is None: ifacenames = self.ifaceobjdict.keys()
+        if not ifacenames: ifacenames = self.ifaceobjdict.keys()
 
         # filter interfaces based on auto and allow classes
-        filtered_ifacenames = [i for i in ifacenames
-             if self.iface_whitelisted(auto, allow_classes, excludepats,
-                                       i) == True]
-
-        if len(filtered_ifacenames) == 0:
+        if ops[0] == 'query-running':
+            filtered_ifacenames = ifacenames
+        else:
+            filtered_ifacenames = [i for i in ifacenames
+                if self._iface_whitelisted(auto, allow_classes,
+                        excludepats, i)]
+        if not filtered_ifacenames:
                 raise Exception('no ifaces found matching ' +
                         'given allow lists')
 
-        if op == 'query':
-            if query_state == None:
-                return self.print_ifaceobjs_pretty(filtered_ifacenames)
-            elif query_state == 'presumed':
-                return self.print_ifaceobjs_saved_state_pretty(
-                                    filtered_ifacenames)
-            elif query_state == 'presumeddetailed':
-                return self.print_ifaceobjs_saved_state_detailed_pretty(
-                                    filtered_ifacenames)
-
-        if op == 'query' or self.NODEPENDS == True:
-            self.run_without_dependents(op, filtered_ifacenames)
-        else:
-            self.run_with_dependents(op, filtered_ifacenames)
-
-        if op == 'query':
-            if query_state == 'curr':
-                # print curr state of all interfaces
-                ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames)
-                if ret != 0:
-                    # if any of the object has an error, signal that silently
-                    raise Exception('')
+        self.populate_dependency_info(ops, filtered_ifacenames)
+        if ops[0] == 'query-dependency' and printdependency:
+            self.print_dependency(filtered_ifacenames, printdependency)
             return
 
-        # Update persistant iface states
+        if ops[0] == 'query':
+            return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
+        elif ops[0] == 'query-raw':
+            return self.print_ifaceobjs_raw(filtered_ifacenames)
+
+        self._sched_ifaces(filtered_ifacenames, ops)
+
+        if ops[0] == 'query-checkcurr':
+            ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames, format)
+            if ret != 0:
+                # if any of the object has an error, signal that silently
+                raise Exception('')
+        elif ops[0] == 'query-running':
+            self.print_ifaceobjsrunning_pretty(filtered_ifacenames, format)
+            return
+
+    def reload(self, upops, downops, auto=False, allow=None,
+            ifacenames=None, excludepats=None, usecurrentconfig=False):
+        """ reload interface config """
+
+        allow_classes = []
+
+        self.logger.debug('reloading interface config ..')
+        if auto:
+            self.ALL = True
+            self.WITH_DEPENDS = True
+
         try:
-            if self.ALL == True:
-                self.statemanager.flush_state(self.ifaceobjdict)
-            else:
-                self.statemanager.flush_state()
-        except Exception, e:
-            if self.logger.isEnabledFor(logging.DEBUG):
-                t = sys.exc_info()[2]
-                traceback.print_tb(t)
-            self.logger.warning('error saving state (%s)' %str(e))
+            self.read_iface_config()
+        except:
+            raise
 
+        # generate dependency graph of interfaces
+        self.populate_dependency_info(upops)
+        if (not usecurrentconfig and self.STATEMANAGER_ENABLE
+                and self.statemanager.ifaceobjdict):
+            # Save a copy of new iface objects and dependency_graph
+            new_ifaceobjdict = dict(self.ifaceobjdict)
+            new_dependency_graph = dict(self.dependency_graph)
+
+            # if old state is present, read old state and mark op for 'down'
+            # followed by 'up' aka: reload
+            # old interface config is read into self.ifaceobjdict
+            self.read_old_iface_config()
+            op = 'reload'
+        else:
+            # oldconfig not available, continue with 'up' with new config
+            op = 'up'
+
+        if not ifacenames: ifacenames = self.ifaceobjdict.keys()
+        if op == 'reload' and ifacenames:
+            filtered_ifacenames = [i for i in ifacenames
+                               if self._iface_whitelisted(auto, allow_classes,
+                               excludepats, i)]
+            # Generate the interface down list
+            # Interfaces that go into the down list:
+            #   - interfaces that were present in last config and are not
+            #     present in the new config
+            #   - interfaces that were changed between the last and current
+            #     config
+            #
+            ifacedownlist = []
+            for ifname, lastifaceobjlist in self.ifaceobjdict.items():
+                objidx = 0
+                # If interface is not present in the new file
+                # append it to the down list
+                newifaceobjlist = new_ifaceobjdict.get(ifname)
+                if not newifaceobjlist:
+                    ifacedownlist.append(ifname)
+                    continue
+                # If interface has changed between the current file
+                # and the last installed append it to the down list
+                if len(newifaceobjlist) != len(lastifaceobjlist):
+                    ifacedownlist.append(ifname)
+                    continue
+                # compare object list
+                for objidx in range(0, len(lastifaceobjlist)):
+                    oldobj = lastifaceobjlist[objidx]
+                    newobj = newifaceobjlist[objidx]
+                    if not newobj.compare(oldobj):
+                        ifacedownlist.append(ifname)
+                        continue
 
-    def up(self, auto=False, allow=None, ifacenames=None, excludepats=None):
-        return self.run('up', auto, allow, ifacenames, excludepats=excludepats)
+            if ifacedownlist:
+                self.logger.info('Executing down on interfaces: %s'
+                                  %str(ifacedownlist))
+                # reinitialize dependency graph 
+                self.dependency_graph = OrderedDict({})
+                # Generate dependency info for old config
+                self.populate_dependency_info(downops, ifacedownlist)
+                self._sched_ifaces(ifacedownlist, downops)
+            else:
+                self.logger.debug('no interfaces to down ..')
 
-    def down(self, auto=False, allow=None, ifacenames=None, excludepats=None):
-        return self.run('down', auto, allow, ifacenames,
-                        excludepats=excludepats);
+        # Now, run 'up' with new config dict
+        # reset statemanager update flag to default
+        self.ifaceobjdict = new_ifaceobjdict
+        self.dependency_graph = new_dependency_graph
+        ifacenames = self.ifaceobjdict.keys()
+        filtered_ifacenames = [i for i in ifacenames
+                               if self._iface_whitelisted(auto, allow_classes,
+                               excludepats, i)]
 
-    def query(self, auto=False, allow=None, ifacenames=None,
-              query_state=False, excludepats=None):
-        return self.run('query', auto, allow, ifacenames,
-                        query_state=query_state, excludepats=excludepats);
+        self.logger.info('Scheduling up on interfaces: %s'
+                                  %str(filtered_ifacenames))
+        self._sched_ifaces(filtered_ifacenames, upops)
+        if self.DRYRUN:
+            return
+        self._save_state()
 
-    def dump(self):
-        """ all state dump """
+    def _pretty_print_ordered_dict(self, prefix, argdict):
+        outbuf = prefix + ' {\n'
+        for k, vlist in argdict.items():
+            outbuf += '\t%s : %s\n' %(k, str(vlist))
+        self.logger.debug(outbuf + '}')
 
-        print 'ifupdown object dump'
-        print self.pp.pprint(self.modules)
-        print self.pp.pprint(self.ifaces)
-        self.state_manager.dump()
+    def print_dependency(self, ifacenames, format):
+        """ prints iface dependency information """
 
-    def print_state(self, ifacenames=None):
-        self.statemanager.dump(ifacenames)
+        if not ifacenames:
+            ifacenames = self.ifaceobjdict.keys()
+        if format == 'list':
+            for k,v in self.dependency_graph.items():
+                print '%s : %s' %(k, str(v))
+        elif format == 'dot':
+            indegrees = {}
+            map(lambda i: indegrees.update({i :
+                self.get_iface_refcnt(i)}),
+                self.dependency_graph.keys())
+            graph.generate_dots(self.dependency_graph, indegrees)
+
+    def print_ifaceobjs_raw(self, ifacenames):
+        """ prints raw lines for ifaces from config file """
 
-    def print_ifaceobjs_pretty(self, ifacenames):
         for i in ifacenames:
-            ifaceobjs = self.get_iface_objs(i)
-            for io in ifaceobjs:
-                io.dump_raw(self.logger)
+            for ifaceobj in self.get_ifaceobjs(i):
+                if (self.is_ifaceobj_builtin(ifaceobj) or 
+                    not ifaceobj.is_config_present()):
+                    continue
+                ifaceobj.dump_raw(self.logger)
                 print '\n'
+                if self.WITH_DEPENDS and not self.ALL:
+                    dlist = ifaceobj.lowerifaces
+                    if not dlist: continue
+                    self.print_ifaceobjs_raw(dlist)
 
-    def print_ifaceobjscurr_pretty(self, ifacenames, format):
-        """ Dumps current running state of interfaces.
-
-        returns 1 if any of the interface has an error,
-        else returns 0
+    def _get_ifaceobjs_pretty(self, ifacenames, ifaceobjs, running=False):
+        """ returns iface obj list """
 
-        """
+        for i in ifacenames:
+            for ifaceobj in self.get_ifaceobjs(i):
+                if ((not running and self.is_ifaceobj_noconfig(ifaceobj)) or
+                    (running and not ifaceobj.is_config_present())):
+                    continue
+                ifaceobjs.append(ifaceobj)
+                if self.WITH_DEPENDS and not self.ALL:
+                    dlist = ifaceobj.lowerifaces
+                    if not dlist: continue
+                    self._get_ifaceobjs_pretty(dlist, ifaceobjs, running)
+
+    def print_ifaceobjs_pretty(self, ifacenames, format='native'):
+        """ pretty prints iface in format given by keyword arg format """
+
+        ifaceobjs = []
+        self._get_ifaceobjs_pretty(ifacenames, ifaceobjs)
+        if not ifaceobjs: return
+        if format == 'json':
+            print json.dumps(ifaceobjs, cls=ifaceJsonEncoder,
+                             indent=4, separators=(',', ': '))
+        else:
+            map(lambda i: i.dump_pretty(), ifaceobjs)
 
+    def _get_ifaceobjscurr_pretty(self, ifacenames, ifaceobjs):
         ret = 0
         for i in ifacenames:
-            ifaceobj = self.get_ifaceobjcurr(i)
-            if ifaceobj.get_status() == ifaceStatus.NOTFOUND:
-                print 'iface %s' %ifaceobj.get_name() + ' (not found)'
-                ret = 1
-                continue
-            elif ifaceobj.get_status() == ifaceStatus.ERROR:
-                ret = 1
-            if format is None or format == 'nwifaces':
-                ifaceobj.dump_pretty(self.logger)
-            else:
-                ifaceobj.dump_json(self.logger)
+            ifaceobjscurr = self.get_ifaceobjcurr(i)
+            if not ifaceobjscurr: continue
+            for ifaceobj in ifaceobjscurr:
+                if (ifaceobj.status == ifaceStatus.NOTFOUND or
+                    ifaceobj.status == ifaceStatus.ERROR):
+                    ret = 1
+                if self.is_ifaceobj_noconfig(ifaceobj):
+                    continue
+                ifaceobjs.append(ifaceobj)
+                if self.WITH_DEPENDS and not self.ALL:
+                    dlist = ifaceobj.lowerifaces
+                    if not dlist: continue
+                    dret = self._get_ifaceobjscurr_pretty(dlist, ifaceobjs)
+                    if dret: ret = 1
+        return ret
+
+    def print_ifaceobjscurr_pretty(self, ifacenames, format='native'):
+        """ pretty prints current running state of interfaces with status.
+
+        returns 1 if any of the interface has an error,
+        else returns 0
+        """
 
+        ifaceobjs = []
+        ret = self._get_ifaceobjscurr_pretty(ifacenames, ifaceobjs)
+        if not ifaceobjs: return
+        self.logger.debug(ifaceobjs)
+        if format == 'json':
+            print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, indent=2,
+                       separators=(',', ': '))
+        else:
+            map(lambda i: i.dump_pretty(with_status=True,
+                    successstr=self.config.get('check_success_str',
+                                               _success_sym),
+                    errorstr=self.config.get('check_error_str', _error_sym)),
+                                ifaceobjs)
         return ret
 
-    def print_ifaceobjs_saved_state_pretty(self, ifacenames):
-        self.statemanager.print_state_pretty(ifacenames, self.logger)
+    def print_ifaceobjsrunning_pretty(self, ifacenames, format='native'):
+        """ pretty prints iface running state """
 
-    def print_ifaceobjs_saved_state_detailed_pretty(self, ifacenames):
-        self.statemanager.print_state_detailed_pretty(ifacenames, self.logger)
+        ifaceobjs = []
+        self._get_ifaceobjs_pretty(ifacenames, ifaceobjs, running=True)
+        if not ifaceobjs: return
+        if format == 'json':
+            print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, indent=2,
+                       separators=(',', ': '))
+        else:
+            map(lambda i: i.dump_pretty(), ifaceobjs)
+
+    def _dump(self):
+        print 'ifupdown main object dump'
+        print self.pp.pprint(self.modules)
+        print self.pp.pprint(self.ifaceobjdict)
+
+    def _dump_ifaceobjs(self, ifacenames):
+        for i in ifacenames:
+            ifaceobjs = self.get_ifaceobjs(i)
+            for i in ifaceobjs:
+                i.dump(self.logger)
+                print '\n'