]> git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdown2/ifupdown/argv.py
ifupdown2 2.0.0 release
[mirror_ifupdown2.git] / ifupdown2 / ifupdown / argv.py
1 #!/usr/bin/python
2 #
3 # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved.
4 # Authors:
5 # Roopa Prabhu, roopa@cumulusnetworks.com
6 # Julien Fortin, julien@cumulusnetworks.com
7 #
8
9 import sys
10 import argparse
11 import argcomplete
12
13 try:
14 from ifupdown2.ifupdown.utils import utils
15 from ifupdown2.ifupdown.exceptions import ArgvParseError
16 except:
17 from ifupdown.utils import utils
18 from ifupdown.exceptions import ArgvParseError
19
20
21 class VersionAction(argparse.Action):
22 def __call__(self, parser, namespace, values, option_string=None):
23
24 try:
25 dpkg = utils.exec_commandl([utils.dpkg_cmd, '-l', 'ifupdown2'])
26
27 if not dpkg:
28 raise Exception('dpkg -l ifupdown2 returns without output')
29
30 dpkg = dpkg.split('\n')
31
32 if not dpkg:
33 raise Exception('dpkg -l ifupdown2 returns without output')
34
35 for line in dpkg:
36 if 'ifupdown2' in line:
37 info = line.split()
38
39 sys.stdout.write('ifupdown2:%s\n' % (info[2]))
40 sys.exit(0)
41
42 raise Exception('ifupdown2 package not found using dpkg -l')
43
44 except Exception as e:
45 sys.stderr.write('error: cannot get current version using dpkg: %s\n' % str(e))
46 sys.exit(1)
47
48
49 class Parse:
50 valid_ops = {
51 'ifup': 'up',
52 'ifdown': 'down',
53 'ifreload': 'reload',
54 'ifquery': 'query'
55 }
56
57 def __init__(self, argv):
58 self.executable_name = argv[0]
59 self.op = self.get_op()
60 self.argv = argv[1:]
61
62 if self.op == 'query':
63 descr = 'query interfaces (all or interface list)'
64 elif self.op == 'reload':
65 descr = 'reload interface configuration.'
66 else:
67 descr = 'interface management'
68 argparser = argparse.ArgumentParser(description=descr)
69 if self.op == 'reload':
70 self.update_ifreload_argparser(argparser)
71 else:
72 self.update_argparser(argparser)
73 if self.op == 'up':
74 self.update_ifup_argparser(argparser)
75 elif self.op == 'down':
76 self.update_ifdown_argparser(argparser)
77 elif self.op == 'query':
78 self.update_ifquery_argparser(argparser)
79 self.update_common_argparser(argparser)
80 argcomplete.autocomplete(argparser)
81 self.args = argparser.parse_args(self.argv)
82
83 def validate(self):
84 if self.op == 'query' and (self.args.syntaxhelp or self.args.list):
85 return True
86
87 if self.op == 'reload':
88 if not self.args.all and not self.args.currentlyup and not self.args.CLASS:
89 raise ArgvParseError("'-a' or '-c' or '-allow' option is required")
90 elif not self.args.iflist and not self.args.all and not self.args.CLASS:
91 raise ArgvParseError("'-a' option or interface list are required")
92
93 if self.args.iflist and self.args.all:
94 raise ArgvParseError("'-a' option and interface list are mutually exclusive")
95
96 if self.op != 'reload' and self.args.CLASS and self.args.all:
97 raise ArgvParseError("'--allow' option is mutually exclusive with '-a'")
98 return True
99
100 def get_op(self):
101 try:
102 for key, value in self.valid_ops.iteritems():
103 if self.executable_name.endswith(key):
104 return value
105 except:
106 raise ArgvParseError("Unexpected executable. Should be 'ifup' or 'ifdown' or 'ifquery'")
107
108 def get_args(self):
109 return self.args
110
111 def update_argparser(self, argparser):
112 """ base parser, common to all commands """
113 argparser.add_argument('-a', '--all', action='store_true', required=False,
114 help='process all interfaces marked "auto"')
115 argparser.add_argument('iflist', metavar='IFACE', nargs='*',
116 help='interface list separated by spaces. '
117 'IFACE list is mutually exclusive with -a option.')
118 argparser.add_argument('-v', '--verbose', dest='verbose', action='store_true', help='verbose')
119 argparser.add_argument('-d', '--debug', dest='debug', action='store_true', help='output debug info')
120 argparser.add_argument('-q', '--quiet', dest='quiet', action='store_true', help=argparse.SUPPRESS)
121 argparser.add_argument('--allow', dest='CLASS', action='append', help='ignore non-"allow-CLASS" interfaces')
122 argparser.add_argument('-w', '--with-depends', dest='withdepends', action='store_true',
123 help="run with all dependent interfaces. "
124 "This option is redundant when '-a' is specified. "
125 "With '-a' interfaces are always executed in dependency order")
126 argparser.add_argument('--perfmode', dest='perfmode', action='store_true', help=argparse.SUPPRESS)
127 argparser.add_argument('--nocache', dest='nocache', action='store_true', help=argparse.SUPPRESS)
128 argparser.add_argument('-X', '--exclude', dest='excludepats', action='append',
129 help='Exclude interfaces from the list of interfaces to operate on. '
130 'Can be specified multiple times.')
131 argparser.add_argument('-i', '--interfaces', dest='interfacesfile', default=None,
132 help='Specify interfaces file instead of file defined in ifupdown2.conf file')
133 argparser.add_argument('-t', '--interfaces-format', dest='interfacesfileformat', default='native',
134 choices=['native', 'json'], help='interfaces file format')
135 argparser.add_argument('-T', '--type', dest='type', default=None, choices=['iface', 'vlan'],
136 help='type of interface entry (iface or vlan). '
137 'This option can be used in case of ambiguity between '
138 'a vlan interface and an iface interface of the same name')
139
140 def update_ifupdown_argparser(self, argparser):
141 """ common arg parser for ifup and ifdown """
142 argparser.add_argument('-f', '--force', dest='force', action='store_true', help='force run all operations')
143 argparser.add_argument('-l', '--syslog', dest='syslog', action='store_true', help=argparse.SUPPRESS)
144 group = argparser.add_mutually_exclusive_group(required=False)
145 group.add_argument('-n', '--no-act', dest='noact', action='store_true',
146 help="print out what would happen, but don't do it")
147 group.add_argument('-p', '--print-dependency', dest='printdependency',
148 choices=['list', 'dot'], help='print iface dependency')
149 group.add_argument('--no-scripts', '--admin-state', dest='noaddons', action='store_true',
150 help='dont run any addon modules/scripts. Only bring the interface administratively up/down')
151
152 def update_ifup_argparser(self, argparser):
153 argparser.add_argument('-s', '--syntax-check', dest='syntaxcheck',
154 action='store_true', help='Only run the interfaces file parser')
155 argparser.add_argument('-k', '--skip-upperifaces', dest='skipupperifaces', action='store_true',
156 help='ifup by default tries to add newly created interfaces into its upper/parent '
157 'interfaces. Eg. if a bridge port is created as a result of ifup on the port, '
158 'ifup automatically adds the port to the bridge. This option can be used to '
159 'disable this default behaviour')
160 self.update_ifupdown_argparser(argparser)
161
162 def update_ifdown_argparser(self, argparser):
163 self.update_ifupdown_argparser(argparser)
164 argparser.add_argument('-u', '--use-current-config',
165 dest='usecurrentconfig', action='store_true',
166 help='By default ifdown looks at the saved state for interfaces to bring down. '
167 'This option allows ifdown to look at the current interfaces file. '
168 'Useful when your state file is corrupted or you want down to use '
169 'the latest from the interfaces file')
170
171 def update_ifquery_argparser(self, argparser):
172 """ arg parser for ifquery options """
173
174 # -l is same as '-a', only here for backward compatibility
175 argparser.add_argument('-l', '--list', action='store_true', dest='list',
176 help='list all matching known interfaces')
177 group = argparser.add_mutually_exclusive_group(required=False)
178 group.add_argument('-r', '--running', dest='running', action='store_true',
179 help='query running state of an interface')
180 group.add_argument('-c', '--check', dest='checkcurr', action='store_true',
181 help='check interface file contents against running state of an interface')
182 group.add_argument('-x', '--raw', action='store_true', dest='raw', help='print raw config file entries')
183 group.add_argument('--print-savedstate', action='store_true', dest='printsavedstate', help=argparse.SUPPRESS)
184 argparser.add_argument('-o', '--format', dest='format', default='native',
185 choices=['native', 'json'], help='interface display format')
186 argparser.add_argument('-p', '--print-dependency', dest='printdependency',
187 choices=['list', 'dot'], help='print interface dependency')
188 argparser.add_argument('-s', '--syntax-help', action='store_true', dest='syntaxhelp',
189 help='print supported interface config syntax')
190 argparser.add_argument('--with-defaults', action='store_true', dest='withdefaults',
191 help='check policy default file contents, for unconfigured attributes, '
192 'against running state of an interface')
193
194 def update_ifreload_argparser(self, argparser):
195 """ parser for ifreload """
196 group = argparser.add_mutually_exclusive_group(required=True)
197 group.add_argument('-a', '--all', action='store_true', help='process all interfaces marked "auto"')
198 group.add_argument('-c', '--currently-up', dest='currentlyup', action='store_true',
199 help='Reload the configuration for all interfaces which are '
200 'currently up regardless of whether an interface has '
201 '"auto <interface>" configuration within the /etc/network/interfaces file.')
202 group.add_argument('--allow', dest='CLASS', action='append', help='ignore non-"allow-CLASS" interfaces')
203 argparser.add_argument('iflist', metavar='IFACE', nargs='*', help=argparse.SUPPRESS)
204 argparser.add_argument('-n', '--no-act', dest='noact', action='store_true',
205 help='print out what would happen, but don\'t do it')
206 argparser.add_argument('-v', '--verbose', dest='verbose', action='store_true', help='verbose')
207 argparser.add_argument('-d', '--debug', dest='debug', action='store_true', help='output debug info')
208 argparser.add_argument('-w', '--with-depends', dest='withdepends', action='store_true', help=argparse.SUPPRESS)
209 argparser.add_argument('--perfmode', dest='perfmode', action='store_true', help=argparse.SUPPRESS)
210 argparser.add_argument('--nocache', dest='nocache', action='store_true', help=argparse.SUPPRESS)
211 argparser.add_argument('-X', '--exclude', dest='excludepats', action='append', help=argparse.SUPPRESS)
212 # argparser.add_argument('-j', '--jobs', dest='jobs', type=int,
213 # default=-1, choices=range(1,12), help=argparse.SUPPRESS)
214 # argparser.add_argument('-i', '--interfaces', dest='interfacesfile',
215 # default='/etc/network/interfaces',
216 # help='use interfaces file instead of default ' +
217 # '/etc/network/interfaces')
218 argparser.add_argument('-u', '--use-current-config', dest='usecurrentconfig', action='store_true',
219 help='By default ifreload looks at saved state for interfaces to bring down. '
220 'With this option ifreload will only look at the current interfaces file. '
221 'Useful when your state file is corrupted or you want down to use the latest '
222 'from the interfaces file')
223 argparser.add_argument('-l', '--syslog', dest='syslog', action='store_true', help=argparse.SUPPRESS)
224 argparser.add_argument('-f', '--force', dest='force', action='store_true', help='force run all operations')
225 argparser.add_argument('-s', '--syntax-check', dest='syntaxcheck', action='store_true',
226 help='Only run the interfaces file parser')
227
228 def update_common_argparser(self, argparser):
229 ''' general parsing rules '''
230
231 argparser.add_argument('-V', '--version', action=VersionAction, nargs=0)