From 72e388445eb6f6903ccfc5079aa206ac2cbcfd5e Mon Sep 17 00:00:00 2001 From: Sachi King Date: Mon, 8 Dec 2014 17:42:48 +1100 Subject: [PATCH] Return exception when attempting to add duplicate VIP 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 | 26 ++++++++++++++++++- .../tests/unit/agent/linux/test_keepalived.py | 8 ++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/neutron/agent/linux/keepalived.py b/neutron/agent/linux/keepalived.py index f856def6d..eccd7a42c 100644 --- a/neutron/agent/linux/keepalived.py +++ b/neutron/agent/linux/keepalived.py @@ -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 diff --git a/neutron/tests/unit/agent/linux/test_keepalived.py b/neutron/tests/unit/agent/linux/test_keepalived.py index 7d6e9806f..3a6fb7213 100644 --- a/neutron/tests/unit/agent/linux/test_keepalived.py +++ b/neutron/tests/unit/agent/linux/test_keepalived.py @@ -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): -- 2.45.2