Browse Source

Update L3 plugin to handle new syntax for deprecated vrf forwarding

Change-Id: I30e77ea2f8b4fa29ce309cb075e6ed780af6d7bc
tags/2018.2.6
Alin Iorga 5 months ago
parent
commit
772ddda115
2 changed files with 112 additions and 38 deletions
  1. +34
    -24
      networking_arista/l3Plugin/arista_l3_driver.py
  2. +78
    -14
      networking_arista/tests/unit/l3Plugin/test_arista_l3_driver.py

+ 34
- 24
networking_arista/l3Plugin/arista_l3_driver.py View File

@@ -36,18 +36,11 @@ IPV6_BITS = 128

# This string-format-at-a-distance confuses pylint :(
# pylint: disable=too-many-format-args
vrf_router_v1 = {'create': ['vrf definition {0}',
'rd {1}',
'exit'],
'delete': ['no vrf definition {0}']}
vrf_router_v2 = {'create': ['vrf instance {0}',
'rd {1}',
'exit'],
'delete': ['no vrf instance {0}']}

router_in_vrf = {
'router': {}, # update on init

router_in_vrf_v1 = {
'router': {'create': ['vrf definition {0}',
'rd {1}',
'exit'],
'delete': ['no vrf definition {0}']},
'interface': {'add': ['ip routing vrf {1}',
'vlan {0}',
'exit',
@@ -56,6 +49,19 @@ router_in_vrf = {
'ip address {2}'],
'remove': ['no interface vlan {0}']}}

router_in_vrf_v2 = {
'router': {'create': ['vrf instance {0}',
'rd {1}',
'exit'],
'delete': ['no vrf instance {0}']},
'interface': {'add': ['ip routing vrf {1}',
'vlan {0}',
'exit',
'interface vlan {0}',
'vrf {1}',
'ip address {2}'],
'remove': ['no interface vlan {0}']}}

router_in_default_vrf = {
'router': {'create': [], # Place holder for now.
'delete': []}, # Place holder for now.
@@ -110,7 +116,8 @@ class AristaL3Driver(object):
self._hosts.append(host)
self._servers.append(self._make_eapi_client(host))
self._mlag_configured = cfg.CONF.l3_arista.mlag_config
self._vrf_instance_supported = None
self._vrf_syntax_v2_supported = None
self._router_in_vrf = router_in_vrf_v2
self._use_vrf = cfg.CONF.l3_arista.use_vrf
if self._mlag_configured:
host = cfg.CONF.l3_arista.secondary_l3_host
@@ -120,9 +127,9 @@ class AristaL3Driver(object):
self._additionalInterfaceCmdsDict = (
additional_cmds_for_mlag['interface'])
if self._use_vrf:
self.routerDict = vrf_router_v2
self.routerDict = self._router_in_vrf['router']
self._update_vrf_commands(keep_alive=False)
self._interfaceDict = router_in_vrf['interface']
self._interfaceDict = self._router_in_vrf['interface']
else:
self.routerDict = router_in_default_vrf['router']
self._interfaceDict = router_in_default_vrf['interface']
@@ -171,7 +178,7 @@ class AristaL3Driver(object):
timeout=cfg.CONF.l3_arista.conn_timeout
)

def _check_vrf_instance_support(self, host, keep_alive=True):
def _check_vrf_syntax_v2_support(self, host, keep_alive=True):
cmds = ['vrf instance _tmp_openstack_vrf',
'no vrf instance _tmp_openstack_vrf']
try:
@@ -192,19 +199,22 @@ class AristaL3Driver(object):
def _update_vrf_commands(self, keep_alive=True):
# This assumes all switches run the same version. This needs to be
# updated if we'll support distributed routing
new_vrf_support = self._check_vrf_instance_support(
new_vrf_support = self._check_vrf_syntax_v2_support(
self._servers[0], keep_alive=keep_alive)

if new_vrf_support == self._vrf_instance_supported:
if new_vrf_support == self._vrf_syntax_v2_supported:
return

LOG.info(_LI('Updating VRF command supported: %s'),
'vrf instance' if new_vrf_support else 'vrf definition')
self._vrf_instance_supported = new_vrf_support
if self._vrf_instance_supported:
self.routerDict = vrf_router_v2
self._vrf_syntax_v2_supported = new_vrf_support
if self._vrf_syntax_v2_supported is False:
self._router_in_vrf = router_in_vrf_v1
else:
self.routerDict = vrf_router_v1
self._router_in_vrf = router_in_vrf_v2
# we don't need to update self.interfaceDict as it is updated by
# _select_dicts function before it is used
self.routerDict = self._router_in_vrf['router']

def _validate_config(self):
if cfg.CONF.l3_arista.get('primary_l3_host') == '':
@@ -262,10 +272,10 @@ class AristaL3Driver(object):
msg = (_('IPv6 subnets are not supported with VRFs'))
LOG.exception(msg)
raise arista_exc.AristaServicePluginRpcError(msg=msg)
self._interfaceDict = router_in_vrf['interface']
self._interfaceDict = self._router_in_vrf['interface']
else:
if ipv == 6:
# for IPv6 use IPv6 commmands
# for IPv6 use IPv6 commands
self._interfaceDict = router_in_default_vrf_v6['interface']
self._additionalInterfaceCmdsDict = (
additional_cmds_for_mlag_v6['interface'])


+ 78
- 14
networking_arista/tests/unit/l3Plugin/test_arista_l3_driver.py View File

@@ -130,10 +130,10 @@ class AristaL3DriverTestCasesUsingVRFs(base.BaseTestCase):
routers = ['testRouterV2-%s' % n for n in range(max_vrfs)]
domains = ['20%s' % n for n in range(max_vrfs)]

with mock.patch.object(self.drv, '_check_vrf_instance_support') as chk:
chk.return_value = True
with mock.patch.object(self.drv, '_check_vrf_syntax_v2_support') as c:
c.return_value = True
self.drv._update_vrf_commands()
chk.assert_called_once_with(self.drv._servers[0], keep_alive=True)
c.assert_called_once_with(self.drv._servers[0], keep_alive=True)

for (r, d) in zip(routers, domains):
self.drv.create_router_on_eos(r, d, self.drv._servers[0])
@@ -149,10 +149,10 @@ class AristaL3DriverTestCasesUsingVRFs(base.BaseTestCase):
max_vrfs = 5
routers = ['testRouterV1-%s' % n for n in range(max_vrfs)]
domains = ['10%s' % n for n in range(max_vrfs)]
with mock.patch.object(self.drv, '_check_vrf_instance_support') as chk:
chk.return_value = False
with mock.patch.object(self.drv, '_check_vrf_syntax_v2_support') as c:
c.return_value = False
self.drv._update_vrf_commands()
chk.assert_called_once_with(self.drv._servers[0], keep_alive=True)
c.assert_called_once_with(self.drv._servers[0], keep_alive=True)

for (r, d) in zip(routers, domains):
self.drv.create_router_on_eos(r, d, self.drv._servers[0])
@@ -168,10 +168,10 @@ class AristaL3DriverTestCasesUsingVRFs(base.BaseTestCase):
max_vrfs = 5
routers = ['testRouter-%s' % n for n in range(max_vrfs)]

with mock.patch.object(self.drv, '_check_vrf_instance_support') as chk:
chk.return_value = False
with mock.patch.object(self.drv, '_check_vrf_syntax_v2_support') as c:
c.return_value = False
self.drv._update_vrf_commands()
chk.assert_called_once_with(self.drv._servers[0], keep_alive=True)
c.assert_called_once_with(self.drv._servers[0], keep_alive=True)

for r in routers:
self.drv.delete_router_from_eos(r, self.drv._servers[0])
@@ -184,10 +184,10 @@ class AristaL3DriverTestCasesUsingVRFs(base.BaseTestCase):
max_vrfs = 5
routers = ['testRouter-%s' % n for n in range(max_vrfs)]

with mock.patch.object(self.drv, '_check_vrf_instance_support') as chk:
chk.return_value = True
with mock.patch.object(self.drv, '_check_vrf_syntax_v2_support') as c:
c.return_value = True
self.drv._update_vrf_commands()
chk.assert_called_once_with(self.drv._servers[0], keep_alive=True)
c.assert_called_once_with(self.drv._servers[0], keep_alive=True)

for r in routers:
self.drv.delete_router_from_eos(r, self.drv._servers[0])
@@ -196,13 +196,19 @@ class AristaL3DriverTestCasesUsingVRFs(base.BaseTestCase):
self.drv._servers[0].execute.assert_called_with(cmds,
keep_alive=True)

def test_add_interface_to_router_on_eos(self):
def test_add_interface_to_router_on_eos_v1(self):
router_name = 'test-router-1'
segment_id = '123'
router_ip = '10.10.10.10'
gw_ip = '10.10.10.1'
mask = '255.255.255.0'

with mock.patch.object(self.drv, '_check_vrf_syntax_v2_support') as c:
c.return_value = False
self.drv._update_vrf_commands()
self.drv._select_dicts(4)
c.assert_called_once_with(self.drv._servers[0], keep_alive=True)

self.drv.add_interface_to_router(segment_id, router_name, gw_ip,
router_ip, mask, self.drv._servers[0])
cmds = ['enable', 'configure',
@@ -215,6 +221,31 @@ class AristaL3DriverTestCasesUsingVRFs(base.BaseTestCase):
self.drv._servers[0].execute.assert_called_once_with(cmds,
keep_alive=True)

def test_add_interface_to_router_on_eos_v2(self):
router_name = 'test-router-1'
segment_id = '123'
router_ip = '10.10.10.10'
gw_ip = '10.10.10.1'
mask = '255.255.255.0'

with mock.patch.object(self.drv, '_check_vrf_syntax_v2_support') as c:
c.return_value = True
self.drv._update_vrf_commands()
self.drv._select_dicts(4)
c.assert_called_once_with(self.drv._servers[0], keep_alive=True)

self.drv.add_interface_to_router(segment_id, router_name, gw_ip,
router_ip, mask, self.drv._servers[0])
cmds = ['enable', 'configure',
'ip routing vrf %s' % router_name,
'vlan %s' % segment_id, 'exit',
'interface vlan %s' % segment_id,
'vrf %s' % router_name,
'ip address %s/%s' % (gw_ip, mask), 'exit']

self.drv._servers[0].execute.assert_called_once_with(cmds,
keep_alive=True)

def test_delete_interface_from_router_on_eos(self):
router_name = 'test-router-1'
segment_id = '123'
@@ -349,13 +380,19 @@ class AristaL3DriverTestCasesMlagVRFConfig(base.BaseTestCase):

s.execute.assert_called_with(cmds, keep_alive=True)

def test_add_interface_to_router_on_eos(self):
def test_add_interface_to_router_on_eos_v1(self):
router_name = 'test-router-1'
segment_id = '123'
router_ip = '10.10.10.10'
gw_ip = '10.10.10.1'
mask = '255.255.255.0'

with mock.patch.object(self.drv, '_check_vrf_syntax_v2_support') as c:
c.return_value = False
self.drv._update_vrf_commands()
self.drv._select_dicts(4)
c.assert_called_once_with(self.drv._servers[0], keep_alive=True)

for s in self.drv._servers:
self.drv.add_interface_to_router(segment_id, router_name, gw_ip,
router_ip, mask, s)
@@ -370,6 +407,33 @@ class AristaL3DriverTestCasesMlagVRFConfig(base.BaseTestCase):

s.execute.assert_called_once_with(cmds, keep_alive=True)

def test_add_interface_to_router_on_eos_v2(self):
router_name = 'test-router-1'
segment_id = '123'
router_ip = '10.10.10.10'
gw_ip = '10.10.10.1'
mask = '255.255.255.0'

with mock.patch.object(self.drv, '_check_vrf_syntax_v2_support') as c:
c.return_value = True
self.drv._update_vrf_commands()
self.drv._select_dicts(4)
c.assert_called_once_with(self.drv._servers[0], keep_alive=True)

for s in self.drv._servers:
self.drv.add_interface_to_router(segment_id, router_name, gw_ip,
router_ip, mask, s)
cmds = ['enable', 'configure',
'ip routing vrf %s' % router_name,
'vlan %s' % segment_id, 'exit',
'interface vlan %s' % segment_id,
'vrf %s' % router_name,
'ip address %s' % router_ip,
'ip virtual-router address %s' % gw_ip,
'exit']

s.execute.assert_called_once_with(cmds, keep_alive=True)

def test_delete_interface_from_router_on_eos(self):
router_name = 'test-router-1'
segment_id = '123'


Loading…
Cancel
Save