From: gong yong sheng Date: Mon, 6 Jul 2015 12:47:25 +0000 (+0800) Subject: Create fip on subnet id X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=e5e5f7a281fd89c06d65da3a6d3a1fe194647432;p=openstack-build%2Fneutron-build.git Create fip on subnet id If there are multiple subnets in the external networks, users can expect to create a floatingip on a specific subnet on which the quality or cost is maybe different than other ones. This patch allows users to create floating ip on specified subnet. DocImpact APIImpact Change-Id: I7a3c27c1d0d2685e31201f1eac6ec74dfb96b279 Closes-Bug: #1468175 --- diff --git a/neutron/db/l3_db.py b/neutron/db/l3_db.py index e8e16275b..c48bcf460 100644 --- a/neutron/db/l3_db.py +++ b/neutron/db/l3_db.py @@ -963,6 +963,9 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase): port['fixed_ips'] = [ {'ip_address': fip['floating_ip_address']}] + if fip.get('subnet_id'): + port['fixed_ips'] = [ + {'subnet_id': fip['subnet_id']}] external_port = self._core_plugin.create_port(context.elevated(), {'port': port}) diff --git a/neutron/extensions/l3.py b/neutron/extensions/l3.py index bcbe15a62..ea1652da1 100644 --- a/neutron/extensions/l3.py +++ b/neutron/extensions/l3.py @@ -124,6 +124,10 @@ RESOURCE_ATTRIBUTE_MAP = { 'validate': {'type:ip_address_or_none': None}, 'is_visible': True, 'default': None, 'enforce_policy': True}, + 'subnet_id': {'allow_post': True, 'allow_put': False, + 'validate': {'type:uuid_or_none': None}, + 'is_visible': False, # Use False for input only attr + 'default': None}, 'floating_network_id': {'allow_post': True, 'allow_put': False, 'validate': {'type:uuid': None}, 'is_visible': True}, diff --git a/neutron/tests/unit/extensions/test_l3.py b/neutron/tests/unit/extensions/test_l3.py index 143c34869..8c6256184 100644 --- a/neutron/tests/unit/extensions/test_l3.py +++ b/neutron/tests/unit/extensions/test_l3.py @@ -408,7 +408,7 @@ class L3NatTestCaseMixin(object): def _create_floatingip(self, fmt, network_id, port_id=None, fixed_ip=None, set_context=False, - floating_ip=None): + floating_ip=None, subnet_id=False): data = {'floatingip': {'floating_network_id': network_id, 'tenant_id': self._tenant_id}} if port_id: @@ -419,6 +419,8 @@ class L3NatTestCaseMixin(object): if floating_ip: data['floatingip']['floating_ip_address'] = floating_ip + if subnet_id: + data['floatingip']['subnet_id'] = subnet_id floatingip_req = self.new_create_request('floatingips', data, fmt) if set_context and self._tenant_id: # create a specific auth context for this request @@ -2099,6 +2101,52 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): self._test_floatingip_with_invalid_create_port( 'neutron.db.db_base_plugin_v2.NeutronDbPluginV2') + def test_create_floatingip_with_subnet_id_non_admin(self): + with self.subnet() as public_sub: + self._set_net_external(public_sub['subnet']['network_id']) + with self.router(): + res = self._create_floatingip( + self.fmt, + public_sub['subnet']['network_id'], + subnet_id=public_sub['subnet']['id'], + set_context=True) + self.assertEqual(res.status_int, exc.HTTPCreated.code) + + def test_create_floatingip_with_multisubnet_id(self): + with self.network() as network: + self._set_net_external(network['network']['id']) + with self.subnet(network, cidr='10.0.12.0/24') as subnet1: + with self.subnet(network, cidr='10.0.13.0/24') as subnet2: + with self.router(): + res = self._create_floatingip( + self.fmt, + subnet1['subnet']['network_id'], + subnet_id=subnet1['subnet']['id']) + fip1 = self.deserialize(self.fmt, res) + res = self._create_floatingip( + self.fmt, + subnet1['subnet']['network_id'], + subnet_id=subnet2['subnet']['id']) + fip2 = self.deserialize(self.fmt, res) + self.assertTrue( + fip1['floatingip']['floating_ip_address'].startswith('10.0.12')) + self.assertTrue( + fip2['floatingip']['floating_ip_address'].startswith('10.0.13')) + + def test_create_floatingip_with_wrong_subnet_id(self): + with self.network() as network1: + self._set_net_external(network1['network']['id']) + with self.subnet(network1, cidr='10.0.12.0/24') as subnet1: + with self.network() as network2: + self._set_net_external(network2['network']['id']) + with self.subnet(network2, cidr='10.0.13.0/24') as subnet2: + with self.router(): + res = self._create_floatingip( + self.fmt, + subnet1['subnet']['network_id'], + subnet_id=subnet2['subnet']['id']) + self.assertEqual(res.status_int, exc.HTTPBadRequest.code) + def test_create_floatingip_no_ext_gateway_return_404(self): with self.subnet() as public_sub: self._set_net_external(public_sub['subnet']['network_id'])