]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown2/sbin/ifupdown
Merge 'vlan filtering bridge + vxlan + mlag + vrr' support from internal
[mirror_ifupdown2.git] / ifupdown2 / sbin / ifupdown
CommitLineData
2c8c4ce7
RP
1#!/usr/bin/python
2#
3# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4# Author: Roopa Prabhu, roopa@cumulusnetworks.com
5#
6# ifupdown --
7# tool to configure network interfaces
8#
9import sys
10import os
11import argcomplete
12import argparse
13import ConfigParser
14import StringIO
15import logging
f82758bf
RP
16import logging.handlers
17import resource
2c8c4ce7
RP
18from ifupdown.ifupdownmain import *
19from ifupdown.utils import *
20
21lockfile="/run/network/.lock"
22configfile="/etc/network/ifupdown2/ifupdown2.conf"
23configmap_g=None
24logger = None
25interfacesfileiobuf=None
26ENVPATH = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
27
28def run_up(args):
29 logger.debug('args = %s' %str(args))
30
31 try:
32 iflist = args.iflist
33 if len(args.iflist) == 0:
34 iflist = None
35 logger.debug('creating ifupdown object ..')
36 cachearg=(False if (iflist or args.nocache or
37 args.perfmode or args.noact)
38 else True)
39 ifupdown_handle = ifupdownMain(config=configmap_g,
40 force=args.force,
41 withdepends=args.withdepends,
42 perfmode=args.perfmode,
43 dryrun=args.noact,
44 cache=cachearg,
45 addons_enable=not args.noaddons,
46 statemanager_enable=not args.noaddons,
47 interfacesfile=args.interfacesfile,
48 interfacesfileiobuf=interfacesfileiobuf,
49 interfacesfileformat=args.interfacesfileformat)
50 if args.noaddons:
51 ifupdown_handle.up(['up'], args.all, args.CLASS, iflist,
52 excludepats=args.excludepats,
53 printdependency=args.printdependency,
f82758bf
RP
54 syntaxcheck=args.syntaxcheck, type=args.type,
55 skipupperifaces=args.skipupperifaces)
2c8c4ce7
RP
56 else:
57 ifupdown_handle.up(['pre-up', 'up', 'post-up'],
58 args.all, args.CLASS, iflist,
59 excludepats=args.excludepats,
60 printdependency=args.printdependency,
f82758bf
RP
61 syntaxcheck=args.syntaxcheck, type=args.type,
62 skipupperifaces=args.skipupperifaces)
2c8c4ce7
RP
63 except:
64 raise
65
66def run_down(args):
67 logger.debug('args = %s' %str(args))
68
69 try:
70 iflist = args.iflist
71 logger.debug('creating ifupdown object ..')
72 ifupdown_handle = ifupdownMain(config=configmap_g, force=args.force,
73 withdepends=args.withdepends,
74 perfmode=args.perfmode,
75 dryrun=args.noact,
76 addons_enable=not args.noaddons,
77 statemanager_enable=not args.noaddons,
78 interfacesfile=args.interfacesfile,
79 interfacesfileiobuf=interfacesfileiobuf,
80 interfacesfileformat=args.interfacesfileformat)
81
82 ifupdown_handle.down(['pre-down', 'down', 'post-down'],
83 args.all, args.CLASS, iflist,
84 excludepats=args.excludepats,
85 printdependency=args.printdependency,
f82758bf
RP
86 usecurrentconfig=args.usecurrentconfig,
87 type=args.type)
2c8c4ce7
RP
88 except:
89 raise
90
91def run_query(args):
92 logger.debug('args = %s' %str(args))
93
94 try:
95 iflist = args.iflist
96 if args.checkcurr:
97 qop='query-checkcurr'
98 elif args.running:
99 qop='query-running'
100 elif args.raw:
101 qop='query-raw'
102 elif args.syntaxhelp:
103 qop = 'query-syntax'
104 elif args.printdependency:
105 qop = 'query-dependency'
106 elif args.printsavedstate:
107 qop = 'query-savedstate'
108 else:
109 qop='query'
110 cachearg=(False if (iflist or args.nocache or
111 args.perfmode or args.syntaxhelp or
112 (qop != 'query-checkcurr' and
113 qop != 'query-running')) else True)
114 if not iflist and qop == 'query-running':
115 iflist = [i for i in os.listdir('/sys/class/net/')
116 if os.path.isdir('/sys/class/net/%s' %i)]
117 logger.debug('creating ifupdown object ..')
118 ifupdown_handle = ifupdownMain(config=configmap_g,
119 withdepends=args.withdepends,
120 perfmode=args.perfmode,
121 cache=cachearg,
122 interfacesfile=args.interfacesfile,
123 interfacesfileiobuf=interfacesfileiobuf,
124 interfacesfileformat=args.interfacesfileformat)
125
126 ifupdown_handle.query([qop], args.all, args.CLASS, iflist,
127 excludepats=args.excludepats,
128 printdependency=args.printdependency,
f82758bf 129 format=args.format, type=args.type)
2c8c4ce7
RP
130 except:
131 raise
132
133def run_reload(args):
134 logger.debug('args = %s' %str(args))
135
136 try:
137 logger.debug('creating ifupdown object ..')
138 ifupdown_handle = ifupdownMain(config=configmap_g,
139 withdepends=args.withdepends,
140 perfmode=args.perfmode)
141 ifupdown_handle.reload(['pre-up', 'up', 'post-up'],
142 ['pre-down', 'down', 'post-down'],
f82758bf 143 auto=args.all, allow=None, ifacenames=None,
2c8c4ce7 144 excludepats=args.excludepats,
f82758bf
RP
145 usecurrentconfig=args.usecurrentconfig,
146 currentlyup=args.currentlyup)
2c8c4ce7
RP
147 except:
148 raise
149
150def init(args):
151 global logger
152 global interfacesfileiobuf
153
154 log_level = logging.WARNING
155 if args.verbose:
156 log_level = logging.INFO
157 if args.debug:
158 log_level = logging.DEBUG
159
160 try:
f82758bf
RP
161 if hasattr(args, 'syslog') and args.syslog:
162 root_logger = logging.getLogger()
163 syslog_handler = logging.handlers.SysLogHandler(address='/dev/log',
164 facility=logging.handlers.SysLogHandler.LOG_DAEMON)
165 logging.addLevelName(logging.ERROR, 'error')
166 logging.addLevelName(logging.WARNING, 'warning')
167 logging.addLevelName(logging.DEBUG, 'debug')
168 logging.addLevelName(logging.INFO, 'info')
169 root_logger.setLevel(log_level)
170 syslog_handler.setFormatter(logging.Formatter(
171 '%(name)s: %(levelname)s: %(message)s'))
172 root_logger.addHandler(syslog_handler)
173 logger = logging.getLogger('ifupdown')
174 else:
175 logging.basicConfig(level=log_level,
176 format='%(levelname)s: %(message)s')
177 logging.addLevelName(logging.ERROR, 'error')
178 logging.addLevelName(logging.WARNING, 'warning')
179 logging.addLevelName(logging.DEBUG, 'debug')
180 logging.addLevelName(logging.INFO, 'info')
181 logger = logging.getLogger('ifupdown')
2c8c4ce7
RP
182 except:
183 raise
184
185 # If interfaces file is stdin, read
186 if hasattr(args, 'interfacesfile') and args.interfacesfile == '-':
187 interfacesfileiobuf = sys.stdin.read()
188
189def deinit():
190 {}
191
192def update_argparser(argparser):
193 """ base parser, common to all commands """
194
195 argparser.add_argument('-a', '--all', action='store_true', required=False,
196 help='process all interfaces marked \"auto\"')
197 argparser.add_argument('iflist', metavar='IFACE',
198 nargs='*', help='interface list separated by spaces. ' +
199 'IFACE list is mutually exclusive with -a option.')
200 argparser.add_argument('-v', '--verbose', dest='verbose',
201 action='store_true', help='verbose')
202 argparser.add_argument('-d', '--debug', dest='debug',
203 action='store_true',
204 help='output debug info')
205 argparser.add_argument('-q', '--quiet', dest='quiet',
206 action='store_true',
207 help=argparse.SUPPRESS)
208 argparser.add_argument('--allow', dest='CLASS',
209 help='ignore non-\"allow-CLASS\" interfaces')
210 argparser.add_argument('-w', '--with-depends', dest='withdepends',
211 action='store_true', help='run with all dependent interfaces.'+
212 ' This option is redundant when \'-a\' is specified. With ' +
213 '\'-a\' interfaces are always executed in dependency order')
214 argparser.add_argument('--perfmode', dest='perfmode',
215 action='store_true', help=argparse.SUPPRESS)
216 #argparser.add_argument('-j', '--jobs', dest='jobs', type=int,
217 # default=-1, choices=range(1,12), help=argparse.SUPPRESS)
218 argparser.add_argument('--nocache', dest='nocache', action='store_true',
219 help=argparse.SUPPRESS)
220 argparser.add_argument('-X', '--exclude', dest='excludepats',
221 action='append',
222 help='Exclude interfaces from the list of interfaces' +
223 ' to operate on. Can be specified multiple times.')
224 argparser.add_argument('-i', '--interfaces', dest='interfacesfile',
225 default='/etc/network/interfaces',
226 help='use interfaces file instead of default ' +
227 '/etc/network/interfaces')
228 argparser.add_argument('-t', '--interfaces-format',
229 dest='interfacesfileformat',
230 default='native',
231 choices=['native', 'json'],
232 help='interfaces file format')
f82758bf
RP
233 argparser.add_argument('-T', '--type',
234 dest='type',
235 default=None,
236 choices=['iface', 'vlan'],
237 help='type of interface entry (iface or vlan).' +
238 'This option can be used in case of ambiguity between ' +
239 'a vlan interface and an iface interface of the same name')
2c8c4ce7
RP
240
241def update_ifupdown_argparser(argparser):
242 """ common arg parser for ifup and ifdown """
243 argparser.add_argument('-f', '--force', dest='force',
244 action='store_true',
245 help='force run all operations')
f82758bf
RP
246 argparser.add_argument('-l', '--syslog', dest='syslog',
247 action='store_true',
248 help=argparse.SUPPRESS)
2c8c4ce7
RP
249 group = argparser.add_mutually_exclusive_group(required=False)
250 group.add_argument('-n', '--no-act', dest='noact',
251 action='store_true', help='print out what would happen,' +
252 'but don\'t do it')
253 group.add_argument('-p', '--print-dependency',
254 dest='printdependency', choices=['list', 'dot'],
255 help='print iface dependency')
256 group.add_argument('--no-scripts', '--admin-state',
257 dest='noaddons', action='store_true',
258 help='dont run any addon modules/scripts. Only bring the ' +
259 'interface administratively up/down')
260
261def update_ifup_argparser(argparser):
262 argparser.add_argument('-s', '--syntax-check', dest='syntaxcheck',
263 action='store_true',
264 help='Only run the interfaces file parser')
f82758bf
RP
265 argparser.add_argument('-k', '--skip-upperifaces', dest='skipupperifaces',
266 action='store_true',
267 help='ifup by default tries to add newly created interfaces' +
268 ' into its upper/parent interfaces. Eg. if a bridge port is' +
269 ' created as a result of ifup on the port, ifup automatically' +
270 ' adds the port to the bridge. This option can be used to ' +
271 'disable this default behaviour')
2c8c4ce7
RP
272 update_ifupdown_argparser(argparser)
273
274def update_ifdown_argparser(argparser):
275 update_ifupdown_argparser(argparser)
276 argparser.add_argument('-u', '--use-current-config',
277 dest='usecurrentconfig', action='store_true',
278 help='By default ifdown looks at the saved state for ' +
279 'interfaces to bring down. This option allows ifdown to ' +
280 'look at the current interfaces file. Useful when your ' +
281 'state file is corrupted or you want down to use the latest '
282 'from the interfaces file')
283
284def update_ifquery_argparser(argparser):
285 """ arg parser for ifquery options """
286
287 # -l is same as '-a', only here for backward compatibility
288 argparser.add_argument('-l', '--list', action='store_true', dest='all',
289 help=argparse.SUPPRESS)
290 group = argparser.add_mutually_exclusive_group(required=False)
291 group.add_argument('-r', '--running', dest='running',
292 action='store_true',
293 help='query running state of an interface')
294 group.add_argument('-c', '--check', dest='checkcurr',
295 action='store_true',
296 help='check interface file contents against ' +
297 'running state of an interface')
298 group.add_argument('-x', '--raw', action='store_true', dest='raw',
299 help='print raw config file entries')
300 group.add_argument('--print-savedstate', action='store_true',
301 dest='printsavedstate',
302 help=argparse.SUPPRESS)
303 argparser.add_argument('-o', '--format', dest='format', default='native',
304 choices=['native', 'json'],
305 help='interface display format')
306 argparser.add_argument('-p', '--print-dependency',
307 dest='printdependency', choices=['list', 'dot'],
308 help='print interface dependency')
309 argparser.add_argument('-s', '--syntax-help', action='store_true',
310 dest='syntaxhelp',
311 help='print supported interface config syntax')
312
313def update_ifreload_argparser(argparser):
314 """ parser for ifreload """
f82758bf
RP
315 group = argparser.add_mutually_exclusive_group(required=True)
316 group.add_argument('-a', '--all', action='store_true',
2c8c4ce7 317 help='process all interfaces marked \"auto\"')
f82758bf
RP
318 group.add_argument('-c', '--currently-up', dest='currentlyup',
319 action='store_true',
320 help='only reload auto and other interfaces that are ' +
321 'currently up')
2c8c4ce7
RP
322 argparser.add_argument('iflist', metavar='IFACE',
323 nargs='*', help=argparse.SUPPRESS)
324 argparser.add_argument('-n', '--no-act', dest='noact',
325 action='store_true', help=argparse.SUPPRESS)
326 argparser.add_argument('-v', '--verbose', dest='verbose',
327 action='store_true', help='verbose')
328 argparser.add_argument('-d', '--debug', dest='debug',
329 action='store_true',
330 help='output debug info')
331 argparser.add_argument('-w', '--with-depends', dest='withdepends',
332 action='store_true', help=argparse.SUPPRESS)
333 argparser.add_argument('--perfmode', dest='perfmode',
334 action='store_true', help=argparse.SUPPRESS)
335 argparser.add_argument('--nocache', dest='nocache', action='store_true',
336 help=argparse.SUPPRESS)
337 argparser.add_argument('-X', '--exclude', dest='excludepats',
338 action='append',
339 help=argparse.SUPPRESS)
340 #argparser.add_argument('-j', '--jobs', dest='jobs', type=int,
341 # default=-1, choices=range(1,12), help=argparse.SUPPRESS)
342 #argparser.add_argument('-i', '--interfaces', dest='interfacesfile',
343 # default='/etc/network/interfaces',
344 # help='use interfaces file instead of default ' +
345 # '/etc/network/interfaces')
346 argparser.add_argument('-u', '--use-current-config',
347 dest='usecurrentconfig', action='store_true',
348 help='By default ifreload looks at saved state for ' +
349 'interfaces to bring down. With this option ifreload will'
350 ' only look at the current interfaces file. Useful when your ' +
351 'state file is corrupted or you want down to use the latest '
352 'from the interfaces file')
f82758bf
RP
353 argparser.add_argument('-l', '--syslog', dest='syslog',
354 action='store_true',
355 help=argparse.SUPPRESS)
356 argparser.add_argument('-f', '--force', dest='force',
357 action='store_true',
358 help='force run all operations')
2c8c4ce7
RP
359
360def parse_args(argsv, op):
361 if op == 'query':
362 descr = 'query interfaces (all or interface list)'
363 elif op == 'reload':
364 descr = 'reload interface configuration.'
365 else:
366 descr = 'interface management'
367 argparser = argparse.ArgumentParser(description=descr)
368 if op == 'reload':
369 update_ifreload_argparser(argparser)
370 else:
371 update_argparser(argparser)
372 if op == 'up':
373 update_ifup_argparser(argparser)
374 elif op == 'down':
375 update_ifdown_argparser(argparser)
376 elif op == 'query':
377 update_ifquery_argparser(argparser)
378 elif op == 'reload':
379 update_ifreload_argparser(argparser)
380 argcomplete.autocomplete(argparser)
381 return argparser.parse_args(argsv)
382
383handlers = {'up' : run_up,
384 'down' : run_down,
385 'query' : run_query,
386 'reload' : run_reload }
387
388def validate_args(op, args):
389 #if op == 'up' and args.syntaxcheck:
390 # if args.iflist or args.all:
391 # print 'ignoring interface options ..'
392 # return True
393 if op == 'query' and args.syntaxhelp:
394 return True
395 if op == 'reload':
f82758bf
RP
396 if not args.all and not args.currentlyup:
397 print '\'-a\' or \'-c\' option is required'
2c8c4ce7
RP
398 return False
399 elif (not args.iflist and
400 not args.all and not args.CLASS):
401 print '\'-a\' option or interface list are required'
402 return False
403 if args.iflist and args.all:
404 print '\'-a\' option and interface list are mutually exclusive'
405 return False
406 if op != 'reload' and args.CLASS and (args.all or args.iflist):
407 print ('\'--allow\' option is mutually exclusive ' +
408 'with interface list and \'-a\'')
409 return False
410 return True
411
f82758bf 412def read_config(args):
2c8c4ce7
RP
413 global configmap_g
414
415 config = open(configfile, 'r').read()
416 configStr = '[ifupdown2]\n' + config
417 configFP = StringIO.StringIO(configStr)
418 parser = ConfigParser.RawConfigParser()
419 parser.readfp(configFP)
420 configmap_g = dict(parser.items('ifupdown2'))
421
f82758bf
RP
422 # Preprocess config map
423 configval = configmap_g.get('multiple_vlan_aware_bridge_support', '0')
424 if configval == '0':
425 # if multiple bridges not allowed, set the bridge-vlan-aware
426 # attribute in the 'no_repeats' config, so that the ifupdownmain
427 # module can catch it appropriately
428 configmap_g['no_repeats'] = {'bridge-vlan-aware' : 'yes'}
429
430
431 configval = configmap_g.get('link_master_slave', '0')
432 if configval == '1':
433 # link_master_slave is only valid when all is set
434 if hasattr(args, 'all') and not args.all:
435 configmap_g['link_master_slave'] = '0'
436
437 configval = configmap_g.get('delay_admin_state_change', '0')
438 if configval == '1':
439 # reset link_master_slave if delay_admin_state_change is on
440 configmap_g['link_master_slave'] = '0'
441
2c8c4ce7
RP
442def main(argv):
443 """ main function """
444 args = None
445 try:
446 op = None
447 if argv[0].endswith('ifup'):
448 op = 'up'
449 elif argv[0].endswith('ifdown'):
450 op = 'down'
451 elif argv[0].endswith('ifquery'):
452 op = 'query'
453 elif argv[0].endswith('ifreload'):
454 op = 'reload'
455 else:
456 print ('Unexpected executable.' +
457 ' Should be \'ifup\' or \'ifdown\' or \'ifquery\'')
458 exit(1)
459 # Command line arg parser
460 args = parse_args(argv[1:], op)
461 if not validate_args(op, args):
462 exit(1)
463
464 if not sys.argv[0].endswith('ifquery') and not os.geteuid() == 0:
465 print 'error: must be root to run this command'
466 exit(1)
467
468 if not sys.argv[0].endswith('ifquery') and not utils.lockFile(lockfile):
469 print 'Another instance of this program is already running.'
470 exit(0)
471
f82758bf 472 read_config(args)
2c8c4ce7
RP
473 init(args)
474 handlers.get(op)(args)
475 except Exception, e:
476 if not str(e):
477 exit(1)
478 if args and args.debug:
479 raise
480 else:
481 if logger:
482 logger.error(str(e))
483 else:
484 print str(e)
485 #if args and not args.debug:
486 # print '\nrerun the command with \'-d\' for a detailed errormsg'
487 exit(1)
488 finally:
489 deinit()
490
491if __name__ == "__main__":
492
2c8c4ce7
RP
493 # required during boot
494 os.putenv('PATH', ENVPATH)
f82758bf 495 resource.setrlimit(resource.RLIMIT_CORE, (0,0))
2c8c4ce7 496 main(sys.argv)