]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Arista L3 Ops is success if it is successful on one peer
authorSukhdev <sukhdev@aristanetworks.com>
Wed, 24 Sep 2014 22:57:15 +0000 (15:57 -0700)
committerAkihiro Motoki <motoki@da.jp.nec.com>
Mon, 13 Oct 2014 23:11:01 +0000 (08:11 +0900)
This fix checks to see if Arista HW is
configured in MLAG (redundant) mode. If yes,
as long as operation is successful on one of the
paired switches, consider it successful.

Closes-bug: 1373652

Change-Id: If929d3fcc109b81f4cf071380a1645d403feb363

neutron/plugins/ml2/drivers/arista/arista_l3_driver.py
neutron/tests/unit/ml2/drivers/arista/test_arista_l3_driver.py

index aac24410f02e5a48390b090e9bad0b81cc24c689..df453f2b1a9070fa7971d5acdea9759e7c2bdfdd 100644 (file)
@@ -247,16 +247,38 @@ class AristaL3Driver(object):
 
             rdm = str(int(hashlib.sha256(router_name).hexdigest(),
                     16) % 6553)
+            mlag_peer_failed = False
             for s in self._servers:
-                self.create_router_on_eos(router_name, rdm, s)
+                try:
+                    self.create_router_on_eos(router_name, rdm, s)
+                    mlag_peer_failed = False
+                except Exception:
+                    if self.mlag_configured and not mlag_peer_failed:
+                        mlag_peer_failed = True
+                    else:
+                        msg = (_('Failed to create router %s on EOS') %
+                               router_name)
+                        LOG.exception(msg)
+                        raise arista_exc.AristaServicePluginRpcError(msg=msg)
 
     def delete_router(self, context, tenant_id, router_id, router):
         """Deletes a router from Arista Switch."""
 
         if router:
+            router_name = self._arista_router_name(tenant_id, router['name'])
+            mlag_peer_failed = False
             for s in self._servers:
-                self.delete_router_from_eos(self._arista_router_name(
-                                               tenant_id, router['name']), s)
+                try:
+                    self.delete_router_from_eos(router_name, s)
+                    mlag_peer_failed = False
+                except Exception:
+                    if self.mlag_configured and not mlag_peer_failed:
+                        mlag_peer_failed = True
+                    else:
+                        msg = (_('Failed to create router %s on EOS') %
+                               router_name)
+                        LOG.exception(msg)
+                        raise arista_exc.AristaServicePluginRpcError(msg=msg)
 
     def update_router(self, context, router_id, original_router, new_router):
         """Updates a router which is already created on Arista Switch.
@@ -279,15 +301,27 @@ class AristaL3Driver(object):
             if self.mlag_configured:
                 # For MLAG, we send a specific IP address as opposed to cidr
                 # For now, we are using x.x.x.253 and x.x.x.254 as virtual IP
+                mlag_peer_failed = False
                 for i, server in enumerate(self._servers):
                     #get appropriate virtual IP address for this router
                     router_ip = self._get_router_ip(cidr, i,
                                                     router_info['ip_version'])
-                    self.add_interface_to_router(router_info['seg_id'],
-                                                 router_name,
-                                                 router_info['gip'],
-                                                 router_ip, subnet_mask,
-                                                 server)
+                    try:
+                        self.add_interface_to_router(router_info['seg_id'],
+                                                     router_name,
+                                                     router_info['gip'],
+                                                     router_ip, subnet_mask,
+                                                     server)
+                        mlag_peer_failed = False
+                    except Exception:
+                        if not mlag_peer_failed:
+                            mlag_peer_failed = True
+                        else:
+                            msg = (_('Failed to add interface to router '
+                                     '%s on EOS') % router_name)
+                            LOG.exception(msg)
+                            raise arista_exc.AristaServicePluginRpcError(
+                                msg=msg)
 
             else:
                 for s in self._servers:
@@ -304,9 +338,21 @@ class AristaL3Driver(object):
         if router_info:
             router_name = self._arista_router_name(router_info['tenant_id'],
                                                    router_info['name'])
+            mlag_peer_failed = False
             for s in self._servers:
-                self.delete_interface_from_router(router_info['seg_id'],
-                                                  router_name, s)
+                try:
+                    self.delete_interface_from_router(router_info['seg_id'],
+                                                      router_name, s)
+                    if self.mlag_configured:
+                        mlag_peer_failed = False
+                except Exception:
+                    if self.mlag_configured and not mlag_peer_failed:
+                        mlag_peer_failed = True
+                    else:
+                        msg = (_('Failed to add interface to router '
+                                 '%s on EOS') % router_name)
+                        LOG.exception(msg)
+                        raise arista_exc.AristaServicePluginRpcError(msg=msg)
 
     def _run_openstack_l3_cmds(self, commands, server):
         """Execute/sends a CAPI (Command API) command to EOS.
index b2a2989b644c511e0073986378ce402a8596d8d1..4cc4db1e28f2407df992498a92120d4fbc1ad4a4 100644 (file)
@@ -391,3 +391,66 @@ class AristaL3DriverTestCases_MLAG_v6(base.BaseTestCase):
                       'ip_version': 6}
 
             self.assertFalse(self.drv.remove_router_interface(None, router))
+
+
+class AristaL3DriverTestCasesMlag_one_switch_failed(base.BaseTestCase):
+    """Test cases to test with non redundant hardare in redundancy mode.
+
+    In the following test cases, the driver is configured in MLAG (redundancy
+    mode) but, one of the switches is mocked to throw exceptoin to mimic
+    failure of the switch. Ensure that the the operation does not fail when
+    one of the switches fails.
+    """
+
+    def setUp(self):
+        super(AristaL3DriverTestCasesMlag_one_switch_failed, self).setUp()
+        setup_arista_config('value', mlag=True)
+        self.drv = arista.AristaL3Driver()
+        self.drv._servers = []
+        self.drv._servers.append(mock.MagicMock())
+        self.drv._servers.append(mock.MagicMock())
+
+    def test_create_router_when_one_switch_fails(self):
+        router = {}
+        router['name'] = 'test-router-1'
+        tenant = '123'
+
+        # Make one of the switches throw an exception - i.e. fail
+        self.drv._servers[0].runCmds = mock.Mock(side_effect = Exception())
+        self.drv.create_router(None, tenant, router)
+
+    def test_delete_router_when_one_switch_fails(self):
+        router = {}
+        router['name'] = 'test-router-1'
+        tenant = '123'
+        router_id = '345'
+
+        # Make one of the switches throw an exception - i.e. fail
+        self.drv._servers[1].runCmds = mock.Mock(side_effect = Exception())
+        self.drv.delete_router(None, tenant, router_id, router)
+
+    def test_add_router_interface_when_one_switch_fails(self):
+        router = {}
+        router['name'] = 'test-router-1'
+        router['tenant_id'] = 'ten-1'
+        router['seg_id'] = '100'
+        router['ip_version'] = 4
+        router['cidr'] = '10.10.10.0/24'
+        router['gip'] = '10.10.10.1'
+
+        # Make one of the switches throw an exception - i.e. fail
+        self.drv._servers[1].runCmds = mock.Mock(side_effect = Exception())
+        self.drv.add_router_interface(None, router)
+
+    def test_remove_router_interface_when_one_switch_fails(self):
+        router = {}
+        router['name'] = 'test-router-1'
+        router['tenant_id'] = 'ten-1'
+        router['seg_id'] = '100'
+        router['ip_version'] = 4
+        router['cidr'] = '10.10.10.0/24'
+        router['gip'] = '10.10.10.1'
+
+        # Make one of the switches throw an exception - i.e. fail
+        self.drv._servers[0].runCmds = mock.Mock(side_effect = Exception())
+        self.drv.remove_router_interface(None, router)