]> git.proxmox.com Git - mirror_ifupdown2.git/blame - addons/vrf.py
normalizing ip address(s) to IPNetwork format for string comparaison
[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')
05ac52f0 126
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:
154 self.logger.info('vrf: iproute2_vrf_map: unable to parse %s'
155 %l)
156 pass
8465de90 157
05ac52f0
RP
158 vrfs = self.ipcmd.link_get_vrfs()
159 running_vrf_map = {}
160 if vrfs:
161 for v, lattrs in vrfs.iteritems():
162 table = lattrs.get('table', None)
163 if table:
164 running_vrf_map[int(table)] = v
165
4934af35 166 if (not running_vrf_map or (running_vrf_map != self.iproute2_vrf_map)):
05ac52f0
RP
167 self.iproute2_vrf_map = running_vrf_map
168 iproute2_vrf_map_force_rewrite = True
169
170 self.iproute2_vrf_map_fd = None
eb3ce8c8
RP
171 if writetodisk:
172 if iproute2_vrf_map_force_rewrite:
173 # reopen the file and rewrite the map
174 self._iproute2_vrf_map_open(True, False)
175 else:
176 self._iproute2_vrf_map_open(False, True)
8465de90 177
05ac52f0
RP
178 self.iproute2_vrf_map_sync_to_disk = False
179 atexit.register(self._iproute2_vrf_map_sync_to_disk)
180
181 self.logger.info("vrf: dumping iproute2_vrf_map")
182 self.logger.info(self.iproute2_vrf_map)
6f2890fc
RP
183
184 last_used_vrf_table = None
185 for t in range(self.vrf_table_id_start,
186 self.vrf_table_id_end):
8465de90
RP
187 if not self.iproute2_vrf_map.get(t):
188 break
6f2890fc 189 last_used_vrf_table = t
8465de90 190 self.last_used_vrf_table = last_used_vrf_table
05ac52f0 191 self._iproute2_vrf_map_initialized = True
c8a3b44e 192 self.vrf_count = len(self.iproute2_vrf_map)
09753350 193
6f5b74f7
RP
194 def _iproute2_map_warn(self, errstr):
195 if self.warn_on_vrf_map_write_err:
196 if not os.path.exists('/etc/iproute2/rt_tables.d/'):
197 self.logger.info('unable to save iproute2 vrf to table ' +
198 'map (%s)\n' %errstr)
199 self.logger.info('cannot find /etc/iproute2/rt_tables.d.' +
200 ' pls check if your iproute2 version' +
201 ' supports rt_tables.d')
202 else:
203 self.logger.warn('unable to open iproute2 vrf to table ' +
204 'map (%s)\n' %errstr)
205 self.warn_on_vrf_map_write_err = False
206
05ac52f0 207 def _iproute2_vrf_map_sync_to_disk(self):
eb3ce8c8
RP
208 if (ifupdownflags.flags.DRYRUN or
209 not self.iproute2_vrf_map_sync_to_disk):
8465de90 210 return
05ac52f0 211 self.logger.info('vrf: syncing table map to %s'
8465de90 212 %self.iproute2_vrf_filename)
6f5b74f7
RP
213 try:
214 with open(self.iproute2_vrf_filename, 'w') as f:
215 f.write(self.iproute2_vrf_filehdr %(self.vrf_table_id_start,
216 self.vrf_table_id_end))
217 for t, v in self.iproute2_vrf_map.iteritems():
218 f.write('%s %s\n' %(t, v))
219 f.flush()
220 except Exception, e:
221 self._iproute2_map_warn(str(e))
222 pass
05ac52f0
RP
223
224 def _iproute2_vrf_map_open(self, sync_vrfs=False, append=False):
225 self.logger.info('vrf: syncing table map to %s'
226 %self.iproute2_vrf_filename)
eb3ce8c8
RP
227 if ifupdownflags.flags.DRYRUN:
228 return
05ac52f0
RP
229 fmode = 'a+' if append else 'w'
230 try:
231 self.iproute2_vrf_map_fd = open(self.iproute2_vrf_filename,
232 '%s' %fmode)
a193d8d1 233 fcntl.fcntl(self.iproute2_vrf_map_fd, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
05ac52f0 234 except Exception, e:
6f5b74f7 235 self._iproute2_map_warn(str(e))
05ac52f0
RP
236 return
237
238 if not append:
239 # write file header
240 self.iproute2_vrf_map_fd.write(self.iproute2_vrf_filehdr
241 %(self.vrf_table_id_start,
242 self.vrf_table_id_end))
243 for t, v in self.iproute2_vrf_map.iteritems():
244 self.iproute2_vrf_map_fd.write('%s %s\n' %(t, v))
245 self.iproute2_vrf_map_fd.flush()
8465de90
RP
246
247 def _is_vrf(self, ifaceobj):
248 if ifaceobj.get_attr_value_first('vrf-table'):
249 return True
250 return False
251
768b4ec5 252 def get_upper_ifacenames(self, ifaceobj, ifacenames_all=None):
8465de90
RP
253 """ Returns list of interfaces dependent on ifaceobj """
254
768b4ec5
RP
255 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
256 if vrf_table:
257 ifaceobj.link_type = ifaceLinkType.LINK_MASTER
258 ifaceobj.link_kind |= ifaceLinkKind.VRF
f7551dcb 259 ifaceobj.role |= ifaceRole.MASTER
8465de90
RP
260 vrf_iface_name = ifaceobj.get_attr_value_first('vrf')
261 if not vrf_iface_name:
262 return None
768b4ec5 263 ifaceobj.link_type = ifaceLinkType.LINK_SLAVE
858a230f 264 ifaceobj.link_privflags |= ifaceLinkPrivFlags.VRF_SLAVE
8ad5c767 265
8465de90
RP
266 return [vrf_iface_name]
267
768b4ec5 268 def get_upper_ifacenames_running(self, ifaceobj):
8465de90
RP
269 return None
270
271 def _get_iproute2_vrf_table(self, vrf_dev_name):
272 for t, v in self.iproute2_vrf_map.iteritems():
273 if v == vrf_dev_name:
09753350 274 return str(t)
8465de90
RP
275 return None
276
277 def _get_avail_vrf_table_id(self):
6f2890fc
RP
278 if self.last_used_vrf_table == None:
279 table_id_start = self.vrf_table_id_start
280 else:
281 table_id_start = self.last_used_vrf_table + 1
282 for t in range(table_id_start,
283 self.vrf_table_id_end):
8465de90
RP
284 if not self.iproute2_vrf_map.get(t):
285 self.last_used_vrf_table = t
6f2890fc 286 return str(t)
8465de90
RP
287 return None
288
bf3eda91 289 def _iproute2_is_vrf_tableid_inuse(self, vrfifaceobj, table_id):
25e2386e 290 old_vrf_name = self.iproute2_vrf_map.get(int(table_id))
bf3eda91 291 if old_vrf_name and old_vrf_name != vrfifaceobj.name:
25e2386e 292 self.log_error('table id %s already assigned to vrf dev %s'
bf3eda91 293 %(table_id, old_vrf_name), vrfifaceobj)
25e2386e 294
bf3eda91 295 def _iproute2_vrf_table_entry_add(self, vrfifaceobj, table_id):
05ac52f0 296 old_vrf_name = self.iproute2_vrf_map.get(int(table_id))
25e2386e 297 if not old_vrf_name:
bf3eda91 298 self.iproute2_vrf_map[int(table_id)] = vrfifaceobj.name
05ac52f0
RP
299 if self.iproute2_vrf_map_fd:
300 self.iproute2_vrf_map_fd.write('%s %s\n'
bf3eda91 301 %(table_id, vrfifaceobj.name))
05ac52f0 302 self.iproute2_vrf_map_fd.flush()
c8a3b44e 303 self.vrf_count += 1
25e2386e 304 return
bf3eda91 305 if old_vrf_name != vrfifaceobj.name:
25e2386e
RP
306 self.log_error('table id %d already assigned to vrf dev %s'
307 %(table_id, old_vrf_name))
8465de90
RP
308
309 def _iproute2_vrf_table_entry_del(self, table_id):
310 try:
05ac52f0
RP
311 # with any del of vrf map, we need to force sync to disk
312 self.iproute2_vrf_map_sync_to_disk = True
09753350 313 del self.iproute2_vrf_map[int(table_id)]
8465de90
RP
314 except Exception, e:
315 self.logger.info('vrf: iproute2 vrf map del failed for %d (%s)'
316 %(table_id, str(e)))
317 pass
318
aa36221f
RP
319 def _is_vrf_dev(self, ifacename):
320 # Look at iproute2 map for now.
321 # If it was a master we knew about,
322 # it is definately there
323 if ifacename in self.iproute2_vrf_map.values():
324 return True
325 return False
326
122ef35b
RP
327 def _is_dhcp_slave(self, ifaceobj):
328 if (not ifaceobj.addr_method or
329 (ifaceobj.addr_method != 'dhcp' and
330 ifaceobj.addr_method != 'dhcp6')):
331 return False
332 return True
333
0ba04b38 334 def _up_vrf_slave_without_master(self, ifacename, vrfname, ifaceobj,
79cf5764 335 vrf_master_objs):
8ad5c767
RP
336 """ If we have a vrf slave that has dhcp configured, bring up the
337 vrf master now. This is needed because vrf has special handling
338 in dhclient hook which requires the vrf master to be present """
0ba04b38 339
8ad5c767
RP
340 vrf_master = ifaceobj.upperifaces[0]
341 if not vrf_master:
342 self.logger.warn('%s: vrf master not found' %ifacename)
343 return
344 if os.path.exists('/sys/class/net/%s' %vrf_master):
345 self.logger.info('%s: vrf master %s exists returning'
346 %(ifacename, vrf_master))
347 return
8ad5c767
RP
348 self.logger.info('%s: bringing up vrf master %s'
349 %(ifacename, vrf_master))
350 for mobj in vrf_master_objs:
351 vrf_table = mobj.get_attr_value_first('vrf-table')
352 if vrf_table:
df53966d
RP
353 if vrf_table == 'auto':
354 vrf_table = self._get_avail_vrf_table_id()
355 if not vrf_table:
356 self.log_error('%s: unable to get an auto table id'
bf3eda91 357 %mobj.name, ifaceobj)
df53966d
RP
358 self.logger.info('%s: table id auto: selected table id %s\n'
359 %(mobj.name, vrf_table))
25e2386e
RP
360 try:
361 self._up_vrf_dev(mobj, vrf_table, False)
362 except Exception:
363 raise
df53966d 364 break
0ba04b38 365 self._handle_existing_connections(ifaceobj, vrfname)
8ad5c767
RP
366 self.ipcmd.link_set(ifacename, 'master', vrfname)
367 return
368
717cee31 369 def _down_dhcp_slave(self, ifaceobj, vrfname):
122ef35b 370 try:
717cee31 371 dhclient_cmd_prefix = None
6369e774
RP
372 if (vrfname and self.vrf_exec_cmd_prefix and
373 self.ipcmd.link_exists(vrfname)):
717cee31
RP
374 dhclient_cmd_prefix = '%s %s' %(self.vrf_exec_cmd_prefix,
375 vrfname)
376 self.dhclientcmd.release(ifaceobj.name, dhclient_cmd_prefix)
122ef35b
RP
377 except:
378 # ignore any dhclient release errors
379 pass
380
0ba04b38 381 def _handle_existing_connections(self, ifaceobj, vrfname):
fc5e1735 382 if not ifaceobj or ifupdownflags.flags.PERFMODE:
0ba04b38
RP
383 return
384 if (self.vrf_mgmt_devname and
385 self.vrf_mgmt_devname == vrfname):
386 self._kill_ssh_connections(ifaceobj.name)
387 if self._is_dhcp_slave(ifaceobj):
717cee31 388 self._down_dhcp_slave(ifaceobj, vrfname)
0ba04b38 389
8ad5c767 390 def _up_vrf_slave(self, ifacename, vrfname, ifaceobj=None,
09753350 391 ifaceobj_getfunc=None, vrf_exists=False):
8465de90 392 try:
d2b35716 393 master_exists = True
09753350
RP
394 if vrf_exists or self.ipcmd.link_exists(vrfname):
395 upper = self.ipcmd.link_get_upper(ifacename)
4d2c9798 396 if not upper or upper != vrfname:
0ba04b38 397 self._handle_existing_connections(ifaceobj, vrfname)
122ef35b 398 self.ipcmd.link_set(ifacename, 'master', vrfname)
79cf5764
RP
399 elif ifaceobj:
400 vrf_master_objs = ifaceobj_getfunc(vrfname)
401 if not vrf_master_objs:
80be09ba
RP
402 # this is the case where vrf is assigned to an interface
403 # but user has not provided a vrf interface.
404 # people expect you to warn them but go ahead with the
405 # rest of the config on that interface
406 netlink.link_set_updown(ifacename, "up")
407 self.log_error('vrf master ifaceobj %s not found'
408 %vrfname)
79cf5764
RP
409 return
410 if (ifupdownflags.flags.ALL or
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
RP
606 if self.vrf_count == self.vrf_max_count:
607 self.log_error('%s: max vrf count %d hit...not '
608 'creating vrf' %(ifaceobj.name,
bf3eda91 609 self.vrf_count), ifaceobj)
6f2890fc
RP
610 if vrf_table == 'auto':
611 vrf_table = self._get_avail_vrf_table_id()
612 if not vrf_table:
613 self.log_error('%s: unable to get an auto table id'
bf3eda91 614 %ifaceobj.name, ifaceobj)
6f2890fc
RP
615 self.logger.info('%s: table id auto: selected table id %s\n'
616 %(ifaceobj.name, vrf_table))
25e2386e 617 else:
bf3eda91 618 self._iproute2_is_vrf_tableid_inuse(ifaceobj, vrf_table)
f6466fcb
RP
619 if ifaceobj.name in self.system_reserved_rt_tables.keys():
620 self.log_error('cannot use system reserved %s table ids'
bf3eda91
RP
621 %(str(self.system_reserved_rt_tables.keys())),
622 ifaceobj)
d54baa22
RP
623
624 if not vrf_table.isdigit():
625 self.log_error('%s: vrf-table must be an integer or \'auto\''
626 %(ifaceobj.name), ifaceobj)
627
6f2890fc
RP
628 # XXX: If we decide to not allow vrf id usages out of
629 # the reserved ifupdown range, then uncomment this code.
fd8c6caf
RP
630 else:
631 if (int(vrf_table) < self.vrf_table_id_start or
632 int(vrf_table) > self.vrf_table_id_end):
633 self.log_error('%s: vrf table id %s out of reserved range [%d,%d]'
634 %(ifaceobj.name, vrf_table,
635 self.vrf_table_id_start,
bf3eda91 636 self.vrf_table_id_end), ifaceobj)
2df6a60f 637 try:
8465de90
RP
638 self.ipcmd.link_create(ifaceobj.name, 'vrf',
639 {'table' : '%s' %vrf_table})
2df6a60f
RP
640 except Exception, e:
641 self.log_error('%s: create failed (%s)\n'
bf3eda91 642 %(ifaceobj.name, str(e)), ifaceobj)
25e2386e 643 if vrf_table != 'auto':
bf3eda91 644 self._iproute2_vrf_table_entry_add(ifaceobj, vrf_table)
2df6a60f 645 else:
4d2c9798
RP
646 if vrf_table == 'auto':
647 vrf_table = self._get_iproute2_vrf_table(ifaceobj.name)
648 if not vrf_table:
649 self.log_error('%s: unable to get vrf table id'
bf3eda91 650 %ifaceobj.name, ifaceobj)
6f2890fc 651
2df6a60f
RP
652 # if the device exists, check if table id is same
653 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobj.name)
654 if vrfdev_attrs:
655 running_table = vrfdev_attrs.get('table', None)
656 if vrf_table != running_table:
6f2890fc 657 self.log_error('%s: cannot change vrf table id,running table id %s is different from config id %s' %(ifaceobj.name,
bf3eda91
RP
658 running_table, vrf_table),
659 ifaceobj)
4d2c9798
RP
660 return vrf_table
661
25e2386e 662 def _up_vrf_helper(self, ifaceobj, vrf_table):
c4e05f9f
RP
663 mode = ""
664 if ifupdownflags.flags.PERFMODE:
665 mode = "boot"
25e2386e 666 if self.vrf_helper:
a193d8d1
JF
667 utils.exec_command('%s create %s %s %s' %
668 (self.vrf_helper,
669 ifaceobj.name,
670 vrf_table,
671 mode))
25e2386e 672
4d2c9798
RP
673 def _up_vrf_dev(self, ifaceobj, vrf_table, add_slaves=True,
674 ifaceobj_getfunc=None):
8ad5c767
RP
675
676 # if vrf dev is already processed return. This can happen
0ba04b38
RP
677 # if we the slave was configured before.
678 # see self._up_vrf_slave_without_master
8ad5c767
RP
679 if self._check_vrf_dev_processed_flag(ifaceobj):
680 return True
681
25e2386e
RP
682 try:
683 vrf_table = self._create_vrf_dev(ifaceobj, vrf_table)
684 except Exception, e:
bf3eda91 685 self.log_error('%s: %s' %(ifaceobj.name, str(e)), ifaceobj)
25e2386e 686
8ad5c767 687 try:
8ad5c767 688 self._add_vrf_rules(ifaceobj.name, vrf_table)
6369e774 689 self._up_vrf_helper(ifaceobj, vrf_table)
8ad5c767 690 if add_slaves:
4d2c9798 691 self._add_vrf_slaves(ifaceobj, ifaceobj_getfunc)
8ad5c767 692 self._set_vrf_dev_processed_flag(ifaceobj)
2864d6f3 693 netlink.link_set_updown(ifaceobj.name, "up")
8ad5c767 694 except Exception, e:
bf3eda91 695 self.log_error('%s: %s' %(ifaceobj.name, str(e)), ifaceobj)
8ad5c767 696
0ba04b38 697 def _kill_ssh_connections(self, ifacename):
5c5a7b93 698 try:
0ba04b38
RP
699 runningaddrsdict = self.ipcmd.addr_get(ifacename)
700 if not runningaddrsdict:
5c5a7b93 701 return
0ba04b38
RP
702 iplist = [i.split('/', 1)[0] for i in runningaddrsdict.keys()]
703 if not iplist:
704 return
705 proc=[]
5c5a7b93
N
706 #Example output:
707 #ESTAB 0 0 10.0.1.84:ssh 10.0.1.228:45186
708 #users:(("sshd",pid=2528,fd=3))
0ba04b38 709 cmdl = ['/bin/ss', '-t', '-p']
a193d8d1 710 for line in utils.exec_commandl(cmdl).splitlines():
5c5a7b93
N
711 citems = line.split()
712 addr = None
713 if '%' in citems[3]:
714 addr = citems[3].split('%')[0]
715 elif ':ssh' in citems[3]:
716 addr = citems[3].split(':')[0]
717 if not addr:
718 continue
0ba04b38 719 if addr in iplist:
5c5a7b93
N
720 if len(citems) == 6:
721 proc.append(citems[5].split(',')[1].split('=')[1])
722
723 if not proc:
724 return
be276272
N
725 pid = None
726 # outpt of '/usr/bin/pstree -Aps <pid>':
727 # 'systemd(1)---sshd(990)---sshd(16112)---sshd(16126)---bash(16127)---sudo(16756)---ifreload(16761)---pstree(16842)\n'
728 # get the above output to following format
729 # ['systemd(1)', 'sshd(990)', 'sshd(16112)', 'sshd(16126)', 'bash(16127)', 'sudo(16756)', 'ifreload(16761)', 'pstree(16850)']
730 pstree = list(reversed(utils.exec_command('/usr/bin/pstree -Aps %s' %os.getpid()).strip().split('---')))
731 for index, process in enumerate(pstree):
732 # check the parent of SSH process to make sure
733 # we don't kill SSH server or systemd process
734 if 'sshd' in process and 'sshd' in pstree[index + 1]:
735 pid = filter(lambda x: x.isdigit(), process)
736 break
aa36221f
RP
737 self.logger.info("%s: killing active ssh sessions: %s"
738 %(ifacename, str(proc)))
cbdde74e
RP
739
740 if ifupdownflags.flags.DRYRUN:
741 return
5c5a7b93
N
742 for id in proc:
743 if id != pid:
744 try:
aa36221f 745 os.kill(int(id), signal.SIGINT)
5c5a7b93
N
746 except OSError as e:
747 continue
0ba04b38
RP
748
749 # Kill current SSH client
5c5a7b93 750 if pid in proc:
32f6e6ca 751 try:
0ba04b38
RP
752 forkret = os.fork()
753 except OSError, e:
754 self.logger.info("fork error : %s [%d]" % (e.strerror, e.errno))
755 if (forkret == 0): # The first child.
756 try:
757 os.setsid()
758 self.logger.info("%s: ifreload continuing in the background" %ifacename)
759 except OSError, (err_no, err_message):
760 self.logger.info("os.setsid failed: errno=%d: %s" % (err_no, err_message))
761 self.logger.info("pid=%d pgid=%d" % (os.getpid(), os.getpgid(0)))
5c5a7b93 762 try:
aa36221f
RP
763 self.logger.info("%s: killing our session: %s"
764 %(ifacename, str(proc)))
765 os.kill(int(pid), signal.SIGINT)
5c5a7b93
N
766 return
767 except OSError as e:
768 return
769 except Exception, e:
770 self.logger.info('%s: %s' %(ifacename, str(e)))
771
8ad5c767 772 def _up(self, ifaceobj, ifaceobj_getfunc=None):
8465de90
RP
773 try:
774 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
775 if vrf_table:
05ac52f0 776 self._iproute2_vrf_map_initialize()
09753350 777 # This is a vrf device
4d2c9798 778 self._up_vrf_dev(ifaceobj, vrf_table, True, ifaceobj_getfunc)
8465de90
RP
779 else:
780 vrf = ifaceobj.get_attr_value_first('vrf')
781 if vrf:
05ac52f0 782 self._iproute2_vrf_map_initialize()
09753350 783 # This is a vrf slave
8ad5c767
RP
784 self._up_vrf_slave(ifaceobj.name, vrf, ifaceobj,
785 ifaceobj_getfunc)
aa36221f
RP
786 else:
787 # check if we were a slave before
788 master = self.ipcmd.link_get_master(ifaceobj.name)
789 if master:
717cee31 790 self._iproute2_vrf_map_initialize()
aa36221f 791 if self._is_vrf_dev(master):
0ba04b38
RP
792 self._down_vrf_slave(ifaceobj.name, ifaceobj,
793 master)
8465de90 794 except Exception, e:
bf3eda91 795 self.log_error(str(e), ifaceobj)
8465de90 796
25e2386e 797 def _down_vrf_helper(self, ifaceobj, vrf_table):
c4e05f9f
RP
798 mode = ""
799 if ifupdownflags.flags.PERFMODE:
800 mode = "boot"
25e2386e 801 if self.vrf_helper:
a193d8d1
JF
802 utils.exec_command('%s delete %s %s %s' %
803 (self.vrf_helper,
804 ifaceobj.name,
805 vrf_table,
806 mode))
25e2386e 807
c4be5481 808 def _down_vrf_dev(self, ifaceobj, vrf_table, ifaceobj_getfunc=None):
5c5a7b93 809
8465de90
RP
810 if vrf_table == 'auto':
811 vrf_table = self._get_iproute2_vrf_table(ifaceobj.name)
aa36221f 812
2365b3c9
RP
813 running_slaves = self.ipcmd.link_get_lowers(ifaceobj.name)
814 if running_slaves:
815 for s in running_slaves:
816 if ifaceobj_getfunc:
817 sobj = ifaceobj_getfunc(s)
818 try:
819 self._handle_existing_connections(sobj[0]
820 if sobj else None,
0ba04b38 821 ifaceobj.name)
2365b3c9
RP
822 except Exception, e:
823 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
824 pass
825 try:
826 self.ipcmd.addr_flush(s)
2864d6f3 827 netlink.link_set_updown(s, "down")
2365b3c9
RP
828 except Exception, e:
829 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
830 pass
768b4ec5 831
40804f1a
RP
832 try:
833 self._down_vrf_helper(ifaceobj, vrf_table)
834 except Exception, e:
835 self.logger.warn('%s: %s' %(ifaceobj.name, str(e)))
836 pass
25e2386e 837
768b4ec5 838 try:
f1c92482 839 self._del_vrf_rules(ifaceobj.name, vrf_table)
768b4ec5
RP
840 except Exception, e:
841 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
842 pass
843
844 try:
f1c92482
RP
845 self.ipcmd.link_delete(ifaceobj.name)
846 except Exception, e:
847 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
848 pass
849
850 try:
851 self._iproute2_vrf_table_entry_del(vrf_table)
8465de90 852 except Exception, e:
768b4ec5
RP
853 self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
854 pass
8465de90 855
f1c92482 856
0ba04b38 857 def _down_vrf_slave(self, ifacename, ifaceobj=None, vrfname=None):
8465de90 858 try:
0ba04b38 859 self._handle_existing_connections(ifaceobj, vrfname)
768b4ec5 860 self.ipcmd.link_set(ifacename, 'nomaster')
2864d6f3 861 netlink.link_set_updown(ifacename, "down")
8465de90 862 except Exception, e:
768b4ec5 863 self.logger.warn('%s: %s' %(ifacename, str(e)))
8465de90 864
8ad5c767 865 def _down(self, ifaceobj, ifaceobj_getfunc=None):
8465de90
RP
866 try:
867 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
868 if vrf_table:
05ac52f0 869 self._iproute2_vrf_map_initialize()
c4be5481 870 self._down_vrf_dev(ifaceobj, vrf_table, ifaceobj_getfunc)
8465de90
RP
871 else:
872 vrf = ifaceobj.get_attr_value_first('vrf')
873 if vrf:
05ac52f0 874 self._iproute2_vrf_map_initialize()
0ba04b38 875 self._down_vrf_slave(ifaceobj.name, ifaceobj, None)
8465de90
RP
876 except Exception, e:
877 self.log_warn(str(e))
878
879 def _query_check_vrf_slave(self, ifaceobj, ifaceobjcurr, vrf):
880 try:
54616d3f 881 master = self.ipcmd.link_get_master(ifaceobj.name)
8465de90 882 if not master or master != vrf:
586535e8 883 ifaceobjcurr.update_config_with_status('vrf', str(master), 1)
8465de90
RP
884 else:
885 ifaceobjcurr.update_config_with_status('vrf', master, 0)
886 except Exception, e:
bf3eda91 887 self.log_error(str(e), ifaceobjcurr)
8465de90 888
6e16e5ae 889 def _query_check_vrf_dev(self, ifaceobj, ifaceobjcurr, vrf_table):
8465de90
RP
890 try:
891 if not self.ipcmd.link_exists(ifaceobj.name):
892 self.logger.info('%s: vrf: does not exist' %(ifaceobj.name))
893 return
894 if vrf_table == 'auto':
895 config_table = self._get_iproute2_vrf_table(ifaceobj.name)
896 else:
897 config_table = vrf_table
898 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobj.name)
899 if not vrfdev_attrs:
900 ifaceobjcurr.update_config_with_status('vrf-table', 'None', 1)
901 return
902 running_table = vrfdev_attrs.get('table')
903 if not running_table:
904 ifaceobjcurr.update_config_with_status('vrf-table', 'None', 1)
905 return
906 if config_table != running_table:
907 ifaceobjcurr.update_config_with_status('vrf-table',
908 running_table, 1)
909 else:
910 ifaceobjcurr.update_config_with_status('vrf-table',
911 running_table, 0)
6e16e5ae 912 if not ifupdownflags.flags.WITHDEFAULTS:
669b422a
RP
913 return
914 if self.vrf_helper:
6e16e5ae 915 try:
a193d8d1 916 utils.exec_command('%s verify %s %s'
6e16e5ae
N
917 %(self.vrf_helper,
918 ifaceobj.name, config_table))
919 ifaceobjcurr.update_config_with_status('vrf-helper',
920 '%s create %s %s'
921 %(self.vrf_helper,
922 ifaceobj.name,
923 config_table), 0)
924 except Exception, e:
925 ifaceobjcurr.update_config_with_status('vrf-helper',
926 '%s create %s %s'
927 %(self.vrf_helper,
928 ifaceobj.name,
929 config_table), 1)
930 pass
8465de90
RP
931 except Exception, e:
932 self.log_warn(str(e))
933
6e16e5ae 934 def _query_check(self, ifaceobj, ifaceobjcurr):
8465de90
RP
935 try:
936 vrf_table = ifaceobj.get_attr_value_first('vrf-table')
937 if vrf_table:
eb3ce8c8 938 self._iproute2_vrf_map_initialize(writetodisk=False)
6e16e5ae 939 self._query_check_vrf_dev(ifaceobj, ifaceobjcurr, vrf_table)
8465de90
RP
940 else:
941 vrf = ifaceobj.get_attr_value_first('vrf')
942 if vrf:
eb3ce8c8 943 self._iproute2_vrf_map_initialize(writetodisk=False)
8465de90
RP
944 self._query_check_vrf_slave(ifaceobj, ifaceobjcurr, vrf)
945 except Exception, e:
946 self.log_warn(str(e))
947
8ad5c767 948 def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
8465de90
RP
949 try:
950 kind = self.ipcmd.link_get_kind(ifaceobjrunning.name)
951 if kind == 'vrf':
54616d3f 952 vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobjrunning.name)
8465de90
RP
953 if vrfdev_attrs:
954 running_table = vrfdev_attrs.get('table')
955 if running_table:
956 ifaceobjrunning.update_config('vrf-table',
957 running_table)
958 elif kind == 'vrf_slave':
54616d3f 959 vrf = self.ipcmd.link_get_master(ifaceobjrunning.name)
8465de90
RP
960 if vrf:
961 ifaceobjrunning.update_config('vrf', vrf)
962 except Exception, e:
963 self.log_warn(str(e))
964
baa909c6
N
965 def _query(self, ifaceobj, **kwargs):
966 if not self.vrf_helper:
967 return
968 if (ifaceobj.link_kind & ifaceLinkKind.VRF):
969 ifaceobj.update_config('vrf-helper', '%s %s' %(self.vrf_helper,
970 ifaceobj.name))
971
8465de90
RP
972 _run_ops = {'pre-up' : _up,
973 'post-down' : _down,
974 'query-running' : _query_running,
baa909c6
N
975 'query-checkcurr' : _query_check,
976 'query' : _query}
8465de90
RP
977
978 def get_ops(self):
979 """ returns list of ops supported by this module """
980 return self._run_ops.keys()
981
982 def _init_command_handlers(self):
8465de90 983 if not self.ipcmd:
fc5e1735 984 self.ipcmd = iproute2()
8465de90 985 if not self.bondcmd:
fc5e1735 986 self.bondcmd = bondutil()
122ef35b 987 if not self.dhclientcmd:
fc5e1735 988 self.dhclientcmd = dhclient()
8465de90 989
8ad5c767
RP
990 def run(self, ifaceobj, operation, query_ifaceobj=None,
991 ifaceobj_getfunc=None, **extra_args):
8465de90
RP
992 """ run bond configuration on the interface object passed as argument
993
994 Args:
995 **ifaceobj** (object): iface object
996
997 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
998 'query-running'
999
1000 Kwargs:
1001 **query_ifaceobj** (object): query check ifaceobject. This is only
1002 valid when op is 'query-checkcurr'. It is an object same as
1003 ifaceobj, but contains running attribute values and its config
1004 status. The modules can use it to return queried running state
1005 of interfaces. status is success if the running state is same
1006 as user required state in ifaceobj. error otherwise.
1007 """
1008 op_handler = self._run_ops.get(operation)
1009 if not op_handler:
1010 return
1011 self._init_command_handlers()
1012 if operation == 'query-checkcurr':
6e16e5ae 1013 op_handler(self, ifaceobj, query_ifaceobj)
8465de90 1014 else:
8ad5c767 1015 op_handler(self, ifaceobj, ifaceobj_getfunc=ifaceobj_getfunc)