Pre-created port clean during subnet deletion

1. What is the problem
Before creating bottom subnet, we need to create some ports to
allocate ip address for bottom dhcp port and bottom gateway port.
These pre-created ports are not deleted after bottom resources
are deleted.

2. What is the solution to the problem
Clean these pre-created ports during top subnet deletion.

3. What the features need to be implemented to the Tricircle
   to realize the solution
Pre-created ports now can be cleaned up.

Change-Id: I73c0ef87e4104f1db9926a5972c5f36be94d724a
This commit is contained in:
zhiyuan_cai 2016-08-15 09:29:24 +08:00
parent 85df9c9c5f
commit a0482b8eb6
3 changed files with 84 additions and 13 deletions

View File

@ -121,6 +121,21 @@ def get_bottom_mappings_by_top_id(context, top_id, resource_type):
return mappings
def delete_pre_created_resource_mapping(context, name):
with context.session.begin():
entries = core.query_resource(
context, models.ResourceRouting,
filters=[{'key': 'top_id', 'comparator': 'eq',
'value': name}], sorts=[])
if entries:
core.delete_resources(
context, models.ResourceRouting,
filters=[{'key': 'top_id', 'comparator': 'eq',
'value': entries[0]['bottom_id']}])
core.delete_resource(context, models.ResourceRouting,
entries[0]['id'])
def get_bottom_id_by_top_id_pod_name(context, top_id, pod_name, resource_type):
"""Get resource bottom id by top id and bottom pod name

View File

@ -335,6 +335,13 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
context, res, network, res['id'])
return res
def _delete_pre_created_port(self, t_ctx, q_ctx, port_name):
ports = super(TricirclePlugin, self).get_ports(
q_ctx, {'name': [port_name]})
if ports:
super(TricirclePlugin, self).delete_port(q_ctx, ports[0]['id'])
db_api.delete_pre_created_resource_mapping(t_ctx, port_name)
def delete_subnet(self, context, subnet_id):
t_ctx = t_context.get_context_from_neutron_context(context)
try:
@ -345,6 +352,9 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
bottom_subnet_id = mapping[1]
self._get_client(pod_name).delete_subnets(
t_ctx, bottom_subnet_id)
interface_name = t_constants.interface_port_name % (
mapping[0]['pod_id'], subnet_id)
self._delete_pre_created_port(t_ctx, context, interface_name)
with t_ctx.session.begin():
core.delete_resources(
t_ctx, models.ResourceRouting,
@ -354,6 +364,8 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
'value': mapping[0]['pod_id']}])
except Exception:
raise
dhcp_port_name = t_constants.dhcp_port_name % subnet_id
self._delete_pre_created_port(t_ctx, context, dhcp_port_name)
super(TricirclePlugin, self).delete_subnet(context, subnet_id)
def update_subnet(self, context, subnet_id, subnet):

View File

@ -341,6 +341,18 @@ class FakeClient(object):
ret_list.append(res)
return ret_list
def delete_resources(self, _type, ctx, _id):
index = -1
if self.pod_name == 'top':
res_list = self._res_map[self.pod_name][_type + 's']
else:
res_list = self._res_map[self.pod_name][_type]
for i, res in enumerate(res_list):
if res['id'] == _id:
index = i
if index != -1:
del res_list[index]
def list_networks(self, ctx, filters=None):
networks = self.list_resources('network', ctx, filters)
if self.pod_name != 'top':
@ -363,6 +375,9 @@ class FakeClient(object):
'comparator': 'eq',
'value': subnet_id}])[0]
def delete_subnets(self, ctx, subnet_id):
self.delete_resources('subnet', ctx, subnet_id)
def update_subnets(self, ctx, subnet_id, body):
pass
@ -383,16 +398,7 @@ class FakeClient(object):
'', params={'filters': {'id': [port_id]}})['ports'][0]
def delete_ports(self, ctx, port_id):
index = -1
if self.pod_name == 'top':
port_list = self._res_map[self.pod_name]['ports']
else:
port_list = self._res_map[self.pod_name]['port']
for i, port in enumerate(port_list):
if port['id'] == port_id:
index = i
if index != -1:
del port_list[index]
self.delete_resources('port', ctx, port_id)
def add_gateway_routers(self, ctx, *args, **kwargs):
# only for mock purpose
@ -797,7 +803,7 @@ class FakeSession(object):
RES_MAP[model_obj.__tablename__].append(model_dict)
def _cascade_delete(self, model_dict, foreign_key, table, key):
if foreign_key not in model_dict:
if key not in model_dict:
return
index = -1
for i, instance in enumerate(RES_MAP[table]):
@ -1383,6 +1389,46 @@ class PluginTest(unittest.TestCase,
return t_net_id, t_subnet_id, t_router_id, b_net_id, b_subnet_id
@patch.object(driver.Pool, 'get_instance', new=fake_get_instance)
@patch.object(ipam_pluggable_backend.IpamPluggableBackend,
'_allocate_ips_for_port', new=fake_allocate_ips_for_port)
@patch.object(db_base_plugin_common.DbBasePluginCommon,
'_make_subnet_dict', new=fake_make_subnet_dict)
@patch.object(context, 'get_context_from_neutron_context')
def test_subnet_clean(self, mock_context):
self._basic_pod_route_setup()
fake_plugin = FakePlugin()
q_ctx = FakeNeutronContext()
t_ctx = context.get_db_context()
mock_context.return_value = t_ctx
tenant_id = 'test_tenant_id'
(t_net_id, t_subnet_id,
t_router_id, b_net_id, b_subnet_id) = self._prepare_router_test(
tenant_id, t_ctx, 'pod_1', 1)
t_port_id = fake_plugin.add_router_interface(
q_ctx, t_router_id, {'subnet_id': t_subnet_id})['port_id']
_, b_router_id = db_api.get_bottom_mappings_by_top_id(
t_ctx, t_router_id, constants.RT_ROUTER)[0]
port_num = len(TOP_PORTS)
pre_created_port_num = 0
for port in TOP_PORTS:
if port.get('name').startswith('dhcp_port_'):
pre_created_port_num += 1
elif port.get('name').startswith('interface_'):
pre_created_port_num += 1
elif port.get('device_owner') == 'network:router_interface':
pre_created_port_num += 1
fake_plugin.remove_router_interface(
q_ctx, t_router_id, {'port_id': t_port_id})
fake_plugin.delete_subnet(q_ctx, t_subnet_id)
# check pre-created ports are all deleted
self.assertEqual(port_num - pre_created_port_num, len(TOP_PORTS))
@patch.object(driver.Pool, 'get_instance', new=fake_get_instance)
@patch.object(ipam_pluggable_backend.IpamPluggableBackend,
'_allocate_ips_for_port', new=fake_allocate_ips_for_port)
@ -1591,7 +1637,6 @@ class PluginTest(unittest.TestCase,
'_allocate_ips_for_port', new=fake_allocate_ips_for_port)
@patch.object(db_base_plugin_common.DbBasePluginCommon,
'_make_subnet_dict', new=fake_make_subnet_dict)
@patch.object(FakeRPCAPI, 'configure_extra_routes', new=mock.Mock)
@patch.object(FakeClient, 'action_routers')
@patch.object(context, 'get_context_from_neutron_context')
def test_add_interface_exception(self, mock_context, mock_action):
@ -1649,7 +1694,6 @@ class PluginTest(unittest.TestCase,
'_allocate_ips_for_port', new=fake_allocate_ips_for_port)
@patch.object(db_base_plugin_common.DbBasePluginCommon,
'_make_subnet_dict', new=fake_make_subnet_dict)
@patch.object(FakeBaseRPCAPI, 'configure_extra_routes', new=mock.Mock)
@patch.object(FakeClient, '_get_connection')
@patch.object(context, 'get_context_from_neutron_context')
def test_add_interface_exception_port_left(self, mock_context,