Local FIP not created after central FIP creation
1. What is the problem After booting a VM, we associate a FIP to it via central Neutron. However, local FIP is not created as expected. Also, there is no related asynchronous job registered. The reason may be that we don't trigger asynchronous job in "create_floatingip" method, and since VM is already there, there's no chance to trigger the job. 2. What is the solution for the problem If "port_id" is specified in the body, trigger asynchronous job. 3. What features need to be implemented to the Tricircle to realize the solution Support creating FIP with "port_id" specified. Change-Id: Iceb15f68acc23f8dcb8767ac0371947334a1e9db Closes-Bug: #1691918
This commit is contained in:
parent
9bffb43330
commit
9897c65a26
|
@ -1733,10 +1733,35 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||
return return_info
|
||||
|
||||
def create_floatingip(self, context, floatingip):
|
||||
# create bottom fip when associating fixed ip
|
||||
return super(TricirclePlugin, self).create_floatingip(
|
||||
context, floatingip,
|
||||
initial_status=constants.FLOATINGIP_STATUS_DOWN)
|
||||
fip = None
|
||||
t_ctx = t_context.get_context_from_neutron_context(context)
|
||||
try:
|
||||
fip = super(TricirclePlugin, self).create_floatingip(
|
||||
context, floatingip,
|
||||
initial_status=constants.FLOATINGIP_STATUS_DOWN)
|
||||
if fip['router_id'] and fip['port_id']:
|
||||
mappings = db_api.get_bottom_mappings_by_top_id(
|
||||
t_ctx, fip['port_id'], t_constants.RT_PORT)
|
||||
if not mappings:
|
||||
# mapping does not exist, meaning that the bottom port has
|
||||
# not been created, we just return and defer the work to
|
||||
# setup bottom floating ip until vm creation
|
||||
return
|
||||
|
||||
int_net_pod, b_int_port_id = mappings[0]
|
||||
int_port = self.get_port(context, fip['port_id'])
|
||||
net_id = int_port['network_id']
|
||||
router = self._get_router(context, fip['router_id'])
|
||||
self.xjob_handler.setup_bottom_router(
|
||||
t_ctx, router['tenant_id'], net_id,
|
||||
fip['router_id'], int_net_pod['pod_id'])
|
||||
return fip
|
||||
except Exception:
|
||||
if fip:
|
||||
# if we fail to register the job, delete the fip
|
||||
super(TricirclePlugin, self).delete_floatingip(context,
|
||||
fip['id'])
|
||||
raise
|
||||
|
||||
def remove_router_interface(self, context, router_id, interface_info):
|
||||
t_ctx = t_context.get_context_from_neutron_context(context)
|
||||
|
@ -1875,8 +1900,8 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||
t_ctx, int_port_id, t_constants.RT_PORT)
|
||||
if not mappings:
|
||||
# mapping does not exist, meaning that the bottom port has not
|
||||
# been created, we just return and leave the work to setup bottom
|
||||
# floating ip to nova api gateway
|
||||
# been created, we just return and defer the work to setup bottom
|
||||
# floating ip until vm creation
|
||||
return
|
||||
|
||||
int_net_pod, b_int_port_id = mappings[0]
|
||||
|
|
|
@ -29,7 +29,8 @@ echo create router
|
|||
router_id=$($openstacktop router create router -c id -f value)
|
||||
|
||||
echo attach router to external network
|
||||
$openstacktop router set --external-gateway ext-net router
|
||||
$openstacktop router set --external-gateway ext-net \
|
||||
--fixed-ip subnet=ext-subnet,ip-address=163.3.124.10 router
|
||||
|
||||
echo create network1
|
||||
$openstacktop network create net1
|
||||
|
@ -52,7 +53,7 @@ echo attach subnet1 to router
|
|||
$openstacktop router add subnet router subnet1
|
||||
|
||||
echo associate floating ip to port1
|
||||
$openstacktop floating ip create --port $port1_id ext-net -c id -f value
|
||||
$openstacktop floating ip create --port $port1_id --floating-ip-address 163.3.124.15 ext-net -c id -f value
|
||||
|
||||
image1_id=$($openstackpod1 image list -c ID -f value)
|
||||
|
||||
|
@ -60,15 +61,18 @@ echo create server1
|
|||
$openstackpod1 server create --flavor 1 --image $image1_id --nic port-id=$port1_id vm1
|
||||
|
||||
echo create network2
|
||||
net2_id=$($openstacktop network create net2 -c id -f value)
|
||||
$openstacktop network create net2
|
||||
|
||||
echo create subnet2
|
||||
$openstacktop subnet create --subnet-range 10.0.2.0/24 --network net2 subnet2
|
||||
|
||||
echo create port2
|
||||
port2_id=$($openstacktop port create --network net2 port2 -c id -f value)
|
||||
|
||||
image2_id=$($openstackpod2 image list -c ID -f value)
|
||||
|
||||
echo create server2
|
||||
$openstackpod2 server create --flavor 1 --image $image2_id --nic net-id=$net2_id vm2
|
||||
$openstackpod2 server create --flavor 1 --image $image2_id --nic port-id=$port2_id vm2
|
||||
|
||||
echo attach subnet2 to router
|
||||
$openstacktop router add subnet router subnet2
|
||||
|
@ -83,6 +87,11 @@ $openstacktop subnet create --subnet-range 10.0.4.0/24 --network net4 \
|
|||
echo create server3
|
||||
$openstackpod1 server create --flavor 1 --image $image1_id --nic net-id=$net4_id vm3
|
||||
|
||||
sleep 10
|
||||
|
||||
echo associate floating ip to port2
|
||||
$openstacktop floating ip create --port $port2_id --floating-ip-address 163.3.124.20 ext-net -c id -f value
|
||||
|
||||
sleep 20
|
||||
|
||||
TOP_DIR=$DEVSTACK_DIR
|
||||
|
@ -171,3 +180,7 @@ $openstackpod2 router show $router_id -c routes -f json | python smoke_test_vali
|
|||
if [ $? != 0 ]; then
|
||||
die $LINENO "Smoke test fails, error in router of RegionTwo"
|
||||
fi
|
||||
$openstackpod2 floating ip list -f json | python smoke_test_validation.py fip 2
|
||||
if [ $? != 0 ]; then
|
||||
die $LINENO "Smoke test fails, error in fip of RegionTwo"
|
||||
fi
|
||||
|
|
|
@ -48,7 +48,9 @@ CONDITIONS = {
|
|||
'router': [
|
||||
{'routes': ContainedString(
|
||||
"destination='0.0.0.0/0', gateway='100.0.0.1'")},
|
||||
{'routes': ContainedString("destination='10.0.1")}]}
|
||||
{'routes': ContainedString("destination='10.0.1")}],
|
||||
'fip': [{'Floating IP Address': '163.3.124.15'},
|
||||
{'Floating IP Address': '163.3.124.20'}]}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -478,31 +478,39 @@ class FakeClient(test_utils.FakeClient):
|
|||
pass
|
||||
|
||||
|
||||
def update_floatingip_dict(fip_dict, update_dict):
|
||||
if not update_dict.get('port_id'):
|
||||
update_dict['fixed_port_id'] = None
|
||||
update_dict['fixed_ip_address'] = None
|
||||
update_dict['router_id'] = None
|
||||
fip_dict.update(update_dict)
|
||||
return fip_dict
|
||||
for port in TOP_PORTS:
|
||||
if port['id'] != update_dict['port_id']:
|
||||
continue
|
||||
update_dict['fixed_port_id'] = port['id']
|
||||
update_dict[
|
||||
'fixed_ip_address'] = port['fixed_ips'][0]['ip_address']
|
||||
for router_port in TOP_ROUTERPORTS:
|
||||
for _port in TOP_PORTS:
|
||||
if _port['id'] != router_port['port_id']:
|
||||
continue
|
||||
if _port['network_id'] == port['network_id']:
|
||||
update_dict['router_id'] = router_port['router_id']
|
||||
|
||||
fip_dict.update(update_dict)
|
||||
return fip_dict
|
||||
|
||||
|
||||
def update_floatingip(self, context, _id, floatingip):
|
||||
for fip in TOP_FLOATINGIPS:
|
||||
if fip['id'] != _id:
|
||||
continue
|
||||
update_dict = floatingip['floatingip']
|
||||
if not floatingip['floatingip']['port_id']:
|
||||
update_dict['fixed_port_id'] = None
|
||||
update_dict['fixed_ip_address'] = None
|
||||
update_dict['router_id'] = None
|
||||
fip.update(update_dict)
|
||||
return
|
||||
for port in TOP_PORTS:
|
||||
if port['id'] != floatingip['floatingip']['port_id']:
|
||||
continue
|
||||
update_dict['fixed_port_id'] = port['id']
|
||||
update_dict[
|
||||
'fixed_ip_address'] = port['fixed_ips'][0]['ip_address']
|
||||
for router_port in TOP_ROUTERPORTS:
|
||||
for _port in TOP_PORTS:
|
||||
if _port['id'] != router_port['port_id']:
|
||||
continue
|
||||
if _port['network_id'] == port['network_id']:
|
||||
update_dict['router_id'] = router_port['router_id']
|
||||
update_floatingip_dict(fip, floatingip['floatingip'])
|
||||
|
||||
fip.update(update_dict)
|
||||
|
||||
def _update_fip_assoc(self, context, fip, floatingip_db, external_port):
|
||||
return update_floatingip_dict(floatingip_db, fip)
|
||||
|
||||
|
||||
class FakeBaseXManager(xmanager.XManager):
|
||||
|
@ -2935,6 +2943,44 @@ class PluginTest(unittest.TestCase,
|
|||
|
||||
return t_port_id, b_port_id, fip, e_net
|
||||
|
||||
@patch.object(directory, 'get_plugin', new=fake_get_plugin)
|
||||
@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(l3_db.L3_NAT_dbonly_mixin, '_make_router_dict',
|
||||
new=fake_make_router_dict)
|
||||
@patch.object(db_base_plugin_common.DbBasePluginCommon,
|
||||
'_make_subnet_dict', new=fake_make_subnet_dict)
|
||||
@patch.object(l3_db.L3_NAT_dbonly_mixin, '_update_fip_assoc',
|
||||
new=_update_fip_assoc)
|
||||
@patch.object(FakeClient, 'create_floatingips')
|
||||
@patch.object(context, 'get_context_from_neutron_context')
|
||||
def test_create_floatingip(self, mock_context, mock_create):
|
||||
fake_plugin = FakePlugin()
|
||||
q_ctx = FakeNeutronContext()
|
||||
t_ctx = context.get_db_context()
|
||||
mock_context.return_value = t_ctx
|
||||
|
||||
(t_port_id, b_port_id,
|
||||
_, e_net) = self._prepare_associate_floatingip_test(t_ctx, q_ctx,
|
||||
fake_plugin)
|
||||
# in _prepare_associate_floatingip_test, we have created an empty fip,
|
||||
# but here we just ignore it and create a new fip by specifying fix ip
|
||||
# at the same time
|
||||
fip_body = {'floating_network_id': e_net['id'],
|
||||
'port_id': t_port_id,
|
||||
'tenant_id': TEST_TENANT_ID}
|
||||
fip = fake_plugin.create_floatingip(q_ctx, {'floatingip': fip_body})
|
||||
b_ext_net_id = db_api.get_bottom_id_by_top_id_region_name(
|
||||
t_ctx, e_net['id'], 'pod_2', constants.RT_NETWORK)
|
||||
calls = [mock.call(t_ctx,
|
||||
{'floatingip': {
|
||||
'floating_network_id': b_ext_net_id,
|
||||
'floating_ip_address': fip[
|
||||
'floating_ip_address'],
|
||||
'port_id': b_port_id}})]
|
||||
mock_create.assert_has_calls(calls)
|
||||
|
||||
@patch.object(directory, 'get_plugin', new=fake_get_plugin)
|
||||
@patch.object(driver.Pool, 'get_instance', new=fake_get_instance)
|
||||
@patch.object(ipam_pluggable_backend.IpamPluggableBackend,
|
||||
|
|
Loading…
Reference in New Issue