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 import ifupdown
.ifupdownflags
as ifupdownflags
17 from ifupdownaddons
.modulebase
import moduleBase
18 from ifupdownaddons
.bondutil
import bondutil
19 from ifupdownaddons
.iproute2
import iproute2
20 from ifupdownaddons
.dhclient
import dhclient
25 class vrf(moduleBase
):
26 """ ifupdown2 addon module to configure vrfs """
27 _modinfo
= { 'mhelp' : 'vrf configuration module',
30 {'help' : 'vrf device table id. key to ' +
31 'creating a vrf device',
32 'example': ['vrf-table-id 1']},
34 {'help' : 'vrf the interface is part of.',
35 'example': ['vrf blue']}}}
37 iproute2_vrf_filename
= '/etc/iproute2/rt_tables.d/ifupdown2_vrf_map.conf'
38 iproute2_vrf_filehdr
= '# This file is autogenerated by ifupdown2.\n' + \
39 '# It contains the vrf name to table mapping.\n' + \
40 '# Reserved table range %s %s\n'
41 VRF_TABLE_START
= 1001
44 system_reserved_rt_tables
= {'255' : 'local', '254' : 'main',
45 '253' : 'default', '0' : 'unspec'}
47 def __init__(self
, *args
, **kargs
):
48 ifupdownaddons
.modulebase
.moduleBase
.__init
__(self
, *args
, **kargs
)
51 self
.dhclientcmd
= None
52 self
.name
= self
.__class
__.__name
__
53 if ifupdownflags
.flags
.PERFMODE
:
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_mgmt_devname
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='vrf-mgmt-devname')
100 self
.vrf_helper
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='vrf-helper')
102 def _iproute2_vrf_map_initialize(self
):
103 if self
._iproute
2_vrf
_map
_initialized
:
106 # XXX: check for vrf reserved overlap in /etc/iproute2/rt_tables
107 self
.iproute2_vrf_map
= {}
108 iproute2_vrf_map_force_rewrite
= False
109 # read or create /etc/iproute2/rt_tables.d/ifupdown2.vrf_map
110 if os
.path
.exists(self
.iproute2_vrf_filename
):
111 vrf_map_fd
= open(self
.iproute2_vrf_filename
, 'r+')
112 lines
= vrf_map_fd
.readlines()
118 (table
, vrf_name
) = l
.strip().split()
119 if self
.iproute2_vrf_map
.get(int(table
)):
120 # looks like the existing file has
121 # duplicate entries, force rewrite of the
123 iproute2_vrf_map_force_rewrite
= True
125 self
.iproute2_vrf_map
[int(table
)] = vrf_name
127 self
.logger
.info('vrf: iproute2_vrf_map: unable to parse %s'
131 vrfs
= self
.ipcmd
.link_get_vrfs()
134 for v
, lattrs
in vrfs
.iteritems():
135 table
= lattrs
.get('table', None)
137 running_vrf_map
[int(table
)] = v
139 if (not running_vrf_map
or (running_vrf_map
!= self
.iproute2_vrf_map
)):
140 self
.iproute2_vrf_map
= running_vrf_map
141 iproute2_vrf_map_force_rewrite
= True
143 self
.iproute2_vrf_map_fd
= None
144 if iproute2_vrf_map_force_rewrite
:
145 # reopen the file and rewrite the map
146 self
._iproute
2_vrf
_map
_open
(True, False)
148 self
._iproute
2_vrf
_map
_open
(False, True)
150 self
.iproute2_vrf_map_sync_to_disk
= False
151 atexit
.register(self
._iproute
2_vrf
_map
_sync
_to
_disk
)
153 self
.logger
.info("vrf: dumping iproute2_vrf_map")
154 self
.logger
.info(self
.iproute2_vrf_map
)
156 last_used_vrf_table
= None
157 for t
in range(self
.vrf_table_id_start
,
158 self
.vrf_table_id_end
):
159 if not self
.iproute2_vrf_map
.get(t
):
161 last_used_vrf_table
= t
162 self
.last_used_vrf_table
= last_used_vrf_table
163 self
._iproute
2_vrf
_map
_initialized
= True
164 self
.vrf_count
= len(self
.iproute2_vrf_map
)
166 def _iproute2_vrf_map_sync_to_disk(self
):
167 if not self
.iproute2_vrf_map_sync_to_disk
:
169 self
.logger
.info('vrf: syncing table map to %s'
170 %self
.iproute2_vrf_filename
)
171 with
open(self
.iproute2_vrf_filename
, 'w') as f
:
172 f
.write(self
.iproute2_vrf_filehdr
%(self
.vrf_table_id_start
,
173 self
.vrf_table_id_end
))
174 for t
, v
in self
.iproute2_vrf_map
.iteritems():
175 f
.write('%s %s\n' %(t
, v
))
178 def _iproute2_vrf_map_open(self
, sync_vrfs
=False, append
=False):
179 self
.logger
.info('vrf: syncing table map to %s'
180 %self
.iproute2_vrf_filename
)
181 fmode
= 'a+' if append
else 'w'
183 self
.iproute2_vrf_map_fd
= open(self
.iproute2_vrf_filename
,
186 self
.log_warn('vrf: error opening %s (%s)'
187 %(self
.iproute2_vrf_filename
, str(e
)))
192 self
.iproute2_vrf_map_fd
.write(self
.iproute2_vrf_filehdr
193 %(self
.vrf_table_id_start
,
194 self
.vrf_table_id_end
))
195 for t
, v
in self
.iproute2_vrf_map
.iteritems():
196 self
.iproute2_vrf_map_fd
.write('%s %s\n' %(t
, v
))
197 self
.iproute2_vrf_map_fd
.flush()
199 def _is_vrf(self
, ifaceobj
):
200 if ifaceobj
.get_attr_value_first('vrf-table'):
204 def get_upper_ifacenames(self
, ifaceobj
, ifacenames_all
=None):
205 """ Returns list of interfaces dependent on ifaceobj """
207 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
209 ifaceobj
.link_type
= ifaceLinkType
.LINK_MASTER
210 ifaceobj
.link_kind |
= ifaceLinkKind
.VRF
211 ifaceobj
.role |
= ifaceRole
.MASTER
212 vrf_iface_name
= ifaceobj
.get_attr_value_first('vrf')
213 if not vrf_iface_name
:
215 ifaceobj
.link_type
= ifaceLinkType
.LINK_SLAVE
216 ifaceobj
.link_privflags |
= ifaceLinkPrivFlags
.VRF_SLAVE
218 return [vrf_iface_name
]
220 def get_upper_ifacenames_running(self
, ifaceobj
):
223 def _get_iproute2_vrf_table(self
, vrf_dev_name
):
224 for t
, v
in self
.iproute2_vrf_map
.iteritems():
225 if v
== vrf_dev_name
:
229 def _get_avail_vrf_table_id(self
):
230 if self
.last_used_vrf_table
== None:
231 table_id_start
= self
.vrf_table_id_start
233 table_id_start
= self
.last_used_vrf_table
+ 1
234 for t
in range(table_id_start
,
235 self
.vrf_table_id_end
):
236 if not self
.iproute2_vrf_map
.get(t
):
237 self
.last_used_vrf_table
= t
241 def _iproute2_is_vrf_tableid_inuse(self
, vrf_dev_name
, table_id
):
242 old_vrf_name
= self
.iproute2_vrf_map
.get(int(table_id
))
243 if old_vrf_name
and old_vrf_name
!= vrf_dev_name
:
244 self
.log_error('table id %s already assigned to vrf dev %s'
245 %(table_id
, old_vrf_name
))
247 def _iproute2_vrf_table_entry_add(self
, vrf_dev_name
, table_id
):
248 old_vrf_name
= self
.iproute2_vrf_map
.get(int(table_id
))
250 self
.iproute2_vrf_map
[int(table_id
)] = vrf_dev_name
251 if self
.iproute2_vrf_map_fd
:
252 self
.iproute2_vrf_map_fd
.write('%s %s\n'
253 %(table_id
, vrf_dev_name
))
254 self
.iproute2_vrf_map_fd
.flush()
258 if old_vrf_name
!= vrf_dev_name
:
259 self
.log_error('table id %d already assigned to vrf dev %s'
260 %(table_id
, old_vrf_name
))
262 def _iproute2_vrf_table_entry_del(self
, table_id
):
264 # with any del of vrf map, we need to force sync to disk
265 self
.iproute2_vrf_map_sync_to_disk
= True
266 del self
.iproute2_vrf_map
[int(table_id
)]
268 self
.logger
.info('vrf: iproute2 vrf map del failed for %d (%s)'
272 def _is_vrf_dev(self
, ifacename
):
273 # Look at iproute2 map for now.
274 # If it was a master we knew about,
275 # it is definately there
276 if ifacename
in self
.iproute2_vrf_map
.values():
280 def _is_dhcp_slave(self
, ifaceobj
):
281 if (not ifaceobj
.addr_method
or
282 (ifaceobj
.addr_method
!= 'dhcp' and
283 ifaceobj
.addr_method
!= 'dhcp6')):
287 def _up_vrf_slave_without_master(self
, ifacename
, vrfname
, ifaceobj
,
289 """ If we have a vrf slave that has dhcp configured, bring up the
290 vrf master now. This is needed because vrf has special handling
291 in dhclient hook which requires the vrf master to be present """
293 vrf_master
= ifaceobj
.upperifaces
[0]
295 self
.logger
.warn('%s: vrf master not found' %ifacename
)
297 if os
.path
.exists('/sys/class/net/%s' %vrf_master
):
298 self
.logger
.info('%s: vrf master %s exists returning'
299 %(ifacename
, vrf_master
))
301 vrf_master_objs
= ifaceobj_getfunc(vrf_master
)
302 if not vrf_master_objs
:
303 self
.logger
.warn('%s: vrf master ifaceobj not found' %ifacename
)
305 self
.logger
.info('%s: bringing up vrf master %s'
306 %(ifacename
, vrf_master
))
307 for mobj
in vrf_master_objs
:
308 vrf_table
= mobj
.get_attr_value_first('vrf-table')
310 if vrf_table
== 'auto':
311 vrf_table
= self
._get
_avail
_vrf
_table
_id
()
313 self
.log_error('%s: unable to get an auto table id'
315 self
.logger
.info('%s: table id auto: selected table id %s\n'
316 %(mobj
.name
, vrf_table
))
318 self
._up
_vrf
_dev
(mobj
, vrf_table
, False)
322 self
._handle
_existing
_connections
(ifaceobj
, vrfname
)
323 self
.ipcmd
.link_set(ifacename
, 'master', vrfname
)
326 def _down_dhcp_slave(self
, ifaceobj
, vrfname
):
328 dhclient_cmd_prefix
= None
329 if (vrfname
and self
.vrf_exec_cmd_prefix
and
330 self
.ipcmd
.link_exists(vrfname
)):
331 dhclient_cmd_prefix
= '%s %s' %(self
.vrf_exec_cmd_prefix
,
333 self
.dhclientcmd
.release(ifaceobj
.name
, dhclient_cmd_prefix
)
335 # ignore any dhclient release errors
338 def _handle_existing_connections(self
, ifaceobj
, vrfname
):
339 if not ifaceobj
or ifupdownflags
.flags
.PERFMODE
:
341 if (self
.vrf_mgmt_devname
and
342 self
.vrf_mgmt_devname
== vrfname
):
343 self
._kill
_ssh
_connections
(ifaceobj
.name
)
344 if self
._is
_dhcp
_slave
(ifaceobj
):
345 self
._down
_dhcp
_slave
(ifaceobj
, vrfname
)
347 def _up_vrf_slave(self
, ifacename
, vrfname
, ifaceobj
=None,
348 ifaceobj_getfunc
=None, vrf_exists
=False):
350 if vrf_exists
or self
.ipcmd
.link_exists(vrfname
):
351 upper
= self
.ipcmd
.link_get_upper(ifacename
)
352 if not upper
or upper
!= vrfname
:
353 self
._handle
_existing
_connections
(ifaceobj
, vrfname
)
354 self
.ipcmd
.link_set(ifacename
, 'master', vrfname
)
356 self
._up
_vrf
_slave
_without
_master
(ifacename
, vrfname
, ifaceobj
,
358 rtnetlink_api
.rtnl_api
.link_set(ifacename
, "up")
360 self
.log_error('%s: %s' %(ifacename
, str(e
)))
362 def _del_vrf_rules(self
, vrf_dev_name
, vrf_table
):
364 ip_rule_out_format
= '%s: from all %s %s lookup %s'
365 ip_rule_cmd
= 'ip %s rule del pref %s %s %s table %s'
367 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
368 if rule
in self
.ip_rule_cache
:
369 rule_cmd
= ip_rule_cmd
%('', pref
, 'oif', vrf_dev_name
,
371 self
.exec_command(rule_cmd
)
373 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
374 if rule
in self
.ip_rule_cache
:
375 rule_cmd
= ip_rule_cmd
%('', pref
, 'iif', vrf_dev_name
,
377 self
.exec_command(rule_cmd
)
379 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
380 if rule
in self
.ip6_rule_cache
:
381 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'oif', vrf_dev_name
,
383 self
.exec_command(rule_cmd
)
385 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
386 if rule
in self
.ip6_rule_cache
:
387 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'iif', vrf_dev_name
,
389 self
.exec_command(rule_cmd
)
391 def _add_vrf_rules(self
, vrf_dev_name
, vrf_table
):
393 ip_rule_out_format
= '%s: from all %s %s lookup %s'
394 ip_rule_cmd
= 'ip %s rule add pref %s %s %s table %s'
395 if self
.vrf_fix_local_table
:
396 self
.vrf_fix_local_table
= False
397 rule
= '0: from all lookup local'
398 if rule
in self
.ip_rule_cache
:
400 self
.exec_command('ip rule del pref 0')
401 self
.exec_command('ip rule add pref 32765 table local')
403 self
.logger
.info('%s' %str
(e
))
405 if rule
in self
.ip6_rule_cache
:
407 self
.exec_command('ip -6 rule del pref 0')
408 self
.exec_command('ip -6 rule add pref 32765 table local')
410 self
.logger
.info('%s' %str
(e
))
414 #200: from all oif blue lookup blue
415 #200: from all iif blue lookup blue
417 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
418 if rule
not in self
.ip_rule_cache
:
419 rule_cmd
= ip_rule_cmd
%('', pref
, 'oif', vrf_dev_name
,
421 self
.exec_command(rule_cmd
)
423 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
424 if rule
not in self
.ip_rule_cache
:
425 rule_cmd
= ip_rule_cmd
%('', pref
, 'iif', vrf_dev_name
,
427 self
.exec_command(rule_cmd
)
429 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
430 if rule
not in self
.ip6_rule_cache
:
431 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'oif', vrf_dev_name
,
433 self
.exec_command(rule_cmd
)
435 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
436 if rule
not in self
.ip6_rule_cache
:
437 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'iif', vrf_dev_name
,
439 self
.exec_command(rule_cmd
)
441 def _add_vrf_slaves(self
, ifaceobj
, ifaceobj_getfunc
=None):
442 running_slaves
= self
.ipcmd
.link_get_lowers(ifaceobj
.name
)
443 config_slaves
= ifaceobj
.lowerifaces
444 if not config_slaves
and not running_slaves
:
447 if not config_slaves
: config_slaves
= []
448 if not running_slaves
: running_slaves
= []
449 add_slaves
= set(config_slaves
).difference(set(running_slaves
))
450 del_slaves
= set(running_slaves
).difference(set(config_slaves
))
456 sobj
= ifaceobj_getfunc(s
)
457 self
._up
_vrf
_slave
(s
, ifaceobj
.name
,
458 sobj
[0] if sobj
else None,
459 ifaceobj_getfunc
, True)
461 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
468 sobj
= ifaceobj_getfunc(s
)
469 self
._down
_vrf
_slave
(s
, sobj
[0] if sobj
else None,
472 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
474 if ifaceobj
.link_type
== ifaceLinkType
.LINK_MASTER
:
475 for s
in config_slaves
:
477 rtnetlink_api
.rtnl_api
.link_set(s
, "up")
479 self
.logger
.debug('%s: %s: link set up (%s)'
480 %(ifaceobj
.name
, s
, str(e
)))
483 def _set_vrf_dev_processed_flag(self
, ifaceobj
):
484 ifaceobj
.module_flags
[self
.name
] = \
485 ifaceobj
.module_flags
.setdefault(self
.name
, 0) | \
486 vrfPrivFlags
.PROCESSED
488 def _check_vrf_dev_processed_flag(self
, ifaceobj
):
489 if (ifaceobj
.module_flags
.get(self
.name
, 0) & vrfPrivFlags
.PROCESSED
):
493 def _create_vrf_dev(self
, ifaceobj
, vrf_table
):
494 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
495 if ifaceobj
.name
in self
.system_reserved_rt_tables
.values():
496 self
.log_error('cannot use system reserved %s vrf names'
497 %( str(self
.system_reserved_rt_tables
.values())))
498 if self
.vrf_count
== self
.vrf_max_count
:
499 self
.log_error('%s: max vrf count %d hit...not '
500 'creating vrf' %(ifaceobj
.name
,
502 if vrf_table
== 'auto':
503 vrf_table
= self
._get
_avail
_vrf
_table
_id
()
505 self
.log_error('%s: unable to get an auto table id'
507 self
.logger
.info('%s: table id auto: selected table id %s\n'
508 %(ifaceobj
.name
, vrf_table
))
510 self
._iproute
2_is
_vrf
_tableid
_inuse
(ifaceobj
.name
, vrf_table
)
511 if ifaceobj
.name
in self
.system_reserved_rt_tables
.keys():
512 self
.log_error('cannot use system reserved %s table ids'
513 %(str(self
.system_reserved_rt_tables
.keys())))
515 if not vrf_table
.isdigit():
516 self
.log_error('%s: vrf-table must be an integer or \'auto\''
517 %(ifaceobj
.name
), ifaceobj
)
519 # XXX: If we decide to not allow vrf id usages out of
520 # the reserved ifupdown range, then uncomment this code.
522 if (int(vrf_table
) < self
.vrf_table_id_start
or
523 int(vrf_table
) > self
.vrf_table_id_end
):
524 self
.log_error('%s: vrf table id %s out of reserved range [%d,%d]'
525 %(ifaceobj
.name
, vrf_table
,
526 self
.vrf_table_id_start
,
527 self
.vrf_table_id_end
))
529 self
.ipcmd
.link_create(ifaceobj
.name
, 'vrf',
530 {'table' : '%s' %vrf_table
})
532 self
.log_error('%s: create failed (%s)\n'
533 %(ifaceobj
.name
, str(e
)))
534 if vrf_table
!= 'auto':
535 self
._iproute
2_vrf
_table
_entry
_add
(ifaceobj
.name
, vrf_table
)
537 if vrf_table
== 'auto':
538 vrf_table
= self
._get
_iproute
2_vrf
_table
(ifaceobj
.name
)
540 self
.log_error('%s: unable to get vrf table id'
543 # if the device exists, check if table id is same
544 vrfdev_attrs
= self
.ipcmd
.link_get_linkinfo_attrs(ifaceobj
.name
)
546 running_table
= vrfdev_attrs
.get('table', None)
547 if vrf_table
!= running_table
:
548 self
.log_error('%s: cannot change vrf table id,running table id %s is different from config id %s' %(ifaceobj
.name
,
549 running_table
, vrf_table
))
552 def _up_vrf_helper(self
, ifaceobj
, vrf_table
):
554 if ifupdownflags
.flags
.PERFMODE
:
557 self
.exec_command('%s create %s %s %s' %(self
.vrf_helper
,
558 ifaceobj
.name
, vrf_table
, mode
))
560 def _up_vrf_dev(self
, ifaceobj
, vrf_table
, add_slaves
=True,
561 ifaceobj_getfunc
=None):
563 # if vrf dev is already processed return. This can happen
564 # if we the slave was configured before.
565 # see self._up_vrf_slave_without_master
566 if self
._check
_vrf
_dev
_processed
_flag
(ifaceobj
):
570 vrf_table
= self
._create
_vrf
_dev
(ifaceobj
, vrf_table
)
572 self
.log_error('%s: %s' %(ifaceobj
.name
, str(e
)))
575 self
._add
_vrf
_rules
(ifaceobj
.name
, vrf_table
)
576 self
._up
_vrf
_helper
(ifaceobj
, vrf_table
)
578 self
._add
_vrf
_slaves
(ifaceobj
, ifaceobj_getfunc
)
579 self
._set
_vrf
_dev
_processed
_flag
(ifaceobj
)
580 rtnetlink_api
.rtnl_api
.link_set(ifaceobj
.name
, "up")
582 self
.log_error('%s: %s' %(ifaceobj
.name
, str(e
)))
584 def _kill_ssh_connections(self
, ifacename
):
586 runningaddrsdict
= self
.ipcmd
.addr_get(ifacename
)
587 if not runningaddrsdict
:
589 iplist
= [i
.split('/', 1)[0] for i
in runningaddrsdict
.keys()]
594 #ESTAB 0 0 10.0.1.84:ssh 10.0.1.228:45186
595 #users:(("sshd",pid=2528,fd=3))
596 cmdl
= ['/bin/ss', '-t', '-p']
597 for line
in subprocess
.check_output(cmdl
, stderr
=subprocess
.STDOUT
,
598 shell
=False).splitlines():
599 citems
= line
.split()
602 addr
= citems
[3].split('%')[0]
603 elif ':ssh' in citems
[3]:
604 addr
= citems
[3].split(':')[0]
609 proc
.append(citems
[5].split(',')[1].split('=')[1])
613 pid
= subprocess
.check_output(['/bin/ps', '--no-headers',
614 '-fp', str(os
.getppid())],
615 stderr
=subprocess
.STDOUT
,
616 shell
=False).split()[2]
617 self
.logger
.info("%s: killing active ssh sessions: %s"
618 %(ifacename
, str(proc
)))
622 os
.kill(int(id), signal
.SIGINT
)
626 # Kill current SSH client
631 self
.logger
.info("fork error : %s [%d]" % (e
.strerror
, e
.errno
))
632 if (forkret
== 0): # The first child.
635 self
.logger
.info("%s: ifreload continuing in the background" %ifacename
)
636 except OSError, (err_no
, err_message
):
637 self
.logger
.info("os.setsid failed: errno=%d: %s" % (err_no
, err_message
))
638 self
.logger
.info("pid=%d pgid=%d" % (os
.getpid(), os
.getpgid(0)))
640 self
.logger
.info("%s: killing our session: %s"
641 %(ifacename
, str(proc
)))
642 os
.kill(int(pid
), signal
.SIGINT
)
647 self
.logger
.info('%s: %s' %(ifacename
, str(e
)))
649 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
651 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
653 self
._iproute
2_vrf
_map
_initialize
()
654 # This is a vrf device
655 self
._up
_vrf
_dev
(ifaceobj
, vrf_table
, True, ifaceobj_getfunc
)
657 vrf
= ifaceobj
.get_attr_value_first('vrf')
659 self
._iproute
2_vrf
_map
_initialize
()
660 # This is a vrf slave
661 self
._up
_vrf
_slave
(ifaceobj
.name
, vrf
, ifaceobj
,
664 # check if we were a slave before
665 master
= self
.ipcmd
.link_get_master(ifaceobj
.name
)
667 self
._iproute
2_vrf
_map
_initialize
()
668 if self
._is
_vrf
_dev
(master
):
669 self
._down
_vrf
_slave
(ifaceobj
.name
, ifaceobj
,
672 self
.log_error(str(e
))
674 def _down_vrf_helper(self
, ifaceobj
, vrf_table
):
676 if ifupdownflags
.flags
.PERFMODE
:
679 self
.exec_command('%s delete %s %s %s' %(self
.vrf_helper
,
680 ifaceobj
.name
, vrf_table
, mode
))
682 def _down_vrf_dev(self
, ifaceobj
, vrf_table
, ifaceobj_getfunc
=None):
684 if vrf_table
== 'auto':
685 vrf_table
= self
._get
_iproute
2_vrf
_table
(ifaceobj
.name
)
688 running_slaves
= self
.ipcmd
.link_get_lowers(ifaceobj
.name
)
690 for s
in running_slaves
:
692 sobj
= ifaceobj_getfunc(s
)
693 self
._handle
_existing
_connections
(sobj
[0] if sobj
else None,
696 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
699 self
._down
_vrf
_helper
(ifaceobj
, vrf_table
)
702 self
._del
_vrf
_rules
(ifaceobj
.name
, vrf_table
)
704 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
708 self
.ipcmd
.link_delete(ifaceobj
.name
)
710 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
714 self
._iproute
2_vrf
_table
_entry
_del
(vrf_table
)
716 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
720 def _down_vrf_slave(self
, ifacename
, ifaceobj
=None, vrfname
=None):
722 self
._handle
_existing
_connections
(ifaceobj
, vrfname
)
723 self
.ipcmd
.link_set(ifacename
, 'nomaster')
724 rtnetlink_api
.rtnl_api
.link_set(ifacename
, "down")
726 self
.logger
.warn('%s: %s' %(ifacename
, str(e
)))
728 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
730 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
732 self
._iproute
2_vrf
_map
_initialize
()
733 self
._down
_vrf
_dev
(ifaceobj
, vrf_table
, ifaceobj_getfunc
)
735 vrf
= ifaceobj
.get_attr_value_first('vrf')
737 self
._iproute
2_vrf
_map
_initialize
()
738 self
._down
_vrf
_slave
(ifaceobj
.name
, ifaceobj
, None)
740 self
.log_warn(str(e
))
742 def _query_check_vrf_slave(self
, ifaceobj
, ifaceobjcurr
, vrf
):
744 master
= self
.ipcmd
.link_get_master(ifaceobj
.name
)
745 if not master
or master
!= vrf
:
746 ifaceobjcurr
.update_config_with_status('vrf', str(master
), 1)
748 ifaceobjcurr
.update_config_with_status('vrf', master
, 0)
750 self
.log_warn(str(e
))
752 def _query_check_vrf_dev(self
, ifaceobj
, ifaceobjcurr
, vrf_table
):
754 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
755 self
.logger
.info('%s: vrf: does not exist' %(ifaceobj
.name
))
757 if vrf_table
== 'auto':
758 config_table
= self
._get
_iproute
2_vrf
_table
(ifaceobj
.name
)
760 config_table
= vrf_table
761 vrfdev_attrs
= self
.ipcmd
.link_get_linkinfo_attrs(ifaceobj
.name
)
763 ifaceobjcurr
.update_config_with_status('vrf-table', 'None', 1)
765 running_table
= vrfdev_attrs
.get('table')
766 if not running_table
:
767 ifaceobjcurr
.update_config_with_status('vrf-table', 'None', 1)
769 if config_table
!= running_table
:
770 ifaceobjcurr
.update_config_with_status('vrf-table',
773 ifaceobjcurr
.update_config_with_status('vrf-table',
775 if not ifupdownflags
.flags
.WITHDEFAULTS
:
779 self
.exec_command('%s verify %s %s'
781 ifaceobj
.name
, config_table
))
782 ifaceobjcurr
.update_config_with_status('vrf-helper',
788 ifaceobjcurr
.update_config_with_status('vrf-helper',
795 self
.log_warn(str(e
))
797 def _query_check(self
, ifaceobj
, ifaceobjcurr
):
799 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
801 self
._iproute
2_vrf
_map
_initialize
()
802 self
._query
_check
_vrf
_dev
(ifaceobj
, ifaceobjcurr
, vrf_table
)
804 vrf
= ifaceobj
.get_attr_value_first('vrf')
806 self
._iproute
2_vrf
_map
_initialize
()
807 self
._query
_check
_vrf
_slave
(ifaceobj
, ifaceobjcurr
, vrf
)
809 self
.log_warn(str(e
))
811 def _query_running(self
, ifaceobjrunning
, ifaceobj_getfunc
=None):
813 kind
= self
.ipcmd
.link_get_kind(ifaceobjrunning
.name
)
815 vrfdev_attrs
= self
.ipcmd
.link_get_linkinfo_attrs(ifaceobjrunning
.name
)
817 running_table
= vrfdev_attrs
.get('table')
819 ifaceobjrunning
.update_config('vrf-table',
821 elif kind
== 'vrf_slave':
822 vrf
= self
.ipcmd
.link_get_master(ifaceobjrunning
.name
)
824 ifaceobjrunning
.update_config('vrf', vrf
)
826 self
.log_warn(str(e
))
828 def _query(self
, ifaceobj
, **kwargs
):
829 if not self
.vrf_helper
:
831 if (ifaceobj
.link_kind
& ifaceLinkKind
.VRF
):
832 ifaceobj
.update_config('vrf-helper', '%s %s' %(self
.vrf_helper
,
835 _run_ops
= {'pre-up' : _up
,
837 'query-running' : _query_running
,
838 'query-checkcurr' : _query_check
,
842 """ returns list of ops supported by this module """
843 return self
._run
_ops
.keys()
845 def _init_command_handlers(self
):
847 self
.ipcmd
= iproute2()
849 self
.bondcmd
= bondutil()
850 if not self
.dhclientcmd
:
851 self
.dhclientcmd
= dhclient()
853 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None,
854 ifaceobj_getfunc
=None, **extra_args
):
855 """ run bond configuration on the interface object passed as argument
858 **ifaceobj** (object): iface object
860 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
864 **query_ifaceobj** (object): query check ifaceobject. This is only
865 valid when op is 'query-checkcurr'. It is an object same as
866 ifaceobj, but contains running attribute values and its config
867 status. The modules can use it to return queried running state
868 of interfaces. status is success if the running state is same
869 as user required state in ifaceobj. error otherwise.
871 op_handler
= self
._run
_ops
.get(operation
)
874 self
._init
_command
_handlers
()
875 if operation
== 'query-checkcurr':
876 op_handler(self
, ifaceobj
, query_ifaceobj
)
878 op_handler(self
, ifaceobj
, ifaceobj_getfunc
=ifaceobj_getfunc
)