]>
Commit | Line | Data |
---|---|---|
d486dd0d JF |
1 | #!/usr/bin/python |
2 | # | |
223ba5af | 3 | # Copyright 2014-2019 Cumulus Networks, Inc. All rights reserved. |
d486dd0d JF |
4 | # Authors: |
5 | # Roopa Prabhu, roopa@cumulusnetworks.com | |
6 | # Julien Fortin, julien@cumulusnetworks.com | |
7 | # ifupdown2 -- | |
8 | # tool to configure network interfaces | |
9 | # | |
10 | ||
11 | import os | |
12 | import sys | |
223ba5af | 13 | import logging |
d486dd0d JF |
14 | import StringIO |
15 | import ConfigParser | |
16 | ||
17 | try: | |
d486dd0d JF |
18 | from ifupdown2.ifupdown.argv import Parse |
19 | from ifupdown2.ifupdown.config import IFUPDOWN2_CONF_PATH | |
20 | from ifupdown2.ifupdown.ifupdownmain import ifupdownMain | |
223ba5af JF |
21 | |
22 | from ifupdown2.lib.dry_run import DryRunManager | |
23 | ||
d486dd0d | 24 | except ImportError: |
d486dd0d JF |
25 | from ifupdown.argv import Parse |
26 | from ifupdown.config import IFUPDOWN2_CONF_PATH | |
27 | from ifupdown.ifupdownmain import ifupdownMain | |
28 | ||
223ba5af | 29 | from lib.dry_run import DryRunManager |
d486dd0d | 30 | |
d486dd0d | 31 | |
223ba5af | 32 | log = logging.getLogger() |
d486dd0d JF |
33 | configmap_g = None |
34 | ||
35 | ||
36 | class Ifupdown2: | |
37 | def __init__(self, daemon, uid): | |
38 | self.daemon = daemon | |
39 | self.uid = uid | |
40 | self.args = None | |
41 | self.op = None | |
42 | ||
43 | self.interfaces_filename = None | |
44 | self.interfaces_file_iobuf = None | |
45 | ||
46 | self.handlers = { | |
47 | 'up': self.run_up, | |
48 | 'down': self.run_down, | |
49 | 'query': self.run_query, | |
50 | 'reload': self.run_reload | |
51 | } | |
52 | ||
53 | def parse_argv(self, argv): | |
54 | args_parse = Parse(argv) | |
55 | args_parse.validate() | |
56 | ||
57 | self.args = args_parse.get_args() | |
58 | self.op = args_parse.get_op() | |
59 | ||
d486dd0d JF |
60 | def main(self, stdin_buffer=None): |
61 | if self.op != 'query' and self.uid != 0: | |
62 | raise Exception('must be root to run this command') | |
63 | ||
64 | try: | |
65 | self.read_config() | |
66 | self.init(stdin_buffer) | |
67 | self.handlers.get(self.op)(self.args) | |
68 | except Exception, e: | |
69 | if not str(e): | |
70 | return 1 | |
71 | # if args and args.debug: | |
72 | raise | |
73 | # else: | |
74 | if log: | |
223ba5af | 75 | log.error('main exception: ' + str(e)) |
d486dd0d JF |
76 | else: |
77 | print str(e) | |
78 | # if args and not args.debug: | |
79 | # print '\nrerun the command with \'-d\' for a detailed errormsg' | |
80 | return 1 | |
81 | return 0 | |
82 | ||
83 | def init(self, stdin_buffer): | |
223ba5af JF |
84 | ############## |
85 | # dry run mode | |
86 | ############## | |
87 | dry_run_mode_on = DryRunManager.get_instance().is_dry_mode_on() | |
88 | ||
89 | if hasattr(self.args, 'noact'): | |
90 | if self.args.noact and not dry_run_mode_on: | |
91 | DryRunManager.get_instance().dry_run_mode_on() | |
92 | elif not self.args.noact and dry_run_mode_on: | |
93 | DryRunManager.get_instance().dry_run_mode_off() | |
94 | elif dry_run_mode_on: | |
95 | # if noact is not in self.args we are probably in | |
96 | # ifquery mode so we need to turn off dry run mode. | |
97 | DryRunManager.get_instance().dry_run_mode_off() | |
98 | ||
99 | ### | |
100 | ||
d486dd0d JF |
101 | if hasattr(self.args, 'interfacesfile') and self.args.interfacesfile != None: |
102 | # Check to see if -i option is allowed by config file | |
103 | # But for ifquery, we will not check this | |
104 | if (not self.op == 'query' and | |
105 | configmap_g.get('disable_cli_interfacesfile', '0') == '1'): | |
106 | log.error('disable_cli_interfacesfile is set so users ' | |
107 | 'not allowed to specify interfaces file on cli.') | |
108 | raise Exception("") | |
109 | if self.args.interfacesfile == '-': | |
110 | # If interfaces file is stdin, read | |
111 | if self.daemon: | |
112 | self.interfaces_file_iobuf = stdin_buffer | |
113 | else: | |
114 | self.interfaces_file_iobuf = sys.stdin.read() | |
115 | else: | |
116 | self.interfaces_filename = self.args.interfacesfile | |
117 | else: | |
118 | # if the ifupdown2 config file does not have it, default to standard | |
119 | self.interfaces_filename = configmap_g.get('default_interfaces_configfile', | |
120 | '/etc/network/interfaces') | |
121 | ||
122 | def read_config(self): | |
123 | global configmap_g | |
124 | ||
125 | with open(IFUPDOWN2_CONF_PATH, 'r') as f: | |
126 | config = f.read() | |
127 | configStr = '[ifupdown2]\n' + config | |
128 | configFP = StringIO.StringIO(configStr) | |
129 | parser = ConfigParser.RawConfigParser() | |
130 | parser.readfp(configFP) | |
131 | configmap_g = dict(parser.items('ifupdown2')) | |
132 | ||
133 | # Preprocess config map | |
134 | configval = configmap_g.get('multiple_vlan_aware_bridge_support', '0') | |
135 | if configval == '0': | |
136 | # if multiple bridges not allowed, set the bridge-vlan-aware | |
137 | # attribute in the 'no_repeats' config, so that the ifupdownmain | |
138 | # module can catch it appropriately | |
139 | configmap_g['no_repeats'] = {'bridge-vlan-aware': 'yes'} | |
140 | ||
141 | configval = configmap_g.get('link_master_slave', '0') | |
142 | if configval == '1': | |
143 | # link_master_slave is only valid when all is set | |
144 | if hasattr(self.args, 'all') and not self.args.all: | |
145 | configmap_g['link_master_slave'] = '0' | |
146 | ||
147 | configval = configmap_g.get('delay_admin_state_change', '0') | |
148 | if configval == '1': | |
149 | # reset link_master_slave if delay_admin_state_change is on | |
150 | configmap_g['link_master_slave'] = '0' | |
151 | ||
152 | def run_up(self, args): | |
153 | log.debug('args = %s' % str(args)) | |
154 | ||
155 | try: | |
156 | iflist = args.iflist | |
157 | if len(args.iflist) == 0: | |
158 | iflist = None | |
159 | log.debug('creating ifupdown object ..') | |
160 | cachearg = (False if (iflist or args.nocache or args.noact) | |
161 | else True) | |
162 | ifupdown_handle = ifupdownMain(daemon=self.daemon, | |
163 | config=configmap_g, | |
164 | force=args.force, | |
165 | withdepends=args.withdepends, | |
166 | perfmode=args.perfmode, | |
167 | dryrun=args.noact, | |
168 | cache=cachearg, | |
169 | addons_enable=not args.noaddons, | |
170 | statemanager_enable=not args.noaddons, | |
171 | interfacesfile=self.interfaces_filename, | |
172 | interfacesfileiobuf=self.interfaces_file_iobuf, | |
173 | interfacesfileformat=args.interfacesfileformat) | |
174 | if args.noaddons: | |
175 | ifupdown_handle.up(['up'], args.all, args.CLASS, iflist, | |
176 | excludepats=args.excludepats, | |
177 | printdependency=args.printdependency, | |
178 | syntaxcheck=args.syntaxcheck, type=args.type, | |
179 | skipupperifaces=args.skipupperifaces) | |
180 | else: | |
181 | ifupdown_handle.up(['pre-up', 'up', 'post-up'], | |
182 | args.all, args.CLASS, iflist, | |
183 | excludepats=args.excludepats, | |
184 | printdependency=args.printdependency, | |
185 | syntaxcheck=args.syntaxcheck, type=args.type, | |
186 | skipupperifaces=args.skipupperifaces) | |
187 | except: | |
188 | raise | |
189 | ||
190 | def run_down(self, args): | |
191 | log.debug('args = %s' % str(args)) | |
192 | ||
193 | try: | |
194 | iflist = args.iflist | |
195 | log.debug('creating ifupdown object ..') | |
196 | ifupdown_handle = ifupdownMain(daemon=self.daemon, | |
197 | config=configmap_g, force=args.force, | |
198 | withdepends=args.withdepends, | |
199 | perfmode=args.perfmode, | |
200 | dryrun=args.noact, | |
201 | addons_enable=not args.noaddons, | |
202 | statemanager_enable=not args.noaddons, | |
203 | interfacesfile=self.interfaces_filename, | |
204 | interfacesfileiobuf=self.interfaces_file_iobuf, | |
205 | interfacesfileformat=args.interfacesfileformat) | |
206 | ||
207 | ifupdown_handle.down(['pre-down', 'down', 'post-down'], | |
208 | args.all, args.CLASS, iflist, | |
209 | excludepats=args.excludepats, | |
210 | printdependency=args.printdependency, | |
211 | usecurrentconfig=args.usecurrentconfig, | |
212 | type=args.type) | |
213 | except: | |
214 | raise | |
215 | ||
216 | def run_query(self, args): | |
217 | log.debug('args = %s' % str(args)) | |
218 | ||
219 | try: | |
220 | iflist = args.iflist | |
221 | if args.checkcurr: | |
222 | qop = 'query-checkcurr' | |
223 | elif args.running: | |
224 | qop = 'query-running' | |
225 | elif args.raw: | |
226 | qop = 'query-raw' | |
227 | elif args.syntaxhelp: | |
228 | qop = 'query-syntax' | |
229 | elif args.printdependency: | |
230 | qop = 'query-dependency' | |
231 | elif args.printsavedstate: | |
232 | qop = 'query-savedstate' | |
233 | else: | |
234 | qop = 'query' | |
235 | cachearg = (False if (iflist or args.nocache or args.syntaxhelp or | |
236 | (qop != 'query-checkcurr' and | |
237 | qop != 'query-running')) else True) | |
238 | if not iflist and qop == 'query-running': | |
239 | iflist = [i for i in os.listdir('/sys/class/net/') | |
240 | if os.path.isdir('/sys/class/net/%s' % i)] | |
241 | log.debug('creating ifupdown object ..') | |
242 | ifupdown_handle = ifupdownMain(daemon=self.daemon, | |
243 | config=configmap_g, | |
244 | withdepends=args.withdepends, | |
245 | perfmode=args.perfmode, | |
246 | cache=cachearg, | |
247 | interfacesfile=self.interfaces_filename, | |
248 | interfacesfileiobuf=self.interfaces_file_iobuf, | |
249 | interfacesfileformat=args.interfacesfileformat, | |
250 | withdefaults=args.withdefaults) | |
251 | # list implies all auto interfaces (this is how ifupdown behaves) | |
252 | if args.list: | |
253 | args.all = True | |
254 | ifupdown_handle.query([qop], args.all, args.list, args.CLASS, iflist, | |
255 | excludepats=args.excludepats, | |
256 | printdependency=args.printdependency, | |
257 | format=args.format, type=args.type) | |
258 | except: | |
259 | raise | |
260 | ||
261 | def run_reload(self, args): | |
262 | log.debug('args = %s' % str(args)) | |
263 | ||
264 | try: | |
265 | log.debug('creating ifupdown object ..') | |
266 | ifupdown_handle = ifupdownMain(daemon=self.daemon, | |
267 | config=configmap_g, | |
268 | interfacesfile=self.interfaces_filename, | |
269 | withdepends=args.withdepends, | |
270 | perfmode=args.perfmode, | |
271 | dryrun=args.noact) | |
272 | ifupdown_handle.reload(['pre-up', 'up', 'post-up'], | |
273 | ['pre-down', 'down', 'post-down'], | |
274 | auto=args.all, allow=args.CLASS, ifacenames=None, | |
275 | excludepats=args.excludepats, | |
276 | usecurrentconfig=args.usecurrentconfig, | |
277 | syntaxcheck=args.syntaxcheck, | |
278 | currentlyup=args.currentlyup) | |
279 | except: | |
280 | raise |