Merge "New fullstack test for subnet port delete race condition"

This commit is contained in:
Zuul 2020-12-21 11:54:16 +00:00 committed by Gerrit Code Review
commit 38d683a7ec
3 changed files with 124 additions and 2 deletions

View File

@ -79,6 +79,16 @@ class ClientFixture(fixtures.Fixture):
def update_router(self, router_id, **kwargs): def update_router(self, router_id, **kwargs):
return self._update_resource('router', router_id, kwargs) return self._update_resource('router', router_id, kwargs)
def create_segment(self, project_id, network, name, network_type=None,
segmentation_id=None, physical_network=None):
resource_type = 'segment'
name = name or utils.get_rand_name(prefix=resource_type)
spec = {'project_id': project_id, 'name': name, 'network_id': network,
'network_type': network_type,
'physical_network': physical_network,
'segmentation_id': segmentation_id}
return self._create_resource(resource_type, spec)
def create_network(self, tenant_id, name=None, external=False, def create_network(self, tenant_id, name=None, external=False,
network_type=None, segmentation_id=None, network_type=None, segmentation_id=None,
physical_network=None, mtu=None): physical_network=None, mtu=None):
@ -129,6 +139,10 @@ class ClientFixture(fixtures.Fixture):
return self._create_resource(resource_type, spec) return self._create_resource(resource_type, spec)
def list_subnets(self, retrieve_all=True, **kwargs):
resp = self.client.list_subnets(retrieve_all=retrieve_all, **kwargs)
return resp['subnets']
def list_ports(self, retrieve_all=True, **kwargs): def list_ports(self, retrieve_all=True, **kwargs):
resp = self.client.list_ports(retrieve_all=retrieve_all, **kwargs) resp = self.client.list_ports(retrieve_all=retrieve_all, **kwargs)
return resp['ports'] return resp['ports']

View File

@ -171,13 +171,19 @@ class ML2ConfigFixture(ConfigFixture):
if self.env_desc.l2_pop: if self.env_desc.l2_pop:
mechanism_drivers += ',l2population' mechanism_drivers += ',l2population'
net_vlan_ranges_extra = ''
if 'segments' in env_desc.service_plugins:
net_vlan_ranges_extra = (',' + PHYSICAL_NETWORK_NAME +
'_lb:1050:1059')
self.config.update({ self.config.update({
'ml2': { 'ml2': {
'tenant_network_types': tenant_network_types, 'tenant_network_types': tenant_network_types,
'mechanism_drivers': mechanism_drivers, 'mechanism_drivers': mechanism_drivers,
}, },
'ml2_type_vlan': { 'ml2_type_vlan': {
'network_vlan_ranges': PHYSICAL_NETWORK_NAME + ':1000:1029', 'network_vlan_ranges': PHYSICAL_NETWORK_NAME + ':1000:1029' +
net_vlan_ranges_extra,
}, },
'ml2_type_gre': { 'ml2_type_gre': {
'tunnel_id_ranges': '1:30', 'tunnel_id_ranges': '1:30',
@ -337,6 +343,8 @@ class LinuxBridgeConfigFixture(ConfigFixture):
env_desc, host_desc, temp_dir, env_desc, host_desc, temp_dir,
base_filename="linuxbridge_agent.ini" base_filename="linuxbridge_agent.ini"
) )
self.service_plugins = env_desc.service_plugins
self.config.update({ self.config.update({
'VXLAN': { 'VXLAN': {
'enable_vxlan': str(self.env_desc.tunneling_enabled), 'enable_vxlan': str(self.env_desc.tunneling_enabled),
@ -376,7 +384,10 @@ class LinuxBridgeConfigFixture(ConfigFixture):
}) })
def _generate_bridge_mappings(self, device_name): def _generate_bridge_mappings(self, device_name):
return '%s:%s' % (PHYSICAL_NETWORK_NAME, device_name) bridge_mappings_extra = ('_lb' if 'segments' in self.service_plugins
else '')
return '%s%s:%s' % (PHYSICAL_NETWORK_NAME, bridge_mappings_extra,
device_name)
class L3ConfigFixture(ConfigFixture): class L3ConfigFixture(ConfigFixture):

View File

@ -235,3 +235,100 @@ class TestDhcpAgentHARaceCondition(BaseDhcpAgentTest):
network_dhcp_agents = self.client.list_dhcp_agent_hosting_networks( network_dhcp_agents = self.client.list_dhcp_agent_hosting_networks(
self.network['id'])['agents'] self.network['id'])['agents']
self.assertEqual(1, len(network_dhcp_agents)) self.assertEqual(1, len(network_dhcp_agents))
class TestSubnetDeleteRace(BaseDhcpAgentTest):
agent_down_time = 30
number_of_hosts = 2
boot_vm_for_test = False
def setUp(self):
host_descriptions = [
environment.HostDescription(
dhcp_agent=True, l2_agent_type=constants.AGENT_TYPE_OVS),
environment.HostDescription(
dhcp_agent=False,
l2_agent_type=constants.AGENT_TYPE_LINUXBRIDGE)
]
env = environment.Environment(
environment.EnvironmentDescription(
network_type='vlan',
mech_drivers='openvswitch,linuxbridge',
l2_pop=False,
arp_responder=False,
agent_down_time=self.agent_down_time,
service_plugins='router,segments'
),
host_descriptions)
# Note(lajoskatona): Here, call grandparent's (BaseFullStackTestCase)
# setup(), to avoid BaseDhcpAgentTest mess up environment.
super(BaseDhcpAgentTest, self).setUp(env)
self.project_id = uuidutils.generate_uuid()
if self.boot_vm_for_test:
self._create_network_subnet_and_vm()
def test_subnet_delete_race_condition(self):
ovs_physnet = ''
lb_physnet = ''
agents = self.client.list_agents()
for agent in agents['agents']:
if agent['binary'] == 'neutron-openvswitch-agent':
ovs_physnet = list(
agent['configurations']['bridge_mappings'].keys())[0]
if agent['binary'] == 'neutron-linuxbridge-agent':
lb_physnet = list(
agent['configurations']['interface_mappings'].keys())[0]
self.network = self.safe_client.create_network(
tenant_id=self.project_id, network_type='vlan',
segmentation_id=103, physical_network=lb_physnet)
self.segment2 = self.safe_client.create_segment(
project_id=self.project_id, network=self.network['id'],
network_type='vlan', name='segment_2', segmentation_id=103,
physical_network=ovs_physnet)
subnet = self.safe_client.create_subnet(
self.project_id,
self.network['id'],
cidr='10.0.11.0/24',
gateway_ip='10.0.11.1',
name='subnet-test',
enable_dhcp=True)
self.vm = self._spawn_vm()
self.vm.block_until_boot()
self.vm.block_until_dhcp_config_done()
dhcp_ports = self.safe_client.list_ports(**{
'device_owner': 'network:dhcp',
'network_id': self.network['id']
})
self.assertEqual(1, len(dhcp_ports))
self.assertEqual('ACTIVE', dhcp_ports[0]['status'])
port_id = self.vm.neutron_port['id']
self.vm.destroy()
self.client.delete_port(port_id)
dhcp_ports = self.safe_client.list_ports(**{
'device_owner': 'network:dhcp',
'network_id': self.network['id']
})
self.assertEqual(1, len(dhcp_ports))
self.client.delete_subnet(subnet['id'])
def _is_subnet_deleted():
snets = self.safe_client.list_subnets()
if len(snets) == 0:
return True
return False
common_utils.wait_until_true(_is_subnet_deleted)
# Note(lajoskatona): Here cleanup do its job and the cleanup
# will fail if the segment or network deletion is inpossible