Remove OSAPI v1.0

Change-Id: I92302c9c2b8f98d140c4844d4522adbcb45c8dd7
This commit is contained in:
Brian Waldon
2011-10-11 16:32:56 -04:00
parent ddb49f7929
commit edf3e39cd3
41 changed files with 485 additions and 3182 deletions

View File

@@ -11,7 +11,6 @@ graft contrib
graft po
graft plugins
graft nova/api/openstack/schemas
include nova/api/openstack/notes.txt
include nova/auth/*.schema
include nova/auth/novarc.template
include nova/auth/opendj.sh

View File

@@ -16,7 +16,6 @@ use = egg:Paste#urlmap
/2008-02-01: ec2metadata
/2008-09-01: ec2metadata
/2009-04-04: ec2metadata
/1.0: ec2metadata
[pipeline:ec2cloud]
pipeline = logrequest ec2noauth cloudrequest authorizer ec2executor
@@ -73,14 +72,8 @@ paste.app_factory = nova.api.ec2.metadatarequesthandler:MetadataRequestHandler.f
[composite:osapi]
use = call:nova.api.openstack.urlmap:urlmap_factory
/: osversions
/v1.0: openstackapi10
/v1.1: openstackapi11
[pipeline:openstackapi10]
pipeline = faultwrap noauth ratelimit osapiapp10
# NOTE(vish): use the following pipeline for deprecated auth
# pipeline = faultwrap auth ratelimit osapiapp10
[pipeline:openstackapi11]
pipeline = faultwrap noauth ratelimit extensions osapiapp11
# NOTE(vish): use the following pipeline for deprecated auth
@@ -101,11 +94,8 @@ paste.filter_factory = nova.api.openstack.limits:RateLimitingMiddleware.factory
[filter:extensions]
paste.filter_factory = nova.api.openstack.extensions:ExtensionMiddleware.factory
[app:osapiapp10]
paste.app_factory = nova.api.openstack:APIRouterV10.factory
[app:osapiapp11]
paste.app_factory = nova.api.openstack:APIRouterV11.factory
paste.app_factory = nova.api.openstack:APIRouter.factory
[pipeline:osversions]
pipeline = faultwrap osversionapp

View File

@@ -24,12 +24,8 @@ import routes
import webob.dec
import webob.exc
from nova import flags
from nova import log as logging
from nova import wsgi as base_wsgi
from nova.api.openstack import accounts
from nova.api.openstack import faults
from nova.api.openstack import backup_schedules
from nova.api.openstack import consoles
from nova.api.openstack import flavors
from nova.api.openstack import images
@@ -38,11 +34,13 @@ from nova.api.openstack import ips
from nova.api.openstack import limits
from nova.api.openstack import servers
from nova.api.openstack import server_metadata
from nova.api.openstack import shared_ip_groups
from nova.api.openstack import users
from nova.api.openstack import versions
from nova.api.openstack import wsgi
from nova.api.openstack import zones
from nova import flags
from nova import log as logging
from nova import wsgi as base_wsgi
LOG = logging.getLogger('nova.api.openstack')
@@ -97,19 +95,11 @@ class APIRouter(base_wsgi.Router):
def __init__(self, ext_mgr=None):
self.server_members = {}
mapper = self._mapper()
mapper = ProjectMapper()
self._setup_routes(mapper)
super(APIRouter, self).__init__(mapper)
def _mapper(self):
return routes.Mapper()
def _setup_routes(self, mapper):
raise NotImplementedError(_("You must implement _setup_routes."))
def _setup_base_routes(self, mapper, version):
"""Routes common to all versions."""
server_members = self.server_members
server_members['action'] = 'POST'
if FLAGS.allow_admin_api:
@@ -127,13 +117,13 @@ class APIRouter(base_wsgi.Router):
collection={'detail': 'GET'})
mapper.resource("zone", "zones",
controller=zones.create_resource(version),
controller=zones.create_resource(),
collection={'detail': 'GET',
'info': 'GET',
'select': 'POST'})
mapper.connect("versions", "/",
controller=versions.create_resource(version),
controller=versions.create_resource(),
action='show')
mapper.resource("console", "consoles",
@@ -142,53 +132,25 @@ class APIRouter(base_wsgi.Router):
collection_name='servers'))
mapper.resource("server", "servers",
controller=servers.create_resource(version),
controller=servers.create_resource(),
collection={'detail': 'GET'},
member=self.server_members)
mapper.resource("ip", "ips", controller=ips.create_resource(version),
mapper.resource("ip", "ips", controller=ips.create_resource(),
parent_resource=dict(member_name='server',
collection_name='servers'))
mapper.resource("image", "images",
controller=images.create_resource(version),
controller=images.create_resource(),
collection={'detail': 'GET'})
mapper.resource("limit", "limits",
controller=limits.create_resource(version))
controller=limits.create_resource())
mapper.resource("flavor", "flavors",
controller=flavors.create_resource(version),
controller=flavors.create_resource(),
collection={'detail': 'GET'})
super(APIRouter, self).__init__(mapper)
class APIRouterV10(APIRouter):
"""Define routes specific to OpenStack API V1.0."""
def _setup_routes(self, mapper):
self._setup_base_routes(mapper, '1.0')
mapper.resource("shared_ip_group", "shared_ip_groups",
collection={'detail': 'GET'},
controller=shared_ip_groups.create_resource())
mapper.resource("backup_schedule", "backup_schedule",
controller=backup_schedules.create_resource(),
parent_resource=dict(member_name='server',
collection_name='servers'))
class APIRouterV11(APIRouter):
"""Define routes specific to OpenStack API V1.1."""
def _mapper(self):
return ProjectMapper()
def _setup_routes(self, mapper):
self._setup_base_routes(mapper, '1.1')
image_metadata_controller = image_metadata.create_resource()
mapper.resource("image_meta", "metadata",

View File

@@ -1,67 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 OpenStack LLC.
# 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 time
from webob import exc
from nova.api.openstack import wsgi
def _translate_keys(inst):
""" Coerces the backup schedule into proper dictionary format """
return dict(backupSchedule=inst)
class Controller(object):
""" The backup schedule API controller for the Openstack API """
def __init__(self):
pass
def index(self, req, server_id, **kwargs):
""" Returns the list of backup schedules for a given instance """
raise exc.HTTPNotImplemented()
def show(self, req, server_id, id, **kwargs):
""" Returns a single backup schedule for a given instance """
raise exc.HTTPNotImplemented()
def create(self, req, server_id, **kwargs):
""" No actual update method required, since the existing API allows
both create and update through a POST """
raise exc.HTTPNotImplemented()
def delete(self, req, server_id, id, **kwargs):
""" Deletes an existing backup schedule """
raise exc.HTTPNotImplemented()
def create_resource():
metadata = {
'attributes': {
'backupSchedule': [],
},
}
body_serializers = {
'application/xml': wsgi.XMLDictSerializer(xmlns=wsgi.XMLNS_V10,
metadata=metadata),
}
serializer = wsgi.ResponseSerializer(body_serializers)
return wsgi.Resource(Controller(), serializer=serializer)

View File

@@ -37,7 +37,6 @@ LOG = logging.getLogger('nova.api.openstack.common')
FLAGS = flags.FLAGS
XML_NS_V10 = 'http://docs.rackspacecloud.com/servers/api/v1.0'
XML_NS_V11 = 'http://docs.openstack.org/compute/api/v1.1'

View File

@@ -20,7 +20,7 @@ from nova.api.openstack import servers
from nova.api.openstack import wsgi
class CreateServerController(servers.ControllerV11):
class CreateServerController(servers.Controller):
def _build_view(self, req, instance, is_detail=False):
server = super(CreateServerController, self)._build_view(req,
instance,
@@ -65,7 +65,7 @@ class Createserverext(extensions.ExtensionDescriptor):
}
body_deserializers = {
'application/xml': servers.ServerXMLDeserializerV11(),
'application/xml': servers.ServerXMLDeserializer(),
}
serializer = wsgi.ResponseSerializer(body_serializers,

View File

@@ -489,7 +489,7 @@ class VsaVPoolController(object):
return faults.Fault(exc.HTTPBadRequest())
class VsaVCController(servers.ControllerV11):
class VsaVCController(servers.Controller):
"""The VSA Virtual Controller API controller for the OpenStack API."""
def __init__(self):

View File

@@ -331,7 +331,7 @@ class VolumeAttachmentController(object):
return {'volumeAttachments': res}
class BootFromVolumeController(servers.ControllerV11):
class BootFromVolumeController(servers.Controller):
"""The boot from volume API controller for the Openstack API."""
def _get_block_device_mapping(self, data):

View File

@@ -60,13 +60,9 @@ class Fault(webob.exc.HTTPException):
# 'code' is an attribute on the fault tag itself
metadata = {'attributes': {fault_name: 'code'}}
xml_serializer = wsgi.XMLDictSerializer(metadata, wsgi.XMLNS_V11)
content_type = req.best_match_content_type()
xml_serializer = {
'1.0': wsgi.XMLDictSerializer(metadata, wsgi.XMLNS_V10),
'1.1': wsgi.XMLDictSerializer(metadata, wsgi.XMLNS_V11),
}[common.get_version_from_href(req.url)]
serializer = {
'application/xml': xml_serializer,
'application/json': wsgi.JSONDictSerializer(),
@@ -105,11 +101,7 @@ class OverLimitFault(webob.exc.HTTPException):
content_type = request.best_match_content_type()
metadata = {"attributes": {"overLimitFault": "code"}}
xml_serializer = {
'1.0': wsgi.XMLDictSerializer(metadata, wsgi.XMLNS_V10),
'1.1': wsgi.XMLDictSerializer(metadata, wsgi.XMLNS_V11),
}[common.get_version_from_href(request.url)]
xml_serializer = wsgi.XMLDictSerializer(metadata, wsgi.XMLNS_V11)
serializer = {
'application/xml': xml_serializer,
'application/json': wsgi.JSONDictSerializer(),

View File

@@ -75,19 +75,10 @@ class Controller(object):
values = builder.build(flavor, is_detail=True)
return dict(flavor=values)
class ControllerV10(Controller):
def _get_view_builder(self, req):
return views.flavors.ViewBuilder()
class ControllerV11(Controller):
def _get_view_builder(self, req):
base_url = req.application_url
project_id = getattr(req.environ['nova.context'], 'project_id', '')
return views.flavors.ViewBuilderV11(base_url, project_id)
return views.flavors.ViewBuilder(base_url, project_id)
class FlavorXMLSerializer(wsgi.XMLDictSerializer):
@@ -136,21 +127,7 @@ class FlavorXMLSerializer(wsgi.XMLDictSerializer):
return self._to_xml(flavors)
def create_resource(version='1.0'):
controller = {
'1.0': ControllerV10,
'1.1': ControllerV11,
}[version]()
xml_serializer = {
'1.0': wsgi.XMLDictSerializer(xmlns=wsgi.XMLNS_V10),
'1.1': FlavorXMLSerializer(),
}[version]
body_serializers = {
'application/xml': xml_serializer,
}
def create_resource():
body_serializers = {'application/xml': FlavorXMLSerializer()}
serializer = wsgi.ResponseSerializer(body_serializers)
return wsgi.Resource(controller, serializer=serializer)
return wsgi.Resource(Controller(), serializer=serializer)

View File

@@ -104,83 +104,11 @@ class Controller(object):
raise webob.exc.HTTPNotFound(explanation=explanation)
return webob.exc.HTTPNoContent()
def get_builder(self, request):
"""Indicates that you must use a Controller subclass."""
raise NotImplementedError()
class ControllerV10(Controller):
"""Version 1.0 specific controller logic."""
@common.check_snapshots_enabled
def create(self, req, body):
"""Snapshot a server instance and save the image."""
try:
image = body["image"]
except (KeyError, TypeError):
msg = _("Invalid image entity")
raise webob.exc.HTTPBadRequest(explanation=msg)
try:
image_name = image["name"]
instance_id = image["serverId"]
except KeyError as missing_key:
msg = _("Image entity requires %s") % missing_key
raise webob.exc.HTTPBadRequest(explanation=msg)
context = req.environ["nova.context"]
props = {'instance_id': instance_id}
try:
image = self._compute_service.snapshot(context,
instance_id,
image_name,
extra_properties=props)
except exception.InstanceBusy:
msg = _("Server is currently creating an image. Please wait.")
raise webob.exc.HTTPConflict(explanation=msg)
return dict(image=self.get_builder(req).build(image, detail=True))
def get_builder(self, request):
"""Property to get the ViewBuilder class we need to use."""
base_url = request.application_url
return images_view.ViewBuilderV10(base_url)
def index(self, req):
"""Return an index listing of images available to the request.
:param req: `wsgi.Request` object
"""
context = req.environ['nova.context']
filters = self._get_filters(req)
images = self._image_service.index(context, filters=filters)
images = common.limited(images, req)
return self.get_builder(req).build_list(images)
def detail(self, req):
"""Return a detailed index listing of images available to the request.
:param req: `wsgi.Request` object.
"""
context = req.environ['nova.context']
filters = self._get_filters(req)
images = self._image_service.detail(context, filters=filters)
images = common.limited(images, req)
builder = self.get_builder(req).build
return dict(images=[builder(image, detail=True) for image in images])
class ControllerV11(Controller):
"""Version 1.1 specific controller logic."""
def get_builder(self, req):
"""Property to get the ViewBuilder class we need to use."""
base_url = req.application_url
project_id = getattr(req.environ['nova.context'], 'project_id', '')
return images_view.ViewBuilderV11(base_url, project_id)
return images_view.ViewBuilder(base_url, project_id)
def index(self, req):
"""Return an index listing of images available to the request.
@@ -298,29 +226,7 @@ class ImageXMLSerializer(wsgi.XMLDictSerializer):
return self._to_xml(image)
def create_resource(version='1.0'):
controller = {
'1.0': ControllerV10,
'1.1': ControllerV11,
}[version]()
metadata = {
"attributes": {
"image": ["id", "name", "updated", "created", "status",
"serverId", "progress", "serverRef"],
"link": ["rel", "type", "href"],
},
}
xml_serializer = {
'1.0': wsgi.XMLDictSerializer(metadata, wsgi.XMLNS_V10),
'1.1': ImageXMLSerializer(),
}[version]
body_serializers = {
'application/xml': xml_serializer,
}
def create_resource():
body_serializers = {'application/xml': ImageXMLSerializer()}
serializer = wsgi.ResponseSerializer(body_serializers)
return wsgi.Resource(controller, serializer=serializer)
return wsgi.Resource(Controller(), serializer=serializer)

View File

@@ -52,37 +52,6 @@ class Controller(object):
def delete(self, req, server_id, id):
raise exc.HTTPNotImplemented()
class ControllerV10(Controller):
def index(self, req, server_id):
context = req.environ['nova.context']
instance = self._get_instance(context, server_id)
networks = common.get_networks_for_instance(context, instance)
builder = self._get_view_builder(req)
return {'addresses': builder.build(networks)}
def show(self, req, server_id, id):
context = req.environ['nova.context']
instance = self._get_instance(context, server_id)
networks = common.get_networks_for_instance(context, instance)
builder = self._get_view_builder(req)
if id == 'private':
view = builder.build_private_parts(networks)
elif id == 'public':
view = builder.build_public_parts(networks)
else:
msg = _("Only private and public networks available")
raise exc.HTTPNotFound(explanation=msg)
return {id: view}
def _get_view_builder(self, req):
return views_addresses.ViewBuilderV10()
class ControllerV11(Controller):
def index(self, req, server_id):
context = req.environ['nova.context']
instance = self._get_instance(context, server_id)
@@ -102,7 +71,7 @@ class ControllerV11(Controller):
return network
def _get_view_builder(self, req):
return views_addresses.ViewBuilderV11()
return views_addresses.ViewBuilder()
class IPXMLSerializer(wsgi.XMLDictSerializer):
@@ -138,24 +107,7 @@ class IPXMLSerializer(wsgi.XMLDictSerializer):
return self._to_xml(addresses)
def create_resource(version):
controller = {
'1.0': ControllerV10,
'1.1': ControllerV11,
}[version]()
metadata = {
'list_collections': {
'public': {'item_name': 'ip', 'item_key': 'addr'},
'private': {'item_name': 'ip', 'item_key': 'addr'},
},
}
xml_serializer = {
'1.0': wsgi.XMLDictSerializer(metadata=metadata, xmlns=wsgi.XMLNS_V11),
'1.1': IPXMLSerializer(),
}[version]
serializer = wsgi.ResponseSerializer({'application/xml': xml_serializer})
return wsgi.Resource(controller, serializer=serializer)
def create_resource():
body_serializers = {'application/xml': IPXMLSerializer()}
serializer = wsgi.ResponseSerializer(body_serializers)
return wsgi.Resource(Controller(), serializer=serializer)

View File

@@ -65,17 +65,7 @@ class LimitsController(object):
return builder.build(rate_limits, abs_limits)
def _get_view_builder(self, req):
raise NotImplementedError()
class LimitsControllerV10(LimitsController):
def _get_view_builder(self, req):
return limits_views.ViewBuilderV10()
class LimitsControllerV11(LimitsController):
def _get_view_builder(self, req):
return limits_views.ViewBuilderV11()
return limits_views.ViewBuilder()
class LimitsXMLSerializer(wsgi.XMLDictSerializer):
@@ -127,39 +117,10 @@ class LimitsXMLSerializer(wsgi.XMLDictSerializer):
return self._to_xml(limits)
def create_resource(version='1.0'):
controller = {
'1.0': LimitsControllerV10,
'1.1': LimitsControllerV11,
}[version]()
xmlns = {
'1.0': wsgi.XMLNS_V10,
'1.1': wsgi.XMLNS_V11,
}[version]
metadata = {
"attributes": {
"limit": ["verb", "URI", "uri", "regex", "value", "unit",
"resetTime", "next-available", "remaining", "name"],
},
"plurals": {
"rate": "limit",
},
}
xml_serializer = {
'1.0': wsgi.XMLDictSerializer(xmlns=xmlns, metadata=metadata),
'1.1': LimitsXMLSerializer(),
}[version]
body_serializers = {
'application/xml': xml_serializer,
}
def create_resource():
body_serializers = {'application/xml': LimitsXMLSerializer()}
serializer = wsgi.ResponseSerializer(body_serializers)
return wsgi.Resource(controller, serializer=serializer)
return wsgi.Resource(LimitsController(), serializer=serializer)
class Limit(object):

View File

@@ -1,20 +0,0 @@
We will need:
ImageService
a service that can do crud on image information. not user-specific. opaque
image ids.
GlanceImageService(ImageService):
image ids are URIs.
OpenstackAPITranslationStore:
translates RS server/images/flavor/etc ids into formats required
by a given ImageService strategy.
api.openstack.images.Controller:
uses an ImageService strategy behind the scenes to do its fetching; it just
converts int image id into a strategy-specific image id.
who maintains the mapping from user to [images he owns]? nobody, because
we have no way of enforcing access to his images, without kryptex which
won't be in Austin.

View File

@@ -85,18 +85,6 @@ class Controller(object):
return exc.HTTPNotFound()
return servers
def _build_view(self, req, instance, is_detail=False):
raise NotImplementedError()
def _build_list(self, req, instances, is_detail=False):
raise NotImplementedError()
def _limit_items(self, items, req):
raise NotImplementedError()
def _action_rebuild(self, info, request, instance_id):
raise NotImplementedError()
def _get_block_device_mapping(self, data):
"""Get block_device_mapping from 'server' dictionary.
Overidden by volumes controller.
@@ -346,10 +334,6 @@ class Controller(object):
except exception.NotFound:
raise exc.HTTPNotFound()
def _get_key_name(self, req, body):
""" Get default keypair if not set """
raise NotImplementedError()
def create(self, req, body):
""" Creates a new server for a given user """
@@ -556,10 +540,8 @@ class Controller(object):
except exception.NotFound:
raise exc.HTTPNotFound()
return self._update(ctxt, req, id, body)
def _update(self, context, req, id, inst_dict):
return exc.HTTPNotImplemented()
instance = self.compute_api.routing_get(ctxt, id)
return self._build_view(req, instance, is_detail=True)
@exception.novaclient_converter
@scheduler_api.redirect_handler
@@ -654,13 +636,6 @@ class Controller(object):
resp.headers['Location'] = image_ref
return resp
@common.check_snapshots_enabled
def _action_create_image(self, input_dict, req, id):
return exc.HTTPNotImplemented()
def _action_change_password(self, input_dict, req, id):
return exc.HTTPNotImplemented()
def _action_confirm_resize(self, input_dict, req, id):
try:
self.compute_api.confirm_resize(req.environ['nova.context'], id)
@@ -683,9 +658,6 @@ class Controller(object):
raise exc.HTTPBadRequest()
return webob.Response(status_int=202)
def _action_resize(self, input_dict, req, id):
return exc.HTTPNotImplemented()
def _action_reboot(self, input_dict, req, id):
if 'reboot' in input_dict and 'type' in input_dict['reboot']:
valid_reboot_types = ['HARD', 'SOFT']
@@ -783,96 +755,6 @@ class Controller(object):
return webob.Response(status_int=202)
class ControllerV10(Controller):
"""v1.0 OpenStack API controller"""
@exception.novaclient_converter
@scheduler_api.redirect_handler
def delete(self, req, id):
""" Destroys a server """
try:
self._delete(req.environ['nova.context'], id)
except exception.NotFound:
raise exc.HTTPNotFound()
return webob.Response(status_int=202)
def _get_key_name(self, req, body):
context = req.environ["nova.context"]
keypairs = db.key_pair_get_all_by_user(context,
context.user_id)
if keypairs:
return keypairs[0]['name']
def _image_ref_from_req_data(self, data):
return data['server']['imageId']
def _flavor_id_from_req_data(self, data):
return data['server']['flavorId']
def _build_view(self, req, instance, is_detail=False):
context = req.environ['nova.context']
addresses = views_addresses.ViewBuilderV10()
builder = views_servers.ViewBuilderV10(context, addresses)
return builder.build(instance, is_detail=is_detail)
def _build_list(self, req, instances, is_detail=False):
context = req.environ['nova.context']
addresses = views_addresses.ViewBuilderV10()
builder = views_servers.ViewBuilderV10(context, addresses)
return builder.build_list(instances, is_detail=is_detail)
def _limit_items(self, items, req):
return common.limited(items, req)
def _update(self, context, req, id, inst_dict):
if 'adminPass' in inst_dict['server']:
self.compute_api.set_admin_password(context, id,
inst_dict['server']['adminPass'])
return exc.HTTPNoContent()
def _action_resize(self, input_dict, req, id):
""" Resizes a given instance to the flavor size requested """
try:
flavor_id = input_dict["resize"]["flavorId"]
except (KeyError, TypeError):
msg = _("Resize requests require 'flavorId' attribute.")
raise exc.HTTPBadRequest(explanation=msg)
return self.resize(req, id, flavor_id)
def _action_rebuild(self, info, request, instance_id):
context = request.environ['nova.context']
try:
image_id = info["rebuild"]["imageId"]
except (KeyError, TypeError):
msg = _("Could not parse imageId from request.")
LOG.debug(msg)
raise exc.HTTPBadRequest(explanation=msg)
password = utils.generate_password(FLAGS.password_length)
try:
self.compute_api.rebuild(context, instance_id, image_id, password)
except exception.RebuildRequiresActiveInstance:
msg = _("Instance %s must be active to rebuild.") % instance_id
raise exc.HTTPConflict(explanation=msg)
return webob.Response(status_int=202)
def _get_server_admin_password(self, server):
""" Determine the admin password for a server on creation """
return self._get_server_admin_password_old_style(server)
def _get_server_search_options(self):
"""Return server search options allowed by non-admin"""
return 'reservation_id', 'fixed_ip', 'name', 'local_zone_only'
class ControllerV11(Controller):
"""v1.1 OpenStack API controller"""
@exception.novaclient_converter
@scheduler_api.redirect_handler
def delete(self, req, id):
@@ -910,10 +792,10 @@ class ControllerV11(Controller):
context = req.environ['nova.context']
project_id = getattr(context, 'project_id', '')
base_url = req.application_url
flavor_builder = views_flavors.ViewBuilderV11(base_url, project_id)
image_builder = views_images.ViewBuilderV11(base_url, project_id)
addresses_builder = views_addresses.ViewBuilderV11()
builder = views_servers.ViewBuilderV11(context, addresses_builder,
flavor_builder = views_flavors.ViewBuilder(base_url, project_id)
image_builder = views_images.ViewBuilder(base_url, project_id)
addresses_builder = views_addresses.ViewBuilder()
builder = views_servers.ViewBuilder(context, addresses_builder,
flavor_builder, image_builder, base_url, project_id)
return builder.build(instance, is_detail=is_detail)
@@ -927,10 +809,10 @@ class ControllerV11(Controller):
context = req.environ['nova.context']
project_id = getattr(context, 'project_id', '')
base_url = req.application_url
flavor_builder = views_flavors.ViewBuilderV11(base_url, project_id)
image_builder = views_images.ViewBuilderV11(base_url, project_id)
addresses_builder = views_addresses.ViewBuilderV11()
builder = views_servers.ViewBuilderV11(context, addresses_builder,
flavor_builder = views_flavors.ViewBuilder(base_url, project_id)
image_builder = views_images.ViewBuilder(base_url, project_id)
addresses_builder = views_addresses.ViewBuilder()
builder = views_servers.ViewBuilder(context, addresses_builder,
flavor_builder, image_builder, base_url, project_id)
return builder.build_list(instances, is_detail=is_detail, **params)
@@ -977,10 +859,6 @@ class ControllerV11(Controller):
LOG.info(msg)
raise exc.HTTPBadRequest(explanation=msg)
def _update(self, context, req, id, inst_dict):
instance = self.compute_api.routing_get(context, id)
return self._build_view(req, instance, is_detail=True)
def _action_resize(self, input_dict, req, id):
""" Resizes a given instance to the flavor size requested """
try:
@@ -1235,55 +1113,7 @@ class ServerXMLSerializer(wsgi.XMLDictSerializer):
return self._to_xml(server)
class ServerXMLDeserializer(wsgi.XMLDeserializer):
"""
Deserializer to handle xml-formatted server create requests.
Handles standard server attributes as well as optional metadata
and personality attributes
"""
metadata_deserializer = common.MetadataXMLDeserializer()
def create(self, string):
"""Deserialize an xml-formatted server create request"""
dom = minidom.parseString(string)
server = self._extract_server(dom)
return {'body': {'server': server}}
def _extract_server(self, node):
"""Marshal the server attribute of a parsed request"""
server = {}
server_node = self.find_first_child_named(node, 'server')
attributes = ["name", "imageId", "flavorId", "adminPass"]
for attr in attributes:
if server_node.getAttribute(attr):
server[attr] = server_node.getAttribute(attr)
metadata_node = self.find_first_child_named(server_node, "metadata")
server["metadata"] = self.metadata_deserializer.extract_metadata(
metadata_node)
server["personality"] = self._extract_personality(server_node)
return server
def _extract_personality(self, server_node):
"""Marshal the personality attribute of a parsed request"""
node = self.find_first_child_named(server_node, "personality")
personality = []
if node is not None:
for file_node in self.find_children_named(node, "file"):
item = {}
if file_node.hasAttribute("path"):
item["path"] = file_node.getAttribute("path")
item["contents"] = self.extract_text(file_node)
personality.append(item)
return personality
class ServerXMLDeserializerV11(wsgi.MetadataXMLDeserializer):
class ServerXMLDeserializer(wsgi.MetadataXMLDeserializer):
"""
Deserializer to handle xml-formatted server create requests.
@@ -1456,57 +1286,13 @@ class ServerXMLDeserializerV11(wsgi.MetadataXMLDeserializer):
return None
def create_resource(version='1.0'):
controller = {
'1.0': ControllerV10,
'1.1': ControllerV11,
}[version]()
metadata = {
"attributes": {
"server": ["id", "imageId", "name", "flavorId", "hostId",
"status", "progress", "adminPass", "flavorRef",
"imageRef", "userId", "tenantId"],
"link": ["rel", "type", "href"],
},
"dict_collections": {
"metadata": {"item_name": "meta", "item_key": "key"},
},
"list_collections": {
"public": {"item_name": "ip", "item_key": "addr"},
"private": {"item_name": "ip", "item_key": "addr"},
},
}
xmlns = {
'1.0': wsgi.XMLNS_V10,
'1.1': wsgi.XMLNS_V11,
}[version]
def create_resource():
headers_serializer = HeadersSerializer()
xml_serializer = {
'1.0': wsgi.XMLDictSerializer(metadata, wsgi.XMLNS_V10),
'1.1': ServerXMLSerializer(),
}[version]
body_serializers = {
'application/xml': xml_serializer,
}
xml_deserializer = {
'1.0': ServerXMLDeserializer(),
'1.1': ServerXMLDeserializerV11(),
}[version]
body_deserializers = {
'application/xml': xml_deserializer,
}
body_serializers = {'application/xml': ServerXMLSerializer()}
serializer = wsgi.ResponseSerializer(body_serializers, headers_serializer)
body_deserializers = {'application/xml': ServerXMLDeserializer()}
deserializer = wsgi.RequestDeserializer(body_deserializers)
return wsgi.Resource(controller, deserializer, serializer)
return wsgi.Resource(Controller(), deserializer, serializer)
def remove_invalid_options(context, search_options, allowed_search_options):

View File

@@ -1,52 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 OpenStack LLC.
# 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.
from webob import exc
from nova.api.openstack import wsgi
class Controller(object):
""" The Shared IP Groups Controller for the Openstack API """
def index(self, req, **kwargs):
""" Returns a list of Shared IP Groups for the user """
raise exc.HTTPNotImplemented()
def show(self, req, id, **kwargs):
""" Shows in-depth information on a specific Shared IP Group """
raise exc.HTTPNotImplemented()
def update(self, req, id, **kwargs):
""" You can't update a Shared IP Group """
raise exc.HTTPNotImplemented()
def delete(self, req, id, **kwargs):
""" Deletes a Shared IP Group """
raise exc.HTTPNotImplemented()
def detail(self, req, **kwargs):
""" Returns a complete list of Shared IP Groups """
raise exc.HTTPNotImplemented()
def create(self, req, **kwargs):
""" Creates a new Shared IP group """
raise exc.HTTPNotImplemented()
def create_resource():
return wsgi.Resource(Controller())

View File

@@ -26,35 +26,6 @@ from nova.api.openstack import xmlutil
VERSIONS = {
"v1.0": {
"id": "v1.0",
"status": "DEPRECATED",
"updated": "2011-01-21T11:33:21Z",
"links": [
{
"rel": "describedby",
"type": "application/pdf",
"href": "http://docs.rackspacecloud.com/"
"servers/api/v1.0/cs-devguide-20110125.pdf",
},
{
"rel": "describedby",
"type": "application/vnd.sun.wadl+xml",
"href": "http://docs.rackspacecloud.com/"
"servers/api/v1.0/application.wadl",
},
],
"media-types": [
{
"base": "application/xml",
"type": "application/vnd.openstack.compute+xml;version=1.0",
},
{
"base": "application/json",
"type": "application/vnd.openstack.compute+json;version=1.0",
}
],
},
"v1.1": {
"id": "v1.1",
"status": "CURRENT",
@@ -122,12 +93,6 @@ class Versions(wsgi.Resource):
return builder.build_choices(VERSIONS, request)
class VersionV10(object):
def show(self, req):
builder = nova.api.openstack.views.versions.get_view_builder(req)
return builder.build_version(VERSIONS['v1.0'])
class VersionV11(object):
def show(self, req):
builder = nova.api.openstack.views.versions.get_view_builder(req)
@@ -282,12 +247,7 @@ class VersionsHeadersSerializer(wsgi.ResponseHeadersSerializer):
response.status_int = 300
def create_resource(version='1.0'):
controller = {
'1.0': VersionV10,
'1.1': VersionV11,
}[version]()
def create_resource():
body_serializers = {
'application/xml': VersionsXMLSerializer(),
'application/atom+xml': VersionsAtomSerializer(),
@@ -296,5 +256,5 @@ def create_resource(version='1.0'):
deserializer = wsgi.RequestDeserializer()
return wsgi.Resource(controller, serializer=serializer,
return wsgi.Resource(VersionV11(), serializer=serializer,
deserializer=deserializer)

View File

@@ -28,9 +28,6 @@ LOG = logging.getLogger('nova.api.openstack.views.addresses')
class ViewBuilder(object):
"""Models a server addresses response as a python dictionary."""
def build(self, inst):
raise NotImplementedError()
def _extract_ips(self, network, key=None):
if key:
chain = network[key]
@@ -41,28 +38,6 @@ class ViewBuilder(object):
continue
yield ip
class ViewBuilderV10(ViewBuilder):
def build(self, networks):
if not networks:
return dict(public=[], private=[])
return dict(public=self.build_public_parts(networks),
private=self.build_private_parts(networks))
def build_public_parts(self, nets):
ips = [self._extract_ips(nets[label],
key='floating_ips') for label in nets]
return [ip['addr'] for ip in itertools.chain(*ips)]
def build_private_parts(self, nets):
ips = [self._extract_ips(nets[label], key='ips') for label in nets]
return [ip['addr'] for ip in itertools.chain(*ips)]
class ViewBuilderV11(ViewBuilder):
def build(self, networks):
result = {}
for network in networks:

View File

@@ -23,6 +23,13 @@ from nova.api.openstack import common
class ViewBuilder(object):
def __init__(self, base_url, project_id=""):
"""
:param base_url: url of the root wsgi application
"""
self.base_url = base_url
self.project_id = project_id
def build(self, flavor_obj, is_detail=False):
"""Generic method used to generate a flavor entity."""
if is_detail:
@@ -30,7 +37,7 @@ class ViewBuilder(object):
else:
flavor = self._build_simple(flavor_obj)
self._build_extra(flavor)
flavor["links"] = self._build_links(flavor)
return flavor
@@ -57,26 +64,9 @@ class ViewBuilder(object):
return detail
def _build_extra(self, flavor_obj):
"""Hook for version-specific changes to newly created flavor object."""
pass
class ViewBuilderV11(ViewBuilder):
"""Openstack API v1.1 flavors view builder."""
def __init__(self, base_url, project_id=""):
"""
:param base_url: url of the root wsgi application
"""
self.base_url = base_url
self.project_id = project_id
def _build_extra(self, flavor_obj):
flavor_obj["links"] = self._build_links(flavor_obj)
def _build_links(self, flavor_obj):
"""Generate a container of links that refer to the provided flavor."""
print flavor_obj
href = self.generate_href(flavor_obj["id"])
bookmark = self.generate_bookmark(flavor_obj["id"])

View File

@@ -71,15 +71,6 @@ class ViewBuilder(object):
"""Return an href string pointing to this object."""
return os.path.join(self.base_url, "images", str(image_id))
def build_list(self, image_objs, detail=False, **kwargs):
"""Return a standardized image list structure for display."""
images = []
for image_obj in image_objs:
image = self.build(image_obj, detail=detail)
images.append(image)
return dict(images=images)
def build(self, image_obj, detail=False):
"""Return a standardized image structure for display by the API."""
self._format_dates(image_obj)
@@ -95,6 +86,27 @@ class ViewBuilder(object):
self._build_server(image, image_obj)
self._build_image_id(image, image_obj)
href = self.generate_href(image_obj["id"])
bookmark = self.generate_bookmark(image_obj["id"])
alternate = self.generate_alternate(image_obj["id"])
image["links"] = [
{
"rel": "self",
"href": href,
},
{
"rel": "bookmark",
"href": bookmark,
},
{
"rel": "alternate",
"type": "application/vnd.openstack.image",
"href": alternate,
},
]
if detail:
image.update({
"created": image_obj.get("created_at"),
@@ -103,28 +115,24 @@ class ViewBuilder(object):
})
image["progress"] = self._get_progress_for_status(orig_status)
image["metadata"] = image_obj.get("properties", {})
min_ram = image_obj.get('min_ram') or 0
try:
min_ram = int(min_ram)
except ValueError:
min_ram = 0
image['minRam'] = min_ram
min_disk = image_obj.get('min_disk') or 0
try:
min_disk = int(min_disk)
except ValueError:
min_disk = 0
image['minDisk'] = min_disk
return image
class ViewBuilderV10(ViewBuilder):
"""OpenStack API v1.0 Image Builder"""
def _build_server(self, image, image_obj):
try:
image['serverId'] = int(image_obj['properties']['instance_id'])
except (KeyError, ValueError):
pass
def _build_image_id(self, image, image_obj):
try:
image['id'] = int(image_obj['id'])
except ValueError:
pass
class ViewBuilderV11(ViewBuilder):
"""OpenStack API v1.1 Image Builder"""
def _build_server(self, image, image_obj):
try:
serverRef = image_obj['properties']['instance_ref']
@@ -179,49 +187,6 @@ class ViewBuilderV11(ViewBuilder):
return reval
def build(self, image_obj, detail=False):
"""Return a standardized image structure for display by the API."""
image = ViewBuilder.build(self, image_obj, detail)
href = self.generate_href(image_obj["id"])
bookmark = self.generate_bookmark(image_obj["id"])
alternate = self.generate_alternate(image_obj["id"])
image["links"] = [
{
"rel": "self",
"href": href,
},
{
"rel": "bookmark",
"href": bookmark,
},
{
"rel": "alternate",
"type": "application/vnd.openstack.image",
"href": alternate,
},
]
if detail:
image["metadata"] = image_obj.get("properties", {})
min_ram = image_obj.get('min_ram') or 0
try:
min_ram = int(min_ram)
except ValueError:
min_ram = 0
image['minRam'] = min_ram
min_disk = image_obj.get('min_disk') or 0
try:
min_disk = int(min_disk)
except ValueError:
min_disk = 0
image['minDisk'] = min_disk
return image
def generate_bookmark(self, image_id):
"""Create a URL that refers to a specific flavor id."""
return os.path.join(common.remove_version_from_href(self.base_url),

View File

@@ -25,12 +25,6 @@ from nova import utils
class ViewBuilder(object):
"""Openstack API base limits view builder."""
def _build_rate_limits(self, rate_limits):
raise NotImplementedError()
def _build_rate_limit(self, rate_limit):
raise NotImplementedError()
def build(self, rate_limits, absolute_limits):
rate_limits = self._build_rate_limits(rate_limits)
absolute_limits = self._build_absolute_limits(absolute_limits)
@@ -66,28 +60,6 @@ class ViewBuilder(object):
limits[name] = value
return limits
class ViewBuilderV10(ViewBuilder):
"""Openstack API v1.0 limits view builder."""
def _build_rate_limits(self, rate_limits):
return [self._build_rate_limit(r) for r in rate_limits]
def _build_rate_limit(self, rate_limit):
return {
"verb": rate_limit["verb"],
"URI": rate_limit["URI"],
"regex": rate_limit["regex"],
"value": rate_limit["value"],
"remaining": int(rate_limit["remaining"]),
"unit": rate_limit["unit"],
"resetTime": rate_limit["resetTime"],
}
class ViewBuilderV11(ViewBuilder):
"""Openstack API v1.1 limits view builder."""
def _build_rate_limits(self, rate_limits):
limits = []
for rate_limit in rate_limits:

View File

@@ -30,16 +30,16 @@ LOG = logging.getLogger('nova.api.openstack.views.servers')
class ViewBuilder(object):
"""Model a server response as a python dictionary.
"""Model a server response as a python dictionary."""
Public methods: build
Abstract methods: _build_image, _build_flavor
"""
def __init__(self, context, addresses_builder):
def __init__(self, context, addresses_builder, flavor_builder,
image_builder, base_url, project_id=""):
self.context = context
self.addresses_builder = addresses_builder
self.flavor_builder = flavor_builder
self.image_builder = image_builder
self.base_url = base_url
self.project_id = project_id
def build(self, inst, is_detail=False):
"""Return a dict that represenst a server."""
@@ -51,20 +51,11 @@ class ViewBuilder(object):
else:
server = self._build_simple(inst)
self._build_extra(server['server'], inst)
self._build_links(server['server'], inst)
server['server']['uuid'] = inst['uuid']
return server
def build_list(self, server_objs, is_detail=False, **kwargs):
limit = kwargs.get('limit', None)
servers = []
servers_links = []
for server_obj in server_objs:
servers.append(self.build(server_obj, is_detail)['server'])
return dict(servers=servers)
def _build_simple(self, inst):
"""Return a simple model of a server."""
return dict(server=dict(id=inst['id'], name=inst['display_name']))
@@ -96,69 +87,25 @@ class ViewBuilder(object):
networks = common.get_networks_for_instance(self.context, inst)
self._build_addresses(inst_dict, networks)
inst_dict['created'] = utils.isotime(inst['created_at'])
inst_dict['updated'] = utils.isotime(inst['updated_at'])
status = inst_dict.get('status')
if status in ('ACTIVE', 'BUILD', 'REBUILD', 'RESIZE',
'VERIFY_RESIZE'):
inst_dict['progress'] = inst['progress'] or 0
inst_dict['accessIPv4'] = inst.get('access_ip_v4') or ""
inst_dict['accessIPv6'] = inst.get('access_ip_v6') or ""
inst_dict['key_name'] = inst.get('key_name', '')
inst_dict['config_drive'] = inst.get('config_drive')
return dict(server=inst_dict)
def _build_addresses(self, response, networks):
"""Return the addresses sub-resource of a server."""
response['addresses'] = self.addresses_builder.build(networks)
def _build_image(self, response, inst):
"""Return the image sub-resource of a server."""
raise NotImplementedError()
def _build_flavor(self, response, inst):
"""Return the flavor sub-resource of a server."""
raise NotImplementedError()
def _build_extra(self, response, inst):
pass
class ViewBuilderV10(ViewBuilder):
"""Model an Openstack API V1.0 server response."""
def _build_extra(self, response, inst):
response['uuid'] = inst['uuid']
def _build_image(self, response, inst):
if inst.get('image_ref', None):
image_ref = inst['image_ref']
if str(image_ref).startswith('http'):
raise exception.ListingImageRefsNotSupported()
response['imageId'] = int(image_ref)
def _build_flavor(self, response, inst):
if inst.get('instance_type', None):
response['flavorId'] = inst['instance_type']['flavorid']
class ViewBuilderV11(ViewBuilder):
"""Model an Openstack API V1.0 server response."""
def __init__(self, context, addresses_builder, flavor_builder,
image_builder, base_url, project_id=""):
super(ViewBuilderV11, self).__init__(context, addresses_builder)
self.flavor_builder = flavor_builder
self.image_builder = image_builder
self.base_url = base_url
self.project_id = project_id
def _build_detail(self, inst):
response = super(ViewBuilderV11, self)._build_detail(inst)
response['server']['created'] = utils.isotime(inst['created_at'])
response['server']['updated'] = utils.isotime(inst['updated_at'])
status = response['server'].get('status')
if status in ('ACTIVE', 'BUILD', 'REBUILD', 'RESIZE',
'VERIFY_RESIZE'):
response['server']['progress'] = inst['progress'] or 0
response['server']['accessIPv4'] = inst.get('access_ip_v4') or ""
response['server']['accessIPv6'] = inst.get('access_ip_v6') or ""
response['server']['key_name'] = inst.get('key_name', '')
response['server']['config_drive'] = inst.get('config_drive')
return response
def _build_image(self, response, inst):
if inst.get("image_ref", None):
image_href = inst['image_ref']
@@ -189,10 +136,6 @@ class ViewBuilderV11(ViewBuilder):
]
}
def _build_extra(self, response, inst):
self._build_links(response, inst)
response['uuid'] = inst['uuid']
def _build_links(self, response, inst):
href = self.generate_href(inst["id"])
bookmark = self.generate_bookmark(inst["id"])

View File

@@ -143,7 +143,7 @@ class Controller(object):
return cooked
def create_resource(version):
def create_resource():
metadata = {
"attributes": {
"zone": ["id", "api_url", "name", "capabilities"],
@@ -151,7 +151,7 @@ def create_resource(version):
}
body_serializers = {
'application/xml': wsgi.XMLDictSerializer(xmlns=wsgi.XMLNS_V10,
'application/xml': wsgi.XMLDictSerializer(xmlns=wsgi.XMLNS_V11,
metadata=metadata),
}
serializer = wsgi.ResponseSerializer(body_serializers)

View File

@@ -65,32 +65,24 @@ def fake_wsgi(self, req):
return self.application
def wsgi_app(inner_app10=None, inner_app11=None, fake_auth=True,
fake_auth_context=None):
if not inner_app10:
inner_app10 = openstack.APIRouterV10()
def wsgi_app(inner_app11=None, fake_auth=True, fake_auth_context=None):
if not inner_app11:
inner_app11 = openstack.APIRouterV11()
inner_app11 = openstack.APIRouter()
if fake_auth:
if fake_auth_context is not None:
ctxt = fake_auth_context
else:
ctxt = context.RequestContext('fake', 'fake', auth_token=True)
api10 = openstack.FaultWrapper(api_auth.InjectContext(ctxt,
limits.RateLimitingMiddleware(inner_app10)))
api11 = openstack.FaultWrapper(api_auth.InjectContext(ctxt,
limits.RateLimitingMiddleware(
extensions.ExtensionMiddleware(inner_app11))))
else:
api10 = openstack.FaultWrapper(auth.AuthMiddleware(
limits.RateLimitingMiddleware(inner_app10)))
api11 = openstack.FaultWrapper(auth.AuthMiddleware(
limits.RateLimitingMiddleware(
extensions.ExtensionMiddleware(inner_app11))))
Auth = auth
mapper = urlmap.URLMap()
mapper['/v1.0'] = api10
mapper['/v1.1'] = api11
mapper['/'] = openstack.FaultWrapper(versions.Versions())
return mapper
@@ -401,7 +393,7 @@ class FakeAuthManager(object):
if p:
return p
else:
raise exc.NotFound
raise exc.ProjectNotFound(project_id=pid)
def get_projects(self, user_id=None):
if not user_id:

View File

@@ -55,7 +55,7 @@ class AccountsTest(test.TestCase):
fakemgr.create_project('test2', superuser)
def test_get_account(self):
req = webob.Request.blank('/v1.0/accounts/test1')
req = webob.Request.blank('/v1.1/fake/accounts/test1')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
@@ -65,7 +65,7 @@ class AccountsTest(test.TestCase):
self.assertEqual(res.status_int, 200)
def test_account_delete(self):
req = webob.Request.blank('/v1.0/accounts/test1')
req = webob.Request.blank('/v1.1/fake/accounts/test1')
req.method = 'DELETE'
res = req.get_response(fakes.wsgi_app())
self.assertTrue('test1' not in fakes.FakeAuthManager.projects)
@@ -74,7 +74,7 @@ class AccountsTest(test.TestCase):
def test_account_create(self):
body = dict(account=dict(description='test account',
manager='id1'))
req = webob.Request.blank('/v1.0/accounts/newacct')
req = webob.Request.blank('/v1.1/fake/accounts/newacct')
req.headers["Content-Type"] = "application/json"
req.method = 'PUT'
req.body = json.dumps(body)
@@ -94,7 +94,7 @@ class AccountsTest(test.TestCase):
def test_account_update(self):
body = dict(account=dict(description='test account',
manager='id2'))
req = webob.Request.blank('/v1.0/accounts/test1')
req = webob.Request.blank('/v1.1/fake/accounts/test1')
req.headers["Content-Type"] = "application/json"
req.method = 'PUT'
req.body = json.dumps(body)

View File

@@ -1,47 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 OpenStack LLC.
# 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 webob
from nova import test
from nova.tests.api.openstack import fakes
class AdminAPITest(test.TestCase):
def setUp(self):
super(AdminAPITest, self).setUp()
fakes.stub_out_networking(self.stubs)
fakes.stub_out_rate_limiting(self.stubs)
self.flags(verbose=True)
def test_admin_enabled(self):
self.flags(allow_admin_api=True)
# We should still be able to access public operations.
req = webob.Request.blank('/v1.0/flavors')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
# TODO: Confirm admin operations are available.
def test_admin_disabled(self):
self.flags(allow_admin_api=False)
# We should still be able to access public operations.
req = webob.Request.blank('/v1.0/flavors')
res = req.get_response(fakes.wsgi_app())
# TODO: Confirm admin operations are unavailable.
self.assertEqual(res.status_int, 200)

View File

@@ -50,7 +50,7 @@ class Test(test.TestCase):
user = nova.auth.manager.User('id1', 'user1', 'user1_key', None, None)
f.add_user(user)
req = webob.Request.blank('/v1.0/')
req = webob.Request.blank('/v1.1/')
req.headers['X-Auth-User'] = 'user1'
req.headers['X-Auth-Key'] = 'user1_key'
req.headers['X-Auth-Project-Id'] = 'user1_project'
@@ -67,21 +67,21 @@ class Test(test.TestCase):
f.add_user(user)
f.create_project('user1_project', user)
req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'})
req = webob.Request.blank('/v1.1/', {'HTTP_HOST': 'foo'})
req.headers['X-Auth-User'] = 'user1'
req.headers['X-Auth-Key'] = 'user1_key'
result = req.get_response(fakes.wsgi_app(fake_auth=False))
self.assertEqual(result.status, '204 No Content')
self.assertEqual(len(result.headers['X-Auth-Token']), 40)
self.assertEqual(result.headers['X-Server-Management-Url'],
"http://foo/v1.0")
"http://foo/v1.1/user1_project")
self.assertEqual(result.headers['X-CDN-Management-Url'],
"")
self.assertEqual(result.headers['X-Storage-Url'], "")
token = result.headers['X-Auth-Token']
self.stubs.Set(nova.api.openstack, 'APIRouterV10', fakes.FakeRouter)
req = webob.Request.blank('/v1.0/user1_project')
self.stubs.Set(nova.api.openstack, 'APIRouter', fakes.FakeRouter)
req = webob.Request.blank('/v1.1/user1_project')
req.headers['X-Auth-Token'] = token
result = req.get_response(fakes.wsgi_app(fake_auth=False))
self.assertEqual(result.status, '200 OK')
@@ -105,7 +105,7 @@ class Test(test.TestCase):
self.stubs.Set(fakes.FakeAuthDatabase, 'auth_token_get',
bad_token)
req = webob.Request.blank('/v1.0/')
req = webob.Request.blank('/v1.1/')
req.headers['X-Auth-Token'] = 'token_hash'
result = req.get_response(fakes.wsgi_app(fake_auth=False))
self.assertEqual(result.status, '401 Unauthorized')
@@ -118,23 +118,22 @@ class Test(test.TestCase):
f.create_project('user1_project', user)
f.create_project('user2_project', user)
req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'})
req = webob.Request.blank('/v1.1/', {'HTTP_HOST': 'foo'})
req.headers['X-Auth-User'] = 'user1'
req.headers['X-Auth-Key'] = 'user1_key'
result = req.get_response(fakes.wsgi_app(fake_auth=False))
self.assertEqual(result.status, '204 No Content')
token = result.headers['X-Auth-Token']
self.stubs.Set(nova.api.openstack, 'APIRouterV10', fakes.FakeRouter)
req = webob.Request.blank('/v1.0/')
self.stubs.Set(nova.api.openstack, 'APIRouter', fakes.FakeRouter)
req = webob.Request.blank('/v1.1/user2_project')
req.headers['X-Auth-Token'] = token
req.headers['X-Auth-Project-Id'] = 'user2_project'
result = req.get_response(fakes.wsgi_app(fake_auth=False))
self.assertEqual(result.status, '200 OK')
self.assertEqual(result.headers['X-Test-Success'], 'True')
def test_bad_user_bad_key(self):
req = webob.Request.blank('/v1.0/')
req = webob.Request.blank('/v1.1/')
req.headers['X-Auth-User'] = 'unknown_user'
req.headers['X-Auth-Key'] = 'unknown_user_key'
req.headers['X-Auth-Project-Id'] = 'user_project'
@@ -146,19 +145,19 @@ class Test(test.TestCase):
user = nova.auth.manager.User('id1', 'user1', 'user1_key', None, None)
f.add_user(user)
req = webob.Request.blank('/v1.0/')
req = webob.Request.blank('/v1.1/')
req.headers['X-Auth-User'] = 'unknown_user'
req.headers['X-Auth-Key'] = 'user1_key'
result = req.get_response(fakes.wsgi_app(fake_auth=False))
self.assertEqual(result.status, '401 Unauthorized')
def test_no_user(self):
req = webob.Request.blank('/v1.0/')
req = webob.Request.blank('/v1.1/')
result = req.get_response(fakes.wsgi_app(fake_auth=False))
self.assertEqual(result.status, '401 Unauthorized')
def test_bad_token(self):
req = webob.Request.blank('/v1.0/')
req = webob.Request.blank('/v1.1/')
req.headers['X-Auth-Token'] = 'unknown_token'
result = req.get_response(fakes.wsgi_app(fake_auth=False))
self.assertEqual(result.status, '401 Unauthorized')
@@ -172,17 +171,16 @@ class Test(test.TestCase):
f.create_project('user1_project', user1)
f.create_project('user2_project', user2)
req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'})
req = webob.Request.blank('/v1.1/', {'HTTP_HOST': 'foo'})
req.headers['X-Auth-User'] = 'user1'
req.headers['X-Auth-Key'] = 'user1_key'
result = req.get_response(fakes.wsgi_app(fake_auth=False))
self.assertEqual(result.status, '204 No Content')
token = result.headers['X-Auth-Token']
self.stubs.Set(nova.api.openstack, 'APIRouterV10', fakes.FakeRouter)
req = webob.Request.blank('/v1.0/fake')
self.stubs.Set(nova.api.openstack, 'APIRouter', fakes.FakeRouter)
req = webob.Request.blank('/v1.1/user2_project')
req.headers['X-Auth-Token'] = token
req.headers['X-Auth-Project-Id'] = 'user2_project'
result = req.get_response(fakes.wsgi_app(fake_auth=False))
self.assertEqual(result.status, '401 Unauthorized')
@@ -192,17 +190,16 @@ class Test(test.TestCase):
f.add_user(user1)
f.create_project('user1_project', user1)
req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'})
req = webob.Request.blank('/v1.1/', {'HTTP_HOST': 'foo'})
req.headers['X-Auth-User'] = 'user1'
req.headers['X-Auth-Key'] = 'user1_key'
result = req.get_response(fakes.wsgi_app(fake_auth=False))
self.assertEqual(result.status, '204 No Content')
token = result.headers['X-Auth-Token']
self.stubs.Set(nova.api.openstack, 'APIRouterV10', fakes.FakeRouter)
req = webob.Request.blank('/v1.0/fake')
self.stubs.Set(nova.api.openstack, 'APIRouter', fakes.FakeRouter)
req = webob.Request.blank('/v1.1/')
req.headers['X-Auth-Token'] = token
req.headers['X-Auth-Project-Id'] = 'unknown_project'
result = req.get_response(fakes.wsgi_app(fake_auth=False))
self.assertEqual(result.status, '401 Unauthorized')
@@ -222,13 +219,13 @@ class TestFunctional(test.TestCase):
created_at=datetime.datetime(2000, 1, 1, 12, 0, 0),
))
req = webob.Request.blank('/v1.0/')
req = webob.Request.blank('/v1.1/')
req.headers['X-Auth-Token'] = 'test_token_hash'
result = req.get_response(fakes.wsgi_app(fake_auth=False))
self.assertEqual(result.status, '401 Unauthorized')
def test_token_doesnotexist(self):
req = webob.Request.blank('/v1.0/')
req = webob.Request.blank('/v1.1/')
req.headers['X-Auth-Token'] = 'nonexistant_token_hash'
result = req.get_response(fakes.wsgi_app(fake_auth=False))
self.assertEqual(result.status, '401 Unauthorized')
@@ -254,15 +251,15 @@ class TestLimiter(test.TestCase):
f.add_user(user)
f.create_project('test', user)
req = webob.Request.blank('/v1.0/')
req = webob.Request.blank('/v1.1/')
req.headers['X-Auth-User'] = 'user1'
req.headers['X-Auth-Key'] = 'user1_key'
result = req.get_response(fakes.wsgi_app(fake_auth=False))
self.assertEqual(len(result.headers['X-Auth-Token']), 40)
token = result.headers['X-Auth-Token']
self.stubs.Set(nova.api.openstack, 'APIRouterV10', fakes.FakeRouter)
req = webob.Request.blank('/v1.0/fake')
self.stubs.Set(nova.api.openstack, 'APIRouter', fakes.FakeRouter)
req = webob.Request.blank('/v1.1/test')
req.method = 'POST'
req.headers['X-Auth-Token'] = token
result = req.get_response(fakes.wsgi_app(fake_auth=False))

View File

@@ -106,7 +106,7 @@ class ConsolesTest(test.TestCase):
super(ConsolesTest, self).setUp()
self.flags(verbose=True)
self.stubs.Set(db.api, 'instance_get', return_server_by_id)
self.webreq = common.webob_factory('/v1.0/servers')
self.webreq = common.webob_factory('/v1.1/fake/servers')
def test_create_console(self):
def fake_create_console(cons_self, context, instance_id):
@@ -114,7 +114,7 @@ class ConsolesTest(test.TestCase):
return {}
self.stubs.Set(console.API, 'create_console', fake_create_console)
req = webob.Request.blank('/v1.0/servers/10/consoles')
req = webob.Request.blank('/v1.1/fake/servers/10/consoles')
req.method = "POST"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
@@ -136,7 +136,7 @@ class ConsolesTest(test.TestCase):
self.stubs.Set(console.API, 'get_console', fake_get_console)
req = webob.Request.blank('/v1.0/servers/10/consoles/20')
req = webob.Request.blank('/v1.1/fake/servers/10/consoles/20')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
res_dict = json.loads(res.body)
@@ -148,7 +148,7 @@ class ConsolesTest(test.TestCase):
self.stubs.Set(console.API, 'get_console', fake_get_console)
req = webob.Request.blank('/v1.0/servers/10/consoles/20')
req = webob.Request.blank('/v1.1/fake/servers/10/consoles/20')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 404)
@@ -158,7 +158,7 @@ class ConsolesTest(test.TestCase):
self.stubs.Set(console.API, 'get_console', fake_get_console)
req = webob.Request.blank('/v1.0/servers/10/consoles/20')
req = webob.Request.blank('/v1.1/fake/servers/10/consoles/20')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 404)
@@ -182,7 +182,7 @@ class ConsolesTest(test.TestCase):
self.stubs.Set(console.API, 'get_consoles', fake_get_consoles)
req = webob.Request.blank('/v1.0/servers/10/consoles')
req = webob.Request.blank('/v1.1/fake/servers/10/consoles')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
res_dict = json.loads(res.body)
@@ -204,7 +204,7 @@ class ConsolesTest(test.TestCase):
self.stubs.Set(console.API, 'get_console', fake_get_console)
self.stubs.Set(console.API, 'delete_console', fake_delete_console)
req = webob.Request.blank('/v1.0/servers/10/consoles/20')
req = webob.Request.blank('/v1.1/fake/servers/10/consoles/20')
req.method = "DELETE"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
@@ -215,7 +215,7 @@ class ConsolesTest(test.TestCase):
self.stubs.Set(console.API, 'delete_console', fake_delete_console)
req = webob.Request.blank('/v1.0/servers/10/consoles/20')
req = webob.Request.blank('/v1.1/fake/servers/10/consoles/20')
req.method = "DELETE"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 404)
@@ -226,7 +226,7 @@ class ConsolesTest(test.TestCase):
self.stubs.Set(console.API, 'delete_console', fake_delete_console)
req = webob.Request.blank('/v1.0/servers/10/consoles/20')
req = webob.Request.blank('/v1.1/fake/servers/10/consoles/20')
req.method = "DELETE"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 404)

View File

@@ -109,7 +109,7 @@ class ExtensionControllerTest(test.TestCase):
self.ext_list.sort()
def test_list_extensions_json(self):
app = openstack.APIRouterV11()
app = openstack.APIRouter()
ext_midware = extensions.ExtensionMiddleware(app)
request = webob.Request.blank("/123/extensions")
response = request.get_response(ext_midware)
@@ -135,7 +135,7 @@ class ExtensionControllerTest(test.TestCase):
)
def test_get_extension_json(self):
app = openstack.APIRouterV11()
app = openstack.APIRouter()
ext_midware = extensions.ExtensionMiddleware(app)
request = webob.Request.blank("/123/extensions/FOXNSOX")
response = request.get_response(ext_midware)
@@ -151,14 +151,14 @@ class ExtensionControllerTest(test.TestCase):
"links": []})
def test_get_non_existing_extension_json(self):
app = openstack.APIRouterV11()
app = openstack.APIRouter()
ext_midware = extensions.ExtensionMiddleware(app)
request = webob.Request.blank("/123/extensions/4")
response = request.get_response(ext_midware)
self.assertEqual(404, response.status_int)
def test_list_extensions_xml(self):
app = openstack.APIRouterV11()
app = openstack.APIRouter()
ext_midware = extensions.ExtensionMiddleware(app)
request = webob.Request.blank("/123/extensions")
request.accept = "application/xml"
@@ -185,7 +185,7 @@ class ExtensionControllerTest(test.TestCase):
xmlutil.validate_schema(root, 'extensions')
def test_get_extension_xml(self):
app = openstack.APIRouterV11()
app = openstack.APIRouter()
ext_midware = extensions.ExtensionMiddleware(app)
request = webob.Request.blank("/123/extensions/FOXNSOX")
request.accept = "application/xml"
@@ -216,7 +216,7 @@ class ResourceExtensionTest(test.TestCase):
def test_no_extension_present(self):
manager = StubExtensionManager(None)
app = openstack.APIRouterV11()
app = openstack.APIRouter()
ext_midware = extensions.ExtensionMiddleware(app, manager)
request = webob.Request.blank("/blah")
response = request.get_response(ext_midware)
@@ -226,7 +226,7 @@ class ResourceExtensionTest(test.TestCase):
res_ext = extensions.ResourceExtension('tweedles',
StubController(response_body))
manager = StubExtensionManager(res_ext)
app = openstack.APIRouterV11()
app = openstack.APIRouter()
ext_midware = extensions.ExtensionMiddleware(app, manager)
request = webob.Request.blank("/123/tweedles")
response = request.get_response(ext_midware)
@@ -237,7 +237,7 @@ class ResourceExtensionTest(test.TestCase):
res_ext = extensions.ResourceExtension('tweedles',
StubController(response_body))
manager = StubExtensionManager(res_ext)
app = openstack.APIRouterV11()
app = openstack.APIRouter()
ext_midware = extensions.ExtensionMiddleware(app, manager)
request = webob.Request.blank("/123/tweedles")
response = request.get_response(ext_midware)
@@ -261,7 +261,7 @@ class ExtensionManagerTest(test.TestCase):
self.flags(osapi_extensions_path=ext_path)
def test_get_resources(self):
app = openstack.APIRouterV11()
app = openstack.APIRouter()
ext_midware = extensions.ExtensionMiddleware(app)
request = webob.Request.blank("/123/foxnsocks")
response = request.get_response(ext_midware)
@@ -269,7 +269,7 @@ class ExtensionManagerTest(test.TestCase):
self.assertEqual(response_body, response.body)
def test_invalid_extensions(self):
app = openstack.APIRouterV11()
app = openstack.APIRouter()
ext_midware = extensions.ExtensionMiddleware(app)
ext_mgr = ext_midware.ext_mgr
ext_mgr.add_extension(InvalidExtension())
@@ -285,7 +285,7 @@ class ActionExtensionTest(test.TestCase):
self.flags(osapi_extensions_path=ext_path)
def _send_server_action_request(self, url, body):
app = openstack.APIRouterV11()
app = openstack.APIRouter()
ext_midware = extensions.ExtensionMiddleware(app)
request = webob.Request.blank(url)
request.method = 'POST'

View File

@@ -38,27 +38,6 @@ class TestFaults(test.TestCase):
xml_string = xml_string.replace("\t", "")
return xml_string
def test_400_fault_xml(self):
"""Test fault serialized to XML via file-extension and/or header."""
requests = [
webob.Request.blank('/.xml'),
webob.Request.blank('/', headers={"Accept": "application/xml"}),
]
for request in requests:
fault = faults.Fault(webob.exc.HTTPBadRequest(explanation='scram'))
response = request.get_response(fault)
expected = self._prepare_xml("""
<badRequest code="400" xmlns="%s">
<message>scram</message>
</badRequest>
""" % common.XML_NS_V10)
actual = self._prepare_xml(response.body)
self.assertEqual(response.content_type, "application/xml")
self.assertEqual(expected, actual)
def test_400_fault_json(self):
"""Test fault serialized to JSON via file-extension and/or header."""
requests = [
@@ -81,30 +60,6 @@ class TestFaults(test.TestCase):
self.assertEqual(response.content_type, "application/json")
self.assertEqual(expected, actual)
def test_413_fault_xml(self):
requests = [
webob.Request.blank('/.xml'),
webob.Request.blank('/', headers={"Accept": "application/xml"}),
]
for request in requests:
exc = webob.exc.HTTPRequestEntityTooLarge
fault = faults.Fault(exc(explanation='sorry',
headers={'Retry-After': 4}))
response = request.get_response(fault)
expected = self._prepare_xml("""
<overLimit code="413" xmlns="%s">
<message>sorry</message>
<retryAfter>4</retryAfter>
</overLimit>
""" % common.XML_NS_V10)
actual = self._prepare_xml(response.body)
self.assertEqual(expected, actual)
self.assertEqual(response.content_type, "application/xml")
self.assertEqual(response.headers['Retry-After'], 4)
def test_413_fault_json(self):
"""Test fault serialized to JSON via file-extension and/or header."""
requests = [
@@ -147,19 +102,7 @@ class TestFaults(test.TestCase):
fault = faults.Fault(webob.exc.HTTPBadRequest(explanation='what?'))
self.assertEqual(fault.status_int, 400)
def test_v10_xml_serializer(self):
"""Ensure that a v1.0 request responds with a v1.0 xmlns"""
request = webob.Request.blank('/',
headers={"Accept": "application/xml"})
fault = faults.Fault(webob.exc.HTTPBadRequest(explanation='scram'))
response = request.get_response(fault)
self.assertTrue(common.XML_NS_V10 in response.body)
self.assertEqual(response.content_type, "application/xml")
self.assertEqual(response.status_int, 400)
def test_v11_xml_serializer(self):
def test_xml_serializer(self):
"""Ensure that a v1.1 request responds with a v1.1 xmlns"""
request = webob.Request.blank('/v1.1',
headers={"Accept": "application/xml"})

View File

@@ -89,90 +89,15 @@ class FlavorsTest(test.TestCase):
self.stubs.UnsetAll()
super(FlavorsTest, self).tearDown()
def test_get_flavor_list_v1_0(self):
req = webob.Request.blank('/v1.0/flavors')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
flavors = json.loads(res.body)["flavors"]
expected = [
{
"id": "1",
"name": "flavor 1",
},
{
"id": "2",
"name": "flavor 2",
},
]
self.assertEqual(flavors, expected)
def test_get_empty_flavor_list_v1_0(self):
self.stubs.Set(nova.db.api, "instance_type_get_all",
empty_instance_type_get_all)
req = webob.Request.blank('/v1.0/flavors')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
flavors = json.loads(res.body)["flavors"]
expected = []
self.assertEqual(flavors, expected)
def test_get_flavor_list_detail_v1_0(self):
req = webob.Request.blank('/v1.0/flavors/detail')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
flavors = json.loads(res.body)["flavors"]
expected = [
{
"id": "1",
"name": "flavor 1",
"ram": "256",
"disk": "10",
"rxtx_cap": "",
"rxtx_quota": "",
"swap": "",
"vcpus": "",
},
{
"id": "2",
"name": "flavor 2",
"ram": "512",
"disk": "20",
"rxtx_cap": "",
"rxtx_quota": "",
"swap": "",
"vcpus": "",
},
]
self.assertEqual(flavors, expected)
def test_get_flavor_by_id_v1_0(self):
req = webob.Request.blank('/v1.0/flavors/1')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
flavor = json.loads(res.body)["flavor"]
expected = {
"id": "1",
"name": "flavor 1",
"ram": "256",
"disk": "10",
"rxtx_cap": "",
"rxtx_quota": "",
"swap": "",
"vcpus": "",
}
self.assertEqual(flavor, expected)
def test_get_flavor_by_invalid_id(self):
self.stubs.Set(nova.db.api, "instance_type_get_by_flavor_id",
return_instance_type_not_found)
req = webob.Request.blank('/v1.0/flavors/asdf')
req = webob.Request.blank('/v1.1/fake/flavors/asdf')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 404)
def test_get_flavor_by_id_v1_1(self):
def test_get_flavor_by_id(self):
req = webob.Request.blank('/v1.1/fake/flavors/1')
req.environ['api.version'] = '1.1'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
flavor = json.loads(res.body)
@@ -200,9 +125,8 @@ class FlavorsTest(test.TestCase):
}
self.assertEqual(flavor, expected)
def test_get_flavor_list_v1_1(self):
def test_get_flavor_list(self):
req = webob.Request.blank('/v1.1/fake/flavors')
req.environ['api.version'] = '1.1'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
flavor = json.loads(res.body)
@@ -240,9 +164,8 @@ class FlavorsTest(test.TestCase):
}
self.assertEqual(flavor, expected)
def test_get_flavor_list_detail_v1_1(self):
def test_get_flavor_list_detail(self):
req = webob.Request.blank('/v1.1/fake/flavors/detail')
req.environ['api.version'] = '1.1'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
flavor = json.loads(res.body)
@@ -292,7 +215,7 @@ class FlavorsTest(test.TestCase):
}
self.assertEqual(flavor, expected)
def test_get_empty_flavor_list_v1_1(self):
def test_get_empty_flavor_list(self):
self.stubs.Set(nova.db.api, "instance_type_get_all",
empty_instance_type_get_all)
@@ -303,10 +226,9 @@ class FlavorsTest(test.TestCase):
expected = []
self.assertEqual(flavors, expected)
def test_get_flavor_list_filter_min_ram_v1_1(self):
def test_get_flavor_list_filter_min_ram(self):
"""Flavor lists may be filtered by minRam"""
req = webob.Request.blank('/v1.1/fake/flavors?minRam=512')
req.environ['api.version'] = '1.1'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
flavor = json.loads(res.body)
@@ -333,7 +255,6 @@ class FlavorsTest(test.TestCase):
def test_get_flavor_list_filter_min_disk(self):
"""Flavor lists may be filtered by minRam"""
req = webob.Request.blank('/v1.1/fake/flavors?minDisk=20')
req.environ['api.version'] = '1.1'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
flavor = json.loads(res.body)
@@ -357,13 +278,12 @@ class FlavorsTest(test.TestCase):
}
self.assertEqual(flavor, expected)
def test_get_flavor_list_detail_min_ram_and_min_disk_v1_1(self):
def test_get_flavor_list_detail_min_ram_and_min_disk(self):
"""Tests that filtering work on flavor details and that minRam and
minDisk filters can be combined
"""
req = webob.Request.blank(
'/v1.1/fake/flavors/detail?minRam=256&minDisk=20')
req.environ['api.version'] = '1.1'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
flavor = json.loads(res.body)
@@ -393,11 +313,10 @@ class FlavorsTest(test.TestCase):
}
self.assertEqual(flavor, expected)
def test_get_flavor_list_detail_bogus_min_ram_v1_1(self):
def test_get_flavor_list_detail_bogus_min_ram(self):
"""Tests that bogus minRam filtering values are ignored"""
req = webob.Request.blank(
'/v1.1/fake/flavors/detail?minRam=16GB')
req.environ['api.version'] = '1.1'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
flavor = json.loads(res.body)
@@ -447,11 +366,10 @@ class FlavorsTest(test.TestCase):
}
self.assertEqual(flavor, expected)
def test_get_flavor_list_detail_bogus_min_disk_v1_1(self):
def test_get_flavor_list_detail_bogus_min_disk(self):
"""Tests that bogus minDisk filtering values are ignored"""
req = webob.Request.blank(
'/v1.1/fake/flavors/detail?minDisk=16GB')
req.environ['api.version'] = '1.1'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
flavor = json.loads(res.body)

View File

@@ -71,48 +71,7 @@ class ImagesTest(test.TestCase):
auth_token = True
return Context()
def test_get_image_index(self):
request = webob.Request.blank('/v1.0/images')
app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
response = request.get_response(app)
response_dict = json.loads(response.body)
response_list = response_dict["images"]
expected = [{'id': 123, 'name': 'public image'},
{'id': 124, 'name': 'queued snapshot'},
{'id': 125, 'name': 'saving snapshot'},
{'id': 126, 'name': 'active snapshot'},
{'id': 127, 'name': 'killed snapshot'},
{'id': 128, 'name': 'deleted snapshot'},
{'id': 129, 'name': 'pending_delete snapshot'},
{'id': 130, 'name': None}]
self.assertDictListMatch(response_list, expected)
def test_get_image(self):
request = webob.Request.blank('/v1.0/images/123')
app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
response = request.get_response(app)
self.assertEqual(200, response.status_int)
actual_image = json.loads(response.body)
expected_image = {
"image": {
"id": 123,
"name": "public image",
"updated": NOW_API_FORMAT,
"created": NOW_API_FORMAT,
"status": "ACTIVE",
"progress": 100,
},
}
self.assertDictMatch(expected_image, actual_image)
def test_get_image_v1_1(self):
self.maxDiff = None
request = webob.Request.blank('/v1.1/fake/images/124')
app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
@@ -169,82 +128,7 @@ class ImagesTest(test.TestCase):
self.assertEqual(expected_image, actual_image)
def test_get_image_xml(self):
request = webob.Request.blank('/v1.0/images/123')
request.accept = "application/xml"
app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
response = request.get_response(app)
actual_image = minidom.parseString(response.body.replace(" ", ""))
expected_now = NOW_API_FORMAT
expected_image = minidom.parseString("""
<image id="123"
name="public image"
updated="%(expected_now)s"
created="%(expected_now)s"
status="ACTIVE"
progress="100"
xmlns="http://docs.rackspacecloud.com/servers/api/v1.0" />
""" % (locals()))
self.assertEqual(expected_image.toxml(), actual_image.toxml())
def test_get_image_xml_no_name(self):
request = webob.Request.blank('/v1.0/images/130')
request.accept = "application/xml"
app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
response = request.get_response(app)
actual_image = minidom.parseString(response.body.replace(" ", ""))
expected_now = NOW_API_FORMAT
expected_image = minidom.parseString("""
<image id="130"
name="None"
updated="%(expected_now)s"
created="%(expected_now)s"
status="ACTIVE"
progress="100"
xmlns="http://docs.rackspacecloud.com/servers/api/v1.0" />
""" % (locals()))
self.assertEqual(expected_image.toxml(), actual_image.toxml())
def test_get_image_404_json(self):
request = webob.Request.blank('/v1.0/images/NonExistantImage')
response = request.get_response(fakes.wsgi_app())
self.assertEqual(404, response.status_int)
expected = {
"itemNotFound": {
"message": "Image not found.",
"code": 404,
},
}
actual = json.loads(response.body)
self.assertEqual(expected, actual)
def test_get_image_404_xml(self):
request = webob.Request.blank('/v1.0/images/NonExistantImage')
request.accept = "application/xml"
response = request.get_response(fakes.wsgi_app())
self.assertEqual(404, response.status_int)
expected = minidom.parseString("""
<itemNotFound code="404"
xmlns="http://docs.rackspacecloud.com/servers/api/v1.0">
<message>Image not found.</message>
</itemNotFound>
""".replace(" ", "").replace("\n", ""))
actual = minidom.parseString(response.body.replace(" ", ""))
self.assertEqual(expected.toxml(), actual.toxml())
def test_get_image_404_v1_1_json(self):
request = webob.Request.blank('/v1.1/fake/images/NonExistantImage')
response = request.get_response(fakes.wsgi_app())
self.assertEqual(404, response.status_int)
@@ -260,7 +144,7 @@ class ImagesTest(test.TestCase):
self.assertEqual(expected, actual)
def test_get_image_404_v1_1_xml(self):
def test_get_image_404_xml(self):
request = webob.Request.blank('/v1.1/fake/images/NonExistantImage')
request.accept = "application/xml"
response = request.get_response(fakes.wsgi_app())
@@ -279,7 +163,7 @@ class ImagesTest(test.TestCase):
self.assertEqual(expected.toxml(), actual.toxml())
def test_get_image_index_v1_1(self):
def test_get_image_index(self):
request = webob.Request.blank('/v1.1/fake/images')
app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
response = request.get_response(app)
@@ -454,7 +338,7 @@ class ImagesTest(test.TestCase):
self.assertDictListMatch(response_list, expected_images)
def test_get_image_index_v1_1_with_limit(self):
def test_get_image_index_with_limit(self):
request = webob.Request.blank('/v1.1/fake/images?limit=3')
app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
response = request.get_response(app)
@@ -533,7 +417,7 @@ class ImagesTest(test.TestCase):
params = urlparse.parse_qs(href_parts.query)
self.assertDictMatch({'limit': ['3'], 'marker': ['125']}, params)
def test_get_image_index_v1_1_with_limit_and_extra_params(self):
def test_get_image_index_with_limit_and_extra_params(self):
request = webob.Request.blank('/v1.1/fake/images?limit=3&extra=boo')
app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
response = request.get_response(app)
@@ -550,7 +434,7 @@ class ImagesTest(test.TestCase):
{'limit': ['3'], 'marker': ['125'], 'extra': ['boo']},
params)
def test_get_image_index_v1_1_with_big_limit(self):
def test_get_image_index_with_big_limit(self):
"""
Make sure we don't get images_links if limit is set
and the number of images returned is < limit
@@ -566,81 +450,6 @@ class ImagesTest(test.TestCase):
self.assertEqual(len(response_list), 8)
def test_get_image_details(self):
request = webob.Request.blank('/v1.0/images/detail')
app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
response = request.get_response(app)
response_dict = json.loads(response.body)
response_list = response_dict["images"]
expected = [{
'id': 123,
'name': 'public image',
'updated': NOW_API_FORMAT,
'created': NOW_API_FORMAT,
'status': 'ACTIVE',
'progress': 100,
},
{
'id': 124,
'name': 'queued snapshot',
'updated': NOW_API_FORMAT,
'created': NOW_API_FORMAT,
'status': 'SAVING',
'progress': 25,
},
{
'id': 125,
'name': 'saving snapshot',
'updated': NOW_API_FORMAT,
'created': NOW_API_FORMAT,
'status': 'SAVING',
'progress': 50,
},
{
'id': 126,
'name': 'active snapshot',
'updated': NOW_API_FORMAT,
'created': NOW_API_FORMAT,
'status': 'ACTIVE',
'progress': 100,
},
{
'id': 127,
'name': 'killed snapshot',
'updated': NOW_API_FORMAT,
'created': NOW_API_FORMAT,
'status': 'ERROR',
'progress': 0,
},
{
'id': 128,
'name': 'deleted snapshot',
'updated': NOW_API_FORMAT,
'created': NOW_API_FORMAT,
'status': 'DELETED',
'progress': 0,
},
{
'id': 129,
'name': 'pending_delete snapshot',
'updated': NOW_API_FORMAT,
'created': NOW_API_FORMAT,
'status': 'DELETED',
'progress': 0,
},
{
'id': 130,
'name': None,
'updated': NOW_API_FORMAT,
'created': NOW_API_FORMAT,
'status': 'ACTIVE',
'progress': 100,
}]
self.assertDictListMatch(expected, response_list)
def test_get_image_details_v1_1(self):
request = webob.Request.blank('/v1.1/fake/images/detail')
app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
response = request.get_response(app)
@@ -931,7 +740,7 @@ class ImagesTest(test.TestCase):
self.assertDictListMatch(expected, response_list)
def test_get_image_details_with_limit_v1_1(self):
def test_get_image_details_with_limit(self):
request = webob.Request.blank('/v1.1/fake/images/detail?limit=2')
app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
response = request.get_response(app)
@@ -1022,7 +831,7 @@ class ImagesTest(test.TestCase):
self.mox.ReplayAll()
request = webob.Request.blank('/v1.1/images?name=testname')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.index(request)
self.mox.VerifyAll()
@@ -1034,7 +843,7 @@ class ImagesTest(test.TestCase):
self.mox.ReplayAll()
request = webob.Request.blank('/v1.1/images?minRam=0')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.index(request)
self.mox.VerifyAll()
@@ -1046,7 +855,7 @@ class ImagesTest(test.TestCase):
self.mox.ReplayAll()
request = webob.Request.blank('/v1.1/images?minDisk=7')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.index(request)
self.mox.VerifyAll()
@@ -1058,7 +867,7 @@ class ImagesTest(test.TestCase):
self.mox.ReplayAll()
request = webob.Request.blank('/v1.1/images?status=ACTIVE')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.index(request)
self.mox.VerifyAll()
@@ -1070,7 +879,7 @@ class ImagesTest(test.TestCase):
self.mox.ReplayAll()
request = webob.Request.blank('/v1.1/images?property-test=3')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.index(request)
self.mox.VerifyAll()
@@ -1084,7 +893,7 @@ class ImagesTest(test.TestCase):
request = webob.Request.blank('/v1.1/images?server='
'http://localhost:8774/servers/12')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.index(request)
self.mox.VerifyAll()
@@ -1097,7 +906,7 @@ class ImagesTest(test.TestCase):
request = webob.Request.blank('/v1.1/images?changes-since='
'2011-01-24T17:08Z')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.index(request)
self.mox.VerifyAll()
@@ -1109,7 +918,7 @@ class ImagesTest(test.TestCase):
self.mox.ReplayAll()
request = webob.Request.blank('/v1.1/images?type=BASE')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.index(request)
self.mox.VerifyAll()
@@ -1122,7 +931,7 @@ class ImagesTest(test.TestCase):
request = webob.Request.blank('/v1.1/images?status=ACTIVE&'
'UNSUPPORTEDFILTER=testname')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.detail(request)
self.mox.VerifyAll()
@@ -1136,7 +945,7 @@ class ImagesTest(test.TestCase):
request = webob.Request.blank(
'/v1.1/images')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.index(request)
self.mox.VerifyAll()
@@ -1148,7 +957,7 @@ class ImagesTest(test.TestCase):
self.mox.ReplayAll()
request = webob.Request.blank('/v1.1/fake/images/detail?name=testname')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.detail(request)
self.mox.VerifyAll()
@@ -1160,7 +969,7 @@ class ImagesTest(test.TestCase):
self.mox.ReplayAll()
request = webob.Request.blank('/v1.1/fake/images/detail?status=ACTIVE')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.detail(request)
self.mox.VerifyAll()
@@ -1173,7 +982,7 @@ class ImagesTest(test.TestCase):
request = webob.Request.blank(
'/v1.1/fake/images/detail?property-test=3')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.detail(request)
self.mox.VerifyAll()
@@ -1187,7 +996,7 @@ class ImagesTest(test.TestCase):
request = webob.Request.blank('/v1.1/fake/images/detail?server='
'http://localhost:8774/servers/12')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.index(request)
self.mox.VerifyAll()
@@ -1200,7 +1009,7 @@ class ImagesTest(test.TestCase):
request = webob.Request.blank('/v1.1/fake/images/detail?changes-since='
'2011-01-24T17:08Z')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.index(request)
self.mox.VerifyAll()
@@ -1212,7 +1021,7 @@ class ImagesTest(test.TestCase):
self.mox.ReplayAll()
request = webob.Request.blank('/v1.1/fake/images/detail?type=BASE')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.index(request)
self.mox.VerifyAll()
@@ -1225,7 +1034,7 @@ class ImagesTest(test.TestCase):
request = webob.Request.blank('/v1.1/fake/images/detail?status=ACTIVE&'
'UNSUPPORTEDFILTER=testname')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.detail(request)
self.mox.VerifyAll()
@@ -1237,82 +1046,24 @@ class ImagesTest(test.TestCase):
self.mox.ReplayAll()
request = webob.Request.blank('/v1.1/fake/images/detail')
request.environ['nova.context'] = context
controller = images.ControllerV11(image_service=image_service)
controller = images.Controller(image_service=image_service)
controller.detail(request)
self.mox.VerifyAll()
def test_get_image_found(self):
req = webob.Request.blank('/v1.0/images/123')
app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
res = req.get_response(app)
image_meta = json.loads(res.body)['image']
expected = {'id': 123, 'name': 'public image',
'updated': NOW_API_FORMAT,
'created': NOW_API_FORMAT, 'status': 'ACTIVE',
'progress': 100}
self.assertDictMatch(image_meta, expected)
def test_get_image_non_existent(self):
req = webob.Request.blank('/v1.0/images/4242')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 404)
def test_create_image(self):
body = dict(image=dict(serverId='123', name='Snapshot 1'))
req = webob.Request.blank('/v1.0/images')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(200, response.status_int)
image_meta = json.loads(response.body)['image']
self.assertEqual(123, image_meta['serverId'])
self.assertEqual('Snapshot 1', image_meta['name'])
def test_create_snapshot_no_name(self):
"""Name is required for snapshots"""
body = dict(image=dict(serverId='123'))
req = webob.Request.blank('/v1.0/images')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(400, response.status_int)
def test_create_image_no_server_id(self):
body = dict(image=dict(name='Snapshot 1'))
req = webob.Request.blank('/v1.0/images')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(400, response.status_int)
def test_create_image_snapshots_disabled(self):
self.flags(allow_instance_snapshots=False)
body = dict(image=dict(serverId='123', name='Snapshot 1'))
req = webob.Request.blank('/v1.0/images')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(400, response.status_int)
def test_generate_alternate(self):
view = images_view.ViewBuilderV11(1)
def test_generate_alternate_link(self):
view = images_view.ViewBuilder(1)
generated_url = view.generate_alternate(1)
actual_url = "%s//images/1" % utils.generate_glance_url()
self.assertEqual(generated_url, actual_url)
def test_delete_image_v1_1(self):
def test_delete_image(self):
request = webob.Request.blank('/v1.1/fake/images/124')
request.method = 'DELETE'
app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
response = request.get_response(app)
self.assertEqual(response.status_int, 204)
def test_delete_image_not_found_v1_1(self):
def test_delete_image_not_found(self):
request = webob.Request.blank('/v1.1/fake/images/300')
request.method = 'DELETE'
app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())

View File

@@ -72,149 +72,15 @@ class BaseLimitTestSuite(unittest.TestCase):
return self.time
class LimitsControllerV10Test(BaseLimitTestSuite):
class LimitsControllerTest(BaseLimitTestSuite):
"""
Tests for `limits.LimitsControllerV10` class.
Tests for `limits.LimitsController` class.
"""
def setUp(self):
"""Run before each test."""
BaseLimitTestSuite.setUp(self)
self.controller = limits.create_resource('1.0')
def _get_index_request(self, accept_header="application/json"):
"""Helper to set routing arguments."""
request = webob.Request.blank("/")
request.accept = accept_header
request.environ["wsgiorg.routing_args"] = (None, {
"action": "index",
"controller": "",
})
context = nova.context.RequestContext('testuser', 'testproject')
request.environ["nova.context"] = context
return request
def _populate_limits(self, request):
"""Put limit info into a request."""
_limits = [
limits.Limit("GET", "*", ".*", 10, 60).display(),
limits.Limit("POST", "*", ".*", 5, 60 * 60).display(),
]
request.environ["nova.limits"] = _limits
return request
def _setup_absolute_limits(self):
self.absolute_limits = {
'instances': 5,
'cores': 8,
'ram': 2 ** 13,
'volumes': 21,
'gigabytes': 34,
'metadata_items': 55,
'injected_files': 89,
'injected_file_content_bytes': 144,
}
def test_empty_index_json(self):
"""Test getting empty limit details in JSON."""
request = self._get_index_request()
response = request.get_response(self.controller)
expected = {
"limits": {
"rate": [],
"absolute": {},
},
}
body = json.loads(response.body)
self.assertEqual(expected, body)
def test_index_json(self):
"""Test getting limit details in JSON."""
request = self._get_index_request()
request = self._populate_limits(request)
self._setup_absolute_limits()
response = request.get_response(self.controller)
expected = {
"limits": {
"rate": [{
"regex": ".*",
"resetTime": 0,
"URI": "*",
"value": 10,
"verb": "GET",
"remaining": 10,
"unit": "MINUTE",
},
{
"regex": ".*",
"resetTime": 0,
"URI": "*",
"value": 5,
"verb": "POST",
"remaining": 5,
"unit": "HOUR",
}],
"absolute": {
"maxTotalInstances": 5,
"maxTotalCores": 8,
"maxTotalRAMSize": 2 ** 13,
"maxServerMeta": 55,
"maxImageMeta": 55,
"maxPersonality": 89,
"maxPersonalitySize": 144,
},
},
}
body = json.loads(response.body)
self.assertEqual(expected, body)
def test_empty_index_xml(self):
"""Test getting limit details in XML."""
request = self._get_index_request("application/xml")
response = request.get_response(self.controller)
expected = minidom.parseString("""
<limits xmlns="http://docs.rackspacecloud.com/servers/api/v1.0">
<rate/>
<absolute/>
</limits>
""".replace(" ", "").replace("\n", ""))
body = minidom.parseString(response.body.replace(" ", ""))
self.assertEqual(expected.toxml(), body.toxml())
def test_index_xml(self):
"""Test getting limit details in XML."""
request = self._get_index_request("application/xml")
request = self._populate_limits(request)
response = request.get_response(self.controller)
expected = minidom.parseString("""
<limits xmlns="http://docs.rackspacecloud.com/servers/api/v1.0">
<rate>
<limit URI="*" regex=".*" remaining="10" resetTime="0"
unit="MINUTE" value="10" verb="GET"/>
<limit URI="*" regex=".*" remaining="5" resetTime="0"
unit="HOUR" value="5" verb="POST"/>
</rate>
<absolute/>
</limits>
""".replace(" ", "").replace("\n", ""))
body = minidom.parseString(response.body.replace(" ", ""))
self.assertEqual(expected.toxml(), body.toxml())
class LimitsControllerV11Test(BaseLimitTestSuite):
"""
Tests for `limits.LimitsControllerV11` class.
"""
def setUp(self):
"""Run before each test."""
BaseLimitTestSuite.setUp(self)
self.controller = limits.create_resource('1.1')
self.controller = limits.create_resource()
self.maxDiff = None
def _get_index_request(self, accept_header="application/json"):
@@ -915,10 +781,10 @@ class WsgiLimiterProxyTest(BaseLimitTestSuite):
self.assertEqual((delay, error), expected)
class LimitsViewBuilderV11Test(test.TestCase):
class LimitsViewBuilderTest(test.TestCase):
def setUp(self):
self.view_builder = views.limits.ViewBuilderV11()
self.view_builder = views.limits.ViewBuilder()
self.rate_limits = [{"URI": "*",
"regex": ".*",
"value": 10,

View File

@@ -117,368 +117,7 @@ class ServerActionsTest(test.TestCase):
def setUp(self):
self.maxDiff = None
super(ServerActionsTest, self).setUp()
self.flags(verbose=True)
self.stubs = stubout.StubOutForTesting()
fakes.stub_out_auth(self.stubs)
self.stubs.Set(nova.db.api, 'instance_get', return_server_by_id)
self.stubs.Set(nova.db.api, 'instance_update', instance_update)
self.webreq = common.webob_factory('/v1.0/servers')
def tearDown(self):
self.stubs.UnsetAll()
def test_server_change_password(self):
body = {'changePassword': {'adminPass': '1234pass'}}
req = webob.Request.blank('/v1.0/servers/1/action')
req.method = 'POST'
req.content_type = 'application/json'
req.body = json.dumps(body)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 501)
def test_server_change_password_xml(self):
req = webob.Request.blank('/v1.0/servers/1/action')
req.method = 'POST'
req.content_type = 'application/xml'
req.body = '<changePassword adminPass="1234pass">'
# res = req.get_response(fakes.wsgi_app())
# self.assertEqual(res.status_int, 501)
def test_server_reboot(self):
body = dict(server=dict(
name='server_test', imageId=2, flavorId=2, metadata={},
personality={}))
req = webob.Request.blank('/v1.0/servers/1/action')
req.method = 'POST'
req.content_type = 'application/json'
req.body = json.dumps(body)
res = req.get_response(fakes.wsgi_app())
def test_server_rebuild_accepted(self):
body = {
"rebuild": {
"imageId": 2,
},
}
req = webob.Request.blank('/v1.0/servers/1/action')
req.method = 'POST'
req.content_type = 'application/json'
req.body = json.dumps(body)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
self.assertEqual(res.body, "")
def test_server_rebuild_rejected_when_building(self):
body = {
"rebuild": {
"imageId": 2,
},
}
state = vm_states.BUILDING
new_return_server = return_server_with_state(state)
self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
self.stubs.Set(nova.db, 'instance_get_by_uuid',
return_server_with_uuid_and_state(state))
req = webob.Request.blank('/v1.0/servers/1/action')
req.method = 'POST'
req.content_type = 'application/json'
req.body = json.dumps(body)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 409)
def test_server_rebuild_bad_entity(self):
body = {
"rebuild": {
},
}
req = webob.Request.blank('/v1.0/servers/1/action')
req.method = 'POST'
req.content_type = 'application/json'
req.body = json.dumps(body)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_resize_server(self):
req = self.webreq('/1/action', 'POST', dict(resize=dict(flavorId=3)))
self.resize_called = False
def resize_mock(*args):
self.resize_called = True
self.stubs.Set(nova.compute.api.API, 'resize', resize_mock)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
self.assertEqual(self.resize_called, True)
def test_resize_bad_flavor_fails(self):
req = self.webreq('/1/action', 'POST', dict(resize=dict(derp=3)))
self.resize_called = False
def resize_mock(*args):
self.resize_called = True
self.stubs.Set(nova.compute.api.API, 'resize', resize_mock)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
self.assertEqual(self.resize_called, False)
def test_resize_raises_fails(self):
req = self.webreq('/1/action', 'POST', dict(resize=dict(flavorId=3)))
def resize_mock(*args):
raise Exception('hurr durr')
self.stubs.Set(nova.compute.api.API, 'resize', resize_mock)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 500)
def test_confirm_resize_server(self):
req = self.webreq('/1/action', 'POST', dict(confirmResize=None))
self.resize_called = False
def confirm_resize_mock(*args):
self.resize_called = True
self.stubs.Set(nova.compute.api.API, 'confirm_resize',
confirm_resize_mock)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 204)
self.assertEqual(self.resize_called, True)
def test_confirm_resize_server_fails(self):
req = self.webreq('/1/action', 'POST', dict(confirmResize=None))
def confirm_resize_mock(*args):
raise Exception('hurr durr')
self.stubs.Set(nova.compute.api.API, 'confirm_resize',
confirm_resize_mock)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_confirm_resize_migration_not_found(self):
req = self.webreq('/1/action', 'POST', dict(confirmResize=None))
def confirm_resize_mock(*args):
raise exception.MigrationNotFoundByStatus(instance_id=1,
status='finished')
self.stubs.Set(nova.compute.api.API,
'confirm_resize',
confirm_resize_mock)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_revert_resize_server(self):
req = self.webreq('/1/action', 'POST', dict(revertResize=None))
self.resize_called = False
def revert_resize_mock(*args):
self.resize_called = True
self.stubs.Set(nova.compute.api.API, 'revert_resize',
revert_resize_mock)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
self.assertEqual(self.resize_called, True)
def test_revert_resize_server_fails(self):
req = self.webreq('/1/action', 'POST', dict(revertResize=None))
def revert_resize_mock(*args):
raise Exception('hurr durr')
self.stubs.Set(nova.compute.api.API, 'revert_resize',
revert_resize_mock)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_revert_resize_migration_not_found(self):
req = self.webreq('/1/action', 'POST', dict(revertResize=None))
def revert_resize_mock(*args):
raise exception.MigrationNotFoundByStatus(instance_id=1,
status='finished')
self.stubs.Set(nova.compute.api.API,
'revert_resize',
revert_resize_mock)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_create_backup(self):
"""The happy path for creating backups"""
self.flags(allow_admin_api=True)
body = {
'createBackup': {
'name': 'Backup 1',
'backup_type': 'daily',
'rotation': 1,
},
}
req = webob.Request.blank('/v1.0/servers/1/action')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(202, response.status_int)
self.assertTrue(response.headers['Location'])
def test_create_backup_admin_api_off(self):
"""The happy path for creating backups"""
self.flags(allow_admin_api=False)
body = {
'createBackup': {
'name': 'Backup 1',
'backup_type': 'daily',
'rotation': 1,
},
}
req = webob.Request.blank('/v1.0/servers/1/action')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(400, response.status_int)
def test_create_backup_with_metadata(self):
self.flags(allow_admin_api=True)
body = {
'createBackup': {
'name': 'Backup 1',
'backup_type': 'daily',
'rotation': 1,
'metadata': {'123': 'asdf'},
},
}
req = webob.Request.blank('/v1.0/servers/1/action')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(202, response.status_int)
self.assertTrue(response.headers['Location'])
def test_create_backup_with_too_much_metadata(self):
self.flags(allow_admin_api=True)
body = {
'createBackup': {
'name': 'Backup 1',
'backup_type': 'daily',
'rotation': 1,
'metadata': {'123': 'asdf'},
},
}
for num in range(FLAGS.quota_metadata_items + 1):
body['createBackup']['metadata']['foo%i' % num] = "bar"
req = webob.Request.blank('/v1.0/servers/1/action')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(413, response.status_int)
def test_create_backup_no_name(self):
"""Name is required for backups"""
self.flags(allow_admin_api=True)
body = {
'createBackup': {
'backup_type': 'daily',
'rotation': 1,
},
}
req = webob.Request.blank('/v1.0/images')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(400, response.status_int)
def test_create_backup_no_rotation(self):
"""Rotation is required for backup requests"""
self.flags(allow_admin_api=True)
body = {
'createBackup': {
'name': 'Backup 1',
'backup_type': 'daily',
},
}
req = webob.Request.blank('/v1.0/images')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(400, response.status_int)
def test_create_backup_no_backup_type(self):
"""Backup Type (daily or weekly) is required for backup requests"""
self.flags(allow_admin_api=True)
body = {
'createBackup': {
'name': 'Backup 1',
'rotation': 1,
},
}
req = webob.Request.blank('/v1.0/images')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(400, response.status_int)
def test_create_backup_bad_entity(self):
self.flags(allow_admin_api=True)
body = {'createBackup': 'go'}
req = webob.Request.blank('/v1.0/images')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(400, response.status_int)
class ServerActionsTestV11(test.TestCase):
def setUp(self):
self.maxDiff = None
super(ServerActionsTestV11, self).setUp()
self.stubs = stubout.StubOutForTesting()
fakes.stub_out_auth(self.stubs)
self.stubs.Set(nova.db.api, 'instance_get', return_server_by_id)
@@ -851,6 +490,42 @@ class ServerActionsTestV11(test.TestCase):
self.assertEqual(res.status_int, 204)
self.assertEqual(self.confirm_resize_called, True)
def test_confirm_resize_migration_not_found(self):
req = webob.Request.blank('/v1.1/fake/servers/1/action')
req.content_type = 'application/json'
req.method = 'POST'
body_dict = dict(confirmResize=None)
req.body = json.dumps(body_dict)
def confirm_resize_mock(*args):
raise exception.MigrationNotFoundByStatus(instance_id=1,
status='finished')
self.stubs.Set(nova.compute.api.API,
'confirm_resize',
confirm_resize_mock)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_revert_resize_migration_not_found(self):
req = webob.Request.blank('/v1.1/fake/servers/1/action')
req.content_type = 'application/json'
req.method = 'POST'
body_dict = dict(revertResize=None)
req.body = json.dumps(body_dict)
def revert_resize_mock(*args):
raise exception.MigrationNotFoundByStatus(instance_id=1,
status='finished')
self.stubs.Set(nova.compute.api.API,
'revert_resize',
revert_resize_mock)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_revert_resize_server(self):
req = webob.Request.blank('/v1.1/fake/servers/1/action')
req.content_type = 'application/json'
@@ -978,11 +653,137 @@ class ServerActionsTestV11(test.TestCase):
self.assertEqual(202, response.status_int)
self.assertTrue(response.headers['Location'])
def test_create_backup_admin_api_off(self):
"""The happy path for creating backups"""
self.flags(allow_admin_api=False)
class TestServerActionXMLDeserializerV11(test.TestCase):
body = {
'createBackup': {
'name': 'Backup 1',
'backup_type': 'daily',
'rotation': 1,
},
}
req = webob.Request.blank('/v1.1/fake/servers/1/action')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(400, response.status_int)
def test_create_backup_with_metadata(self):
self.flags(allow_admin_api=True)
body = {
'createBackup': {
'name': 'Backup 1',
'backup_type': 'daily',
'rotation': 1,
'metadata': {'123': 'asdf'},
},
}
req = webob.Request.blank('/v1.1/fake/servers/1/action')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(202, response.status_int)
self.assertTrue(response.headers['Location'])
def test_create_backup_with_too_much_metadata(self):
self.flags(allow_admin_api=True)
body = {
'createBackup': {
'name': 'Backup 1',
'backup_type': 'daily',
'rotation': 1,
'metadata': {'123': 'asdf'},
},
}
for num in range(FLAGS.quota_metadata_items + 1):
body['createBackup']['metadata']['foo%i' % num] = "bar"
req = webob.Request.blank('/v1.1/fake/servers/1/action')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(413, response.status_int)
def test_create_backup_no_name(self):
"""Name is required for backups"""
self.flags(allow_admin_api=True)
body = {
'createBackup': {
'backup_type': 'daily',
'rotation': 1,
},
}
req = webob.Request.blank('/v1.1/fake/servers/1/action')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(400, response.status_int)
def test_create_backup_no_rotation(self):
"""Rotation is required for backup requests"""
self.flags(allow_admin_api=True)
body = {
'createBackup': {
'name': 'Backup 1',
'backup_type': 'daily',
},
}
req = webob.Request.blank('/v1.1/fake/servers/1/action')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(400, response.status_int)
def test_create_backup_no_backup_type(self):
"""Backup Type (daily or weekly) is required for backup requests"""
self.flags(allow_admin_api=True)
body = {
'createBackup': {
'name': 'Backup 1',
'rotation': 1,
},
}
req = webob.Request.blank('/v1.1/fake/servers/1/action')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(400, response.status_int)
def test_create_backup_bad_entity(self):
self.flags(allow_admin_api=True)
body = {'createBackup': 'go'}
req = webob.Request.blank('/v1.1/fake/servers/1/action')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
self.assertEqual(400, response.status_int)
class TestServerActionXMLDeserializer(test.TestCase):
def setUp(self):
self.deserializer = servers.ServerXMLDeserializerV11()
self.deserializer = servers.ServerXMLDeserializer()
def tearDown(self):
pass

File diff suppressed because it is too large Load Diff

View File

@@ -1,51 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 OpenStack LLC.
# 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 webob
from nova import test
from nova.tests.api.openstack import fakes
class SharedIpGroupsTest(test.TestCase):
def test_get_shared_ip_groups(self):
req = webob.Request.blank('/v1.0/shared_ip_groups')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 501)
def test_create_shared_ip_group(self):
req = webob.Request.blank('/v1.0/shared_ip_groups')
req.method = 'POST'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 501)
def test_update_shared_ip_group(self):
req = webob.Request.blank('/v1.0/shared_ip_groups/12')
req.method = 'PUT'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 501)
def test_delete_shared_ip_group(self):
req = webob.Request.blank('/v1.0/shared_ip_groups/12')
req.method = 'DELETE'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 501)
def test_deprecated_v11(self):
req = webob.Request.blank('/v1.1/shared_ip_groups')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 404)

View File

@@ -28,16 +28,6 @@ class UrlmapTest(test.TestCase):
super(UrlmapTest, self).setUp()
fakes.stub_out_rate_limiting(self.stubs)
def test_path_version_v1_0(self):
"""Test URL path specifying v1.0 returns v1.0 content."""
req = webob.Request.blank('/v1.0/')
req.accept = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
self.assertEqual(res.content_type, "application/json")
body = json.loads(res.body)
self.assertEqual(body['version']['id'], 'v1.0')
def test_path_version_v1_1(self):
"""Test URL path specifying v1.1 returns v1.1 content."""
req = webob.Request.blank('/v1.1/')
@@ -48,17 +38,6 @@ class UrlmapTest(test.TestCase):
body = json.loads(res.body)
self.assertEqual(body['version']['id'], 'v1.1')
def test_content_type_version_v1_0(self):
"""Test Content-Type specifying v1.0 returns v1.0 content."""
req = webob.Request.blank('/')
req.content_type = "application/json;version=1.0"
req.accept = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
self.assertEqual(res.content_type, "application/json")
body = json.loads(res.body)
self.assertEqual(body['version']['id'], 'v1.0')
def test_content_type_version_v1_1(self):
"""Test Content-Type specifying v1.1 returns v1.1 content."""
req = webob.Request.blank('/')
@@ -70,16 +49,6 @@ class UrlmapTest(test.TestCase):
body = json.loads(res.body)
self.assertEqual(body['version']['id'], 'v1.1')
def test_accept_version_v1_0(self):
"""Test Accept header specifying v1.0 returns v1.0 content."""
req = webob.Request.blank('/')
req.accept = "application/json;version=1.0"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
self.assertEqual(res.content_type, "application/json")
body = json.loads(res.body)
self.assertEqual(body['version']['id'], 'v1.0')
def test_accept_version_v1_1(self):
"""Test Accept header specifying v1.1 returns v1.1 content."""
req = webob.Request.blank('/')

View File

@@ -56,7 +56,7 @@ class UsersTest(test.TestCase):
fakemgr.add_user(User('id2', 'guy2', 'acc2', 'secret2', True))
def test_get_user_list(self):
req = webob.Request.blank('/v1.0/users')
req = webob.Request.blank('/v1.1/fake/users')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
@@ -64,7 +64,7 @@ class UsersTest(test.TestCase):
self.assertEqual(len(res_dict['users']), 2)
def test_get_user_by_id(self):
req = webob.Request.blank('/v1.0/users/id2')
req = webob.Request.blank('/v1.1/fake/users/id2')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
@@ -76,7 +76,7 @@ class UsersTest(test.TestCase):
def test_user_delete(self):
# Check the user exists
req = webob.Request.blank('/v1.0/users/id1')
req = webob.Request.blank('/v1.1/fake/users/id1')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
@@ -84,7 +84,7 @@ class UsersTest(test.TestCase):
self.assertEqual(res.status_int, 200)
# Delete the user
req = webob.Request.blank('/v1.0/users/id1')
req = webob.Request.blank('/v1.1/fake/users/id1')
req.method = 'DELETE'
res = req.get_response(fakes.wsgi_app())
self.assertTrue('id1' not in [u.id for u in
@@ -92,7 +92,7 @@ class UsersTest(test.TestCase):
self.assertEqual(res.status_int, 200)
# Check the user is not returned (and returns 404)
req = webob.Request.blank('/v1.0/users/id1')
req = webob.Request.blank('/v1.1/fake/users/id1')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
self.assertEqual(res.status_int, 404)
@@ -103,7 +103,7 @@ class UsersTest(test.TestCase):
access='acc3',
secret=secret,
admin=True))
req = webob.Request.blank('/v1.0/users')
req = webob.Request.blank('/v1.1/fake/users')
req.headers["Content-Type"] = "application/json"
req.method = 'POST'
req.body = json.dumps(body)
@@ -130,7 +130,7 @@ class UsersTest(test.TestCase):
body = dict(user=dict(name='guy2',
access='acc2',
secret=new_secret))
req = webob.Request.blank('/v1.0/users/id2')
req = webob.Request.blank('/v1.1/fake/users/id2')
req.headers["Content-Type"] = "application/json"
req.method = 'PUT'
req.body = json.dumps(body)

View File

@@ -35,35 +35,6 @@ NS = {
'ns': 'http://docs.openstack.org/compute/api/v1.1'
}
VERSIONS = {
"v1.0": {
"id": "v1.0",
"status": "DEPRECATED",
"updated": "2011-01-21T11:33:21Z",
"links": [
{
"rel": "describedby",
"type": "application/pdf",
"href": "http://docs.rackspacecloud.com/"
"servers/api/v1.0/cs-devguide-20110125.pdf",
},
{
"rel": "describedby",
"type": "application/vnd.sun.wadl+xml",
"href": "http://docs.rackspacecloud.com/"
"servers/api/v1.0/application.wadl",
},
],
"media-types": [
{
"base": "application/xml",
"type": "application/vnd.openstack.compute+xml;version=1.0",
},
{
"base": "application/json",
"type": "application/vnd.openstack.compute+json;version=1.0",
},
],
},
"v1.1": {
"id": "v1.1",
"status": "CURRENT",
@@ -118,16 +89,6 @@ class VersionsTest(test.TestCase):
self.assertEqual(res.content_type, "application/json")
versions = json.loads(res.body)["versions"]
expected = [
{
"id": "v1.0",
"status": "DEPRECATED",
"updated": "2011-01-21T11:33:21Z",
"links": [
{
"rel": "self",
"href": "http://localhost/v1.0/",
}],
},
{
"id": "v1.1",
"status": "CURRENT",
@@ -141,52 +102,6 @@ class VersionsTest(test.TestCase):
]
self.assertEqual(versions, expected)
def test_get_version_1_0_detail(self):
req = webob.Request.blank('/v1.0/')
req.accept = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
self.assertEqual(res.content_type, "application/json")
version = json.loads(res.body)
expected = {
"version": {
"id": "v1.0",
"status": "DEPRECATED",
"updated": "2011-01-21T11:33:21Z",
"links": [
{
"rel": "self",
"href": "http://localhost/v1.0/",
},
{
"rel": "describedby",
"type": "application/pdf",
"href": "http://docs.rackspacecloud.com/"
"servers/api/v1.0/cs-devguide-20110125.pdf",
},
{
"rel": "describedby",
"type": "application/vnd.sun.wadl+xml",
"href": "http://docs.rackspacecloud.com/"
"servers/api/v1.0/application.wadl",
},
],
"media-types": [
{
"base": "application/xml",
"type": "application/"
"vnd.openstack.compute+xml;version=1.0",
},
{
"base": "application/json",
"type": "application/"
"vnd.openstack.compute+json;version=1.0",
},
],
},
}
self.assertEqual(expected, version)
def test_get_version_1_1_detail(self):
req = webob.Request.blank('/v1.1/')
req.accept = "application/json"
@@ -279,29 +194,6 @@ class VersionsTest(test.TestCase):
}
self.assertEqual(expected, version)
def test_get_version_1_0_detail_xml(self):
req = webob.Request.blank('/v1.0/')
req.accept = "application/xml"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
self.assertEqual(res.content_type, "application/xml")
version = etree.XML(res.body)
xmlutil.validate_schema(version, 'version')
expected = VERSIONS['v1.0']
self.assertTrue(version.xpath('/ns:version', namespaces=NS))
media_types = version.xpath('ns:media-types/ns:media-type',
namespaces=NS)
self.assertTrue(common.compare_media_types(media_types,
expected['media-types']))
for key in ['id', 'status', 'updated']:
self.assertEqual(version.get(key), expected[key])
links = version.xpath('atom:link', namespaces=NS)
self.assertTrue(common.compare_links(links,
[{'rel': 'self', 'href': 'http://localhost/v1.0/'}]
+ expected['links']))
def test_get_version_1_1_detail_xml(self):
req = webob.Request.blank('/v1.1/')
req.accept = "application/xml"
@@ -338,9 +230,9 @@ class VersionsTest(test.TestCase):
self.assertTrue(root.xpath('/ns:versions', namespaces=NS))
versions = root.xpath('ns:version', namespaces=NS)
self.assertEqual(len(versions), 2)
self.assertEqual(len(versions), 1)
for i, v in enumerate(['v1.0', 'v1.1']):
for i, v in enumerate(['v1.1']):
version = versions[i]
expected = VERSIONS[v]
for key in ['id', 'status', 'updated']:
@@ -349,47 +241,6 @@ class VersionsTest(test.TestCase):
self.assertTrue(common.compare_links(link,
[{'rel': 'self', 'href': 'http://localhost/%s/' % v}]))
def test_get_version_1_0_detail_atom(self):
req = webob.Request.blank('/v1.0/')
req.accept = "application/atom+xml"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
self.assertEqual("application/atom+xml", res.content_type)
xmlutil.validate_schema(etree.XML(res.body), 'atom')
f = feedparser.parse(res.body)
self.assertEqual(f.feed.title, 'About This Version')
self.assertEqual(f.feed.updated, '2011-01-21T11:33:21Z')
self.assertEqual(f.feed.id, 'http://localhost/v1.0/')
self.assertEqual(f.feed.author, 'Rackspace')
self.assertEqual(f.feed.author_detail.href,
'http://www.rackspace.com/')
self.assertEqual(f.feed.links[0]['href'], 'http://localhost/v1.0/')
self.assertEqual(f.feed.links[0]['rel'], 'self')
self.assertEqual(len(f.entries), 1)
entry = f.entries[0]
self.assertEqual(entry.id, 'http://localhost/v1.0/')
self.assertEqual(entry.title, 'Version v1.0')
self.assertEqual(entry.updated, '2011-01-21T11:33:21Z')
self.assertEqual(len(entry.content), 1)
self.assertEqual(entry.content[0].value,
'Version v1.0 DEPRECATED (2011-01-21T11:33:21Z)')
self.assertEqual(len(entry.links), 3)
self.assertEqual(entry.links[0]['href'], 'http://localhost/v1.0/')
self.assertEqual(entry.links[0]['rel'], 'self')
self.assertEqual(entry.links[1], {
'href': 'http://docs.rackspacecloud.com/servers/api/v1.0/'\
'cs-devguide-20110125.pdf',
'type': 'application/pdf',
'rel': 'describedby'})
self.assertEqual(entry.links[2], {
'href': 'http://docs.rackspacecloud.com/servers/api/v1.0/'\
'application.wadl',
'type': 'application/vnd.sun.wadl+xml',
'rel': 'describedby'})
def test_get_version_1_1_detail_atom(self):
req = webob.Request.blank('/v1.1/')
req.accept = "application/atom+xml"
@@ -448,18 +299,8 @@ class VersionsTest(test.TestCase):
self.assertEqual(f.feed.links[0]['href'], 'http://localhost/')
self.assertEqual(f.feed.links[0]['rel'], 'self')
self.assertEqual(len(f.entries), 2)
self.assertEqual(len(f.entries), 1)
entry = f.entries[0]
self.assertEqual(entry.id, 'http://localhost/v1.0/')
self.assertEqual(entry.title, 'Version v1.0')
self.assertEqual(entry.updated, '2011-01-21T11:33:21Z')
self.assertEqual(len(entry.content), 1)
self.assertEqual(entry.content[0].value,
'Version v1.0 DEPRECATED (2011-01-21T11:33:21Z)')
self.assertEqual(len(entry.links), 1)
self.assertEqual(entry.links[0]['href'], 'http://localhost/v1.0/')
self.assertEqual(entry.links[0]['rel'], 'self')
entry = f.entries[1]
self.assertEqual(entry.id, 'http://localhost/v1.1/')
self.assertEqual(entry.title, 'Version v1.1')
self.assertEqual(entry.updated, '2011-01-21T11:33:21Z')
@@ -501,28 +342,6 @@ class VersionsTest(test.TestCase):
},
],
},
{
"id": "v1.0",
"status": "DEPRECATED",
"links": [
{
"href": "http://localhost/v1.0/images/1",
"rel": "self",
},
],
"media-types": [
{
"base": "application/xml",
"type": "application/vnd.openstack.compute+xml"
";version=1.0"
},
{
"base": "application/json",
"type": "application/vnd.openstack.compute+json"
";version=1.0"
},
],
},
], }
self.assertDictMatch(expected, json.loads(res.body))
@@ -537,7 +356,7 @@ class VersionsTest(test.TestCase):
root = etree.XML(res.body)
self.assertTrue(root.xpath('/ns:choices', namespaces=NS))
versions = root.xpath('ns:version', namespaces=NS)
self.assertEqual(len(versions), 2)
self.assertEqual(len(versions), 1)
version = versions[0]
self.assertEqual(version.get('id'), 'v1.1')
@@ -550,17 +369,6 @@ class VersionsTest(test.TestCase):
self.assertTrue(common.compare_links(links,
[{'rel': 'self', 'href': 'http://localhost/v1.1/images/1'}]))
version = versions[1]
self.assertEqual(version.get('id'), 'v1.0')
self.assertEqual(version.get('status'), 'DEPRECATED')
media_types = version.xpath('ns:media-types/ns:media-type',
namespaces=NS)
self.assertTrue(common.compare_media_types(media_types,
VERSIONS['v1.0']['media-types']))
links = version.xpath('atom:link', namespaces=NS)
self.assertTrue(common.compare_links(links,
[{'rel': 'self', 'href': 'http://localhost/v1.0/images/1'}]))
def test_multi_choice_server_atom(self):
"""
Make sure multi choice responses do not have content-type
@@ -603,28 +411,6 @@ class VersionsTest(test.TestCase):
},
],
},
{
"id": "v1.0",
"status": "DEPRECATED",
"links": [
{
"href": "http://localhost/v1.0/servers/2",
"rel": "self",
},
],
"media-types": [
{
"base": "application/xml",
"type": "application/vnd.openstack.compute+xml"
";version=1.0"
},
{
"base": "application/json",
"type": "application/vnd.openstack.compute+json"
";version=1.0"
},
],
},
], }
self.assertDictMatch(expected, json.loads(res.body))
@@ -754,70 +540,6 @@ class VersionsSerializerTests(test.TestCase):
self.assertTrue(common.compare_links(link,
versions_data['choices'][0]['links']))
def test_version_detail_xml_serializer(self):
version_data = {
"version": {
"id": "v1.0",
"status": "CURRENT",
"updated": "2011-01-21T11:33:21Z",
"links": [
{
"rel": "self",
"href": "http://localhost/v1.0/",
},
{
"rel": "describedby",
"type": "application/pdf",
"href": "http://docs.rackspacecloud.com/"
"servers/api/v1.0/cs-devguide-20110125.pdf",
},
{
"rel": "describedby",
"type": "application/vnd.sun.wadl+xml",
"href": "http://docs.rackspacecloud.com/"
"servers/api/v1.0/application.wadl",
},
],
"media-types": [
{
"base": "application/xml",
"type": "application/vnd.openstack.compute+xml"
";version=1.0",
},
{
"base": "application/json",
"type": "application/vnd.openstack.compute+json"
";version=1.0",
},
],
},
}
serializer = versions.VersionsXMLSerializer()
response = serializer.show(version_data)
root = etree.XML(response)
self.assertEqual(root.tag.split('}')[1], "version")
self.assertEqual(root.tag.split('}')[0].strip('{'), wsgi.XMLNS_V11)
children = list(root)
media_types = children[0]
media_type_nodes = list(media_types)
links = (children[1], children[2], children[3])
self.assertEqual(media_types.tag.split('}')[1], 'media-types')
for i, media_node in enumerate(media_type_nodes):
self.assertEqual(media_node.tag.split('}')[1], 'media-type')
for key, val in version_data['version']['media-types'][i].items():
self.assertEqual(val, media_node.get(key))
for i, link in enumerate(links):
self.assertEqual(link.tag.split('}')[0].strip('{'),
'http://www.w3.org/2005/Atom')
self.assertEqual(link.tag.split('}')[1], 'link')
for key, val in version_data['version']['links'][i].items():
self.assertEqual(val, link.get(key))
def test_versions_list_atom_serializer(self):
versions_data = {
'versions': [

View File

@@ -105,7 +105,7 @@ class ZonesTest(test.TestCase):
def test_get_zone_list_scheduler(self):
self.stubs.Set(api, '_call_scheduler', zone_get_all_scheduler)
req = webob.Request.blank('/v1.0/zones')
req = webob.Request.blank('/v1.1/fake/zones')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
@@ -115,7 +115,7 @@ class ZonesTest(test.TestCase):
def test_get_zone_list_db(self):
self.stubs.Set(api, '_call_scheduler', zone_get_all_scheduler_empty)
self.stubs.Set(nova.db, 'zone_get_all', zone_get_all_db)
req = webob.Request.blank('/v1.0/zones')
req = webob.Request.blank('/v1.1/fake/zones')
req.headers["Content-Type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
@@ -124,7 +124,7 @@ class ZonesTest(test.TestCase):
self.assertEqual(len(res_dict['zones']), 2)
def test_get_zone_by_id(self):
req = webob.Request.blank('/v1.0/zones/1')
req = webob.Request.blank('/v1.1/fake/zones/1')
req.headers["Content-Type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
@@ -135,7 +135,7 @@ class ZonesTest(test.TestCase):
self.assertFalse('password' in res_dict['zone'])
def test_zone_delete(self):
req = webob.Request.blank('/v1.0/zones/1')
req = webob.Request.blank('/v1.1/fake/zones/1')
req.headers["Content-Type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
@@ -144,7 +144,7 @@ class ZonesTest(test.TestCase):
def test_zone_create(self):
body = dict(zone=dict(api_url='http://example.com', username='fred',
password='fubar'))
req = webob.Request.blank('/v1.0/zones')
req = webob.Request.blank('/v1.1/fake/zones')
req.headers["Content-Type"] = "application/json"
req.method = 'POST'
req.body = json.dumps(body)
@@ -159,7 +159,7 @@ class ZonesTest(test.TestCase):
def test_zone_update(self):
body = dict(zone=dict(username='zeb', password='sneaky'))
req = webob.Request.blank('/v1.0/zones/1')
req = webob.Request.blank('/v1.1/fake/zones/1')
req.headers["Content-Type"] = "application/json"
req.method = 'PUT'
req.body = json.dumps(body)
@@ -178,7 +178,7 @@ class ZonesTest(test.TestCase):
self.stubs.Set(api, '_call_scheduler', zone_capabilities)
body = dict(zone=dict(username='zeb', password='sneaky'))
req = webob.Request.blank('/v1.0/zones/info')
req = webob.Request.blank('/v1.1/fake/zones/info')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
@@ -192,7 +192,7 @@ class ZonesTest(test.TestCase):
self.flags(build_plan_encryption_key=key)
self.stubs.Set(api, 'select', zone_select)
req = webob.Request.blank('/v1.0/zones/select')
req = webob.Request.blank('/v1.1/fake/zones/select')
req.method = 'POST'
req.headers["Content-Type"] = "application/json"
# Select queries end up being JSON encoded twice.

View File

@@ -96,18 +96,15 @@ class ServersTest(integrated_helpers._IntegratedTestBase):
self.assertRaises(client.OpenStackApiException,
self.api.post_server, post)
# Add a valid imageId/imageRef
server['imageId'] = good_server.get('imageId')
# Add a valid imageRef
server['imageRef'] = good_server.get('imageRef')
# Without flavorId, this throws 500
# Without flavorRef, this throws 500
# TODO(justinsb): Check whatever the spec says should be thrown here
self.assertRaises(client.OpenStackApiException,
self.api.post_server, post)
# Set a valid flavorId/flavorRef
server['flavorRef'] = good_server.get('flavorRef')
server['flavorId'] = good_server.get('flavorId')
# Without a name, this throws 500
# TODO(justinsb): Check whatever the spec says should be thrown here