]> git.proxmox.com Git - mirror_ifupdown2.git/blobdiff - sbin/ifupdown
execute 'up' on upper devices if ifup is called with --with-depends
[mirror_ifupdown2.git] / sbin / ifupdown
index ca8c63e3165933ccd3115f26e550adc4e170d610..8e1b21c5b6c34c4b406f83e774628378ae1eee48 100755 (executable)
@@ -1,8 +1,9 @@
 #!/usr/bin/python
+# PYTHON_ARGCOMPLETE_OK
 
 import sys
 import os
-import re
+import argcomplete
 import argparse
 from ifupdown.ifupdownmain import *
 
@@ -11,46 +12,119 @@ import logging
 lockfile="/run/network/.lock"
 logger = None
 
-def run(args, op):
+def run_up(args):
     logger.debug('args = %s' %str(args))
 
     try:
-        logger.debug('creating ifupdown object ..')
-        if op == 'up' or op == 'down':
-            ifupdown_handle = ifupdownMain(force=args.force,
-                                            nodepends=args.nodepends,
-                                            perfmode=args.perfmode,
-                                            njobs=args.jobs,
-                                            dryrun=args.noact)
-        elif op == 'query':
-            ifupdown_handle = ifupdownMain(nodepends=args.nodepends,
-                                            perfmode=args.perfmode,
-                                            njobs=args.jobs,
-                                            format=args.format)
-
         iflist = args.iflist
         if len(args.iflist) == 0:
             iflist = None
+        logger.debug('creating ifupdown object ..')
+        cachearg=(False if (iflist or args.nocache or
+                            args.perfmode or args.noact)
+                            else True)
+        ifupdown_handle = ifupdownMain(force=args.force,
+                                       withdepends=args.withdepends,
+                                       perfmode=args.perfmode,
+                                       njobs=args.jobs,
+                                       dryrun=args.noact,
+                                       cache=cachearg,
+                                       addons_enable=not args.noaddons,
+                                       statemanager_enable=not args.noaddons)
+
+        if args.noaddons:
+            ifupdown_handle.up(['up'], args.all, args.CLASS, iflist,
+                               excludepats=args.excludepats,
+                               printdependency=args.printdependency)
+        else:
+            ifupdown_handle.up(['pre-up', 'up', 'post-up'],
+                               args.all, args.CLASS, iflist,
+                               excludepats=args.excludepats,
+                               printdependency=args.printdependency)
+    except:
+        raise
 
-        logger.debug('calling %s' %op + ' for all interfaces ..')
-        if op == 'up':
-            ifupdown_handle.up(args.all, args.CLASS, iflist,
-                               excludepats=args.excludepats)
-        elif op == 'down':
-            ifupdown_handle.down(args.all, args.CLASS, iflist,
-                                 excludepats=args.excludepats)
-        elif op == 'query':
-            if args.curstate == True:
-                qstate='curr'
-            elif args.presumedstate == True:
-                qstate='presumed'
-            elif args.presumedstatedetailed == True:
-                qstate='presumeddetailed'
-            else:
-                qstate=None
-            ifupdown_handle.query(args.all, args.CLASS, iflist,
-                                  query_state=qstate,
-                                  excludepats=args.excludepats)
+def run_down(args):
+    logger.debug('args = %s' %str(args))
+
+    try:
+        iflist = args.iflist
+        logger.debug('creating ifupdown object ..')
+        cachearg=(False if (iflist or args.nocache or
+                            args.perfmode or args.noact)
+                            else True)
+        ifupdown_handle = ifupdownMain(force=args.force,
+                                       withdepends=args.withdepends,
+                                       perfmode=args.perfmode,
+                                       njobs=args.jobs,
+                                       dryrun=args.noact,
+                                       cache=cachearg,
+                                       addons_enable=not args.noaddons,
+                                       statemanager_enable=not args.noaddons)
+
+        ifupdown_handle.down(['pre-down', 'down', 'post-down'],
+                             args.all, args.CLASS, iflist,
+                             excludepats=args.excludepats,
+                             printdependency=args.printdependency,
+                             usecurrentconfig=args.usecurrentconfig)
+    except:
+        raise
+
+def run_query(args):
+    logger.debug('args = %s' %str(args))
+
+    try:
+        iflist = args.iflist
+        if args.checkcurr:
+            qop='query-checkcurr'
+        elif args.running:
+            qop='query-running'
+        elif args.raw:
+            qop='query-raw'
+        elif args.syntaxhelp:
+            qop = 'query-syntax'
+        elif args.printdependency:
+            qop = 'query-dependency'
+        elif args.printsavedstate:
+            qop = 'query-savedstate'
+        else:
+            qop='query'
+        cachearg=(False if (iflist or args.nocache or
+                            args.perfmode or args.syntaxhelp or
+                            (qop != 'query-checkcurr' and
+                            qop != 'query-running')) else True)
+        if not iflist and qop == 'query-running':
+            iflist = [i for i in os.listdir('/sys/class/net/')
+                        if os.path.isdir('/sys/class/net/%s' %i)]
+        logger.debug('creating ifupdown object ..')
+        ifupdown_handle = ifupdownMain(withdepends=args.withdepends,
+                                       perfmode=args.perfmode,
+                                       njobs=args.jobs,
+                                       cache=cachearg)
+
+        ifupdown_handle.query([qop], args.all, args.CLASS, iflist,
+                              excludepats=args.excludepats,
+                              printdependency=args.printdependency,
+                              format=args.format)
+    except:
+        raise
+
+def run_reload(args):
+    logger.debug('args = %s' %str(args))
+
+    try:
+        logger.debug('creating ifupdown object ..')
+        cachearg=(False if (args.nocache or
+                            args.perfmode or args.noact) else True)
+        ifupdown_handle = ifupdownMain(withdepends=args.withdepends,
+                                            perfmode=args.perfmode,
+                                            njobs=args.jobs,
+                                            cache=cachearg)
+        ifupdown_handle.reload(['pre-up', 'up', 'post-up'],
+                               ['pre-down', 'down', 'post-down'],
+                               args.all, None, None,
+                               excludepats=args.excludepats,
+                               downchangediface=args.downchangediface)
     except:
         raise
 
@@ -58,11 +132,9 @@ def init(args):
     global logger
 
     log_level = logging.WARNING
-
-    if args.verbose == True:
+    if args.verbose:
         log_level = logging.INFO
-
-    if args.debug == True:
+    if args.debug:
         log_level = logging.DEBUG
 
     try:
@@ -77,8 +149,13 @@ def deinit():
     {}
 
 def update_argparser(argparser):
+    """ base parser, common to all commands """
+
+    argparser.add_argument('-a', '--all', action='store_true', required=False,
+                help='process all interfaces marked \"auto\"')
     argparser.add_argument('iflist', metavar='IFACE',
-                nargs='*', help='interfaces list')
+                nargs='*', help='interface list separated by spaces. ' +
+                'IFACE list is mutually exclusive with -a option.')
     argparser.add_argument('-v', '--verbose', dest='verbose',
                 action='store_true', help='verbose')
     argparser.add_argument('-d', '--debug', dest='debug',
@@ -89,101 +166,178 @@ def update_argparser(argparser):
                 help=argparse.SUPPRESS)
     argparser.add_argument('--allow', dest='CLASS', 
                 help='ignore non-\"allow-CLASS\" interfaces')
-    argparser.add_argument('--nodepends', dest='nodepends',
-                action='store_true', help=argparse.SUPPRESS)
+    argparser.add_argument('--with-depends', dest='withdepends',
+                action='store_true', help='run with all dependent interfaces.'+
+                ' This option is redundant when \'-a\' is specified. With ' +
+                '\'-a\' interfaces are always executed in dependency order')
     argparser.add_argument('--perfmode', dest='perfmode',
                 action='store_true', help=argparse.SUPPRESS)
     argparser.add_argument('-j', '--jobs', dest='jobs', type=int,
                 default=-1, choices=range(1,12), help=argparse.SUPPRESS)
+    argparser.add_argument('--nocache', dest='nocache', action='store_true',
+                help=argparse.SUPPRESS)
     argparser.add_argument('-X', '--exclude', dest='excludepats',
-                action='append', help='exclude interfaces from the list of '
-                + 'interfaces to operate on by a PATTERN '
-                + '(note that this option doesn\'t disable mappings)')
-
+                action='append',
+                help='Exclude interfaces from the list of interfaces' +
+                ' to operate on. Can be specified multiple times.')
 
 def update_ifupdown_argparser(argparser):
-    argparser.add_argument('-a', '--all', action='store_true',
-                help='process all interfaces marked \"auto\"')
+    """ common arg parser for ifup and ifdown """
     argparser.add_argument('-f', '--force', dest='force',
                 action='store_true',
                 help='force run all operations')
-    argparser.add_argument('-n', '--no-act', dest='noact',
+    group = argparser.add_mutually_exclusive_group(required=False)
+    group.add_argument('-n', '--no-act', dest='noact',
                 action='store_true', help='print out what would happen,' +
                 'but don\'t do it')
+    group.add_argument('--print-dependency',
+                dest='printdependency', choices=['list', 'dot'],
+                help='print iface dependency')
+    group.add_argument('--no-scripts', '--no-addons',
+                dest='noaddons',  action='store_true',
+                help='dont run any addon modules or scripts. Runs only link ' +
+                     'up/down')
 
 def update_ifup_argparser(argparser):
     update_ifupdown_argparser(argparser)
 
 def update_ifdown_argparser(argparser):
     update_ifupdown_argparser(argparser)
+    argparser.add_argument('--use-current-config',
+                dest='usecurrentconfig',  action='store_true',
+                help=argparse.SUPPRESS)
+                #help='By default ifdown looks at the saved state for ' +
+                #'interfaces to bring down. This option allows ifdown to ' +
+                #'look at the current interfaces file. Useful when your ' +
+                #'state file is corrupted or you want down to use the latest '
+                #'from the interfaces file')
 
 def update_ifquery_argparser(argparser):
+    """ arg parser for ifquery options """
+
+    # -l is same as '-a', only here for backward compatibility
     argparser.add_argument('-l', '--list', action='store_true', dest='all',
-                help='process all interfaces marked \"auto\"')
+                help=argparse.SUPPRESS)
     group = argparser.add_mutually_exclusive_group(required=False)
-    group.add_argument('-r', '--running-state', dest='curstate',
+    group.add_argument('-r', '--running', dest='running',
                        action='store_true',
                        help='query running state of an interface')
-
-    # presumed-state is state maintained by ifupdown
-    group.add_argument('--presumed-state', dest='presumedstate',
-                       action='store_true', help=argparse.SUPPRESS)
-
-    # presumed-state-detailed prints all details about the object stored
-    # by ifupdown
-    group.add_argument('--presumed-state-detailed',
-                       dest='presumedstatedetailed',
-                       action='store_true', help=argparse.SUPPRESS)
-
-    group.add_argument('--format', dest='format', default='nwifaces',
-                       choices=['nwifaces', 'json'], help=argparse.SUPPRESS)
-
+    group.add_argument('-c', '--check', dest='checkcurr',
+                       action='store_true',
+                       help='check interface file contents against ' +
+                       'running state of an interface')
+    group.add_argument('--raw', action='store_true', dest='raw',
+                       help='print raw config file entries')
+    group.add_argument('--print-savedstate', action='store_true',
+                       dest='printsavedstate',
+                       help=argparse.SUPPRESS)
+    argparser.add_argument('--format', dest='format', default='native',
+                       choices=['native', 'json'], help=argparse.SUPPRESS)
+    argparser.add_argument('--print-dependency',
+                           dest='printdependency', choices=['list', 'dot'],
+                           help='print interface dependency')
+    argparser.add_argument('--syntax-help', action='store_true',
+                           dest='syntaxhelp',
+                           help='print supported interface config syntax')
+
+def update_ifreload_argparser(argparser):
+    """ parser for ifreload """
+    argparser.add_argument('-a', '--all', action='store_true', required=True,
+                help='process all interfaces marked \"auto\"')
+    argparser.add_argument('iflist', metavar='IFACE',
+                nargs='*', help=argparse.SUPPRESS)
+    argparser.add_argument('-n', '--no-act', dest='noact',
+                action='store_true', help=argparse.SUPPRESS)
+    argparser.add_argument('-v', '--verbose', dest='verbose',
+                action='store_true', help='verbose')
+    argparser.add_argument('-d', '--debug', dest='debug',
+                action='store_true',
+                help='output debug info')
+    argparser.add_argument('--with-depends', dest='withdepends',
+                action='store_true', help=argparse.SUPPRESS)
+    argparser.add_argument('--perfmode', dest='perfmode',
+                action='store_true', help=argparse.SUPPRESS)
+    argparser.add_argument('--nocache', dest='nocache', action='store_true',
+                help=argparse.SUPPRESS)
+    argparser.add_argument('-X', '--exclude', dest='excludepats',
+                action='append',
+                help=argparse.SUPPRESS)
+    argparser.add_argument('-j', '--jobs', dest='jobs', type=int,
+                default=-1, choices=range(1,12), help=argparse.SUPPRESS)
+    argparser.add_argument('--down-changediface', dest='downchangediface',
+                            action='store_true', help='down interfaces whose ' +
+                            'config have changed before bringing them up. By' +
+                            ' default all interfaces are brought up')
 
 def parse_args(argsv, op):
-    descr = 'interface management'
-
+    if op == 'query':
+        descr = 'query interfaces (all or interface list)'
+    else:
+        descr = 'interface management'
     argparser = argparse.ArgumentParser(description=descr)
-    update_argparser(argparser)
-    if op == 'up':
-        update_ifup_argparser(argparser)
-    elif op == 'down':
-        update_ifdown_argparser(argparser)
-    elif op == 'query':
-        update_ifquery_argparser(argparser)
+    if op == 'reload':
+        update_ifreload_argparser(argparser)
+    else:
+        update_argparser(argparser)
+        if op == 'up':
+            update_ifup_argparser(argparser)
+        elif op == 'down':
+            update_ifdown_argparser(argparser)
+        elif op == 'query':
+            update_ifquery_argparser(argparser)
+        elif op == 'reload':
+            update_ifreload_argparser(argparser)
+
+    argcomplete.autocomplete(argparser)
 
     return argparser.parse_args(argsv)
 
+handlers = {'up' : run_up,
+            'down' : run_down,
+            'query' : run_query,
+            'reload' : run_reload }
+
 def main(argv):
     """ main function """
+    args = None
     try:
         op = None
-        if re.search(r'ifup', argv[0]) != None:
+        if argv[0].endswith('ifup'):
             op = 'up'
-        elif re.search(r'ifdown', argv[0]) != None:
+        elif argv[0].endswith('ifdown'):
             op = 'down'
-        elif re.search(r'ifquery', argv[0]) != None:
+        elif argv[0].endswith('ifquery'):
             op = 'query'
+        elif argv[0].endswith('ifreload'):
+            op = 'reload'
         else:
             print ('Unexpected executable.' +
                    ' Should be \'ifup\' or \'ifdown\' or \'ifquery\'')
             exit(1)
-
         # Command line arg parser
         args = parse_args(argv[1:], op)
-        if len(args.iflist) > 0 and args.all is True:
-            print 'interface list and \'-a\' are mutually exclusive'
-            exit(1)
+        if not args.iflist and not args.all:
+            if op != 'query' or not args.syntaxhelp:
+                print '\'-a\' option or interface list are required'
+                exit(1)
 
+        if args.iflist and args.all:
+            print '\'-a\' option and interface list are mutually exclusive'
+            exit(1)
         init(args)
-        run(args, op)
+        handlers.get(op)(args)
     except Exception, e:
-        if str(e) == '':
+        if not str(e):
             exit(1)
-
-        if args.debug == True:
+        if args and args.debug:
             raise
         else:
-            logger.error(str(e))
+            if logger:
+                logger.error(str(e))
+            else:
+                print str(e)
+            if args and not args.debug:
+                print '\nRerun the command with \'-d\' for a detailed errormsg'
         exit(1)
     finally:
         deinit()