]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Add InvalidIpForNetwork and InvalidIpForSubnet exception
authorQin Zhao <chaochin@gmail.com>
Tue, 16 Sep 2014 07:17:44 +0000 (15:17 +0800)
committerQin Zhao <chaochin@gmail.com>
Mon, 2 Mar 2015 07:18:58 +0000 (15:18 +0800)
When posting an 'attach interface' request to Nova with an invalid
ip for defined network, Nova returns an HTTP 500 error. In fact,
Neutron returns 'InvalidInput' error, but Neutron client is not able
to translate this error to a specific exception. So that a general
'BadRequest' exception is thrown. Neutron client and Nova need a more
specific Neutron error type, in order to address and translate the
error in to a proper Nova exception.

APIImpact

Change-Id: Id4d3108234a198c0eb75237ea8991a72bd3cc4bb
Partial-Bug: 1369871

neutron/common/exceptions.py
neutron/db/db_base_plugin_v2.py
neutron/tests/unit/opencontrail/test_contrail_plugin.py
neutron/tests/unit/test_db_plugin.py

index 03f4e077710233605008c078d6130b0e860e74e3..e2b9f7bde4242a4af149e254f534b836e982f47c 100644 (file)
@@ -147,6 +147,16 @@ class DNSNameServersExhausted(BadRequest):
                 "The number of DNS nameservers exceeds the limit %(quota)s.")
 
 
+class InvalidIpForNetwork(BadRequest):
+    message = _("IP address %(ip_address)s is not a valid IP "
+                "for any of the subnets on the specified network.")
+
+
+class InvalidIpForSubnet(BadRequest):
+    message = _("IP address %(ip_address)s is not a valid IP "
+                "for the specified subnet.")
+
+
 class IpAddressInUse(InUse):
     message = _("Unable to complete operation for network %(net_id)s. "
                 "The IP address %(ip_address)s is in use.")
index 03bbe948f1ec888a31214229bfcd84606a8c27ca..2145a86d3410eb22d7b476843b77b5b70f71bf9a 100644 (file)
@@ -358,7 +358,8 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
         IPs. Include the subnet_id in the result if only an IP address is
         configured.
 
-        :raises: InvalidInput, IpAddressInUse
+        :raises: InvalidInput, IpAddressInUse, InvalidIpForNetwork,
+                 InvalidIpForSubnet
         """
         fixed_ip_set = []
         for fixed in fixed_ips:
@@ -377,9 +378,8 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
                         subnet_id = subnet['id']
                         break
                 if not found:
-                    msg = _('IP address %s is not a valid IP for the defined '
-                            'networks subnets') % fixed['ip_address']
-                    raise n_exc.InvalidInput(error_message=msg)
+                    raise n_exc.InvalidIpForNetwork(
+                        ip_address=fixed['ip_address'])
             else:
                 subnet = self._get_subnet(context, fixed['subnet_id'])
                 if subnet['network_id'] != network_id:
@@ -403,9 +403,8 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
                 if (not found and
                     not self._check_subnet_ip(subnet['cidr'],
                                               fixed['ip_address'])):
-                    msg = _('IP address %s is not a valid IP for the defined '
-                            'subnet') % fixed['ip_address']
-                    raise n_exc.InvalidInput(error_message=msg)
+                    raise n_exc.InvalidIpForSubnet(
+                        ip_address=fixed['ip_address'])
                 if (ipv6_utils.is_auto_address_subnet(subnet) and
                     device_owner not in
                         constants.ROUTER_INTERFACE_OWNERS):
index 974fb7b462787515e6dd28c3a9fc2a1966582191..f05407012b8fcb69f496c16f0187dec6dc1db450 100644 (file)
@@ -257,8 +257,15 @@ class TestContrailSubnetsV2(test_plugin.TestSubnetsV2,
 
 class TestContrailPortsV2(test_plugin.TestPortsV2,
                           ContrailPluginTestCase):
-    def setUp(self):
-        super(TestContrailPortsV2, self).setUp()
+    def test_create_port_public_network_with_invalid_ip_no_subnet_id(self):
+        super(TestContrailPortsV2, self). \
+            test_create_port_public_network_with_invalid_ip_no_subnet_id(
+                expected_error='ContrailBadRequestError')
+
+    def test_create_port_public_network_with_invalid_ip_and_subnet_id(self):
+        super(TestContrailPortsV2, self). \
+            test_create_port_public_network_with_invalid_ip_and_subnet_id(
+                expected_error='ContrailBadRequestError')
 
     def test_delete_ports_by_device_id(self):
         self.skipTest("This method tests rpc API of "
index ae88c86a024ba0a0aedff3d40b47965276fdf580..b5dd98fd7ad82aac7175ab67e3b49e71881d6b3d 100644 (file)
@@ -853,6 +853,37 @@ class TestPortsV2(NeutronDbPluginV2TestCase):
                 self.assertIn('mac_address', port['port'])
                 self._delete('ports', port['port']['id'])
 
+    def test_create_port_public_network_with_invalid_ip_no_subnet_id(self,
+            expected_error='InvalidIpForNetwork'):
+        with self.network(shared=True) as network:
+            with self.subnet(network=network, cidr='10.0.0.0/24'):
+                ips = [{'ip_address': '1.1.1.1'}]
+                res = self._create_port(self.fmt,
+                                        network['network']['id'],
+                                        webob.exc.HTTPBadRequest.code,
+                                        fixed_ips=ips,
+                                        set_context=True)
+                data = self.deserialize(self.fmt, res)
+                msg = str(n_exc.InvalidIpForNetwork(ip_address='1.1.1.1'))
+                self.assertEqual(expected_error, data['NeutronError']['type'])
+                self.assertEqual(msg, data['NeutronError']['message'])
+
+    def test_create_port_public_network_with_invalid_ip_and_subnet_id(self,
+            expected_error='InvalidIpForSubnet'):
+        with self.network(shared=True) as network:
+            with self.subnet(network=network, cidr='10.0.0.0/24') as subnet:
+                ips = [{'subnet_id': subnet['subnet']['id'],
+                        'ip_address': '1.1.1.1'}]
+                res = self._create_port(self.fmt,
+                                        network['network']['id'],
+                                        webob.exc.HTTPBadRequest.code,
+                                        fixed_ips=ips,
+                                        set_context=True)
+                data = self.deserialize(self.fmt, res)
+                msg = str(n_exc.InvalidIpForSubnet(ip_address='1.1.1.1'))
+                self.assertEqual(expected_error, data['NeutronError']['type'])
+                self.assertEqual(msg, data['NeutronError']['message'])
+
     def test_create_ports_bulk_native(self):
         if self._skip_native_bulk:
             self.skipTest("Plugin does not support native bulk port create")