]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdownaddons/modulebase.py
Fix setup.py to include new example file names
[mirror_ifupdown2.git] / ifupdownaddons / modulebase.py
CommitLineData
15ef32ea
RP
1#!/usr/bin/python
2#
3# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4# Author: Roopa Prabhu, roopa@cumulusnetworks.com
5#
6
7import re
8import io
9import logging
10import subprocess
11import traceback
12from ifupdown.iface import *
13#from ifupdownaddons.iproute2 import *
14#from ifupdownaddons.dhclient import *
15#from ifupdownaddons.bridgeutils import *
16#from ifupdownaddons.mstpctlutil import *
17#from ifupdownaddons.ifenslaveutil import *
18
19class moduleBase(object):
20 """ Base class for ifupdown addon modules
21
22 Provides common infrastructure methods for all addon modules """
23
24 def __init__(self, *args, **kargs):
25 modulename = self.__class__.__name__
26 self.logger = logging.getLogger('ifupdown.' + modulename)
27 self.FORCE = kargs.get('force', False)
28 """force interface configuration"""
29 self.DRYRUN = kargs.get('dryrun', False)
30 """only predend you are applying configuration, dont really do it"""
31 self.NOWAIT = kargs.get('nowait', False)
32 self.PERFMODE = kargs.get('perfmode', False)
33 self.CACHE = kargs.get('cache', False)
34 self.CACHE_FLAGS = kargs.get('cacheflags', 0x0)
35
36 def log_warn(self, str):
37 """ log a warning if err str is not one of which we should ignore """
38 if not self.ignore_error(str):
39 if self.logger.getEffectiveLevel() == logging.DEBUG:
40 traceback.print_stack()
41 self.logger.warn(str)
42 pass
43
44 def log_error(self, str):
45 """ log an err if err str is not one of which we should ignore and raise an exception """
46 if not self.ignore_error(str):
47 if self.logger.getEffectiveLevel() == logging.DEBUG:
48 traceback.print_stack()
49 raise Exception(str)
50 else:
51 pass
52
53 def exec_command(self, cmd, cmdenv=None):
54 """ execute command passed as argument.
55
56 Args:
57 cmd (str): command to execute
58
59 Kwargs:
60 cmdenv (dict): environment variable name value pairs
61 """
62 cmd_returncode = 0
63 cmdout = ''
64
65 try:
66 self.logger.info('Executing ' + cmd)
67 if self.DRYRUN:
68 return cmdout
69 ch = subprocess.Popen(cmd.split(),
70 stdout=subprocess.PIPE,
71 shell=False, env=cmdenv,
72 stderr=subprocess.STDOUT,
73 close_fds=True)
74 cmdout = ch.communicate()[0]
75 cmd_returncode = ch.wait()
76 except OSError, e:
77 raise Exception('could not execute ' + cmd +
78 '(' + str(e) + ')')
79 if cmd_returncode != 0:
80 raise Exception('error executing cmd \'%s\'' %cmd +
81 '(' + cmdout.strip('\n ') + ')')
82 return cmdout
83
84 def exec_command_talk_stdin(self, cmd, stdinbuf):
85 """ execute command passed as argument and write contents of stdinbuf
86 into stdin of the cmd
87
88 Args:
89 cmd (str): command to execute
90 stdinbuf (str): string to write to stdin of the cmd process
91 """
92 cmd_returncode = 0
93 cmdout = ''
94
95 try:
96 self.logger.info('Executing %s (stdin=%s)' %(cmd, stdinbuf))
97 if self.DRYRUN:
98 return cmdout
99 ch = subprocess.Popen(cmd.split(),
100 stdout=subprocess.PIPE,
101 stdin=subprocess.PIPE,
102 shell=False, env=cmdenv,
103 stderr=subprocess.STDOUT,
104 close_fds=True)
105 cmdout = ch.communicate(input=stdinbuf)[0]
106 cmd_returncode = ch.wait()
107 except OSError, e:
108 raise Exception('could not execute ' + cmd +
109 '(' + str(e) + ')')
110 if cmd_returncode != 0:
111 raise Exception('error executing cmd \'%s (%s)\''
112 %(cmd, stdinbuf) + '(' + cmdout.strip('\n ') + ')')
113 return cmdout
114
115 def get_ifaces_from_proc(self):
116 ifacenames = []
117 with open('/proc/net/dev') as f:
118 try:
119 lines = f.readlines()
120 for line in lines:
121 ifacenames.append(line.split()[0].strip(': '))
122 except:
123 raise
124 return ifacenames
125
126 def parse_regex(self, expr, ifacenames=None):
127 try:
128 proc_ifacenames = self.get_ifaces_from_proc()
129 except:
130 self.logger.warn('error reading ifaces from proc')
131 for proc_ifacename in proc_ifacenames:
132 if re.search(expr + '$', proc_ifacename):
133 yield proc_ifacename
134 if not ifacenames:
135 return
136 for ifacename in ifacenames:
137 if re.search(expr + '$', ifacename):
138 yield ifacename
139
140 def parse_glob(self, expr):
141 errmsg = ('error parsing glob expression \'%s\'' %expr +
142 ' (supported glob syntax: swp1-10 or swp[1-10])')
143 start_index = 0
144 end_index = 0
145 try:
1d591e73
RP
146 regexs = [re.compile(r"([A-Za-z0-9\-]+[A-Za-z])(\d+)\-(\d+)(.*)"),
147 re.compile(r"([A-Za-z0-9\-]+)\[(\d+)\-(\d+)\](.*)")]
15ef32ea
RP
148 for r in regexs:
149 m = r.match(expr)
150 if not m:
151 continue
152 mlist = m.groups()
153 if len(mlist) != 4:
154 raise Exception(errmsg + '(unexpected len)')
155 prefix = mlist[0]
156 suffix = mlist[3]
157 start_index = int(mlist[1])
158 end_index = int(mlist[2])
159 except:
160 self.logger.warn(errmsg)
161 pass
162 if not start_index and not end_index:
163 self.logger.warn(errmsg)
164 yield expr
165 else:
166 for i in range(start_index, end_index + 1):
167 yield prefix + '%d' %i + suffix
168
169 def parse_port_list(self, port_expr, ifacenames=None):
170 """ parse port list containing glob and regex
171
172 Args:
173 port_expr (str): expression
174 ifacenames (list): list of interface names. This needs to be specified if the expression has a regular expression
175 """
176 regex = 0
177 glob = 0
178 portlist = []
179
180 if not port_expr:
181 return None
182 for expr in re.split(r'[\s\t]\s*', port_expr):
84ca006f
RP
183 if expr == 'noregex':
184 regex = 0
185 elif expr == 'noglob':
186 glob = 0
187 elif expr == 'regex':
15ef32ea
RP
188 regex = 1
189 elif expr == 'glob':
190 glob = 1
191 elif regex:
192 for port in self.parse_regex(expr, ifacenames):
193 if port not in portlist:
194 portlist.append(port)
195 regex = 0
196 elif glob:
197 for port in self.parse_glob(expr):
198 portlist.append(port)
199 glob = 0
200 else:
201 portlist.append(expr)
202 if not portlist:
203 return None
204 return portlist
205
206 def ignore_error(self, errmsg):
207 if (self.FORCE or re.search(r'exists', errmsg,
208 re.IGNORECASE | re.MULTILINE)):
209 return True
210 return False
211
212 def write_file(self, filename, strexpr):
213 """ writes string to a file """
214 try:
215 self.logger.info('writing \'%s\'' %strexpr +
216 ' to file %s' %filename)
217 if self.DRYRUN:
218 return 0
219 with open(filename, 'w') as f:
220 f.write(strexpr)
221 except IOError, e:
222 self.logger.warn('error writing to file %s'
223 %filename + '(' + str(e) + ')')
224 return -1
225 return 0
226
227 def read_file(self, filename):
228 """ read file and return lines from the file """
229 try:
230 self.logger.info('reading \'%s\'' %filename)
231 with open(filename, 'r') as f:
232 return f.readlines()
233 except:
234 return None
235 return None
236
237 def read_file_oneline(self, filename):
238 """ reads and returns first line from the file """
239 try:
240 self.logger.info('reading \'%s\'' %filename)
241 with open(filename, 'r') as f:
242 return f.readline().strip('\n')
243 except:
244 return None
245 return None
246
247 def sysctl_set(self, variable, value):
248 """ set sysctl variable to value passed as argument """
249 self.exec_command('sysctl %s=' %variable + '%s' %value)
250
251 def sysctl_get(self, variable):
252 """ get value of sysctl variable """
253 return self.exec_command('sysctl %s' %variable).split('=')[1].strip()
254
255 def set_iface_attr(self, ifaceobj, attr_name, attr_valsetfunc,
256 prehook=None, prehookargs=None):
257 ifacename = ifaceobj.name
258 attrvalue = ifaceobj.get_attr_value_first(attr_name)
259 if attrvalue:
260 if prehook:
261 if prehookargs:
262 prehook(prehookargs)
263 else:
264 prehook(ifacename)
265 attr_valsetfunc(ifacename, attrvalue)
266
267 def query_n_update_ifaceobjcurr_attr(self, ifaceobj, ifaceobjcurr,
268 attr_name, attr_valgetfunc,
269 attr_valgetextraarg=None):
270 attrvalue = ifaceobj.get_attr_value_first(attr_name)
271 if not attrvalue:
272 return
273 if attr_valgetextraarg:
274 runningattrvalue = attr_valgetfunc(ifaceobj.name,
275 attr_valgetextraarg)
276 else:
277 runningattrvalue = attr_valgetfunc(ifaceobj.name)
278 if (not runningattrvalue or
279 (runningattrvalue != attrvalue)):
280 ifaceobjcurr.update_config_with_status(attr_name,
281 runningattrvalue, 1)
282 else:
283 ifaceobjcurr.update_config_with_status(attr_name,
284 runningattrvalue, 0)
285
286 def dict_key_subset(self, a, b):
287 """ returns a list of differing keys """
288 return [x for x in a if x in b]
289
290 def get_mod_attrs(self):
291 """ returns list of all module attrs defined in the module _modinfo dict"""
292 try:
293 return self._modinfo.get('attrs').keys()
294 except:
295 return None
296
297 def get_mod_attr(self, attrname):
298 """ returns module attr info """
299 try:
300 return self._modinfo.get('attrs', {}).get(attrname)
301 except:
302 return None
303
304 def get_mod_subattr(self, attrname, subattrname):
305 """ returns module attrs defined in the module _modinfo dict"""
306 try:
307 return reduce(lambda d, k: d[k], ['attrs', attrname, subattrname],
308 self._modinfo)
309 except:
310 return None
311
312 def get_modinfo(self):
313 """ return module info """
314 try:
315 return self._modinfo
316 except:
317 return None
318
319 def get_flags(self):
320 return dict(force=self.FORCE, dryrun=self.DRYRUN, nowait=self.NOWAIT,
321 perfmode=self.PERFMODE, cache=self.CACHE,
322 cacheflags=self.CACHE_FLAGS)
2da58137
RP
323
324 def _get_reserved_vlan_range(self):
325 start = end = 0
326 get_resvvlan = '/usr/share/python-ifupdown2/get_reserved_vlan_range.sh'
327 try:
ad25e7bb
RP
328 (s, e) = self.exec_command(get_resvvlan).strip('\n').split('-')
329 start = int(s)
330 end = int(e)
2da58137
RP
331 except:
332 # ignore errors
333 pass
334 return (start, end)