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