Add network_id column to apic_ml2_ha_ipaddress_to_port_owner table
Add network_id column to apic_ml2_ha_ipaddress_to_port_owner table to guard against multiple rows of same VIP address. Change-Id: I2d5a2cfdb4242450140689adc50df2197d4a04b3
This commit is contained in:
@@ -5129,9 +5129,12 @@ class TestMigrations(ApicAimTestCase, db.DbMixin):
|
||||
for sg_rule in [sg_rule1, sg_rule2]:
|
||||
self._check_sg_rule(sg['id'], sg_rule)
|
||||
|
||||
def test_ha_ip_vrf_name_insertion(self):
|
||||
net = self._make_network(self.fmt, 'net1', True)
|
||||
sub = self._make_subnet(self.fmt, net, '10.0.0.1', '10.0.0.0/24')[
|
||||
def test_ha_ip_duplicate_entries_removal(self):
|
||||
net1 = self._make_network(self.fmt, 'net1', True)
|
||||
sub1 = self._make_subnet(self.fmt, net1, '10.0.0.1', '10.0.0.0/24')[
|
||||
'subnet']
|
||||
net2 = self._make_network(self.fmt, 'net1', True)
|
||||
sub2 = self._make_subnet(self.fmt, net2, '10.0.0.2', '10.0.0.0/24')[
|
||||
'subnet']
|
||||
allow_addr = [{'ip_address': '1.2.3.250',
|
||||
'mac_address': '00:00:00:AA:AA:AA'},
|
||||
@@ -5139,39 +5142,95 @@ class TestMigrations(ApicAimTestCase, db.DbMixin):
|
||||
'mac_address': '00:00:00:BB:BB:BB'}]
|
||||
owned_addr = ['1.2.3.250', '1.2.3.251']
|
||||
# create 2 ports configured with the same allowed-addresses
|
||||
p1 = self._make_port(self.fmt, net['network']['id'],
|
||||
p1 = self._make_port(self.fmt, net1['network']['id'],
|
||||
arg_list=('allowed_address_pairs',),
|
||||
device_owner='compute:',
|
||||
fixed_ips=[{'subnet_id': sub['id']}],
|
||||
fixed_ips=[{'subnet_id': sub1['id']}],
|
||||
allowed_address_pairs=allow_addr)['port']
|
||||
self._bind_port_to_host(p1['id'], 'h1')
|
||||
net_mapping = self._get_network_mapping(
|
||||
self.db_session, p1['network_id'])
|
||||
vrf1 = net_mapping.vrf_name
|
||||
ip_owner_info = {'port': p1['id'],
|
||||
'ip_address_v4': owned_addr[0],
|
||||
'network_id': p1['network_id']}
|
||||
self.update_ip_owner(ip_owner_info)
|
||||
p1_2 = self._make_port(self.fmt, net1['network']['id'],
|
||||
arg_list=('allowed_address_pairs',),
|
||||
device_owner='compute:',
|
||||
fixed_ips=[{'subnet_id': sub1['id']}],
|
||||
allowed_address_pairs=allow_addr)['port']
|
||||
self._bind_port_to_host(p1['id'], 'h1')
|
||||
ip_owner_info = {'port': p1_2['id'],
|
||||
'ip_address_v4': owned_addr[0],
|
||||
'network_id': p1_2['network_id']}
|
||||
self.update_ip_owner(ip_owner_info)
|
||||
p2 = self._make_port(self.fmt, net2['network']['id'],
|
||||
arg_list=('allowed_address_pairs',),
|
||||
device_owner='compute:',
|
||||
fixed_ips=[{'subnet_id': sub2['id']}],
|
||||
allowed_address_pairs=allow_addr)['port']
|
||||
self._bind_port_to_host(p2['id'], 'h2')
|
||||
ip_owner_info = {'port': p2['id'],
|
||||
'ip_address_v4': owned_addr[0],
|
||||
'network_id': p2['network_id']}
|
||||
self.update_ip_owner(ip_owner_info)
|
||||
data_migrations.do_ha_ip_duplicate_entries_removal(self.db_session)
|
||||
dump = self.get_ha_port_associations()
|
||||
self.assertEqual(2, len(dump))
|
||||
|
||||
def test_ha_ip_network_id_insertion(self):
|
||||
net1 = self._make_network(self.fmt, 'net1', True)
|
||||
sub1 = self._make_subnet(self.fmt, net1, '10.0.0.1', '10.0.0.0/24')[
|
||||
'subnet']
|
||||
net2 = self._make_network(self.fmt, 'net1', True)
|
||||
sub2 = self._make_subnet(self.fmt, net2, '10.0.0.2', '10.0.0.0/24')[
|
||||
'subnet']
|
||||
allow_addr = [{'ip_address': '1.2.3.250',
|
||||
'mac_address': '00:00:00:AA:AA:AA'},
|
||||
{'ip_address': '1.2.3.251',
|
||||
'mac_address': '00:00:00:BB:BB:BB'}]
|
||||
owned_addr = ['1.2.3.250', '1.2.3.251']
|
||||
# create 2 ports configured with the same allowed-addresses
|
||||
p1 = self._make_port(self.fmt, net1['network']['id'],
|
||||
arg_list=('allowed_address_pairs',),
|
||||
device_owner='compute:',
|
||||
fixed_ips=[{'subnet_id': sub1['id']}],
|
||||
allowed_address_pairs=allow_addr)['port']
|
||||
self._bind_port_to_host(p1['id'], 'h1')
|
||||
ip_owner_info = {'port': p1['id'],
|
||||
'ip_address_v4': owned_addr[0],
|
||||
'network_id': p1['network_id']}
|
||||
self.update_ip_owner(ip_owner_info)
|
||||
p2 = self._make_port(self.fmt, net2['network']['id'],
|
||||
arg_list=('allowed_address_pairs',),
|
||||
device_owner='compute:',
|
||||
fixed_ips=[{'subnet_id': sub2['id']}],
|
||||
allowed_address_pairs=allow_addr)['port']
|
||||
self._bind_port_to_host(p2['id'], 'h2')
|
||||
ip_owner_info = {'port': p2['id'],
|
||||
'ip_address_v4': owned_addr[0],
|
||||
'network_id': p2['network_id']}
|
||||
self.update_ip_owner(ip_owner_info)
|
||||
with self.db_session.begin(subtransactions=True):
|
||||
obj = self.get_port_for_ha_ipaddress_and_vrf(
|
||||
owned_addr[0], vrf1, p1['network_id'], session=self.db_session)
|
||||
dump = self.get_ha_port_associations()
|
||||
self.assertEqual(2, len(dump))
|
||||
obj = self.get_port_for_ha_ipaddress(
|
||||
owned_addr[0], p1['network_id'], session=self.db_session)
|
||||
# check HAIP object details
|
||||
self.assertEqual(obj['port_id'], p1['id'])
|
||||
self.assertEqual(obj['ha_ip_address'], owned_addr[0])
|
||||
self.assertEqual(obj['vrf'], vrf1)
|
||||
# Wipe out vrf from HAIP object
|
||||
self.assertEqual(obj['network_id'], p1['network_id'])
|
||||
# Wipe out network_id from HAIP object
|
||||
haip_ip = db.HAIPAddressToPortAssociation.ha_ip_address
|
||||
haip_port_id = db.HAIPAddressToPortAssociation.port_id
|
||||
self.db_session.query(db.HAIPAddressToPortAssociation).filter(
|
||||
haip_ip == owned_addr[0]).filter(
|
||||
haip_port_id == p1['id']).update(
|
||||
{'vrf': ''})
|
||||
# check that vrf value is wiped from the object
|
||||
self.assertEqual(obj['vrf'], '')
|
||||
{'network_id': ''})
|
||||
# check that network id value is wiped from the object
|
||||
self.assertEqual(obj['network_id'], '')
|
||||
# perform data migration
|
||||
data_migrations.do_ha_ip_vrf_name_insertion(self.db_session)
|
||||
# check that vrf value is again added correctly to the obj
|
||||
self.assertEqual(obj['vrf'], vrf1)
|
||||
data_migrations.do_ha_ip_network_id_insertion(self.db_session)
|
||||
# check that network id value is again added correctly to the obj
|
||||
self.assertEqual(obj['network_id'], p1['network_id'])
|
||||
|
||||
|
||||
class TestPortBinding(ApicAimTestCase):
|
||||
@@ -6396,77 +6455,73 @@ class TestPortToHAIPAddressBinding(ApicAimTestCase):
|
||||
self.port1 = self.plugin.create_port(self.context, self.port1_data)
|
||||
self.port1_2 = self.plugin.create_port(self.context, self.port1_2_data)
|
||||
self.port2 = self.plugin.create_port(self.context, self.port2_data)
|
||||
self.net1_id = self.port1['network_id']
|
||||
self.net2_id = self.port2['network_id']
|
||||
self.port_haip = db.DbMixin()
|
||||
self.net1_mapping = self.port_haip._get_network_mapping(
|
||||
self.db_session, self.port1['network_id'])
|
||||
self.net2_mapping = self.port_haip._get_network_mapping(
|
||||
self.db_session, self.port2['network_id'])
|
||||
self.vrf1 = self.net1_mapping.vrf_name
|
||||
self.vrf2 = self.net2_mapping.vrf_name
|
||||
self.port_haip.plugin = self.plugin
|
||||
|
||||
def test_update_and_get_port_to_ha_ip_binding(self):
|
||||
# Test new HA IP address to port binding can be created
|
||||
obj = self.port_haip.update_port_id_for_ha_ipaddress(
|
||||
self.port1['id'], self.ha_ip1, 'vrf1')
|
||||
self.port1['id'], self.ha_ip1, self.net1_id)
|
||||
self.assertEqual(self.port1['id'], obj['port_id'])
|
||||
self.assertEqual(self.ha_ip1, obj['ha_ip_address'])
|
||||
# In this test case we also test that same HA IP address can be set/get
|
||||
# for two different ports in different networks
|
||||
obj = self.port_haip.update_port_id_for_ha_ipaddress(
|
||||
self.port2['id'], self.ha_ip1, 'vrf2')
|
||||
self.port2['id'], self.ha_ip1, self.net2_id)
|
||||
self.assertEqual(self.port2['id'], obj['port_id'])
|
||||
self.assertEqual(self.ha_ip1, obj['ha_ip_address'])
|
||||
# Test get
|
||||
obj = self.port_haip.get_port_for_ha_ipaddress_and_vrf(
|
||||
self.ha_ip1, 'vrf1', self.port1['network_id'])
|
||||
obj = self.port_haip.get_port_for_ha_ipaddress(
|
||||
self.ha_ip1, self.net1_id)
|
||||
self.assertEqual(self.port1['id'], obj['port_id'])
|
||||
obj = self.port_haip.get_port_for_ha_ipaddress_and_vrf(
|
||||
self.ha_ip1, 'vrf2', self.port2['network_id'])
|
||||
obj = self.port_haip.get_port_for_ha_ipaddress(
|
||||
self.ha_ip1, self.net2_id)
|
||||
self.assertEqual(self.port2['id'], obj['port_id'])
|
||||
|
||||
def test_port_to_multiple_ha_ip_binding(self):
|
||||
self.port_haip.update_port_id_for_ha_ipaddress(self.port1['id'],
|
||||
self.ha_ip1,
|
||||
self.vrf1)
|
||||
self.net1_id)
|
||||
self.port_haip.update_port_id_for_ha_ipaddress(self.port1['id'],
|
||||
self.ha_ip2,
|
||||
self.vrf1)
|
||||
obj = self.port_haip.get_port_for_ha_ipaddress_and_vrf(
|
||||
self.ha_ip1, self.vrf1, self.port1['network_id'])
|
||||
self.net1_id)
|
||||
obj = self.port_haip.get_port_for_ha_ipaddress(
|
||||
self.ha_ip1, self.net1_id)
|
||||
self.assertEqual(self.port1['id'], obj['port_id'])
|
||||
obj = self.port_haip.get_port_for_ha_ipaddress_and_vrf(
|
||||
self.ha_ip2, self.vrf1, self.port1['network_id'])
|
||||
obj = self.port_haip.get_port_for_ha_ipaddress(
|
||||
self.ha_ip2, self.net1_id)
|
||||
self.assertEqual(self.port1['id'], obj['port_id'])
|
||||
|
||||
def test_delete_port_for_ha_ip_binding(self):
|
||||
self.port_haip.update_port_id_for_ha_ipaddress(self.port1['id'],
|
||||
self.ha_ip1,
|
||||
self.vrf1)
|
||||
self.net1_id)
|
||||
result = self.port_haip.delete_port_id_for_ha_ipaddress(
|
||||
self.port1['id'], self.ha_ip1)
|
||||
self.assertEqual(1, result)
|
||||
obj = self.port_haip.get_port_for_ha_ipaddress_and_vrf(
|
||||
self.ha_ip1, self.vrf2, self.port2['network_id'])
|
||||
obj = self.port_haip.get_port_for_ha_ipaddress(
|
||||
self.ha_ip1, self.net2_id)
|
||||
self.assertIsNone(obj)
|
||||
|
||||
def test_get_ha_ip_addresses_for_port(self):
|
||||
self.port_haip.update_port_id_for_ha_ipaddress(self.port1['id'],
|
||||
self.ha_ip1,
|
||||
self.vrf1)
|
||||
self.net1_id)
|
||||
self.port_haip.update_port_id_for_ha_ipaddress(self.port1['id'],
|
||||
self.ha_ip2,
|
||||
self.vrf1)
|
||||
self.net1_id)
|
||||
ha_ips = self.port_haip.get_ha_ipaddresses_for_port(self.port1['id'])
|
||||
self.assertEqual(sorted([self.ha_ip1, self.ha_ip2]), ha_ips)
|
||||
|
||||
def test_idempotent(self):
|
||||
self.port_haip.update_port_id_for_ha_ipaddress(self.port1['id'],
|
||||
self.ha_ip1,
|
||||
self.vrf1)
|
||||
self.net1_id)
|
||||
obj = self.port_haip.update_port_id_for_ha_ipaddress(self.port1['id'],
|
||||
self.ha_ip1,
|
||||
self.vrf1)
|
||||
self.net1_id)
|
||||
self.assertEqual(self.port1['id'], obj['port_id'])
|
||||
self.assertEqual(self.ha_ip1, obj['ha_ip_address'])
|
||||
|
||||
@@ -6478,7 +6533,7 @@ class TestPortToHAIPAddressBinding(ApicAimTestCase):
|
||||
def test_delete_non_existing_entry(self):
|
||||
self.port_haip.update_port_id_for_ha_ipaddress(self.port1['id'],
|
||||
self.ha_ip1,
|
||||
self.vrf1)
|
||||
self.net1_id)
|
||||
result = self.port_haip.delete_port_id_for_ha_ipaddress(
|
||||
self.port1['id'], "fake")
|
||||
self.assertEqual(0, result)
|
||||
@@ -6492,21 +6547,21 @@ class TestPortToHAIPAddressBinding(ApicAimTestCase):
|
||||
|
||||
# set new owner
|
||||
ports = self.port_haip.update_ip_owner(ip_owner_info)
|
||||
obj = self.port_haip.get_port_for_ha_ipaddress_and_vrf(
|
||||
self.ha_ip1, self.vrf1, self.port1['network_id'])
|
||||
obj = self.port_haip.get_port_for_ha_ipaddress(
|
||||
self.ha_ip1, self.net1_id)
|
||||
self.assertEqual(self.port1['id'], obj['port_id'])
|
||||
self.assertTrue(self.port1['id'] in ports)
|
||||
|
||||
# update owner
|
||||
self.port2_data['port']['id'] = _uuid()
|
||||
self.port2_data['port']['network_id'] = self.port1['network_id']
|
||||
self.port2_data['port']['network_id'] = self.net1_id
|
||||
self.port2_data['port']['mac_address'] = 'fake-mac-3'
|
||||
port3 = self.plugin.create_port(self.context, self.port2_data)
|
||||
|
||||
ip_owner_info['port'] = port3['id']
|
||||
ports = self.port_haip.update_ip_owner(ip_owner_info)
|
||||
obj = self.port_haip.get_port_for_ha_ipaddress_and_vrf(
|
||||
self.ha_ip1, self.vrf2, port3['network_id'])
|
||||
obj = self.port_haip.get_port_for_ha_ipaddress(
|
||||
self.ha_ip1, port3['network_id'])
|
||||
self.assertEqual(port3['id'], obj['port_id'])
|
||||
|
||||
def test_ip_replaced(self):
|
||||
@@ -6538,16 +6593,16 @@ class TestPortToHAIPAddressBinding(ApicAimTestCase):
|
||||
|
||||
def test_duplicate_entry_handled_gracefully(self):
|
||||
self.port_haip.update_port_id_for_ha_ipaddress(
|
||||
self.port1['id'], self.ha_ip1, self.vrf1)
|
||||
self.port1['id'], self.ha_ip1, self.net1_id)
|
||||
# Set this twice, without hijacking the query
|
||||
obj = self.port_haip.update_port_id_for_ha_ipaddress(
|
||||
self.port1['id'], self.ha_ip1, self.vrf1)
|
||||
self.port1['id'], self.ha_ip1, self.net1_id)
|
||||
self.assertEqual(obj.port_id, self.port1['id'])
|
||||
self.assertEqual(obj.ha_ip_address, self.ha_ip1)
|
||||
# Now simulate null return from query
|
||||
self.port_haip._get_ha_ipaddress = mock.Mock(return_value=None)
|
||||
obj = self.port_haip.update_port_id_for_ha_ipaddress(
|
||||
self.port1['id'], self.ha_ip1, self.vrf1)
|
||||
self.port1['id'], self.ha_ip1, self.net1_id)
|
||||
self.assertIsNone(obj)
|
||||
|
||||
|
||||
@@ -12147,10 +12202,8 @@ class TestOpflexRpc(ApicAimTestCase):
|
||||
self.driver.ip_address_owner_update(
|
||||
n_context.get_admin_context(), ip_owner_info=ip_owner_info,
|
||||
host='h1')
|
||||
mapping = self.driver._get_network_mapping(self.db_session, net_id)
|
||||
vrf_name = mapping.vrf_name
|
||||
obj = self.driver.get_port_for_ha_ipaddress_and_vrf(
|
||||
'1.2.3.4', vrf_name, net_id)
|
||||
obj = self.driver.get_port_for_ha_ipaddress(
|
||||
'1.2.3.4', net_id)
|
||||
self.assertEqual(port1_id, obj['port_id'])
|
||||
self.driver._notify_port_update.assert_called_with(
|
||||
mock.ANY, port1_id)
|
||||
@@ -12161,8 +12214,8 @@ class TestOpflexRpc(ApicAimTestCase):
|
||||
self.driver.ip_address_owner_update(
|
||||
n_context.get_admin_context(), ip_owner_info=ip_owner_info,
|
||||
host='h2')
|
||||
obj = self.driver.get_port_for_ha_ipaddress_and_vrf(
|
||||
'1.2.3.4', vrf_name, net_id)
|
||||
obj = self.driver.get_port_for_ha_ipaddress(
|
||||
'1.2.3.4', net_id)
|
||||
self.assertEqual(port2_id, obj['port_id'])
|
||||
exp_calls = [
|
||||
mock.call(mock.ANY, port1_id),
|
||||
|
||||
@@ -3747,11 +3747,8 @@ class TestPolicyTarget(AIMBaseTestCase,
|
||||
# set new owner
|
||||
self.mech_driver.ip_address_owner_update(self._context,
|
||||
ip_owner_info=ip_owner_info, host='h1')
|
||||
mapping = self.mech_driver._get_network_mapping(
|
||||
self.db_session, net_id)
|
||||
vrf_name = mapping.vrf_name
|
||||
obj = self.mech_driver.get_port_for_ha_ipaddress_and_vrf(
|
||||
'1.2.3.4', vrf_name, net_id)
|
||||
obj = self.mech_driver.get_port_for_ha_ipaddress(
|
||||
'1.2.3.4', net_id)
|
||||
|
||||
self.assertEqual(pt1['port_id'], obj['port_id'])
|
||||
self.mech_driver._notify_port_update.assert_called_with(
|
||||
@@ -3762,8 +3759,8 @@ class TestPolicyTarget(AIMBaseTestCase,
|
||||
ip_owner_info['port'] = pt2['port_id']
|
||||
self.mech_driver.ip_address_owner_update(self._context,
|
||||
ip_owner_info=ip_owner_info, host='h2')
|
||||
obj = self.mech_driver.get_port_for_ha_ipaddress_and_vrf(
|
||||
'1.2.3.4', vrf_name, net_id)
|
||||
obj = self.mech_driver.get_port_for_ha_ipaddress(
|
||||
'1.2.3.4', net_id)
|
||||
self.assertEqual(pt2['port_id'], obj['port_id'])
|
||||
exp_calls = [
|
||||
mock.call(mock.ANY, pt1['port_id']),
|
||||
|
||||
Reference in New Issue
Block a user