]> git.proxmox.com Git - mirror_ifupdown2.git/blame - sbin/ifupdown
Add rtnetlink api's for link creates
[mirror_ifupdown2.git] / sbin / ifupdown
CommitLineData
a6f80f0e 1#!/usr/bin/python
904908bc
RP
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#
a6f80f0e 9import sys
10import os
e6c9d007 11import argcomplete
a6f80f0e 12import argparse
14dc390d 13import ConfigParser
14import StringIO
a6f80f0e 15import logging
d40e96ee 16from ifupdown.ifupdownmain import *
17from ifupdown.utils import *
a6f80f0e 18
19lockfile="/run/network/.lock"
14dc390d 20configfile="/etc/network/ifupdown2/ifupdown2.conf"
21configmap_g=None
a6f80f0e 22logger = None
3dcc1d0e 23interfacesfileiobuf=None
03d5166b 24ENVPATH = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
a6f80f0e 25
f802fe3c 26def run_up(args):
a6f80f0e 27 logger.debug('args = %s' %str(args))
28
29 try:
739f665b 30 iflist = args.iflist
31 if len(args.iflist) == 0:
32 iflist = None
a6f80f0e 33 logger.debug('creating ifupdown object ..')
f802fe3c 34 cachearg=(False if (iflist or args.nocache or
d08d5f54 35 args.perfmode or args.noact)
36 else True)
14dc390d 37 ifupdown_handle = ifupdownMain(config=configmap_g,
38 force=args.force,
f802fe3c 39 withdepends=args.withdepends,
40 perfmode=args.perfmode,
f802fe3c 41 dryrun=args.noact,
20dd6242 42 cache=cachearg,
43 addons_enable=not args.noaddons,
14dc390d 44 statemanager_enable=not args.noaddons,
3dcc1d0e 45 interfacesfile=args.interfacesfile,
46 interfacesfileiobuf=interfacesfileiobuf,
47 interfacesfileformat=args.interfacesfileformat)
20dd6242 48 if args.noaddons:
49 ifupdown_handle.up(['up'], args.all, args.CLASS, iflist,
50 excludepats=args.excludepats,
9dce3561 51 printdependency=args.printdependency,
52 syntaxcheck=args.syntaxcheck)
20dd6242 53 else:
54 ifupdown_handle.up(['pre-up', 'up', 'post-up'],
d08d5f54 55 args.all, args.CLASS, iflist,
739f665b 56 excludepats=args.excludepats,
9dce3561 57 printdependency=args.printdependency,
58 syntaxcheck=args.syntaxcheck)
f802fe3c 59 except:
60 raise
739f665b 61
f802fe3c 62def run_down(args):
63 logger.debug('args = %s' %str(args))
64
65 try:
66 iflist = args.iflist
f802fe3c 67 logger.debug('creating ifupdown object ..')
14dc390d 68 ifupdown_handle = ifupdownMain(config=configmap_g, force=args.force,
f802fe3c 69 withdepends=args.withdepends,
70 perfmode=args.perfmode,
f802fe3c 71 dryrun=args.noact,
20dd6242 72 addons_enable=not args.noaddons,
14dc390d 73 statemanager_enable=not args.noaddons,
3dcc1d0e 74 interfacesfile=args.interfacesfile,
75 interfacesfileiobuf=interfacesfileiobuf,
76 interfacesfileformat=args.interfacesfileformat)
f802fe3c 77
78 ifupdown_handle.down(['pre-down', 'down', 'post-down'],
79 args.all, args.CLASS, iflist,
80 excludepats=args.excludepats,
5c721925 81 printdependency=args.printdependency,
82 usecurrentconfig=args.usecurrentconfig)
f802fe3c 83 except:
84 raise
85
86def run_query(args):
87 logger.debug('args = %s' %str(args))
88
89 try:
90 iflist = args.iflist
f802fe3c 91 if args.checkcurr:
92 qop='query-checkcurr'
93 elif args.running:
f802fe3c 94 qop='query-running'
95 elif args.raw:
96 qop='query-raw'
97 elif args.syntaxhelp:
98 qop = 'query-syntax'
99 elif args.printdependency:
100 qop = 'query-dependency'
5c721925 101 elif args.printsavedstate:
102 qop = 'query-savedstate'
f802fe3c 103 else:
104 qop='query'
83c1f241 105 cachearg=(False if (iflist or args.nocache or
106 args.perfmode or args.syntaxhelp or
107 (qop != 'query-checkcurr' and
108 qop != 'query-running')) else True)
c798b0f4 109 if not iflist and qop == 'query-running':
110 iflist = [i for i in os.listdir('/sys/class/net/')
111 if os.path.isdir('/sys/class/net/%s' %i)]
83c1f241 112 logger.debug('creating ifupdown object ..')
14dc390d 113 ifupdown_handle = ifupdownMain(config=configmap_g,
114 withdepends=args.withdepends,
83c1f241 115 perfmode=args.perfmode,
14dc390d 116 cache=cachearg,
3dcc1d0e 117 interfacesfile=args.interfacesfile,
118 interfacesfileiobuf=interfacesfileiobuf,
119 interfacesfileformat=args.interfacesfileformat)
83c1f241 120
f802fe3c 121 ifupdown_handle.query([qop], args.all, args.CLASS, iflist,
122 excludepats=args.excludepats,
123 printdependency=args.printdependency,
124 format=args.format)
125 except:
126 raise
127
f802fe3c 128def run_reload(args):
129 logger.debug('args = %s' %str(args))
130
131 try:
132 logger.debug('creating ifupdown object ..')
14dc390d 133 ifupdown_handle = ifupdownMain(config=configmap_g,
134 withdepends=args.withdepends,
135 perfmode=args.perfmode)
20dd6242 136 ifupdown_handle.reload(['pre-up', 'up', 'post-up'],
137 ['pre-down', 'down', 'post-down'],
138 args.all, None, None,
14dc390d 139 excludepats=args.excludepats,
140 usecurrentconfig=args.usecurrentconfig)
a6f80f0e 141 except:
142 raise
143
a6f80f0e 144def init(args):
145 global logger
3dcc1d0e 146 global interfacesfileiobuf
a6f80f0e 147
148 log_level = logging.WARNING
fe0a57d3 149 if args.verbose:
a6f80f0e 150 log_level = logging.INFO
fe0a57d3 151 if args.debug:
a6f80f0e 152 log_level = logging.DEBUG
153
154 try:
155 logging.basicConfig(level=log_level,
eab25b7c 156 format='%(levelname)s: %(message)s')
c778afeb 157 logging.addLevelName(logging.ERROR, 'error')
158 logging.addLevelName(logging.WARNING, 'warning')
159 logging.addLevelName(logging.DEBUG, 'debug')
160 logging.addLevelName(logging.INFO, 'info')
a6f80f0e 161 logger = logging.getLogger('ifupdown')
162 except:
163 raise
164
3dcc1d0e 165 # If interfaces file is stdin, read
166 if hasattr(args, 'interfacesfile') and args.interfacesfile == '-':
167 interfacesfileiobuf = sys.stdin.read()
a6f80f0e 168
169def deinit():
eab25b7c 170 {}
a6f80f0e 171
172def update_argparser(argparser):
cca03c30 173 """ base parser, common to all commands """
37c0543d 174
175 argparser.add_argument('-a', '--all', action='store_true', required=False,
cca03c30 176 help='process all interfaces marked \"auto\"')
a6f80f0e 177 argparser.add_argument('iflist', metavar='IFACE',
f802fe3c 178 nargs='*', help='interface list separated by spaces. ' +
179 'IFACE list is mutually exclusive with -a option.')
a6f80f0e 180 argparser.add_argument('-v', '--verbose', dest='verbose',
181 action='store_true', help='verbose')
182 argparser.add_argument('-d', '--debug', dest='debug',
183 action='store_true',
184 help='output debug info')
185 argparser.add_argument('-q', '--quiet', dest='quiet',
186 action='store_true',
187 help=argparse.SUPPRESS)
eab25b7c 188 argparser.add_argument('--allow', dest='CLASS',
189 help='ignore non-\"allow-CLASS\" interfaces')
14dc390d 190 argparser.add_argument('-w', '--with-depends', dest='withdepends',
f802fe3c 191 action='store_true', help='run with all dependent interfaces.'+
192 ' This option is redundant when \'-a\' is specified. With ' +
193 '\'-a\' interfaces are always executed in dependency order')
3e8ee54f 194 argparser.add_argument('--perfmode', dest='perfmode',
eab25b7c 195 action='store_true', help=argparse.SUPPRESS)
14dc390d 196 #argparser.add_argument('-j', '--jobs', dest='jobs', type=int,
197 # default=-1, choices=range(1,12), help=argparse.SUPPRESS)
739f665b 198 argparser.add_argument('--nocache', dest='nocache', action='store_true',
199 help=argparse.SUPPRESS)
3e8ee54f 200 argparser.add_argument('-X', '--exclude', dest='excludepats',
37c0543d 201 action='append',
202 help='Exclude interfaces from the list of interfaces' +
f802fe3c 203 ' to operate on. Can be specified multiple times.')
14dc390d 204 argparser.add_argument('-i', '--interfaces', dest='interfacesfile',
205 default='/etc/network/interfaces',
206 help='use interfaces file instead of default ' +
207 '/etc/network/interfaces')
3dcc1d0e 208 argparser.add_argument('-t', '--interfaces-format',
209 dest='interfacesfileformat',
210 default='native',
211 choices=['native', 'json'],
212 help='interfaces file format')
a6f80f0e 213
214def update_ifupdown_argparser(argparser):
cca03c30 215 """ common arg parser for ifup and ifdown """
a6f80f0e 216 argparser.add_argument('-f', '--force', dest='force',
217 action='store_true',
218 help='force run all operations')
5c721925 219 group = argparser.add_mutually_exclusive_group(required=False)
220 group.add_argument('-n', '--no-act', dest='noact',
3e8ee54f 221 action='store_true', help='print out what would happen,' +
222 'but don\'t do it')
14dc390d 223 group.add_argument('-p', '--print-dependency',
cca03c30 224 dest='printdependency', choices=['list', 'dot'],
225 help='print iface dependency')
d40e96ee 226 group.add_argument('--no-scripts', '--admin-state',
20dd6242 227 dest='noaddons', action='store_true',
14dc390d 228 help='dont run any addon modules/scripts. Only bring the ' +
229 'interface administratively up/down')
a6f80f0e 230
231def update_ifup_argparser(argparser):
9dce3561 232 argparser.add_argument('-s', '--syntax-check', dest='syntaxcheck',
233 action='store_true',
234 help='Only run the interfaces file parser')
a6f80f0e 235 update_ifupdown_argparser(argparser)
236
237def update_ifdown_argparser(argparser):
238 update_ifupdown_argparser(argparser)
522bf8e6 239 argparser.add_argument('-u', '--use-current-config',
5c721925 240 dest='usecurrentconfig', action='store_true',
14dc390d 241 help='By default ifdown looks at the saved state for ' +
242 'interfaces to bring down. This option allows ifdown to ' +
243 'look at the current interfaces file. Useful when your ' +
244 'state file is corrupted or you want down to use the latest '
245 'from the interfaces file')
a6f80f0e 246
247def update_ifquery_argparser(argparser):
cca03c30 248 """ arg parser for ifquery options """
249
37c0543d 250 # -l is same as '-a', only here for backward compatibility
3e8ee54f 251 argparser.add_argument('-l', '--list', action='store_true', dest='all',
cca03c30 252 help=argparse.SUPPRESS)
a6f80f0e 253 group = argparser.add_mutually_exclusive_group(required=False)
360d5f8e 254 group.add_argument('-r', '--running', dest='running',
eab25b7c 255 action='store_true',
256 help='query running state of an interface')
360d5f8e 257 group.add_argument('-c', '--check', dest='checkcurr',
739f665b 258 action='store_true',
360d5f8e 259 help='check interface file contents against ' +
260 'running state of an interface')
51a80991 261 group.add_argument('-x', '--raw', action='store_true', dest='raw',
d08d5f54 262 help='print raw config file entries')
5c721925 263 group.add_argument('--print-savedstate', action='store_true',
264 dest='printsavedstate',
265 help=argparse.SUPPRESS)
522bf8e6 266 argparser.add_argument('-o', '--format', dest='format', default='native',
14dc390d 267 choices=['native', 'json'],
268 help='interface display format')
269 argparser.add_argument('-p', '--print-dependency',
d08d5f54 270 dest='printdependency', choices=['list', 'dot'],
271 help='print interface dependency')
14dc390d 272 argparser.add_argument('-s', '--syntax-help', action='store_true',
d08d5f54 273 dest='syntaxhelp',
274 help='print supported interface config syntax')
37c0543d 275
739f665b 276def update_ifreload_argparser(argparser):
f802fe3c 277 """ parser for ifreload """
278 argparser.add_argument('-a', '--all', action='store_true', required=True,
279 help='process all interfaces marked \"auto\"')
280 argparser.add_argument('iflist', metavar='IFACE',
281 nargs='*', help=argparse.SUPPRESS)
282 argparser.add_argument('-n', '--no-act', dest='noact',
283 action='store_true', help=argparse.SUPPRESS)
284 argparser.add_argument('-v', '--verbose', dest='verbose',
285 action='store_true', help='verbose')
286 argparser.add_argument('-d', '--debug', dest='debug',
37c0543d 287 action='store_true',
f802fe3c 288 help='output debug info')
14dc390d 289 argparser.add_argument('-w', '--with-depends', dest='withdepends',
f802fe3c 290 action='store_true', help=argparse.SUPPRESS)
291 argparser.add_argument('--perfmode', dest='perfmode',
292 action='store_true', help=argparse.SUPPRESS)
293 argparser.add_argument('--nocache', dest='nocache', action='store_true',
294 help=argparse.SUPPRESS)
295 argparser.add_argument('-X', '--exclude', dest='excludepats',
296 action='append',
297 help=argparse.SUPPRESS)
14dc390d 298 #argparser.add_argument('-j', '--jobs', dest='jobs', type=int,
299 # default=-1, choices=range(1,12), help=argparse.SUPPRESS)
3dcc1d0e 300 #argparser.add_argument('-i', '--interfaces', dest='interfacesfile',
301 # default='/etc/network/interfaces',
302 # help='use interfaces file instead of default ' +
303 # '/etc/network/interfaces')
522bf8e6 304 argparser.add_argument('-u', '--use-current-config',
14dc390d 305 dest='usecurrentconfig', action='store_true',
306 help='By default ifreload looks at saved state for ' +
307 'interfaces to bring down. With this option ifreload will'
308 ' only look at the current interfaces file. Useful when your ' +
309 'state file is corrupted or you want down to use the latest '
310 'from the interfaces file')
37c0543d 311
a6f80f0e 312def parse_args(argsv, op):
cca03c30 313 if op == 'query':
37c0543d 314 descr = 'query interfaces (all or interface list)'
91067b3d 315 elif op == 'reload':
316 descr = 'reload interface configuration.'
cca03c30 317 else:
318 descr = 'interface management'
a6f80f0e 319 argparser = argparse.ArgumentParser(description=descr)
f802fe3c 320 if op == 'reload':
739f665b 321 update_ifreload_argparser(argparser)
f802fe3c 322 else:
323 update_argparser(argparser)
324 if op == 'up':
325 update_ifup_argparser(argparser)
326 elif op == 'down':
327 update_ifdown_argparser(argparser)
328 elif op == 'query':
329 update_ifquery_argparser(argparser)
330 elif op == 'reload':
331 update_ifreload_argparser(argparser)
e6c9d007 332 argcomplete.autocomplete(argparser)
a6f80f0e 333 return argparser.parse_args(argsv)
334
f802fe3c 335handlers = {'up' : run_up,
336 'down' : run_down,
337 'query' : run_query,
338 'reload' : run_reload }
339
9dce3561 340def validate_args(op, args):
3dcc1d0e 341 #if op == 'up' and args.syntaxcheck:
342 # if args.iflist or args.all:
343 # print 'ignoring interface options ..'
344 # return True
9dce3561 345 if op == 'query' and args.syntaxhelp:
346 return True
fffdae9c
RP
347 if op == 'reload':
348 if not args.all:
349 print '\'-a\' option is required'
350 return False
351 elif (not args.iflist and
352 not args.all and not args.CLASS):
9dce3561 353 print '\'-a\' option or interface list are required'
354 return False
355 if args.iflist and args.all:
356 print '\'-a\' option and interface list are mutually exclusive'
357 return False
fffdae9c 358 if op != 'reload' and args.CLASS and (args.all or args.iflist):
5ee3e1a8
RP
359 print ('\'--allow\' option is mutually exclusive ' +
360 'with interface list and \'-a\'')
361 return False
9dce3561 362 return True
363
14dc390d 364def read_config():
365 global configmap_g
366
367 config = open(configfile, 'r').read()
368 configStr = '[ifupdown2]\n' + config
369 configFP = StringIO.StringIO(configStr)
370 parser = ConfigParser.RawConfigParser()
371 parser.readfp(configFP)
372 configmap_g = dict(parser.items('ifupdown2'))
373
a6f80f0e 374def main(argv):
375 """ main function """
f802fe3c 376 args = None
a6f80f0e 377 try:
378 op = None
fe0a57d3 379 if argv[0].endswith('ifup'):
a6f80f0e 380 op = 'up'
fe0a57d3 381 elif argv[0].endswith('ifdown'):
a6f80f0e 382 op = 'down'
fe0a57d3 383 elif argv[0].endswith('ifquery'):
a6f80f0e 384 op = 'query'
fe0a57d3 385 elif argv[0].endswith('ifreload'):
739f665b 386 op = 'reload'
a6f80f0e 387 else:
388 print ('Unexpected executable.' +
389 ' Should be \'ifup\' or \'ifdown\' or \'ifquery\'')
390 exit(1)
a6f80f0e 391 # Command line arg parser
392 args = parse_args(argv[1:], op)
9dce3561 393 if not validate_args(op, args):
a6f80f0e 394 exit(1)
522bf8e6
RP
395
396 if not sys.argv[0].endswith('ifquery') and not os.geteuid() == 0:
397 print 'error: must be root to run this command'
398 exit(1)
399
400 if not sys.argv[0].endswith('ifquery') and not utils.lockFile(lockfile):
401 print 'Another instance of this program is already running.'
402 exit(0)
403
14dc390d 404 read_config()
a6f80f0e 405 init(args)
f802fe3c 406 handlers.get(op)(args)
a6f80f0e 407 except Exception, e:
fe0a57d3 408 if not str(e):
eab25b7c 409 exit(1)
f802fe3c 410 if args and args.debug:
a6f80f0e 411 raise
412 else:
f802fe3c 413 if logger:
414 logger.error(str(e))
415 else:
416 print str(e)
86fc62e2 417 #if args and not args.debug:
418 # print '\nrerun the command with \'-d\' for a detailed errormsg'
eab25b7c 419 exit(1)
a6f80f0e 420 finally:
421 deinit()
422
a6f80f0e 423if __name__ == "__main__":
424
d40e96ee 425
03d5166b 426 # required during boot
427 os.putenv('PATH', ENVPATH)
a6f80f0e 428 main(sys.argv)