]> git.proxmox.com Git - mirror_ifupdown2.git/blame - addons/vrf.py
ifupdownmain: scheduler: propagate sched error on interfaces to upper layers
[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
122ef35b 16from ifupdownaddons.dhclient import dhclient
8465de90 17
8ad5c767
RP
18class vrfPrivFlags:
19 PROCESSED = 0x1
20
8465de90
RP
21class 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']},
54616d3f
N
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']},
8465de90
RP
33 'vrf':
34 {'help' : 'vrf the interface is part of.',
35 'example': ['vrf blue']}}}
36
a1c23686 37 iproute2_vrf_filename = '/etc/iproute2/rt_tables.d/ifupdown2_vrf_map.conf'
8465de90
RP
38 iproute2_vrf_filehdr = '# This file is autogenerated by ifupdown2.\n' + \
39 '# It contains the vrf name to table mapping.\n' + \
6f2890fc
RP
40 '# Reserved table range %s %s\n'
41 VRF_TABLE_START = 1001
42 VRF_TABLE_END = 5000
8465de90
RP
43
44 def __init__(self, *args, **kargs):
45 ifupdownaddons.modulebase.moduleBase.__init__(self, *args, **kargs)
46 self.ipcmd = None
47 self.bondcmd = None
122ef35b 48 self.dhclientcmd = None
8ad5c767 49 self.name = self.__class__.__name__
122ef35b
RP
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))
8465de90
RP
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
6f2890fc
RP
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
4a95c92f 120 self.vrf_max_count = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-max-count')
6f2890fc
RP
121
122 last_used_vrf_table = None
123 for t in range(self.vrf_table_id_start,
124 self.vrf_table_id_end):
8465de90
RP
125 if not self.iproute2_vrf_map.get(t):
126 break
6f2890fc 127 last_used_vrf_table = t
8465de90
RP
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)
3fcb15fe 131 self.vrf_fix_local_table = True
6f2890fc 132 self.vrf_count = 0
83841a51 133 self.vrf_cgroup_create = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-cgroup-create')
6f2890fc
RP
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
8465de90
RP
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:
6f2890fc
RP
147 f.write(self.iproute2_vrf_filehdr %(self.vrf_table_id_start,
148 self.vrf_table_id_end))
8465de90
RP
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
768b4ec5 157 def get_upper_ifacenames(self, ifaceobj, ifacenames_all=None):
8465de90
RP
158 """ Returns list of interfaces dependent on ifaceobj """
159
768b4ec5
RP
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
8465de90
RP
164 vrf_iface_name = ifaceobj.get_attr_value_first('vrf')
165 if not vrf_iface_name:
166 return None
768b4ec5 167 ifaceobj.link_type = ifaceLinkType.LINK_SLAVE
8ad5c767
RP
168 ifaceobj.link_kind |= ifaceLinkKind.VRF_SLAVE
169
8465de90
RP
170 return [vrf_iface_name]
171
768b4ec5 172 def get_upper_ifacenames_running(self, ifaceobj):
8465de90
RP
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):
6f2890fc
RP
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):
8465de90
RP
188 if not self.iproute2_vrf_map.get(t):
189 self.last_used_vrf_table = t
6f2890fc 190 return str(t)
8465de90
RP
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
122ef35b
RP
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
8ad5c767
RP
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 """
122ef35b
RP
218 if not self._is_dhcp_slave(ifaceobj):
219 return False
8ad5c767
RP
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:
df53966d
RP
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))
8ad5c767 244 self._up_vrf_dev(mobj, vrf_table, False)
df53966d 245 break
122ef35b 246 self._down_dhcp_slave(ifaceobj)
8ad5c767
RP
247 self.ipcmd.link_set(ifacename, 'master', vrfname)
248 return
249
122ef35b
RP
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
8ad5c767
RP
257 def _up_vrf_slave(self, ifacename, vrfname, ifaceobj=None,
258 ifaceobj_getfunc=None):
8465de90 259 try:
768b4ec5 260 if self.ipcmd.link_exists(vrfname):
122ef35b
RP
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)
8ad5c767
RP
266 elif ifaceobj:
267 self._handle_dhcp_slaves(ifacename, vrfname, ifaceobj,
268 ifaceobj_getfunc)
8465de90 269 except Exception, e:
d54baa22 270 self.log_error('%s: %s' %(ifacename, str(e)))
8465de90
RP
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
4ce47ce4 277 rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
8465de90
RP
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
4ce47ce4 282 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
8465de90
RP
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
4ce47ce4 287 rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
8465de90
RP
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
4ce47ce4 293 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
8465de90
RP
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'
659097a0
N
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:
3fcb15fe
N
308 self.exec_command('ip rule del pref 0')
309 self.exec_command('ip rule add pref 32765 table local')
659097a0
N
310 except Exception, e:
311 self.logger.info('%s' %str(e))
312 pass
8465de90 313
3fcb15fe
N
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)
8465de90
RP
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
3fcb15fe 323 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
8465de90
RP
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
3fcb15fe 328 rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
8465de90 329 if rule not in self.ip_rule_cache:
3fcb15fe 330 rule_cmd = ip_rule_cmd %('-6', pref, 'oif', vrf_dev_name, vrf_table)
8465de90
RP
331 self.exec_command(rule_cmd)
332
3fcb15fe 333 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
8465de90
RP
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
768b4ec5
RP
339 def _add_vrf_slaves(self, ifaceobj):
340 running_slaves = self.ipcmd.link_get_lowers(ifaceobj.name)
341 config_slaves = ifaceobj.lowerifaces
b94e4d24 342 if not config_slaves and not running_slaves:
867e11a2 343 return
768b4ec5
RP
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
8465de90 368
2df6a60f 369 def _create_cgroup(self, ifaceobj):
6f2890fc
RP
370 if not self.vrf_cgroup_create:
371 return
2df6a60f 372 try:
d1e1c43b 373 if not os.path.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj.name):
40103cf7 374 self.exec_command('/usr/bin/cgcreate -g l3mdev:%s' %ifaceobj.name)
8ad5c767
RP
375 except Exception, e:
376 self.log_error('%s: cgroup create failed (%s)\n'
377 %(ifaceobj.name, str(e)), ifaceobj)
378 try:
40103cf7 379 self.exec_command('/usr/bin/cgset -r l3mdev.master-device=%s %s'
2df6a60f
RP
380 %(ifaceobj.name, ifaceobj.name))
381 except Exception, e:
8ad5c767 382 self.log_warn('%s: cgset failed (%s)\n'
2df6a60f
RP
383 %(ifaceobj.name, str(e)), ifaceobj)
384
8ad5c767
RP
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
8465de90 394
8ad5c767 395 def _create_vrf_dev(self, ifaceobj, vrf_table):
2df6a60f 396 if not self.ipcmd.link_exists(ifaceobj.name):
6f2890fc
RP
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))
d54baa22
RP
404
405 if not vrf_table.isdigit():
406 self.log_error('%s: vrf-table must be an integer or \'auto\''
407 %(ifaceobj.name), ifaceobj)
408
6f2890fc
RP
409 # XXX: If we decide to not allow vrf id usages out of
410 # the reserved ifupdown range, then uncomment this code.
411 #else:
412 # if (int(vrf_table) < self.vrf_table_id_start or
413 # int(vrf_table) > self.vrf_table_id_end):
414 # self.log_error('%s: vrf table id %s out of reserved range [%d,%d]'
415 # %(ifaceobj.name, vrf_table,
416 # self.vrf_table_id_start,
417 # self.vrf_table_id_end))
2df6a60f 418 try:
8465de90
RP
419 self.ipcmd.link_create(ifaceobj.name, 'vrf',
420 {'table' : '%s' %vrf_table})
2df6a60f
RP
421 except Exception, e:
422 self.log_error('%s: create failed (%s)\n'
423 %(ifaceobj.name, str(e)))
424 else:
6f2890fc
RP
425 vrf_table = self._get_iproute2_vrf_table(ifaceobj.name)
426 if not vrf_table:
427 self.log_error('%s: unable to get vrf table id'
428 %ifaceobj.name)
429
2df6a60f
RP
430 # if the device exists, check if table id is same
431 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobj.name)
432 if vrfdev_attrs:
433 running_table = vrfdev_attrs.get('table', None)
434 if vrf_table != running_table:
6f2890fc
RP
435 self.log_error('%s: cannot change vrf table id,running table id %s is different from config id %s' %(ifaceobj.name,
436 running_table, vrf_table))
d54baa22
RP
437 if vrf_table != 'auto':
438 self._iproute2_vrf_table_entry_add(ifaceobj.name, vrf_table)
2df6a60f 439
8ad5c767 440 def _add_vrf_default_route(self, ifaceobj, vrf_table):
54616d3f
N
441 vrf_default_route = ifaceobj.get_attr_value_first('vrf-default-route')
442 if not vrf_default_route:
443 vrf_default_route = policymanager.policymanager_api.get_attr_default(
8ad5c767
RP
444 module_name=self.__class__.__name__,
445 attr='vrf-default-route')
54616d3f
N
446 if not vrf_default_route:
447 return
448 if str(vrf_default_route).lower() == "yes":
449 try:
8ad5c767 450 self.exec_command('ip route add table %s unreachable default'
05ca6f01 451 ' metric %d' %(vrf_table, 240))
54616d3f
N
452 except OSError, e:
453 if e.errno != 17:
454 raise
455 pass
456
0ba9abeb 457 try:
05ca6f01
RP
458 self.exec_command('ip -6 route add table %s unreachable '
459 'default metric %d' %(vrf_table, 240))
0ba9abeb
N
460 except OSError, e:
461 if e.errno != 17:
462 raise
463 pass
464
8ad5c767
RP
465 def _up_vrf_dev(self, ifaceobj, vrf_table, add_slaves=True):
466
467 # if vrf dev is already processed return. This can happen
468 # if we had a dhcp slave. See self._handle_dhcp_slaves
469 if self._check_vrf_dev_processed_flag(ifaceobj):
470 return True
471
472 self._create_vrf_dev(ifaceobj, vrf_table)
473 try:
8ad5c767
RP
474 self._add_vrf_rules(ifaceobj.name, vrf_table)
475 self._create_cgroup(ifaceobj)
476 if add_slaves:
477 self._add_vrf_slaves(ifaceobj)
478 self._add_vrf_default_route(ifaceobj, vrf_table)
479 self._set_vrf_dev_processed_flag(ifaceobj)
480 except Exception, e:
481 self.log_error('%s: %s' %(ifaceobj.name, str(e)))
482
483 def _up(self, ifaceobj, ifaceobj_getfunc=None):
8465de90
RP
484 try:
485 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
486 if vrf_table:
6f2890fc
RP
487 if self.vrf_count == self.vrf_max_count:
488 self.log_error('%s: max vrf count %d hit...not '
489 'creating vrf' %(ifaceobj.name,
490 self.vrf_count))
8465de90
RP
491 self._up_vrf_dev(ifaceobj, vrf_table)
492 else:
493 vrf = ifaceobj.get_attr_value_first('vrf')
494 if vrf:
8ad5c767
RP
495 self._up_vrf_slave(ifaceobj.name, vrf, ifaceobj,
496 ifaceobj_getfunc)
8465de90
RP
497 except Exception, e:
498 self.log_error(str(e))
499
2df6a60f
RP
500 def _delete_cgroup(self, ifaceobj):
501 try:
d1e1c43b
RP
502 if os.path.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj.name):
503 self.exec_command('cgdelete -g l3mdev:%s' %ifaceobj.name)
2df6a60f 504 except Exception, e:
d1e1c43b 505 self.log_warn('%s: cgroup delete failed (%s)\n'
2df6a60f
RP
506 %(ifaceobj.name, str(e)), ifaceobj)
507
8465de90
RP
508 def _down_vrf_dev(self, ifaceobj, vrf_table):
509 if vrf_table == 'auto':
510 vrf_table = self._get_iproute2_vrf_table(ifaceobj.name)
511 try:
512 self.ipcmd.link_delete(ifaceobj.name)
768b4ec5
RP
513 except Exception, e:
514 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
515 pass
516
517 try:
8465de90 518 self._iproute2_vrf_table_entry_del(vrf_table)
2df6a60f 519 self._delete_cgroup(ifaceobj)
768b4ec5
RP
520 except Exception, e:
521 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
522 pass
523
524 try:
8465de90
RP
525 self._del_vrf_rules(ifaceobj.name, vrf_table)
526 except Exception, e:
768b4ec5
RP
527 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
528 pass
8465de90 529
768b4ec5 530 def _down_vrf_slave(self, ifacename, vrf):
8465de90 531 try:
768b4ec5 532 self.ipcmd.link_set(ifacename, 'nomaster')
8465de90 533 except Exception, e:
768b4ec5 534 self.logger.warn('%s: %s' %(ifacename, str(e)))
8465de90 535
8ad5c767 536 def _down(self, ifaceobj, ifaceobj_getfunc=None):
8465de90
RP
537 try:
538 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
539 if vrf_table:
540 self._down_vrf_dev(ifaceobj, vrf_table)
541 else:
542 vrf = ifaceobj.get_attr_value_first('vrf')
543 if vrf:
768b4ec5 544 self._down_vrf_slave(ifaceobj.name, vrf)
8465de90
RP
545 except Exception, e:
546 self.log_warn(str(e))
547
548 def _query_check_vrf_slave(self, ifaceobj, ifaceobjcurr, vrf):
549 try:
54616d3f 550 master = self.ipcmd.link_get_master(ifaceobj.name)
8465de90
RP
551 if not master or master != vrf:
552 ifaceobjcurr.update_config_with_status('vrf', master, 1)
553 else:
554 ifaceobjcurr.update_config_with_status('vrf', master, 0)
555 except Exception, e:
556 self.log_warn(str(e))
557
558 def _query_check_vrf_dev(self, ifaceobj, ifaceobjcurr, vrf_table):
559 try:
560 if not self.ipcmd.link_exists(ifaceobj.name):
561 self.logger.info('%s: vrf: does not exist' %(ifaceobj.name))
562 return
563 if vrf_table == 'auto':
564 config_table = self._get_iproute2_vrf_table(ifaceobj.name)
565 else:
566 config_table = vrf_table
567 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobj.name)
568 if not vrfdev_attrs:
569 ifaceobjcurr.update_config_with_status('vrf-table', 'None', 1)
570 return
571 running_table = vrfdev_attrs.get('table')
572 if not running_table:
573 ifaceobjcurr.update_config_with_status('vrf-table', 'None', 1)
574 return
575 if config_table != running_table:
576 ifaceobjcurr.update_config_with_status('vrf-table',
577 running_table, 1)
578 else:
579 ifaceobjcurr.update_config_with_status('vrf-table',
580 running_table, 0)
581 except Exception, e:
582 self.log_warn(str(e))
583
584 def _query_check(self, ifaceobj, ifaceobjcurr):
585 try:
586 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
587 if vrf_table:
588 self._query_check_vrf_dev(ifaceobj, ifaceobjcurr, vrf_table)
589 else:
590 vrf = ifaceobj.get_attr_value_first('vrf')
591 if vrf:
592 self._query_check_vrf_slave(ifaceobj, ifaceobjcurr, vrf)
593 except Exception, e:
594 self.log_warn(str(e))
595
8ad5c767 596 def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
8465de90
RP
597 try:
598 kind = self.ipcmd.link_get_kind(ifaceobjrunning.name)
599 if kind == 'vrf':
54616d3f 600 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobjrunning.name)
8465de90
RP
601 if vrfdev_attrs:
602 running_table = vrfdev_attrs.get('table')
603 if running_table:
604 ifaceobjrunning.update_config('vrf-table',
605 running_table)
606 elif kind == 'vrf_slave':
54616d3f 607 vrf = self.ipcmd.link_get_master(ifaceobjrunning.name)
8465de90
RP
608 if vrf:
609 ifaceobjrunning.update_config('vrf', vrf)
610 except Exception, e:
611 self.log_warn(str(e))
612
613 _run_ops = {'pre-up' : _up,
614 'post-down' : _down,
615 'query-running' : _query_running,
616 'query-checkcurr' : _query_check}
617
618 def get_ops(self):
619 """ returns list of ops supported by this module """
620 return self._run_ops.keys()
621
622 def _init_command_handlers(self):
623 flags = self.get_flags()
624 if not self.ipcmd:
625 self.ipcmd = iproute2(**flags)
626 if not self.bondcmd:
627 self.bondcmd = bondutil(**flags)
122ef35b
RP
628 if not self.dhclientcmd:
629 self.dhclientcmd = dhclient(**flags)
8465de90 630
8ad5c767
RP
631 def run(self, ifaceobj, operation, query_ifaceobj=None,
632 ifaceobj_getfunc=None, **extra_args):
8465de90
RP
633 """ run bond configuration on the interface object passed as argument
634
635 Args:
636 **ifaceobj** (object): iface object
637
638 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
639 'query-running'
640
641 Kwargs:
642 **query_ifaceobj** (object): query check ifaceobject. This is only
643 valid when op is 'query-checkcurr'. It is an object same as
644 ifaceobj, but contains running attribute values and its config
645 status. The modules can use it to return queried running state
646 of interfaces. status is success if the running state is same
647 as user required state in ifaceobj. error otherwise.
648 """
649 op_handler = self._run_ops.get(operation)
650 if not op_handler:
651 return
652 self._init_command_handlers()
653 if operation == 'query-checkcurr':
654 op_handler(self, ifaceobj, query_ifaceobj)
655 else:
8ad5c767 656 op_handler(self, ifaceobj, ifaceobj_getfunc=ifaceobj_getfunc)