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