From 717cee318704bd48525eb0ad632e84cd7eda197c Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Tue, 5 Apr 2016 16:11:41 -0700 Subject: [PATCH] addons: dhcp: add vrf awareness Ticket: CM-10292, CM-10282 Reviewed By: dsa, nikhil, julien Testing Done: Tested dhcp config on an vrf slave - Add support for policy module_globals variable "vrf-exec-cmd-prefix". It is read into per module self.vrf_exec_cmd_prefix variable - If self.vrf_exec_cmd_prefix is present and interface is a vrf slave, use ifupdown2 will call such command in vrf context using: "%s %s %s" %(, , ) - This also fixes calling of dhcp refresh when a dhcp slave is removed from a vrf Signed-off-by: Roopa Prabhu --- addons/dhcp.py | 17 +++++++++-- addons/vrf.py | 13 ++++++--- ifupdownaddons/dhclient.py | 56 ++++++++++++++++++++++-------------- ifupdownaddons/modulebase.py | 6 ++++ 4 files changed, 64 insertions(+), 28 deletions(-) diff --git a/addons/dhcp.py b/addons/dhcp.py index d9eee77..bc5faea 100644 --- a/addons/dhcp.py +++ b/addons/dhcp.py @@ -31,9 +31,14 @@ class dhcp(moduleBase): ifaceobj.name) return try: + dhclient_cmd_prefix = None dhcp_wait = policymanager.policymanager_api.get_attr_default( module_name=self.__class__.__name__, attr='dhcp-wait') wait = not str(dhcp_wait).lower() == "no" + vrf = ifaceobj.get_attr_value_first('vrf') + if vrf and self.vrf_exec_cmd_prefix: + dhclient_cmd_prefix = '%s %s' %(self.vrf_exec_cmd_prefix, vrf) + if ifaceobj.addr_family == 'inet': # First release any existing dhclient processes try: @@ -41,7 +46,8 @@ class dhcp(moduleBase): self.dhclientcmd.stop(ifaceobj.name) except: pass - self.dhclientcmd.start(ifaceobj.name, wait=wait) + self.dhclientcmd.start(ifaceobj.name, wait=wait, + cmd_prefix=dhclient_cmd_prefix) elif ifaceobj.addr_family == 'inet6': accept_ra = ifaceobj.get_attr_value_first('accept_ra') if accept_ra: @@ -57,12 +63,17 @@ class dhcp(moduleBase): self.dhclientcmd.stop6(ifaceobj.name) except: pass - self.dhclientcmd.start6(ifaceobj.name, wait=wait) + self.dhclientcmd.start6(ifaceobj.name, wait=wait, + cmd_prefix=dhclient_cmd_prefix) except Exception, e: self.log_error(str(e)) def _down(self, ifaceobj): - self.dhclientcmd.release(ifaceobj.name) + dhclient_cmd_prefix = None + vrf = ifaceobj.get_attr_value_first('vrf') + if vrf and self.vrf_exec_cmd_prefix: + dhclient_cmd_prefix = '%s %s' %(self.vrf_exec_cmd_prefix, vrf) + self.dhclientcmd.release(ifaceobj.name, dhclient_cmd_prefix) self.ipcmd.link_down(ifaceobj.name) def _query_check(self, ifaceobj, ifaceobjcurr): diff --git a/addons/vrf.py b/addons/vrf.py index 3639051..76459bb 100644 --- a/addons/vrf.py +++ b/addons/vrf.py @@ -313,9 +313,13 @@ class vrf(moduleBase): self.ipcmd.link_set(ifacename, 'master', vrfname) return - def _down_dhcp_slave(self, ifaceobj): + def _down_dhcp_slave(self, ifaceobj, vrfname): try: - self.dhclientcmd.release(ifaceobj.name) + dhclient_cmd_prefix = None + if vrfname and self.vrf_exec_cmd_prefix: + dhclient_cmd_prefix = '%s %s' %(self.vrf_exec_cmd_prefix, + vrfname) + self.dhclientcmd.release(ifaceobj.name, dhclient_cmd_prefix) except: # ignore any dhclient release errors pass @@ -327,7 +331,7 @@ class vrf(moduleBase): self.vrf_mgmt_devname == vrfname): self._kill_ssh_connections(ifaceobj.name) if self._is_dhcp_slave(ifaceobj): - self._down_dhcp_slave(ifaceobj) + self._down_dhcp_slave(ifaceobj, vrfname) def _up_vrf_slave(self, ifacename, vrfname, ifaceobj=None, ifaceobj_getfunc=None, vrf_exists=False): @@ -681,6 +685,7 @@ class vrf(moduleBase): # check if we were a slave before master = self.ipcmd.link_get_master(ifaceobj.name) if master: + self._iproute2_vrf_map_initialize() if self._is_vrf_dev(master): self._down_vrf_slave(ifaceobj.name, ifaceobj, master) @@ -701,7 +706,7 @@ class vrf(moduleBase): vrf_table = self._get_iproute2_vrf_table(ifaceobj.name) try: - self.exec_command('/usr/cumulus/bin/cl-vrf service disable %s' %ifaceobj.name) + self.exec_command('/usr/bin/vrf service disable %s' %ifaceobj.name) except Exception, e: self.logger.info('%s: %s' %(ifaceobj.name, str(e))) pass diff --git a/ifupdownaddons/dhclient.py b/ifupdownaddons/dhclient.py index d7e21f4..6056a66 100644 --- a/ifupdownaddons/dhclient.py +++ b/ifupdownaddons/dhclient.py @@ -29,7 +29,18 @@ class dhclient(utilsBase): def is_running6(self, ifacename): return self._pid_exists('/run/dhclient6.%s.pid' %ifacename) - def stop(self, ifacename): + def _run_dhclient_cmd(self, cmd, cmd_prefix=None): + if not cmd_prefix: + cmd_aslist = [] + else: + cmd_aslist = cmd_prefix.split() + if cmd_aslist: + cmd_aslist.extend(cmd) + else: + cmd_aslist = cmd + self.subprocess_check_call(cmd_aslist) + + def stop(self, ifacename, cmd_prefix=None): if os.path.exists('/sbin/dhclient3'): cmd = ['/sbin/dhclient3', '-x', '-pf', '/run/dhclient.%s.pid' %ifacename, '-lf', @@ -40,23 +51,24 @@ class dhclient(utilsBase): '/run/dhclient.%s.pid' %ifacename, '-lf', '/var/lib/dhcp/dhclient.%s.leases' %ifacename, '%s' %ifacename] - self.subprocess_check_call(cmd) + self._run_dhclient_cmd(cmd, cmd_prefix) - def start(self, ifacename, wait=True): + def start(self, ifacename, wait=True, cmd_prefix=None): if os.path.exists('/sbin/dhclient3'): cmd = ['/sbin/dhclient3', '-pf', '/run/dhclient.%s.pid' %ifacename, '-lf', '/var/lib/dhcp3/dhclient.%s.leases' %ifacename, '%s' %ifacename] else: - cmd = ['/sbin/dhclient', '-pf', '/run/dhclient.%s.pid' %ifacename, - '-lf', '/var/lib/dhcp/dhclient.%s.leases' %ifacename, + cmd = ['/sbin/dhclient', '-pf', + '/run/dhclient.%s.pid' %ifacename, '-lf', + '/var/lib/dhcp/dhclient.%s.leases' %ifacename, '%s' %ifacename] if not wait: cmd.append('-nw') - self.subprocess_check_call(cmd) + self._run_dhclient_cmd(cmd, cmd_prefix) - def release(self, ifacename): + def release(self, ifacename, cmd_prefix=None): if os.path.exists('/sbin/dhclient3'): cmd = ['/sbin/dhclient3', '-r', '-pf', '/run/dhclient.%s.pid' %ifacename, '-lf', @@ -67,25 +79,27 @@ class dhclient(utilsBase): '/run/dhclient.%s.pid' %ifacename, '-lf', '/var/lib/dhcp/dhclient.%s.leases' %ifacename, '%s' %ifacename] - self.subprocess_check_call(cmd) + self._run_dhclient_cmd(cmd, cmd_prefix) - def start6(self, ifacename, wait=True): - cmd = ['dhclient', '-6', '-pf', + def start6(self, ifacename, wait=True, cmd_prefix=None): + cmd = ['/sbin/dhclient', '-6', '-pf', '/run/dhclient6.%s.pid' %ifacename, '-lf', '/var/lib/dhcp/dhclient.%s.leases ' %ifacename, '%s' %ifacename] if not wait: cmd.append('-nw') - self.subprocess_check_call(cmd) + self._run_dhclient_cmd(cmd, cmd_prefix) - def stop6(self, ifacename): - self.subprocess_check_call(['dhclient', '-6', '-x', '-pf', - '/run/dhclient.%s.pid' %ifacename, '-lf', - '/var/lib/dhcp/dhclient.%s.leases ' %ifacename, - '%s' %ifacename]) + def stop6(self, ifacename, cmd_prefix=None): + cmd = ['/sbin/dhclient', '-6', '-x', '-pf', + '/run/dhclient.%s.pid' %ifacename, '-lf', + '/var/lib/dhcp/dhclient.%s.leases ' %ifacename, + '%s' %ifacename] + self._run_dhclient_cmd(cmd, cmd_prefix) - def release6(self, ifacename): - self.subprocess_check_call(['dhclient', '-6', '-r', '-pf', - '/run/dhclient6.%s.pid' %ifacename, '-lf', - '/var/lib/dhcp/dhclient6.%s.leases' %ifacename, - '%s' %ifacename]) + def release6(self, ifacename, cmd_prefix=None): + cmd = ['/sbin/dhclient', '-6', '-r', '-pf', + '/run/dhclient6.%s.pid' %ifacename, '-lf', + '/var/lib/dhcp/dhclient6.%s.leases' %ifacename, + '%s' %ifacename] + self._run_dhclient_cmd(cmd, cmd_prefix) diff --git a/ifupdownaddons/modulebase.py b/ifupdownaddons/modulebase.py index 522b4db..2768791 100644 --- a/ifupdownaddons/modulebase.py +++ b/ifupdownaddons/modulebase.py @@ -15,6 +15,7 @@ import shlex from ifupdown.utils import utils from ifupdown.iface import * +import ifupdown.policymanager as policymanager #from ifupdownaddons.iproute2 import * #from ifupdownaddons.dhclient import * #from ifupdownaddons.bridgeutils import * @@ -38,6 +39,11 @@ class moduleBase(object): self.CACHE = kargs.get('cache', False) self.CACHE_FLAGS = kargs.get('cacheflags', 0x0) + # vrfs are a global concept and a vrf context can be applicable + # to all global vrf commands. Get the default vrf-exec-cmd-prefix + # here so that all modules can use it + self.vrf_exec_cmd_prefix = policymanager.policymanager_api.get_module_globals('vrf', attr='vrf-exec-cmd-prefix') + def log_warn(self, str, ifaceobj=None): """ log a warning if err str is not one of which we should ignore """ if not self.ignore_error(str):