]> git.proxmox.com Git - mirror_ifupdown2.git/blob - addons/vrf.py
addons: vrf: fix a few vrf enslavement and table id allocation corner cases
[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 not upper or 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.log_error('%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, ifaceobj_getfunc=None):
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
345 if not config_slaves: config_slaves = []
346 if not running_slaves: running_slaves = []
347 add_slaves = set(config_slaves).difference(set(running_slaves))
348 del_slaves = set(running_slaves).difference(set(config_slaves))
349 if add_slaves:
350 for s in add_slaves:
351 try:
352 self._up_vrf_slave(s, ifaceobj.name)
353 except Exception, e:
354 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
355
356 if del_slaves:
357 for s in del_slaves:
358 try:
359 if ifaceobj_getfunc:
360 sobj = ifaceobj_getfunc(s)
361 # if dhcp slave, release the dhcp lease
362 if sobj and self._is_dhcp_slave(sobj[0]):
363 self._down_dhcp_slave(sobj[0])
364 self._down_vrf_slave(s, ifaceobj.name)
365 except Exception, e:
366 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
367
368 if ifaceobj.link_type == ifaceLinkType.LINK_MASTER:
369 for s in config_slaves:
370 try:
371 rtnetlink_api.rtnl_api.link_set(s, "up")
372 except Exception, e:
373 self.logger.debug('%s: %s: link set up (%s)'
374 %(ifaceobj.name, s, str(e)))
375 pass
376
377 def _create_cgroup(self, ifaceobj):
378 if not self.vrf_cgroup_create:
379 return
380 try:
381 if not os.path.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj.name):
382 self.exec_command('/usr/bin/cgcreate -g l3mdev:%s' %ifaceobj.name)
383 except Exception, e:
384 self.log_error('%s: cgroup create failed (%s)\n'
385 %(ifaceobj.name, str(e)), ifaceobj)
386 try:
387 self.exec_command('/usr/bin/cgset -r l3mdev.master-device=%s %s'
388 %(ifaceobj.name, ifaceobj.name))
389 except Exception, e:
390 self.log_warn('%s: cgset failed (%s)\n'
391 %(ifaceobj.name, str(e)), ifaceobj)
392
393 def _set_vrf_dev_processed_flag(self, ifaceobj):
394 ifaceobj.module_flags[self.name] = \
395 ifaceobj.module_flags.setdefault(self.name, 0) | \
396 vrfPrivFlags.PROCESSED
397
398 def _check_vrf_dev_processed_flag(self, ifaceobj):
399 if (ifaceobj.module_flags.get(self.name, 0x0) & vrfPrivFlags.PROCESSED):
400 return True
401 return False
402
403 def _create_vrf_dev(self, ifaceobj, vrf_table):
404 if not self.ipcmd.link_exists(ifaceobj.name):
405 if vrf_table == 'auto':
406 vrf_table = self._get_avail_vrf_table_id()
407 if not vrf_table:
408 self.log_error('%s: unable to get an auto table id'
409 %ifaceobj.name)
410 self.logger.info('%s: table id auto: selected table id %s\n'
411 %(ifaceobj.name, vrf_table))
412
413 if not vrf_table.isdigit():
414 self.log_error('%s: vrf-table must be an integer or \'auto\''
415 %(ifaceobj.name), ifaceobj)
416
417 # XXX: If we decide to not allow vrf id usages out of
418 # the reserved ifupdown range, then uncomment this code.
419 #else:
420 # if (int(vrf_table) < self.vrf_table_id_start or
421 # int(vrf_table) > self.vrf_table_id_end):
422 # self.log_error('%s: vrf table id %s out of reserved range [%d,%d]'
423 # %(ifaceobj.name, vrf_table,
424 # self.vrf_table_id_start,
425 # self.vrf_table_id_end))
426 try:
427 self.ipcmd.link_create(ifaceobj.name, 'vrf',
428 {'table' : '%s' %vrf_table})
429 except Exception, e:
430 self.log_error('%s: create failed (%s)\n'
431 %(ifaceobj.name, str(e)))
432 else:
433 if vrf_table == 'auto':
434 vrf_table = self._get_iproute2_vrf_table(ifaceobj.name)
435 if not vrf_table:
436 self.log_error('%s: unable to get vrf table id'
437 %ifaceobj.name)
438
439 # if the device exists, check if table id is same
440 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobj.name)
441 if vrfdev_attrs:
442 running_table = vrfdev_attrs.get('table', None)
443 if vrf_table != running_table:
444 self.log_error('%s: cannot change vrf table id,running table id %s is different from config id %s' %(ifaceobj.name,
445 running_table, vrf_table))
446 if vrf_table != 'auto':
447 self._iproute2_vrf_table_entry_add(ifaceobj.name, vrf_table)
448
449 return vrf_table
450
451 def _add_vrf_default_route(self, ifaceobj, vrf_table):
452 vrf_default_route = ifaceobj.get_attr_value_first('vrf-default-route')
453 if not vrf_default_route:
454 vrf_default_route = policymanager.policymanager_api.get_attr_default(
455 module_name=self.__class__.__name__,
456 attr='vrf-default-route')
457 if not vrf_default_route:
458 return
459 if str(vrf_default_route).lower() == "yes":
460 try:
461 self.exec_command('ip route add table %s unreachable default'
462 ' metric %d' %(vrf_table, 240))
463 except OSError, e:
464 if e.errno != 17:
465 raise
466 pass
467
468 try:
469 self.exec_command('ip -6 route add table %s unreachable '
470 'default metric %d' %(vrf_table, 240))
471 except OSError, e:
472 if e.errno != 17:
473 raise
474 pass
475
476 def _up_vrf_dev(self, ifaceobj, vrf_table, add_slaves=True,
477 ifaceobj_getfunc=None):
478
479 # if vrf dev is already processed return. This can happen
480 # if we had a dhcp slave. See self._handle_dhcp_slaves
481 if self._check_vrf_dev_processed_flag(ifaceobj):
482 return True
483
484 vrf_table = self._create_vrf_dev(ifaceobj, vrf_table)
485 try:
486 self._add_vrf_rules(ifaceobj.name, vrf_table)
487 self._create_cgroup(ifaceobj)
488 if add_slaves:
489 self._add_vrf_slaves(ifaceobj, ifaceobj_getfunc)
490 self._add_vrf_default_route(ifaceobj, vrf_table)
491 self._set_vrf_dev_processed_flag(ifaceobj)
492 except Exception, e:
493 self.log_error('%s: %s' %(ifaceobj.name, str(e)))
494
495 def _up(self, ifaceobj, ifaceobj_getfunc=None):
496 try:
497 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
498 if vrf_table:
499 if self.vrf_count == self.vrf_max_count:
500 self.log_error('%s: max vrf count %d hit...not '
501 'creating vrf' %(ifaceobj.name,
502 self.vrf_count))
503 self._up_vrf_dev(ifaceobj, vrf_table, True, ifaceobj_getfunc)
504 else:
505 vrf = ifaceobj.get_attr_value_first('vrf')
506 if vrf:
507 self._up_vrf_slave(ifaceobj.name, vrf, ifaceobj,
508 ifaceobj_getfunc)
509 except Exception, e:
510 self.log_error(str(e))
511
512 def _delete_cgroup(self, ifaceobj):
513 try:
514 if os.path.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj.name):
515 self.exec_command('cgdelete -g l3mdev:%s' %ifaceobj.name)
516 except Exception, e:
517 self.log_warn('%s: cgroup delete failed (%s)\n'
518 %(ifaceobj.name, str(e)), ifaceobj)
519
520 def _down_vrf_dev(self, ifaceobj, vrf_table):
521 if vrf_table == 'auto':
522 vrf_table = self._get_iproute2_vrf_table(ifaceobj.name)
523 try:
524 self.ipcmd.link_delete(ifaceobj.name)
525 except Exception, e:
526 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
527 pass
528
529 try:
530 self._iproute2_vrf_table_entry_del(vrf_table)
531 self._delete_cgroup(ifaceobj)
532 except Exception, e:
533 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
534 pass
535
536 try:
537 self._del_vrf_rules(ifaceobj.name, vrf_table)
538 except Exception, e:
539 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
540 pass
541
542 def _down_vrf_slave(self, ifacename, vrf):
543 try:
544 self.ipcmd.link_set(ifacename, 'nomaster')
545 except Exception, e:
546 self.logger.warn('%s: %s' %(ifacename, str(e)))
547
548 def _down(self, ifaceobj, ifaceobj_getfunc=None):
549 try:
550 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
551 if vrf_table:
552 self._down_vrf_dev(ifaceobj, vrf_table)
553 else:
554 vrf = ifaceobj.get_attr_value_first('vrf')
555 if vrf:
556 self._down_vrf_slave(ifaceobj.name, vrf)
557 except Exception, e:
558 self.log_warn(str(e))
559
560 def _query_check_vrf_slave(self, ifaceobj, ifaceobjcurr, vrf):
561 try:
562 master = self.ipcmd.link_get_master(ifaceobj.name)
563 if not master or master != vrf:
564 ifaceobjcurr.update_config_with_status('vrf', master, 1)
565 else:
566 ifaceobjcurr.update_config_with_status('vrf', master, 0)
567 except Exception, e:
568 self.log_warn(str(e))
569
570 def _query_check_vrf_dev(self, ifaceobj, ifaceobjcurr, vrf_table):
571 try:
572 if not self.ipcmd.link_exists(ifaceobj.name):
573 self.logger.info('%s: vrf: does not exist' %(ifaceobj.name))
574 return
575 if vrf_table == 'auto':
576 config_table = self._get_iproute2_vrf_table(ifaceobj.name)
577 else:
578 config_table = vrf_table
579 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobj.name)
580 if not vrfdev_attrs:
581 ifaceobjcurr.update_config_with_status('vrf-table', 'None', 1)
582 return
583 running_table = vrfdev_attrs.get('table')
584 if not running_table:
585 ifaceobjcurr.update_config_with_status('vrf-table', 'None', 1)
586 return
587 if config_table != running_table:
588 ifaceobjcurr.update_config_with_status('vrf-table',
589 running_table, 1)
590 else:
591 ifaceobjcurr.update_config_with_status('vrf-table',
592 running_table, 0)
593 except Exception, e:
594 self.log_warn(str(e))
595
596 def _query_check(self, ifaceobj, ifaceobjcurr):
597 try:
598 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
599 if vrf_table:
600 self._query_check_vrf_dev(ifaceobj, ifaceobjcurr, vrf_table)
601 else:
602 vrf = ifaceobj.get_attr_value_first('vrf')
603 if vrf:
604 self._query_check_vrf_slave(ifaceobj, ifaceobjcurr, vrf)
605 except Exception, e:
606 self.log_warn(str(e))
607
608 def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
609 try:
610 kind = self.ipcmd.link_get_kind(ifaceobjrunning.name)
611 if kind == 'vrf':
612 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobjrunning.name)
613 if vrfdev_attrs:
614 running_table = vrfdev_attrs.get('table')
615 if running_table:
616 ifaceobjrunning.update_config('vrf-table',
617 running_table)
618 elif kind == 'vrf_slave':
619 vrf = self.ipcmd.link_get_master(ifaceobjrunning.name)
620 if vrf:
621 ifaceobjrunning.update_config('vrf', vrf)
622 except Exception, e:
623 self.log_warn(str(e))
624
625 _run_ops = {'pre-up' : _up,
626 'post-down' : _down,
627 'query-running' : _query_running,
628 'query-checkcurr' : _query_check}
629
630 def get_ops(self):
631 """ returns list of ops supported by this module """
632 return self._run_ops.keys()
633
634 def _init_command_handlers(self):
635 flags = self.get_flags()
636 if not self.ipcmd:
637 self.ipcmd = iproute2(**flags)
638 if not self.bondcmd:
639 self.bondcmd = bondutil(**flags)
640 if not self.dhclientcmd:
641 self.dhclientcmd = dhclient(**flags)
642
643 def run(self, ifaceobj, operation, query_ifaceobj=None,
644 ifaceobj_getfunc=None, **extra_args):
645 """ run bond configuration on the interface object passed as argument
646
647 Args:
648 **ifaceobj** (object): iface object
649
650 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
651 'query-running'
652
653 Kwargs:
654 **query_ifaceobj** (object): query check ifaceobject. This is only
655 valid when op is 'query-checkcurr'. It is an object same as
656 ifaceobj, but contains running attribute values and its config
657 status. The modules can use it to return queried running state
658 of interfaces. status is success if the running state is same
659 as user required state in ifaceobj. error otherwise.
660 """
661 op_handler = self._run_ops.get(operation)
662 if not op_handler:
663 return
664 self._init_command_handlers()
665 if operation == 'query-checkcurr':
666 op_handler(self, ifaceobj, query_ifaceobj)
667 else:
668 op_handler(self, ifaceobj, ifaceobj_getfunc=ifaceobj_getfunc)