Merge "Implement router interface deletion"

This commit is contained in:
Jenkins 2016-05-05 02:56:12 +00:00 committed by Gerrit Code Review
commit 7961f642ea
2 changed files with 87 additions and 5 deletions

View File

@ -305,7 +305,7 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
super(TricirclePlugin, self).delete_subnet(context, subnet_id)
def update_subnet(self, context, subnet_id, subnet):
return super(TricirclePlugin, self).update_network(
return super(TricirclePlugin, self).update_subnet(
context, subnet_id, subnet)
def create_port(self, context, port):
@ -1123,10 +1123,6 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
context, router_id, interface_info)
raise
# TODO(zhiyuan) improve reliability
# this is a casting rpc, so no guarantee that this operation will
# success, find out a way to improve reliability, like introducing
# job mechanism for async operations
self.xjob_handler.configure_extra_routes(t_ctx, router_id)
return return_info
@ -1136,6 +1132,56 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
context, floatingip,
initial_status=constants.FLOATINGIP_STATUS_DOWN)
def remove_router_interface(self, context, router_id, interface_info):
t_ctx = t_context.get_context_from_neutron_context(context)
router = self._get_router(context, router_id)
project_id = router['tenant_id']
add_by_port, _ = self._validate_interface_info(interface_info,
for_removal=True)
# make sure network not crosses pods
# TODO(zhiyuan) support cross-pod tenant network
az, t_net = self._judge_network_across_pods(
context, interface_info, add_by_port)
b_pod, b_az = az_ag.get_pod_by_az_tenant(t_ctx, az, project_id)
b_router_id = db_api.get_bottom_id_by_top_id_pod_name(
t_ctx, router_id, b_pod['pod_name'], t_constants.RT_ROUTER)
handle_bottom = b_router_id is not None
if add_by_port:
t_port_id = interface_info['port_id']
b_port_id = db_api.get_bottom_id_by_top_id_pod_name(
t_ctx, t_port_id, b_pod['pod_name'], t_constants.RT_PORT)
request_body = {'port_id': b_port_id}
handle_bottom = handle_bottom and (b_port_id is not None)
else:
t_subnet_id = interface_info['subnet_id']
b_subnet_id = db_api.get_bottom_id_by_top_id_pod_name(
t_ctx, t_subnet_id, b_pod['pod_name'], t_constants.RT_SUBNET)
request_body = {'subnet_id': b_subnet_id}
handle_bottom = handle_bottom and (b_subnet_id is not None)
if handle_bottom:
b_client = self._get_client(b_pod['pod_name'])
try:
b_client.action_routers(t_ctx, 'remove_interface', b_router_id,
request_body)
except Exception as e:
if hasattr(e, 'status_code') and e.status_code == 404:
# Note(zhiyuan) we get a 404 error from client, the
# possible reason is that router/subnet/port doesn't exist
# in bottom pod, in this case, no need to remove bottom
# interface, we just continue to remove top interface.
pass
else:
raise
return_info = super(TricirclePlugin, self).remove_router_interface(
context, router_id, interface_info)
if handle_bottom:
self.xjob_handler.configure_extra_routes(t_ctx, router_id)
return return_info
@staticmethod
def _safe_create_bottom_floatingip(t_ctx, client, fip_net_id,
fip_address, port_id):

View File

@ -1378,6 +1378,42 @@ class PluginTest(unittest.TestCase,
# bottom interface and bridge port
self.assertEqual(2, len(BOTTOM1_PORTS))
@patch.object(ipam_non_pluggable_backend.IpamNonPluggableBackend,
'_allocate_specific_ip', new=_allocate_specific_ip)
@patch.object(ipam_non_pluggable_backend.IpamNonPluggableBackend,
'_generate_ip', new=fake_generate_ip)
@patch.object(db_base_plugin_common.DbBasePluginCommon,
'_make_subnet_dict', new=fake_make_subnet_dict)
@patch.object(subnet_alloc.SubnetAllocator, '_lock_subnetpool',
new=mock.Mock)
@patch.object(FakeRPCAPI, 'configure_extra_routes')
@patch.object(FakeClient, 'action_routers')
@patch.object(context, 'get_context_from_neutron_context')
def test_remove_interface(self, mock_context, mock_action, mock_rpc):
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 = self._prepare_router_test(
tenant_id)
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]
_, b_port_id = db_api.get_bottom_mappings_by_top_id(
t_ctx, t_port_id, constants.RT_PORT)[0]
fake_plugin.remove_router_interface(
q_ctx, t_router_id, {'port_id': t_port_id})
mock_action.assert_called_with(
t_ctx, 'remove_interface', b_router_id, {'port_id': b_port_id})
mock_rpc.assert_called_with(t_ctx, t_router_id)
@patch.object(context, 'get_context_from_neutron_context')
def test_create_external_network(self, mock_context):
plugin_path = 'tricircle.tests.unit.network.test_plugin.FakePlugin'