]> git.proxmox.com Git - mirror_ifupdown2.git/blob - addons/vrf.py
addons: vrf: delete rules before deleting the vrf interface on down
[mirror_ifupdown2.git] / addons / vrf.py
1 #!/usr/bin/python
2 #
3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
5 #
6
7 import os
8 import atexit
9 from ifupdown.iface import *
10 import ifupdown.policymanager as policymanager
11 import ifupdownaddons
12 import ifupdown.rtnetlink_api as rtnetlink_api
13 from ifupdownaddons.modulebase import moduleBase
14 from ifupdownaddons.bondutil import bondutil
15 from ifupdownaddons.iproute2 import iproute2
16 from ifupdownaddons.dhclient import dhclient
17
18 class vrfPrivFlags:
19 PROCESSED = 0x1
20
21 class vrf(moduleBase):
22 """ ifupdown2 addon module to configure vrfs """
23 _modinfo = { 'mhelp' : 'vrf configuration module',
24 'attrs' : {
25 'vrf-table':
26 {'help' : 'vrf device table id. key to ' +
27 'creating a vrf device',
28 'example': ['vrf-table-id 1']},
29 'vrf-default-route':
30 {'help' : 'vrf device default route ' +
31 'to avoid communication outside the vrf device',
32 'example': ['vrf-default-route yes/no']},
33 'vrf':
34 {'help' : 'vrf the interface is part of.',
35 'example': ['vrf blue']}}}
36
37 iproute2_vrf_filename = '/etc/iproute2/rt_tables.d/ifupdown2_vrf_map.conf'
38 iproute2_vrf_filehdr = '# This file is autogenerated by ifupdown2.\n' + \
39 '# It contains the vrf name to table mapping.\n' + \
40 '# Reserved table range %s %s\n'
41 VRF_TABLE_START = 1001
42 VRF_TABLE_END = 5000
43
44 def __init__(self, *args, **kargs):
45 ifupdownaddons.modulebase.moduleBase.__init__(self, *args, **kargs)
46 self.ipcmd = None
47 self.bondcmd = None
48 self.dhclientcmd = None
49 self.name = self.__class__.__name__
50 if self.PERFMODE:
51 # if perf mode is set, remove vrf map file.
52 # start afresh. PERFMODE is set at boot
53 if os.path.exists(self.iproute2_vrf_filename):
54 try:
55 self.logger.info('vrf: removing file %s'
56 %self.iproute2_vrf_filename)
57 os.remove(self.iproute2_vrf_filename)
58 except Exception, e:
59 self.logger.debug('vrf: removing file failed (%s)'
60 %str(e))
61 try:
62 ip_rules = self.exec_command('/sbin/ip rule show').splitlines()
63 self.ip_rule_cache = [' '.join(r.split()) for r in ip_rules]
64 except Exception, e:
65 self.ip_rule_cache = []
66 self.logger.warn('%s' %str(e))
67
68 try:
69 ip_rules = self.exec_command('/sbin/ip -6 rule show').splitlines()
70 self.ip6_rule_cache = [' '.join(r.split()) for r in ip_rules]
71 except Exception, e:
72 self.ip6_rule_cache = []
73 self.logger.warn('%s' %str(e))
74
75 #self.logger.debug("vrf: ip rule cache")
76 #self.logger.info(self.ip_rule_cache)
77
78 #self.logger.info("vrf: ip -6 rule cache")
79 #self.logger.info(self.ip6_rule_cache)
80
81 # XXX: check for vrf reserved overlap in /etc/iproute2/rt_tables
82 self.iproute2_vrf_map = {}
83 # read or create /etc/iproute2/rt_tables.d/ifupdown2.vrf_map
84 if os.path.exists(self.iproute2_vrf_filename):
85 self.vrf_map_fd = open(self.iproute2_vrf_filename, 'a+')
86 lines = self.vrf_map_fd.readlines()
87 for l in lines:
88 l = l.strip()
89 if l[0] == '#':
90 continue
91 try:
92 (table, vrf_name) = l.strip().split()
93 self.iproute2_vrf_map[table] = vrf_name
94 except Exception, e:
95 self.logger.info('vrf: iproute2_vrf_map: unable to parse %s'
96 %l)
97 pass
98 #self.logger.info("vrf: dumping iproute2_vrf_map")
99 #self.logger.info(self.iproute2_vrf_map)
100
101 # purge vrf table entries that are not around
102 iproute2_vrf_map_pruned = {}
103 for t, v in self.iproute2_vrf_map.iteritems():
104 if os.path.exists('/sys/class/net/%s' %v):
105 iproute2_vrf_map_pruned[int(t)] = v
106 else:
107 try:
108 # cleanup rules
109 self._del_vrf_rules(v, t)
110 except Exception:
111 pass
112 self.iproute2_vrf_map = iproute2_vrf_map_pruned
113
114 self.vrf_table_id_start = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-table-id-start')
115 if not self.vrf_table_id_start:
116 self.vrf_table_id_start = self.VRF_TABLE_START
117 self.vrf_table_id_end = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-table-id-end')
118 if not self.vrf_table_id_end:
119 self.vrf_table_id_end = self.VRF_TABLE_END
120 self.vrf_max_count = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-max-count')
121
122 last_used_vrf_table = None
123 for t in range(self.vrf_table_id_start,
124 self.vrf_table_id_end):
125 if not self.iproute2_vrf_map.get(t):
126 break
127 last_used_vrf_table = t
128 self.last_used_vrf_table = last_used_vrf_table
129
130 self.iproute2_write_vrf_map = False
131 atexit.register(self.iproute2_vrf_map_write)
132 self.vrf_fix_local_table = True
133 self.vrf_count = 0
134 self.vrf_cgroup_create = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-cgroup-create')
135 if not self.vrf_cgroup_create:
136 self.vrf_cgroup_create = False
137 elif self.vrf_cgroup_create == 'yes':
138 self.vrf_cgroup_create = True
139 else:
140 self.vrf_cgroup_create = False
141
142 def iproute2_vrf_map_write(self):
143 if not self.iproute2_write_vrf_map:
144 return
145 self.logger.info('vrf: writing table map to %s'
146 %self.iproute2_vrf_filename)
147 with open(self.iproute2_vrf_filename, 'w') as f:
148 f.write(self.iproute2_vrf_filehdr %(self.vrf_table_id_start,
149 self.vrf_table_id_end))
150 for t, v in self.iproute2_vrf_map.iteritems():
151 f.write('%s %s\n' %(t, v))
152
153 def _is_vrf(self, ifaceobj):
154 if ifaceobj.get_attr_value_first('vrf-table'):
155 return True
156 return False
157
158 def get_upper_ifacenames(self, ifaceobj, ifacenames_all=None):
159 """ Returns list of interfaces dependent on ifaceobj """
160
161 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
162 if vrf_table:
163 ifaceobj.link_type = ifaceLinkType.LINK_MASTER
164 ifaceobj.link_kind |= ifaceLinkKind.VRF
165 vrf_iface_name = ifaceobj.get_attr_value_first('vrf')
166 if not vrf_iface_name:
167 return None
168 ifaceobj.link_type = ifaceLinkType.LINK_SLAVE
169 ifaceobj.link_kind |= ifaceLinkKind.VRF_SLAVE
170
171 return [vrf_iface_name]
172
173 def get_upper_ifacenames_running(self, ifaceobj):
174 return None
175
176 def _get_iproute2_vrf_table(self, vrf_dev_name):
177 for t, v in self.iproute2_vrf_map.iteritems():
178 if v == vrf_dev_name:
179 return str(t)
180 return None
181
182 def _get_avail_vrf_table_id(self):
183 if self.last_used_vrf_table == None:
184 table_id_start = self.vrf_table_id_start
185 else:
186 table_id_start = self.last_used_vrf_table + 1
187 for t in range(table_id_start,
188 self.vrf_table_id_end):
189 if not self.iproute2_vrf_map.get(t):
190 self.last_used_vrf_table = t
191 return str(t)
192 return None
193
194 def _iproute2_vrf_table_entry_add(self, vrf_dev_name, table_id):
195 self.iproute2_vrf_map[int(table_id)] = vrf_dev_name
196 self.iproute2_write_vrf_map = True
197
198 def _iproute2_vrf_table_entry_del(self, table_id):
199 try:
200 del self.iproute2_vrf_map[int(table_id)]
201 self.iproute2_write_vrf_map = True
202 except Exception, e:
203 self.logger.info('vrf: iproute2 vrf map del failed for %d (%s)'
204 %(table_id, str(e)))
205 pass
206
207 def _is_dhcp_slave(self, ifaceobj):
208 if (not ifaceobj.addr_method or
209 (ifaceobj.addr_method != 'dhcp' and
210 ifaceobj.addr_method != 'dhcp6')):
211 return False
212 return True
213
214 def _handle_dhcp_slaves(self, ifacename, vrfname, ifaceobj,
215 ifaceobj_getfunc):
216 """ If we have a vrf slave that has dhcp configured, bring up the
217 vrf master now. This is needed because vrf has special handling
218 in dhclient hook which requires the vrf master to be present """
219 if not self._is_dhcp_slave(ifaceobj):
220 return False
221 vrf_master = ifaceobj.upperifaces[0]
222 if not vrf_master:
223 self.logger.warn('%s: vrf master not found' %ifacename)
224 return
225 if os.path.exists('/sys/class/net/%s' %vrf_master):
226 self.logger.info('%s: vrf master %s exists returning'
227 %(ifacename, vrf_master))
228 return
229 vrf_master_objs = ifaceobj_getfunc(vrf_master)
230 if not vrf_master_objs:
231 self.logger.warn('%s: vrf master ifaceobj not found' %ifacename)
232 return
233 self.logger.info('%s: bringing up vrf master %s'
234 %(ifacename, vrf_master))
235 for mobj in vrf_master_objs:
236 vrf_table = mobj.get_attr_value_first('vrf-table')
237 if vrf_table:
238 if vrf_table == 'auto':
239 vrf_table = self._get_avail_vrf_table_id()
240 if not vrf_table:
241 self.log_error('%s: unable to get an auto table id'
242 %mobj.name)
243 self.logger.info('%s: table id auto: selected table id %s\n'
244 %(mobj.name, vrf_table))
245 self._up_vrf_dev(mobj, vrf_table, False)
246 break
247 self._down_dhcp_slave(ifaceobj)
248 self.ipcmd.link_set(ifacename, 'master', vrfname)
249 return
250
251 def _down_dhcp_slave(self, ifaceobj):
252 try:
253 self.dhclientcmd.release(ifaceobj.name)
254 except:
255 # ignore any dhclient release errors
256 pass
257
258 def _up_vrf_slave(self, ifacename, vrfname, ifaceobj=None,
259 ifaceobj_getfunc=None, vrf_exists=False):
260 try:
261 if vrf_exists or self.ipcmd.link_exists(vrfname):
262 upper = self.ipcmd.link_get_upper(ifacename)
263 if not upper or upper != vrfname:
264 if ifaceobj and self._is_dhcp_slave(ifaceobj):
265 self._down_dhcp_slave(ifaceobj)
266 self.ipcmd.link_set(ifacename, 'master', vrfname)
267 elif ifaceobj:
268 self._handle_dhcp_slaves(ifacename, vrfname, ifaceobj,
269 ifaceobj_getfunc)
270 except Exception, e:
271 self.log_error('%s: %s' %(ifacename, str(e)))
272
273 def _del_vrf_rules(self, vrf_dev_name, vrf_table):
274 pref = 200
275 ip_rule_out_format = '%s: from all %s %s lookup %s'
276 ip_rule_cmd = 'ip %s rule del pref %s %s %s table %s'
277
278 rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
279 if rule in self.ip_rule_cache:
280 rule_cmd = ip_rule_cmd %('', pref, 'oif', vrf_dev_name, vrf_table)
281 self.exec_command(rule_cmd)
282
283 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
284 if rule in self.ip_rule_cache:
285 rule_cmd = ip_rule_cmd %('', pref, 'iif', vrf_dev_name, vrf_table)
286 self.exec_command(rule_cmd)
287
288 rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
289 if rule in self.ip6_rule_cache:
290 rule_cmd = ip_rule_cmd %('-6', pref, 'oif', vrf_dev_name,
291 vrf_table)
292 self.exec_command(rule_cmd)
293
294 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
295 if rule in self.ip6_rule_cache:
296 rule_cmd = ip_rule_cmd %('-6', pref, 'iif', vrf_dev_name,
297 vrf_table)
298 self.exec_command(rule_cmd)
299
300 def _add_vrf_rules(self, vrf_dev_name, vrf_table):
301 pref = 200
302 ip_rule_out_format = '%s: from all %s %s lookup %s'
303 ip_rule_cmd = 'ip %s rule add pref %s %s %s table %s'
304 if self.vrf_fix_local_table:
305 self.vrf_fix_local_table = False
306 rule = '0: from all lookup local'
307 if rule in self.ip_rule_cache:
308 try:
309 self.exec_command('ip rule del pref 0')
310 self.exec_command('ip rule add pref 32765 table local')
311 except Exception, e:
312 self.logger.info('%s' %str(e))
313 pass
314 if rule in self.ip6_rule_cache:
315 try:
316 self.exec_command('ip -6 rule del pref 0')
317 self.exec_command('ip -6 rule add pref 32765 table local')
318 except Exception, e:
319 self.logger.info('%s' %str(e))
320 pass
321
322 #Example ip rule
323 #200: from all oif blue lookup blue
324 #200: from all iif blue lookup blue
325
326 rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
327 if rule not in self.ip_rule_cache:
328 rule_cmd = ip_rule_cmd %('', pref, 'oif', vrf_dev_name, vrf_table)
329 self.exec_command(rule_cmd)
330
331 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
332 if rule not in self.ip_rule_cache:
333 rule_cmd = ip_rule_cmd %('', pref, 'iif', vrf_dev_name, vrf_table)
334 self.exec_command(rule_cmd)
335
336 rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
337 if rule not in self.ip6_rule_cache:
338 rule_cmd = ip_rule_cmd %('-6', pref, 'oif', vrf_dev_name, vrf_table)
339 self.exec_command(rule_cmd)
340
341 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
342 if rule not in self.ip6_rule_cache:
343 rule_cmd = ip_rule_cmd %('-6', pref, 'iif', vrf_dev_name,
344 vrf_table)
345 self.exec_command(rule_cmd)
346
347 def _add_vrf_slaves(self, ifaceobj, ifaceobj_getfunc=None):
348 running_slaves = self.ipcmd.link_get_lowers(ifaceobj.name)
349 config_slaves = ifaceobj.lowerifaces
350 if not config_slaves and not running_slaves:
351 return
352
353 if not config_slaves: config_slaves = []
354 if not running_slaves: running_slaves = []
355 add_slaves = set(config_slaves).difference(set(running_slaves))
356 del_slaves = set(running_slaves).difference(set(config_slaves))
357 if add_slaves:
358 for s in add_slaves:
359 try:
360 sobj = None
361 if ifaceobj_getfunc:
362 sobj = ifaceobj_getfunc(s)
363 self._up_vrf_slave(s, ifaceobj.name,
364 sobj[0] if sobj else None,
365 ifaceobj_getfunc, True)
366 except Exception, e:
367 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
368
369 if del_slaves:
370 for s in del_slaves:
371 try:
372 if ifaceobj_getfunc:
373 sobj = ifaceobj_getfunc(s)
374 # if dhcp slave, release the dhcp lease
375 if sobj and self._is_dhcp_slave(sobj[0]):
376 self._down_dhcp_slave(sobj[0])
377 self._down_vrf_slave(s, ifaceobj.name)
378 except Exception, e:
379 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
380
381 if ifaceobj.link_type == ifaceLinkType.LINK_MASTER:
382 for s in config_slaves:
383 try:
384 rtnetlink_api.rtnl_api.link_set(s, "up")
385 except Exception, e:
386 self.logger.debug('%s: %s: link set up (%s)'
387 %(ifaceobj.name, s, str(e)))
388 pass
389
390 def _create_cgroup(self, ifaceobj):
391 if not self.vrf_cgroup_create:
392 return
393 try:
394 if not os.path.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj.name):
395 self.exec_command('/usr/bin/cgcreate -g l3mdev:%s' %ifaceobj.name)
396 except Exception, e:
397 self.log_error('%s: cgroup create failed (%s)\n'
398 %(ifaceobj.name, str(e)), ifaceobj)
399 try:
400 self.exec_command('/usr/bin/cgset -r l3mdev.master-device=%s %s'
401 %(ifaceobj.name, ifaceobj.name))
402 except Exception, e:
403 self.log_warn('%s: cgset failed (%s)\n'
404 %(ifaceobj.name, str(e)), ifaceobj)
405
406 def _set_vrf_dev_processed_flag(self, ifaceobj):
407 ifaceobj.module_flags[self.name] = \
408 ifaceobj.module_flags.setdefault(self.name, 0) | \
409 vrfPrivFlags.PROCESSED
410
411 def _check_vrf_dev_processed_flag(self, ifaceobj):
412 if (ifaceobj.module_flags.get(self.name, 0x0) & vrfPrivFlags.PROCESSED):
413 return True
414 return False
415
416 def _create_vrf_dev(self, ifaceobj, vrf_table):
417 if not self.ipcmd.link_exists(ifaceobj.name):
418 if vrf_table == 'auto':
419 vrf_table = self._get_avail_vrf_table_id()
420 if not vrf_table:
421 self.log_error('%s: unable to get an auto table id'
422 %ifaceobj.name)
423 self.logger.info('%s: table id auto: selected table id %s\n'
424 %(ifaceobj.name, vrf_table))
425
426 if not vrf_table.isdigit():
427 self.log_error('%s: vrf-table must be an integer or \'auto\''
428 %(ifaceobj.name), ifaceobj)
429
430 # XXX: If we decide to not allow vrf id usages out of
431 # the reserved ifupdown range, then uncomment this code.
432 else:
433 if (int(vrf_table) < self.vrf_table_id_start or
434 int(vrf_table) > self.vrf_table_id_end):
435 self.log_error('%s: vrf table id %s out of reserved range [%d,%d]'
436 %(ifaceobj.name, vrf_table,
437 self.vrf_table_id_start,
438 self.vrf_table_id_end))
439 try:
440 self.ipcmd.link_create(ifaceobj.name, 'vrf',
441 {'table' : '%s' %vrf_table})
442 except Exception, e:
443 self.log_error('%s: create failed (%s)\n'
444 %(ifaceobj.name, str(e)))
445 else:
446 if vrf_table == 'auto':
447 vrf_table = self._get_iproute2_vrf_table(ifaceobj.name)
448 if not vrf_table:
449 self.log_error('%s: unable to get vrf table id'
450 %ifaceobj.name)
451
452 # if the device exists, check if table id is same
453 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobj.name)
454 if vrfdev_attrs:
455 running_table = vrfdev_attrs.get('table', None)
456 if vrf_table != running_table:
457 self.log_error('%s: cannot change vrf table id,running table id %s is different from config id %s' %(ifaceobj.name,
458 running_table, vrf_table))
459 if vrf_table != 'auto':
460 self._iproute2_vrf_table_entry_add(ifaceobj.name, vrf_table)
461
462 return vrf_table
463
464 def _add_vrf_default_route(self, ifaceobj, vrf_table):
465 vrf_default_route = ifaceobj.get_attr_value_first('vrf-default-route')
466 if not vrf_default_route:
467 vrf_default_route = policymanager.policymanager_api.get_attr_default(
468 module_name=self.__class__.__name__,
469 attr='vrf-default-route')
470 if not vrf_default_route:
471 return
472 if str(vrf_default_route).lower() == "yes":
473 try:
474 self.exec_command('ip route add table %s unreachable default'
475 ' metric %d' %(vrf_table, 240))
476 except OSError, e:
477 if e.errno != 17:
478 raise
479 pass
480
481 try:
482 self.exec_command('ip -6 route add table %s unreachable '
483 'default metric %d' %(vrf_table, 240))
484 except OSError, e:
485 if e.errno != 17:
486 raise
487 pass
488
489 def _up_vrf_dev(self, ifaceobj, vrf_table, add_slaves=True,
490 ifaceobj_getfunc=None):
491
492 # if vrf dev is already processed return. This can happen
493 # if we had a dhcp slave. See self._handle_dhcp_slaves
494 if self._check_vrf_dev_processed_flag(ifaceobj):
495 return True
496
497 vrf_table = self._create_vrf_dev(ifaceobj, vrf_table)
498 try:
499 self._add_vrf_rules(ifaceobj.name, vrf_table)
500 self._create_cgroup(ifaceobj)
501 if add_slaves:
502 self._add_vrf_slaves(ifaceobj, ifaceobj_getfunc)
503 self._add_vrf_default_route(ifaceobj, vrf_table)
504 self._set_vrf_dev_processed_flag(ifaceobj)
505 except Exception, e:
506 self.log_error('%s: %s' %(ifaceobj.name, str(e)))
507
508 def _up(self, ifaceobj, ifaceobj_getfunc=None):
509 try:
510 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
511 if vrf_table:
512 # This is a vrf device
513 if self.vrf_count == self.vrf_max_count:
514 self.log_error('%s: max vrf count %d hit...not '
515 'creating vrf' %(ifaceobj.name,
516 self.vrf_count))
517 self._up_vrf_dev(ifaceobj, vrf_table, True, ifaceobj_getfunc)
518 else:
519 vrf = ifaceobj.get_attr_value_first('vrf')
520 if vrf:
521 # This is a vrf slave
522 self._up_vrf_slave(ifaceobj.name, vrf, ifaceobj,
523 ifaceobj_getfunc)
524 except Exception, e:
525 self.log_error(str(e))
526
527 def _delete_cgroup(self, ifaceobj):
528 try:
529 if os.path.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj.name):
530 self.exec_command('/usr/bin/cgdelete -g l3mdev:%s' %ifaceobj.name)
531 except Exception, e:
532 self.log_info('%s: cgroup delete failed (%s)\n'
533 %(ifaceobj.name, str(e)), ifaceobj)
534
535 def _down_vrf_dev(self, ifaceobj, vrf_table, ifaceobj_getfunc=None):
536 if vrf_table == 'auto':
537 vrf_table = self._get_iproute2_vrf_table(ifaceobj.name)
538 try:
539 running_slaves = self.ipcmd.link_get_lowers(ifaceobj.name)
540 if running_slaves:
541 for s in running_slaves:
542 if ifaceobj_getfunc:
543 sobj = ifaceobj_getfunc(s)
544 # if dhcp slave, release the dhcp lease
545 if sobj and self._is_dhcp_slave(sobj[0]):
546 self._down_dhcp_slave(sobj[0])
547 except Exception, e:
548 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
549 pass
550
551 try:
552 self._del_vrf_rules(ifaceobj.name, vrf_table)
553 except Exception, e:
554 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
555 pass
556
557 try:
558 self.ipcmd.link_delete(ifaceobj.name)
559 except Exception, e:
560 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
561 pass
562
563 try:
564 self._iproute2_vrf_table_entry_del(vrf_table)
565 self._delete_cgroup(ifaceobj)
566 except Exception, e:
567 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
568 pass
569
570
571 def _down_vrf_slave(self, ifacename, vrf):
572 try:
573 self.ipcmd.link_set(ifacename, 'nomaster')
574 except Exception, e:
575 self.logger.warn('%s: %s' %(ifacename, str(e)))
576
577 def _down(self, ifaceobj, ifaceobj_getfunc=None):
578 try:
579 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
580 if vrf_table:
581 self._down_vrf_dev(ifaceobj, vrf_table, ifaceobj_getfunc)
582 else:
583 vrf = ifaceobj.get_attr_value_first('vrf')
584 if vrf:
585 self._down_vrf_slave(ifaceobj.name, vrf)
586 except Exception, e:
587 self.log_warn(str(e))
588
589 def _query_check_vrf_slave(self, ifaceobj, ifaceobjcurr, vrf):
590 try:
591 master = self.ipcmd.link_get_master(ifaceobj.name)
592 if not master or master != vrf:
593 ifaceobjcurr.update_config_with_status('vrf', master, 1)
594 else:
595 ifaceobjcurr.update_config_with_status('vrf', master, 0)
596 except Exception, e:
597 self.log_warn(str(e))
598
599 def _query_check_vrf_dev(self, ifaceobj, ifaceobjcurr, vrf_table):
600 try:
601 if not self.ipcmd.link_exists(ifaceobj.name):
602 self.logger.info('%s: vrf: does not exist' %(ifaceobj.name))
603 return
604 if vrf_table == 'auto':
605 config_table = self._get_iproute2_vrf_table(ifaceobj.name)
606 else:
607 config_table = vrf_table
608 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobj.name)
609 if not vrfdev_attrs:
610 ifaceobjcurr.update_config_with_status('vrf-table', 'None', 1)
611 return
612 running_table = vrfdev_attrs.get('table')
613 if not running_table:
614 ifaceobjcurr.update_config_with_status('vrf-table', 'None', 1)
615 return
616 if config_table != running_table:
617 ifaceobjcurr.update_config_with_status('vrf-table',
618 running_table, 1)
619 else:
620 ifaceobjcurr.update_config_with_status('vrf-table',
621 running_table, 0)
622 except Exception, e:
623 self.log_warn(str(e))
624
625 def _query_check(self, ifaceobj, ifaceobjcurr):
626 try:
627 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
628 if vrf_table:
629 self._query_check_vrf_dev(ifaceobj, ifaceobjcurr, vrf_table)
630 else:
631 vrf = ifaceobj.get_attr_value_first('vrf')
632 if vrf:
633 self._query_check_vrf_slave(ifaceobj, ifaceobjcurr, vrf)
634 except Exception, e:
635 self.log_warn(str(e))
636
637 def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
638 try:
639 kind = self.ipcmd.link_get_kind(ifaceobjrunning.name)
640 if kind == 'vrf':
641 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobjrunning.name)
642 if vrfdev_attrs:
643 running_table = vrfdev_attrs.get('table')
644 if running_table:
645 ifaceobjrunning.update_config('vrf-table',
646 running_table)
647 elif kind == 'vrf_slave':
648 vrf = self.ipcmd.link_get_master(ifaceobjrunning.name)
649 if vrf:
650 ifaceobjrunning.update_config('vrf', vrf)
651 except Exception, e:
652 self.log_warn(str(e))
653
654 _run_ops = {'pre-up' : _up,
655 'post-down' : _down,
656 'query-running' : _query_running,
657 'query-checkcurr' : _query_check}
658
659 def get_ops(self):
660 """ returns list of ops supported by this module """
661 return self._run_ops.keys()
662
663 def _init_command_handlers(self):
664 flags = self.get_flags()
665 if not self.ipcmd:
666 self.ipcmd = iproute2(**flags)
667 if not self.bondcmd:
668 self.bondcmd = bondutil(**flags)
669 if not self.dhclientcmd:
670 self.dhclientcmd = dhclient(**flags)
671
672 def run(self, ifaceobj, operation, query_ifaceobj=None,
673 ifaceobj_getfunc=None, **extra_args):
674 """ run bond configuration on the interface object passed as argument
675
676 Args:
677 **ifaceobj** (object): iface object
678
679 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
680 'query-running'
681
682 Kwargs:
683 **query_ifaceobj** (object): query check ifaceobject. This is only
684 valid when op is 'query-checkcurr'. It is an object same as
685 ifaceobj, but contains running attribute values and its config
686 status. The modules can use it to return queried running state
687 of interfaces. status is success if the running state is same
688 as user required state in ifaceobj. error otherwise.
689 """
690 op_handler = self._run_ops.get(operation)
691 if not op_handler:
692 return
693 self._init_command_handlers()
694 if operation == 'query-checkcurr':
695 op_handler(self, ifaceobj, query_ifaceobj)
696 else:
697 op_handler(self, ifaceobj, ifaceobj_getfunc=ifaceobj_getfunc)