]>
git.proxmox.com Git - mirror_ifupdown2.git/blob - addons/vrf.py
3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
12 from ifupdown
.iface
import *
13 import ifupdown
.policymanager
as policymanager
15 import ifupdown
.rtnetlink_api
as rtnetlink_api
16 from ifupdownaddons
.modulebase
import moduleBase
17 from ifupdownaddons
.bondutil
import bondutil
18 from ifupdownaddons
.iproute2
import iproute2
19 from ifupdownaddons
.dhclient
import dhclient
24 class vrf(moduleBase
):
25 """ ifupdown2 addon module to configure vrfs """
26 _modinfo
= { 'mhelp' : 'vrf configuration module',
29 {'help' : 'vrf device table id. key to ' +
30 'creating a vrf device',
31 'example': ['vrf-table-id 1']},
33 {'help' : 'vrf device default route ' +
34 'to avoid communication outside the vrf device',
35 'example': ['vrf-default-route yes/no']},
37 {'help' : 'vrf the interface is part of.',
38 'example': ['vrf blue']}}}
40 iproute2_vrf_filename
= '/etc/iproute2/rt_tables.d/ifupdown2_vrf_map.conf'
41 iproute2_vrf_filehdr
= '# This file is autogenerated by ifupdown2.\n' + \
42 '# It contains the vrf name to table mapping.\n' + \
43 '# Reserved table range %s %s\n'
44 VRF_TABLE_START
= 1001
47 def __init__(self
, *args
, **kargs
):
48 ifupdownaddons
.modulebase
.moduleBase
.__init
__(self
, *args
, **kargs
)
51 self
.dhclientcmd
= None
52 self
.name
= self
.__class
__.__name
__
54 # if perf mode is set, remove vrf map file.
55 # start afresh. PERFMODE is set at boot
56 if os
.path
.exists(self
.iproute2_vrf_filename
):
58 self
.logger
.info('vrf: removing file %s'
59 %self
.iproute2_vrf_filename
)
60 os
.remove(self
.iproute2_vrf_filename
)
62 self
.logger
.debug('vrf: removing file failed (%s)'
65 ip_rules
= self
.exec_command('/sbin/ip rule show').splitlines()
66 self
.ip_rule_cache
= [' '.join(r
.split()) for r
in ip_rules
]
68 self
.ip_rule_cache
= []
69 self
.logger
.warn('%s' %str
(e
))
72 ip_rules
= self
.exec_command('/sbin/ip -6 rule show').splitlines()
73 self
.ip6_rule_cache
= [' '.join(r
.split()) for r
in ip_rules
]
75 self
.ip6_rule_cache
= []
76 self
.logger
.warn('%s' %str
(e
))
78 #self.logger.debug("vrf: ip rule cache")
79 #self.logger.info(self.ip_rule_cache)
81 #self.logger.info("vrf: ip -6 rule cache")
82 #self.logger.info(self.ip6_rule_cache)
84 # XXX: check for vrf reserved overlap in /etc/iproute2/rt_tables
85 self
.iproute2_vrf_map
= {}
86 # read or create /etc/iproute2/rt_tables.d/ifupdown2.vrf_map
87 if os
.path
.exists(self
.iproute2_vrf_filename
):
88 self
.vrf_map_fd
= open(self
.iproute2_vrf_filename
, 'a+')
89 lines
= self
.vrf_map_fd
.readlines()
95 (table
, vrf_name
) = l
.strip().split()
96 self
.iproute2_vrf_map
[table
] = vrf_name
98 self
.logger
.info('vrf: iproute2_vrf_map: unable to parse %s'
101 #self.logger.info("vrf: dumping iproute2_vrf_map")
102 #self.logger.info(self.iproute2_vrf_map)
104 # purge vrf table entries that are not around
105 iproute2_vrf_map_pruned
= {}
106 for t
, v
in self
.iproute2_vrf_map
.iteritems():
107 if os
.path
.exists('/sys/class/net/%s' %v
):
108 iproute2_vrf_map_pruned
[int(t
)] = v
112 self
._del
_vrf
_rules
(v
, t
)
115 self
.iproute2_vrf_map
= iproute2_vrf_map_pruned
117 self
.vrf_table_id_start
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='vrf-table-id-start')
118 if not self
.vrf_table_id_start
:
119 self
.vrf_table_id_start
= self
.VRF_TABLE_START
120 self
.vrf_table_id_end
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='vrf-table-id-end')
121 if not self
.vrf_table_id_end
:
122 self
.vrf_table_id_end
= self
.VRF_TABLE_END
123 self
.vrf_max_count
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='vrf-max-count')
125 last_used_vrf_table
= None
126 for t
in range(self
.vrf_table_id_start
,
127 self
.vrf_table_id_end
):
128 if not self
.iproute2_vrf_map
.get(t
):
130 last_used_vrf_table
= t
131 self
.last_used_vrf_table
= last_used_vrf_table
133 self
.iproute2_write_vrf_map
= False
134 atexit
.register(self
.iproute2_vrf_map_write
)
135 self
.vrf_fix_local_table
= True
137 self
.vrf_cgroup_create
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='vrf-cgroup-create')
138 if not self
.vrf_cgroup_create
:
139 self
.vrf_cgroup_create
= False
140 elif self
.vrf_cgroup_create
== 'yes':
141 self
.vrf_cgroup_create
= True
143 self
.vrf_cgroup_create
= False
145 def iproute2_vrf_map_write(self
):
146 if not self
.iproute2_write_vrf_map
:
148 self
.logger
.info('vrf: writing table map to %s'
149 %self
.iproute2_vrf_filename
)
150 with
open(self
.iproute2_vrf_filename
, 'w') as f
:
151 f
.write(self
.iproute2_vrf_filehdr
%(self
.vrf_table_id_start
,
152 self
.vrf_table_id_end
))
153 for t
, v
in self
.iproute2_vrf_map
.iteritems():
154 f
.write('%s %s\n' %(t
, v
))
156 def _is_vrf(self
, ifaceobj
):
157 if ifaceobj
.get_attr_value_first('vrf-table'):
161 def get_upper_ifacenames(self
, ifaceobj
, ifacenames_all
=None):
162 """ Returns list of interfaces dependent on ifaceobj """
164 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
166 ifaceobj
.link_type
= ifaceLinkType
.LINK_MASTER
167 ifaceobj
.link_kind |
= ifaceLinkKind
.VRF
168 vrf_iface_name
= ifaceobj
.get_attr_value_first('vrf')
169 if not vrf_iface_name
:
171 ifaceobj
.link_type
= ifaceLinkType
.LINK_SLAVE
172 ifaceobj
.link_kind |
= ifaceLinkKind
.VRF_SLAVE
174 return [vrf_iface_name
]
176 def get_upper_ifacenames_running(self
, ifaceobj
):
179 def _get_iproute2_vrf_table(self
, vrf_dev_name
):
180 for t
, v
in self
.iproute2_vrf_map
.iteritems():
181 if v
== vrf_dev_name
:
185 def _get_avail_vrf_table_id(self
):
186 if self
.last_used_vrf_table
== None:
187 table_id_start
= self
.vrf_table_id_start
189 table_id_start
= self
.last_used_vrf_table
+ 1
190 for t
in range(table_id_start
,
191 self
.vrf_table_id_end
):
192 if not self
.iproute2_vrf_map
.get(t
):
193 self
.last_used_vrf_table
= t
197 def _iproute2_vrf_table_entry_add(self
, vrf_dev_name
, table_id
):
198 self
.iproute2_vrf_map
[int(table_id
)] = vrf_dev_name
199 self
.iproute2_write_vrf_map
= True
201 def _iproute2_vrf_table_entry_del(self
, table_id
):
203 del self
.iproute2_vrf_map
[int(table_id
)]
204 self
.iproute2_write_vrf_map
= True
206 self
.logger
.info('vrf: iproute2 vrf map del failed for %d (%s)'
210 def _is_vrf_dev(self
, ifacename
):
211 # Look at iproute2 map for now.
212 # If it was a master we knew about,
213 # it is definately there
214 if ifacename
in self
.iproute2_vrf_map
.values():
218 def _is_dhcp_slave(self
, ifaceobj
):
219 if (not ifaceobj
.addr_method
or
220 (ifaceobj
.addr_method
!= 'dhcp' and
221 ifaceobj
.addr_method
!= 'dhcp6')):
225 def _handle_dhcp_slaves(self
, ifacename
, vrfname
, ifaceobj
,
227 """ If we have a vrf slave that has dhcp configured, bring up the
228 vrf master now. This is needed because vrf has special handling
229 in dhclient hook which requires the vrf master to be present """
230 if not self
._is
_dhcp
_slave
(ifaceobj
):
232 vrf_master
= ifaceobj
.upperifaces
[0]
234 self
.logger
.warn('%s: vrf master not found' %ifacename
)
236 if os
.path
.exists('/sys/class/net/%s' %vrf_master
):
237 self
.logger
.info('%s: vrf master %s exists returning'
238 %(ifacename
, vrf_master
))
240 vrf_master_objs
= ifaceobj_getfunc(vrf_master
)
241 if not vrf_master_objs
:
242 self
.logger
.warn('%s: vrf master ifaceobj not found' %ifacename
)
244 self
.logger
.info('%s: bringing up vrf master %s'
245 %(ifacename
, vrf_master
))
246 for mobj
in vrf_master_objs
:
247 vrf_table
= mobj
.get_attr_value_first('vrf-table')
249 if vrf_table
== 'auto':
250 vrf_table
= self
._get
_avail
_vrf
_table
_id
()
252 self
.log_error('%s: unable to get an auto table id'
254 self
.logger
.info('%s: table id auto: selected table id %s\n'
255 %(mobj
.name
, vrf_table
))
256 self
._up
_vrf
_dev
(mobj
, vrf_table
, False)
258 if vrfname
== 'mgmt':
259 self
._kill
_ssh
(ifaceobj
.name
)
260 self
._down
_dhcp
_slave
(ifaceobj
)
261 self
.ipcmd
.link_set(ifacename
, 'master', vrfname
)
264 def _down_dhcp_slave(self
, ifaceobj
):
266 self
.dhclientcmd
.release(ifaceobj
.name
)
268 # ignore any dhclient release errors
271 def _up_vrf_slave(self
, ifacename
, vrfname
, ifaceobj
=None,
272 ifaceobj_getfunc
=None, vrf_exists
=False):
274 if vrf_exists
or self
.ipcmd
.link_exists(vrfname
):
275 upper
= self
.ipcmd
.link_get_upper(ifacename
)
276 if not upper
or upper
!= vrfname
:
277 if ifaceobj
and vrfname
== 'mgmt':
278 self
._kill
_ssh
(ifaceobj
.name
)
279 if ifaceobj
and self
._is
_dhcp
_slave
(ifaceobj
):
280 self
._down
_dhcp
_slave
(ifaceobj
)
281 self
.ipcmd
.link_set(ifacename
, 'master', vrfname
)
283 self
._handle
_dhcp
_slaves
(ifacename
, vrfname
, ifaceobj
,
286 self
.log_error('%s: %s' %(ifacename
, str(e
)))
288 def _del_vrf_rules(self
, vrf_dev_name
, vrf_table
):
290 ip_rule_out_format
= '%s: from all %s %s lookup %s'
291 ip_rule_cmd
= 'ip %s rule del pref %s %s %s table %s'
293 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
294 if rule
in self
.ip_rule_cache
:
295 rule_cmd
= ip_rule_cmd
%('', pref
, 'oif', vrf_dev_name
, vrf_table
)
296 self
.exec_command(rule_cmd
)
298 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
299 if rule
in self
.ip_rule_cache
:
300 rule_cmd
= ip_rule_cmd
%('', pref
, 'iif', vrf_dev_name
, vrf_table
)
301 self
.exec_command(rule_cmd
)
303 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
304 if rule
in self
.ip6_rule_cache
:
305 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'oif', vrf_dev_name
,
307 self
.exec_command(rule_cmd
)
309 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
310 if rule
in self
.ip6_rule_cache
:
311 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'iif', vrf_dev_name
,
313 self
.exec_command(rule_cmd
)
315 def _add_vrf_rules(self
, vrf_dev_name
, vrf_table
):
317 ip_rule_out_format
= '%s: from all %s %s lookup %s'
318 ip_rule_cmd
= 'ip %s rule add pref %s %s %s table %s'
319 if self
.vrf_fix_local_table
:
320 self
.vrf_fix_local_table
= False
321 rule
= '0: from all lookup local'
322 if rule
in self
.ip_rule_cache
:
324 self
.exec_command('ip rule del pref 0')
325 self
.exec_command('ip rule add pref 32765 table local')
327 self
.logger
.info('%s' %str
(e
))
329 if rule
in self
.ip6_rule_cache
:
331 self
.exec_command('ip -6 rule del pref 0')
332 self
.exec_command('ip -6 rule add pref 32765 table local')
334 self
.logger
.info('%s' %str
(e
))
338 #200: from all oif blue lookup blue
339 #200: from all iif blue lookup blue
341 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
342 if rule
not in self
.ip_rule_cache
:
343 rule_cmd
= ip_rule_cmd
%('', pref
, 'oif', vrf_dev_name
, vrf_table
)
344 self
.exec_command(rule_cmd
)
346 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
347 if rule
not in self
.ip_rule_cache
:
348 rule_cmd
= ip_rule_cmd
%('', pref
, 'iif', vrf_dev_name
, vrf_table
)
349 self
.exec_command(rule_cmd
)
351 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
352 if rule
not in self
.ip6_rule_cache
:
353 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'oif', vrf_dev_name
, vrf_table
)
354 self
.exec_command(rule_cmd
)
356 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
357 if rule
not in self
.ip6_rule_cache
:
358 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'iif', vrf_dev_name
,
360 self
.exec_command(rule_cmd
)
362 def _add_vrf_slaves(self
, ifaceobj
, ifaceobj_getfunc
=None):
363 running_slaves
= self
.ipcmd
.link_get_lowers(ifaceobj
.name
)
364 config_slaves
= ifaceobj
.lowerifaces
365 if not config_slaves
and not running_slaves
:
368 if not config_slaves
: config_slaves
= []
369 if not running_slaves
: running_slaves
= []
370 add_slaves
= set(config_slaves
).difference(set(running_slaves
))
371 del_slaves
= set(running_slaves
).difference(set(config_slaves
))
377 sobj
= ifaceobj_getfunc(s
)
378 self
._up
_vrf
_slave
(s
, ifaceobj
.name
,
379 sobj
[0] if sobj
else None,
380 ifaceobj_getfunc
, True)
382 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
389 sobj
= ifaceobj_getfunc(s
)
390 # if dhcp slave, release the dhcp lease
391 if sobj
and ifaceobj
.name
== 'mgmt':
392 self
._kill
_ssh
(sobj
[0].name
)
393 self
._down
_vrf
_slave
(s
, sobj
[0] if sobj
else None)
395 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
397 if ifaceobj
.link_type
== ifaceLinkType
.LINK_MASTER
:
398 for s
in config_slaves
:
400 rtnetlink_api
.rtnl_api
.link_set(s
, "up")
402 self
.logger
.debug('%s: %s: link set up (%s)'
403 %(ifaceobj
.name
, s
, str(e
)))
406 def _create_cgroup(self
, ifaceobj
):
407 if not self
.vrf_cgroup_create
:
410 if not os
.path
.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj
.name
):
411 self
.exec_command('/usr/bin/cgcreate -g l3mdev:%s' %ifaceobj
.name
)
413 self
.log_error('%s: cgroup create failed (%s)\n'
414 %(ifaceobj
.name
, str(e
)), ifaceobj
)
416 self
.exec_command('/usr/bin/cgset -r l3mdev.master-device=%s %s'
417 %(ifaceobj
.name
, ifaceobj
.name
))
419 self
.log_warn('%s: cgset failed (%s)\n'
420 %(ifaceobj
.name
, str(e
)), ifaceobj
)
422 def _set_vrf_dev_processed_flag(self
, ifaceobj
):
423 ifaceobj
.module_flags
[self
.name
] = \
424 ifaceobj
.module_flags
.setdefault(self
.name
, 0) | \
425 vrfPrivFlags
.PROCESSED
427 def _check_vrf_dev_processed_flag(self
, ifaceobj
):
428 if (ifaceobj
.module_flags
.get(self
.name
, 0x0) & vrfPrivFlags
.PROCESSED
):
432 def _create_vrf_dev(self
, ifaceobj
, vrf_table
):
433 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
434 if vrf_table
== 'auto':
435 vrf_table
= self
._get
_avail
_vrf
_table
_id
()
437 self
.log_error('%s: unable to get an auto table id'
439 self
.logger
.info('%s: table id auto: selected table id %s\n'
440 %(ifaceobj
.name
, vrf_table
))
442 if not vrf_table
.isdigit():
443 self
.log_error('%s: vrf-table must be an integer or \'auto\''
444 %(ifaceobj
.name
), ifaceobj
)
446 # XXX: If we decide to not allow vrf id usages out of
447 # the reserved ifupdown range, then uncomment this code.
449 if (int(vrf_table
) < self
.vrf_table_id_start
or
450 int(vrf_table
) > self
.vrf_table_id_end
):
451 self
.log_error('%s: vrf table id %s out of reserved range [%d,%d]'
452 %(ifaceobj
.name
, vrf_table
,
453 self
.vrf_table_id_start
,
454 self
.vrf_table_id_end
))
456 self
.ipcmd
.link_create(ifaceobj
.name
, 'vrf',
457 {'table' : '%s' %vrf_table
})
459 self
.log_error('%s: create failed (%s)\n'
460 %(ifaceobj
.name
, str(e
)))
462 if vrf_table
== 'auto':
463 vrf_table
= self
._get
_iproute
2_vrf
_table
(ifaceobj
.name
)
465 self
.log_error('%s: unable to get vrf table id'
468 # if the device exists, check if table id is same
469 vrfdev_attrs
= self
.ipcmd
.link_get_linkinfo_attrs(ifaceobj
.name
)
471 running_table
= vrfdev_attrs
.get('table', None)
472 if vrf_table
!= running_table
:
473 self
.log_error('%s: cannot change vrf table id,running table id %s is different from config id %s' %(ifaceobj
.name
,
474 running_table
, vrf_table
))
475 if vrf_table
!= 'auto':
476 self
._iproute
2_vrf
_table
_entry
_add
(ifaceobj
.name
, vrf_table
)
480 def _add_vrf_default_route(self
, ifaceobj
, vrf_table
):
481 vrf_default_route
= ifaceobj
.get_attr_value_first('vrf-default-route')
482 if not vrf_default_route
:
483 vrf_default_route
= policymanager
.policymanager_api
.get_attr_default(
484 module_name
=self
.__class
__.__name
__,
485 attr
='vrf-default-route')
486 if not vrf_default_route
:
488 if str(vrf_default_route
).lower() == "yes":
490 self
.exec_command('ip route add table %s unreachable default'
491 ' metric %d' %(vrf_table
, 240))
498 self
.exec_command('ip -6 route add table %s unreachable '
499 'default metric %d' %(vrf_table
, 240))
505 def _up_vrf_dev(self
, ifaceobj
, vrf_table
, add_slaves
=True,
506 ifaceobj_getfunc
=None):
508 # if vrf dev is already processed return. This can happen
509 # if we had a dhcp slave. See self._handle_dhcp_slaves
510 if self
._check
_vrf
_dev
_processed
_flag
(ifaceobj
):
513 vrf_table
= self
._create
_vrf
_dev
(ifaceobj
, vrf_table
)
515 self
._add
_vrf
_rules
(ifaceobj
.name
, vrf_table
)
516 self
._create
_cgroup
(ifaceobj
)
518 self
._add
_vrf
_slaves
(ifaceobj
, ifaceobj_getfunc
)
519 self
._add
_vrf
_default
_route
(ifaceobj
, vrf_table
)
520 self
._set
_vrf
_dev
_processed
_flag
(ifaceobj
)
522 self
.log_error('%s: %s' %(ifaceobj
.name
, str(e
)))
524 def _kill_ssh(self
, ifacename
):
525 # Fix this in the next version
526 # runningaddrsdict = self.ipcmd.addr_get(ifacename)
528 # XXX: Roopa: it is currently killing ifupdown2.
529 # so, until we fix it, lets not do anything
537 #2: eth0 inet 10.0.1.84/22 brd 10.0.3.255 scope global eth0\
538 #valid_lft forever preferred_lft forever
539 for line
in self
.ipcmd
.addr_show(ifacename
=ifacename
).splitlines():
540 citems
= line
.split()
541 if any(word
in citems
for word
in ['inet','inet6']):
543 ip
.append(citems
[citems
.index('inet')+1].split('/')[0])
545 ip6
.append(citems
[citems
.index('inet6')+1].split('/')[0])
547 if not ip
and not ip6
:
551 #ESTAB 0 0 10.0.1.84:ssh 10.0.1.228:45186
552 #users:(("sshd",pid=2528,fd=3))
553 cmdl
= ['ss', '-t', '-p']
554 for line
in subprocess
.check_output(cmdl
, stderr
=subprocess
.STDOUT
,
555 shell
=False).splitlines():
556 citems
= line
.split()
559 addr
= citems
[3].split('%')[0]
560 elif ':ssh' in citems
[3]:
561 addr
= citems
[3].split(':')[0]
564 if (addr
in ip
) or (addr
in ip6
):
566 proc
.append(citems
[5].split(',')[1].split('=')[1])
570 pid
= subprocess
.check_output(['ps', '--no-headers',
571 '-fp', str(os
.getppid())],
572 stderr
=subprocess
.STDOUT
,
573 shell
=False).split()[2]
574 self
.logger
.info("%s: killing active ssh sessions: %s"
575 %(ifacename
, str(proc
)))
579 os
.kill(int(id), signal
.SIGINT
)
585 except OSError, (err_no
, err_message
):
586 self
.logger
.info("os.setsid failed: errno=%d: %s" % (err_no
, err_message
))
587 self
.logger
.info("pid=%d pgid=%d" % (os
.getpid(), os
.getpgid(0)))
589 self
.logger
.info("%s: killing our session: %s"
590 %(ifacename
, str(proc
)))
591 os
.kill(int(pid
), signal
.SIGINT
)
596 self
.logger
.info('%s: %s' %(ifacename
, str(e
)))
598 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
600 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
602 # This is a vrf device
603 if self
.vrf_count
== self
.vrf_max_count
:
604 self
.log_error('%s: max vrf count %d hit...not '
605 'creating vrf' %(ifaceobj
.name
,
607 self
._up
_vrf
_dev
(ifaceobj
, vrf_table
, True, ifaceobj_getfunc
)
609 vrf
= ifaceobj
.get_attr_value_first('vrf')
611 # This is a vrf slave
612 self
._up
_vrf
_slave
(ifaceobj
.name
, vrf
, ifaceobj
,
615 # check if we were a slave before
616 master
= self
.ipcmd
.link_get_master(ifaceobj
.name
)
618 if self
._is
_vrf
_dev
(master
):
619 self
._down
_vrf
_slave
(ifaceobj
.name
, ifaceobj
)
621 self
.log_error(str(e
))
623 def _delete_cgroup(self
, ifaceobj
):
625 if os
.path
.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj
.name
):
626 self
.exec_command('/usr/bin/cgdelete -g l3mdev:%s' %ifaceobj
.name
)
628 self
.log_info('%s: cgroup delete failed (%s)\n'
629 %(ifaceobj
.name
, str(e
)), ifaceobj
)
631 def _down_vrf_dev(self
, ifaceobj
, vrf_table
, ifaceobj_getfunc
=None):
633 if vrf_table
== 'auto':
634 vrf_table
= self
._get
_iproute
2_vrf
_table
(ifaceobj
.name
)
637 self
.exec_command('/usr/cumulus/bin/cl-vrf service disable %s' %ifaceobj
.name
)
639 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
643 running_slaves
= self
.ipcmd
.link_get_lowers(ifaceobj
.name
)
645 for s
in running_slaves
:
647 sobj
= ifaceobj_getfunc(s
)
648 if sobj
and self
.ipcmd
.link_get_master(sobj
[0].name
) == 'mgmt':
649 self
._kill
_ssh
(sobj
[0].name
)
650 # if dhcp slave, release the dhcp lease
651 if sobj
and self
._is
_dhcp
_slave
(sobj
[0]):
652 self
._down
_dhcp
_slave
(sobj
[0])
654 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
658 self
._del
_vrf
_rules
(ifaceobj
.name
, vrf_table
)
660 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
664 self
.ipcmd
.link_delete(ifaceobj
.name
)
666 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
670 self
._iproute
2_vrf
_table
_entry
_del
(vrf_table
)
671 self
._delete
_cgroup
(ifaceobj
)
673 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
677 def _down_vrf_slave(self
, ifacename
, ifaceobj
=None):
679 if ifaceobj
and self
._is
_dhcp
_slave
(ifaceobj
):
680 self
._down
_dhcp
_slave
(ifaceobj
)
681 self
.ipcmd
.link_set(ifacename
, 'nomaster')
682 rtnetlink_api
.rtnl_api
.link_set(ifacename
, "down")
684 self
.logger
.warn('%s: %s' %(ifacename
, str(e
)))
686 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
688 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
690 self
._down
_vrf
_dev
(ifaceobj
, vrf_table
, ifaceobj_getfunc
)
692 vrf
= ifaceobj
.get_attr_value_first('vrf')
694 self
._down
_vrf
_slave
(ifaceobj
.name
, ifaceobj
)
696 self
.log_warn(str(e
))
698 def _query_check_vrf_slave(self
, ifaceobj
, ifaceobjcurr
, vrf
):
700 master
= self
.ipcmd
.link_get_master(ifaceobj
.name
)
701 if not master
or master
!= vrf
:
702 ifaceobjcurr
.update_config_with_status('vrf', str(master
), 1)
704 ifaceobjcurr
.update_config_with_status('vrf', master
, 0)
706 self
.log_warn(str(e
))
708 def _query_check_vrf_dev(self
, ifaceobj
, ifaceobjcurr
, vrf_table
):
710 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
711 self
.logger
.info('%s: vrf: does not exist' %(ifaceobj
.name
))
713 if vrf_table
== 'auto':
714 config_table
= self
._get
_iproute
2_vrf
_table
(ifaceobj
.name
)
716 config_table
= vrf_table
717 vrfdev_attrs
= self
.ipcmd
.link_get_linkinfo_attrs(ifaceobj
.name
)
719 ifaceobjcurr
.update_config_with_status('vrf-table', 'None', 1)
721 running_table
= vrfdev_attrs
.get('table')
722 if not running_table
:
723 ifaceobjcurr
.update_config_with_status('vrf-table', 'None', 1)
725 if config_table
!= running_table
:
726 ifaceobjcurr
.update_config_with_status('vrf-table',
729 ifaceobjcurr
.update_config_with_status('vrf-table',
732 self
.log_warn(str(e
))
734 def _query_check(self
, ifaceobj
, ifaceobjcurr
):
736 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
738 self
._query
_check
_vrf
_dev
(ifaceobj
, ifaceobjcurr
, vrf_table
)
740 vrf
= ifaceobj
.get_attr_value_first('vrf')
742 self
._query
_check
_vrf
_slave
(ifaceobj
, ifaceobjcurr
, vrf
)
744 self
.log_warn(str(e
))
746 def _query_running(self
, ifaceobjrunning
, ifaceobj_getfunc
=None):
748 kind
= self
.ipcmd
.link_get_kind(ifaceobjrunning
.name
)
750 vrfdev_attrs
= self
.ipcmd
.link_get_linkinfo_attrs(ifaceobjrunning
.name
)
752 running_table
= vrfdev_attrs
.get('table')
754 ifaceobjrunning
.update_config('vrf-table',
756 elif kind
== 'vrf_slave':
757 vrf
= self
.ipcmd
.link_get_master(ifaceobjrunning
.name
)
759 ifaceobjrunning
.update_config('vrf', vrf
)
761 self
.log_warn(str(e
))
763 _run_ops
= {'pre-up' : _up
,
765 'query-running' : _query_running
,
766 'query-checkcurr' : _query_check
}
769 """ returns list of ops supported by this module """
770 return self
._run
_ops
.keys()
772 def _init_command_handlers(self
):
773 flags
= self
.get_flags()
775 self
.ipcmd
= iproute2(**flags
)
777 self
.bondcmd
= bondutil(**flags
)
778 if not self
.dhclientcmd
:
779 self
.dhclientcmd
= dhclient(**flags
)
781 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None,
782 ifaceobj_getfunc
=None, **extra_args
):
783 """ run bond configuration on the interface object passed as argument
786 **ifaceobj** (object): iface object
788 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
792 **query_ifaceobj** (object): query check ifaceobject. This is only
793 valid when op is 'query-checkcurr'. It is an object same as
794 ifaceobj, but contains running attribute values and its config
795 status. The modules can use it to return queried running state
796 of interfaces. status is success if the running state is same
797 as user required state in ifaceobj. error otherwise.
799 op_handler
= self
._run
_ops
.get(operation
)
802 self
._init
_command
_handlers
()
803 if operation
== 'query-checkcurr':
804 op_handler(self
, ifaceobj
, query_ifaceobj
)
806 op_handler(self
, ifaceobj
, ifaceobj_getfunc
=ifaceobj_getfunc
)