diff --git a/nova/api/openstack/compute/floating_ips.py b/nova/api/openstack/compute/floating_ips.py index d8c73de38b..616155bcbc 100644 --- a/nova/api/openstack/compute/floating_ips.py +++ b/nova/api/openstack/compute/floating_ips.py @@ -42,21 +42,21 @@ def _translate_floating_ip_view(floating_ip): return { 'floating_ip': { - 'id': floating_ip['id'], - 'ip': floating_ip['floating_ip_address'], - 'pool': floating_ip['network_details']['name'] or ( - floating_ip['network_details']['id']), 'fixed_ip': floating_ip['fixed_ip_address'], + 'id': floating_ip['id'], 'instance_id': instance_id, + 'ip': floating_ip['floating_ip_address'], + 'pool': ( + floating_ip['network_details']['name'] or + floating_ip['network_details']['id']), } } def get_instance_by_floating_ip_addr(self, context, address): try: - instance_id =\ - self.network_api.get_instance_id_by_floating_address( - context, address) + instance_id = self.network_api.get_instance_id_by_floating_address( + context, address) except exception.FloatingIpNotFoundForAddress as ex: raise webob.exc.HTTPNotFound(explanation=ex.format_message()) except exception.FloatingIpMultipleFoundForAddress as ex: @@ -74,6 +74,7 @@ def disassociate_floating_ip(self, context, instance, address): raise webob.exc.HTTPForbidden() +@validation.validated class FloatingIPController(wsgi.Controller): """The Floating IPs API controller for the OpenStack API.""" @@ -85,6 +86,7 @@ class FloatingIPController(wsgi.Controller): @wsgi.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION) @wsgi.expected_errors((400, 404)) @validation.query_schema(schema.show_query) + @validation.response_body_schema(schema.show_response) def show(self, req, id): """Return data about the given floating IP.""" context = req.environ['nova.context'] @@ -104,6 +106,7 @@ class FloatingIPController(wsgi.Controller): @wsgi.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION) @wsgi.expected_errors(()) @validation.query_schema(schema.index_query) + @validation.response_body_schema(schema.index_response) def index(self, req): """Return a list of floating IPs allocated to a project.""" context = req.environ['nova.context'] @@ -118,6 +121,7 @@ class FloatingIPController(wsgi.Controller): @wsgi.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION) @wsgi.expected_errors((400, 403, 404)) @validation.schema(schema.create) + @validation.response_body_schema(schema.create_response) def create(self, req, body=None): context = req.environ['nova.context'] context.can(fi_policies.BASE_POLICY_NAME % 'create', @@ -151,6 +155,7 @@ class FloatingIPController(wsgi.Controller): @wsgi.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION) @wsgi.response(202) @wsgi.expected_errors((400, 403, 404, 409)) + @validation.response_body_schema(schema.delete_response) def delete(self, req, id): context = req.environ['nova.context'] context.can(fi_policies.BASE_POLICY_NAME % 'delete', diff --git a/nova/api/openstack/compute/schemas/floating_ips.py b/nova/api/openstack/compute/schemas/floating_ips.py index f2996315f3..b7bf06e069 100644 --- a/nova/api/openstack/compute/schemas/floating_ips.py +++ b/nova/api/openstack/compute/schemas/floating_ips.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +import copy from nova.api.validation import parameter_types @@ -62,6 +63,50 @@ remove_floating_ip = { show_query = {} index_query = {} +_floating_ip_response = { + 'type': 'object', + 'properties': { + 'fixed_ip': { + 'type': ['string', 'null'], + 'anyOf': [{'format': 'ipv4'}, {'format': 'ipv6'}], + }, + 'id': {'type': 'string', 'format': 'uuid'}, + 'instance_id': {'type': ['string', 'null'], 'format': 'uuid'}, + 'ip': { + 'type': 'string', + 'anyOf': [{'format': 'ipv4'}, {'format': 'ipv6'}], + }, + 'pool': {'type': 'string'}, + }, + 'required': ['fixed_ip', 'id', 'instance_id', 'ip', 'pool'], + 'additionalProperties': False +} + +show_response = { + 'type': 'object', + 'properties': { + 'floating_ip': _floating_ip_response, + }, + 'required': ['floating_ip'], + 'additionalProperties': False, +} + +index_response = { + 'type': 'object', + 'properties': { + 'floating_ips': { + 'type': 'array', + 'items': _floating_ip_response, + }, + }, + 'required': ['floating_ips'], + 'additionalProperties': False, +} + +create_response = copy.deepcopy(show_response) + +delete_response = {'type': 'null'} + add_floating_ip_response = { 'type': 'null', } diff --git a/nova/tests/unit/policies/test_floating_ips.py b/nova/tests/unit/policies/test_floating_ips.py index 1ed4ceaa18..28fc8d44a9 100644 --- a/nova/tests/unit/policies/test_floating_ips.py +++ b/nova/tests/unit/policies/test_floating_ips.py @@ -91,6 +91,13 @@ class FloatingIPPolicyTest(base.BasePolicyTest): @mock.patch('nova.network.neutron.API.get_floating_ip') def test_show_floating_ip_policy(self, mock_get): + mock_get.return_value = { + 'fixed_ip_address': None, + 'floating_ip_address': '172.16.22.3', + 'id': uuids.floating_ip_id, + 'network_details': {'name': 'public'}, + 'port_details': None, + } rule_name = "os_compute_api:os-floating-ips:show" self.common_policy_auth(self.project_reader_authorized_contexts, rule_name, self.controller.show, @@ -106,6 +113,13 @@ class FloatingIPPolicyTest(base.BasePolicyTest): @mock.patch('nova.network.neutron.API.get_floating_ip_by_address') @mock.patch('nova.network.neutron.API.allocate_floating_ip') def test_create_floating_ip_policy(self, mock_create, mock_get): + mock_get.return_value = { + 'fixed_ip_address': None, + 'floating_ip_address': '172.16.22.3', + 'id': uuids.floating_ip_id, + 'network_details': {'name': 'public'}, + 'port_details': None, + } rule_name = "os_compute_api:os-floating-ips:create" self.common_policy_auth(self.member_authorized_contexts, rule_name, self.controller.create,