]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Return exception when attempting to add duplicate VIP
authorSachi King <nakato@nakato.io>
Mon, 8 Dec 2014 06:42:48 +0000 (17:42 +1100)
committerSachi King <nakato@nakato.io>
Fri, 24 Apr 2015 06:34:52 +0000 (16:34 +1000)
Neutron should never attempt to add a VIP to keepalived's config
multiple times, and to do so is an error.  As such this adds an
exception if this is ever attempted.

Change-Id: If1c41c3164e8a998c73f9b7aa566e2ba6570f54b
Closes-Bug: #1400217

neutron/agent/linux/keepalived.py
neutron/tests/unit/agent/linux/test_keepalived.py

index f856def6d46304f11a63d909fda34624c4db91fb..eccd7a42cc0c31fa66bd4317800a19b8f31d5de2 100644 (file)
@@ -77,6 +77,17 @@ class InvalidAuthenticationTypeException(exceptions.NeutronException):
         super(InvalidAuthenticationTypeException, self).__init__(**kwargs)
 
 
+class VIPDuplicateAddressException(exceptions.NeutronException):
+    message = _('Attempted to add duplicate VIP address, '
+                'existing vips are: %(existing_vips)s, '
+                'duplicate vip is: %(duplicate_vip)s')
+
+    def __init__(self, **kwargs):
+        kwargs['existing_vips'] = ', '.join(str(vip) for vip in
+                                            kwargs['existing_vips'])
+        super(VIPDuplicateAddressException, self).__init__(**kwargs)
+
+
 class KeepalivedVipAddress(object):
     """A virtual address entry of a keepalived configuration."""
 
@@ -85,6 +96,15 @@ class KeepalivedVipAddress(object):
         self.interface_name = interface_name
         self.scope = scope
 
+    def __eq__(self, other):
+        return (isinstance(other, KeepalivedVipAddress) and
+                self.ip_address == other.ip_address)
+
+    def __str__(self):
+        return '[%s, %s, %s]' % (self.ip_address,
+                                 self.interface_name,
+                                 self.scope)
+
     def build_config(self):
         result = '%s dev %s' % (self.ip_address, self.interface_name)
         if self.scope:
@@ -168,7 +188,11 @@ class KeepalivedInstance(object):
         self.authentication = (auth_type, password)
 
     def add_vip(self, ip_cidr, interface_name, scope):
-        self.vips.append(KeepalivedVipAddress(ip_cidr, interface_name, scope))
+        vip = KeepalivedVipAddress(ip_cidr, interface_name, scope)
+        if vip in self.vips:
+            raise VIPDuplicateAddressException(existing_vips=self.vips,
+                                               duplicate_vip=vip)
+        self.vips.append(vip)
 
     def remove_vips_vroutes_by_interface(self, interface_name):
         self.vips = [vip for vip in self.vips
index 7d6e9806f9ec422b8ccd8eceba11951cb267e8b9..3a6fb7213622cd5f7b40606270c5f666d9ff0807 100644 (file)
@@ -306,6 +306,14 @@ class KeepalivedVipAddressTestCase(base.BaseTestCase):
         self.assertEqual('fe80::3e97:eff:fe26:3bfa/64 dev eth1 scope link',
                          vip.build_config())
 
+    def test_add_vip_returns_exception_on_duplicate_ip(self):
+        instance = keepalived.KeepalivedInstance('MASTER', 'eth0', 1,
+                                                 ['169.254.192.0/18'])
+        instance.add_vip('192.168.222.1/32', 'eth11', None)
+        self.assertRaises(keepalived.VIPDuplicateAddressException,
+                          instance.add_vip, '192.168.222.1/32', 'eth12',
+                          'link')
+
 
 class KeepalivedVirtualRouteTestCase(base.BaseTestCase):
     def test_virtual_route_with_dev(self):