vmware-nsx/quantum/api/api_common.py
Salvatore Orlando 2049e868a5 Fix for bug 921743
Response codes for create ops in API v1.0 not compliant with spec

Change-Id: I7723e46b05ffd7b29940327b9c7362f843e01817
2012-03-13 17:22:11 +00:00

197 lines
6.3 KiB
Python

# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 Citrix System.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import logging
from webob import exc
from quantum import wsgi
from quantum.api import faults
XML_NS_V10 = 'http://openstack.org/quantum/api/v1.0'
XML_NS_V11 = 'http://openstack.org/quantum/api/v1.1'
LOG = logging.getLogger('quantum.api.api_common')
class OperationalStatus:
""" Enumeration for operational status
UP : the resource is available (operationall up)
DOWN : the resource is not operational; this might indicate
a failure in the underlying switching fabric.
PROVISIONING: the plugin is creating or updating the resource
in the underlying switching fabric
UNKNOWN: the plugin does not support the operational status concept.
"""
UP = "UP"
DOWN = "DOWN"
PROVISIONING = "PROVISIONING"
UNKNOWN = "UNKNOWN"
def create_resource(version, controller_dict):
"""
Generic function for creating a wsgi resource
The function takes as input:
- desired version
- controller and metadata dictionary
e.g.: {'1.0': [ctrl_v10, meta_v10, xml_ns],
'1.1': [ctrl_v11, meta_v11, xml_ns]}
"""
# the first element of the iterable is expected to be the controller
controller = controller_dict[version][0]
# the second element should be the metadata
metadata = controller_dict[version][1]
# and the third element the xml namespace
xmlns = controller_dict[version][2]
# and also the function for building the fault body
fault_body_function = faults.fault_body_function(version)
headers_serializers = {
'1.0': HeaderSerializer10(),
'1.1': HeaderSerializer11()
}
xml_serializer = wsgi.XMLDictSerializer(metadata, xmlns)
json_serializer = wsgi.JSONDictSerializer()
xml_deserializer = wsgi.XMLDeserializer(metadata)
json_deserializer = wsgi.JSONDeserializer()
body_serializers = {
'application/xml': xml_serializer,
'application/json': json_serializer,
}
body_deserializers = {
'application/xml': xml_deserializer,
'application/json': json_deserializer,
}
serializer = wsgi.ResponseSerializer(body_serializers,
headers_serializers[version])
deserializer = wsgi.RequestDeserializer(body_deserializers)
return wsgi.Resource(controller,
fault_body_function,
deserializer,
serializer)
def APIFaultWrapper(errors=None):
quantum_error_dict = {
'1.0': faults.Quantum10HTTPError,
'1.1': faults.Quantum11HTTPError
}
def wrapper(func, **kwargs):
def the_func(*args, **kwargs):
try:
# Grab API version from type of controller
controller = args[0]
version = controller.version
return func(*args, **kwargs)
except Exception as e:
if errors is not None and type(e) in errors:
# Version-specific behaviour
quantum_error_class = quantum_error_dict[version]
raise quantum_error_class(e)
# otherwise just re-raise
raise
the_func.__name__ = func.__name__
return the_func
return wrapper
class HeaderSerializer10(wsgi.ResponseHeaderSerializer):
"""
Defines default respone status codes for Quantum API 1.0 operations
create - 200 OK
update - 204 NOCONTENT
delete - 204 NOCONTENT
others - 200 OK (defined in base class)
"""
def create(self, response, data):
response.status_int = 200
def delete(self, response, data):
response.status_int = 204
def update(self, response, data):
response.status_int = 204
def attach_resource(self, response, data):
response.status_int = 204
def detach_resource(self, response, data):
response.status_int = 204
class HeaderSerializer11(HeaderSerializer10):
"""
Defines default respone status codes for Quantum API 1.0 operations
create - 202 ACCEPTED
update - 204 NOCONTENT
delete - 204 NOCONTENT
others - 200 OK (defined in base class)
"""
def create(self, response, data):
response.status_int = 202
class QuantumController(object):
""" Base controller class for Quantum API """
def __init__(self, plugin):
self._plugin = plugin
super(QuantumController, self).__init__()
def _prepare_request_body(self, body, params):
""" verifies required parameters are in request body.
sets default value for missing optional parameters.
body argument must be the deserialized body
"""
try:
if body is None:
# Initialize empty resource for setting default value
body = {self._resource_name: {}}
data = body[self._resource_name]
except KeyError:
# raise if _resource_name is not in req body.
raise exc.HTTPBadRequest("Unable to find '%s' in request body"\
% self._resource_name)
for param in params:
param_name = param['param-name']
param_value = data.get(param_name, None)
# If the parameter wasn't found and it was required, return 400
if param_value is None and param['required']:
msg = ("Failed to parse request. " +
"Parameter: " + param_name + " not specified")
for line in msg.split('\n'):
LOG.error(line)
raise exc.HTTPBadRequest(msg)
data[param_name] = param_value or param.get('default-value')
return body