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