]> git.proxmox.com Git - mirror_ifupdown2.git/blame - addons/vrf.py
addons: vrf: fix vrf slave link kind (fixes #39)
[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
5c5a7b93 8import signal
a193d8d1
JF
9import errno
10import fcntl
8465de90 11import atexit
0aa91758 12import re
79cf5764 13from sets import Set
8465de90 14from ifupdown.iface import *
a193d8d1 15from ifupdown.utils import utils
54616d3f 16import ifupdown.policymanager as policymanager
8465de90 17import ifupdownaddons
2864d6f3 18from ifupdown.netlink import netlink
fc5e1735 19import ifupdown.ifupdownflags as ifupdownflags
8465de90
RP
20from ifupdownaddons.modulebase import moduleBase
21from ifupdownaddons.bondutil import bondutil
22from ifupdownaddons.iproute2 import iproute2
122ef35b 23from ifupdownaddons.dhclient import dhclient
be276272 24from ifupdownaddons.utilsbase import *
8465de90 25
8ad5c767
RP
26class vrfPrivFlags:
27 PROCESSED = 0x1
28
8465de90
RP
29class vrf(moduleBase):
30 """ ifupdown2 addon module to configure vrfs """
31 _modinfo = { 'mhelp' : 'vrf configuration module',
32 'attrs' : {
33 'vrf-table':
fffec8bb
N
34 {'help' : 'vrf device routing table id. key to ' +
35 'creating a vrf device. ' +
36 'Table id is either \'auto\' or '+
37 '\'valid routing table id\'',
2c592263 38 'validvals': ['auto', '<number>'],
fffec8bb 39 'example': ['vrf-table auto', 'vrf-table 1001']},
8465de90
RP
40 'vrf':
41 {'help' : 'vrf the interface is part of.',
482b2fab 42 'validvals': ['<text>'],
8465de90
RP
43 'example': ['vrf blue']}}}
44
a1c23686 45 iproute2_vrf_filename = '/etc/iproute2/rt_tables.d/ifupdown2_vrf_map.conf'
8465de90
RP
46 iproute2_vrf_filehdr = '# This file is autogenerated by ifupdown2.\n' + \
47 '# It contains the vrf name to table mapping.\n' + \
6f2890fc
RP
48 '# Reserved table range %s %s\n'
49 VRF_TABLE_START = 1001
50 VRF_TABLE_END = 5000
8465de90 51
f6466fcb
RP
52 system_reserved_rt_tables = {'255' : 'local', '254' : 'main',
53 '253' : 'default', '0' : 'unspec'}
54
8465de90
RP
55 def __init__(self, *args, **kargs):
56 ifupdownaddons.modulebase.moduleBase.__init__(self, *args, **kargs)
57 self.ipcmd = None
58 self.bondcmd = None
122ef35b 59 self.dhclientcmd = None
8ad5c767 60 self.name = self.__class__.__name__
d9e75535
RP
61 self.vrf_mgmt_devname = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-mgmt-devname')
62
63 if (ifupdownflags.flags.PERFMODE and
64 not (self.vrf_mgmt_devname and os.path.exists('/sys/class/net/%s'
65 %self.vrf_mgmt_devname))):
66 # if perf mode is set (PERFMODE is set at boot), and this is the first
67 # time we are calling ifup at boot (check for mgmt vrf existance at
68 # boot, make sure this is really the first invocation at boot.
69 # ifup is called with PERFMODE at boot multiple times (once for mgmt vrf
70 # and the second time with all auto interfaces). We want to delete
71 # the map file only the first time. This is to avoid accidently
72 # deleting map file with a valid mgmt vrf entry
122ef35b
RP
73 if os.path.exists(self.iproute2_vrf_filename):
74 try:
75 self.logger.info('vrf: removing file %s'
76 %self.iproute2_vrf_filename)
77 os.remove(self.iproute2_vrf_filename)
78 except Exception, e:
79 self.logger.debug('vrf: removing file failed (%s)'
80 %str(e))
8465de90 81 try:
a193d8d1 82 ip_rules = utils.exec_command('/sbin/ip rule show').splitlines()
8465de90
RP
83 self.ip_rule_cache = [' '.join(r.split()) for r in ip_rules]
84 except Exception, e:
85 self.ip_rule_cache = []
a193d8d1 86 self.logger.warn('vrf: cache v4: %s' % str(e))
8465de90
RP
87
88 try:
a193d8d1 89 ip_rules = utils.exec_command('/sbin/ip -6 rule show').splitlines()
8465de90
RP
90 self.ip6_rule_cache = [' '.join(r.split()) for r in ip_rules]
91 except Exception, e:
92 self.ip6_rule_cache = []
a193d8d1 93 self.logger.warn('vrf: cache v6: %s' % str(e))
8465de90
RP
94
95 #self.logger.debug("vrf: ip rule cache")
96 #self.logger.info(self.ip_rule_cache)
97
98 #self.logger.info("vrf: ip -6 rule cache")
99 #self.logger.info(self.ip6_rule_cache)
100
0aa91758
N
101 self.l3mdev_checked = False
102 self.l3mdev4_rule = False
103 if self._l3mdev_rule(self.ip_rule_cache):
104 self.l3mdev4_rule = True
105 self.l3mdev_checked = True
106 self.l3mdev6_rule = False
107 if self._l3mdev_rule(self.ip6_rule_cache):
108 self.l3mdev6_rule = True
109 self.l3mdev_checked = True
05ac52f0
RP
110 self._iproute2_vrf_map_initialized = False
111 self.iproute2_vrf_map = {}
112 self.iproute2_vrf_map_fd = None
113 self.iproute2_vrf_map_sync_to_disk = False
114
115 self.vrf_table_id_start = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-table-id-start')
116 if not self.vrf_table_id_start:
117 self.vrf_table_id_start = self.VRF_TABLE_START
118 self.vrf_table_id_end = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-table-id-end')
119 if not self.vrf_table_id_end:
120 self.vrf_table_id_end = self.VRF_TABLE_END
121 self.vrf_max_count = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-max-count')
122
123 self.vrf_fix_local_table = True
124 self.vrf_count = 0
25e2386e 125 self.vrf_helper = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-helper')
6fbd7444 126 self.vrf_close_socks_on_down = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-close-socks-on-down')
6f5b74f7
RP
127 self.warn_on_vrf_map_write_err = True
128
eb3ce8c8 129 def _iproute2_vrf_map_initialize(self, writetodisk=True):
05ac52f0
RP
130 if self._iproute2_vrf_map_initialized:
131 return
132
8465de90
RP
133 # XXX: check for vrf reserved overlap in /etc/iproute2/rt_tables
134 self.iproute2_vrf_map = {}
05ac52f0 135 iproute2_vrf_map_force_rewrite = False
8465de90
RP
136 # read or create /etc/iproute2/rt_tables.d/ifupdown2.vrf_map
137 if os.path.exists(self.iproute2_vrf_filename):
a193d8d1
JF
138 with open(self.iproute2_vrf_filename, 'r+') as vrf_map_fd:
139 lines = vrf_map_fd.readlines()
140 for l in lines:
141 l = l.strip()
142 if l[0] == '#':
05ac52f0 143 continue
a193d8d1
JF
144 try:
145 (table, vrf_name) = l.strip().split()
146 if self.iproute2_vrf_map.get(int(table)):
147 # looks like the existing file has
148 # duplicate entries, force rewrite of the
149 # file
150 iproute2_vrf_map_force_rewrite = True
151 continue
152 self.iproute2_vrf_map[int(table)] = vrf_name
153 except Exception, e:
42e85fc8 154 self.logger.info('vrf: iproute2_vrf_map: unable to parse %s (%s)' %(l, str(e)))
a193d8d1 155 pass
8465de90 156
05ac52f0
RP
157 vrfs = self.ipcmd.link_get_vrfs()
158 running_vrf_map = {}
159 if vrfs:
160 for v, lattrs in vrfs.iteritems():
161 table = lattrs.get('table', None)
162 if table:
163 running_vrf_map[int(table)] = v
164
4934af35 165 if (not running_vrf_map or (running_vrf_map != self.iproute2_vrf_map)):
05ac52f0
RP
166 self.iproute2_vrf_map = running_vrf_map
167 iproute2_vrf_map_force_rewrite = True
168
169 self.iproute2_vrf_map_fd = None
eb3ce8c8
RP
170 if writetodisk:
171 if iproute2_vrf_map_force_rewrite:
172 # reopen the file and rewrite the map
173 self._iproute2_vrf_map_open(True, False)
174 else:
175 self._iproute2_vrf_map_open(False, True)
8465de90 176
05ac52f0
RP
177 self.iproute2_vrf_map_sync_to_disk = False
178 atexit.register(self._iproute2_vrf_map_sync_to_disk)
179
180 self.logger.info("vrf: dumping iproute2_vrf_map")
181 self.logger.info(self.iproute2_vrf_map)
6f2890fc
RP
182
183 last_used_vrf_table = None
184 for t in range(self.vrf_table_id_start,
185 self.vrf_table_id_end):
8465de90
RP
186 if not self.iproute2_vrf_map.get(t):
187 break
6f2890fc 188 last_used_vrf_table = t
8465de90 189 self.last_used_vrf_table = last_used_vrf_table
05ac52f0 190 self._iproute2_vrf_map_initialized = True
c8a3b44e 191 self.vrf_count = len(self.iproute2_vrf_map)
09753350 192
6f5b74f7
RP
193 def _iproute2_map_warn(self, errstr):
194 if self.warn_on_vrf_map_write_err:
195 if not os.path.exists('/etc/iproute2/rt_tables.d/'):
196 self.logger.info('unable to save iproute2 vrf to table ' +
197 'map (%s)\n' %errstr)
198 self.logger.info('cannot find /etc/iproute2/rt_tables.d.' +
199 ' pls check if your iproute2 version' +
200 ' supports rt_tables.d')
201 else:
202 self.logger.warn('unable to open iproute2 vrf to table ' +
203 'map (%s)\n' %errstr)
204 self.warn_on_vrf_map_write_err = False
205
05ac52f0 206 def _iproute2_vrf_map_sync_to_disk(self):
eb3ce8c8
RP
207 if (ifupdownflags.flags.DRYRUN or
208 not self.iproute2_vrf_map_sync_to_disk):
8465de90 209 return
05ac52f0 210 self.logger.info('vrf: syncing table map to %s'
8465de90 211 %self.iproute2_vrf_filename)
6f5b74f7
RP
212 try:
213 with open(self.iproute2_vrf_filename, 'w') as f:
214 f.write(self.iproute2_vrf_filehdr %(self.vrf_table_id_start,
215 self.vrf_table_id_end))
216 for t, v in self.iproute2_vrf_map.iteritems():
217 f.write('%s %s\n' %(t, v))
218 f.flush()
219 except Exception, e:
220 self._iproute2_map_warn(str(e))
221 pass
05ac52f0
RP
222
223 def _iproute2_vrf_map_open(self, sync_vrfs=False, append=False):
224 self.logger.info('vrf: syncing table map to %s'
225 %self.iproute2_vrf_filename)
eb3ce8c8
RP
226 if ifupdownflags.flags.DRYRUN:
227 return
05ac52f0
RP
228 fmode = 'a+' if append else 'w'
229 try:
230 self.iproute2_vrf_map_fd = open(self.iproute2_vrf_filename,
231 '%s' %fmode)
a193d8d1 232 fcntl.fcntl(self.iproute2_vrf_map_fd, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
05ac52f0 233 except Exception, e:
6f5b74f7 234 self._iproute2_map_warn(str(e))
05ac52f0
RP
235 return
236
237 if not append:
238 # write file header
239 self.iproute2_vrf_map_fd.write(self.iproute2_vrf_filehdr
240 %(self.vrf_table_id_start,
241 self.vrf_table_id_end))
242 for t, v in self.iproute2_vrf_map.iteritems():
243 self.iproute2_vrf_map_fd.write('%s %s\n' %(t, v))
244 self.iproute2_vrf_map_fd.flush()
8465de90
RP
245
246 def _is_vrf(self, ifaceobj):
247 if ifaceobj.get_attr_value_first('vrf-table'):
248 return True
249 return False
250
768b4ec5 251 def get_upper_ifacenames(self, ifaceobj, ifacenames_all=None):
8465de90
RP
252 """ Returns list of interfaces dependent on ifaceobj """
253
768b4ec5
RP
254 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
255 if vrf_table:
256 ifaceobj.link_type = ifaceLinkType.LINK_MASTER
257 ifaceobj.link_kind |= ifaceLinkKind.VRF
f7551dcb 258 ifaceobj.role |= ifaceRole.MASTER
8465de90
RP
259 vrf_iface_name = ifaceobj.get_attr_value_first('vrf')
260 if not vrf_iface_name:
261 return None
768b4ec5 262 ifaceobj.link_type = ifaceLinkType.LINK_SLAVE
858a230f 263 ifaceobj.link_privflags |= ifaceLinkPrivFlags.VRF_SLAVE
8ad5c767 264
8465de90
RP
265 return [vrf_iface_name]
266
768b4ec5 267 def get_upper_ifacenames_running(self, ifaceobj):
8465de90
RP
268 return None
269
270 def _get_iproute2_vrf_table(self, vrf_dev_name):
271 for t, v in self.iproute2_vrf_map.iteritems():
272 if v == vrf_dev_name:
09753350 273 return str(t)
8465de90
RP
274 return None
275
276 def _get_avail_vrf_table_id(self):
6f2890fc
RP
277 if self.last_used_vrf_table == None:
278 table_id_start = self.vrf_table_id_start
279 else:
280 table_id_start = self.last_used_vrf_table + 1
281 for t in range(table_id_start,
282 self.vrf_table_id_end):
8465de90
RP
283 if not self.iproute2_vrf_map.get(t):
284 self.last_used_vrf_table = t
6f2890fc 285 return str(t)
8465de90
RP
286 return None
287
bf3eda91 288 def _iproute2_is_vrf_tableid_inuse(self, vrfifaceobj, table_id):
25e2386e 289 old_vrf_name = self.iproute2_vrf_map.get(int(table_id))
bf3eda91 290 if old_vrf_name and old_vrf_name != vrfifaceobj.name:
25e2386e 291 self.log_error('table id %s already assigned to vrf dev %s'
bf3eda91 292 %(table_id, old_vrf_name), vrfifaceobj)
25e2386e 293
bf3eda91 294 def _iproute2_vrf_table_entry_add(self, vrfifaceobj, table_id):
05ac52f0 295 old_vrf_name = self.iproute2_vrf_map.get(int(table_id))
25e2386e 296 if not old_vrf_name:
bf3eda91 297 self.iproute2_vrf_map[int(table_id)] = vrfifaceobj.name
05ac52f0
RP
298 if self.iproute2_vrf_map_fd:
299 self.iproute2_vrf_map_fd.write('%s %s\n'
bf3eda91 300 %(table_id, vrfifaceobj.name))
05ac52f0 301 self.iproute2_vrf_map_fd.flush()
c8a3b44e 302 self.vrf_count += 1
25e2386e 303 return
bf3eda91 304 if old_vrf_name != vrfifaceobj.name:
25e2386e
RP
305 self.log_error('table id %d already assigned to vrf dev %s'
306 %(table_id, old_vrf_name))
8465de90
RP
307
308 def _iproute2_vrf_table_entry_del(self, table_id):
309 try:
05ac52f0
RP
310 # with any del of vrf map, we need to force sync to disk
311 self.iproute2_vrf_map_sync_to_disk = True
09753350 312 del self.iproute2_vrf_map[int(table_id)]
8465de90 313 except Exception, e:
04e4f352 314 self.logger.info('vrf: iproute2 vrf map del failed for %s (%s)'
8465de90
RP
315 %(table_id, str(e)))
316 pass
317
aa36221f
RP
318 def _is_vrf_dev(self, ifacename):
319 # Look at iproute2 map for now.
320 # If it was a master we knew about,
321 # it is definately there
322 if ifacename in self.iproute2_vrf_map.values():
323 return True
324 return False
325
122ef35b
RP
326 def _is_dhcp_slave(self, ifaceobj):
327 if (not ifaceobj.addr_method or
328 (ifaceobj.addr_method != 'dhcp' and
329 ifaceobj.addr_method != 'dhcp6')):
330 return False
331 return True
332
0ba04b38 333 def _up_vrf_slave_without_master(self, ifacename, vrfname, ifaceobj,
79cf5764 334 vrf_master_objs):
8ad5c767
RP
335 """ If we have a vrf slave that has dhcp configured, bring up the
336 vrf master now. This is needed because vrf has special handling
337 in dhclient hook which requires the vrf master to be present """
0ba04b38 338
8ad5c767
RP
339 vrf_master = ifaceobj.upperifaces[0]
340 if not vrf_master:
341 self.logger.warn('%s: vrf master not found' %ifacename)
342 return
343 if os.path.exists('/sys/class/net/%s' %vrf_master):
344 self.logger.info('%s: vrf master %s exists returning'
345 %(ifacename, vrf_master))
346 return
8ad5c767
RP
347 self.logger.info('%s: bringing up vrf master %s'
348 %(ifacename, vrf_master))
349 for mobj in vrf_master_objs:
350 vrf_table = mobj.get_attr_value_first('vrf-table')
351 if vrf_table:
df53966d
RP
352 if vrf_table == 'auto':
353 vrf_table = self._get_avail_vrf_table_id()
354 if not vrf_table:
355 self.log_error('%s: unable to get an auto table id'
bf3eda91 356 %mobj.name, ifaceobj)
df53966d
RP
357 self.logger.info('%s: table id auto: selected table id %s\n'
358 %(mobj.name, vrf_table))
25e2386e
RP
359 try:
360 self._up_vrf_dev(mobj, vrf_table, False)
361 except Exception:
362 raise
df53966d 363 break
0ba04b38 364 self._handle_existing_connections(ifaceobj, vrfname)
3e960ac2 365 netlink.link_set_master(ifacename, vrfname)
8ad5c767
RP
366 return
367
717cee31 368 def _down_dhcp_slave(self, ifaceobj, vrfname):
122ef35b 369 try:
717cee31 370 dhclient_cmd_prefix = None
6369e774
RP
371 if (vrfname and self.vrf_exec_cmd_prefix and
372 self.ipcmd.link_exists(vrfname)):
717cee31
RP
373 dhclient_cmd_prefix = '%s %s' %(self.vrf_exec_cmd_prefix,
374 vrfname)
375 self.dhclientcmd.release(ifaceobj.name, dhclient_cmd_prefix)
122ef35b
RP
376 except:
377 # ignore any dhclient release errors
378 pass
379
0ba04b38 380 def _handle_existing_connections(self, ifaceobj, vrfname):
fc5e1735 381 if not ifaceobj or ifupdownflags.flags.PERFMODE:
0ba04b38
RP
382 return
383 if (self.vrf_mgmt_devname and
384 self.vrf_mgmt_devname == vrfname):
385 self._kill_ssh_connections(ifaceobj.name)
386 if self._is_dhcp_slave(ifaceobj):
717cee31 387 self._down_dhcp_slave(ifaceobj, vrfname)
0ba04b38 388
8ad5c767 389 def _up_vrf_slave(self, ifacename, vrfname, ifaceobj=None,
09753350 390 ifaceobj_getfunc=None, vrf_exists=False):
8465de90 391 try:
d2b35716 392 master_exists = True
09753350 393 if vrf_exists or self.ipcmd.link_exists(vrfname):
42e85fc8
RP
394 uppers = self.ipcmd.link_get_uppers(ifacename)
395 if not uppers or vrfname not in uppers:
0ba04b38 396 self._handle_existing_connections(ifaceobj, vrfname)
3e960ac2 397 netlink.link_set_master(ifacename, vrfname)
79cf5764
RP
398 elif ifaceobj:
399 vrf_master_objs = ifaceobj_getfunc(vrfname)
400 if not vrf_master_objs:
80be09ba
RP
401 # this is the case where vrf is assigned to an interface
402 # but user has not provided a vrf interface.
403 # people expect you to warn them but go ahead with the
404 # rest of the config on that interface
405 netlink.link_set_updown(ifacename, "up")
406 self.log_error('vrf master ifaceobj %s not found'
407 %vrfname)
79cf5764
RP
408 return
409 if (ifupdownflags.flags.ALL or
1ce8b5bb 410 ifupdownflags.flags.WITH_DEPENDS or
79cf5764
RP
411 (ifupdownflags.flags.CLASS and
412 ifaceobj.classes and vrf_master_objs[0].classes and
413 Set(ifaceobj.classes).intersection(vrf_master_objs[0].classes))):
414 self._up_vrf_slave_without_master(ifacename, vrfname,
415 ifaceobj,
416 vrf_master_objs)
417 else:
418 master_exists = False
d2b35716
RP
419 else:
420 master_exists = False
421 if master_exists:
c9b929f9 422 netlink.link_set_updown(ifacename, "up")
79cf5764 423 else:
d2b35716 424 self.log_error('vrf %s not around, skipping vrf config'
bf3eda91 425 %(vrfname), ifaceobj)
8465de90 426 except Exception, e:
bf3eda91 427 self.log_error('%s: %s' %(ifacename, str(e)), ifaceobj)
8465de90
RP
428
429 def _del_vrf_rules(self, vrf_dev_name, vrf_table):
430 pref = 200
431 ip_rule_out_format = '%s: from all %s %s lookup %s'
432 ip_rule_cmd = 'ip %s rule del pref %s %s %s table %s'
433
4ce47ce4 434 rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
8465de90 435 if rule in self.ip_rule_cache:
25e2386e
RP
436 rule_cmd = ip_rule_cmd %('', pref, 'oif', vrf_dev_name,
437 vrf_dev_name)
a193d8d1 438 utils.exec_command(rule_cmd)
8465de90 439
4ce47ce4 440 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
8465de90 441 if rule in self.ip_rule_cache:
25e2386e
RP
442 rule_cmd = ip_rule_cmd %('', pref, 'iif', vrf_dev_name,
443 vrf_dev_name)
a193d8d1 444 utils.exec_command(rule_cmd)
8465de90 445
4ce47ce4 446 rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
e6072769 447 if rule in self.ip6_rule_cache:
8465de90 448 rule_cmd = ip_rule_cmd %('-6', pref, 'oif', vrf_dev_name,
25e2386e 449 vrf_dev_name)
a193d8d1 450 utils.exec_command(rule_cmd)
8465de90 451
4ce47ce4 452 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
e6072769 453 if rule in self.ip6_rule_cache:
8465de90 454 rule_cmd = ip_rule_cmd %('-6', pref, 'iif', vrf_dev_name,
25e2386e 455 vrf_dev_name)
a193d8d1 456 utils.exec_command(rule_cmd)
8465de90 457
0aa91758
N
458 def _l3mdev_rule(self, ip_rules):
459 for rule in ip_rules:
460 if not re.search(r"\d.*from\s+all\s+lookup\s+\W?l3mdev-table\W?",
461 rule):
462 continue
463 return True
464 return False
465
466 def _rule_cache_fill(self):
467 ip_rules = utils.exec_command('/sbin/ip rule show').splitlines()
468 self.ip_rule_cache = [' '.join(r.split()) for r in ip_rules]
469 self.l3mdev4_rule = self._l3mdev_rule(self.ip_rule_cache)
470 ip_rules = utils.exec_command('/sbin/ip -6 rule show').splitlines()
471 self.ip6_rule_cache = [' '.join(r.split()) for r in ip_rules]
472 self.l3mdev6_rule = self._l3mdev_rule(self.ip6_rule_cache)
473
8465de90
RP
474 def _add_vrf_rules(self, vrf_dev_name, vrf_table):
475 pref = 200
476 ip_rule_out_format = '%s: from all %s %s lookup %s'
477 ip_rule_cmd = 'ip %s rule add pref %s %s %s table %s'
659097a0
N
478 if self.vrf_fix_local_table:
479 self.vrf_fix_local_table = False
480 rule = '0: from all lookup local'
481 if rule in self.ip_rule_cache:
482 try:
a193d8d1
JF
483 utils.exec_command('ip rule del pref 0')
484 utils.exec_command('ip rule add pref 32765 table local')
659097a0 485 except Exception, e:
a193d8d1 486 self.logger.info('%s: %s' % (vrf_dev_name, str(e)))
659097a0 487 pass
c61672da
N
488 if rule in self.ip6_rule_cache:
489 try:
a193d8d1
JF
490 utils.exec_command('ip -6 rule del pref 0')
491 utils.exec_command('ip -6 rule add pref 32765 table local')
c61672da 492 except Exception, e:
a193d8d1 493 self.logger.info('%s: %s' % (vrf_dev_name, str(e)))
c61672da 494 pass
8465de90 495
0aa91758
N
496 if not self.l3mdev_checked:
497 self._rule_cache_fill()
498 self.l3mdev_checked = True
3fcb15fe
N
499 #Example ip rule
500 #200: from all oif blue lookup blue
501 #200: from all iif blue lookup blue
502
503 rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
0aa91758 504 if not self.l3mdev4_rule and rule not in self.ip_rule_cache:
25e2386e
RP
505 rule_cmd = ip_rule_cmd %('', pref, 'oif', vrf_dev_name,
506 vrf_dev_name)
a193d8d1 507 utils.exec_command(rule_cmd)
8465de90 508
3fcb15fe 509 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
0aa91758 510 if not self.l3mdev4_rule and rule not in self.ip_rule_cache:
25e2386e
RP
511 rule_cmd = ip_rule_cmd %('', pref, 'iif', vrf_dev_name,
512 vrf_dev_name)
a193d8d1 513 utils.exec_command(rule_cmd)
8465de90 514
3fcb15fe 515 rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
0aa91758 516 if not self.l3mdev6_rule and rule not in self.ip6_rule_cache:
25e2386e
RP
517 rule_cmd = ip_rule_cmd %('-6', pref, 'oif', vrf_dev_name,
518 vrf_dev_name)
a193d8d1 519 utils.exec_command(rule_cmd)
8465de90 520
3fcb15fe 521 rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
0aa91758 522 if not self.l3mdev6_rule and rule not in self.ip6_rule_cache:
8465de90 523 rule_cmd = ip_rule_cmd %('-6', pref, 'iif', vrf_dev_name,
25e2386e 524 vrf_dev_name)
a193d8d1 525 utils.exec_command(rule_cmd)
8465de90 526
1b284018
RP
527 def _is_address_virtual_slaves(self, vrfobj, config_vrfslaves,
528 vrfslave):
529 # Address virtual lines on a vrf slave will create
530 # macvlan devices on the vrf slave and enslave them
531 # to the vrf master. This function checks if the
532 # vrf slave is such a macvlan interface.
533 # XXX: additional possible checks that can be done here
534 # are:
535 # - check if it is also a macvlan device of the
536 # format <vrf_slave>-v<int> created by the
537 # address virtual module
538 vrfslave_lowers = self.ipcmd.link_get_lowers(vrfslave)
539 if vrfslave_lowers:
540 if vrfslave_lowers[0] in config_vrfslaves:
541 return True
542 return False
543
4d2c9798 544 def _add_vrf_slaves(self, ifaceobj, ifaceobj_getfunc=None):
768b4ec5
RP
545 running_slaves = self.ipcmd.link_get_lowers(ifaceobj.name)
546 config_slaves = ifaceobj.lowerifaces
b94e4d24 547 if not config_slaves and not running_slaves:
867e11a2 548 return
4d2c9798
RP
549
550 if not config_slaves: config_slaves = []
551 if not running_slaves: running_slaves = []
768b4ec5
RP
552 add_slaves = set(config_slaves).difference(set(running_slaves))
553 del_slaves = set(running_slaves).difference(set(config_slaves))
554 if add_slaves:
555 for s in add_slaves:
556 try:
d2b35716
RP
557 if not self.ipcmd.link_exists(s):
558 continue
09753350
RP
559 sobj = None
560 if ifaceobj_getfunc:
561 sobj = ifaceobj_getfunc(s)
562 self._up_vrf_slave(s, ifaceobj.name,
563 sobj[0] if sobj else None,
564 ifaceobj_getfunc, True)
768b4ec5
RP
565 except Exception, e:
566 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
567
568 if del_slaves:
569 for s in del_slaves:
570 try:
1b284018
RP
571 if self._is_address_virtual_slaves(ifaceobj,
572 config_slaves, s):
573 continue
aa36221f 574 sobj = None
4d2c9798
RP
575 if ifaceobj_getfunc:
576 sobj = ifaceobj_getfunc(s)
0ba04b38
RP
577 self._down_vrf_slave(s, sobj[0] if sobj else None,
578 ifaceobj.name)
768b4ec5
RP
579 except Exception, e:
580 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
581
582 if ifaceobj.link_type == ifaceLinkType.LINK_MASTER:
583 for s in config_slaves:
584 try:
2864d6f3 585 netlink.link_set_updown(s, "up")
768b4ec5 586 except Exception, e:
2864d6f3 587 self.logger.debug('%s: %s' % (ifaceobj.name, str(e)))
768b4ec5 588 pass
8465de90 589
8ad5c767
RP
590 def _set_vrf_dev_processed_flag(self, ifaceobj):
591 ifaceobj.module_flags[self.name] = \
592 ifaceobj.module_flags.setdefault(self.name, 0) | \
593 vrfPrivFlags.PROCESSED
594
595 def _check_vrf_dev_processed_flag(self, ifaceobj):
25e2386e 596 if (ifaceobj.module_flags.get(self.name, 0) & vrfPrivFlags.PROCESSED):
8ad5c767
RP
597 return True
598 return False
8465de90 599
8ad5c767 600 def _create_vrf_dev(self, ifaceobj, vrf_table):
2df6a60f 601 if not self.ipcmd.link_exists(ifaceobj.name):
f6466fcb
RP
602 if ifaceobj.name in self.system_reserved_rt_tables.values():
603 self.log_error('cannot use system reserved %s vrf names'
bf3eda91
RP
604 %(str(self.system_reserved_rt_tables.values())),
605 ifaceobj)
c8a3b44e 606 if self.vrf_count == self.vrf_max_count:
9b35cb3e
JF
607 self.log_error('max vrf count %d hit...not '
608 'creating vrf' % self.vrf_count, ifaceobj)
6f2890fc
RP
609 if vrf_table == 'auto':
610 vrf_table = self._get_avail_vrf_table_id()
611 if not vrf_table:
9b35cb3e 612 self.log_error('unable to get an auto table id', ifaceobj)
6f2890fc
RP
613 self.logger.info('%s: table id auto: selected table id %s\n'
614 %(ifaceobj.name, vrf_table))
25e2386e 615 else:
bf3eda91 616 self._iproute2_is_vrf_tableid_inuse(ifaceobj, vrf_table)
f6466fcb
RP
617 if ifaceobj.name in self.system_reserved_rt_tables.keys():
618 self.log_error('cannot use system reserved %s table ids'
bf3eda91
RP
619 %(str(self.system_reserved_rt_tables.keys())),
620 ifaceobj)
d54baa22
RP
621
622 if not vrf_table.isdigit():
9b35cb3e 623 self.log_error('vrf-table must be an integer or \'auto\'', ifaceobj)
d54baa22 624
6f2890fc
RP
625 # XXX: If we decide to not allow vrf id usages out of
626 # the reserved ifupdown range, then uncomment this code.
fd8c6caf
RP
627 else:
628 if (int(vrf_table) < self.vrf_table_id_start or
629 int(vrf_table) > self.vrf_table_id_end):
9b35cb3e
JF
630 self.log_error('vrf table id %s out of reserved range [%d,%d]'
631 %(vrf_table,
fd8c6caf 632 self.vrf_table_id_start,
bf3eda91 633 self.vrf_table_id_end), ifaceobj)
2df6a60f 634 try:
8465de90
RP
635 self.ipcmd.link_create(ifaceobj.name, 'vrf',
636 {'table' : '%s' %vrf_table})
2df6a60f 637 except Exception, e:
9b35cb3e 638 self.log_error('create failed (%s)\n' % str(e), ifaceobj)
25e2386e 639 if vrf_table != 'auto':
bf3eda91 640 self._iproute2_vrf_table_entry_add(ifaceobj, vrf_table)
2df6a60f 641 else:
4d2c9798
RP
642 if vrf_table == 'auto':
643 vrf_table = self._get_iproute2_vrf_table(ifaceobj.name)
644 if not vrf_table:
9b35cb3e 645 self.log_error('unable to get vrf table id', ifaceobj)
6f2890fc 646
2df6a60f
RP
647 # if the device exists, check if table id is same
648 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobj.name)
649 if vrfdev_attrs:
650 running_table = vrfdev_attrs.get('table', None)
651 if vrf_table != running_table:
9b35cb3e
JF
652 self.log_error('cannot change vrf table id,running table id'
653 ' %s is different from config id %s'
654 % (running_table, vrf_table), ifaceobj)
4d2c9798
RP
655 return vrf_table
656
25e2386e 657 def _up_vrf_helper(self, ifaceobj, vrf_table):
c4e05f9f
RP
658 mode = ""
659 if ifupdownflags.flags.PERFMODE:
660 mode = "boot"
25e2386e 661 if self.vrf_helper:
a193d8d1
JF
662 utils.exec_command('%s create %s %s %s' %
663 (self.vrf_helper,
664 ifaceobj.name,
665 vrf_table,
666 mode))
25e2386e 667
4d2c9798
RP
668 def _up_vrf_dev(self, ifaceobj, vrf_table, add_slaves=True,
669 ifaceobj_getfunc=None):
8ad5c767
RP
670
671 # if vrf dev is already processed return. This can happen
0ba04b38
RP
672 # if we the slave was configured before.
673 # see self._up_vrf_slave_without_master
8ad5c767
RP
674 if self._check_vrf_dev_processed_flag(ifaceobj):
675 return True
676
25e2386e
RP
677 try:
678 vrf_table = self._create_vrf_dev(ifaceobj, vrf_table)
679 except Exception, e:
bf3eda91 680 self.log_error('%s: %s' %(ifaceobj.name, str(e)), ifaceobj)
25e2386e 681
8ad5c767 682 try:
8ad5c767 683 self._add_vrf_rules(ifaceobj.name, vrf_table)
6369e774 684 self._up_vrf_helper(ifaceobj, vrf_table)
8ad5c767 685 if add_slaves:
4d2c9798 686 self._add_vrf_slaves(ifaceobj, ifaceobj_getfunc)
8ad5c767 687 self._set_vrf_dev_processed_flag(ifaceobj)
2864d6f3 688 netlink.link_set_updown(ifaceobj.name, "up")
8ad5c767 689 except Exception, e:
bf3eda91 690 self.log_error('%s: %s' %(ifaceobj.name, str(e)), ifaceobj)
8ad5c767 691
0ba04b38 692 def _kill_ssh_connections(self, ifacename):
5c5a7b93 693 try:
0ba04b38
RP
694 runningaddrsdict = self.ipcmd.addr_get(ifacename)
695 if not runningaddrsdict:
5c5a7b93 696 return
0ba04b38
RP
697 iplist = [i.split('/', 1)[0] for i in runningaddrsdict.keys()]
698 if not iplist:
699 return
700 proc=[]
5c5a7b93
N
701 #Example output:
702 #ESTAB 0 0 10.0.1.84:ssh 10.0.1.228:45186
703 #users:(("sshd",pid=2528,fd=3))
0ba04b38 704 cmdl = ['/bin/ss', '-t', '-p']
a193d8d1 705 for line in utils.exec_commandl(cmdl).splitlines():
5c5a7b93
N
706 citems = line.split()
707 addr = None
708 if '%' in citems[3]:
709 addr = citems[3].split('%')[0]
710 elif ':ssh' in citems[3]:
711 addr = citems[3].split(':')[0]
712 if not addr:
713 continue
0ba04b38 714 if addr in iplist:
5c5a7b93
N
715 if len(citems) == 6:
716 proc.append(citems[5].split(',')[1].split('=')[1])
717
718 if not proc:
719 return
be276272
N
720 pid = None
721 # outpt of '/usr/bin/pstree -Aps <pid>':
722 # 'systemd(1)---sshd(990)---sshd(16112)---sshd(16126)---bash(16127)---sudo(16756)---ifreload(16761)---pstree(16842)\n'
723 # get the above output to following format
724 # ['systemd(1)', 'sshd(990)', 'sshd(16112)', 'sshd(16126)', 'bash(16127)', 'sudo(16756)', 'ifreload(16761)', 'pstree(16850)']
725 pstree = list(reversed(utils.exec_command('/usr/bin/pstree -Aps %s' %os.getpid()).strip().split('---')))
726 for index, process in enumerate(pstree):
727 # check the parent of SSH process to make sure
728 # we don't kill SSH server or systemd process
729 if 'sshd' in process and 'sshd' in pstree[index + 1]:
730 pid = filter(lambda x: x.isdigit(), process)
731 break
aa36221f
RP
732 self.logger.info("%s: killing active ssh sessions: %s"
733 %(ifacename, str(proc)))
cbdde74e
RP
734
735 if ifupdownflags.flags.DRYRUN:
736 return
5c5a7b93
N
737 for id in proc:
738 if id != pid:
739 try:
aa36221f 740 os.kill(int(id), signal.SIGINT)
5c5a7b93
N
741 except OSError as e:
742 continue
0ba04b38
RP
743
744 # Kill current SSH client
5c5a7b93 745 if pid in proc:
32f6e6ca 746 try:
0ba04b38
RP
747 forkret = os.fork()
748 except OSError, e:
749 self.logger.info("fork error : %s [%d]" % (e.strerror, e.errno))
750 if (forkret == 0): # The first child.
751 try:
752 os.setsid()
753 self.logger.info("%s: ifreload continuing in the background" %ifacename)
754 except OSError, (err_no, err_message):
755 self.logger.info("os.setsid failed: errno=%d: %s" % (err_no, err_message))
756 self.logger.info("pid=%d pgid=%d" % (os.getpid(), os.getpgid(0)))
5c5a7b93 757 try:
aa36221f
RP
758 self.logger.info("%s: killing our session: %s"
759 %(ifacename, str(proc)))
760 os.kill(int(pid), signal.SIGINT)
5c5a7b93
N
761 return
762 except OSError as e:
763 return
764 except Exception, e:
765 self.logger.info('%s: %s' %(ifacename, str(e)))
766
8ad5c767 767 def _up(self, ifaceobj, ifaceobj_getfunc=None):
8465de90
RP
768 try:
769 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
770 if vrf_table:
05ac52f0 771 self._iproute2_vrf_map_initialize()
09753350 772 # This is a vrf device
4d2c9798 773 self._up_vrf_dev(ifaceobj, vrf_table, True, ifaceobj_getfunc)
8465de90
RP
774 else:
775 vrf = ifaceobj.get_attr_value_first('vrf')
776 if vrf:
05ac52f0 777 self._iproute2_vrf_map_initialize()
09753350 778 # This is a vrf slave
8ad5c767
RP
779 self._up_vrf_slave(ifaceobj.name, vrf, ifaceobj,
780 ifaceobj_getfunc)
aa36221f
RP
781 else:
782 # check if we were a slave before
783 master = self.ipcmd.link_get_master(ifaceobj.name)
784 if master:
717cee31 785 self._iproute2_vrf_map_initialize()
aa36221f 786 if self._is_vrf_dev(master):
0ba04b38
RP
787 self._down_vrf_slave(ifaceobj.name, ifaceobj,
788 master)
8465de90 789 except Exception, e:
bf3eda91 790 self.log_error(str(e), ifaceobj)
8465de90 791
25e2386e 792 def _down_vrf_helper(self, ifaceobj, vrf_table):
c4e05f9f
RP
793 mode = ""
794 if ifupdownflags.flags.PERFMODE:
795 mode = "boot"
25e2386e 796 if self.vrf_helper:
a193d8d1
JF
797 utils.exec_command('%s delete %s %s %s' %
798 (self.vrf_helper,
799 ifaceobj.name,
800 vrf_table,
801 mode))
25e2386e 802
6fbd7444
RP
803 def _close_sockets(self, ifaceobj, ifindex):
804 if not self.vrf_close_socks_on_down:
805 return
806
807 try:
808 utils.exec_command('/bin/ss -aK \"dev == %s\"'
809 %ifindex)
810 except Exception, e:
811 self.logger.info('%s: closing socks using ss'
812 ' failed (%s)\n' %(ifaceobj.name, str(e)))
813 pass
814
c4be5481 815 def _down_vrf_dev(self, ifaceobj, vrf_table, ifaceobj_getfunc=None):
5c5a7b93 816
6fbd7444
RP
817 if not self.ipcmd.link_exists(ifaceobj.name):
818 return
819
8465de90
RP
820 if vrf_table == 'auto':
821 vrf_table = self._get_iproute2_vrf_table(ifaceobj.name)
aa36221f 822
2365b3c9
RP
823 running_slaves = self.ipcmd.link_get_lowers(ifaceobj.name)
824 if running_slaves:
825 for s in running_slaves:
826 if ifaceobj_getfunc:
827 sobj = ifaceobj_getfunc(s)
828 try:
829 self._handle_existing_connections(sobj[0]
830 if sobj else None,
0ba04b38 831 ifaceobj.name)
2365b3c9
RP
832 except Exception, e:
833 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
834 pass
835 try:
836 self.ipcmd.addr_flush(s)
2864d6f3 837 netlink.link_set_updown(s, "down")
2365b3c9
RP
838 except Exception, e:
839 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
840 pass
768b4ec5 841
40804f1a
RP
842 try:
843 self._down_vrf_helper(ifaceobj, vrf_table)
844 except Exception, e:
845 self.logger.warn('%s: %s' %(ifaceobj.name, str(e)))
846 pass
25e2386e 847
768b4ec5 848 try:
f1c92482 849 self._del_vrf_rules(ifaceobj.name, vrf_table)
768b4ec5
RP
850 except Exception, e:
851 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
852 pass
853
6fbd7444
RP
854 ifindex = self.ipcmd.link_get_ifindex(ifaceobj.name)
855
768b4ec5 856 try:
f1c92482
RP
857 self.ipcmd.link_delete(ifaceobj.name)
858 except Exception, e:
859 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
860 pass
861
6fbd7444
RP
862 self._close_sockets(ifaceobj, ifindex)
863
f1c92482
RP
864 try:
865 self._iproute2_vrf_table_entry_del(vrf_table)
8465de90 866 except Exception, e:
768b4ec5
RP
867 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
868 pass
8465de90 869
f1c92482 870
0ba04b38 871 def _down_vrf_slave(self, ifacename, ifaceobj=None, vrfname=None):
8465de90 872 try:
0ba04b38 873 self._handle_existing_connections(ifaceobj, vrfname)
3e960ac2 874 netlink.link_set_nomaster(ifacename)
dc3f4c45
RP
875 # Down this slave only if it is a slave ifupdown2 manages.
876 # we dont want to down slaves that maybe up'ed by
877 # somebody else. One such example is a macvlan device
878 # which ifupdown2 addressvirtual addon module auto creates
879 if ifaceobj:
880 netlink.link_set_updown(ifacename, "down")
8465de90 881 except Exception, e:
768b4ec5 882 self.logger.warn('%s: %s' %(ifacename, str(e)))
8465de90 883
8ad5c767 884 def _down(self, ifaceobj, ifaceobj_getfunc=None):
8465de90
RP
885 try:
886 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
887 if vrf_table:
05ac52f0 888 self._iproute2_vrf_map_initialize()
c4be5481 889 self._down_vrf_dev(ifaceobj, vrf_table, ifaceobj_getfunc)
8465de90
RP
890 else:
891 vrf = ifaceobj.get_attr_value_first('vrf')
892 if vrf:
05ac52f0 893 self._iproute2_vrf_map_initialize()
0ba04b38 894 self._down_vrf_slave(ifaceobj.name, ifaceobj, None)
8465de90
RP
895 except Exception, e:
896 self.log_warn(str(e))
897
898 def _query_check_vrf_slave(self, ifaceobj, ifaceobjcurr, vrf):
899 try:
54616d3f 900 master = self.ipcmd.link_get_master(ifaceobj.name)
8465de90 901 if not master or master != vrf:
586535e8 902 ifaceobjcurr.update_config_with_status('vrf', str(master), 1)
8465de90
RP
903 else:
904 ifaceobjcurr.update_config_with_status('vrf', master, 0)
905 except Exception, e:
bf3eda91 906 self.log_error(str(e), ifaceobjcurr)
8465de90 907
6e16e5ae 908 def _query_check_vrf_dev(self, ifaceobj, ifaceobjcurr, vrf_table):
8465de90
RP
909 try:
910 if not self.ipcmd.link_exists(ifaceobj.name):
911 self.logger.info('%s: vrf: does not exist' %(ifaceobj.name))
912 return
913 if vrf_table == 'auto':
914 config_table = self._get_iproute2_vrf_table(ifaceobj.name)
915 else:
916 config_table = vrf_table
917 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobj.name)
918 if not vrfdev_attrs:
919 ifaceobjcurr.update_config_with_status('vrf-table', 'None', 1)
920 return
921 running_table = vrfdev_attrs.get('table')
922 if not running_table:
923 ifaceobjcurr.update_config_with_status('vrf-table', 'None', 1)
924 return
925 if config_table != running_table:
926 ifaceobjcurr.update_config_with_status('vrf-table',
927 running_table, 1)
928 else:
929 ifaceobjcurr.update_config_with_status('vrf-table',
930 running_table, 0)
6e16e5ae 931 if not ifupdownflags.flags.WITHDEFAULTS:
669b422a
RP
932 return
933 if self.vrf_helper:
6e16e5ae 934 try:
a193d8d1 935 utils.exec_command('%s verify %s %s'
6e16e5ae
N
936 %(self.vrf_helper,
937 ifaceobj.name, config_table))
938 ifaceobjcurr.update_config_with_status('vrf-helper',
939 '%s create %s %s'
940 %(self.vrf_helper,
941 ifaceobj.name,
942 config_table), 0)
943 except Exception, e:
944 ifaceobjcurr.update_config_with_status('vrf-helper',
945 '%s create %s %s'
946 %(self.vrf_helper,
947 ifaceobj.name,
948 config_table), 1)
949 pass
8465de90
RP
950 except Exception, e:
951 self.log_warn(str(e))
952
6e16e5ae 953 def _query_check(self, ifaceobj, ifaceobjcurr):
8465de90
RP
954 try:
955 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
956 if vrf_table:
eb3ce8c8 957 self._iproute2_vrf_map_initialize(writetodisk=False)
6e16e5ae 958 self._query_check_vrf_dev(ifaceobj, ifaceobjcurr, vrf_table)
8465de90
RP
959 else:
960 vrf = ifaceobj.get_attr_value_first('vrf')
961 if vrf:
eb3ce8c8 962 self._iproute2_vrf_map_initialize(writetodisk=False)
8465de90
RP
963 self._query_check_vrf_slave(ifaceobj, ifaceobjcurr, vrf)
964 except Exception, e:
965 self.log_warn(str(e))
966
8ad5c767 967 def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
8465de90
RP
968 try:
969 kind = self.ipcmd.link_get_kind(ifaceobjrunning.name)
970 if kind == 'vrf':
54616d3f 971 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobjrunning.name)
8465de90
RP
972 if vrfdev_attrs:
973 running_table = vrfdev_attrs.get('table')
974 if running_table:
975 ifaceobjrunning.update_config('vrf-table',
976 running_table)
5b563460
JF
977 return
978 slave_kind = self.ipcmd.link_get_slave_kind(ifaceobjrunning.name)
979 if slave_kind == 'vrf_slave':
54616d3f 980 vrf = self.ipcmd.link_get_master(ifaceobjrunning.name)
8465de90
RP
981 if vrf:
982 ifaceobjrunning.update_config('vrf', vrf)
983 except Exception, e:
984 self.log_warn(str(e))
985
baa909c6
N
986 def _query(self, ifaceobj, **kwargs):
987 if not self.vrf_helper:
988 return
989 if (ifaceobj.link_kind & ifaceLinkKind.VRF):
990 ifaceobj.update_config('vrf-helper', '%s %s' %(self.vrf_helper,
991 ifaceobj.name))
992
8465de90
RP
993 _run_ops = {'pre-up' : _up,
994 'post-down' : _down,
995 'query-running' : _query_running,
baa909c6
N
996 'query-checkcurr' : _query_check,
997 'query' : _query}
8465de90
RP
998
999 def get_ops(self):
1000 """ returns list of ops supported by this module """
1001 return self._run_ops.keys()
1002
1003 def _init_command_handlers(self):
8465de90 1004 if not self.ipcmd:
fc5e1735 1005 self.ipcmd = iproute2()
8465de90 1006 if not self.bondcmd:
fc5e1735 1007 self.bondcmd = bondutil()
122ef35b 1008 if not self.dhclientcmd:
fc5e1735 1009 self.dhclientcmd = dhclient()
8465de90 1010
8ad5c767
RP
1011 def run(self, ifaceobj, operation, query_ifaceobj=None,
1012 ifaceobj_getfunc=None, **extra_args):
8465de90
RP
1013 """ run bond configuration on the interface object passed as argument
1014
1015 Args:
1016 **ifaceobj** (object): iface object
1017
1018 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
1019 'query-running'
1020
1021 Kwargs:
1022 **query_ifaceobj** (object): query check ifaceobject. This is only
1023 valid when op is 'query-checkcurr'. It is an object same as
1024 ifaceobj, but contains running attribute values and its config
1025 status. The modules can use it to return queried running state
1026 of interfaces. status is success if the running state is same
1027 as user required state in ifaceobj. error otherwise.
1028 """
1029 op_handler = self._run_ops.get(operation)
1030 if not op_handler:
1031 return
1032 self._init_command_handlers()
1033 if operation == 'query-checkcurr':
6e16e5ae 1034 op_handler(self, ifaceobj, query_ifaceobj)
8465de90 1035 else:
8ad5c767 1036 op_handler(self, ifaceobj, ifaceobj_getfunc=ifaceobj_getfunc)