mirror of
https://github.com/CumulusNetworks/ifupdown2.git
synced 2024-05-06 15:54:50 +00:00
addons: vrf: more fixes and cleanups for mgmt and data vrf handling
Ticket: CM-10188, CM-9881 Reviewed By: nikhil, julien, dsa, daniel Testing Done: Tested mgmt vrf bringup, teardown, static routes at boot etc This patch fixes a few things: - kill existing ssh clients on enslavement change for mgmt vrf (original patch by NikhilG) - bring vrf master up first during vrf slave enslavement if master does not exist. This was originally done only for vrf dhcp slaves. With this patch we do it for all vrf slaves. needed for static routes on vrf slaves (CM-10188). - cleanup: reorganize code and a few cleanups and corner case handling Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com> Signed-off-by: Nikhil Gajendrakumar <nikhil@cumulusnetworks.com>
This commit is contained in:
112
addons/vrf.py
112
addons/vrf.py
@@ -142,6 +142,8 @@ class vrf(moduleBase):
|
||||
else:
|
||||
self.vrf_cgroup_create = False
|
||||
|
||||
self.vrf_mgmt_devname = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-mgmt-devname')
|
||||
|
||||
def iproute2_vrf_map_write(self):
|
||||
if not self.iproute2_write_vrf_map:
|
||||
return
|
||||
@@ -222,13 +224,12 @@ class vrf(moduleBase):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _handle_dhcp_slaves(self, ifacename, vrfname, ifaceobj,
|
||||
ifaceobj_getfunc):
|
||||
def _up_vrf_slave_without_master(self, ifacename, vrfname, ifaceobj,
|
||||
ifaceobj_getfunc):
|
||||
""" If we have a vrf slave that has dhcp configured, bring up the
|
||||
vrf master now. This is needed because vrf has special handling
|
||||
in dhclient hook which requires the vrf master to be present """
|
||||
if not self._is_dhcp_slave(ifaceobj):
|
||||
return False
|
||||
|
||||
vrf_master = ifaceobj.upperifaces[0]
|
||||
if not vrf_master:
|
||||
self.logger.warn('%s: vrf master not found' %ifacename)
|
||||
@@ -255,9 +256,7 @@ class vrf(moduleBase):
|
||||
%(mobj.name, vrf_table))
|
||||
self._up_vrf_dev(mobj, vrf_table, False)
|
||||
break
|
||||
if vrfname == 'mgmt':
|
||||
self._kill_ssh(ifaceobj.name)
|
||||
self._down_dhcp_slave(ifaceobj)
|
||||
self._handle_existing_connections(ifaceobj, vrfname)
|
||||
self.ipcmd.link_set(ifacename, 'master', vrfname)
|
||||
return
|
||||
|
||||
@@ -268,20 +267,27 @@ class vrf(moduleBase):
|
||||
# ignore any dhclient release errors
|
||||
pass
|
||||
|
||||
def _handle_existing_connections(self, ifaceobj, vrfname):
|
||||
if not ifaceobj or self.PERFMODE:
|
||||
return
|
||||
if (self.vrf_mgmt_devname and
|
||||
self.vrf_mgmt_devname == vrfname):
|
||||
self._kill_ssh_connections(ifaceobj.name)
|
||||
if self._is_dhcp_slave(ifaceobj):
|
||||
self._down_dhcp_slave(ifaceobj)
|
||||
|
||||
def _up_vrf_slave(self, ifacename, vrfname, ifaceobj=None,
|
||||
ifaceobj_getfunc=None, vrf_exists=False):
|
||||
try:
|
||||
if vrf_exists or self.ipcmd.link_exists(vrfname):
|
||||
upper = self.ipcmd.link_get_upper(ifacename)
|
||||
if not upper or upper != vrfname:
|
||||
if ifaceobj and vrfname == 'mgmt':
|
||||
self._kill_ssh(ifaceobj.name)
|
||||
if ifaceobj and self._is_dhcp_slave(ifaceobj):
|
||||
self._down_dhcp_slave(ifaceobj)
|
||||
self._handle_existing_connections(ifaceobj, vrfname)
|
||||
self.ipcmd.link_set(ifacename, 'master', vrfname)
|
||||
elif ifaceobj:
|
||||
self._handle_dhcp_slaves(ifacename, vrfname, ifaceobj,
|
||||
ifaceobj_getfunc)
|
||||
self._up_vrf_slave_without_master(ifacename, vrfname, ifaceobj,
|
||||
ifaceobj_getfunc)
|
||||
rtnetlink_api.rtnl_api.link_set(ifacename, "up")
|
||||
except Exception, e:
|
||||
self.log_error('%s: %s' %(ifacename, str(e)))
|
||||
|
||||
@@ -387,10 +393,8 @@ class vrf(moduleBase):
|
||||
sobj = None
|
||||
if ifaceobj_getfunc:
|
||||
sobj = ifaceobj_getfunc(s)
|
||||
# if dhcp slave, release the dhcp lease
|
||||
if sobj and ifaceobj.name == 'mgmt':
|
||||
self._kill_ssh(sobj[0].name)
|
||||
self._down_vrf_slave(s, sobj[0] if sobj else None)
|
||||
self._down_vrf_slave(s, sobj[0] if sobj else None,
|
||||
ifaceobj.name)
|
||||
except Exception, e:
|
||||
self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
|
||||
|
||||
@@ -506,7 +510,8 @@ class vrf(moduleBase):
|
||||
ifaceobj_getfunc=None):
|
||||
|
||||
# if vrf dev is already processed return. This can happen
|
||||
# if we had a dhcp slave. See self._handle_dhcp_slaves
|
||||
# if we the slave was configured before.
|
||||
# see self._up_vrf_slave_without_master
|
||||
if self._check_vrf_dev_processed_flag(ifaceobj):
|
||||
return True
|
||||
|
||||
@@ -518,39 +523,23 @@ class vrf(moduleBase):
|
||||
self._add_vrf_slaves(ifaceobj, ifaceobj_getfunc)
|
||||
self._add_vrf_default_route(ifaceobj, vrf_table)
|
||||
self._set_vrf_dev_processed_flag(ifaceobj)
|
||||
rtnetlink_api.rtnl_api.link_set(ifaceobj.name, "up")
|
||||
except Exception, e:
|
||||
self.log_error('%s: %s' %(ifaceobj.name, str(e)))
|
||||
|
||||
def _kill_ssh(self, ifacename):
|
||||
# Fix this in the next version
|
||||
# runningaddrsdict = self.ipcmd.addr_get(ifacename)
|
||||
|
||||
# XXX: Roopa: it is currently killing ifupdown2.
|
||||
# so, until we fix it, lets not do anything
|
||||
return
|
||||
|
||||
def _kill_ssh_connections(self, ifacename):
|
||||
try:
|
||||
ip=[]
|
||||
ip6=[]
|
||||
proc=[]
|
||||
#Example output:
|
||||
#2: eth0 inet 10.0.1.84/22 brd 10.0.3.255 scope global eth0\
|
||||
#valid_lft forever preferred_lft forever
|
||||
for line in self.ipcmd.addr_show(ifacename=ifacename).splitlines():
|
||||
citems = line.split()
|
||||
if any(word in citems for word in ['inet','inet6']):
|
||||
if 'inet' in citems:
|
||||
ip.append(citems[citems.index('inet')+1].split('/')[0])
|
||||
else:
|
||||
ip6.append(citems[citems.index('inet6')+1].split('/')[0])
|
||||
|
||||
if not ip and not ip6:
|
||||
runningaddrsdict = self.ipcmd.addr_get(ifacename)
|
||||
if not runningaddrsdict:
|
||||
return
|
||||
|
||||
iplist = [i.split('/', 1)[0] for i in runningaddrsdict.keys()]
|
||||
if not iplist:
|
||||
return
|
||||
proc=[]
|
||||
#Example output:
|
||||
#ESTAB 0 0 10.0.1.84:ssh 10.0.1.228:45186
|
||||
#users:(("sshd",pid=2528,fd=3))
|
||||
cmdl = ['ss', '-t', '-p']
|
||||
cmdl = ['/bin/ss', '-t', '-p']
|
||||
for line in subprocess.check_output(cmdl, stderr=subprocess.STDOUT,
|
||||
shell=False).splitlines():
|
||||
citems = line.split()
|
||||
@@ -561,13 +550,13 @@ class vrf(moduleBase):
|
||||
addr = citems[3].split(':')[0]
|
||||
if not addr:
|
||||
continue
|
||||
if (addr in ip) or (addr in ip6):
|
||||
if addr in iplist:
|
||||
if len(citems) == 6:
|
||||
proc.append(citems[5].split(',')[1].split('=')[1])
|
||||
|
||||
if not proc:
|
||||
return
|
||||
pid = subprocess.check_output(['ps', '--no-headers',
|
||||
pid = subprocess.check_output(['/bin/ps', '--no-headers',
|
||||
'-fp', str(os.getppid())],
|
||||
stderr=subprocess.STDOUT,
|
||||
shell=False).split()[2]
|
||||
@@ -579,12 +568,20 @@ class vrf(moduleBase):
|
||||
os.kill(int(id), signal.SIGINT)
|
||||
except OSError as e:
|
||||
continue
|
||||
|
||||
# Kill current SSH client
|
||||
if pid in proc:
|
||||
try:
|
||||
os.setsid()
|
||||
except OSError, (err_no, err_message):
|
||||
self.logger.info("os.setsid failed: errno=%d: %s" % (err_no, err_message))
|
||||
self.logger.info("pid=%d pgid=%d" % (os.getpid(), os.getpgid(0)))
|
||||
forkret = os.fork()
|
||||
except OSError, e:
|
||||
self.logger.info("fork error : %s [%d]" % (e.strerror, e.errno))
|
||||
if (forkret == 0): # The first child.
|
||||
try:
|
||||
os.setsid()
|
||||
self.logger.info("%s: ifreload continuing in the background" %ifacename)
|
||||
except OSError, (err_no, err_message):
|
||||
self.logger.info("os.setsid failed: errno=%d: %s" % (err_no, err_message))
|
||||
self.logger.info("pid=%d pgid=%d" % (os.getpid(), os.getpgid(0)))
|
||||
try:
|
||||
self.logger.info("%s: killing our session: %s"
|
||||
%(ifacename, str(proc)))
|
||||
@@ -616,7 +613,8 @@ class vrf(moduleBase):
|
||||
master = self.ipcmd.link_get_master(ifaceobj.name)
|
||||
if master:
|
||||
if self._is_vrf_dev(master):
|
||||
self._down_vrf_slave(ifaceobj.name, ifaceobj)
|
||||
self._down_vrf_slave(ifaceobj.name, ifaceobj,
|
||||
master)
|
||||
except Exception, e:
|
||||
self.log_error(str(e))
|
||||
|
||||
@@ -645,11 +643,8 @@ class vrf(moduleBase):
|
||||
for s in running_slaves:
|
||||
if ifaceobj_getfunc:
|
||||
sobj = ifaceobj_getfunc(s)
|
||||
if sobj and self.ipcmd.link_get_master(sobj[0].name) == 'mgmt':
|
||||
self._kill_ssh(sobj[0].name)
|
||||
# if dhcp slave, release the dhcp lease
|
||||
if sobj and self._is_dhcp_slave(sobj[0]):
|
||||
self._down_dhcp_slave(sobj[0])
|
||||
self._handle_existing_connections(sobj[0] if sobj else None,
|
||||
ifaceobj.name)
|
||||
except Exception, e:
|
||||
self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
|
||||
pass
|
||||
@@ -674,10 +669,9 @@ class vrf(moduleBase):
|
||||
pass
|
||||
|
||||
|
||||
def _down_vrf_slave(self, ifacename, ifaceobj=None):
|
||||
def _down_vrf_slave(self, ifacename, ifaceobj=None, vrfname=None):
|
||||
try:
|
||||
if ifaceobj and self._is_dhcp_slave(ifaceobj):
|
||||
self._down_dhcp_slave(ifaceobj)
|
||||
self._handle_existing_connections(ifaceobj, vrfname)
|
||||
self.ipcmd.link_set(ifacename, 'nomaster')
|
||||
rtnetlink_api.rtnl_api.link_set(ifacename, "down")
|
||||
except Exception, e:
|
||||
@@ -691,7 +685,7 @@ class vrf(moduleBase):
|
||||
else:
|
||||
vrf = ifaceobj.get_attr_value_first('vrf')
|
||||
if vrf:
|
||||
self._down_vrf_slave(ifaceobj.name, ifaceobj)
|
||||
self._down_vrf_slave(ifaceobj.name, ifaceobj, None)
|
||||
except Exception, e:
|
||||
self.log_warn(str(e))
|
||||
|
||||
|
Reference in New Issue
Block a user