]> git.proxmox.com Git - mirror_ifupdown2.git/blob - addons/vrf.py
addons: vrf: release any dhcp leases before vrf slave enslavement
[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[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 self.iproute2_write_vrf_map = False
130 atexit.register(self.iproute2_vrf_map_write)
131 self.vrf_fix_local_table = True
132 self.vrf_count = 0
133 self.vrf_cgroup_create = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-cgroup-create')
134 if not self.vrf_cgroup_create:
135 self.vrf_cgroup_create = False
136 elif self.vrf_cgroup_create == 'yes':
137 self.vrf_cgroup_create = True
138 else:
139 self.vrf_cgroup_create = False
140
141 def iproute2_vrf_map_write(self):
142 if not self.iproute2_write_vrf_map:
143 return
144 self.logger.info('vrf: writing table map to %s'
145 %self.iproute2_vrf_filename)
146 with open(self.iproute2_vrf_filename, 'w') as f:
147 f.write(self.iproute2_vrf_filehdr %(self.vrf_table_id_start,
148 self.vrf_table_id_end))
149 for t, v in self.iproute2_vrf_map.iteritems():
150 f.write('%s %s\n' %(t, v))
151
152 def _is_vrf(self, ifaceobj):
153 if ifaceobj.get_attr_value_first('vrf-table'):
154 return True
155 return False
156
157 def get_upper_ifacenames(self, ifaceobj, ifacenames_all=None):
158 """ Returns list of interfaces dependent on ifaceobj """
159
160 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
161 if vrf_table:
162 ifaceobj.link_type = ifaceLinkType.LINK_MASTER
163 ifaceobj.link_kind |= ifaceLinkKind.VRF
164 vrf_iface_name = ifaceobj.get_attr_value_first('vrf')
165 if not vrf_iface_name:
166 return None
167 ifaceobj.link_type = ifaceLinkType.LINK_SLAVE
168 ifaceobj.link_kind |= ifaceLinkKind.VRF_SLAVE
169
170 return [vrf_iface_name]
171
172 def get_upper_ifacenames_running(self, ifaceobj):
173 return None
174
175 def _get_iproute2_vrf_table(self, vrf_dev_name):
176 for t, v in self.iproute2_vrf_map.iteritems():
177 if v == vrf_dev_name:
178 return t
179 return None
180
181 def _get_avail_vrf_table_id(self):
182 if self.last_used_vrf_table == None:
183 table_id_start = self.vrf_table_id_start
184 else:
185 table_id_start = self.last_used_vrf_table + 1
186 for t in range(table_id_start,
187 self.vrf_table_id_end):
188 if not self.iproute2_vrf_map.get(t):
189 self.last_used_vrf_table = t
190 return str(t)
191 return None
192
193 def _iproute2_vrf_table_entry_add(self, vrf_dev_name, table_id):
194 self.iproute2_vrf_map[table_id] = vrf_dev_name
195 self.iproute2_write_vrf_map = True
196
197 def _iproute2_vrf_table_entry_del(self, table_id):
198 try:
199 del self.iproute2_vrf_map[table_id]
200 self.iproute2_write_vrf_map = True
201 except Exception, e:
202 self.logger.info('vrf: iproute2 vrf map del failed for %d (%s)'
203 %(table_id, str(e)))
204 pass
205
206 def _is_dhcp_slave(self, ifaceobj):
207 if (not ifaceobj.addr_method or
208 (ifaceobj.addr_method != 'dhcp' and
209 ifaceobj.addr_method != 'dhcp6')):
210 return False
211 return True
212
213 def _handle_dhcp_slaves(self, ifacename, vrfname, ifaceobj,
214 ifaceobj_getfunc):
215 """ If we have a vrf slave that has dhcp configured, bring up the
216 vrf master now. This is needed because vrf has special handling
217 in dhclient hook which requires the vrf master to be present """
218 if not self._is_dhcp_slave(ifaceobj):
219 return False
220 vrf_master = ifaceobj.upperifaces[0]
221 if not vrf_master:
222 self.logger.warn('%s: vrf master not found' %ifacename)
223 return
224 if os.path.exists('/sys/class/net/%s' %vrf_master):
225 self.logger.info('%s: vrf master %s exists returning'
226 %(ifacename, vrf_master))
227 return
228 vrf_master_objs = ifaceobj_getfunc(vrf_master)
229 if not vrf_master_objs:
230 self.logger.warn('%s: vrf master ifaceobj not found' %ifacename)
231 return
232 self.logger.info('%s: bringing up vrf master %s'
233 %(ifacename, vrf_master))
234 for mobj in vrf_master_objs:
235 vrf_table = mobj.get_attr_value_first('vrf-table')
236 if vrf_table:
237 if vrf_table == 'auto':
238 vrf_table = self._get_avail_vrf_table_id()
239 if not vrf_table:
240 self.log_error('%s: unable to get an auto table id'
241 %mobj.name)
242 self.logger.info('%s: table id auto: selected table id %s\n'
243 %(mobj.name, vrf_table))
244 self._up_vrf_dev(mobj, vrf_table, False)
245 break
246 self._down_dhcp_slave(ifaceobj)
247 self.ipcmd.link_set(ifacename, 'master', vrfname)
248 return
249
250 def _down_dhcp_slave(self, ifaceobj):
251 try:
252 self.dhclientcmd.release(ifaceobj.name)
253 except:
254 # ignore any dhclient release errors
255 pass
256
257 def _up_vrf_slave(self, ifacename, vrfname, ifaceobj=None,
258 ifaceobj_getfunc=None):
259 try:
260 if self.ipcmd.link_exists(vrfname):
261 upper = self.ipcmd.link_get_upper(vrfname)
262 if upper and upper != vrfname:
263 if self._is_dhcp_slave(ifaceobj):
264 self._down_dhcp_slave(ifaceobj)
265 self.ipcmd.link_set(ifacename, 'master', vrfname)
266 elif ifaceobj:
267 self._handle_dhcp_slaves(ifacename, vrfname, ifaceobj,
268 ifaceobj_getfunc)
269 except Exception, e:
270 self.logger.warn('%s: %s' %(ifacename, str(e)))
271
272 def _del_vrf_rules(self, vrf_dev_name, vrf_table):
273 pref = 200
274 ip_rule_out_format = '%s: from all %s %s lookup %s'
275 ip_rule_cmd = 'ip %s rule del pref %s %s %s table %s'
276
277 rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
278 if rule in self.ip_rule_cache:
279 rule_cmd = ip_rule_cmd %('', pref, 'oif', vrf_dev_name, vrf_table)
280 self.exec_command(rule_cmd)
281
282 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
283 if rule in self.ip_rule_cache:
284 rule_cmd = ip_rule_cmd %('', pref, 'iif', vrf_dev_name, vrf_table)
285 self.exec_command(rule_cmd)
286
287 rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
288 if rule in self.ip_rule_cache:
289 rule_cmd = ip_rule_cmd %('-6', pref, 'oif', vrf_dev_name,
290 vrf_table)
291 self.exec_command(rule_cmd)
292
293 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
294 if rule in self.ip_rule_cache:
295 rule_cmd = ip_rule_cmd %('-6', pref, 'iif', vrf_dev_name,
296 vrf_table)
297 self.exec_command(rule_cmd)
298
299 def _add_vrf_rules(self, vrf_dev_name, vrf_table):
300 pref = 200
301 ip_rule_out_format = '%s: from all %s %s lookup %s'
302 ip_rule_cmd = 'ip %s rule add pref %s %s %s table %s'
303 if self.vrf_fix_local_table:
304 self.vrf_fix_local_table = False
305 rule = '0: from all lookup local'
306 if rule in self.ip_rule_cache:
307 try:
308 self.exec_command('ip rule del pref 0')
309 self.exec_command('ip rule add pref 32765 table local')
310 except Exception, e:
311 self.logger.info('%s' %str(e))
312 pass
313
314 #Example ip rule
315 #200: from all oif blue lookup blue
316 #200: from all iif blue lookup blue
317
318 rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
319 if rule not in self.ip_rule_cache:
320 rule_cmd = ip_rule_cmd %('', pref, 'oif', vrf_dev_name, vrf_table)
321 self.exec_command(rule_cmd)
322
323 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
324 if rule not in self.ip_rule_cache:
325 rule_cmd = ip_rule_cmd %('', pref, 'iif', vrf_dev_name, vrf_table)
326 self.exec_command(rule_cmd)
327
328 rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
329 if rule not in self.ip_rule_cache:
330 rule_cmd = ip_rule_cmd %('-6', pref, 'oif', vrf_dev_name, vrf_table)
331 self.exec_command(rule_cmd)
332
333 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
334 if rule not in self.ip_rule_cache:
335 rule_cmd = ip_rule_cmd %('-6', pref, 'iif', vrf_dev_name,
336 vrf_table)
337 self.exec_command(rule_cmd)
338
339 def _add_vrf_slaves(self, ifaceobj):
340 running_slaves = self.ipcmd.link_get_lowers(ifaceobj.name)
341 config_slaves = ifaceobj.lowerifaces
342 if not config_slaves and not running_slaves:
343 return
344 add_slaves = set(config_slaves).difference(set(running_slaves))
345 del_slaves = set(running_slaves).difference(set(config_slaves))
346 if add_slaves:
347 for s in add_slaves:
348 try:
349 self._up_vrf_slave(s, ifaceobj.name)
350 except Exception, e:
351 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
352
353 if del_slaves:
354 for s in del_slaves:
355 try:
356 self._down_vrf_slave(s, ifaceobj.name)
357 except Exception, e:
358 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
359
360 if ifaceobj.link_type == ifaceLinkType.LINK_MASTER:
361 for s in config_slaves:
362 try:
363 rtnetlink_api.rtnl_api.link_set(s, "up")
364 except Exception, e:
365 self.logger.debug('%s: %s: link set up (%s)'
366 %(ifaceobj.name, s, str(e)))
367 pass
368
369 def _create_cgroup(self, ifaceobj):
370 if not self.vrf_cgroup_create:
371 return
372 try:
373 if not os.path.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj.name):
374 self.exec_command('/usr/bin/cgcreate -g l3mdev:%s' %ifaceobj.name)
375 except Exception, e:
376 self.log_error('%s: cgroup create failed (%s)\n'
377 %(ifaceobj.name, str(e)), ifaceobj)
378 try:
379 self.exec_command('/usr/bin/cgset -r l3mdev.master-device=%s %s'
380 %(ifaceobj.name, ifaceobj.name))
381 except Exception, e:
382 self.log_warn('%s: cgset failed (%s)\n'
383 %(ifaceobj.name, str(e)), ifaceobj)
384
385 def _set_vrf_dev_processed_flag(self, ifaceobj):
386 ifaceobj.module_flags[self.name] = \
387 ifaceobj.module_flags.setdefault(self.name, 0) | \
388 vrfPrivFlags.PROCESSED
389
390 def _check_vrf_dev_processed_flag(self, ifaceobj):
391 if (ifaceobj.module_flags.get(self.name, 0x0) & vrfPrivFlags.PROCESSED):
392 return True
393 return False
394
395 def _create_vrf_dev(self, ifaceobj, vrf_table):
396 if not self.ipcmd.link_exists(ifaceobj.name):
397 if vrf_table == 'auto':
398 vrf_table = self._get_avail_vrf_table_id()
399 if not vrf_table:
400 self.log_error('%s: unable to get an auto table id'
401 %ifaceobj.name)
402 self.logger.info('%s: table id auto: selected table id %s\n'
403 %(ifaceobj.name, vrf_table))
404 # XXX: If we decide to not allow vrf id usages out of
405 # the reserved ifupdown range, then uncomment this code.
406 #else:
407 # if (int(vrf_table) < self.vrf_table_id_start or
408 # int(vrf_table) > self.vrf_table_id_end):
409 # self.log_error('%s: vrf table id %s out of reserved range [%d,%d]'
410 # %(ifaceobj.name, vrf_table,
411 # self.vrf_table_id_start,
412 # self.vrf_table_id_end))
413 try:
414 self.ipcmd.link_create(ifaceobj.name, 'vrf',
415 {'table' : '%s' %vrf_table})
416 except Exception, e:
417 self.log_error('%s: create failed (%s)\n'
418 %(ifaceobj.name, str(e)))
419 else:
420 vrf_table = self._get_iproute2_vrf_table(ifaceobj.name)
421 if not vrf_table:
422 self.log_error('%s: unable to get vrf table id'
423 %ifaceobj.name)
424
425 # if the device exists, check if table id is same
426 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobj.name)
427 if vrfdev_attrs:
428 running_table = vrfdev_attrs.get('table', None)
429 if vrf_table != running_table:
430 self.log_error('%s: cannot change vrf table id,running table id %s is different from config id %s' %(ifaceobj.name,
431 running_table, vrf_table))
432
433 def _add_vrf_default_route(self, ifaceobj, vrf_table):
434 vrf_default_route = ifaceobj.get_attr_value_first('vrf-default-route')
435 if not vrf_default_route:
436 vrf_default_route = policymanager.policymanager_api.get_attr_default(
437 module_name=self.__class__.__name__,
438 attr='vrf-default-route')
439 if not vrf_default_route:
440 return
441 if str(vrf_default_route).lower() == "yes":
442 try:
443 self.exec_command('ip route add table %s unreachable default'
444 ' metric %d' %(vrf_table, 240))
445 except OSError, e:
446 if e.errno != 17:
447 raise
448 pass
449
450 try:
451 self.exec_command('ip -6 route add table %s unreachable '
452 'default metric %d' %(vrf_table, 240))
453 except OSError, e:
454 if e.errno != 17:
455 raise
456 pass
457
458 def _up_vrf_dev(self, ifaceobj, vrf_table, add_slaves=True):
459
460 # if vrf dev is already processed return. This can happen
461 # if we had a dhcp slave. See self._handle_dhcp_slaves
462 if self._check_vrf_dev_processed_flag(ifaceobj):
463 return True
464
465 self._create_vrf_dev(ifaceobj, vrf_table)
466 try:
467 self._iproute2_vrf_table_entry_add(ifaceobj.name, vrf_table)
468 self._add_vrf_rules(ifaceobj.name, vrf_table)
469 self._create_cgroup(ifaceobj)
470 if add_slaves:
471 self._add_vrf_slaves(ifaceobj)
472 self._add_vrf_default_route(ifaceobj, vrf_table)
473 self._set_vrf_dev_processed_flag(ifaceobj)
474 except Exception, e:
475 self.log_error('%s: %s' %(ifaceobj.name, str(e)))
476
477 def _up(self, ifaceobj, ifaceobj_getfunc=None):
478 try:
479 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
480 if vrf_table:
481 if self.vrf_count == self.vrf_max_count:
482 self.log_error('%s: max vrf count %d hit...not '
483 'creating vrf' %(ifaceobj.name,
484 self.vrf_count))
485 self._up_vrf_dev(ifaceobj, vrf_table)
486 else:
487 vrf = ifaceobj.get_attr_value_first('vrf')
488 if vrf:
489 self._up_vrf_slave(ifaceobj.name, vrf, ifaceobj,
490 ifaceobj_getfunc)
491 except Exception, e:
492 self.log_error(str(e))
493
494 def _delete_cgroup(self, ifaceobj):
495 try:
496 if os.path.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj.name):
497 self.exec_command('cgdelete -g l3mdev:%s' %ifaceobj.name)
498 except Exception, e:
499 self.log_warn('%s: cgroup delete failed (%s)\n'
500 %(ifaceobj.name, str(e)), ifaceobj)
501
502 def _down_vrf_dev(self, ifaceobj, vrf_table):
503 if vrf_table == 'auto':
504 vrf_table = self._get_iproute2_vrf_table(ifaceobj.name)
505 try:
506 self.ipcmd.link_delete(ifaceobj.name)
507 except Exception, e:
508 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
509 pass
510
511 try:
512 self._iproute2_vrf_table_entry_del(vrf_table)
513 self._delete_cgroup(ifaceobj)
514 except Exception, e:
515 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
516 pass
517
518 try:
519 self._del_vrf_rules(ifaceobj.name, vrf_table)
520 except Exception, e:
521 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
522 pass
523
524 def _down_vrf_slave(self, ifacename, vrf):
525 try:
526 self.ipcmd.link_set(ifacename, 'nomaster')
527 except Exception, e:
528 self.logger.warn('%s: %s' %(ifacename, str(e)))
529
530 def _down(self, ifaceobj, ifaceobj_getfunc=None):
531 try:
532 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
533 if vrf_table:
534 self._down_vrf_dev(ifaceobj, vrf_table)
535 else:
536 vrf = ifaceobj.get_attr_value_first('vrf')
537 if vrf:
538 self._down_vrf_slave(ifaceobj.name, vrf)
539 except Exception, e:
540 self.log_warn(str(e))
541
542 def _query_check_vrf_slave(self, ifaceobj, ifaceobjcurr, vrf):
543 try:
544 master = self.ipcmd.link_get_master(ifaceobj.name)
545 if not master or master != vrf:
546 ifaceobjcurr.update_config_with_status('vrf', master, 1)
547 else:
548 ifaceobjcurr.update_config_with_status('vrf', master, 0)
549 except Exception, e:
550 self.log_warn(str(e))
551
552 def _query_check_vrf_dev(self, ifaceobj, ifaceobjcurr, vrf_table):
553 try:
554 if not self.ipcmd.link_exists(ifaceobj.name):
555 self.logger.info('%s: vrf: does not exist' %(ifaceobj.name))
556 return
557 if vrf_table == 'auto':
558 config_table = self._get_iproute2_vrf_table(ifaceobj.name)
559 else:
560 config_table = vrf_table
561 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobj.name)
562 if not vrfdev_attrs:
563 ifaceobjcurr.update_config_with_status('vrf-table', 'None', 1)
564 return
565 running_table = vrfdev_attrs.get('table')
566 if not running_table:
567 ifaceobjcurr.update_config_with_status('vrf-table', 'None', 1)
568 return
569 if config_table != running_table:
570 ifaceobjcurr.update_config_with_status('vrf-table',
571 running_table, 1)
572 else:
573 ifaceobjcurr.update_config_with_status('vrf-table',
574 running_table, 0)
575 except Exception, e:
576 self.log_warn(str(e))
577
578 def _query_check(self, ifaceobj, ifaceobjcurr):
579 try:
580 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
581 if vrf_table:
582 self._query_check_vrf_dev(ifaceobj, ifaceobjcurr, vrf_table)
583 else:
584 vrf = ifaceobj.get_attr_value_first('vrf')
585 if vrf:
586 self._query_check_vrf_slave(ifaceobj, ifaceobjcurr, vrf)
587 except Exception, e:
588 self.log_warn(str(e))
589
590 def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
591 try:
592 kind = self.ipcmd.link_get_kind(ifaceobjrunning.name)
593 if kind == 'vrf':
594 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobjrunning.name)
595 if vrfdev_attrs:
596 running_table = vrfdev_attrs.get('table')
597 if running_table:
598 ifaceobjrunning.update_config('vrf-table',
599 running_table)
600 elif kind == 'vrf_slave':
601 vrf = self.ipcmd.link_get_master(ifaceobjrunning.name)
602 if vrf:
603 ifaceobjrunning.update_config('vrf', vrf)
604 except Exception, e:
605 self.log_warn(str(e))
606
607 _run_ops = {'pre-up' : _up,
608 'post-down' : _down,
609 'query-running' : _query_running,
610 'query-checkcurr' : _query_check}
611
612 def get_ops(self):
613 """ returns list of ops supported by this module """
614 return self._run_ops.keys()
615
616 def _init_command_handlers(self):
617 flags = self.get_flags()
618 if not self.ipcmd:
619 self.ipcmd = iproute2(**flags)
620 if not self.bondcmd:
621 self.bondcmd = bondutil(**flags)
622 if not self.dhclientcmd:
623 self.dhclientcmd = dhclient(**flags)
624
625 def run(self, ifaceobj, operation, query_ifaceobj=None,
626 ifaceobj_getfunc=None, **extra_args):
627 """ run bond configuration on the interface object passed as argument
628
629 Args:
630 **ifaceobj** (object): iface object
631
632 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
633 'query-running'
634
635 Kwargs:
636 **query_ifaceobj** (object): query check ifaceobject. This is only
637 valid when op is 'query-checkcurr'. It is an object same as
638 ifaceobj, but contains running attribute values and its config
639 status. The modules can use it to return queried running state
640 of interfaces. status is success if the running state is same
641 as user required state in ifaceobj. error otherwise.
642 """
643 op_handler = self._run_ops.get(operation)
644 if not op_handler:
645 return
646 self._init_command_handlers()
647 if operation == 'query-checkcurr':
648 op_handler(self, ifaceobj, query_ifaceobj)
649 else:
650 op_handler(self, ifaceobj, ifaceobj_getfunc=ifaceobj_getfunc)