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 self
._iproute
2_vrf
_map
_initialized
= False
85 self
.iproute2_vrf_map
= {}
86 self
.iproute2_vrf_map_fd
= None
87 self
.iproute2_vrf_map_sync_to_disk
= False
89 self
.vrf_table_id_start
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='vrf-table-id-start')
90 if not self
.vrf_table_id_start
:
91 self
.vrf_table_id_start
= self
.VRF_TABLE_START
92 self
.vrf_table_id_end
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='vrf-table-id-end')
93 if not self
.vrf_table_id_end
:
94 self
.vrf_table_id_end
= self
.VRF_TABLE_END
95 self
.vrf_max_count
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='vrf-max-count')
97 self
.vrf_fix_local_table
= True
99 self
.vrf_cgroup_create
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='vrf-cgroup-create')
100 if not self
.vrf_cgroup_create
:
101 self
.vrf_cgroup_create
= False
102 elif self
.vrf_cgroup_create
== 'yes':
103 self
.vrf_cgroup_create
= True
105 self
.vrf_cgroup_create
= False
106 self
.vrf_mgmt_devname
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='vrf-mgmt-devname')
108 def _iproute2_vrf_map_initialize(self
):
109 if self
._iproute
2_vrf
_map
_initialized
:
112 # XXX: check for vrf reserved overlap in /etc/iproute2/rt_tables
113 self
.iproute2_vrf_map
= {}
114 iproute2_vrf_map_force_rewrite
= False
115 # read or create /etc/iproute2/rt_tables.d/ifupdown2.vrf_map
116 if os
.path
.exists(self
.iproute2_vrf_filename
):
117 vrf_map_fd
= open(self
.iproute2_vrf_filename
, 'r+')
118 lines
= vrf_map_fd
.readlines()
124 (table
, vrf_name
) = l
.strip().split()
125 if self
.iproute2_vrf_map
.get(int(table
)):
126 # looks like the existing file has
127 # duplicate entries, force rewrite of the
129 iproute2_vrf_map_force_rewrite
= True
131 self
.iproute2_vrf_map
[int(table
)] = vrf_name
133 self
.logger
.info('vrf: iproute2_vrf_map: unable to parse %s'
137 vrfs
= self
.ipcmd
.link_get_vrfs()
140 for v
, lattrs
in vrfs
.iteritems():
141 table
= lattrs
.get('table', None)
143 running_vrf_map
[int(table
)] = v
145 if running_vrf_map
and (running_vrf_map
!= self
.iproute2_vrf_map
):
146 self
.iproute2_vrf_map
= running_vrf_map
147 iproute2_vrf_map_force_rewrite
= True
149 self
.iproute2_vrf_map_fd
= None
150 if iproute2_vrf_map_force_rewrite
:
151 # reopen the file and rewrite the map
152 self
._iproute
2_vrf
_map
_open
(True, False)
154 self
._iproute
2_vrf
_map
_open
(False, True)
156 self
.iproute2_vrf_map_sync_to_disk
= False
157 atexit
.register(self
._iproute
2_vrf
_map
_sync
_to
_disk
)
159 self
.logger
.info("vrf: dumping iproute2_vrf_map")
160 self
.logger
.info(self
.iproute2_vrf_map
)
162 last_used_vrf_table
= None
163 for t
in range(self
.vrf_table_id_start
,
164 self
.vrf_table_id_end
):
165 if not self
.iproute2_vrf_map
.get(t
):
167 last_used_vrf_table
= t
168 self
.last_used_vrf_table
= last_used_vrf_table
169 self
._iproute
2_vrf
_map
_initialized
= True
171 def _iproute2_vrf_map_sync_to_disk(self
):
172 if not self
.iproute2_vrf_map_sync_to_disk
:
174 self
.logger
.info('vrf: syncing table map to %s'
175 %self
.iproute2_vrf_filename
)
176 with
open(self
.iproute2_vrf_filename
, 'w') as f
:
177 f
.write(self
.iproute2_vrf_filehdr
%(self
.vrf_table_id_start
,
178 self
.vrf_table_id_end
))
179 for t
, v
in self
.iproute2_vrf_map
.iteritems():
180 f
.write('%s %s\n' %(t
, v
))
183 def _iproute2_vrf_map_open(self
, sync_vrfs
=False, append
=False):
184 self
.logger
.info('vrf: syncing table map to %s'
185 %self
.iproute2_vrf_filename
)
186 fmode
= 'a+' if append
else 'w'
188 self
.iproute2_vrf_map_fd
= open(self
.iproute2_vrf_filename
,
191 self
.log_warn('vrf: error opening %s (%s)'
192 %(self
.iproute2_vrf_filename
, str(e
)))
197 self
.iproute2_vrf_map_fd
.write(self
.iproute2_vrf_filehdr
198 %(self
.vrf_table_id_start
,
199 self
.vrf_table_id_end
))
200 for t
, v
in self
.iproute2_vrf_map
.iteritems():
201 self
.iproute2_vrf_map_fd
.write('%s %s\n' %(t
, v
))
202 self
.iproute2_vrf_map_fd
.flush()
204 def _is_vrf(self
, ifaceobj
):
205 if ifaceobj
.get_attr_value_first('vrf-table'):
209 def get_upper_ifacenames(self
, ifaceobj
, ifacenames_all
=None):
210 """ Returns list of interfaces dependent on ifaceobj """
212 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
214 ifaceobj
.link_type
= ifaceLinkType
.LINK_MASTER
215 ifaceobj
.link_kind |
= ifaceLinkKind
.VRF
216 ifaceobj
.role |
= ifaceRole
.MASTER
217 vrf_iface_name
= ifaceobj
.get_attr_value_first('vrf')
218 if not vrf_iface_name
:
220 ifaceobj
.link_type
= ifaceLinkType
.LINK_SLAVE
221 ifaceobj
.link_privflags |
= ifaceLinkPrivFlags
.VRF_SLAVE
223 return [vrf_iface_name
]
225 def get_upper_ifacenames_running(self
, ifaceobj
):
228 def _get_iproute2_vrf_table(self
, vrf_dev_name
):
229 for t
, v
in self
.iproute2_vrf_map
.iteritems():
230 if v
== vrf_dev_name
:
234 def _get_avail_vrf_table_id(self
):
235 if self
.last_used_vrf_table
== None:
236 table_id_start
= self
.vrf_table_id_start
238 table_id_start
= self
.last_used_vrf_table
+ 1
239 for t
in range(table_id_start
,
240 self
.vrf_table_id_end
):
241 if not self
.iproute2_vrf_map
.get(t
):
242 self
.last_used_vrf_table
= t
246 def _iproute2_vrf_table_entry_add(self
, vrf_dev_name
, table_id
):
247 old_vrf_name
= self
.iproute2_vrf_map
.get(int(table_id
))
248 if not old_vrf_name
or (old_vrf_name
!= vrf_dev_name
):
249 self
.iproute2_vrf_map
[int(table_id
)] = vrf_dev_name
250 if self
.iproute2_vrf_map_fd
:
251 self
.iproute2_vrf_map_fd
.write('%s %s\n'
252 %(table_id
, vrf_dev_name
))
253 self
.iproute2_vrf_map_fd
.flush()
255 def _iproute2_vrf_table_entry_del(self
, table_id
):
257 # with any del of vrf map, we need to force sync to disk
258 self
.iproute2_vrf_map_sync_to_disk
= True
259 del self
.iproute2_vrf_map
[int(table_id
)]
261 self
.logger
.info('vrf: iproute2 vrf map del failed for %d (%s)'
265 def _is_vrf_dev(self
, ifacename
):
266 # Look at iproute2 map for now.
267 # If it was a master we knew about,
268 # it is definately there
269 if ifacename
in self
.iproute2_vrf_map
.values():
273 def _is_dhcp_slave(self
, ifaceobj
):
274 if (not ifaceobj
.addr_method
or
275 (ifaceobj
.addr_method
!= 'dhcp' and
276 ifaceobj
.addr_method
!= 'dhcp6')):
280 def _up_vrf_slave_without_master(self
, ifacename
, vrfname
, ifaceobj
,
282 """ If we have a vrf slave that has dhcp configured, bring up the
283 vrf master now. This is needed because vrf has special handling
284 in dhclient hook which requires the vrf master to be present """
286 vrf_master
= ifaceobj
.upperifaces
[0]
288 self
.logger
.warn('%s: vrf master not found' %ifacename
)
290 if os
.path
.exists('/sys/class/net/%s' %vrf_master
):
291 self
.logger
.info('%s: vrf master %s exists returning'
292 %(ifacename
, vrf_master
))
294 vrf_master_objs
= ifaceobj_getfunc(vrf_master
)
295 if not vrf_master_objs
:
296 self
.logger
.warn('%s: vrf master ifaceobj not found' %ifacename
)
298 self
.logger
.info('%s: bringing up vrf master %s'
299 %(ifacename
, vrf_master
))
300 for mobj
in vrf_master_objs
:
301 vrf_table
= mobj
.get_attr_value_first('vrf-table')
303 if vrf_table
== 'auto':
304 vrf_table
= self
._get
_avail
_vrf
_table
_id
()
306 self
.log_error('%s: unable to get an auto table id'
308 self
.logger
.info('%s: table id auto: selected table id %s\n'
309 %(mobj
.name
, vrf_table
))
310 self
._up
_vrf
_dev
(mobj
, vrf_table
, False)
312 self
._handle
_existing
_connections
(ifaceobj
, vrfname
)
313 self
.ipcmd
.link_set(ifacename
, 'master', vrfname
)
316 def _down_dhcp_slave(self
, ifaceobj
):
318 self
.dhclientcmd
.release(ifaceobj
.name
)
320 # ignore any dhclient release errors
323 def _handle_existing_connections(self
, ifaceobj
, vrfname
):
324 if not ifaceobj
or self
.PERFMODE
:
326 if (self
.vrf_mgmt_devname
and
327 self
.vrf_mgmt_devname
== vrfname
):
328 self
._kill
_ssh
_connections
(ifaceobj
.name
)
329 if self
._is
_dhcp
_slave
(ifaceobj
):
330 self
._down
_dhcp
_slave
(ifaceobj
)
332 def _up_vrf_slave(self
, ifacename
, vrfname
, ifaceobj
=None,
333 ifaceobj_getfunc
=None, vrf_exists
=False):
335 if vrf_exists
or self
.ipcmd
.link_exists(vrfname
):
336 upper
= self
.ipcmd
.link_get_upper(ifacename
)
337 if not upper
or upper
!= vrfname
:
338 self
._handle
_existing
_connections
(ifaceobj
, vrfname
)
339 self
.ipcmd
.link_set(ifacename
, 'master', vrfname
)
341 self
._up
_vrf
_slave
_without
_master
(ifacename
, vrfname
, ifaceobj
,
343 rtnetlink_api
.rtnl_api
.link_set(ifacename
, "up")
345 self
.log_error('%s: %s' %(ifacename
, str(e
)))
347 def _del_vrf_rules(self
, vrf_dev_name
, vrf_table
):
349 ip_rule_out_format
= '%s: from all %s %s lookup %s'
350 ip_rule_cmd
= 'ip %s rule del pref %s %s %s table %s'
352 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
353 if rule
in self
.ip_rule_cache
:
354 rule_cmd
= ip_rule_cmd
%('', pref
, 'oif', vrf_dev_name
, vrf_table
)
355 self
.exec_command(rule_cmd
)
357 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
358 if rule
in self
.ip_rule_cache
:
359 rule_cmd
= ip_rule_cmd
%('', pref
, 'iif', vrf_dev_name
, vrf_table
)
360 self
.exec_command(rule_cmd
)
362 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
363 if rule
in self
.ip6_rule_cache
:
364 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'oif', vrf_dev_name
,
366 self
.exec_command(rule_cmd
)
368 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
369 if rule
in self
.ip6_rule_cache
:
370 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'iif', vrf_dev_name
,
372 self
.exec_command(rule_cmd
)
374 def _add_vrf_rules(self
, vrf_dev_name
, vrf_table
):
376 ip_rule_out_format
= '%s: from all %s %s lookup %s'
377 ip_rule_cmd
= 'ip %s rule add pref %s %s %s table %s'
378 if self
.vrf_fix_local_table
:
379 self
.vrf_fix_local_table
= False
380 rule
= '0: from all lookup local'
381 if rule
in self
.ip_rule_cache
:
383 self
.exec_command('ip rule del pref 0')
384 self
.exec_command('ip rule add pref 32765 table local')
386 self
.logger
.info('%s' %str
(e
))
388 if rule
in self
.ip6_rule_cache
:
390 self
.exec_command('ip -6 rule del pref 0')
391 self
.exec_command('ip -6 rule add pref 32765 table local')
393 self
.logger
.info('%s' %str
(e
))
397 #200: from all oif blue lookup blue
398 #200: from all iif blue lookup blue
400 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
401 if rule
not in self
.ip_rule_cache
:
402 rule_cmd
= ip_rule_cmd
%('', pref
, 'oif', vrf_dev_name
, vrf_table
)
403 self
.exec_command(rule_cmd
)
405 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
406 if rule
not in self
.ip_rule_cache
:
407 rule_cmd
= ip_rule_cmd
%('', pref
, 'iif', vrf_dev_name
, vrf_table
)
408 self
.exec_command(rule_cmd
)
410 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
411 if rule
not in self
.ip6_rule_cache
:
412 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'oif', vrf_dev_name
, vrf_table
)
413 self
.exec_command(rule_cmd
)
415 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
416 if rule
not in self
.ip6_rule_cache
:
417 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'iif', vrf_dev_name
,
419 self
.exec_command(rule_cmd
)
421 def _add_vrf_slaves(self
, ifaceobj
, ifaceobj_getfunc
=None):
422 running_slaves
= self
.ipcmd
.link_get_lowers(ifaceobj
.name
)
423 config_slaves
= ifaceobj
.lowerifaces
424 if not config_slaves
and not running_slaves
:
427 if not config_slaves
: config_slaves
= []
428 if not running_slaves
: running_slaves
= []
429 add_slaves
= set(config_slaves
).difference(set(running_slaves
))
430 del_slaves
= set(running_slaves
).difference(set(config_slaves
))
436 sobj
= ifaceobj_getfunc(s
)
437 self
._up
_vrf
_slave
(s
, ifaceobj
.name
,
438 sobj
[0] if sobj
else None,
439 ifaceobj_getfunc
, True)
441 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
448 sobj
= ifaceobj_getfunc(s
)
449 self
._down
_vrf
_slave
(s
, sobj
[0] if sobj
else None,
452 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
454 if ifaceobj
.link_type
== ifaceLinkType
.LINK_MASTER
:
455 for s
in config_slaves
:
457 rtnetlink_api
.rtnl_api
.link_set(s
, "up")
459 self
.logger
.debug('%s: %s: link set up (%s)'
460 %(ifaceobj
.name
, s
, str(e
)))
463 def _create_cgroup(self
, ifaceobj
):
464 if not self
.vrf_cgroup_create
:
467 if not os
.path
.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj
.name
):
468 self
.exec_command('/usr/bin/cgcreate -g l3mdev:%s' %ifaceobj
.name
)
470 self
.log_error('%s: cgroup create failed (%s)\n'
471 %(ifaceobj
.name
, str(e
)), ifaceobj
)
473 self
.exec_command('/usr/bin/cgset -r l3mdev.master-device=%s %s'
474 %(ifaceobj
.name
, ifaceobj
.name
))
476 self
.log_warn('%s: cgset failed (%s)\n'
477 %(ifaceobj
.name
, str(e
)), ifaceobj
)
479 def _set_vrf_dev_processed_flag(self
, ifaceobj
):
480 ifaceobj
.module_flags
[self
.name
] = \
481 ifaceobj
.module_flags
.setdefault(self
.name
, 0) | \
482 vrfPrivFlags
.PROCESSED
484 def _check_vrf_dev_processed_flag(self
, ifaceobj
):
485 if (ifaceobj
.module_flags
.get(self
.name
, 0x0) & vrfPrivFlags
.PROCESSED
):
489 def _create_vrf_dev(self
, ifaceobj
, vrf_table
):
490 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
491 if vrf_table
== 'auto':
492 vrf_table
= self
._get
_avail
_vrf
_table
_id
()
494 self
.log_error('%s: unable to get an auto table id'
496 self
.logger
.info('%s: table id auto: selected table id %s\n'
497 %(ifaceobj
.name
, vrf_table
))
499 if not vrf_table
.isdigit():
500 self
.log_error('%s: vrf-table must be an integer or \'auto\''
501 %(ifaceobj
.name
), ifaceobj
)
503 # XXX: If we decide to not allow vrf id usages out of
504 # the reserved ifupdown range, then uncomment this code.
506 if (int(vrf_table
) < self
.vrf_table_id_start
or
507 int(vrf_table
) > self
.vrf_table_id_end
):
508 self
.log_error('%s: vrf table id %s out of reserved range [%d,%d]'
509 %(ifaceobj
.name
, vrf_table
,
510 self
.vrf_table_id_start
,
511 self
.vrf_table_id_end
))
513 self
.ipcmd
.link_create(ifaceobj
.name
, 'vrf',
514 {'table' : '%s' %vrf_table
})
516 self
.log_error('%s: create failed (%s)\n'
517 %(ifaceobj
.name
, str(e
)))
519 if vrf_table
== 'auto':
520 vrf_table
= self
._get
_iproute
2_vrf
_table
(ifaceobj
.name
)
522 self
.log_error('%s: unable to get vrf table id'
525 # if the device exists, check if table id is same
526 vrfdev_attrs
= self
.ipcmd
.link_get_linkinfo_attrs(ifaceobj
.name
)
528 running_table
= vrfdev_attrs
.get('table', None)
529 if vrf_table
!= running_table
:
530 self
.log_error('%s: cannot change vrf table id,running table id %s is different from config id %s' %(ifaceobj
.name
,
531 running_table
, vrf_table
))
532 if vrf_table
!= 'auto':
533 self
._iproute
2_vrf
_table
_entry
_add
(ifaceobj
.name
, vrf_table
)
537 def _add_del_vrf_default_route(self
, ifaceobj
, vrf_table
, add
=True):
538 vrf_default_route
= ifaceobj
.get_attr_value_first('vrf-default-route')
539 if not vrf_default_route
:
540 vrf_default_route
= policymanager
.policymanager_api
.get_attr_default(
541 module_name
=self
.__class
__.__name
__,
542 attr
='vrf-default-route')
543 if not vrf_default_route
:
545 if str(vrf_default_route
).lower() == "yes":
548 self
.exec_command('ip route add table %s unreachable '
549 'default metric %d' %(vrf_table
, 240))
551 self
.exec_command('ip route del table %s unreachable '
552 'default metric %d' %(vrf_table
, 240))
554 if add
and e
.errno
!= 17:
557 self
.logger
.info('%s: error deleting default route (%s)'
558 %(ifaceobj
.name
, str(e
)))
563 self
.exec_command('ip -6 route add table %s unreachable '
564 'default metric %d' %(vrf_table
, 240))
566 self
.exec_command('ip -6 route del table %s unreachable '
567 'default metric %d' %(vrf_table
, 240))
569 if add
and e
.errno
!= 17:
572 self
.logger
.info('%s: error deleting default route (%s)'
573 %(ifaceobj
.name
, str(e
)))
576 def _up_vrf_dev(self
, ifaceobj
, vrf_table
, add_slaves
=True,
577 ifaceobj_getfunc
=None):
579 # if vrf dev is already processed return. This can happen
580 # if we the slave was configured before.
581 # see self._up_vrf_slave_without_master
582 if self
._check
_vrf
_dev
_processed
_flag
(ifaceobj
):
585 vrf_table
= self
._create
_vrf
_dev
(ifaceobj
, vrf_table
)
587 self
._add
_vrf
_rules
(ifaceobj
.name
, vrf_table
)
588 self
._create
_cgroup
(ifaceobj
)
590 self
._add
_vrf
_slaves
(ifaceobj
, ifaceobj_getfunc
)
591 self
._add
_del
_vrf
_default
_route
(ifaceobj
, vrf_table
)
592 self
._set
_vrf
_dev
_processed
_flag
(ifaceobj
)
593 rtnetlink_api
.rtnl_api
.link_set(ifaceobj
.name
, "up")
595 self
.log_error('%s: %s' %(ifaceobj
.name
, str(e
)))
597 def _kill_ssh_connections(self
, ifacename
):
599 runningaddrsdict
= self
.ipcmd
.addr_get(ifacename
)
600 if not runningaddrsdict
:
602 iplist
= [i
.split('/', 1)[0] for i
in runningaddrsdict
.keys()]
607 #ESTAB 0 0 10.0.1.84:ssh 10.0.1.228:45186
608 #users:(("sshd",pid=2528,fd=3))
609 cmdl
= ['/bin/ss', '-t', '-p']
610 for line
in subprocess
.check_output(cmdl
, stderr
=subprocess
.STDOUT
,
611 shell
=False).splitlines():
612 citems
= line
.split()
615 addr
= citems
[3].split('%')[0]
616 elif ':ssh' in citems
[3]:
617 addr
= citems
[3].split(':')[0]
622 proc
.append(citems
[5].split(',')[1].split('=')[1])
626 pid
= subprocess
.check_output(['/bin/ps', '--no-headers',
627 '-fp', str(os
.getppid())],
628 stderr
=subprocess
.STDOUT
,
629 shell
=False).split()[2]
630 self
.logger
.info("%s: killing active ssh sessions: %s"
631 %(ifacename
, str(proc
)))
635 os
.kill(int(id), signal
.SIGINT
)
639 # Kill current SSH client
644 self
.logger
.info("fork error : %s [%d]" % (e
.strerror
, e
.errno
))
645 if (forkret
== 0): # The first child.
648 self
.logger
.info("%s: ifreload continuing in the background" %ifacename
)
649 except OSError, (err_no
, err_message
):
650 self
.logger
.info("os.setsid failed: errno=%d: %s" % (err_no
, err_message
))
651 self
.logger
.info("pid=%d pgid=%d" % (os
.getpid(), os
.getpgid(0)))
653 self
.logger
.info("%s: killing our session: %s"
654 %(ifacename
, str(proc
)))
655 os
.kill(int(pid
), signal
.SIGINT
)
660 self
.logger
.info('%s: %s' %(ifacename
, str(e
)))
662 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
664 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
666 self
._iproute
2_vrf
_map
_initialize
()
667 # This is a vrf device
668 if self
.vrf_count
== self
.vrf_max_count
:
669 self
.log_error('%s: max vrf count %d hit...not '
670 'creating vrf' %(ifaceobj
.name
,
672 self
._up
_vrf
_dev
(ifaceobj
, vrf_table
, True, ifaceobj_getfunc
)
674 vrf
= ifaceobj
.get_attr_value_first('vrf')
676 self
._iproute
2_vrf
_map
_initialize
()
677 # This is a vrf slave
678 self
._up
_vrf
_slave
(ifaceobj
.name
, vrf
, ifaceobj
,
681 # check if we were a slave before
682 master
= self
.ipcmd
.link_get_master(ifaceobj
.name
)
684 if self
._is
_vrf
_dev
(master
):
685 self
._down
_vrf
_slave
(ifaceobj
.name
, ifaceobj
,
688 self
.log_error(str(e
))
690 def _delete_cgroup(self
, ifaceobj
):
692 if os
.path
.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj
.name
):
693 self
.exec_command('/usr/bin/cgdelete -g l3mdev:%s' %ifaceobj
.name
)
695 self
.log_info('%s: cgroup delete failed (%s)\n'
696 %(ifaceobj
.name
, str(e
)), ifaceobj
)
698 def _down_vrf_dev(self
, ifaceobj
, vrf_table
, ifaceobj_getfunc
=None):
700 if vrf_table
== 'auto':
701 vrf_table
= self
._get
_iproute
2_vrf
_table
(ifaceobj
.name
)
704 self
.exec_command('/usr/cumulus/bin/cl-vrf service disable %s' %ifaceobj
.name
)
706 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
710 running_slaves
= self
.ipcmd
.link_get_lowers(ifaceobj
.name
)
712 for s
in running_slaves
:
714 sobj
= ifaceobj_getfunc(s
)
715 self
._handle
_existing
_connections
(sobj
[0] if sobj
else None,
718 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
722 self
._del
_vrf
_rules
(ifaceobj
.name
, vrf_table
)
724 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
728 self
.ipcmd
.link_delete(ifaceobj
.name
)
730 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
734 self
._iproute
2_vrf
_table
_entry
_del
(vrf_table
)
735 self
._add
_del
_vrf
_default
_route
(ifaceobj
, vrf_table
, False)
736 self
._delete
_cgroup
(ifaceobj
)
738 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
742 def _down_vrf_slave(self
, ifacename
, ifaceobj
=None, vrfname
=None):
744 self
._handle
_existing
_connections
(ifaceobj
, vrfname
)
745 self
.ipcmd
.link_set(ifacename
, 'nomaster')
746 rtnetlink_api
.rtnl_api
.link_set(ifacename
, "down")
748 self
.logger
.warn('%s: %s' %(ifacename
, str(e
)))
750 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
752 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
754 self
._iproute
2_vrf
_map
_initialize
()
755 self
._down
_vrf
_dev
(ifaceobj
, vrf_table
, ifaceobj_getfunc
)
757 vrf
= ifaceobj
.get_attr_value_first('vrf')
759 self
._iproute
2_vrf
_map
_initialize
()
760 self
._down
_vrf
_slave
(ifaceobj
.name
, ifaceobj
, None)
762 self
.log_warn(str(e
))
764 def _query_check_vrf_slave(self
, ifaceobj
, ifaceobjcurr
, vrf
):
766 master
= self
.ipcmd
.link_get_master(ifaceobj
.name
)
767 if not master
or master
!= vrf
:
768 ifaceobjcurr
.update_config_with_status('vrf', str(master
), 1)
770 ifaceobjcurr
.update_config_with_status('vrf', master
, 0)
772 self
.log_warn(str(e
))
774 def _query_check_vrf_dev(self
, ifaceobj
, ifaceobjcurr
, vrf_table
):
776 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
777 self
.logger
.info('%s: vrf: does not exist' %(ifaceobj
.name
))
779 if vrf_table
== 'auto':
780 config_table
= self
._get
_iproute
2_vrf
_table
(ifaceobj
.name
)
782 config_table
= vrf_table
783 vrfdev_attrs
= self
.ipcmd
.link_get_linkinfo_attrs(ifaceobj
.name
)
785 ifaceobjcurr
.update_config_with_status('vrf-table', 'None', 1)
787 running_table
= vrfdev_attrs
.get('table')
788 if not running_table
:
789 ifaceobjcurr
.update_config_with_status('vrf-table', 'None', 1)
791 if config_table
!= running_table
:
792 ifaceobjcurr
.update_config_with_status('vrf-table',
795 ifaceobjcurr
.update_config_with_status('vrf-table',
798 self
.log_warn(str(e
))
800 def _query_check(self
, ifaceobj
, ifaceobjcurr
):
802 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
804 self
._iproute
2_vrf
_map
_initialize
()
805 self
._query
_check
_vrf
_dev
(ifaceobj
, ifaceobjcurr
, vrf_table
)
807 vrf
= ifaceobj
.get_attr_value_first('vrf')
809 self
._iproute
2_vrf
_map
_initialize
()
810 self
._query
_check
_vrf
_slave
(ifaceobj
, ifaceobjcurr
, vrf
)
812 self
.log_warn(str(e
))
814 def _query_running(self
, ifaceobjrunning
, ifaceobj_getfunc
=None):
816 kind
= self
.ipcmd
.link_get_kind(ifaceobjrunning
.name
)
818 vrfdev_attrs
= self
.ipcmd
.link_get_linkinfo_attrs(ifaceobjrunning
.name
)
820 running_table
= vrfdev_attrs
.get('table')
822 ifaceobjrunning
.update_config('vrf-table',
824 elif kind
== 'vrf_slave':
825 vrf
= self
.ipcmd
.link_get_master(ifaceobjrunning
.name
)
827 ifaceobjrunning
.update_config('vrf', vrf
)
829 self
.log_warn(str(e
))
831 _run_ops
= {'pre-up' : _up
,
833 'query-running' : _query_running
,
834 'query-checkcurr' : _query_check
}
837 """ returns list of ops supported by this module """
838 return self
._run
_ops
.keys()
840 def _init_command_handlers(self
):
841 flags
= self
.get_flags()
843 self
.ipcmd
= iproute2(**flags
)
845 self
.bondcmd
= bondutil(**flags
)
846 if not self
.dhclientcmd
:
847 self
.dhclientcmd
= dhclient(**flags
)
849 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None,
850 ifaceobj_getfunc
=None, **extra_args
):
851 """ run bond configuration on the interface object passed as argument
854 **ifaceobj** (object): iface object
856 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
860 **query_ifaceobj** (object): query check ifaceobject. This is only
861 valid when op is 'query-checkcurr'. It is an object same as
862 ifaceobj, but contains running attribute values and its config
863 status. The modules can use it to return queried running state
864 of interfaces. status is success if the running state is same
865 as user required state in ifaceobj. error otherwise.
867 op_handler
= self
._run
_ops
.get(operation
)
870 self
._init
_command
_handlers
()
871 if operation
== 'query-checkcurr':
872 op_handler(self
, ifaceobj
, query_ifaceobj
)
874 op_handler(self
, ifaceobj
, ifaceobj_getfunc
=ifaceobj_getfunc
)