]>
git.proxmox.com Git - mirror_ifupdown2.git/blob - sbin/ifupdown2
3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
7 # tool to configure network interfaces
16 import logging
.handlers
18 from ifupdown
.ifupdownmain
import *
19 from ifupdown
.utils
import *
21 IFUPDOWN2_VERSION
= '1.1-cl3u9'
23 lockfile
="/run/network/.lock"
24 configfile
="/etc/network/ifupdown2/ifupdown2.conf"
27 interfacesfileiobuf
=None
28 interfacesfilename
=None
29 ENVPATH
= "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
32 logger
.debug('args = %s' %str
(args
))
36 if len(args
.iflist
) == 0:
38 logger
.debug('creating ifupdown object ..')
39 cachearg
=(False if (iflist
or args
.nocache
or
40 args
.perfmode
or args
.noact
)
42 ifupdown_handle
= ifupdownMain(config
=configmap_g
,
44 withdepends
=args
.withdepends
,
45 perfmode
=args
.perfmode
,
48 addons_enable
=not args
.noaddons
,
49 statemanager_enable
=not args
.noaddons
,
50 interfacesfile
=interfacesfilename
,
51 interfacesfileiobuf
=interfacesfileiobuf
,
52 interfacesfileformat
=args
.interfacesfileformat
)
54 ifupdown_handle
.up(['up'], args
.all
, args
.CLASS
, iflist
,
55 excludepats
=args
.excludepats
,
56 printdependency
=args
.printdependency
,
57 syntaxcheck
=args
.syntaxcheck
, type=args
.type,
58 skipupperifaces
=args
.skipupperifaces
)
60 ifupdown_handle
.up(['pre-up', 'up', 'post-up'],
61 args
.all
, args
.CLASS
, iflist
,
62 excludepats
=args
.excludepats
,
63 printdependency
=args
.printdependency
,
64 syntaxcheck
=args
.syntaxcheck
, type=args
.type,
65 skipupperifaces
=args
.skipupperifaces
)
70 logger
.debug('args = %s' %str
(args
))
74 logger
.debug('creating ifupdown object ..')
75 ifupdown_handle
= ifupdownMain(config
=configmap_g
, force
=args
.force
,
76 withdepends
=args
.withdepends
,
77 perfmode
=args
.perfmode
,
79 addons_enable
=not args
.noaddons
,
80 statemanager_enable
=not args
.noaddons
,
81 interfacesfile
=interfacesfilename
,
82 interfacesfileiobuf
=interfacesfileiobuf
,
83 interfacesfileformat
=args
.interfacesfileformat
)
85 ifupdown_handle
.down(['pre-down', 'down', 'post-down'],
86 args
.all
, args
.CLASS
, iflist
,
87 excludepats
=args
.excludepats
,
88 printdependency
=args
.printdependency
,
89 usecurrentconfig
=args
.usecurrentconfig
,
95 logger
.debug('args = %s' %str
(args
))
100 qop
='query-checkcurr'
105 elif args
.syntaxhelp
:
107 elif args
.printdependency
:
108 qop
= 'query-dependency'
109 elif args
.printsavedstate
:
110 qop
= 'query-savedstate'
113 cachearg
=(False if (iflist
or args
.nocache
or
114 args
.perfmode
or args
.syntaxhelp
or
115 (qop
!= 'query-checkcurr' and
116 qop
!= 'query-running')) else True)
117 if not iflist
and qop
== 'query-running':
118 iflist
= [i
for i
in os
.listdir('/sys/class/net/')
119 if os
.path
.isdir('/sys/class/net/%s' %i)]
120 logger
.debug('creating ifupdown object ..')
121 ifupdown_handle
= ifupdownMain(config
=configmap_g
,
122 withdepends
=args
.withdepends
,
123 perfmode
=args
.perfmode
,
125 interfacesfile
=interfacesfilename
,
126 interfacesfileiobuf
=interfacesfileiobuf
,
127 interfacesfileformat
=args
.interfacesfileformat
,
128 withdefaults
=args
.withdefaults
)
129 # list implies all auto interfaces (this is how ifupdown behaves)
132 ifupdown_handle
.query([qop
], args
.all
, args
.list, args
.CLASS
, iflist
,
133 excludepats
=args
.excludepats
,
134 printdependency
=args
.printdependency
,
135 format
=args
.format
, type=args
.type)
139 def run_reload(args
):
140 logger
.debug('args = %s' %str
(args
))
143 logger
.debug('creating ifupdown object ..')
144 ifupdown_handle
= ifupdownMain(config
=configmap_g
,
145 interfacesfile
=interfacesfilename
,
146 withdepends
=args
.withdepends
,
147 perfmode
=args
.perfmode
,
149 ifupdown_handle
.reload(['pre-up', 'up', 'post-up'],
150 ['pre-down', 'down', 'post-down'],
151 auto
=args
.all
, allow
=args
.CLASS
, ifacenames
=None,
152 excludepats
=args
.excludepats
,
153 usecurrentconfig
=args
.usecurrentconfig
,
154 syntaxcheck
=args
.syntaxcheck
,
155 currentlyup
=args
.currentlyup
)
161 global interfacesfileiobuf
162 global interfacesfilename
164 log_level
= logging
.WARNING
166 log_level
= logging
.INFO
168 log_level
= logging
.DEBUG
171 if hasattr(args
, 'syslog') and args
.syslog
:
172 root_logger
= logging
.getLogger()
173 syslog_handler
= logging
.handlers
.SysLogHandler(address
='/dev/log',
174 facility
=logging
.handlers
.SysLogHandler
.LOG_DAEMON
)
175 logging
.addLevelName(logging
.ERROR
, 'error')
176 logging
.addLevelName(logging
.WARNING
, 'warning')
177 logging
.addLevelName(logging
.DEBUG
, 'debug')
178 logging
.addLevelName(logging
.INFO
, 'info')
179 root_logger
.setLevel(log_level
)
180 syslog_handler
.setFormatter(logging
.Formatter(
181 '%(name)s: %(levelname)s: %(message)s'))
182 root_logger
.addHandler(syslog_handler
)
183 logger
= logging
.getLogger('ifupdown')
185 logging
.basicConfig(level
=log_level
,
186 format
='%(levelname)s: %(message)s')
187 logging
.addLevelName(logging
.ERROR
, 'error')
188 logging
.addLevelName(logging
.WARNING
, 'warning')
189 logging
.addLevelName(logging
.DEBUG
, 'debug')
190 logging
.addLevelName(logging
.INFO
, 'info')
191 logger
= logging
.getLogger('ifupdown')
195 if hasattr(args
, 'interfacesfile') and args
.interfacesfile
!= None:
196 # Check to see if -i option is allowed by config file
197 # But for ifquery, we will not check this
198 if (not sys
.argv
[0].endswith('ifquery') and
199 configmap_g
.get('disable_cli_interfacesfile','0') == '1'):
200 logger
.error('disable_cli_interfacesfile is set so users '
201 'not allowed to specify interfaces file on cli.')
203 if args
.interfacesfile
== '-':
204 # If interfaces file is stdin, read
205 interfacesfileiobuf
= sys
.stdin
.read()
207 interfacesfilename
= args
.interfacesfile
209 # if the ifupdown2 config file does not have it, default to standard
210 interfacesfilename
= configmap_g
.get('default_interfaces_configfile',
211 '/etc/network/interfaces')
219 def update_argparser(argparser
):
220 """ base parser, common to all commands """
222 argparser
.add_argument('-a', '--all', action
='store_true', required
=False,
223 help='process all interfaces marked \"auto\"')
224 argparser
.add_argument('iflist', metavar
='IFACE',
225 nargs
='*', help='interface list separated by spaces. ' +
226 'IFACE list is mutually exclusive with -a option.')
227 argparser
.add_argument('-v', '--verbose', dest
='verbose',
228 action
='store_true', help='verbose')
229 argparser
.add_argument('-d', '--debug', dest
='debug',
231 help='output debug info')
232 argparser
.add_argument('-q', '--quiet', dest
='quiet',
234 help=argparse
.SUPPRESS
)
235 argparser
.add_argument('--allow', dest
='CLASS',
236 help='ignore non-\"allow-CLASS\" interfaces')
237 argparser
.add_argument('-w', '--with-depends', dest
='withdepends',
238 action
='store_true', help='run with all dependent interfaces.'+
239 ' This option is redundant when \'-a\' is specified. With ' +
240 '\'-a\' interfaces are always executed in dependency order')
241 argparser
.add_argument('--perfmode', dest
='perfmode',
242 action
='store_true', help=argparse
.SUPPRESS
)
243 #argparser.add_argument('-j', '--jobs', dest='jobs', type=int,
244 # default=-1, choices=range(1,12), help=argparse.SUPPRESS)
245 argparser
.add_argument('--nocache', dest
='nocache', action
='store_true',
246 help=argparse
.SUPPRESS
)
247 argparser
.add_argument('-X', '--exclude', dest
='excludepats',
249 help='Exclude interfaces from the list of interfaces' +
250 ' to operate on. Can be specified multiple times.')
251 argparser
.add_argument('-i', '--interfaces', dest
='interfacesfile',
253 help='Specify interfaces file instead of file defined ' +
254 'in ifupdown2.conf file')
255 argparser
.add_argument('-t', '--interfaces-format',
256 dest
='interfacesfileformat',
258 choices
=['native', 'json'],
259 help='interfaces file format')
260 argparser
.add_argument('-T', '--type',
263 choices
=['iface', 'vlan'],
264 help='type of interface entry (iface or vlan).' +
265 'This option can be used in case of ambiguity between ' +
266 'a vlan interface and an iface interface of the same name')
268 def update_ifupdown_argparser(argparser
):
269 """ common arg parser for ifup and ifdown """
270 argparser
.add_argument('-f', '--force', dest
='force',
272 help='force run all operations')
273 argparser
.add_argument('-l', '--syslog', dest
='syslog',
275 help=argparse
.SUPPRESS
)
276 group
= argparser
.add_mutually_exclusive_group(required
=False)
277 group
.add_argument('-n', '--no-act', dest
='noact',
278 action
='store_true', help='print out what would happen,' +
280 group
.add_argument('-p', '--print-dependency',
281 dest
='printdependency', choices
=['list', 'dot'],
282 help='print iface dependency')
283 group
.add_argument('--no-scripts', '--admin-state',
284 dest
='noaddons', action
='store_true',
285 help='dont run any addon modules/scripts. Only bring the ' +
286 'interface administratively up/down')
288 def update_ifup_argparser(argparser
):
289 argparser
.add_argument('-s', '--syntax-check', dest
='syntaxcheck',
291 help='Only run the interfaces file parser')
292 argparser
.add_argument('-k', '--skip-upperifaces', dest
='skipupperifaces',
294 help='ifup by default tries to add newly created interfaces' +
295 ' into its upper/parent interfaces. Eg. if a bridge port is' +
296 ' created as a result of ifup on the port, ifup automatically' +
297 ' adds the port to the bridge. This option can be used to ' +
298 'disable this default behaviour')
299 update_ifupdown_argparser(argparser
)
301 def update_ifdown_argparser(argparser
):
302 update_ifupdown_argparser(argparser
)
303 argparser
.add_argument('-u', '--use-current-config',
304 dest
='usecurrentconfig', action
='store_true',
305 help='By default ifdown looks at the saved state for ' +
306 'interfaces to bring down. This option allows ifdown to ' +
307 'look at the current interfaces file. Useful when your ' +
308 'state file is corrupted or you want down to use the latest '
309 'from the interfaces file')
311 def update_ifquery_argparser(argparser
):
312 """ arg parser for ifquery options """
314 # -l is same as '-a', only here for backward compatibility
315 argparser
.add_argument('-l', '--list', action
='store_true', dest
='list',
316 help='list all matching known interfaces')
317 group
= argparser
.add_mutually_exclusive_group(required
=False)
318 group
.add_argument('-r', '--running', dest
='running',
320 help='query running state of an interface')
321 group
.add_argument('-c', '--check', dest
='checkcurr',
323 help='check interface file contents against ' +
324 'running state of an interface')
325 group
.add_argument('-x', '--raw', action
='store_true', dest
='raw',
326 help='print raw config file entries')
327 group
.add_argument('--print-savedstate', action
='store_true',
328 dest
='printsavedstate',
329 help=argparse
.SUPPRESS
)
330 argparser
.add_argument('-o', '--format', dest
='format', default
='native',
331 choices
=['native', 'json'],
332 help='interface display format')
333 argparser
.add_argument('-p', '--print-dependency',
334 dest
='printdependency', choices
=['list', 'dot'],
335 help='print interface dependency')
336 argparser
.add_argument('-s', '--syntax-help', action
='store_true',
338 help='print supported interface config syntax')
339 argparser
.add_argument('--with-defaults', action
='store_true',
341 help='check policy default file contents, ' +
342 'for unconfigured attributes, against ' +
343 'running state of an interface')
345 def update_ifreload_argparser(argparser
):
346 """ parser for ifreload """
347 group
= argparser
.add_mutually_exclusive_group(required
=True)
348 group
.add_argument('-a', '--all', action
='store_true',
349 help='process all interfaces marked \"auto\"')
350 group
.add_argument('-c', '--currently-up', dest
='currentlyup',
352 help='only reload auto and other interfaces that are ' +
354 group
.add_argument('--allow', dest
='CLASS',
355 help='ignore non-\"allow-CLASS\" interfaces')
356 argparser
.add_argument('iflist', metavar
='IFACE',
357 nargs
='*', help=argparse
.SUPPRESS
)
358 argparser
.add_argument('-n', '--no-act', dest
='noact',
359 action
='store_true', help='print out what would happen,' +
361 argparser
.add_argument('-v', '--verbose', dest
='verbose',
362 action
='store_true', help='verbose')
363 argparser
.add_argument('-d', '--debug', dest
='debug',
365 help='output debug info')
366 argparser
.add_argument('-w', '--with-depends', dest
='withdepends',
367 action
='store_true', help=argparse
.SUPPRESS
)
368 argparser
.add_argument('--perfmode', dest
='perfmode',
369 action
='store_true', help=argparse
.SUPPRESS
)
370 argparser
.add_argument('--nocache', dest
='nocache', action
='store_true',
371 help=argparse
.SUPPRESS
)
372 argparser
.add_argument('-X', '--exclude', dest
='excludepats',
374 help=argparse
.SUPPRESS
)
375 #argparser.add_argument('-j', '--jobs', dest='jobs', type=int,
376 # default=-1, choices=range(1,12), help=argparse.SUPPRESS)
377 #argparser.add_argument('-i', '--interfaces', dest='interfacesfile',
378 # default='/etc/network/interfaces',
379 # help='use interfaces file instead of default ' +
380 # '/etc/network/interfaces')
381 argparser
.add_argument('-u', '--use-current-config',
382 dest
='usecurrentconfig', action
='store_true',
383 help='By default ifreload looks at saved state for ' +
384 'interfaces to bring down. With this option ifreload will'
385 ' only look at the current interfaces file. Useful when your ' +
386 'state file is corrupted or you want down to use the latest '
387 'from the interfaces file')
388 argparser
.add_argument('-l', '--syslog', dest
='syslog',
390 help=argparse
.SUPPRESS
)
391 argparser
.add_argument('-f', '--force', dest
='force',
393 help='force run all operations')
394 argparser
.add_argument('-s', '--syntax-check', dest
='syntaxcheck',
396 help='Only run the interfaces file parser')
398 def update_common_argparser(argparser
):
399 ''' general parsing rules '''
401 argparser
.add_argument('-V', '--version',
403 version
='ifupdown2:%(prog)s ' + IFUPDOWN2_VERSION
,
404 help='display current ifupdown2 version')
406 def parse_args(argsv
, op
):
408 descr
= 'query interfaces (all or interface list)'
410 descr
= 'reload interface configuration.\n\n \
411 ifreload downs interfaces that were removed\n \
412 from the interfaces file and subsequently runs ifup\n \
413 on all interfaces. ifreload is non-disruptive. It will fix\n \
414 running config to match what is configured in the interfaces\n \
415 file without bringing the interface down. It may flap an interface\n\
416 for some attribute changes. Please see man ifreload\n \
419 descr
= 'interface management'
420 argparser
= argparse
.ArgumentParser(description
=descr
)
422 update_ifreload_argparser(argparser
)
424 update_argparser(argparser
)
426 update_ifup_argparser(argparser
)
428 update_ifdown_argparser(argparser
)
430 update_ifquery_argparser(argparser
)
431 update_common_argparser(argparser
)
432 argcomplete
.autocomplete(argparser
)
433 return argparser
.parse_args(argsv
)
435 handlers
= {'up' : run_up
,
438 'reload' : run_reload
}
440 def validate_args(op
, args
):
441 #if op == 'up' and args.syntaxcheck:
442 # if args.iflist or args.all:
443 # print 'ignoring interface options ..'
445 if op
== 'query' and (args
.syntaxhelp
or args
.list):
448 if not args
.all
and not args
.currentlyup
and not args
.CLASS
:
449 print '\'-a\' or \'-c\' or \'-allow\' option is required'
451 elif (not args
.iflist
and
452 not args
.all
and not args
.CLASS
):
453 print '\'-a\' option or interface list are required'
455 if args
.iflist
and args
.all
:
456 print '\'-a\' option and interface list are mutually exclusive'
458 if op
!= 'reload' and args
.CLASS
and (args
.all
or args
.iflist
):
459 print ('\'--allow\' option is mutually exclusive ' +
460 'with interface list and \'-a\'')
464 def read_config(args
):
467 with
open(configfile
, 'r') as f
:
469 configStr
= '[ifupdown2]\n' + config
470 configFP
= StringIO
.StringIO(configStr
)
471 parser
= ConfigParser
.RawConfigParser()
472 parser
.readfp(configFP
)
473 configmap_g
= dict(parser
.items('ifupdown2'))
475 # Preprocess config map
476 configval
= configmap_g
.get('multiple_vlan_aware_bridge_support', '0')
478 # if multiple bridges not allowed, set the bridge-vlan-aware
479 # attribute in the 'no_repeats' config, so that the ifupdownmain
480 # module can catch it appropriately
481 configmap_g
['no_repeats'] = {'bridge-vlan-aware' : 'yes'}
484 configval
= configmap_g
.get('link_master_slave', '0')
486 # link_master_slave is only valid when all is set
487 if hasattr(args
, 'all') and not args
.all
:
488 configmap_g
['link_master_slave'] = '0'
490 configval
= configmap_g
.get('delay_admin_state_change', '0')
492 # reset link_master_slave if delay_admin_state_change is on
493 configmap_g
['link_master_slave'] = '0'
496 """ main function """
500 if argv
[0].endswith('ifup'):
502 elif argv
[0].endswith('ifdown'):
504 elif argv
[0].endswith('ifquery'):
506 elif argv
[0].endswith('ifreload'):
509 print ('Unexpected executable.' +
510 ' Should be \'ifup\' or \'ifdown\' or \'ifquery\'')
512 # Command line arg parser
513 args
= parse_args(argv
[1:], op
)
514 if not validate_args(op
, args
):
517 if not sys
.argv
[0].endswith('ifquery') and not os
.geteuid() == 0:
518 print 'error: must be root to run this command'
521 if not sys
.argv
[0].endswith('ifquery') and not utils
.lockFile(lockfile
):
522 print 'Another instance of this program is already running.'
527 handlers
.get(op
)(args
)
531 if args
and args
.debug
:
538 #if args and not args.debug:
539 # print '\nrerun the command with \'-d\' for a detailed errormsg'
544 if __name__
== "__main__":
546 # required during boot
547 os
.putenv('PATH', ENVPATH
)
548 resource
.setrlimit(resource
.RLIMIT_CORE
, (0,0))