]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Create fip on subnet id
authorgong yong sheng <gong.yongsheng@99cloud.net>
Mon, 6 Jul 2015 12:47:25 +0000 (20:47 +0800)
committergong yong sheng <gong.yongsheng@99cloud.net>
Fri, 24 Jul 2015 02:39:25 +0000 (10:39 +0800)
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

neutron/db/l3_db.py
neutron/extensions/l3.py
neutron/tests/unit/extensions/test_l3.py

index e8e16275bae7f5496358491c237c78e37875835c..c48bcf4609057683bb8a17622ae0905945b16163 100644 (file)
@@ -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})
 
index bcbe15a62e4304c077188532b3bada40d9e3b000..ea1652da1a18b09fa6fb41f093343c33d693fd0d 100644 (file)
@@ -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},
index 143c34869e72936f7a19e06839a52080544a5853..8c6256184d5c33d1750a1bb88944a28db5cb4ecc 100644 (file)
@@ -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'])