Allow to create vip in lb-mgmt-net
Change-Id: Ie2c916bd557190e5dfead12c2635955da92c52ff Closes-Bug: #1659488
This commit is contained in:
parent
0d275928b3
commit
e1ec15c9a8
@ -74,10 +74,14 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver):
|
||||
ret.append(interface)
|
||||
return ret
|
||||
|
||||
def _get_plugged_interface(self, compute_id, network_id):
|
||||
def _get_plugged_interface(self, compute_id, network_id, lb_network_ip):
|
||||
interfaces = self.get_plugged_networks(compute_id)
|
||||
for interface in interfaces:
|
||||
if interface.network_id == network_id:
|
||||
is_correct_interface = interface.network_id == network_id
|
||||
for ip in interface.fixed_ips:
|
||||
if ip.ip_address == lb_network_ip:
|
||||
is_correct_interface = False
|
||||
if is_correct_interface:
|
||||
return interface
|
||||
|
||||
def _plug_amphora_vip(self, amphora, subnet):
|
||||
@ -299,8 +303,8 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver):
|
||||
lambda amp: amp.status == constants.AMPHORA_ALLOCATED,
|
||||
load_balancer.amphorae):
|
||||
|
||||
interface = self._get_plugged_interface(amphora.compute_id,
|
||||
subnet.network_id)
|
||||
interface = self._get_plugged_interface(
|
||||
amphora.compute_id, subnet.network_id, amphora.lb_network_ip)
|
||||
if not interface:
|
||||
interface = self._plug_amphora_vip(amphora, subnet)
|
||||
|
||||
@ -310,7 +314,9 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver):
|
||||
interface.port_id)
|
||||
vrrp_ip = None
|
||||
for fixed_ip in interface.fixed_ips:
|
||||
if fixed_ip.subnet_id == subnet.id:
|
||||
is_correct_subnet = fixed_ip.subnet_id == subnet.id
|
||||
is_management_ip = fixed_ip.ip_address == amphora.lb_network_ip
|
||||
if is_correct_subnet and not is_management_ip:
|
||||
vrrp_ip = fixed_ip.ip_address
|
||||
break
|
||||
plugged_amphorae.append(data_models.Amphora(
|
||||
@ -358,8 +364,8 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver):
|
||||
lambda amp: amp.status == constants.AMPHORA_ALLOCATED,
|
||||
load_balancer.amphorae):
|
||||
|
||||
interface = self._get_plugged_interface(amphora.compute_id,
|
||||
subnet.network_id)
|
||||
interface = self._get_plugged_interface(
|
||||
amphora.compute_id, subnet.network_id, amphora.lb_network_ip)
|
||||
if not interface:
|
||||
# Thought about raising PluggedVIPNotFound exception but
|
||||
# then that wouldn't evaluate all amphorae, so just continue
|
||||
|
@ -18,14 +18,18 @@ class MockNovaInterface(object):
|
||||
port_id = None
|
||||
fixed_ips = []
|
||||
|
||||
MOCK_NETWORK_ID = '1'
|
||||
MOCK_NETWORK_ID = 'mock-network-1'
|
||||
MOCK_NETWORK_ID2 = 'mock-network-2'
|
||||
MOCK_NETWORK_NAME = 'TestNet1'
|
||||
MOCK_SUBNET_ID = '2'
|
||||
MOCK_SUBNET_ID = 'mock-subnet-1'
|
||||
MOCK_SUBNET_ID2 = 'mock-subnet-2'
|
||||
MOCK_SUBNET_NAME = 'TestSubnet1'
|
||||
MOCK_PORT_ID = '3'
|
||||
MOCK_PORT_ID = 'mock-port-1'
|
||||
MOCK_PORT_ID2 = 'mock-port-2'
|
||||
MOCK_PORT_NAME = 'TestPort1'
|
||||
MOCK_COMPUTE_ID = '4'
|
||||
MOCK_COMPUTE_ID = 'mock-compute-1'
|
||||
MOCK_IP_ADDRESS = '10.0.0.1'
|
||||
MOCK_IP_ADDRESS2 = '10.0.0.2'
|
||||
MOCK_CIDR = '10.0.0.0/24'
|
||||
MOCK_MAC_ADDR = 'fe:16:3e:00:95:5c'
|
||||
MOCK_NOVA_INTERFACE = MockNovaInterface()
|
||||
@ -33,6 +37,12 @@ MOCK_SUBNET = {'subnet': {'id': MOCK_SUBNET_ID, 'network_id': MOCK_NETWORK_ID}}
|
||||
MOCK_NOVA_INTERFACE.net_id = MOCK_NETWORK_ID
|
||||
MOCK_NOVA_INTERFACE.port_id = MOCK_PORT_ID
|
||||
MOCK_NOVA_INTERFACE.fixed_ips = [{'ip_address': MOCK_IP_ADDRESS}]
|
||||
MOCK_NOVA_INTERFACE2 = MockNovaInterface()
|
||||
MOCK_SUBNET2 = {'subnet': {'id': MOCK_SUBNET_ID2,
|
||||
'network_id': MOCK_NETWORK_ID2}}
|
||||
MOCK_NOVA_INTERFACE2.net_id = MOCK_NETWORK_ID2
|
||||
MOCK_NOVA_INTERFACE2.port_id = MOCK_PORT_ID2
|
||||
MOCK_NOVA_INTERFACE2.fixed_ips = [{'ip_address': MOCK_IP_ADDRESS2}]
|
||||
MOCK_DEVICE_OWNER = 'Moctavia'
|
||||
MOCK_DEVICE_ID = 'Moctavia123'
|
||||
|
||||
@ -42,3 +52,76 @@ MOCK_NEUTRON_PORT = {'port': {'network_id': MOCK_NETWORK_ID,
|
||||
'id': MOCK_PORT_ID,
|
||||
'fixed_ips': [{'ip_address': MOCK_IP_ADDRESS,
|
||||
'subnet_id': MOCK_SUBNET_ID}]}}
|
||||
|
||||
MOCK_AMP_ID1 = 'amp1-id'
|
||||
MOCK_AMP_ID2 = 'amp2-id'
|
||||
MOCK_AMP_COMPUTE_ID1 = 'amp1-compute-id'
|
||||
MOCK_AMP_COMPUTE_ID2 = 'amp2-compute-id'
|
||||
|
||||
MOCK_MANAGEMENT_SUBNET_ID = 'mgmt-subnet-1'
|
||||
MOCK_MANAGEMENT_NET_ID = 'mgmt-net-1'
|
||||
MOCK_MANAGEMENT_PORT_ID1 = 'mgmt-port-1'
|
||||
MOCK_MANAGEMENT_PORT_ID2 = 'mgmt-port-2'
|
||||
# These IPs become lb_network_ip
|
||||
MOCK_MANAGEMENT_IP1 = '99.99.99.1'
|
||||
MOCK_MANAGEMENT_IP2 = '99.99.99.2'
|
||||
|
||||
MOCK_MANAGEMENT_FIXED_IPS1 = [{'ip_address': MOCK_MANAGEMENT_IP1,
|
||||
'subnet_id': MOCK_MANAGEMENT_SUBNET_ID}]
|
||||
MOCK_MANAGEMENT_FIXED_IPS2 = [{'ip_address': MOCK_MANAGEMENT_IP2,
|
||||
'subnet_id': MOCK_MANAGEMENT_SUBNET_ID}]
|
||||
|
||||
MOCK_MANAGEMENT_INTERFACE1 = MockNovaInterface()
|
||||
MOCK_MANAGEMENT_INTERFACE1.net_id = MOCK_MANAGEMENT_NET_ID
|
||||
MOCK_MANAGEMENT_INTERFACE1.port_id = MOCK_MANAGEMENT_PORT_ID1
|
||||
MOCK_MANAGEMENT_INTERFACE1.fixed_ips = MOCK_MANAGEMENT_FIXED_IPS1
|
||||
MOCK_MANAGEMENT_INTERFACE2 = MockNovaInterface()
|
||||
MOCK_MANAGEMENT_INTERFACE2.net_id = MOCK_MANAGEMENT_NET_ID
|
||||
MOCK_MANAGEMENT_INTERFACE2.port_id = MOCK_MANAGEMENT_PORT_ID2
|
||||
MOCK_MANAGEMENT_INTERFACE2.fixed_ips = MOCK_MANAGEMENT_FIXED_IPS2
|
||||
|
||||
MOCK_MANAGEMENT_PORT1 = {'port': {'network_id': MOCK_MANAGEMENT_NET_ID,
|
||||
'device_id': MOCK_AMP_COMPUTE_ID1,
|
||||
'device_owner': MOCK_DEVICE_OWNER,
|
||||
'id': MOCK_MANAGEMENT_PORT_ID1,
|
||||
'fixed_ips': MOCK_MANAGEMENT_FIXED_IPS1}}
|
||||
|
||||
MOCK_MANAGEMENT_PORT2 = {'port': {'network_id': MOCK_MANAGEMENT_NET_ID,
|
||||
'device_id': MOCK_AMP_COMPUTE_ID2,
|
||||
'device_owner': MOCK_DEVICE_OWNER,
|
||||
'id': MOCK_MANAGEMENT_PORT_ID2,
|
||||
'fixed_ips': MOCK_MANAGEMENT_FIXED_IPS2}}
|
||||
|
||||
MOCK_VIP_SUBNET_ID = 'vip-subnet-1'
|
||||
MOCK_VIP_NET_ID = 'vip-net-1'
|
||||
MOCK_VRRP_PORT_ID1 = 'vrrp-port-1'
|
||||
MOCK_VRRP_PORT_ID2 = 'vrrp-port-2'
|
||||
# These IPs become vrrp_ip
|
||||
MOCK_VRRP_IP1 = '55.55.55.1'
|
||||
MOCK_VRRP_IP2 = '55.55.55.2'
|
||||
|
||||
MOCK_VRRP_FIXED_IPS1 = [{'ip_address': MOCK_VRRP_IP1,
|
||||
'subnet_id': MOCK_VIP_SUBNET_ID}]
|
||||
MOCK_VRRP_FIXED_IPS2 = [{'ip_address': MOCK_VRRP_IP2,
|
||||
'subnet_id': MOCK_VIP_SUBNET_ID}]
|
||||
|
||||
MOCK_VRRP_INTERFACE1 = MockNovaInterface()
|
||||
MOCK_VRRP_INTERFACE1.net_id = MOCK_VIP_NET_ID
|
||||
MOCK_VRRP_INTERFACE1.port_id = MOCK_VRRP_PORT_ID1
|
||||
MOCK_VRRP_INTERFACE1.fixed_ips = MOCK_VRRP_FIXED_IPS1
|
||||
MOCK_VRRP_INTERFACE2 = MockNovaInterface()
|
||||
MOCK_VRRP_INTERFACE2.net_id = MOCK_VIP_NET_ID
|
||||
MOCK_VRRP_INTERFACE2.port_id = MOCK_VRRP_PORT_ID2
|
||||
MOCK_VRRP_INTERFACE2.fixed_ips = MOCK_VRRP_FIXED_IPS2
|
||||
|
||||
MOCK_VRRP_PORT1 = {'port': {'network_id': MOCK_VIP_NET_ID,
|
||||
'device_id': MOCK_AMP_COMPUTE_ID1,
|
||||
'device_owner': MOCK_DEVICE_OWNER,
|
||||
'id': MOCK_VRRP_PORT_ID1,
|
||||
'fixed_ips': MOCK_VRRP_FIXED_IPS1}}
|
||||
|
||||
MOCK_VRRP_PORT2 = {'port': {'network_id': MOCK_VIP_NET_ID,
|
||||
'device_id': MOCK_AMP_COMPUTE_ID2,
|
||||
'device_owner': MOCK_DEVICE_OWNER,
|
||||
'id': MOCK_VRRP_PORT_ID2,
|
||||
'fixed_ips': MOCK_VRRP_FIXED_IPS2}}
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
from octavia.common import constants
|
||||
from octavia.common import data_models
|
||||
from octavia.tests.common import constants as ut_constants
|
||||
|
||||
|
||||
def generate_load_balancer_tree():
|
||||
@ -54,8 +55,8 @@ def generate_vip(load_balancer=None):
|
||||
global VIP_SEED
|
||||
VIP_SEED += 1
|
||||
vip = data_models.Vip(ip_address='10.0.0.{0}'.format(VIP_SEED),
|
||||
subnet_id='subnet{0}-id'.format(VIP_SEED),
|
||||
port_id='port{0}-id'.format(VIP_SEED),
|
||||
subnet_id=ut_constants.MOCK_VIP_SUBNET_ID,
|
||||
port_id='vrrp-port-{0}'.format(VIP_SEED),
|
||||
load_balancer=load_balancer)
|
||||
if load_balancer:
|
||||
vip.load_balancer_id = load_balancer.id
|
||||
@ -69,10 +70,10 @@ def generate_amphora(load_balancer=None):
|
||||
global AMP_SEED
|
||||
AMP_SEED += 1
|
||||
amp = data_models.Amphora(id='amp{0}-id'.format(AMP_SEED),
|
||||
compute_id='compute{0}-id'.format(AMP_SEED),
|
||||
compute_id='amp{0}-compute-id'.format(AMP_SEED),
|
||||
status='ACTIVE',
|
||||
lb_network_ip='11.0.0.{0}'.format(AMP_SEED),
|
||||
vrrp_ip='12.0.0.{0}'.format(AMP_SEED),
|
||||
lb_network_ip='99.99.99.{0}'.format(AMP_SEED),
|
||||
vrrp_ip='55.55.55.{0}'.format(AMP_SEED),
|
||||
load_balancer=load_balancer)
|
||||
if load_balancer:
|
||||
amp.load_balancer_id = load_balancer.id
|
||||
|
@ -252,11 +252,17 @@ class TestAllowedAddressPairsDriver(base.TestCase):
|
||||
show_subnet = self.driver.neutron_client.show_subnet
|
||||
show_subnet.return_value = {
|
||||
'subnet': {
|
||||
'id': lb.vip.subnet_id
|
||||
'id': t_constants.MOCK_VIP_SUBNET_ID,
|
||||
'network_id': t_constants.MOCK_VIP_NET_ID
|
||||
}
|
||||
}
|
||||
list_ports = self.driver.neutron_client.list_ports
|
||||
port1 = t_constants.MOCK_MANAGEMENT_PORT1['port']
|
||||
port2 = t_constants.MOCK_MANAGEMENT_PORT2['port']
|
||||
list_ports.side_effect = [{'ports': [port1]}, {'ports': [port2]}]
|
||||
interface_attach = self.driver.nova_client.servers.interface_attach
|
||||
interface_attach.return_value = t_constants.MOCK_NOVA_INTERFACE
|
||||
interface_attach.side_effect = [t_constants.MOCK_VRRP_INTERFACE1,
|
||||
t_constants.MOCK_VRRP_INTERFACE2]
|
||||
list_security_groups = self.driver.neutron_client.list_security_groups
|
||||
list_security_groups.return_value = {
|
||||
'security_groups': [
|
||||
@ -266,22 +272,69 @@ class TestAllowedAddressPairsDriver(base.TestCase):
|
||||
update_port = self.driver.neutron_client.update_port
|
||||
expected_aap = {'port': {'allowed_address_pairs':
|
||||
[{'ip_address': lb.vip.ip_address}]}}
|
||||
interface_list = self.driver.nova_client.servers.interface_list
|
||||
if1 = t_constants.MOCK_NOVA_INTERFACE
|
||||
if2 = t_constants.MockNovaInterface()
|
||||
if2.net_id = '3'
|
||||
if2.port_id = '4'
|
||||
if2.fixed_ips = [{'ip_address': '10.0.0.2'}]
|
||||
if1.fixed_ips = [{'ip_address': t_constants.MOCK_IP_ADDRESS,
|
||||
'subnet_id': lb.vip.subnet_id}]
|
||||
interface_list.return_value = [if1, if2]
|
||||
amps = self.driver.plug_vip(lb, lb.vip)
|
||||
self.assertEqual(5, update_port.call_count)
|
||||
update_port.assert_any_call(if1.port_id, expected_aap)
|
||||
for amp in amps:
|
||||
self.assertEqual(t_constants.MOCK_IP_ADDRESS, amp.vrrp_ip)
|
||||
update_port.assert_any_call(amp.vrrp_port_id, expected_aap)
|
||||
self.assertIn(amp.vrrp_ip, [t_constants.MOCK_VRRP_IP1,
|
||||
t_constants.MOCK_VRRP_IP2])
|
||||
self.assertEqual(lb.vip.ip_address, amp.ha_ip)
|
||||
|
||||
def _set_safely(self, obj, name, value):
|
||||
if isinstance(obj, dict):
|
||||
current = obj.get(name)
|
||||
self.addCleanup(obj.update, {name: current})
|
||||
obj.update({name: value})
|
||||
else:
|
||||
current = getattr(obj, name)
|
||||
self.addCleanup(setattr, obj, name, current)
|
||||
setattr(obj, name, value)
|
||||
|
||||
def test_plug_vip_on_mgmt_net(self):
|
||||
lb = dmh.generate_load_balancer_tree()
|
||||
lb.vip.subnet_id = t_constants.MOCK_MANAGEMENT_SUBNET_ID
|
||||
show_subnet = self.driver.neutron_client.show_subnet
|
||||
show_subnet.return_value = {
|
||||
'subnet': {
|
||||
'id': t_constants.MOCK_MANAGEMENT_SUBNET_ID,
|
||||
'network_id': t_constants.MOCK_MANAGEMENT_NET_ID
|
||||
}
|
||||
}
|
||||
list_ports = self.driver.neutron_client.list_ports
|
||||
port1 = t_constants.MOCK_MANAGEMENT_PORT1['port']
|
||||
port2 = t_constants.MOCK_MANAGEMENT_PORT2['port']
|
||||
self._set_safely(t_constants.MOCK_MANAGEMENT_FIXED_IPS1[0],
|
||||
'ip_address', lb.amphorae[0].lb_network_ip)
|
||||
self._set_safely(t_constants.MOCK_MANAGEMENT_FIXED_IPS2[0],
|
||||
'ip_address', lb.amphorae[1].lb_network_ip)
|
||||
list_ports.side_effect = [{'ports': [port1]}, {'ports': [port2]}]
|
||||
interface_attach = self.driver.nova_client.servers.interface_attach
|
||||
self._set_safely(t_constants.MOCK_VRRP_INTERFACE1,
|
||||
'net_id', t_constants.MOCK_MANAGEMENT_NET_ID)
|
||||
self._set_safely(t_constants.MOCK_VRRP_FIXED_IPS1[0],
|
||||
'subnet_id', t_constants.MOCK_MANAGEMENT_SUBNET_ID)
|
||||
self._set_safely(t_constants.MOCK_VRRP_INTERFACE2,
|
||||
'net_id', t_constants.MOCK_MANAGEMENT_NET_ID)
|
||||
self._set_safely(t_constants.MOCK_VRRP_FIXED_IPS2[0],
|
||||
'subnet_id', t_constants.MOCK_MANAGEMENT_SUBNET_ID)
|
||||
interface_attach.side_effect = [t_constants.MOCK_VRRP_INTERFACE1,
|
||||
t_constants.MOCK_VRRP_INTERFACE2]
|
||||
list_security_groups = self.driver.neutron_client.list_security_groups
|
||||
list_security_groups.return_value = {
|
||||
'security_groups': [
|
||||
{'id': 'lb-sec-grp1'}
|
||||
]
|
||||
}
|
||||
update_port = self.driver.neutron_client.update_port
|
||||
expected_aap = {'port': {'allowed_address_pairs':
|
||||
[{'ip_address': lb.vip.ip_address}]}}
|
||||
amps = self.driver.plug_vip(lb, lb.vip)
|
||||
self.assertEqual(5, update_port.call_count)
|
||||
for amp in amps:
|
||||
update_port.assert_any_call(amp.vrrp_port_id, expected_aap)
|
||||
self.assertIn(amp.vrrp_ip, [t_constants.MOCK_VRRP_IP1,
|
||||
t_constants.MOCK_VRRP_IP2])
|
||||
self.assertEqual(lb.vip.ip_address, amp.ha_ip)
|
||||
self.assertIn(amp.id, [lb.amphorae[0].id, lb.amphorae[1].id])
|
||||
|
||||
def test_allocate_vip_when_port_already_provided(self):
|
||||
show_port = self.driver.neutron_client.show_port
|
||||
@ -306,7 +359,7 @@ class TestAllowedAddressPairsDriver(base.TestCase):
|
||||
self.assertRaises(network_base.AllocateVIPException,
|
||||
self.driver.allocate_vip, fake_lb)
|
||||
|
||||
def test_allocate_vip_when_only_subnet_provided(self):
|
||||
def test_allocate_vip_when_no_port_provided(self):
|
||||
port_create_dict = copy.copy(t_constants.MOCK_NEUTRON_PORT)
|
||||
port_create_dict['port']['device_owner'] = (
|
||||
allowed_address_pairs.OCTAVIA_OWNER)
|
||||
@ -433,7 +486,8 @@ class TestAllowedAddressPairsDriver(base.TestCase):
|
||||
actual_ips = [fixed_ip.ip_address
|
||||
for fixed_ip in oct_interface.fixed_ips]
|
||||
self.assertEqual(exp_ips, actual_ips)
|
||||
self.assertEqual(t_constants.MOCK_COMPUTE_ID, oct_interface.compute_id)
|
||||
self.assertEqual(t_constants.MOCK_COMPUTE_ID,
|
||||
oct_interface.compute_id)
|
||||
self.assertEqual(net_id, oct_interface.network_id)
|
||||
|
||||
def test_unplug_network_when_compute_port_cant_be_found(self):
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
fixes:
|
||||
- Allow the loadbalancer's VIP to be created on the same
|
||||
network as the management interface.
|
Loading…
x
Reference in New Issue
Block a user