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