Merged from trunk,resolved conflicts and fixed broken unit tests due to changes in the extensions which now include ProjectMapper
This commit is contained in:
commit
4ded14d0d8
|
@ -68,6 +68,22 @@ class FaultWrapper(base_wsgi.Middleware):
|
||||||
return faults.Fault(exc)
|
return faults.Fault(exc)
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectMapper(routes.Mapper):
|
||||||
|
|
||||||
|
def resource(self, member_name, collection_name, **kwargs):
|
||||||
|
if not ('parent_resource' in kwargs):
|
||||||
|
kwargs['path_prefix'] = '{project_id}/'
|
||||||
|
else:
|
||||||
|
parent_resource = kwargs['parent_resource']
|
||||||
|
p_collection = parent_resource['collection_name']
|
||||||
|
p_member = parent_resource['member_name']
|
||||||
|
kwargs['path_prefix'] = '{project_id}/%s/:%s_id' % (p_collection,
|
||||||
|
p_member)
|
||||||
|
routes.Mapper.resource(self, member_name,
|
||||||
|
collection_name,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class APIRouter(base_wsgi.Router):
|
class APIRouter(base_wsgi.Router):
|
||||||
"""
|
"""
|
||||||
Routes requests on the OpenStack API to the appropriate controller
|
Routes requests on the OpenStack API to the appropriate controller
|
||||||
|
@ -81,10 +97,13 @@ class APIRouter(base_wsgi.Router):
|
||||||
|
|
||||||
def __init__(self, ext_mgr=None):
|
def __init__(self, ext_mgr=None):
|
||||||
self.server_members = {}
|
self.server_members = {}
|
||||||
mapper = routes.Mapper()
|
mapper = self._mapper()
|
||||||
self._setup_routes(mapper)
|
self._setup_routes(mapper)
|
||||||
super(APIRouter, self).__init__(mapper)
|
super(APIRouter, self).__init__(mapper)
|
||||||
|
|
||||||
|
def _mapper(self):
|
||||||
|
return routes.Mapper()
|
||||||
|
|
||||||
def _setup_routes(self, mapper):
|
def _setup_routes(self, mapper):
|
||||||
raise NotImplementedError(_("You must implement _setup_routes."))
|
raise NotImplementedError(_("You must implement _setup_routes."))
|
||||||
|
|
||||||
|
@ -174,6 +193,9 @@ class APIRouterV10(APIRouter):
|
||||||
class APIRouterV11(APIRouter):
|
class APIRouterV11(APIRouter):
|
||||||
"""Define routes specific to OpenStack API V1.1."""
|
"""Define routes specific to OpenStack API V1.1."""
|
||||||
|
|
||||||
|
def _mapper(self):
|
||||||
|
return ProjectMapper()
|
||||||
|
|
||||||
def _setup_routes(self, mapper):
|
def _setup_routes(self, mapper):
|
||||||
self._setup_base_routes(mapper, '1.1')
|
self._setup_base_routes(mapper, '1.1')
|
||||||
|
|
||||||
|
@ -184,7 +206,7 @@ class APIRouterV11(APIRouter):
|
||||||
parent_resource=dict(member_name='image',
|
parent_resource=dict(member_name='image',
|
||||||
collection_name='images'))
|
collection_name='images'))
|
||||||
|
|
||||||
mapper.connect("metadata", "/images/{image_id}/metadata",
|
mapper.connect("metadata", "/{project_id}/images/{image_id}/metadata",
|
||||||
controller=image_metadata_controller,
|
controller=image_metadata_controller,
|
||||||
action='update_all',
|
action='update_all',
|
||||||
conditions={"method": ['PUT']})
|
conditions={"method": ['PUT']})
|
||||||
|
@ -196,7 +218,8 @@ class APIRouterV11(APIRouter):
|
||||||
parent_resource=dict(member_name='server',
|
parent_resource=dict(member_name='server',
|
||||||
collection_name='servers'))
|
collection_name='servers'))
|
||||||
|
|
||||||
mapper.connect("metadata", "/servers/{server_id}/metadata",
|
mapper.connect("metadata",
|
||||||
|
"/{project_id}/servers/{server_id}/metadata",
|
||||||
controller=server_metadata_controller,
|
controller=server_metadata_controller,
|
||||||
action='update_all',
|
action='update_all',
|
||||||
conditions={"method": ['PUT']})
|
conditions={"method": ['PUT']})
|
||||||
|
|
|
@ -28,6 +28,7 @@ from nova import flags
|
||||||
from nova import log as logging
|
from nova import log as logging
|
||||||
from nova import utils
|
from nova import utils
|
||||||
from nova import wsgi
|
from nova import wsgi
|
||||||
|
from nova.api.openstack import common
|
||||||
from nova.api.openstack import faults
|
from nova.api.openstack import faults
|
||||||
|
|
||||||
LOG = logging.getLogger('nova.api.openstack')
|
LOG = logging.getLogger('nova.api.openstack')
|
||||||
|
@ -55,16 +56,33 @@ class AuthMiddleware(wsgi.Middleware):
|
||||||
LOG.warn(msg % locals())
|
LOG.warn(msg % locals())
|
||||||
return faults.Fault(webob.exc.HTTPUnauthorized())
|
return faults.Fault(webob.exc.HTTPUnauthorized())
|
||||||
|
|
||||||
try:
|
# Get all valid projects for the user
|
||||||
project_id = req.headers["X-Auth-Project-Id"]
|
projects = self.auth.get_projects(user_id)
|
||||||
except KeyError:
|
if not projects:
|
||||||
# FIXME(usrleon): It needed only for compatibility
|
return faults.Fault(webob.exc.HTTPUnauthorized())
|
||||||
# while osapi clients don't use this header
|
|
||||||
projects = self.auth.get_projects(user_id)
|
project_id = ""
|
||||||
if projects:
|
path_parts = req.path.split('/')
|
||||||
project_id = projects[0].id
|
# TODO(wwolf): this v1.1 check will be temporary as
|
||||||
else:
|
# keystone should be taking this over at some point
|
||||||
|
if len(path_parts) > 1 and path_parts[1] == 'v1.1':
|
||||||
|
project_id = path_parts[2]
|
||||||
|
# Check that the project for project_id exists, and that user
|
||||||
|
# is authorized to use it
|
||||||
|
try:
|
||||||
|
project = self.auth.get_project(project_id)
|
||||||
|
except exception.ProjectNotFound:
|
||||||
return faults.Fault(webob.exc.HTTPUnauthorized())
|
return faults.Fault(webob.exc.HTTPUnauthorized())
|
||||||
|
if project_id not in [p.id for p in projects]:
|
||||||
|
return faults.Fault(webob.exc.HTTPUnauthorized())
|
||||||
|
else:
|
||||||
|
# As a fallback, set project_id from the headers, which is the v1.0
|
||||||
|
# behavior. As a last resort, be forgiving to the user and set
|
||||||
|
# project_id based on a valid project of theirs.
|
||||||
|
try:
|
||||||
|
project_id = req.headers["X-Auth-Project-Id"]
|
||||||
|
except KeyError:
|
||||||
|
project_id = projects[0].id
|
||||||
|
|
||||||
is_admin = self.auth.is_admin(user_id)
|
is_admin = self.auth.is_admin(user_id)
|
||||||
req.environ['nova.context'] = context.RequestContext(user_id,
|
req.environ['nova.context'] = context.RequestContext(user_id,
|
||||||
|
@ -95,12 +113,19 @@ class AuthMiddleware(wsgi.Middleware):
|
||||||
LOG.warn(msg)
|
LOG.warn(msg)
|
||||||
return faults.Fault(webob.exc.HTTPUnauthorized(explanation=msg))
|
return faults.Fault(webob.exc.HTTPUnauthorized(explanation=msg))
|
||||||
|
|
||||||
|
def _get_auth_header(key):
|
||||||
|
"""Ensures that the KeyError returned is meaningful."""
|
||||||
|
try:
|
||||||
|
return req.headers[key]
|
||||||
|
except KeyError as ex:
|
||||||
|
raise KeyError(key)
|
||||||
try:
|
try:
|
||||||
username = req.headers['X-Auth-User']
|
username = _get_auth_header('X-Auth-User')
|
||||||
key = req.headers['X-Auth-Key']
|
key = _get_auth_header('X-Auth-Key')
|
||||||
except KeyError as ex:
|
except KeyError as ex:
|
||||||
LOG.warn(_("Could not find %s in request.") % ex)
|
msg = _("Could not find %s in request.") % ex
|
||||||
return faults.Fault(webob.exc.HTTPUnauthorized())
|
LOG.warn(msg)
|
||||||
|
return faults.Fault(webob.exc.HTTPUnauthorized(explanation=msg))
|
||||||
|
|
||||||
token, user = self._authorize_user(username, key, req)
|
token, user = self._authorize_user(username, key, req)
|
||||||
if user and token:
|
if user and token:
|
||||||
|
@ -149,6 +174,16 @@ class AuthMiddleware(wsgi.Middleware):
|
||||||
"""
|
"""
|
||||||
ctxt = context.get_admin_context()
|
ctxt = context.get_admin_context()
|
||||||
|
|
||||||
|
project_id = req.headers.get('X-Auth-Project-Id')
|
||||||
|
if project_id is None:
|
||||||
|
# If the project_id is not provided in the headers, be forgiving to
|
||||||
|
# the user and set project_id based on a valid project of theirs.
|
||||||
|
user = self.auth.get_user_from_access_key(key)
|
||||||
|
projects = self.auth.get_projects(user.id)
|
||||||
|
if not projects:
|
||||||
|
raise webob.exc.HTTPUnauthorized()
|
||||||
|
project_id = projects[0].id
|
||||||
|
|
||||||
try:
|
try:
|
||||||
user = self.auth.get_user_from_access_key(key)
|
user = self.auth.get_user_from_access_key(key)
|
||||||
except exception.NotFound:
|
except exception.NotFound:
|
||||||
|
@ -162,7 +197,10 @@ class AuthMiddleware(wsgi.Middleware):
|
||||||
token_dict['token_hash'] = token_hash
|
token_dict['token_hash'] = token_hash
|
||||||
token_dict['cdn_management_url'] = ''
|
token_dict['cdn_management_url'] = ''
|
||||||
os_url = req.url
|
os_url = req.url
|
||||||
token_dict['server_management_url'] = os_url
|
token_dict['server_management_url'] = os_url.strip('/')
|
||||||
|
version = common.get_version_from_href(os_url)
|
||||||
|
if version == '1.1':
|
||||||
|
token_dict['server_management_url'] += '/' + project_id
|
||||||
token_dict['storage_url'] = ''
|
token_dict['storage_url'] = ''
|
||||||
token_dict['user_id'] = user.id
|
token_dict['user_id'] = user.id
|
||||||
token = self.db.auth_token_create(ctxt, token_dict)
|
token = self.db.auth_token_create(ctxt, token_dict)
|
||||||
|
|
|
@ -15,8 +15,9 @@
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License
|
# under the License
|
||||||
from webob import exc
|
import webob
|
||||||
|
|
||||||
|
from nova import compute
|
||||||
from nova import exception
|
from nova import exception
|
||||||
from nova import log as logging
|
from nova import log as logging
|
||||||
from nova import network
|
from nova import network
|
||||||
|
@ -71,18 +72,22 @@ class FloatingIPController(object):
|
||||||
try:
|
try:
|
||||||
floating_ip = self.network_api.get_floating_ip(context, id)
|
floating_ip = self.network_api.get_floating_ip(context, id)
|
||||||
except exception.NotFound:
|
except exception.NotFound:
|
||||||
return faults.Fault(exc.HTTPNotFound())
|
return faults.Fault(webob.exc.HTTPNotFound())
|
||||||
|
|
||||||
return _translate_floating_ip_view(floating_ip)
|
return _translate_floating_ip_view(floating_ip)
|
||||||
|
|
||||||
def index(self, req):
|
def index(self, req):
|
||||||
context = req.environ['nova.context']
|
context = req.environ['nova.context']
|
||||||
|
|
||||||
floating_ips = self.network_api.list_floating_ips(context)
|
try:
|
||||||
|
# FIXME(ja) - why does self.network_api.list_floating_ips raise?
|
||||||
|
floating_ips = self.network_api.list_floating_ips(context)
|
||||||
|
except exception.FloatingIpNotFoundForProject:
|
||||||
|
floating_ips = []
|
||||||
|
|
||||||
return _translate_floating_ips_view(floating_ips)
|
return _translate_floating_ips_view(floating_ips)
|
||||||
|
|
||||||
def create(self, req):
|
def create(self, req, body=None):
|
||||||
context = req.environ['nova.context']
|
context = req.environ['nova.context']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -95,56 +100,19 @@ class FloatingIPController(object):
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
return {'allocated': {
|
return _translate_floating_ip_view(ip)
|
||||||
"id": ip['id'],
|
|
||||||
"floating_ip": ip['address']}}
|
|
||||||
|
|
||||||
def delete(self, req, id):
|
def delete(self, req, id):
|
||||||
context = req.environ['nova.context']
|
|
||||||
ip = self.network_api.get_floating_ip(context, id)
|
|
||||||
|
|
||||||
if 'fixed_ip' in ip:
|
|
||||||
self.disassociate(req, id)
|
|
||||||
|
|
||||||
self.network_api.release_floating_ip(context, address=ip['address'])
|
|
||||||
|
|
||||||
return {'released': {
|
|
||||||
"id": ip['id'],
|
|
||||||
"floating_ip": ip['address']}}
|
|
||||||
|
|
||||||
def associate(self, req, id, body):
|
|
||||||
""" /floating_ips/{id}/associate fixed ip in body """
|
|
||||||
context = req.environ['nova.context']
|
|
||||||
floating_ip = self._get_ip_by_id(context, id)
|
|
||||||
|
|
||||||
fixed_ip = body['associate_address']['fixed_ip']
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.network_api.associate_floating_ip(context,
|
|
||||||
floating_ip, fixed_ip)
|
|
||||||
except rpc.RemoteError:
|
|
||||||
raise
|
|
||||||
|
|
||||||
return {'associated':
|
|
||||||
{
|
|
||||||
"floating_ip_id": id,
|
|
||||||
"floating_ip": floating_ip,
|
|
||||||
"fixed_ip": fixed_ip}}
|
|
||||||
|
|
||||||
def disassociate(self, req, id, body=None):
|
|
||||||
""" POST /floating_ips/{id}/disassociate """
|
|
||||||
context = req.environ['nova.context']
|
context = req.environ['nova.context']
|
||||||
floating_ip = self.network_api.get_floating_ip(context, id)
|
floating_ip = self.network_api.get_floating_ip(context, id)
|
||||||
address = floating_ip['address']
|
|
||||||
fixed_ip = floating_ip['fixed_ip']['address']
|
|
||||||
|
|
||||||
try:
|
if 'fixed_ip' in floating_ip:
|
||||||
self.network_api.disassociate_floating_ip(context, address)
|
self.network_api.disassociate_floating_ip(context,
|
||||||
except rpc.RemoteError:
|
floating_ip['address'])
|
||||||
raise
|
|
||||||
|
|
||||||
return {'disassociated': {'floating_ip': address,
|
self.network_api.release_floating_ip(context,
|
||||||
'fixed_ip': fixed_ip}}
|
address=floating_ip['address'])
|
||||||
|
return webob.exc.HTTPAccepted()
|
||||||
|
|
||||||
def _get_ip_by_id(self, context, value):
|
def _get_ip_by_id(self, context, value):
|
||||||
"""Checks that value is id and then returns its address."""
|
"""Checks that value is id and then returns its address."""
|
||||||
|
@ -152,6 +120,47 @@ class FloatingIPController(object):
|
||||||
|
|
||||||
|
|
||||||
class Floating_ips(extensions.ExtensionDescriptor):
|
class Floating_ips(extensions.ExtensionDescriptor):
|
||||||
|
def __init__(self):
|
||||||
|
self.compute_api = compute.API()
|
||||||
|
self.network_api = network.API()
|
||||||
|
super(Floating_ips, self).__init__()
|
||||||
|
|
||||||
|
def _add_floating_ip(self, input_dict, req, instance_id):
|
||||||
|
"""Associate floating_ip to an instance."""
|
||||||
|
context = req.environ['nova.context']
|
||||||
|
|
||||||
|
try:
|
||||||
|
address = input_dict['addFloatingIp']['address']
|
||||||
|
except TypeError:
|
||||||
|
msg = _("Missing parameter dict")
|
||||||
|
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||||
|
except KeyError:
|
||||||
|
msg = _("Address not specified")
|
||||||
|
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||||
|
|
||||||
|
self.compute_api.associate_floating_ip(context, instance_id, address)
|
||||||
|
|
||||||
|
return webob.Response(status_int=202)
|
||||||
|
|
||||||
|
def _remove_floating_ip(self, input_dict, req, instance_id):
|
||||||
|
"""Dissociate floating_ip from an instance."""
|
||||||
|
context = req.environ['nova.context']
|
||||||
|
|
||||||
|
try:
|
||||||
|
address = input_dict['removeFloatingIp']['address']
|
||||||
|
except TypeError:
|
||||||
|
msg = _("Missing parameter dict")
|
||||||
|
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||||
|
except KeyError:
|
||||||
|
msg = _("Address not specified")
|
||||||
|
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||||
|
|
||||||
|
floating_ip = self.network_api.get_floating_ip_by_ip(context, address)
|
||||||
|
if 'fixed_ip' in floating_ip:
|
||||||
|
self.network_api.disassociate_floating_ip(context, address)
|
||||||
|
|
||||||
|
return webob.Response(status_int=202)
|
||||||
|
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
return "Floating_ips"
|
return "Floating_ips"
|
||||||
|
|
||||||
|
@ -172,9 +181,18 @@ class Floating_ips(extensions.ExtensionDescriptor):
|
||||||
|
|
||||||
res = extensions.ResourceExtension('os-floating-ips',
|
res = extensions.ResourceExtension('os-floating-ips',
|
||||||
FloatingIPController(),
|
FloatingIPController(),
|
||||||
member_actions={
|
member_actions={})
|
||||||
'associate': 'POST',
|
|
||||||
'disassociate': 'POST'})
|
|
||||||
resources.append(res)
|
resources.append(res)
|
||||||
|
|
||||||
return resources
|
return resources
|
||||||
|
|
||||||
|
def get_actions(self):
|
||||||
|
"""Return the actions the extension adds, as required by contract."""
|
||||||
|
actions = [
|
||||||
|
extensions.ActionExtension("servers", "addFloatingIp",
|
||||||
|
self._add_floating_ip),
|
||||||
|
extensions.ActionExtension("servers", "removeFloatingIp",
|
||||||
|
self._remove_floating_ip),
|
||||||
|
]
|
||||||
|
|
||||||
|
return actions
|
||||||
|
|
|
@ -25,10 +25,11 @@ from nova import db
|
||||||
from nova import exception
|
from nova import exception
|
||||||
from nova import flags
|
from nova import flags
|
||||||
from nova import log as logging
|
from nova import log as logging
|
||||||
|
from nova import rpc
|
||||||
from nova.api.openstack import common
|
from nova.api.openstack import common
|
||||||
from nova.api.openstack import extensions
|
from nova.api.openstack import extensions
|
||||||
from nova.api.openstack import wsgi
|
from nova.api.openstack import wsgi
|
||||||
|
from nova.compute import power_state
|
||||||
|
|
||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
|
|
||||||
|
@ -73,33 +74,28 @@ class SecurityGroupController(object):
|
||||||
context, rule)]
|
context, rule)]
|
||||||
return security_group
|
return security_group
|
||||||
|
|
||||||
def show(self, req, id):
|
def _get_security_group(self, context, id):
|
||||||
"""Return data about the given security group."""
|
|
||||||
context = req.environ['nova.context']
|
|
||||||
try:
|
try:
|
||||||
id = int(id)
|
id = int(id)
|
||||||
security_group = db.security_group_get(context, id)
|
security_group = db.security_group_get(context, id)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
msg = _("Security group id is not integer")
|
msg = _("Security group id should be integer")
|
||||||
return exc.HTTPBadRequest(explanation=msg)
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
except exception.NotFound as exp:
|
except exception.NotFound as exp:
|
||||||
return exc.HTTPNotFound(explanation=unicode(exp))
|
raise exc.HTTPNotFound(explanation=unicode(exp))
|
||||||
|
return security_group
|
||||||
|
|
||||||
|
def show(self, req, id):
|
||||||
|
"""Return data about the given security group."""
|
||||||
|
context = req.environ['nova.context']
|
||||||
|
security_group = self._get_security_group(context, id)
|
||||||
return {'security_group': self._format_security_group(context,
|
return {'security_group': self._format_security_group(context,
|
||||||
security_group)}
|
security_group)}
|
||||||
|
|
||||||
def delete(self, req, id):
|
def delete(self, req, id):
|
||||||
"""Delete a security group."""
|
"""Delete a security group."""
|
||||||
context = req.environ['nova.context']
|
context = req.environ['nova.context']
|
||||||
try:
|
security_group = self._get_security_group(context, id)
|
||||||
id = int(id)
|
|
||||||
security_group = db.security_group_get(context, id)
|
|
||||||
except ValueError:
|
|
||||||
msg = _("Security group id is not integer")
|
|
||||||
return exc.HTTPBadRequest(explanation=msg)
|
|
||||||
except exception.SecurityGroupNotFound as exp:
|
|
||||||
return exc.HTTPNotFound(explanation=unicode(exp))
|
|
||||||
|
|
||||||
LOG.audit(_("Delete security group %s"), id, context=context)
|
LOG.audit(_("Delete security group %s"), id, context=context)
|
||||||
db.security_group_destroy(context, security_group.id)
|
db.security_group_destroy(context, security_group.id)
|
||||||
|
|
||||||
|
@ -226,9 +222,9 @@ class SecurityGroupRulesController(SecurityGroupController):
|
||||||
security_group_rule = db.security_group_rule_create(context, values)
|
security_group_rule = db.security_group_rule_create(context, values)
|
||||||
|
|
||||||
self.compute_api.trigger_security_group_rules_refresh(context,
|
self.compute_api.trigger_security_group_rules_refresh(context,
|
||||||
security_group_id=security_group['id'])
|
security_group_id=security_group['id'])
|
||||||
|
|
||||||
return {'security_group_rule': self._format_security_group_rule(
|
return {"security_group_rule": self._format_security_group_rule(
|
||||||
context,
|
context,
|
||||||
security_group_rule)}
|
security_group_rule)}
|
||||||
|
|
||||||
|
@ -336,6 +332,11 @@ class SecurityGroupRulesController(SecurityGroupController):
|
||||||
|
|
||||||
|
|
||||||
class Security_groups(extensions.ExtensionDescriptor):
|
class Security_groups(extensions.ExtensionDescriptor):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.compute_api = compute.API()
|
||||||
|
super(Security_groups, self).__init__()
|
||||||
|
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
return "SecurityGroups"
|
return "SecurityGroups"
|
||||||
|
|
||||||
|
@ -351,6 +352,82 @@ class Security_groups(extensions.ExtensionDescriptor):
|
||||||
def get_updated(self):
|
def get_updated(self):
|
||||||
return "2011-07-21T00:00:00+00:00"
|
return "2011-07-21T00:00:00+00:00"
|
||||||
|
|
||||||
|
def _addSecurityGroup(self, input_dict, req, instance_id):
|
||||||
|
context = req.environ['nova.context']
|
||||||
|
|
||||||
|
try:
|
||||||
|
body = input_dict['addSecurityGroup']
|
||||||
|
group_name = body['name']
|
||||||
|
instance_id = int(instance_id)
|
||||||
|
except ValueError:
|
||||||
|
msg = _("Server id should be integer")
|
||||||
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
|
except TypeError:
|
||||||
|
msg = _("Missing parameter dict")
|
||||||
|
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||||
|
except KeyError:
|
||||||
|
msg = _("Security group not specified")
|
||||||
|
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||||
|
|
||||||
|
if not group_name or group_name.strip() == '':
|
||||||
|
msg = _("Security group name cannot be empty")
|
||||||
|
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.compute_api.add_security_group(context, instance_id,
|
||||||
|
group_name)
|
||||||
|
except exception.SecurityGroupNotFound as exp:
|
||||||
|
return exc.HTTPNotFound(explanation=unicode(exp))
|
||||||
|
except exception.InstanceNotFound as exp:
|
||||||
|
return exc.HTTPNotFound(explanation=unicode(exp))
|
||||||
|
except exception.Invalid as exp:
|
||||||
|
return exc.HTTPBadRequest(explanation=unicode(exp))
|
||||||
|
|
||||||
|
return exc.HTTPAccepted()
|
||||||
|
|
||||||
|
def _removeSecurityGroup(self, input_dict, req, instance_id):
|
||||||
|
context = req.environ['nova.context']
|
||||||
|
|
||||||
|
try:
|
||||||
|
body = input_dict['removeSecurityGroup']
|
||||||
|
group_name = body['name']
|
||||||
|
instance_id = int(instance_id)
|
||||||
|
except ValueError:
|
||||||
|
msg = _("Server id should be integer")
|
||||||
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
|
except TypeError:
|
||||||
|
msg = _("Missing parameter dict")
|
||||||
|
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||||
|
except KeyError:
|
||||||
|
msg = _("Security group not specified")
|
||||||
|
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||||
|
|
||||||
|
if not group_name or group_name.strip() == '':
|
||||||
|
msg = _("Security group name cannot be empty")
|
||||||
|
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.compute_api.remove_security_group(context, instance_id,
|
||||||
|
group_name)
|
||||||
|
except exception.SecurityGroupNotFound as exp:
|
||||||
|
return exc.HTTPNotFound(explanation=unicode(exp))
|
||||||
|
except exception.InstanceNotFound as exp:
|
||||||
|
return exc.HTTPNotFound(explanation=unicode(exp))
|
||||||
|
except exception.Invalid as exp:
|
||||||
|
return exc.HTTPBadRequest(explanation=unicode(exp))
|
||||||
|
|
||||||
|
return exc.HTTPAccepted()
|
||||||
|
|
||||||
|
def get_actions(self):
|
||||||
|
"""Return the actions the extensions adds"""
|
||||||
|
actions = [
|
||||||
|
extensions.ActionExtension("servers", "addSecurityGroup",
|
||||||
|
self._addSecurityGroup),
|
||||||
|
extensions.ActionExtension("servers", "removeSecurityGroup",
|
||||||
|
self._removeSecurityGroup)
|
||||||
|
]
|
||||||
|
return actions
|
||||||
|
|
||||||
def get_resources(self):
|
def get_resources(self):
|
||||||
resources = []
|
resources = []
|
||||||
|
|
||||||
|
|
|
@ -111,8 +111,16 @@ class CreateInstanceHelper(object):
|
||||||
if personality:
|
if personality:
|
||||||
injected_files = self._get_injected_files(personality)
|
injected_files = self._get_injected_files(personality)
|
||||||
|
|
||||||
requested_networks = server_dict.get('networks')
|
sg_names = []
|
||||||
|
security_groups = server_dict.get('security_groups')
|
||||||
|
if security_groups is not None:
|
||||||
|
sg_names = [sg['name'] for sg in security_groups if sg.get('name')]
|
||||||
|
if not sg_names:
|
||||||
|
sg_names.append('default')
|
||||||
|
|
||||||
|
sg_names = list(set(sg_names))
|
||||||
|
|
||||||
|
requested_networks = server_dict.get('networks')
|
||||||
if requested_networks is not None:
|
if requested_networks is not None:
|
||||||
requested_networks = self._get_requested_networks(
|
requested_networks = self._get_requested_networks(
|
||||||
requested_networks)
|
requested_networks)
|
||||||
|
@ -164,6 +172,8 @@ class CreateInstanceHelper(object):
|
||||||
key_name=key_name,
|
key_name=key_name,
|
||||||
key_data=key_data,
|
key_data=key_data,
|
||||||
metadata=server_dict.get('metadata', {}),
|
metadata=server_dict.get('metadata', {}),
|
||||||
|
access_ip_v4=server_dict.get('accessIPv4'),
|
||||||
|
access_ip_v6=server_dict.get('accessIPv6'),
|
||||||
injected_files=injected_files,
|
injected_files=injected_files,
|
||||||
admin_password=password,
|
admin_password=password,
|
||||||
zone_blob=zone_blob,
|
zone_blob=zone_blob,
|
||||||
|
@ -171,6 +181,7 @@ class CreateInstanceHelper(object):
|
||||||
min_count=min_count,
|
min_count=min_count,
|
||||||
max_count=max_count,
|
max_count=max_count,
|
||||||
requested_networks=requested_networks,
|
requested_networks=requested_networks,
|
||||||
|
security_group=sg_names,
|
||||||
user_data=user_data,
|
user_data=user_data,
|
||||||
availability_zone=availability_zone))
|
availability_zone=availability_zone))
|
||||||
except quota.QuotaError as error:
|
except quota.QuotaError as error:
|
||||||
|
@ -181,6 +192,8 @@ class CreateInstanceHelper(object):
|
||||||
except exception.FlavorNotFound as error:
|
except exception.FlavorNotFound as error:
|
||||||
msg = _("Invalid flavorRef provided.")
|
msg = _("Invalid flavorRef provided.")
|
||||||
raise exc.HTTPBadRequest(explanation=msg)
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
|
except exception.SecurityGroupNotFound as error:
|
||||||
|
raise exc.HTTPBadRequest(explanation=unicode(error))
|
||||||
except RemoteError as err:
|
except RemoteError as err:
|
||||||
msg = "%(err_type)s: %(err_msg)s" % \
|
msg = "%(err_type)s: %(err_msg)s" % \
|
||||||
{'err_type': err.exc_type, 'err_msg': err.value}
|
{'err_type': err.exc_type, 'err_msg': err.value}
|
||||||
|
@ -503,7 +516,8 @@ class ServerXMLDeserializerV11(wsgi.MetadataXMLDeserializer):
|
||||||
server = {}
|
server = {}
|
||||||
server_node = self.find_first_child_named(node, 'server')
|
server_node = self.find_first_child_named(node, 'server')
|
||||||
|
|
||||||
attributes = ["name", "imageRef", "flavorRef", "adminPass"]
|
attributes = ["name", "imageRef", "flavorRef", "adminPass",
|
||||||
|
"accessIPv4", "accessIPv6"]
|
||||||
for attr in attributes:
|
for attr in attributes:
|
||||||
if server_node.getAttribute(attr):
|
if server_node.getAttribute(attr):
|
||||||
server[attr] = server_node.getAttribute(attr)
|
server[attr] = server_node.getAttribute(attr)
|
||||||
|
@ -520,6 +534,10 @@ class ServerXMLDeserializerV11(wsgi.MetadataXMLDeserializer):
|
||||||
if networks is not None:
|
if networks is not None:
|
||||||
server["networks"] = networks
|
server["networks"] = networks
|
||||||
|
|
||||||
|
security_groups = self._extract_security_groups(server_node)
|
||||||
|
if security_groups is not None:
|
||||||
|
server["security_groups"] = security_groups
|
||||||
|
|
||||||
return server
|
return server
|
||||||
|
|
||||||
def _extract_personality(self, server_node):
|
def _extract_personality(self, server_node):
|
||||||
|
@ -553,3 +571,18 @@ class ServerXMLDeserializerV11(wsgi.MetadataXMLDeserializer):
|
||||||
return networks
|
return networks
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def _extract_security_groups(self, server_node):
|
||||||
|
"""Marshal the security_groups attribute of a parsed request"""
|
||||||
|
node = self.find_first_child_named(server_node, "security_groups")
|
||||||
|
if node is not None:
|
||||||
|
security_groups = []
|
||||||
|
for sg_node in self.find_children_named(node, "security_group"):
|
||||||
|
item = {}
|
||||||
|
name_node = self.find_first_child_named(sg_node, "name")
|
||||||
|
if name_node:
|
||||||
|
item["name"] = self.extract_text(name_node)
|
||||||
|
security_groups.append(item)
|
||||||
|
return security_groups
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
|
@ -29,6 +29,7 @@ from nova import exception
|
||||||
from nova import flags
|
from nova import flags
|
||||||
from nova import log as logging
|
from nova import log as logging
|
||||||
from nova import wsgi as base_wsgi
|
from nova import wsgi as base_wsgi
|
||||||
|
import nova.api.openstack
|
||||||
from nova.api.openstack import common
|
from nova.api.openstack import common
|
||||||
from nova.api.openstack import faults
|
from nova.api.openstack import faults
|
||||||
from nova.api.openstack import wsgi
|
from nova.api.openstack import wsgi
|
||||||
|
@ -220,12 +221,13 @@ class ExtensionMiddleware(base_wsgi.Middleware):
|
||||||
for action in ext_mgr.get_actions():
|
for action in ext_mgr.get_actions():
|
||||||
if not action.collection in action_resources.keys():
|
if not action.collection in action_resources.keys():
|
||||||
resource = ActionExtensionResource(application)
|
resource = ActionExtensionResource(application)
|
||||||
mapper.connect("/%s/:(id)/action.:(format)" %
|
mapper.connect("/:(project_id)/%s/:(id)/action.:(format)" %
|
||||||
action.collection,
|
action.collection,
|
||||||
action='action',
|
action='action',
|
||||||
controller=resource,
|
controller=resource,
|
||||||
conditions=dict(method=['POST']))
|
conditions=dict(method=['POST']))
|
||||||
mapper.connect("/%s/:(id)/action" % action.collection,
|
mapper.connect("/:(project_id)/%s/:(id)/action" %
|
||||||
|
action.collection,
|
||||||
action='action',
|
action='action',
|
||||||
controller=resource,
|
controller=resource,
|
||||||
conditions=dict(method=['POST']))
|
conditions=dict(method=['POST']))
|
||||||
|
@ -258,7 +260,7 @@ class ExtensionMiddleware(base_wsgi.Middleware):
|
||||||
ext_mgr = ExtensionManager(FLAGS.osapi_extensions_path)
|
ext_mgr = ExtensionManager(FLAGS.osapi_extensions_path)
|
||||||
self.ext_mgr = ext_mgr
|
self.ext_mgr = ext_mgr
|
||||||
|
|
||||||
mapper = routes.Mapper()
|
mapper = nova.api.openstack.ProjectMapper()
|
||||||
|
|
||||||
serializer = wsgi.ResponseSerializer(
|
serializer = wsgi.ResponseSerializer(
|
||||||
{'application/xml': ExtensionsXMLSerializer()})
|
{'application/xml': ExtensionsXMLSerializer()})
|
||||||
|
@ -269,13 +271,17 @@ class ExtensionMiddleware(base_wsgi.Middleware):
|
||||||
if resource.serializer is None:
|
if resource.serializer is None:
|
||||||
resource.serializer = serializer
|
resource.serializer = serializer
|
||||||
|
|
||||||
mapper.resource(resource.collection, resource.collection,
|
kargs = dict(
|
||||||
controller=wsgi.Resource(
|
controller=wsgi.Resource(
|
||||||
resource.controller, resource.deserializer,
|
resource.controller, resource.deserializer,
|
||||||
resource.serializer),
|
resource.serializer),
|
||||||
collection=resource.collection_actions,
|
collection=resource.collection_actions,
|
||||||
member=resource.member_actions,
|
member=resource.member_actions)
|
||||||
parent_resource=resource.parent)
|
|
||||||
|
if resource.parent:
|
||||||
|
kargs['parent_resource'] = resource.parent
|
||||||
|
|
||||||
|
mapper.resource(resource.collection, resource.collection, **kargs)
|
||||||
|
|
||||||
# extended actions
|
# extended actions
|
||||||
action_resources = self._action_ext_resources(application, ext_mgr,
|
action_resources = self._action_ext_resources(application, ext_mgr,
|
||||||
|
|
|
@ -72,7 +72,8 @@ class ControllerV11(Controller):
|
||||||
|
|
||||||
def _get_view_builder(self, req):
|
def _get_view_builder(self, req):
|
||||||
base_url = req.application_url
|
base_url = req.application_url
|
||||||
return views.flavors.ViewBuilderV11(base_url)
|
project_id = getattr(req.environ['nova.context'], 'project_id', '')
|
||||||
|
return views.flavors.ViewBuilderV11(base_url, project_id)
|
||||||
|
|
||||||
|
|
||||||
class FlavorXMLSerializer(wsgi.XMLDictSerializer):
|
class FlavorXMLSerializer(wsgi.XMLDictSerializer):
|
||||||
|
|
|
@ -166,10 +166,11 @@ class ControllerV10(Controller):
|
||||||
class ControllerV11(Controller):
|
class ControllerV11(Controller):
|
||||||
"""Version 1.1 specific controller logic."""
|
"""Version 1.1 specific controller logic."""
|
||||||
|
|
||||||
def get_builder(self, request):
|
def get_builder(self, req):
|
||||||
"""Property to get the ViewBuilder class we need to use."""
|
"""Property to get the ViewBuilder class we need to use."""
|
||||||
base_url = request.application_url
|
base_url = req.application_url
|
||||||
return images_view.ViewBuilderV11(base_url)
|
project_id = getattr(req.environ['nova.context'], 'project_id', '')
|
||||||
|
return images_view.ViewBuilderV11(base_url, project_id)
|
||||||
|
|
||||||
def index(self, req):
|
def index(self, req):
|
||||||
"""Return an index listing of images available to the request.
|
"""Return an index listing of images available to the request.
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
<element name="server" ns="http://docs.openstack.org/compute/api/v1.1"
|
||||||
|
xmlns="http://relaxng.org/ns/structure/1.0">
|
||||||
|
<attribute name="name"> <text/> </attribute>
|
||||||
|
<attribute name="id"> <text/> </attribute>
|
||||||
|
<attribute name="uuid"> <text/> </attribute>
|
||||||
|
<attribute name="updated"> <text/> </attribute>
|
||||||
|
<attribute name="created"> <text/> </attribute>
|
||||||
|
<attribute name="hostId"> <text/> </attribute>
|
||||||
|
<attribute name="accessIPv4"> <text/> </attribute>
|
||||||
|
<attribute name="accessIPv6"> <text/> </attribute>
|
||||||
|
<attribute name="status"> <text/> </attribute>
|
||||||
|
<optional>
|
||||||
|
<attribute name="progress"> <text/> </attribute>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="adminPass"> <text/> </attribute>
|
||||||
|
</optional>
|
||||||
|
<zeroOrMore>
|
||||||
|
<externalRef href="../atom-link.rng"/>
|
||||||
|
</zeroOrMore>
|
||||||
|
<element name="image">
|
||||||
|
<attribute name="id"> <text/> </attribute>
|
||||||
|
<externalRef href="../atom-link.rng"/>
|
||||||
|
</element>
|
||||||
|
<element name="flavor">
|
||||||
|
<attribute name="id"> <text/> </attribute>
|
||||||
|
<externalRef href="../atom-link.rng"/>
|
||||||
|
</element>
|
||||||
|
<element name="metadata">
|
||||||
|
<zeroOrMore>
|
||||||
|
<element name="meta">
|
||||||
|
<attribute name="key"> <text/> </attribute>
|
||||||
|
<text/>
|
||||||
|
</element>
|
||||||
|
</zeroOrMore>
|
||||||
|
</element>
|
||||||
|
<element name="addresses">
|
||||||
|
<zeroOrMore>
|
||||||
|
<element name="network">
|
||||||
|
<attribute name="id"> <text/> </attribute>
|
||||||
|
<zeroOrMore>
|
||||||
|
<element name="ip">
|
||||||
|
<attribute name="version"> <text/> </attribute>
|
||||||
|
<attribute name="addr"> <text/> </attribute>
|
||||||
|
</element>
|
||||||
|
</zeroOrMore>
|
||||||
|
</element>
|
||||||
|
</zeroOrMore>
|
||||||
|
</element>
|
||||||
|
</element>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<element name="servers" xmlns="http://relaxng.org/ns/structure/1.0"
|
||||||
|
ns="http://docs.openstack.org/compute/api/v1.1">
|
||||||
|
<zeroOrMore>
|
||||||
|
<externalRef href="server.rng"/>
|
||||||
|
</zeroOrMore>
|
||||||
|
</element>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<element name="servers" ns="http://docs.openstack.org/compute/api/v1.1"
|
||||||
|
xmlns="http://relaxng.org/ns/structure/1.0">
|
||||||
|
<zeroOrMore>
|
||||||
|
<element name="server">
|
||||||
|
<attribute name="name"> <text/> </attribute>
|
||||||
|
<attribute name="id"> <text/> </attribute>
|
||||||
|
<zeroOrMore>
|
||||||
|
<externalRef href="../atom-link.rng"/>
|
||||||
|
</zeroOrMore>
|
||||||
|
</element>
|
||||||
|
</zeroOrMore>
|
||||||
|
</element>
|
|
@ -163,7 +163,7 @@ class Controller(object):
|
||||||
|
|
||||||
@scheduler_api.redirect_handler
|
@scheduler_api.redirect_handler
|
||||||
def update(self, req, id, body):
|
def update(self, req, id, body):
|
||||||
"""Update server name then pass on to version-specific controller"""
|
"""Update server then pass on to version-specific controller"""
|
||||||
if len(req.body) == 0:
|
if len(req.body) == 0:
|
||||||
raise exc.HTTPUnprocessableEntity()
|
raise exc.HTTPUnprocessableEntity()
|
||||||
|
|
||||||
|
@ -178,6 +178,14 @@ class Controller(object):
|
||||||
self.helper._validate_server_name(name)
|
self.helper._validate_server_name(name)
|
||||||
update_dict['display_name'] = name.strip()
|
update_dict['display_name'] = name.strip()
|
||||||
|
|
||||||
|
if 'accessIPv4' in body['server']:
|
||||||
|
access_ipv4 = body['server']['accessIPv4']
|
||||||
|
update_dict['access_ip_v4'] = access_ipv4.strip()
|
||||||
|
|
||||||
|
if 'accessIPv6' in body['server']:
|
||||||
|
access_ipv6 = body['server']['accessIPv6']
|
||||||
|
update_dict['access_ip_v6'] = access_ipv6.strip()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.compute_api.update(ctxt, id, **update_dict)
|
self.compute_api.update(ctxt, id, **update_dict)
|
||||||
except exception.NotFound:
|
except exception.NotFound:
|
||||||
|
@ -642,14 +650,16 @@ class ControllerV11(Controller):
|
||||||
return common.get_id_from_href(flavor_ref)
|
return common.get_id_from_href(flavor_ref)
|
||||||
|
|
||||||
def _build_view(self, req, instance, is_detail=False):
|
def _build_view(self, req, instance, is_detail=False):
|
||||||
|
project_id = getattr(req.environ['nova.context'], 'project_id', '')
|
||||||
base_url = req.application_url
|
base_url = req.application_url
|
||||||
flavor_builder = nova.api.openstack.views.flavors.ViewBuilderV11(
|
flavor_builder = nova.api.openstack.views.flavors.ViewBuilderV11(
|
||||||
base_url)
|
base_url, project_id)
|
||||||
image_builder = nova.api.openstack.views.images.ViewBuilderV11(
|
image_builder = nova.api.openstack.views.images.ViewBuilderV11(
|
||||||
base_url)
|
base_url, project_id)
|
||||||
addresses_builder = nova.api.openstack.views.addresses.ViewBuilderV11()
|
addresses_builder = nova.api.openstack.views.addresses.ViewBuilderV11()
|
||||||
builder = nova.api.openstack.views.servers.ViewBuilderV11(
|
builder = nova.api.openstack.views.servers.ViewBuilderV11(
|
||||||
addresses_builder, flavor_builder, image_builder, base_url)
|
addresses_builder, flavor_builder, image_builder,
|
||||||
|
base_url, project_id)
|
||||||
|
|
||||||
return builder.build(instance, is_detail=is_detail)
|
return builder.build(instance, is_detail=is_detail)
|
||||||
|
|
||||||
|
@ -837,6 +847,10 @@ class ServerXMLSerializer(wsgi.XMLDictSerializer):
|
||||||
node.setAttribute('created', str(server['created']))
|
node.setAttribute('created', str(server['created']))
|
||||||
node.setAttribute('updated', str(server['updated']))
|
node.setAttribute('updated', str(server['updated']))
|
||||||
node.setAttribute('status', server['status'])
|
node.setAttribute('status', server['status'])
|
||||||
|
if 'accessIPv4' in server:
|
||||||
|
node.setAttribute('accessIPv4', str(server['accessIPv4']))
|
||||||
|
if 'accessIPv6' in server:
|
||||||
|
node.setAttribute('accessIPv6', str(server['accessIPv6']))
|
||||||
if 'progress' in server:
|
if 'progress' in server:
|
||||||
node.setAttribute('progress', str(server['progress']))
|
node.setAttribute('progress', str(server['progress']))
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
|
||||||
from nova.api.openstack import common
|
from nova.api.openstack import common
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,11 +62,12 @@ class ViewBuilder(object):
|
||||||
class ViewBuilderV11(ViewBuilder):
|
class ViewBuilderV11(ViewBuilder):
|
||||||
"""Openstack API v1.1 flavors view builder."""
|
"""Openstack API v1.1 flavors view builder."""
|
||||||
|
|
||||||
def __init__(self, base_url):
|
def __init__(self, base_url, project_id=""):
|
||||||
"""
|
"""
|
||||||
:param base_url: url of the root wsgi application
|
:param base_url: url of the root wsgi application
|
||||||
"""
|
"""
|
||||||
self.base_url = base_url
|
self.base_url = base_url
|
||||||
|
self.project_id = project_id
|
||||||
|
|
||||||
def _build_extra(self, flavor_obj):
|
def _build_extra(self, flavor_obj):
|
||||||
flavor_obj["links"] = self._build_links(flavor_obj)
|
flavor_obj["links"] = self._build_links(flavor_obj)
|
||||||
|
@ -88,11 +92,10 @@ class ViewBuilderV11(ViewBuilder):
|
||||||
|
|
||||||
def generate_href(self, flavor_id):
|
def generate_href(self, flavor_id):
|
||||||
"""Create an url that refers to a specific flavor id."""
|
"""Create an url that refers to a specific flavor id."""
|
||||||
return "%s/flavors/%s" % (self.base_url, flavor_id)
|
return os.path.join(self.base_url, self.project_id,
|
||||||
|
"flavors", str(flavor_id))
|
||||||
|
|
||||||
def generate_bookmark(self, flavor_id):
|
def generate_bookmark(self, flavor_id):
|
||||||
"""Create an url that refers to a specific flavor id."""
|
"""Create an url that refers to a specific flavor id."""
|
||||||
return "%s/flavors/%s" % (
|
return os.path.join(common.remove_version_from_href(self.base_url),
|
||||||
common.remove_version_from_href(self.base_url),
|
self.project_id, "flavors", str(flavor_id))
|
||||||
flavor_id,
|
|
||||||
)
|
|
||||||
|
|
|
@ -23,9 +23,10 @@ from nova.api.openstack import common
|
||||||
class ViewBuilder(object):
|
class ViewBuilder(object):
|
||||||
"""Base class for generating responses to OpenStack API image requests."""
|
"""Base class for generating responses to OpenStack API image requests."""
|
||||||
|
|
||||||
def __init__(self, base_url):
|
def __init__(self, base_url, project_id=""):
|
||||||
"""Initialize new `ViewBuilder`."""
|
"""Initialize new `ViewBuilder`."""
|
||||||
self._url = base_url
|
self.base_url = base_url
|
||||||
|
self.project_id = project_id
|
||||||
|
|
||||||
def _format_dates(self, image):
|
def _format_dates(self, image):
|
||||||
"""Update all date fields to ensure standardized formatting."""
|
"""Update all date fields to ensure standardized formatting."""
|
||||||
|
@ -54,7 +55,7 @@ class ViewBuilder(object):
|
||||||
|
|
||||||
def generate_href(self, image_id):
|
def generate_href(self, image_id):
|
||||||
"""Return an href string pointing to this object."""
|
"""Return an href string pointing to this object."""
|
||||||
return os.path.join(self._url, "images", str(image_id))
|
return os.path.join(self.base_url, "images", str(image_id))
|
||||||
|
|
||||||
def build(self, image_obj, detail=False):
|
def build(self, image_obj, detail=False):
|
||||||
"""Return a standardized image structure for display by the API."""
|
"""Return a standardized image structure for display by the API."""
|
||||||
|
@ -117,6 +118,11 @@ class ViewBuilderV11(ViewBuilder):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def generate_href(self, image_id):
|
||||||
|
"""Return an href string pointing to this object."""
|
||||||
|
return os.path.join(self.base_url, self.project_id,
|
||||||
|
"images", str(image_id))
|
||||||
|
|
||||||
def build(self, image_obj, detail=False):
|
def build(self, image_obj, detail=False):
|
||||||
"""Return a standardized image structure for display by the API."""
|
"""Return a standardized image structure for display by the API."""
|
||||||
image = ViewBuilder.build(self, image_obj, detail)
|
image = ViewBuilder.build(self, image_obj, detail)
|
||||||
|
@ -142,5 +148,5 @@ class ViewBuilderV11(ViewBuilder):
|
||||||
|
|
||||||
def generate_bookmark(self, image_id):
|
def generate_bookmark(self, image_id):
|
||||||
"""Create an url that refers to a specific flavor id."""
|
"""Create an url that refers to a specific flavor id."""
|
||||||
return os.path.join(common.remove_version_from_href(self._url),
|
return os.path.join(common.remove_version_from_href(self.base_url),
|
||||||
"images", str(image_id))
|
self.project_id, "images", str(image_id))
|
||||||
|
|
|
@ -128,11 +128,12 @@ class ViewBuilderV10(ViewBuilder):
|
||||||
class ViewBuilderV11(ViewBuilder):
|
class ViewBuilderV11(ViewBuilder):
|
||||||
"""Model an Openstack API V1.0 server response."""
|
"""Model an Openstack API V1.0 server response."""
|
||||||
def __init__(self, addresses_builder, flavor_builder, image_builder,
|
def __init__(self, addresses_builder, flavor_builder, image_builder,
|
||||||
base_url):
|
base_url, project_id=""):
|
||||||
ViewBuilder.__init__(self, addresses_builder)
|
ViewBuilder.__init__(self, addresses_builder)
|
||||||
self.flavor_builder = flavor_builder
|
self.flavor_builder = flavor_builder
|
||||||
self.image_builder = image_builder
|
self.image_builder = image_builder
|
||||||
self.base_url = base_url
|
self.base_url = base_url
|
||||||
|
self.project_id = project_id
|
||||||
|
|
||||||
def _build_detail(self, inst):
|
def _build_detail(self, inst):
|
||||||
response = super(ViewBuilderV11, self)._build_detail(inst)
|
response = super(ViewBuilderV11, self)._build_detail(inst)
|
||||||
|
@ -143,6 +144,10 @@ class ViewBuilderV11(ViewBuilder):
|
||||||
response['server']['progress'] = 100
|
response['server']['progress'] = 100
|
||||||
elif response['server']['status'] == "BUILD":
|
elif response['server']['status'] == "BUILD":
|
||||||
response['server']['progress'] = 0
|
response['server']['progress'] = 0
|
||||||
|
|
||||||
|
response['server']['accessIPv4'] = inst.get('access_ip_v4') or ""
|
||||||
|
response['server']['accessIPv6'] = inst.get('access_ip_v6') or ""
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def _build_image(self, response, inst):
|
def _build_image(self, response, inst):
|
||||||
|
@ -202,9 +207,10 @@ class ViewBuilderV11(ViewBuilder):
|
||||||
|
|
||||||
def generate_href(self, server_id):
|
def generate_href(self, server_id):
|
||||||
"""Create an url that refers to a specific server id."""
|
"""Create an url that refers to a specific server id."""
|
||||||
return os.path.join(self.base_url, "servers", str(server_id))
|
return os.path.join(self.base_url, self.project_id,
|
||||||
|
"servers", str(server_id))
|
||||||
|
|
||||||
def generate_bookmark(self, server_id):
|
def generate_bookmark(self, server_id):
|
||||||
"""Create an url that refers to a specific flavor id."""
|
"""Create an url that refers to a specific flavor id."""
|
||||||
return os.path.join(common.remove_version_from_href(self.base_url),
|
return os.path.join(common.remove_version_from_href(self.base_url),
|
||||||
"servers", str(server_id))
|
self.project_id, "servers", str(server_id))
|
||||||
|
|
|
@ -486,6 +486,10 @@ class Resource(wsgi.Application):
|
||||||
msg = _("Malformed request body")
|
msg = _("Malformed request body")
|
||||||
return faults.Fault(webob.exc.HTTPBadRequest(explanation=msg))
|
return faults.Fault(webob.exc.HTTPBadRequest(explanation=msg))
|
||||||
|
|
||||||
|
project_id = args.pop("project_id", None)
|
||||||
|
if 'nova.context' in request.environ and project_id:
|
||||||
|
request.environ['nova.context'].project_id = project_id
|
||||||
|
|
||||||
try:
|
try:
|
||||||
action_result = self.dispatch(request, action, args)
|
action_result = self.dispatch(request, action, args)
|
||||||
except webob.exc.HTTPException as ex:
|
except webob.exc.HTTPException as ex:
|
||||||
|
|
|
@ -163,7 +163,8 @@ class API(base.Base):
|
||||||
key_name=None, key_data=None, security_group='default',
|
key_name=None, key_data=None, security_group='default',
|
||||||
availability_zone=None, user_data=None, metadata=None,
|
availability_zone=None, user_data=None, metadata=None,
|
||||||
injected_files=None, admin_password=None, zone_blob=None,
|
injected_files=None, admin_password=None, zone_blob=None,
|
||||||
reservation_id=None, requested_networks=None):
|
reservation_id=None, access_ip_v4=None, access_ip_v6=None,
|
||||||
|
requested_networks=None):
|
||||||
"""Verify all the input parameters regardless of the provisioning
|
"""Verify all the input parameters regardless of the provisioning
|
||||||
strategy being performed."""
|
strategy being performed."""
|
||||||
|
|
||||||
|
@ -258,6 +259,8 @@ class API(base.Base):
|
||||||
'key_data': key_data,
|
'key_data': key_data,
|
||||||
'locked': False,
|
'locked': False,
|
||||||
'metadata': metadata,
|
'metadata': metadata,
|
||||||
|
'access_ip_v4': access_ip_v4,
|
||||||
|
'access_ip_v6': access_ip_v6,
|
||||||
'availability_zone': availability_zone,
|
'availability_zone': availability_zone,
|
||||||
'os_type': os_type,
|
'os_type': os_type,
|
||||||
'architecture': architecture,
|
'architecture': architecture,
|
||||||
|
@ -450,6 +453,7 @@ class API(base.Base):
|
||||||
availability_zone=None, user_data=None, metadata=None,
|
availability_zone=None, user_data=None, metadata=None,
|
||||||
injected_files=None, admin_password=None, zone_blob=None,
|
injected_files=None, admin_password=None, zone_blob=None,
|
||||||
reservation_id=None, block_device_mapping=None,
|
reservation_id=None, block_device_mapping=None,
|
||||||
|
access_ip_v4=None, access_ip_v6=None,
|
||||||
requested_networks=None):
|
requested_networks=None):
|
||||||
"""Provision the instances by passing the whole request to
|
"""Provision the instances by passing the whole request to
|
||||||
the Scheduler for execution. Returns a Reservation ID
|
the Scheduler for execution. Returns a Reservation ID
|
||||||
|
@ -466,7 +470,8 @@ class API(base.Base):
|
||||||
key_name, key_data, security_group,
|
key_name, key_data, security_group,
|
||||||
availability_zone, user_data, metadata,
|
availability_zone, user_data, metadata,
|
||||||
injected_files, admin_password, zone_blob,
|
injected_files, admin_password, zone_blob,
|
||||||
reservation_id, requested_networks)
|
reservation_id, access_ip_v4, access_ip_v6,
|
||||||
|
requested_networks)
|
||||||
|
|
||||||
self._ask_scheduler_to_create_instance(context, base_options,
|
self._ask_scheduler_to_create_instance(context, base_options,
|
||||||
instance_type, zone_blob,
|
instance_type, zone_blob,
|
||||||
|
@ -485,6 +490,7 @@ class API(base.Base):
|
||||||
availability_zone=None, user_data=None, metadata=None,
|
availability_zone=None, user_data=None, metadata=None,
|
||||||
injected_files=None, admin_password=None, zone_blob=None,
|
injected_files=None, admin_password=None, zone_blob=None,
|
||||||
reservation_id=None, block_device_mapping=None,
|
reservation_id=None, block_device_mapping=None,
|
||||||
|
access_ip_v4=None, access_ip_v6=None,
|
||||||
requested_networks=None):
|
requested_networks=None):
|
||||||
"""
|
"""
|
||||||
Provision the instances by sending off a series of single
|
Provision the instances by sending off a series of single
|
||||||
|
@ -509,7 +515,8 @@ class API(base.Base):
|
||||||
key_name, key_data, security_group,
|
key_name, key_data, security_group,
|
||||||
availability_zone, user_data, metadata,
|
availability_zone, user_data, metadata,
|
||||||
injected_files, admin_password, zone_blob,
|
injected_files, admin_password, zone_blob,
|
||||||
reservation_id, requested_networks)
|
reservation_id, access_ip_v4, access_ip_v6,
|
||||||
|
requested_networks)
|
||||||
|
|
||||||
block_device_mapping = block_device_mapping or []
|
block_device_mapping = block_device_mapping or []
|
||||||
instances = []
|
instances = []
|
||||||
|
@ -627,6 +634,78 @@ class API(base.Base):
|
||||||
self.db.queue_get_for(context, FLAGS.compute_topic, host),
|
self.db.queue_get_for(context, FLAGS.compute_topic, host),
|
||||||
{'method': 'refresh_provider_fw_rules', 'args': {}})
|
{'method': 'refresh_provider_fw_rules', 'args': {}})
|
||||||
|
|
||||||
|
def _is_security_group_associated_with_server(self, security_group,
|
||||||
|
instance_id):
|
||||||
|
"""Check if the security group is already associated
|
||||||
|
with the instance. If Yes, return True.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not security_group:
|
||||||
|
return False
|
||||||
|
|
||||||
|
instances = security_group.get('instances')
|
||||||
|
if not instances:
|
||||||
|
return False
|
||||||
|
|
||||||
|
inst_id = None
|
||||||
|
for inst_id in (instance['id'] for instance in instances \
|
||||||
|
if instance_id == instance['id']):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def add_security_group(self, context, instance_id, security_group_name):
|
||||||
|
"""Add security group to the instance"""
|
||||||
|
security_group = db.security_group_get_by_name(context,
|
||||||
|
context.project_id,
|
||||||
|
security_group_name)
|
||||||
|
# check if the server exists
|
||||||
|
inst = db.instance_get(context, instance_id)
|
||||||
|
#check if the security group is associated with the server
|
||||||
|
if self._is_security_group_associated_with_server(security_group,
|
||||||
|
instance_id):
|
||||||
|
raise exception.SecurityGroupExistsForInstance(
|
||||||
|
security_group_id=security_group['id'],
|
||||||
|
instance_id=instance_id)
|
||||||
|
|
||||||
|
#check if the instance is in running state
|
||||||
|
if inst['state'] != power_state.RUNNING:
|
||||||
|
raise exception.InstanceNotRunning(instance_id=instance_id)
|
||||||
|
|
||||||
|
db.instance_add_security_group(context.elevated(),
|
||||||
|
instance_id,
|
||||||
|
security_group['id'])
|
||||||
|
rpc.cast(context,
|
||||||
|
db.queue_get_for(context, FLAGS.compute_topic, inst['host']),
|
||||||
|
{"method": "refresh_security_group_rules",
|
||||||
|
"args": {"security_group_id": security_group['id']}})
|
||||||
|
|
||||||
|
def remove_security_group(self, context, instance_id, security_group_name):
|
||||||
|
"""Remove the security group associated with the instance"""
|
||||||
|
security_group = db.security_group_get_by_name(context,
|
||||||
|
context.project_id,
|
||||||
|
security_group_name)
|
||||||
|
# check if the server exists
|
||||||
|
inst = db.instance_get(context, instance_id)
|
||||||
|
#check if the security group is associated with the server
|
||||||
|
if not self._is_security_group_associated_with_server(security_group,
|
||||||
|
instance_id):
|
||||||
|
raise exception.SecurityGroupNotExistsForInstance(
|
||||||
|
security_group_id=security_group['id'],
|
||||||
|
instance_id=instance_id)
|
||||||
|
|
||||||
|
#check if the instance is in running state
|
||||||
|
if inst['state'] != power_state.RUNNING:
|
||||||
|
raise exception.InstanceNotRunning(instance_id=instance_id)
|
||||||
|
|
||||||
|
db.instance_remove_security_group(context.elevated(),
|
||||||
|
instance_id,
|
||||||
|
security_group['id'])
|
||||||
|
rpc.cast(context,
|
||||||
|
db.queue_get_for(context, FLAGS.compute_topic, inst['host']),
|
||||||
|
{"method": "refresh_security_group_rules",
|
||||||
|
"args": {"security_group_id": security_group['id']}})
|
||||||
|
|
||||||
@scheduler_api.reroute_compute("update")
|
@scheduler_api.reroute_compute("update")
|
||||||
def update(self, context, instance_id, **kwargs):
|
def update(self, context, instance_id, **kwargs):
|
||||||
"""Updates the instance in the datastore.
|
"""Updates the instance in the datastore.
|
||||||
|
|
|
@ -569,6 +569,12 @@ def instance_add_security_group(context, instance_id, security_group_id):
|
||||||
security_group_id)
|
security_group_id)
|
||||||
|
|
||||||
|
|
||||||
|
def instance_remove_security_group(context, instance_id, security_group_id):
|
||||||
|
"""Disassociate the given security group from the given instance."""
|
||||||
|
return IMPL.instance_remove_security_group(context, instance_id,
|
||||||
|
security_group_id)
|
||||||
|
|
||||||
|
|
||||||
def instance_action_create(context, values):
|
def instance_action_create(context, values):
|
||||||
"""Create an instance action from the values dictionary."""
|
"""Create an instance action from the values dictionary."""
|
||||||
return IMPL.instance_action_create(context, values)
|
return IMPL.instance_action_create(context, values)
|
||||||
|
|
|
@ -1514,6 +1514,19 @@ def instance_add_security_group(context, instance_id, security_group_id):
|
||||||
instance_ref.save(session=session)
|
instance_ref.save(session=session)
|
||||||
|
|
||||||
|
|
||||||
|
@require_context
|
||||||
|
def instance_remove_security_group(context, instance_id, security_group_id):
|
||||||
|
"""Disassociate the given security group from the given instance"""
|
||||||
|
session = get_session()
|
||||||
|
|
||||||
|
session.query(models.SecurityGroupInstanceAssociation).\
|
||||||
|
filter_by(instance_id=instance_id).\
|
||||||
|
filter_by(security_group_id=security_group_id).\
|
||||||
|
update({'deleted': True,
|
||||||
|
'deleted_at': utils.utcnow(),
|
||||||
|
'updated_at': literal_column('updated_at')})
|
||||||
|
|
||||||
|
|
||||||
@require_context
|
@require_context
|
||||||
def instance_action_create(context, values):
|
def instance_action_create(context, values):
|
||||||
"""Create an instance action from the values dictionary."""
|
"""Create an instance action from the values dictionary."""
|
||||||
|
@ -2484,6 +2497,7 @@ def security_group_get(context, security_group_id, session=None):
|
||||||
filter_by(deleted=can_read_deleted(context),).\
|
filter_by(deleted=can_read_deleted(context),).\
|
||||||
filter_by(id=security_group_id).\
|
filter_by(id=security_group_id).\
|
||||||
options(joinedload_all('rules')).\
|
options(joinedload_all('rules')).\
|
||||||
|
options(joinedload_all('instances')).\
|
||||||
first()
|
first()
|
||||||
else:
|
else:
|
||||||
result = session.query(models.SecurityGroup).\
|
result = session.query(models.SecurityGroup).\
|
||||||
|
@ -2491,6 +2505,7 @@ def security_group_get(context, security_group_id, session=None):
|
||||||
filter_by(id=security_group_id).\
|
filter_by(id=security_group_id).\
|
||||||
filter_by(project_id=context.project_id).\
|
filter_by(project_id=context.project_id).\
|
||||||
options(joinedload_all('rules')).\
|
options(joinedload_all('rules')).\
|
||||||
|
options(joinedload_all('instances')).\
|
||||||
first()
|
first()
|
||||||
if not result:
|
if not result:
|
||||||
raise exception.SecurityGroupNotFound(
|
raise exception.SecurityGroupNotFound(
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
# Copyright 2011 OpenStack LLC.
|
||||||
|
#
|
||||||
|
# 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 sqlalchemy import Column, Integer, MetaData, Table, String
|
||||||
|
|
||||||
|
meta = MetaData()
|
||||||
|
|
||||||
|
accessIPv4 = Column(
|
||||||
|
'access_ip_v4',
|
||||||
|
String(length=255, convert_unicode=False, assert_unicode=None,
|
||||||
|
unicode_error=None, _warn_on_bytestring=False),
|
||||||
|
nullable=True)
|
||||||
|
|
||||||
|
accessIPv6 = Column(
|
||||||
|
'access_ip_v6',
|
||||||
|
String(length=255, convert_unicode=False, assert_unicode=None,
|
||||||
|
unicode_error=None, _warn_on_bytestring=False),
|
||||||
|
nullable=True)
|
||||||
|
|
||||||
|
instances = Table('instances', meta,
|
||||||
|
Column('id', Integer(), primary_key=True, nullable=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade(migrate_engine):
|
||||||
|
# Upgrade operations go here. Don't create your own engine;
|
||||||
|
# bind migrate_engine to your metadata
|
||||||
|
meta.bind = migrate_engine
|
||||||
|
instances.create_column(accessIPv4)
|
||||||
|
instances.create_column(accessIPv6)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade(migrate_engine):
|
||||||
|
# Operations to reverse the above upgrade go here.
|
||||||
|
meta.bind = migrate_engine
|
||||||
|
instances.drop_column('access_ip_v4')
|
||||||
|
instances.drop_column('access_ip_v6')
|
|
@ -231,6 +231,11 @@ class Instance(BASE, NovaBase):
|
||||||
|
|
||||||
root_device_name = Column(String(255))
|
root_device_name = Column(String(255))
|
||||||
|
|
||||||
|
# User editable field meant to represent what ip should be used
|
||||||
|
# to connect to the instance
|
||||||
|
access_ip_v4 = Column(String(255))
|
||||||
|
access_ip_v6 = Column(String(255))
|
||||||
|
|
||||||
# TODO(vish): see Ewan's email about state improvements, probably
|
# TODO(vish): see Ewan's email about state improvements, probably
|
||||||
# should be in a driver base class or some such
|
# should be in a driver base class or some such
|
||||||
# vmstate_state = running, halted, suspended, paused
|
# vmstate_state = running, halted, suspended, paused
|
||||||
|
|
|
@ -563,6 +563,16 @@ class SecurityGroupNotFoundForRule(SecurityGroupNotFound):
|
||||||
message = _("Security group with rule %(rule_id)s not found.")
|
message = _("Security group with rule %(rule_id)s not found.")
|
||||||
|
|
||||||
|
|
||||||
|
class SecurityGroupExistsForInstance(Invalid):
|
||||||
|
message = _("Security group %(security_group_id)s is already associated"
|
||||||
|
" with the instance %(instance_id)s")
|
||||||
|
|
||||||
|
|
||||||
|
class SecurityGroupNotExistsForInstance(Invalid):
|
||||||
|
message = _("Security group %(security_group_id)s is not associated with"
|
||||||
|
" the instance %(instance_id)s")
|
||||||
|
|
||||||
|
|
||||||
class MigrationNotFound(NotFound):
|
class MigrationNotFound(NotFound):
|
||||||
message = _("Migration %(migration_id)s could not be found.")
|
message = _("Migration %(migration_id)s could not be found.")
|
||||||
|
|
||||||
|
|
|
@ -44,14 +44,15 @@ class RateLimitingMiddlewareTest(test.TestCase):
|
||||||
action = middleware.get_action_name(req)
|
action = middleware.get_action_name(req)
|
||||||
self.assertEqual(action, action_name)
|
self.assertEqual(action, action_name)
|
||||||
|
|
||||||
verify('PUT', '/servers/4', 'PUT')
|
verify('PUT', '/fake/servers/4', 'PUT')
|
||||||
verify('DELETE', '/servers/4', 'DELETE')
|
verify('DELETE', '/fake/servers/4', 'DELETE')
|
||||||
verify('POST', '/images/4', 'POST')
|
verify('POST', '/fake/images/4', 'POST')
|
||||||
verify('POST', '/servers/4', 'POST servers')
|
verify('POST', '/fake/servers/4', 'POST servers')
|
||||||
verify('GET', '/foo?a=4&changes-since=never&b=5', 'GET changes-since')
|
verify('GET', '/fake/foo?a=4&changes-since=never&b=5',
|
||||||
verify('GET', '/foo?a=4&monkeys-since=never&b=5', None)
|
'GET changes-since')
|
||||||
verify('GET', '/servers/4', None)
|
verify('GET', '/fake/foo?a=4&monkeys-since=never&b=5', None)
|
||||||
verify('HEAD', '/servers/4', None)
|
verify('GET', '/fake/servers/4', None)
|
||||||
|
verify('HEAD', '/fake/servers/4', None)
|
||||||
|
|
||||||
def exhaust(self, middleware, method, url, username, times):
|
def exhaust(self, middleware, method, url, username, times):
|
||||||
req = Request.blank(url, dict(REQUEST_METHOD=method),
|
req = Request.blank(url, dict(REQUEST_METHOD=method),
|
||||||
|
@ -67,13 +68,13 @@ class RateLimitingMiddlewareTest(test.TestCase):
|
||||||
|
|
||||||
def test_single_action(self):
|
def test_single_action(self):
|
||||||
middleware = RateLimitingMiddleware(simple_wsgi)
|
middleware = RateLimitingMiddleware(simple_wsgi)
|
||||||
self.exhaust(middleware, 'DELETE', '/servers/4', 'usr1', 100)
|
self.exhaust(middleware, 'DELETE', '/fake/servers/4', 'usr1', 100)
|
||||||
self.exhaust(middleware, 'DELETE', '/servers/4', 'usr2', 100)
|
self.exhaust(middleware, 'DELETE', '/fake/servers/4', 'usr2', 100)
|
||||||
|
|
||||||
def test_POST_servers_action_implies_POST_action(self):
|
def test_POST_servers_action_implies_POST_action(self):
|
||||||
middleware = RateLimitingMiddleware(simple_wsgi)
|
middleware = RateLimitingMiddleware(simple_wsgi)
|
||||||
self.exhaust(middleware, 'POST', '/servers/4', 'usr1', 10)
|
self.exhaust(middleware, 'POST', '/fake/servers/4', 'usr1', 10)
|
||||||
self.exhaust(middleware, 'POST', '/images/4', 'usr2', 10)
|
self.exhaust(middleware, 'POST', '/fake/images/4', 'usr2', 10)
|
||||||
self.assertTrue(set(middleware.limiter._levels) == \
|
self.assertTrue(set(middleware.limiter._levels) == \
|
||||||
set(['usr1:POST', 'usr1:POST servers', 'usr2:POST']))
|
set(['usr1:POST', 'usr1:POST servers', 'usr2:POST']))
|
||||||
|
|
||||||
|
@ -81,11 +82,11 @@ class RateLimitingMiddlewareTest(test.TestCase):
|
||||||
middleware = RateLimitingMiddleware(simple_wsgi)
|
middleware = RateLimitingMiddleware(simple_wsgi)
|
||||||
# Use up all of our "POST" allowance for the minute, 5 times
|
# Use up all of our "POST" allowance for the minute, 5 times
|
||||||
for i in range(5):
|
for i in range(5):
|
||||||
self.exhaust(middleware, 'POST', '/servers/4', 'usr1', 10)
|
self.exhaust(middleware, 'POST', '/fake/servers/4', 'usr1', 10)
|
||||||
# Reset the 'POST' action counter.
|
# Reset the 'POST' action counter.
|
||||||
del middleware.limiter._levels['usr1:POST']
|
del middleware.limiter._levels['usr1:POST']
|
||||||
# All 50 daily "POST servers" actions should be all used up
|
# All 50 daily "POST servers" actions should be all used up
|
||||||
self.exhaust(middleware, 'POST', '/servers/4', 'usr1', 0)
|
self.exhaust(middleware, 'POST', '/fake/servers/4', 'usr1', 0)
|
||||||
|
|
||||||
def test_proxy_ctor_works(self):
|
def test_proxy_ctor_works(self):
|
||||||
middleware = RateLimitingMiddleware(simple_wsgi)
|
middleware = RateLimitingMiddleware(simple_wsgi)
|
||||||
|
|
|
@ -120,7 +120,7 @@ class CreateserverextTest(test.TestCase):
|
||||||
return {'server': server}
|
return {'server': server}
|
||||||
|
|
||||||
def _get_create_request_json(self, body_dict):
|
def _get_create_request_json(self, body_dict):
|
||||||
req = webob.Request.blank('/v1.1/os-create-server-ext')
|
req = webob.Request.blank('/v1.1/123/os-create-server-ext')
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json.dumps(body_dict)
|
req.body = json.dumps(body_dict)
|
||||||
|
@ -164,7 +164,7 @@ class CreateserverextTest(test.TestCase):
|
||||||
return ''.join(body_parts)
|
return ''.join(body_parts)
|
||||||
|
|
||||||
def _get_create_request_xml(self, body_dict):
|
def _get_create_request_xml(self, body_dict):
|
||||||
req = webob.Request.blank('/v1.1/os-create-server-ext')
|
req = webob.Request.blank('/v1.1/123/os-create-server-ext')
|
||||||
req.content_type = 'application/xml'
|
req.content_type = 'application/xml'
|
||||||
req.accept = 'application/xml'
|
req.accept = 'application/xml'
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
|
|
|
@ -17,6 +17,7 @@ import json
|
||||||
import stubout
|
import stubout
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
|
from nova import compute
|
||||||
from nova import context
|
from nova import context
|
||||||
from nova import db
|
from nova import db
|
||||||
from nova import test
|
from nova import test
|
||||||
|
@ -29,6 +30,11 @@ from nova.api.openstack.contrib.floating_ips import _translate_floating_ip_view
|
||||||
|
|
||||||
|
|
||||||
def network_api_get_floating_ip(self, context, id):
|
def network_api_get_floating_ip(self, context, id):
|
||||||
|
return {'id': 1, 'address': '10.10.10.10',
|
||||||
|
'fixed_ip': None}
|
||||||
|
|
||||||
|
|
||||||
|
def network_api_get_floating_ip_by_ip(self, context, address):
|
||||||
return {'id': 1, 'address': '10.10.10.10',
|
return {'id': 1, 'address': '10.10.10.10',
|
||||||
'fixed_ip': {'address': '11.0.0.1'}}
|
'fixed_ip': {'address': '11.0.0.1'}}
|
||||||
|
|
||||||
|
@ -50,7 +56,7 @@ def network_api_release(self, context, address):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def network_api_associate(self, context, floating_ip, fixed_ip):
|
def compute_api_associate(self, context, instance_id, floating_ip):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,14 +84,16 @@ class FloatingIpTest(test.TestCase):
|
||||||
fakes.stub_out_rate_limiting(self.stubs)
|
fakes.stub_out_rate_limiting(self.stubs)
|
||||||
self.stubs.Set(network.api.API, "get_floating_ip",
|
self.stubs.Set(network.api.API, "get_floating_ip",
|
||||||
network_api_get_floating_ip)
|
network_api_get_floating_ip)
|
||||||
|
self.stubs.Set(network.api.API, "get_floating_ip_by_ip",
|
||||||
|
network_api_get_floating_ip)
|
||||||
self.stubs.Set(network.api.API, "list_floating_ips",
|
self.stubs.Set(network.api.API, "list_floating_ips",
|
||||||
network_api_list_floating_ips)
|
network_api_list_floating_ips)
|
||||||
self.stubs.Set(network.api.API, "allocate_floating_ip",
|
self.stubs.Set(network.api.API, "allocate_floating_ip",
|
||||||
network_api_allocate)
|
network_api_allocate)
|
||||||
self.stubs.Set(network.api.API, "release_floating_ip",
|
self.stubs.Set(network.api.API, "release_floating_ip",
|
||||||
network_api_release)
|
network_api_release)
|
||||||
self.stubs.Set(network.api.API, "associate_floating_ip",
|
self.stubs.Set(compute.api.API, "associate_floating_ip",
|
||||||
network_api_associate)
|
compute_api_associate)
|
||||||
self.stubs.Set(network.api.API, "disassociate_floating_ip",
|
self.stubs.Set(network.api.API, "disassociate_floating_ip",
|
||||||
network_api_disassociate)
|
network_api_disassociate)
|
||||||
self.context = context.get_admin_context()
|
self.context = context.get_admin_context()
|
||||||
|
@ -112,7 +120,7 @@ class FloatingIpTest(test.TestCase):
|
||||||
self.assertTrue('floating_ip' in view)
|
self.assertTrue('floating_ip' in view)
|
||||||
|
|
||||||
def test_floating_ips_list(self):
|
def test_floating_ips_list(self):
|
||||||
req = webob.Request.blank('/v1.1/os-floating-ips')
|
req = webob.Request.blank('/v1.1/123/os-floating-ips')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
res_dict = json.loads(res.body)
|
res_dict = json.loads(res.body)
|
||||||
|
@ -127,65 +135,91 @@ class FloatingIpTest(test.TestCase):
|
||||||
self.assertEqual(res_dict, response)
|
self.assertEqual(res_dict, response)
|
||||||
|
|
||||||
def test_floating_ip_show(self):
|
def test_floating_ip_show(self):
|
||||||
req = webob.Request.blank('/v1.1/os-floating-ips/1')
|
req = webob.Request.blank('/v1.1/123/os-floating-ips/1')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
res_dict = json.loads(res.body)
|
res_dict = json.loads(res.body)
|
||||||
self.assertEqual(res_dict['floating_ip']['id'], 1)
|
self.assertEqual(res_dict['floating_ip']['id'], 1)
|
||||||
self.assertEqual(res_dict['floating_ip']['ip'], '10.10.10.10')
|
self.assertEqual(res_dict['floating_ip']['ip'], '10.10.10.10')
|
||||||
self.assertEqual(res_dict['floating_ip']['fixed_ip'], '11.0.0.1')
|
|
||||||
self.assertEqual(res_dict['floating_ip']['instance_id'], None)
|
self.assertEqual(res_dict['floating_ip']['instance_id'], None)
|
||||||
|
|
||||||
def test_floating_ip_allocate(self):
|
def test_floating_ip_allocate(self):
|
||||||
req = webob.Request.blank('/v1.1/os-floating-ips')
|
req = webob.Request.blank('/v1.1/123/os-floating-ips')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
print res
|
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
ip = json.loads(res.body)['allocated']
|
ip = json.loads(res.body)['floating_ip']
|
||||||
|
|
||||||
expected = {
|
expected = {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"floating_ip": '10.10.10.10'}
|
"instance_id": None,
|
||||||
|
"ip": "10.10.10.10",
|
||||||
|
"fixed_ip": None}
|
||||||
self.assertEqual(ip, expected)
|
self.assertEqual(ip, expected)
|
||||||
|
|
||||||
def test_floating_ip_release(self):
|
def test_floating_ip_release(self):
|
||||||
req = webob.Request.blank('/v1.1/os-floating-ips/1')
|
req = webob.Request.blank('/v1.1/123/os-floating-ips/1')
|
||||||
req.method = 'DELETE'
|
req.method = 'DELETE'
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 202)
|
||||||
actual = json.loads(res.body)['released']
|
|
||||||
expected = {
|
|
||||||
"id": 1,
|
|
||||||
"floating_ip": '10.10.10.10'}
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
def test_floating_ip_associate(self):
|
def test_add_floating_ip_to_instance(self):
|
||||||
body = dict(associate_address=dict(fixed_ip='1.2.3.4'))
|
body = dict(addFloatingIp=dict(address='11.0.0.1'))
|
||||||
req = webob.Request.blank('/v1.1/os-floating-ips/1/associate')
|
req = webob.Request.blank('/v1.1/123/servers/test_inst/action')
|
||||||
req.method = 'POST'
|
req.method = "POST"
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
|
||||||
res = req.get_response(fakes.wsgi_app())
|
resp = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(resp.status_int, 202)
|
||||||
actual = json.loads(res.body)['associated']
|
|
||||||
expected = {
|
|
||||||
"floating_ip_id": '1',
|
|
||||||
"floating_ip": "10.10.10.10",
|
|
||||||
"fixed_ip": "1.2.3.4"}
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
def test_floating_ip_disassociate(self):
|
def test_remove_floating_ip_from_instance(self):
|
||||||
body = dict()
|
body = dict(removeFloatingIp=dict(address='11.0.0.1'))
|
||||||
req = webob.Request.blank('/v1.1/os-floating-ips/1/disassociate')
|
req = webob.Request.blank('/v1.1/123/servers/test_inst/action')
|
||||||
req.method = 'POST'
|
req.method = "POST"
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers["content-type"] = "application/json"
|
||||||
res = req.get_response(fakes.wsgi_app())
|
|
||||||
self.assertEqual(res.status_int, 200)
|
resp = req.get_response(fakes.wsgi_app())
|
||||||
ip = json.loads(res.body)['disassociated']
|
self.assertEqual(resp.status_int, 202)
|
||||||
expected = {
|
|
||||||
"floating_ip": '10.10.10.10',
|
def test_bad_address_param_in_remove_floating_ip(self):
|
||||||
"fixed_ip": '11.0.0.1'}
|
body = dict(removeFloatingIp=dict(badparam='11.0.0.1'))
|
||||||
self.assertEqual(ip, expected)
|
req = webob.Request.blank('/v1.1/123/servers/test_inst/action')
|
||||||
|
req.method = "POST"
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
req.headers["content-type"] = "application/json"
|
||||||
|
|
||||||
|
resp = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEqual(resp.status_int, 400)
|
||||||
|
|
||||||
|
def test_missing_dict_param_in_remove_floating_ip(self):
|
||||||
|
body = dict(removeFloatingIp='11.0.0.1')
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/test_inst/action')
|
||||||
|
req.method = "POST"
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
req.headers["content-type"] = "application/json"
|
||||||
|
|
||||||
|
resp = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEqual(resp.status_int, 400)
|
||||||
|
|
||||||
|
def test_bad_address_param_in_add_floating_ip(self):
|
||||||
|
body = dict(addFloatingIp=dict(badparam='11.0.0.1'))
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/test_inst/action')
|
||||||
|
req.method = "POST"
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
req.headers["content-type"] = "application/json"
|
||||||
|
|
||||||
|
resp = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEqual(resp.status_int, 400)
|
||||||
|
|
||||||
|
def test_missing_dict_param_in_add_floating_ip(self):
|
||||||
|
body = dict(addFloatingIp='11.0.0.1')
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/test_inst/action')
|
||||||
|
req.method = "POST"
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
req.headers["content-type"] = "application/json"
|
||||||
|
|
||||||
|
resp = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEqual(resp.status_int, 400)
|
||||||
|
|
|
@ -58,7 +58,7 @@ class KeypairsTest(test.TestCase):
|
||||||
self.context = context.get_admin_context()
|
self.context = context.get_admin_context()
|
||||||
|
|
||||||
def test_keypair_list(self):
|
def test_keypair_list(self):
|
||||||
req = webob.Request.blank('/v1.1/os-keypairs')
|
req = webob.Request.blank('/v1.1/123/os-keypairs')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
res_dict = json.loads(res.body)
|
res_dict = json.loads(res.body)
|
||||||
|
@ -67,7 +67,7 @@ class KeypairsTest(test.TestCase):
|
||||||
|
|
||||||
def test_keypair_create(self):
|
def test_keypair_create(self):
|
||||||
body = {'keypair': {'name': 'create_test'}}
|
body = {'keypair': {'name': 'create_test'}}
|
||||||
req = webob.Request.blank('/v1.1/os-keypairs')
|
req = webob.Request.blank('/v1.1/123/os-keypairs')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
@ -93,7 +93,7 @@ class KeypairsTest(test.TestCase):
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
req = webob.Request.blank('/v1.1/os-keypairs')
|
req = webob.Request.blank('/v1.1/123/os-keypairs')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
@ -105,7 +105,7 @@ class KeypairsTest(test.TestCase):
|
||||||
self.assertFalse('private_key' in res_dict['keypair'])
|
self.assertFalse('private_key' in res_dict['keypair'])
|
||||||
|
|
||||||
def test_keypair_delete(self):
|
def test_keypair_delete(self):
|
||||||
req = webob.Request.blank('/v1.1/os-keypairs/FAKE')
|
req = webob.Request.blank('/v1.1/123/os-keypairs/FAKE')
|
||||||
req.method = 'DELETE'
|
req.method = 'DELETE'
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
|
|
|
@ -55,7 +55,7 @@ class FixedIpTest(test.TestCase):
|
||||||
last_add_fixed_ip = (None, None)
|
last_add_fixed_ip = (None, None)
|
||||||
|
|
||||||
body = dict(addFixedIp=dict(networkId='test_net'))
|
body = dict(addFixedIp=dict(networkId='test_net'))
|
||||||
req = webob.Request.blank('/v1.1/servers/test_inst/action')
|
req = webob.Request.blank('/v1.1/123/servers/test_inst/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers['content-type'] = 'application/json'
|
req.headers['content-type'] = 'application/json'
|
||||||
|
@ -69,7 +69,7 @@ class FixedIpTest(test.TestCase):
|
||||||
last_add_fixed_ip = (None, None)
|
last_add_fixed_ip = (None, None)
|
||||||
|
|
||||||
body = dict(addFixedIp=dict())
|
body = dict(addFixedIp=dict())
|
||||||
req = webob.Request.blank('/v1.1/servers/test_inst/action')
|
req = webob.Request.blank('/v1.1/123/servers/test_inst/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers['content-type'] = 'application/json'
|
req.headers['content-type'] = 'application/json'
|
||||||
|
@ -83,7 +83,7 @@ class FixedIpTest(test.TestCase):
|
||||||
last_remove_fixed_ip = (None, None)
|
last_remove_fixed_ip = (None, None)
|
||||||
|
|
||||||
body = dict(removeFixedIp=dict(address='10.10.10.1'))
|
body = dict(removeFixedIp=dict(address='10.10.10.1'))
|
||||||
req = webob.Request.blank('/v1.1/servers/test_inst/action')
|
req = webob.Request.blank('/v1.1/123/servers/test_inst/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers['content-type'] = 'application/json'
|
req.headers['content-type'] = 'application/json'
|
||||||
|
@ -97,7 +97,7 @@ class FixedIpTest(test.TestCase):
|
||||||
last_remove_fixed_ip = (None, None)
|
last_remove_fixed_ip = (None, None)
|
||||||
|
|
||||||
body = dict(removeFixedIp=dict())
|
body = dict(removeFixedIp=dict())
|
||||||
req = webob.Request.blank('/v1.1/servers/test_inst/action')
|
req = webob.Request.blank('/v1.1/123/servers/test_inst/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers['content-type'] = 'application/json'
|
req.headers['content-type'] = 'application/json'
|
||||||
|
|
|
@ -78,7 +78,8 @@ class QuotaSetsTest(test.TestCase):
|
||||||
self.assertEqual(qs['injected_file_content_bytes'], 10240)
|
self.assertEqual(qs['injected_file_content_bytes'], 10240)
|
||||||
|
|
||||||
def test_quotas_defaults(self):
|
def test_quotas_defaults(self):
|
||||||
req = webob.Request.blank('/v1.1/os-quota-sets/fake_tenant/defaults')
|
uri = '/v1.1/fake_tenant/os-quota-sets/fake_tenant/defaults'
|
||||||
|
req = webob.Request.blank(uri)
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
|
@ -99,7 +100,7 @@ class QuotaSetsTest(test.TestCase):
|
||||||
self.assertEqual(json.loads(res.body), expected)
|
self.assertEqual(json.loads(res.body), expected)
|
||||||
|
|
||||||
def test_quotas_show_as_admin(self):
|
def test_quotas_show_as_admin(self):
|
||||||
req = webob.Request.blank('/v1.1/os-quota-sets/1234')
|
req = webob.Request.blank('/v1.1/1234/os-quota-sets/1234')
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
res = req.get_response(fakes.wsgi_app(
|
res = req.get_response(fakes.wsgi_app(
|
||||||
|
@ -109,7 +110,7 @@ class QuotaSetsTest(test.TestCase):
|
||||||
self.assertEqual(json.loads(res.body), quota_set('1234'))
|
self.assertEqual(json.loads(res.body), quota_set('1234'))
|
||||||
|
|
||||||
def test_quotas_show_as_unauthorized_user(self):
|
def test_quotas_show_as_unauthorized_user(self):
|
||||||
req = webob.Request.blank('/v1.1/os-quota-sets/1234')
|
req = webob.Request.blank('/v1.1/fake/os-quota-sets/1234')
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
res = req.get_response(fakes.wsgi_app(
|
res = req.get_response(fakes.wsgi_app(
|
||||||
|
@ -124,7 +125,7 @@ class QuotaSetsTest(test.TestCase):
|
||||||
'metadata_items': 128, 'injected_files': 5,
|
'metadata_items': 128, 'injected_files': 5,
|
||||||
'injected_file_content_bytes': 10240}}
|
'injected_file_content_bytes': 10240}}
|
||||||
|
|
||||||
req = webob.Request.blank('/v1.1/os-quota-sets/update_me')
|
req = webob.Request.blank('/v1.1/1234/os-quota-sets/update_me')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = json.dumps(updated_quota_set)
|
req.body = json.dumps(updated_quota_set)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
@ -141,7 +142,7 @@ class QuotaSetsTest(test.TestCase):
|
||||||
'metadata_items': 128, 'injected_files': 5,
|
'metadata_items': 128, 'injected_files': 5,
|
||||||
'injected_file_content_bytes': 10240}}
|
'injected_file_content_bytes': 10240}}
|
||||||
|
|
||||||
req = webob.Request.blank('/v1.1/os-quota-sets/update_me')
|
req = webob.Request.blank('/v1.1/1234/os-quota-sets/update_me')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = json.dumps(updated_quota_set)
|
req.body = json.dumps(updated_quota_set)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
|
|
@ -36,7 +36,7 @@ class RescueTest(test.TestCase):
|
||||||
|
|
||||||
def test_rescue(self):
|
def test_rescue(self):
|
||||||
body = dict(rescue=None)
|
body = dict(rescue=None)
|
||||||
req = webob.Request.blank('/v1.1/servers/test_inst/action')
|
req = webob.Request.blank('/v1.1/123/servers/test_inst/action')
|
||||||
req.method = "POST"
|
req.method = "POST"
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -46,7 +46,7 @@ class RescueTest(test.TestCase):
|
||||||
|
|
||||||
def test_unrescue(self):
|
def test_unrescue(self):
|
||||||
body = dict(unrescue=None)
|
body = dict(unrescue=None)
|
||||||
req = webob.Request.blank('/v1.1/servers/test_inst/action')
|
req = webob.Request.blank('/v1.1/123/servers/test_inst/action')
|
||||||
req.method = "POST"
|
req.method = "POST"
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
|
|
@ -15,17 +15,20 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import mox
|
||||||
|
import nova
|
||||||
import unittest
|
import unittest
|
||||||
import webob
|
import webob
|
||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
|
|
||||||
|
from nova import exception
|
||||||
from nova import test
|
from nova import test
|
||||||
from nova.api.openstack.contrib import security_groups
|
from nova.api.openstack.contrib import security_groups
|
||||||
from nova.tests.api.openstack import fakes
|
from nova.tests.api.openstack import fakes
|
||||||
|
|
||||||
|
|
||||||
def _get_create_request_json(body_dict):
|
def _get_create_request_json(body_dict):
|
||||||
req = webob.Request.blank('/v1.1/os-security-groups')
|
req = webob.Request.blank('/v1.1/123/os-security-groups')
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json.dumps(body_dict)
|
req.body = json.dumps(body_dict)
|
||||||
|
@ -51,6 +54,28 @@ def _create_security_group_request_dict(security_group):
|
||||||
return {'security_group': sg}
|
return {'security_group': sg}
|
||||||
|
|
||||||
|
|
||||||
|
def return_server(context, server_id):
|
||||||
|
return {'id': server_id, 'state': 0x01, 'host': "localhost"}
|
||||||
|
|
||||||
|
|
||||||
|
def return_non_running_server(context, server_id):
|
||||||
|
return {'id': server_id, 'state': 0x02,
|
||||||
|
'host': "localhost"}
|
||||||
|
|
||||||
|
|
||||||
|
def return_security_group(context, project_id, group_name):
|
||||||
|
return {'id': 1, 'name': group_name, "instances": [
|
||||||
|
{'id': 1}]}
|
||||||
|
|
||||||
|
|
||||||
|
def return_security_group_without_instances(context, project_id, group_name):
|
||||||
|
return {'id': 1, 'name': group_name}
|
||||||
|
|
||||||
|
|
||||||
|
def return_server_nonexistant(context, server_id):
|
||||||
|
raise exception.InstanceNotFound(instance_id=server_id)
|
||||||
|
|
||||||
|
|
||||||
class TestSecurityGroups(test.TestCase):
|
class TestSecurityGroups(test.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestSecurityGroups, self).setUp()
|
super(TestSecurityGroups, self).setUp()
|
||||||
|
@ -84,7 +109,7 @@ class TestSecurityGroups(test.TestCase):
|
||||||
return ''.join(body_parts)
|
return ''.join(body_parts)
|
||||||
|
|
||||||
def _get_create_request_xml(self, body_dict):
|
def _get_create_request_xml(self, body_dict):
|
||||||
req = webob.Request.blank('/v1.1/os-security-groups')
|
req = webob.Request.blank('/v1.1/123/os-security-groups')
|
||||||
req.headers['Content-Type'] = 'application/xml'
|
req.headers['Content-Type'] = 'application/xml'
|
||||||
req.content_type = 'application/xml'
|
req.content_type = 'application/xml'
|
||||||
req.accept = 'application/xml'
|
req.accept = 'application/xml'
|
||||||
|
@ -99,7 +124,7 @@ class TestSecurityGroups(test.TestCase):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def _delete_security_group(self, id):
|
def _delete_security_group(self, id):
|
||||||
request = webob.Request.blank('/v1.1/os-security-groups/%s'
|
request = webob.Request.blank('/v1.1/123/os-security-groups/%s'
|
||||||
% id)
|
% id)
|
||||||
request.method = 'DELETE'
|
request.method = 'DELETE'
|
||||||
response = request.get_response(fakes.wsgi_app())
|
response = request.get_response(fakes.wsgi_app())
|
||||||
|
@ -238,7 +263,7 @@ class TestSecurityGroups(test.TestCase):
|
||||||
security_group['description'] = "group-description"
|
security_group['description'] = "group-description"
|
||||||
response = _create_security_group_json(security_group)
|
response = _create_security_group_json(security_group)
|
||||||
|
|
||||||
req = webob.Request.blank('/v1.1/os-security-groups')
|
req = webob.Request.blank('/v1.1/123/os-security-groups')
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
response = req.get_response(fakes.wsgi_app())
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
@ -247,7 +272,7 @@ class TestSecurityGroups(test.TestCase):
|
||||||
expected = {'security_groups': [
|
expected = {'security_groups': [
|
||||||
{'id': 1,
|
{'id': 1,
|
||||||
'name':"default",
|
'name':"default",
|
||||||
'tenant_id': "fake",
|
'tenant_id': "123",
|
||||||
"description":"default",
|
"description":"default",
|
||||||
"rules": []
|
"rules": []
|
||||||
},
|
},
|
||||||
|
@ -257,7 +282,7 @@ class TestSecurityGroups(test.TestCase):
|
||||||
{
|
{
|
||||||
'id': 2,
|
'id': 2,
|
||||||
'name': "test",
|
'name': "test",
|
||||||
'tenant_id': "fake",
|
'tenant_id': "123",
|
||||||
"description": "group-description",
|
"description": "group-description",
|
||||||
"rules": []
|
"rules": []
|
||||||
}
|
}
|
||||||
|
@ -272,7 +297,7 @@ class TestSecurityGroups(test.TestCase):
|
||||||
response = _create_security_group_json(security_group)
|
response = _create_security_group_json(security_group)
|
||||||
|
|
||||||
res_dict = json.loads(response.body)
|
res_dict = json.loads(response.body)
|
||||||
req = webob.Request.blank('/v1.1/os-security-groups/%s' %
|
req = webob.Request.blank('/v1.1/123/os-security-groups/%s' %
|
||||||
res_dict['security_group']['id'])
|
res_dict['security_group']['id'])
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
|
@ -283,23 +308,22 @@ class TestSecurityGroups(test.TestCase):
|
||||||
'security_group': {
|
'security_group': {
|
||||||
'id': 2,
|
'id': 2,
|
||||||
'name': "test",
|
'name': "test",
|
||||||
'tenant_id': "fake",
|
'tenant_id': "123",
|
||||||
'description': "group-description",
|
'description': "group-description",
|
||||||
'rules': []
|
'rules': []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.assertEquals(response.status_int, 200)
|
|
||||||
self.assertEquals(res_dict, expected)
|
self.assertEquals(res_dict, expected)
|
||||||
|
|
||||||
def test_get_security_group_by_invalid_id(self):
|
def test_get_security_group_by_invalid_id(self):
|
||||||
req = webob.Request.blank('/v1.1/os-security-groups/invalid')
|
req = webob.Request.blank('/v1.1/123/os-security-groups/invalid')
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
response = req.get_response(fakes.wsgi_app())
|
response = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEquals(response.status_int, 400)
|
self.assertEquals(response.status_int, 400)
|
||||||
|
|
||||||
def test_get_security_group_by_non_existing_id(self):
|
def test_get_security_group_by_non_existing_id(self):
|
||||||
req = webob.Request.blank('/v1.1/os-security-groups/111111111')
|
req = webob.Request.blank('/v1.1/123/os-security-groups/111111111')
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
response = req.get_response(fakes.wsgi_app())
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
@ -325,6 +349,252 @@ class TestSecurityGroups(test.TestCase):
|
||||||
response = self._delete_security_group(11111111)
|
response = self._delete_security_group(11111111)
|
||||||
self.assertEquals(response.status_int, 404)
|
self.assertEquals(response.status_int, 404)
|
||||||
|
|
||||||
|
def test_associate_by_non_existing_security_group_name(self):
|
||||||
|
body = dict(addSecurityGroup=dict(name='non-existing'))
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 404)
|
||||||
|
|
||||||
|
def test_associate_by_invalid_server_id(self):
|
||||||
|
body = dict(addSecurityGroup=dict(name='test'))
|
||||||
|
self.stubs.Set(nova.db, 'security_group_get_by_name',
|
||||||
|
return_security_group)
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/invalid/action')
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 400)
|
||||||
|
|
||||||
|
def test_associate_without_body(self):
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
body = dict(addSecurityGroup=None)
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_server)
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 400)
|
||||||
|
|
||||||
|
def test_associate_no_security_group_name(self):
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
body = dict(addSecurityGroup=dict())
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_server)
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 400)
|
||||||
|
|
||||||
|
def test_associate_security_group_name_with_whitespaces(self):
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
body = dict(addSecurityGroup=dict(name=" "))
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_server)
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 400)
|
||||||
|
|
||||||
|
def test_associate_non_existing_instance(self):
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_server_nonexistant)
|
||||||
|
body = dict(addSecurityGroup=dict(name="test"))
|
||||||
|
self.stubs.Set(nova.db, 'security_group_get_by_name',
|
||||||
|
return_security_group)
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/10000/action')
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 404)
|
||||||
|
|
||||||
|
def test_associate_non_running_instance(self):
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_non_running_server)
|
||||||
|
self.stubs.Set(nova.db, 'security_group_get_by_name',
|
||||||
|
return_security_group_without_instances)
|
||||||
|
body = dict(addSecurityGroup=dict(name="test"))
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 400)
|
||||||
|
|
||||||
|
def test_associate_already_associated_security_group_to_instance(self):
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_server)
|
||||||
|
self.stubs.Set(nova.db, 'security_group_get_by_name',
|
||||||
|
return_security_group)
|
||||||
|
body = dict(addSecurityGroup=dict(name="test"))
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 400)
|
||||||
|
|
||||||
|
def test_associate(self):
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_server)
|
||||||
|
self.mox.StubOutWithMock(nova.db, 'instance_add_security_group')
|
||||||
|
nova.db.instance_add_security_group(mox.IgnoreArg(),
|
||||||
|
mox.IgnoreArg(),
|
||||||
|
mox.IgnoreArg())
|
||||||
|
self.stubs.Set(nova.db, 'security_group_get_by_name',
|
||||||
|
return_security_group_without_instances)
|
||||||
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
|
body = dict(addSecurityGroup=dict(name="test"))
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 202)
|
||||||
|
|
||||||
|
def test_associate_xml(self):
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_server)
|
||||||
|
self.mox.StubOutWithMock(nova.db, 'instance_add_security_group')
|
||||||
|
nova.db.instance_add_security_group(mox.IgnoreArg(),
|
||||||
|
mox.IgnoreArg(),
|
||||||
|
mox.IgnoreArg())
|
||||||
|
self.stubs.Set(nova.db, 'security_group_get_by_name',
|
||||||
|
return_security_group_without_instances)
|
||||||
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
req.headers['Content-Type'] = 'application/xml'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = """<addSecurityGroup>
|
||||||
|
<name>test</name>
|
||||||
|
</addSecurityGroup>"""
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 202)
|
||||||
|
|
||||||
|
def test_disassociate_by_non_existing_security_group_name(self):
|
||||||
|
body = dict(removeSecurityGroup=dict(name='non-existing'))
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 404)
|
||||||
|
|
||||||
|
def test_disassociate_by_invalid_server_id(self):
|
||||||
|
body = dict(removeSecurityGroup=dict(name='test'))
|
||||||
|
self.stubs.Set(nova.db, 'security_group_get_by_name',
|
||||||
|
return_security_group)
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/invalid/action')
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 400)
|
||||||
|
|
||||||
|
def test_disassociate_without_body(self):
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
body = dict(removeSecurityGroup=None)
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_server)
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 400)
|
||||||
|
|
||||||
|
def test_disassociate_no_security_group_name(self):
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
body = dict(removeSecurityGroup=dict())
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_server)
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 400)
|
||||||
|
|
||||||
|
def test_disassociate_security_group_name_with_whitespaces(self):
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
body = dict(removeSecurityGroup=dict(name=" "))
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_server)
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 400)
|
||||||
|
|
||||||
|
def test_disassociate_non_existing_instance(self):
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_server_nonexistant)
|
||||||
|
body = dict(removeSecurityGroup=dict(name="test"))
|
||||||
|
self.stubs.Set(nova.db, 'security_group_get_by_name',
|
||||||
|
return_security_group)
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/10000/action')
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 404)
|
||||||
|
|
||||||
|
def test_disassociate_non_running_instance(self):
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_non_running_server)
|
||||||
|
self.stubs.Set(nova.db, 'security_group_get_by_name',
|
||||||
|
return_security_group)
|
||||||
|
body = dict(removeSecurityGroup=dict(name="test"))
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 400)
|
||||||
|
|
||||||
|
def test_disassociate_already_associated_security_group_to_instance(self):
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_server)
|
||||||
|
self.stubs.Set(nova.db, 'security_group_get_by_name',
|
||||||
|
return_security_group_without_instances)
|
||||||
|
body = dict(removeSecurityGroup=dict(name="test"))
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 400)
|
||||||
|
|
||||||
|
def test_disassociate(self):
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_server)
|
||||||
|
self.mox.StubOutWithMock(nova.db, 'instance_remove_security_group')
|
||||||
|
nova.db.instance_remove_security_group(mox.IgnoreArg(),
|
||||||
|
mox.IgnoreArg(),
|
||||||
|
mox.IgnoreArg())
|
||||||
|
self.stubs.Set(nova.db, 'security_group_get_by_name',
|
||||||
|
return_security_group)
|
||||||
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
|
body = dict(removeSecurityGroup=dict(name="test"))
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = json.dumps(body)
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 202)
|
||||||
|
|
||||||
|
def test_disassociate_xml(self):
|
||||||
|
self.stubs.Set(nova.db, 'instance_get', return_server)
|
||||||
|
self.mox.StubOutWithMock(nova.db, 'instance_remove_security_group')
|
||||||
|
nova.db.instance_remove_security_group(mox.IgnoreArg(),
|
||||||
|
mox.IgnoreArg(),
|
||||||
|
mox.IgnoreArg())
|
||||||
|
self.stubs.Set(nova.db, 'security_group_get_by_name',
|
||||||
|
return_security_group)
|
||||||
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
|
req = webob.Request.blank('/v1.1/123/servers/1/action')
|
||||||
|
req.headers['Content-Type'] = 'application/xml'
|
||||||
|
req.method = 'POST'
|
||||||
|
req.body = """<removeSecurityGroup>
|
||||||
|
<name>test</name>
|
||||||
|
</removeSecurityGroup>"""
|
||||||
|
response = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEquals(response.status_int, 202)
|
||||||
|
|
||||||
|
|
||||||
class TestSecurityGroupRules(test.TestCase):
|
class TestSecurityGroupRules(test.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -354,7 +624,7 @@ class TestSecurityGroupRules(test.TestCase):
|
||||||
super(TestSecurityGroupRules, self).tearDown()
|
super(TestSecurityGroupRules, self).tearDown()
|
||||||
|
|
||||||
def _create_security_group_rule_json(self, rules):
|
def _create_security_group_rule_json(self, rules):
|
||||||
request = webob.Request.blank('/v1.1/os-security-group-rules')
|
request = webob.Request.blank('/v1.1/123/os-security-group-rules')
|
||||||
request.headers['Content-Type'] = 'application/json'
|
request.headers['Content-Type'] = 'application/json'
|
||||||
request.method = 'POST'
|
request.method = 'POST'
|
||||||
request.body = json.dumps(rules)
|
request.body = json.dumps(rules)
|
||||||
|
@ -362,7 +632,7 @@ class TestSecurityGroupRules(test.TestCase):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def _delete_security_group_rule(self, id):
|
def _delete_security_group_rule(self, id):
|
||||||
request = webob.Request.blank('/v1.1/os-security-group-rules/%s'
|
request = webob.Request.blank('/v1.1/123/os-security-group-rules/%s'
|
||||||
% id)
|
% id)
|
||||||
request.method = 'DELETE'
|
request.method = 'DELETE'
|
||||||
response = request.get_response(fakes.wsgi_app())
|
response = request.get_response(fakes.wsgi_app())
|
||||||
|
@ -420,7 +690,7 @@ class TestSecurityGroupRules(test.TestCase):
|
||||||
self.assertEquals(response.status_int, 400)
|
self.assertEquals(response.status_int, 400)
|
||||||
|
|
||||||
def test_create_with_no_body_json(self):
|
def test_create_with_no_body_json(self):
|
||||||
request = webob.Request.blank('/v1.1/os-security-group-rules')
|
request = webob.Request.blank('/v1.1/123/os-security-group-rules')
|
||||||
request.headers['Content-Type'] = 'application/json'
|
request.headers['Content-Type'] = 'application/json'
|
||||||
request.method = 'POST'
|
request.method = 'POST'
|
||||||
request.body = json.dumps(None)
|
request.body = json.dumps(None)
|
||||||
|
@ -428,7 +698,7 @@ class TestSecurityGroupRules(test.TestCase):
|
||||||
self.assertEquals(response.status_int, 422)
|
self.assertEquals(response.status_int, 422)
|
||||||
|
|
||||||
def test_create_with_no_security_group_rule_in_body_json(self):
|
def test_create_with_no_security_group_rule_in_body_json(self):
|
||||||
request = webob.Request.blank('/v1.1/os-security-group-rules')
|
request = webob.Request.blank('/v1.1/123/os-security-group-rules')
|
||||||
request.headers['Content-Type'] = 'application/json'
|
request.headers['Content-Type'] = 'application/json'
|
||||||
request.method = 'POST'
|
request.method = 'POST'
|
||||||
body_dict = {'test': "test"}
|
body_dict = {'test': "test"}
|
||||||
|
|
|
@ -43,7 +43,7 @@ class ServerVirtualInterfaceTest(test.TestCase):
|
||||||
super(ServerVirtualInterfaceTest, self).tearDown()
|
super(ServerVirtualInterfaceTest, self).tearDown()
|
||||||
|
|
||||||
def test_get_virtual_interfaces_list(self):
|
def test_get_virtual_interfaces_list(self):
|
||||||
req = webob.Request.blank('/v1.1/servers/1/os-virtual-interfaces')
|
req = webob.Request.blank('/v1.1/123/servers/1/os-virtual-interfaces')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
res_dict = json.loads(res.body)
|
res_dict = json.loads(res.body)
|
||||||
|
|
|
@ -72,8 +72,9 @@ class Foxinsocks(object):
|
||||||
res.body = json.dumps(data)
|
res.body = json.dumps(data)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
req_ext1 = extensions.RequestExtension('GET', '/v1.1/flavors/:(id)',
|
req_ext1 = extensions.RequestExtension('GET',
|
||||||
_goose_handler)
|
'/v1.1/:(project_id)/flavors/:(id)',
|
||||||
|
_goose_handler)
|
||||||
request_exts.append(req_ext1)
|
request_exts.append(req_ext1)
|
||||||
|
|
||||||
def _bands_handler(req, res):
|
def _bands_handler(req, res):
|
||||||
|
@ -84,8 +85,9 @@ class Foxinsocks(object):
|
||||||
res.body = json.dumps(data)
|
res.body = json.dumps(data)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
req_ext2 = extensions.RequestExtension('GET', '/v1.1/flavors/:(id)',
|
req_ext2 = extensions.RequestExtension('GET',
|
||||||
_bands_handler)
|
'/v1.1/:(project_id)/flavors/:(id)',
|
||||||
|
_bands_handler)
|
||||||
request_exts.append(req_ext2)
|
request_exts.append(req_ext2)
|
||||||
return request_exts
|
return request_exts
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ class Test(test.TestCase):
|
||||||
req = webob.Request.blank('/v1.0/')
|
req = webob.Request.blank('/v1.0/')
|
||||||
req.headers['X-Auth-User'] = 'user1'
|
req.headers['X-Auth-User'] = 'user1'
|
||||||
req.headers['X-Auth-Key'] = 'user1_key'
|
req.headers['X-Auth-Key'] = 'user1_key'
|
||||||
|
req.headers['X-Auth-Project-Id'] = 'user1_project'
|
||||||
result = req.get_response(fakes.wsgi_app(fake_auth=False))
|
result = req.get_response(fakes.wsgi_app(fake_auth=False))
|
||||||
self.assertEqual(result.status, '204 No Content')
|
self.assertEqual(result.status, '204 No Content')
|
||||||
self.assertEqual(len(result.headers['X-Auth-Token']), 40)
|
self.assertEqual(len(result.headers['X-Auth-Token']), 40)
|
||||||
|
@ -73,14 +74,14 @@ class Test(test.TestCase):
|
||||||
self.assertEqual(result.status, '204 No Content')
|
self.assertEqual(result.status, '204 No Content')
|
||||||
self.assertEqual(len(result.headers['X-Auth-Token']), 40)
|
self.assertEqual(len(result.headers['X-Auth-Token']), 40)
|
||||||
self.assertEqual(result.headers['X-Server-Management-Url'],
|
self.assertEqual(result.headers['X-Server-Management-Url'],
|
||||||
"http://foo/v1.0/")
|
"http://foo/v1.0")
|
||||||
self.assertEqual(result.headers['X-CDN-Management-Url'],
|
self.assertEqual(result.headers['X-CDN-Management-Url'],
|
||||||
"")
|
"")
|
||||||
self.assertEqual(result.headers['X-Storage-Url'], "")
|
self.assertEqual(result.headers['X-Storage-Url'], "")
|
||||||
|
|
||||||
token = result.headers['X-Auth-Token']
|
token = result.headers['X-Auth-Token']
|
||||||
self.stubs.Set(nova.api.openstack, 'APIRouterV10', fakes.FakeRouter)
|
self.stubs.Set(nova.api.openstack, 'APIRouterV10', fakes.FakeRouter)
|
||||||
req = webob.Request.blank('/v1.0/fake')
|
req = webob.Request.blank('/v1.0/user1_project')
|
||||||
req.headers['X-Auth-Token'] = token
|
req.headers['X-Auth-Token'] = token
|
||||||
result = req.get_response(fakes.wsgi_app(fake_auth=False))
|
result = req.get_response(fakes.wsgi_app(fake_auth=False))
|
||||||
self.assertEqual(result.status, '200 OK')
|
self.assertEqual(result.status, '200 OK')
|
||||||
|
@ -125,7 +126,7 @@ class Test(test.TestCase):
|
||||||
|
|
||||||
token = result.headers['X-Auth-Token']
|
token = result.headers['X-Auth-Token']
|
||||||
self.stubs.Set(nova.api.openstack, 'APIRouterV10', fakes.FakeRouter)
|
self.stubs.Set(nova.api.openstack, 'APIRouterV10', fakes.FakeRouter)
|
||||||
req = webob.Request.blank('/v1.0/fake')
|
req = webob.Request.blank('/v1.0/')
|
||||||
req.headers['X-Auth-Token'] = token
|
req.headers['X-Auth-Token'] = token
|
||||||
req.headers['X-Auth-Project-Id'] = 'user2_project'
|
req.headers['X-Auth-Project-Id'] = 'user2_project'
|
||||||
result = req.get_response(fakes.wsgi_app(fake_auth=False))
|
result = req.get_response(fakes.wsgi_app(fake_auth=False))
|
||||||
|
@ -136,6 +137,7 @@ class Test(test.TestCase):
|
||||||
req = webob.Request.blank('/v1.0/')
|
req = webob.Request.blank('/v1.0/')
|
||||||
req.headers['X-Auth-User'] = 'unknown_user'
|
req.headers['X-Auth-User'] = 'unknown_user'
|
||||||
req.headers['X-Auth-Key'] = 'unknown_user_key'
|
req.headers['X-Auth-Key'] = 'unknown_user_key'
|
||||||
|
req.headers['X-Auth-Project-Id'] = 'user_project'
|
||||||
result = req.get_response(fakes.wsgi_app(fake_auth=False))
|
result = req.get_response(fakes.wsgi_app(fake_auth=False))
|
||||||
self.assertEqual(result.status, '401 Unauthorized')
|
self.assertEqual(result.status, '401 Unauthorized')
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ class ExtensionControllerTest(test.TestCase):
|
||||||
def test_list_extensions_json(self):
|
def test_list_extensions_json(self):
|
||||||
app = openstack.APIRouterV11()
|
app = openstack.APIRouterV11()
|
||||||
ext_midware = extensions.ExtensionMiddleware(app)
|
ext_midware = extensions.ExtensionMiddleware(app)
|
||||||
request = webob.Request.blank("/extensions")
|
request = webob.Request.blank("/123/extensions")
|
||||||
response = request.get_response(ext_midware)
|
response = request.get_response(ext_midware)
|
||||||
self.assertEqual(200, response.status_int)
|
self.assertEqual(200, response.status_int)
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ class ExtensionControllerTest(test.TestCase):
|
||||||
def test_get_extension_json(self):
|
def test_get_extension_json(self):
|
||||||
app = openstack.APIRouterV11()
|
app = openstack.APIRouterV11()
|
||||||
ext_midware = extensions.ExtensionMiddleware(app)
|
ext_midware = extensions.ExtensionMiddleware(app)
|
||||||
request = webob.Request.blank("/extensions/FOXNSOX")
|
request = webob.Request.blank("/123/extensions/FOXNSOX")
|
||||||
response = request.get_response(ext_midware)
|
response = request.get_response(ext_midware)
|
||||||
self.assertEqual(200, response.status_int)
|
self.assertEqual(200, response.status_int)
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ class ExtensionControllerTest(test.TestCase):
|
||||||
def test_list_extensions_xml(self):
|
def test_list_extensions_xml(self):
|
||||||
app = openstack.APIRouterV11()
|
app = openstack.APIRouterV11()
|
||||||
ext_midware = extensions.ExtensionMiddleware(app)
|
ext_midware = extensions.ExtensionMiddleware(app)
|
||||||
request = webob.Request.blank("/extensions")
|
request = webob.Request.blank("/123/extensions")
|
||||||
request.accept = "application/xml"
|
request.accept = "application/xml"
|
||||||
response = request.get_response(ext_midware)
|
response = request.get_response(ext_midware)
|
||||||
self.assertEqual(200, response.status_int)
|
self.assertEqual(200, response.status_int)
|
||||||
|
@ -172,7 +172,7 @@ class ExtensionControllerTest(test.TestCase):
|
||||||
def test_get_extension_xml(self):
|
def test_get_extension_xml(self):
|
||||||
app = openstack.APIRouterV11()
|
app = openstack.APIRouterV11()
|
||||||
ext_midware = extensions.ExtensionMiddleware(app)
|
ext_midware = extensions.ExtensionMiddleware(app)
|
||||||
request = webob.Request.blank("/extensions/FOXNSOX")
|
request = webob.Request.blank("/123/extensions/FOXNSOX")
|
||||||
request.accept = "application/xml"
|
request.accept = "application/xml"
|
||||||
response = request.get_response(ext_midware)
|
response = request.get_response(ext_midware)
|
||||||
self.assertEqual(200, response.status_int)
|
self.assertEqual(200, response.status_int)
|
||||||
|
@ -213,7 +213,7 @@ class ResourceExtensionTest(test.TestCase):
|
||||||
manager = StubExtensionManager(res_ext)
|
manager = StubExtensionManager(res_ext)
|
||||||
app = openstack.APIRouterV11()
|
app = openstack.APIRouterV11()
|
||||||
ext_midware = extensions.ExtensionMiddleware(app, manager)
|
ext_midware = extensions.ExtensionMiddleware(app, manager)
|
||||||
request = webob.Request.blank("/tweedles")
|
request = webob.Request.blank("/123/tweedles")
|
||||||
response = request.get_response(ext_midware)
|
response = request.get_response(ext_midware)
|
||||||
self.assertEqual(200, response.status_int)
|
self.assertEqual(200, response.status_int)
|
||||||
self.assertEqual(response_body, response.body)
|
self.assertEqual(response_body, response.body)
|
||||||
|
@ -224,7 +224,7 @@ class ResourceExtensionTest(test.TestCase):
|
||||||
manager = StubExtensionManager(res_ext)
|
manager = StubExtensionManager(res_ext)
|
||||||
app = openstack.APIRouterV11()
|
app = openstack.APIRouterV11()
|
||||||
ext_midware = extensions.ExtensionMiddleware(app, manager)
|
ext_midware = extensions.ExtensionMiddleware(app, manager)
|
||||||
request = webob.Request.blank("/tweedles")
|
request = webob.Request.blank("/123/tweedles")
|
||||||
response = request.get_response(ext_midware)
|
response = request.get_response(ext_midware)
|
||||||
self.assertEqual(200, response.status_int)
|
self.assertEqual(200, response.status_int)
|
||||||
self.assertEqual(response_body, response.body)
|
self.assertEqual(response_body, response.body)
|
||||||
|
@ -248,7 +248,7 @@ class ExtensionManagerTest(test.TestCase):
|
||||||
def test_get_resources(self):
|
def test_get_resources(self):
|
||||||
app = openstack.APIRouterV11()
|
app = openstack.APIRouterV11()
|
||||||
ext_midware = extensions.ExtensionMiddleware(app)
|
ext_midware = extensions.ExtensionMiddleware(app)
|
||||||
request = webob.Request.blank("/foxnsocks")
|
request = webob.Request.blank("/123/foxnsocks")
|
||||||
response = request.get_response(ext_midware)
|
response = request.get_response(ext_midware)
|
||||||
self.assertEqual(200, response.status_int)
|
self.assertEqual(200, response.status_int)
|
||||||
self.assertEqual(response_body, response.body)
|
self.assertEqual(response_body, response.body)
|
||||||
|
@ -281,23 +281,26 @@ class ActionExtensionTest(test.TestCase):
|
||||||
|
|
||||||
def test_extended_action(self):
|
def test_extended_action(self):
|
||||||
body = dict(add_tweedle=dict(name="test"))
|
body = dict(add_tweedle=dict(name="test"))
|
||||||
response = self._send_server_action_request("/servers/1/action", body)
|
url = "/123/servers/1/action"
|
||||||
|
response = self._send_server_action_request(url, body)
|
||||||
self.assertEqual(200, response.status_int)
|
self.assertEqual(200, response.status_int)
|
||||||
self.assertEqual("Tweedle Beetle Added.", response.body)
|
self.assertEqual("Tweedle Beetle Added.", response.body)
|
||||||
|
|
||||||
body = dict(delete_tweedle=dict(name="test"))
|
body = dict(delete_tweedle=dict(name="test"))
|
||||||
response = self._send_server_action_request("/servers/1/action", body)
|
response = self._send_server_action_request(url, body)
|
||||||
self.assertEqual(200, response.status_int)
|
self.assertEqual(200, response.status_int)
|
||||||
self.assertEqual("Tweedle Beetle Deleted.", response.body)
|
self.assertEqual("Tweedle Beetle Deleted.", response.body)
|
||||||
|
|
||||||
def test_invalid_action_body(self):
|
def test_invalid_action_body(self):
|
||||||
body = dict(blah=dict(name="test")) # Doesn't exist
|
body = dict(blah=dict(name="test")) # Doesn't exist
|
||||||
response = self._send_server_action_request("/servers/1/action", body)
|
url = "/123/servers/1/action"
|
||||||
|
response = self._send_server_action_request(url, body)
|
||||||
self.assertEqual(400, response.status_int)
|
self.assertEqual(400, response.status_int)
|
||||||
|
|
||||||
def test_invalid_action(self):
|
def test_invalid_action(self):
|
||||||
body = dict(blah=dict(name="test"))
|
body = dict(blah=dict(name="test"))
|
||||||
response = self._send_server_action_request("/fdsa/1/action", body)
|
url = "/123/fdsa/1/action"
|
||||||
|
response = self._send_server_action_request(url, body)
|
||||||
self.assertEqual(404, response.status_int)
|
self.assertEqual(404, response.status_int)
|
||||||
|
|
||||||
|
|
||||||
|
@ -318,13 +321,13 @@ class RequestExtensionTest(test.TestCase):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
req_ext = extensions.RequestExtension('GET',
|
req_ext = extensions.RequestExtension('GET',
|
||||||
'/v1.1/flavors/:(id)',
|
'/v1.1/123/flavors/:(id)',
|
||||||
_req_handler)
|
_req_handler)
|
||||||
|
|
||||||
manager = StubExtensionManager(None, None, req_ext)
|
manager = StubExtensionManager(None, None, req_ext)
|
||||||
app = fakes.wsgi_app()
|
app = fakes.wsgi_app()
|
||||||
ext_midware = extensions.ExtensionMiddleware(app, manager)
|
ext_midware = extensions.ExtensionMiddleware(app, manager)
|
||||||
request = webob.Request.blank("/v1.1/flavors/1?chewing=bluegoo")
|
request = webob.Request.blank("/v1.1/123/flavors/1?chewing=bluegoo")
|
||||||
request.environ['api.version'] = '1.1'
|
request.environ['api.version'] = '1.1'
|
||||||
response = request.get_response(ext_midware)
|
response = request.get_response(ext_midware)
|
||||||
self.assertEqual(200, response.status_int)
|
self.assertEqual(200, response.status_int)
|
||||||
|
@ -335,7 +338,7 @@ class RequestExtensionTest(test.TestCase):
|
||||||
|
|
||||||
app = fakes.wsgi_app()
|
app = fakes.wsgi_app()
|
||||||
ext_midware = extensions.ExtensionMiddleware(app)
|
ext_midware = extensions.ExtensionMiddleware(app)
|
||||||
request = webob.Request.blank("/v1.1/flavors/1?chewing=newblue")
|
request = webob.Request.blank("/v1.1/123/flavors/1?chewing=newblue")
|
||||||
request.environ['api.version'] = '1.1'
|
request.environ['api.version'] = '1.1'
|
||||||
response = request.get_response(ext_midware)
|
response = request.get_response(ext_midware)
|
||||||
self.assertEqual(200, response.status_int)
|
self.assertEqual(200, response.status_int)
|
||||||
|
|
|
@ -138,7 +138,7 @@ class FlavorsTest(test.TestCase):
|
||||||
self.assertEqual(res.status_int, 404)
|
self.assertEqual(res.status_int, 404)
|
||||||
|
|
||||||
def test_get_flavor_by_id_v1_1(self):
|
def test_get_flavor_by_id_v1_1(self):
|
||||||
req = webob.Request.blank('/v1.1/flavors/12')
|
req = webob.Request.blank('/v1.1/fake/flavors/12')
|
||||||
req.environ['api.version'] = '1.1'
|
req.environ['api.version'] = '1.1'
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
|
@ -152,11 +152,11 @@ class FlavorsTest(test.TestCase):
|
||||||
"links": [
|
"links": [
|
||||||
{
|
{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/flavors/12",
|
"href": "http://localhost/v1.1/fake/flavors/12",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/flavors/12",
|
"href": "http://localhost/fake/flavors/12",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -164,7 +164,7 @@ class FlavorsTest(test.TestCase):
|
||||||
self.assertEqual(flavor, expected)
|
self.assertEqual(flavor, expected)
|
||||||
|
|
||||||
def test_get_flavor_list_v1_1(self):
|
def test_get_flavor_list_v1_1(self):
|
||||||
req = webob.Request.blank('/v1.1/flavors')
|
req = webob.Request.blank('/v1.1/fake/flavors')
|
||||||
req.environ['api.version'] = '1.1'
|
req.environ['api.version'] = '1.1'
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
|
@ -177,11 +177,11 @@ class FlavorsTest(test.TestCase):
|
||||||
"links": [
|
"links": [
|
||||||
{
|
{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/flavors/1",
|
"href": "http://localhost/v1.1/fake/flavors/1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/flavors/1",
|
"href": "http://localhost/fake/flavors/1",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -191,11 +191,11 @@ class FlavorsTest(test.TestCase):
|
||||||
"links": [
|
"links": [
|
||||||
{
|
{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/flavors/2",
|
"href": "http://localhost/v1.1/fake/flavors/2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/flavors/2",
|
"href": "http://localhost/fake/flavors/2",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -204,7 +204,7 @@ class FlavorsTest(test.TestCase):
|
||||||
self.assertEqual(flavor, expected)
|
self.assertEqual(flavor, expected)
|
||||||
|
|
||||||
def test_get_flavor_list_detail_v1_1(self):
|
def test_get_flavor_list_detail_v1_1(self):
|
||||||
req = webob.Request.blank('/v1.1/flavors/detail')
|
req = webob.Request.blank('/v1.1/fake/flavors/detail')
|
||||||
req.environ['api.version'] = '1.1'
|
req.environ['api.version'] = '1.1'
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
|
@ -219,11 +219,11 @@ class FlavorsTest(test.TestCase):
|
||||||
"links": [
|
"links": [
|
||||||
{
|
{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/flavors/1",
|
"href": "http://localhost/v1.1/fake/flavors/1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/flavors/1",
|
"href": "http://localhost/fake/flavors/1",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -235,11 +235,11 @@ class FlavorsTest(test.TestCase):
|
||||||
"links": [
|
"links": [
|
||||||
{
|
{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/flavors/2",
|
"href": "http://localhost/v1.1/fake/flavors/2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/flavors/2",
|
"href": "http://localhost/fake/flavors/2",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -252,7 +252,7 @@ class FlavorsTest(test.TestCase):
|
||||||
return {}
|
return {}
|
||||||
self.stubs.Set(nova.db.api, "instance_type_get_all", _return_empty)
|
self.stubs.Set(nova.db.api, "instance_type_get_all", _return_empty)
|
||||||
|
|
||||||
req = webob.Request.blank('/v1.1/flavors')
|
req = webob.Request.blank('/v1.1/fake/flavors')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
flavors = json.loads(res.body)["flavors"]
|
flavors = json.loads(res.body)["flavors"]
|
||||||
|
@ -274,11 +274,11 @@ class FlavorsXMLSerializationTest(test.TestCase):
|
||||||
"links": [
|
"links": [
|
||||||
{
|
{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/flavors/12",
|
"href": "http://localhost/v1.1/fake/flavors/12",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/flavors/12",
|
"href": "http://localhost/fake/flavors/12",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -294,8 +294,10 @@ class FlavorsXMLSerializationTest(test.TestCase):
|
||||||
name="asdf"
|
name="asdf"
|
||||||
ram="256"
|
ram="256"
|
||||||
disk="10">
|
disk="10">
|
||||||
<atom:link href="http://localhost/v1.1/flavors/12" rel="self"/>
|
<atom:link href="http://localhost/v1.1/fake/flavors/12"
|
||||||
<atom:link href="http://localhost/flavors/12" rel="bookmark"/>
|
rel="self"/>
|
||||||
|
<atom:link href="http://localhost/fake/flavors/12"
|
||||||
|
rel="bookmark"/>
|
||||||
</flavor>
|
</flavor>
|
||||||
""".replace(" ", ""))
|
""".replace(" ", ""))
|
||||||
|
|
||||||
|
@ -313,11 +315,11 @@ class FlavorsXMLSerializationTest(test.TestCase):
|
||||||
"links": [
|
"links": [
|
||||||
{
|
{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/flavors/12",
|
"href": "http://localhost/v1.1/fake/flavors/12",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/flavors/12",
|
"href": "http://localhost/fake/flavors/12",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -333,8 +335,10 @@ class FlavorsXMLSerializationTest(test.TestCase):
|
||||||
name="asdf"
|
name="asdf"
|
||||||
ram="256"
|
ram="256"
|
||||||
disk="10">
|
disk="10">
|
||||||
<atom:link href="http://localhost/v1.1/flavors/12" rel="self"/>
|
<atom:link href="http://localhost/v1.1/fake/flavors/12"
|
||||||
<atom:link href="http://localhost/flavors/12" rel="bookmark"/>
|
rel="self"/>
|
||||||
|
<atom:link href="http://localhost/fake/flavors/12"
|
||||||
|
rel="bookmark"/>
|
||||||
</flavor>
|
</flavor>
|
||||||
""".replace(" ", ""))
|
""".replace(" ", ""))
|
||||||
|
|
||||||
|
@ -353,11 +357,11 @@ class FlavorsXMLSerializationTest(test.TestCase):
|
||||||
"links": [
|
"links": [
|
||||||
{
|
{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/flavors/23",
|
"href": "http://localhost/v1.1/fake/flavors/23",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/flavors/23",
|
"href": "http://localhost/fake/flavors/23",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}, {
|
}, {
|
||||||
|
@ -368,11 +372,11 @@ class FlavorsXMLSerializationTest(test.TestCase):
|
||||||
"links": [
|
"links": [
|
||||||
{
|
{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/flavors/13",
|
"href": "http://localhost/v1.1/fake/flavors/13",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/flavors/13",
|
"href": "http://localhost/fake/flavors/13",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -389,15 +393,19 @@ class FlavorsXMLSerializationTest(test.TestCase):
|
||||||
name="flavor 23"
|
name="flavor 23"
|
||||||
ram="512"
|
ram="512"
|
||||||
disk="20">
|
disk="20">
|
||||||
<atom:link href="http://localhost/v1.1/flavors/23" rel="self"/>
|
<atom:link href="http://localhost/v1.1/fake/flavors/23"
|
||||||
<atom:link href="http://localhost/flavors/23" rel="bookmark"/>
|
rel="self"/>
|
||||||
|
<atom:link href="http://localhost/fake/flavors/23"
|
||||||
|
rel="bookmark"/>
|
||||||
</flavor>
|
</flavor>
|
||||||
<flavor id="13"
|
<flavor id="13"
|
||||||
name="flavor 13"
|
name="flavor 13"
|
||||||
ram="256"
|
ram="256"
|
||||||
disk="10">
|
disk="10">
|
||||||
<atom:link href="http://localhost/v1.1/flavors/13" rel="self"/>
|
<atom:link href="http://localhost/v1.1/fake/flavors/13"
|
||||||
<atom:link href="http://localhost/flavors/13" rel="bookmark"/>
|
rel="self"/>
|
||||||
|
<atom:link href="http://localhost/fake/flavors/13"
|
||||||
|
rel="bookmark"/>
|
||||||
</flavor>
|
</flavor>
|
||||||
</flavors>
|
</flavors>
|
||||||
""".replace(" ", "") % locals())
|
""".replace(" ", "") % locals())
|
||||||
|
@ -417,11 +425,11 @@ class FlavorsXMLSerializationTest(test.TestCase):
|
||||||
"links": [
|
"links": [
|
||||||
{
|
{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/flavors/23",
|
"href": "http://localhost/v1.1/fake/flavors/23",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/flavors/23",
|
"href": "http://localhost/fake/flavors/23",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}, {
|
}, {
|
||||||
|
@ -432,11 +440,11 @@ class FlavorsXMLSerializationTest(test.TestCase):
|
||||||
"links": [
|
"links": [
|
||||||
{
|
{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/flavors/13",
|
"href": "http://localhost/v1.1/fake/flavors/13",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/flavors/13",
|
"href": "http://localhost/fake/flavors/13",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -450,12 +458,16 @@ class FlavorsXMLSerializationTest(test.TestCase):
|
||||||
<flavors xmlns="http://docs.openstack.org/compute/api/v1.1"
|
<flavors xmlns="http://docs.openstack.org/compute/api/v1.1"
|
||||||
xmlns:atom="http://www.w3.org/2005/Atom">
|
xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
<flavor id="23" name="flavor 23">
|
<flavor id="23" name="flavor 23">
|
||||||
<atom:link href="http://localhost/v1.1/flavors/23" rel="self"/>
|
<atom:link href="http://localhost/v1.1/fake/flavors/23"
|
||||||
<atom:link href="http://localhost/flavors/23" rel="bookmark"/>
|
rel="self"/>
|
||||||
|
<atom:link href="http://localhost/fake/flavors/23"
|
||||||
|
rel="bookmark"/>
|
||||||
</flavor>
|
</flavor>
|
||||||
<flavor id="13" name="flavor 13">
|
<flavor id="13" name="flavor 13">
|
||||||
<atom:link href="http://localhost/v1.1/flavors/13" rel="self"/>
|
<atom:link href="http://localhost/v1.1/fake/flavors/13"
|
||||||
<atom:link href="http://localhost/flavors/13" rel="bookmark"/>
|
rel="self"/>
|
||||||
|
<atom:link href="http://localhost/fake/flavors/13"
|
||||||
|
rel="bookmark"/>
|
||||||
</flavor>
|
</flavor>
|
||||||
</flavors>
|
</flavors>
|
||||||
""".replace(" ", "") % locals())
|
""".replace(" ", "") % locals())
|
||||||
|
|
|
@ -63,7 +63,7 @@ class FlavorsExtraSpecsTest(test.TestCase):
|
||||||
def test_index(self):
|
def test_index(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_type_extra_specs_get',
|
self.stubs.Set(nova.db.api, 'instance_type_extra_specs_get',
|
||||||
return_flavor_extra_specs)
|
return_flavor_extra_specs)
|
||||||
request = webob.Request.blank('/v1.1/flavors/1/os-extra_specs')
|
request = webob.Request.blank('/v1.1/123/flavors/1/os-extra_specs')
|
||||||
res = request.get_response(fakes.wsgi_app())
|
res = request.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(200, res.status_int)
|
self.assertEqual(200, res.status_int)
|
||||||
res_dict = json.loads(res.body)
|
res_dict = json.loads(res.body)
|
||||||
|
@ -73,7 +73,7 @@ class FlavorsExtraSpecsTest(test.TestCase):
|
||||||
def test_index_no_data(self):
|
def test_index_no_data(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_type_extra_specs_get',
|
self.stubs.Set(nova.db.api, 'instance_type_extra_specs_get',
|
||||||
return_empty_flavor_extra_specs)
|
return_empty_flavor_extra_specs)
|
||||||
req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs')
|
req = webob.Request.blank('/v1.1/123/flavors/1/os-extra_specs')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
res_dict = json.loads(res.body)
|
res_dict = json.loads(res.body)
|
||||||
self.assertEqual(200, res.status_int)
|
self.assertEqual(200, res.status_int)
|
||||||
|
@ -83,7 +83,7 @@ class FlavorsExtraSpecsTest(test.TestCase):
|
||||||
def test_show(self):
|
def test_show(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_type_extra_specs_get',
|
self.stubs.Set(nova.db.api, 'instance_type_extra_specs_get',
|
||||||
return_flavor_extra_specs)
|
return_flavor_extra_specs)
|
||||||
req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs/key5')
|
req = webob.Request.blank('/v1.1/123/flavors/1/os-extra_specs/key5')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(200, res.status_int)
|
self.assertEqual(200, res.status_int)
|
||||||
res_dict = json.loads(res.body)
|
res_dict = json.loads(res.body)
|
||||||
|
@ -93,7 +93,7 @@ class FlavorsExtraSpecsTest(test.TestCase):
|
||||||
def test_show_spec_not_found(self):
|
def test_show_spec_not_found(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_type_extra_specs_get',
|
self.stubs.Set(nova.db.api, 'instance_type_extra_specs_get',
|
||||||
return_empty_flavor_extra_specs)
|
return_empty_flavor_extra_specs)
|
||||||
req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs/key6')
|
req = webob.Request.blank('/v1.1/123/flavors/1/os-extra_specs/key6')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
res_dict = json.loads(res.body)
|
res_dict = json.loads(res.body)
|
||||||
self.assertEqual(404, res.status_int)
|
self.assertEqual(404, res.status_int)
|
||||||
|
@ -101,7 +101,7 @@ class FlavorsExtraSpecsTest(test.TestCase):
|
||||||
def test_delete(self):
|
def test_delete(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_type_extra_specs_delete',
|
self.stubs.Set(nova.db.api, 'instance_type_extra_specs_delete',
|
||||||
delete_flavor_extra_specs)
|
delete_flavor_extra_specs)
|
||||||
req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs/key5')
|
req = webob.Request.blank('/v1.1/123/flavors/1/os-extra_specs/key5')
|
||||||
req.method = 'DELETE'
|
req.method = 'DELETE'
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(200, res.status_int)
|
self.assertEqual(200, res.status_int)
|
||||||
|
@ -110,7 +110,7 @@ class FlavorsExtraSpecsTest(test.TestCase):
|
||||||
self.stubs.Set(nova.db.api,
|
self.stubs.Set(nova.db.api,
|
||||||
'instance_type_extra_specs_update_or_create',
|
'instance_type_extra_specs_update_or_create',
|
||||||
return_create_flavor_extra_specs)
|
return_create_flavor_extra_specs)
|
||||||
req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs')
|
req = webob.Request.blank('/v1.1/123/flavors/1/os-extra_specs')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = '{"extra_specs": {"key1": "value1"}}'
|
req.body = '{"extra_specs": {"key1": "value1"}}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -124,7 +124,7 @@ class FlavorsExtraSpecsTest(test.TestCase):
|
||||||
self.stubs.Set(nova.db.api,
|
self.stubs.Set(nova.db.api,
|
||||||
'instance_type_extra_specs_update_or_create',
|
'instance_type_extra_specs_update_or_create',
|
||||||
return_create_flavor_extra_specs)
|
return_create_flavor_extra_specs)
|
||||||
req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs')
|
req = webob.Request.blank('/v1.1/123/flavors/1/os-extra_specs')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
|
@ -134,7 +134,7 @@ class FlavorsExtraSpecsTest(test.TestCase):
|
||||||
self.stubs.Set(nova.db.api,
|
self.stubs.Set(nova.db.api,
|
||||||
'instance_type_extra_specs_update_or_create',
|
'instance_type_extra_specs_update_or_create',
|
||||||
return_create_flavor_extra_specs)
|
return_create_flavor_extra_specs)
|
||||||
req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs/key1')
|
req = webob.Request.blank('/v1.1/123/flavors/1/os-extra_specs/key1')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = '{"key1": "value1"}'
|
req.body = '{"key1": "value1"}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -148,7 +148,7 @@ class FlavorsExtraSpecsTest(test.TestCase):
|
||||||
self.stubs.Set(nova.db.api,
|
self.stubs.Set(nova.db.api,
|
||||||
'instance_type_extra_specs_update_or_create',
|
'instance_type_extra_specs_update_or_create',
|
||||||
return_create_flavor_extra_specs)
|
return_create_flavor_extra_specs)
|
||||||
req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs/key1')
|
req = webob.Request.blank('/v1.1/123/flavors/1/os-extra_specs/key1')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
|
@ -158,7 +158,7 @@ class FlavorsExtraSpecsTest(test.TestCase):
|
||||||
self.stubs.Set(nova.db.api,
|
self.stubs.Set(nova.db.api,
|
||||||
'instance_type_extra_specs_update_or_create',
|
'instance_type_extra_specs_update_or_create',
|
||||||
return_create_flavor_extra_specs)
|
return_create_flavor_extra_specs)
|
||||||
req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs/key1')
|
req = webob.Request.blank('/v1.1/123/flavors/1/os-extra_specs/key1')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = '{"key1": "value1", "key2": "value2"}'
|
req.body = '{"key1": "value1", "key2": "value2"}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -169,7 +169,7 @@ class FlavorsExtraSpecsTest(test.TestCase):
|
||||||
self.stubs.Set(nova.db.api,
|
self.stubs.Set(nova.db.api,
|
||||||
'instance_type_extra_specs_update_or_create',
|
'instance_type_extra_specs_update_or_create',
|
||||||
return_create_flavor_extra_specs)
|
return_create_flavor_extra_specs)
|
||||||
req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs/bad')
|
req = webob.Request.blank('/v1.1/123/flavors/1/os-extra_specs/bad')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = '{"key1": "value1"}'
|
req.body = '{"key1": "value1"}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
|
|
@ -90,7 +90,7 @@ class ImageMetaDataTest(test.TestCase):
|
||||||
fakes.stub_out_glance(self.stubs, self.IMAGE_FIXTURES)
|
fakes.stub_out_glance(self.stubs, self.IMAGE_FIXTURES)
|
||||||
|
|
||||||
def test_index(self):
|
def test_index(self):
|
||||||
req = webob.Request.blank('/v1.1/images/1/metadata')
|
req = webob.Request.blank('/v1.1/123/images/1/metadata')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
res_dict = json.loads(res.body)
|
res_dict = json.loads(res.body)
|
||||||
self.assertEqual(200, res.status_int)
|
self.assertEqual(200, res.status_int)
|
||||||
|
@ -100,7 +100,7 @@ class ImageMetaDataTest(test.TestCase):
|
||||||
self.assertEqual(value, res_dict['metadata'][key])
|
self.assertEqual(value, res_dict['metadata'][key])
|
||||||
|
|
||||||
def test_show(self):
|
def test_show(self):
|
||||||
req = webob.Request.blank('/v1.1/images/1/metadata/key1')
|
req = webob.Request.blank('/v1.1/fake/images/1/metadata/key1')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
res_dict = json.loads(res.body)
|
res_dict = json.loads(res.body)
|
||||||
self.assertEqual(200, res.status_int)
|
self.assertEqual(200, res.status_int)
|
||||||
|
@ -109,12 +109,12 @@ class ImageMetaDataTest(test.TestCase):
|
||||||
self.assertEqual('value1', res_dict['meta']['key1'])
|
self.assertEqual('value1', res_dict['meta']['key1'])
|
||||||
|
|
||||||
def test_show_not_found(self):
|
def test_show_not_found(self):
|
||||||
req = webob.Request.blank('/v1.1/images/1/metadata/key9')
|
req = webob.Request.blank('/v1.1/fake/images/1/metadata/key9')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(404, res.status_int)
|
self.assertEqual(404, res.status_int)
|
||||||
|
|
||||||
def test_create(self):
|
def test_create(self):
|
||||||
req = webob.Request.blank('/v1.1/images/2/metadata')
|
req = webob.Request.blank('/v1.1/fake/images/2/metadata')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = '{"metadata": {"key9": "value9"}}'
|
req.body = '{"metadata": {"key9": "value9"}}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -134,7 +134,7 @@ class ImageMetaDataTest(test.TestCase):
|
||||||
self.assertEqual(expected_output, actual_output)
|
self.assertEqual(expected_output, actual_output)
|
||||||
|
|
||||||
def test_update_all(self):
|
def test_update_all(self):
|
||||||
req = webob.Request.blank('/v1.1/images/2/metadata')
|
req = webob.Request.blank('/v1.1/fake/images/1/metadata')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = '{"metadata": {"key9": "value9"}}'
|
req.body = '{"metadata": {"key9": "value9"}}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -152,7 +152,7 @@ class ImageMetaDataTest(test.TestCase):
|
||||||
self.assertEqual(expected_output, actual_output)
|
self.assertEqual(expected_output, actual_output)
|
||||||
|
|
||||||
def test_update_item(self):
|
def test_update_item(self):
|
||||||
req = webob.Request.blank('/v1.1/images/1/metadata/key1')
|
req = webob.Request.blank('/v1.1/fake/images/1/metadata/key1')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = '{"meta": {"key1": "zz"}}'
|
req.body = '{"meta": {"key1": "zz"}}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -168,7 +168,7 @@ class ImageMetaDataTest(test.TestCase):
|
||||||
self.assertEqual(actual_output, expected_output)
|
self.assertEqual(actual_output, expected_output)
|
||||||
|
|
||||||
def test_update_item_bad_body(self):
|
def test_update_item_bad_body(self):
|
||||||
req = webob.Request.blank('/v1.1/images/1/metadata/key1')
|
req = webob.Request.blank('/v1.1/fake/images/1/metadata/key1')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = '{"key1": "zz"}'
|
req.body = '{"key1": "zz"}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -176,7 +176,7 @@ class ImageMetaDataTest(test.TestCase):
|
||||||
self.assertEqual(400, res.status_int)
|
self.assertEqual(400, res.status_int)
|
||||||
|
|
||||||
def test_update_item_too_many_keys(self):
|
def test_update_item_too_many_keys(self):
|
||||||
req = webob.Request.blank('/v1.1/images/1/metadata/key1')
|
req = webob.Request.blank('/v1.1/fake/images/1/metadata/key1')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = '{"meta": {"key1": "value1", "key2": "value2"}}'
|
req.body = '{"meta": {"key1": "value1", "key2": "value2"}}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -184,7 +184,7 @@ class ImageMetaDataTest(test.TestCase):
|
||||||
self.assertEqual(400, res.status_int)
|
self.assertEqual(400, res.status_int)
|
||||||
|
|
||||||
def test_update_item_body_uri_mismatch(self):
|
def test_update_item_body_uri_mismatch(self):
|
||||||
req = webob.Request.blank('/v1.1/images/1/metadata/bad')
|
req = webob.Request.blank('/v1.1/fake/images/1/metadata/bad')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = '{"meta": {"key1": "value1"}}'
|
req.body = '{"meta": {"key1": "value1"}}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -192,7 +192,7 @@ class ImageMetaDataTest(test.TestCase):
|
||||||
self.assertEqual(400, res.status_int)
|
self.assertEqual(400, res.status_int)
|
||||||
|
|
||||||
def test_update_item_xml(self):
|
def test_update_item_xml(self):
|
||||||
req = webob.Request.blank('/v1.1/images/1/metadata/key1')
|
req = webob.Request.blank('/v1.1/fake/images/1/metadata/key1')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = '<meta key="key1">five</meta>'
|
req.body = '<meta key="key1">five</meta>'
|
||||||
req.headers["content-type"] = "application/xml"
|
req.headers["content-type"] = "application/xml"
|
||||||
|
@ -208,14 +208,14 @@ class ImageMetaDataTest(test.TestCase):
|
||||||
self.assertEqual(actual_output, expected_output)
|
self.assertEqual(actual_output, expected_output)
|
||||||
|
|
||||||
def test_delete(self):
|
def test_delete(self):
|
||||||
req = webob.Request.blank('/v1.1/images/2/metadata/key1')
|
req = webob.Request.blank('/v1.1/fake/images/2/metadata/key1')
|
||||||
req.method = 'DELETE'
|
req.method = 'DELETE'
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(204, res.status_int)
|
self.assertEqual(204, res.status_int)
|
||||||
self.assertEqual('', res.body)
|
self.assertEqual('', res.body)
|
||||||
|
|
||||||
def test_delete_not_found(self):
|
def test_delete_not_found(self):
|
||||||
req = webob.Request.blank('/v1.1/images/2/metadata/blah')
|
req = webob.Request.blank('/v1.1/fake/images/2/metadata/blah')
|
||||||
req.method = 'DELETE'
|
req.method = 'DELETE'
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(404, res.status_int)
|
self.assertEqual(404, res.status_int)
|
||||||
|
@ -225,7 +225,7 @@ class ImageMetaDataTest(test.TestCase):
|
||||||
for num in range(FLAGS.quota_metadata_items + 1):
|
for num in range(FLAGS.quota_metadata_items + 1):
|
||||||
data['metadata']['key%i' % num] = "blah"
|
data['metadata']['key%i' % num] = "blah"
|
||||||
json_string = str(data).replace("\'", "\"")
|
json_string = str(data).replace("\'", "\"")
|
||||||
req = webob.Request.blank('/v1.1/images/2/metadata')
|
req = webob.Request.blank('/v1.1/fake/images/2/metadata')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json_string
|
req.body = json_string
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -233,7 +233,7 @@ class ImageMetaDataTest(test.TestCase):
|
||||||
self.assertEqual(413, res.status_int)
|
self.assertEqual(413, res.status_int)
|
||||||
|
|
||||||
def test_too_many_metadata_items_on_put(self):
|
def test_too_many_metadata_items_on_put(self):
|
||||||
req = webob.Request.blank('/v1.1/images/3/metadata/blah')
|
req = webob.Request.blank('/v1.1/fake/images/3/metadata/blah')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = '{"meta": {"blah": "blah"}}'
|
req.body = '{"meta": {"blah": "blah"}}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
|
|
@ -339,6 +339,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
self.stubs.UnsetAll()
|
self.stubs.UnsetAll()
|
||||||
super(ImageControllerWithGlanceServiceTest, self).tearDown()
|
super(ImageControllerWithGlanceServiceTest, self).tearDown()
|
||||||
|
|
||||||
|
def _get_fake_context(self):
|
||||||
|
class Context(object):
|
||||||
|
project_id = 'fake'
|
||||||
|
return Context()
|
||||||
|
|
||||||
def _applicable_fixture(self, fixture, user_id):
|
def _applicable_fixture(self, fixture, user_id):
|
||||||
"""Determine if this fixture is applicable for given user id."""
|
"""Determine if this fixture is applicable for given user id."""
|
||||||
is_public = fixture["is_public"]
|
is_public = fixture["is_public"]
|
||||||
|
@ -386,13 +391,13 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
self.assertEqual(expected_image, actual_image)
|
self.assertEqual(expected_image, actual_image)
|
||||||
|
|
||||||
def test_get_image_v1_1(self):
|
def test_get_image_v1_1(self):
|
||||||
request = webob.Request.blank('/v1.1/images/124')
|
request = webob.Request.blank('/v1.1/fake/images/124')
|
||||||
response = request.get_response(fakes.wsgi_app())
|
response = request.get_response(fakes.wsgi_app())
|
||||||
|
|
||||||
actual_image = json.loads(response.body)
|
actual_image = json.loads(response.body)
|
||||||
|
|
||||||
href = "http://localhost/v1.1/images/124"
|
href = "http://localhost/v1.1/fake/images/124"
|
||||||
bookmark = "http://localhost/images/124"
|
bookmark = "http://localhost/fake/images/124"
|
||||||
server_href = "http://localhost/v1.1/servers/42"
|
server_href = "http://localhost/v1.1/servers/42"
|
||||||
server_bookmark = "http://localhost/servers/42"
|
server_bookmark = "http://localhost/servers/42"
|
||||||
|
|
||||||
|
@ -508,7 +513,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
self.assertEqual(expected.toxml(), actual.toxml())
|
self.assertEqual(expected.toxml(), actual.toxml())
|
||||||
|
|
||||||
def test_get_image_404_v1_1_json(self):
|
def test_get_image_404_v1_1_json(self):
|
||||||
request = webob.Request.blank('/v1.1/images/NonExistantImage')
|
request = webob.Request.blank('/v1.1/fake/images/NonExistantImage')
|
||||||
response = request.get_response(fakes.wsgi_app())
|
response = request.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(404, response.status_int)
|
self.assertEqual(404, response.status_int)
|
||||||
|
|
||||||
|
@ -524,7 +529,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
def test_get_image_404_v1_1_xml(self):
|
def test_get_image_404_v1_1_xml(self):
|
||||||
request = webob.Request.blank('/v1.1/images/NonExistantImage')
|
request = webob.Request.blank('/v1.1/fake/images/NonExistantImage')
|
||||||
request.accept = "application/xml"
|
request.accept = "application/xml"
|
||||||
response = request.get_response(fakes.wsgi_app())
|
response = request.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(404, response.status_int)
|
self.assertEqual(404, response.status_int)
|
||||||
|
@ -545,7 +550,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
self.assertEqual(expected.toxml(), actual.toxml())
|
self.assertEqual(expected.toxml(), actual.toxml())
|
||||||
|
|
||||||
def test_get_image_index_v1_1(self):
|
def test_get_image_index_v1_1(self):
|
||||||
request = webob.Request.blank('/v1.1/images')
|
request = webob.Request.blank('/v1.1/fake/images')
|
||||||
response = request.get_response(fakes.wsgi_app())
|
response = request.get_response(fakes.wsgi_app())
|
||||||
|
|
||||||
response_dict = json.loads(response.body)
|
response_dict = json.loads(response.body)
|
||||||
|
@ -558,8 +563,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
fixtures.remove(image)
|
fixtures.remove(image)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
href = "http://localhost/v1.1/images/%s" % image["id"]
|
href = "http://localhost/v1.1/fake/images/%s" % image["id"]
|
||||||
bookmark = "http://localhost/images/%s" % image["id"]
|
bookmark = "http://localhost/fake/images/%s" % image["id"]
|
||||||
test_image = {
|
test_image = {
|
||||||
"id": image["id"],
|
"id": image["id"],
|
||||||
"name": image["name"],
|
"name": image["name"],
|
||||||
|
@ -637,7 +642,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
self.assertDictListMatch(expected, response_list)
|
self.assertDictListMatch(expected, response_list)
|
||||||
|
|
||||||
def test_get_image_details_v1_1(self):
|
def test_get_image_details_v1_1(self):
|
||||||
request = webob.Request.blank('/v1.1/images/detail')
|
request = webob.Request.blank('/v1.1/fake/images/detail')
|
||||||
response = request.get_response(fakes.wsgi_app())
|
response = request.get_response(fakes.wsgi_app())
|
||||||
|
|
||||||
response_dict = json.loads(response.body)
|
response_dict = json.loads(response.body)
|
||||||
|
@ -655,11 +660,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
'progress': 100,
|
'progress': 100,
|
||||||
"links": [{
|
"links": [{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/images/123",
|
"href": "http://localhost/v1.1/fake/images/123",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/images/123",
|
"href": "http://localhost/fake/images/123",
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -686,11 +691,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
},
|
},
|
||||||
"links": [{
|
"links": [{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/images/124",
|
"href": "http://localhost/v1.1/fake/images/124",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/images/124",
|
"href": "http://localhost/fake/images/124",
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -717,11 +722,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
},
|
},
|
||||||
"links": [{
|
"links": [{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/images/125",
|
"href": "http://localhost/v1.1/fake/images/125",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/images/125",
|
"href": "http://localhost/fake/images/125",
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -748,11 +753,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
},
|
},
|
||||||
"links": [{
|
"links": [{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/images/126",
|
"href": "http://localhost/v1.1/fake/images/126",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/images/126",
|
"href": "http://localhost/fake/images/126",
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -779,11 +784,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
},
|
},
|
||||||
"links": [{
|
"links": [{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/images/127",
|
"href": "http://localhost/v1.1/fake/images/127",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/images/127",
|
"href": "http://localhost/fake/images/127",
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -796,11 +801,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
'progress': 100,
|
'progress': 100,
|
||||||
"links": [{
|
"links": [{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": "http://localhost/v1.1/images/129",
|
"href": "http://localhost/v1.1/fake/images/129",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "bookmark",
|
"rel": "bookmark",
|
||||||
"href": "http://localhost/images/129",
|
"href": "http://localhost/fake/images/129",
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -809,7 +814,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_filter_with_name(self):
|
def test_image_filter_with_name(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
filters = {'name': 'testname'}
|
filters = {'name': 'testname'}
|
||||||
image_service.index(context, filters=filters).AndReturn([])
|
image_service.index(context, filters=filters).AndReturn([])
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
@ -821,7 +826,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_filter_with_status(self):
|
def test_image_filter_with_status(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
filters = {'status': 'ACTIVE'}
|
filters = {'status': 'ACTIVE'}
|
||||||
image_service.index(context, filters=filters).AndReturn([])
|
image_service.index(context, filters=filters).AndReturn([])
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
@ -833,7 +838,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_filter_with_property(self):
|
def test_image_filter_with_property(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
filters = {'property-test': '3'}
|
filters = {'property-test': '3'}
|
||||||
image_service.index(context, filters=filters).AndReturn([])
|
image_service.index(context, filters=filters).AndReturn([])
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
@ -845,7 +850,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_filter_server(self):
|
def test_image_filter_server(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
# 'server' should be converted to 'property-instance_ref'
|
# 'server' should be converted to 'property-instance_ref'
|
||||||
filters = {'property-instance_ref': 'http://localhost:8774/servers/12'}
|
filters = {'property-instance_ref': 'http://localhost:8774/servers/12'}
|
||||||
image_service.index(context, filters=filters).AndReturn([])
|
image_service.index(context, filters=filters).AndReturn([])
|
||||||
|
@ -859,7 +864,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_filter_changes_since(self):
|
def test_image_filter_changes_since(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
filters = {'changes-since': '2011-01-24T17:08Z'}
|
filters = {'changes-since': '2011-01-24T17:08Z'}
|
||||||
image_service.index(context, filters=filters).AndReturn([])
|
image_service.index(context, filters=filters).AndReturn([])
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
@ -872,7 +877,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_filter_with_type(self):
|
def test_image_filter_with_type(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
filters = {'property-image_type': 'BASE'}
|
filters = {'property-image_type': 'BASE'}
|
||||||
image_service.index(context, filters=filters).AndReturn([])
|
image_service.index(context, filters=filters).AndReturn([])
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
@ -884,7 +889,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_filter_not_supported(self):
|
def test_image_filter_not_supported(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
filters = {'status': 'ACTIVE'}
|
filters = {'status': 'ACTIVE'}
|
||||||
image_service.detail(context, filters=filters).AndReturn([])
|
image_service.detail(context, filters=filters).AndReturn([])
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
@ -897,7 +902,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_no_filters(self):
|
def test_image_no_filters(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
filters = {}
|
filters = {}
|
||||||
image_service.index(
|
image_service.index(
|
||||||
context, filters=filters).AndReturn([])
|
context, filters=filters).AndReturn([])
|
||||||
|
@ -911,11 +916,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_detail_filter_with_name(self):
|
def test_image_detail_filter_with_name(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
filters = {'name': 'testname'}
|
filters = {'name': 'testname'}
|
||||||
image_service.detail(context, filters=filters).AndReturn([])
|
image_service.detail(context, filters=filters).AndReturn([])
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
request = webob.Request.blank('/v1.1/images/detail?name=testname')
|
request = webob.Request.blank('/v1.1/fake/images/detail?name=testname')
|
||||||
request.environ['nova.context'] = context
|
request.environ['nova.context'] = context
|
||||||
controller = images.ControllerV11(image_service=image_service)
|
controller = images.ControllerV11(image_service=image_service)
|
||||||
controller.detail(request)
|
controller.detail(request)
|
||||||
|
@ -923,11 +928,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_detail_filter_with_status(self):
|
def test_image_detail_filter_with_status(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
filters = {'status': 'ACTIVE'}
|
filters = {'status': 'ACTIVE'}
|
||||||
image_service.detail(context, filters=filters).AndReturn([])
|
image_service.detail(context, filters=filters).AndReturn([])
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
request = webob.Request.blank('/v1.1/images/detail?status=ACTIVE')
|
request = webob.Request.blank('/v1.1/fake/images/detail?status=ACTIVE')
|
||||||
request.environ['nova.context'] = context
|
request.environ['nova.context'] = context
|
||||||
controller = images.ControllerV11(image_service=image_service)
|
controller = images.ControllerV11(image_service=image_service)
|
||||||
controller.detail(request)
|
controller.detail(request)
|
||||||
|
@ -935,11 +940,12 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_detail_filter_with_property(self):
|
def test_image_detail_filter_with_property(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
filters = {'property-test': '3'}
|
filters = {'property-test': '3'}
|
||||||
image_service.detail(context, filters=filters).AndReturn([])
|
image_service.detail(context, filters=filters).AndReturn([])
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
request = webob.Request.blank('/v1.1/images/detail?property-test=3')
|
request = webob.Request.blank(
|
||||||
|
'/v1.1/fake/images/detail?property-test=3')
|
||||||
request.environ['nova.context'] = context
|
request.environ['nova.context'] = context
|
||||||
controller = images.ControllerV11(image_service=image_service)
|
controller = images.ControllerV11(image_service=image_service)
|
||||||
controller.detail(request)
|
controller.detail(request)
|
||||||
|
@ -947,12 +953,12 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_detail_filter_server(self):
|
def test_image_detail_filter_server(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
# 'server' should be converted to 'property-instance_ref'
|
# 'server' should be converted to 'property-instance_ref'
|
||||||
filters = {'property-instance_ref': 'http://localhost:8774/servers/12'}
|
filters = {'property-instance_ref': 'http://localhost:8774/servers/12'}
|
||||||
image_service.index(context, filters=filters).AndReturn([])
|
image_service.index(context, filters=filters).AndReturn([])
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
request = webob.Request.blank('/v1.1/images/detail?server='
|
request = webob.Request.blank('/v1.1/fake/images/detail?server='
|
||||||
'http://localhost:8774/servers/12')
|
'http://localhost:8774/servers/12')
|
||||||
request.environ['nova.context'] = context
|
request.environ['nova.context'] = context
|
||||||
controller = images.ControllerV11(image_service=image_service)
|
controller = images.ControllerV11(image_service=image_service)
|
||||||
|
@ -961,11 +967,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_detail_filter_changes_since(self):
|
def test_image_detail_filter_changes_since(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
filters = {'changes-since': '2011-01-24T17:08Z'}
|
filters = {'changes-since': '2011-01-24T17:08Z'}
|
||||||
image_service.index(context, filters=filters).AndReturn([])
|
image_service.index(context, filters=filters).AndReturn([])
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
request = webob.Request.blank('/v1.1/images/detail?changes-since='
|
request = webob.Request.blank('/v1.1/fake/images/detail?changes-since='
|
||||||
'2011-01-24T17:08Z')
|
'2011-01-24T17:08Z')
|
||||||
request.environ['nova.context'] = context
|
request.environ['nova.context'] = context
|
||||||
controller = images.ControllerV11(image_service=image_service)
|
controller = images.ControllerV11(image_service=image_service)
|
||||||
|
@ -974,11 +980,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_detail_filter_with_type(self):
|
def test_image_detail_filter_with_type(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
filters = {'property-image_type': 'BASE'}
|
filters = {'property-image_type': 'BASE'}
|
||||||
image_service.index(context, filters=filters).AndReturn([])
|
image_service.index(context, filters=filters).AndReturn([])
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
request = webob.Request.blank('/v1.1/images/detail?type=BASE')
|
request = webob.Request.blank('/v1.1/fake/images/detail?type=BASE')
|
||||||
request.environ['nova.context'] = context
|
request.environ['nova.context'] = context
|
||||||
controller = images.ControllerV11(image_service=image_service)
|
controller = images.ControllerV11(image_service=image_service)
|
||||||
controller.index(request)
|
controller.index(request)
|
||||||
|
@ -986,11 +992,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_detail_filter_not_supported(self):
|
def test_image_detail_filter_not_supported(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
filters = {'status': 'ACTIVE'}
|
filters = {'status': 'ACTIVE'}
|
||||||
image_service.detail(context, filters=filters).AndReturn([])
|
image_service.detail(context, filters=filters).AndReturn([])
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
request = webob.Request.blank('/v1.1/images/detail?status=ACTIVE&'
|
request = webob.Request.blank('/v1.1/fake/images/detail?status=ACTIVE&'
|
||||||
'UNSUPPORTEDFILTER=testname')
|
'UNSUPPORTEDFILTER=testname')
|
||||||
request.environ['nova.context'] = context
|
request.environ['nova.context'] = context
|
||||||
controller = images.ControllerV11(image_service=image_service)
|
controller = images.ControllerV11(image_service=image_service)
|
||||||
|
@ -999,11 +1005,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
|
||||||
|
|
||||||
def test_image_detail_no_filters(self):
|
def test_image_detail_no_filters(self):
|
||||||
image_service = self.mox.CreateMockAnything()
|
image_service = self.mox.CreateMockAnything()
|
||||||
context = object()
|
context = self._get_fake_context()
|
||||||
filters = {}
|
filters = {}
|
||||||
image_service.detail(context, filters=filters).AndReturn([])
|
image_service.detail(context, filters=filters).AndReturn([])
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
request = webob.Request.blank('/v1.1/images/detail')
|
request = webob.Request.blank('/v1.1/fake/images/detail')
|
||||||
request.environ['nova.context'] = context
|
request.environ['nova.context'] = context
|
||||||
controller = images.ControllerV11(image_service=image_service)
|
controller = images.ControllerV11(image_service=image_service)
|
||||||
controller.detail(request)
|
controller.detail(request)
|
||||||
|
@ -1123,8 +1129,8 @@ class ImageXMLSerializationTest(test.TestCase):
|
||||||
TIMESTAMP = "2010-10-11T10:30:22Z"
|
TIMESTAMP = "2010-10-11T10:30:22Z"
|
||||||
SERVER_HREF = 'http://localhost/v1.1/servers/123'
|
SERVER_HREF = 'http://localhost/v1.1/servers/123'
|
||||||
SERVER_BOOKMARK = 'http://localhost/servers/123'
|
SERVER_BOOKMARK = 'http://localhost/servers/123'
|
||||||
IMAGE_HREF = 'http://localhost/v1.1/images/%s'
|
IMAGE_HREF = 'http://localhost/v1.1/fake/images/%s'
|
||||||
IMAGE_BOOKMARK = 'http://localhost/images/%s'
|
IMAGE_BOOKMARK = 'http://localhost/fake/images/%s'
|
||||||
|
|
||||||
def test_show(self):
|
def test_show(self):
|
||||||
serializer = images.ImageXMLSerializer()
|
serializer = images.ImageXMLSerializer()
|
||||||
|
|
|
@ -489,7 +489,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
|
|
||||||
def test_server_bad_body(self):
|
def test_server_bad_body(self):
|
||||||
body = {}
|
body = {}
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -498,7 +498,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
|
|
||||||
def test_server_unknown_action(self):
|
def test_server_unknown_action(self):
|
||||||
body = {'sockTheFox': {'fakekey': '1234'}}
|
body = {'sockTheFox': {'fakekey': '1234'}}
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -509,7 +509,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
mock_method = MockSetAdminPassword()
|
mock_method = MockSetAdminPassword()
|
||||||
self.stubs.Set(nova.compute.api.API, 'set_admin_password', mock_method)
|
self.stubs.Set(nova.compute.api.API, 'set_admin_password', mock_method)
|
||||||
body = {'changePassword': {'adminPass': '1234pass'}}
|
body = {'changePassword': {'adminPass': '1234pass'}}
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -521,7 +521,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
def test_server_change_password_xml(self):
|
def test_server_change_password_xml(self):
|
||||||
mock_method = MockSetAdminPassword()
|
mock_method = MockSetAdminPassword()
|
||||||
self.stubs.Set(nova.compute.api.API, 'set_admin_password', mock_method)
|
self.stubs.Set(nova.compute.api.API, 'set_admin_password', mock_method)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = "application/xml"
|
req.content_type = "application/xml"
|
||||||
req.body = """<?xml version="1.0" encoding="UTF-8"?>
|
req.body = """<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
@ -535,7 +535,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
|
|
||||||
def test_server_change_password_not_a_string(self):
|
def test_server_change_password_not_a_string(self):
|
||||||
body = {'changePassword': {'adminPass': 1234}}
|
body = {'changePassword': {'adminPass': 1234}}
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -544,7 +544,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
|
|
||||||
def test_server_change_password_bad_request(self):
|
def test_server_change_password_bad_request(self):
|
||||||
body = {'changePassword': {'pass': '12345'}}
|
body = {'changePassword': {'pass': '12345'}}
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -553,7 +553,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
|
|
||||||
def test_server_change_password_empty_string(self):
|
def test_server_change_password_empty_string(self):
|
||||||
body = {'changePassword': {'adminPass': ''}}
|
body = {'changePassword': {'adminPass': ''}}
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -562,7 +562,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
|
|
||||||
def test_server_change_password_none(self):
|
def test_server_change_password_none(self):
|
||||||
body = {'changePassword': {'adminPass': None}}
|
body = {'changePassword': {'adminPass': None}}
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -571,7 +571,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
|
|
||||||
def test_server_reboot_hard(self):
|
def test_server_reboot_hard(self):
|
||||||
body = dict(reboot=dict(type="HARD"))
|
body = dict(reboot=dict(type="HARD"))
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -580,7 +580,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
|
|
||||||
def test_server_reboot_soft(self):
|
def test_server_reboot_soft(self):
|
||||||
body = dict(reboot=dict(type="SOFT"))
|
body = dict(reboot=dict(type="SOFT"))
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -589,7 +589,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
|
|
||||||
def test_server_reboot_incorrect_type(self):
|
def test_server_reboot_incorrect_type(self):
|
||||||
body = dict(reboot=dict(type="NOT_A_TYPE"))
|
body = dict(reboot=dict(type="NOT_A_TYPE"))
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -598,7 +598,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
|
|
||||||
def test_server_reboot_missing_type(self):
|
def test_server_reboot_missing_type(self):
|
||||||
body = dict(reboot=dict())
|
body = dict(reboot=dict())
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -612,7 +612,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -633,7 +633,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
self.stubs.Set(nova.db, 'instance_get_by_uuid',
|
self.stubs.Set(nova.db, 'instance_get_by_uuid',
|
||||||
return_server_with_uuid_and_power_state(state))
|
return_server_with_uuid_and_power_state(state))
|
||||||
|
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -651,7 +651,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -667,7 +667,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -682,7 +682,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -701,7 +701,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -720,7 +720,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
|
@ -730,7 +730,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
|
|
||||||
def test_resize_server(self):
|
def test_resize_server(self):
|
||||||
|
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
body_dict = dict(resize=dict(flavorRef="http://localhost/3"))
|
body_dict = dict(resize=dict(flavorRef="http://localhost/3"))
|
||||||
|
@ -748,7 +748,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
self.assertEqual(self.resize_called, True)
|
self.assertEqual(self.resize_called, True)
|
||||||
|
|
||||||
def test_resize_server_no_flavor(self):
|
def test_resize_server_no_flavor(self):
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
body_dict = dict(resize=dict())
|
body_dict = dict(resize=dict())
|
||||||
|
@ -758,7 +758,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
self.assertEqual(res.status_int, 400)
|
self.assertEqual(res.status_int, 400)
|
||||||
|
|
||||||
def test_resize_server_no_flavor_ref(self):
|
def test_resize_server_no_flavor_ref(self):
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
body_dict = dict(resize=dict(flavorRef=None))
|
body_dict = dict(resize=dict(flavorRef=None))
|
||||||
|
@ -768,7 +768,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
self.assertEqual(res.status_int, 400)
|
self.assertEqual(res.status_int, 400)
|
||||||
|
|
||||||
def test_confirm_resize_server(self):
|
def test_confirm_resize_server(self):
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
body_dict = dict(confirmResize=None)
|
body_dict = dict(confirmResize=None)
|
||||||
|
@ -786,7 +786,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
self.assertEqual(self.confirm_resize_called, True)
|
self.assertEqual(self.confirm_resize_called, True)
|
||||||
|
|
||||||
def test_revert_resize_server(self):
|
def test_revert_resize_server(self):
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
body_dict = dict(revertResize=None)
|
body_dict = dict(revertResize=None)
|
||||||
|
@ -809,7 +809,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
'name': 'Snapshot 1',
|
'name': 'Snapshot 1',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -828,7 +828,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
'name': 'Snapshot 1',
|
'name': 'Snapshot 1',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -842,7 +842,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
'metadata': {'key': 'asdf'},
|
'metadata': {'key': 'asdf'},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -860,7 +860,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
}
|
}
|
||||||
for num in range(FLAGS.quota_metadata_items + 1):
|
for num in range(FLAGS.quota_metadata_items + 1):
|
||||||
body['createImage']['metadata']['foo%i' % num] = "bar"
|
body['createImage']['metadata']['foo%i' % num] = "bar"
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -871,7 +871,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
body = {
|
body = {
|
||||||
'createImage': {},
|
'createImage': {},
|
||||||
}
|
}
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -885,7 +885,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
'metadata': 'henry',
|
'metadata': 'henry',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -904,7 +904,7 @@ class ServerActionsTestV11(test.TestCase):
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
req = webob.Request.blank('/v1.1/servers/1/action')
|
req = webob.Request.blank('/v1.1/fake/servers/1/action')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json.dumps(body)
|
req.body = json.dumps(body)
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
|
|
@ -83,7 +83,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_index(self):
|
def test_index(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_get',
|
self.stubs.Set(nova.db.api, 'instance_metadata_get',
|
||||||
return_server_metadata)
|
return_server_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(200, res.status_int)
|
self.assertEqual(200, res.status_int)
|
||||||
res_dict = json.loads(res.body)
|
res_dict = json.loads(res.body)
|
||||||
|
@ -100,7 +100,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_index_xml(self):
|
def test_index_xml(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_get',
|
self.stubs.Set(nova.db.api, 'instance_metadata_get',
|
||||||
return_server_metadata)
|
return_server_metadata)
|
||||||
request = webob.Request.blank("/v1.1/servers/1/metadata")
|
request = webob.Request.blank("/v1.1/fake/servers/1/metadata")
|
||||||
request.accept = "application/xml"
|
request.accept = "application/xml"
|
||||||
response = request.get_response(fakes.wsgi_app())
|
response = request.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(200, response.status_int)
|
self.assertEqual(200, response.status_int)
|
||||||
|
@ -120,14 +120,14 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
|
|
||||||
def test_index_nonexistant_server(self):
|
def test_index_nonexistant_server(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
|
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(404, res.status_int)
|
self.assertEqual(404, res.status_int)
|
||||||
|
|
||||||
def test_index_no_data(self):
|
def test_index_no_data(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_get',
|
self.stubs.Set(nova.db.api, 'instance_metadata_get',
|
||||||
return_empty_server_metadata)
|
return_empty_server_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(200, res.status_int)
|
self.assertEqual(200, res.status_int)
|
||||||
res_dict = json.loads(res.body)
|
res_dict = json.loads(res.body)
|
||||||
|
@ -137,7 +137,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_show(self):
|
def test_show(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_get',
|
self.stubs.Set(nova.db.api, 'instance_metadata_get',
|
||||||
return_server_metadata)
|
return_server_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata/key2')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata/key2')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
res_dict = json.loads(res.body)
|
res_dict = json.loads(res.body)
|
||||||
self.assertEqual(200, res.status_int)
|
self.assertEqual(200, res.status_int)
|
||||||
|
@ -147,7 +147,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_show_xml(self):
|
def test_show_xml(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_get',
|
self.stubs.Set(nova.db.api, 'instance_metadata_get',
|
||||||
return_server_metadata)
|
return_server_metadata)
|
||||||
request = webob.Request.blank("/v1.1/servers/1/metadata/key2")
|
request = webob.Request.blank("/v1.1/fake/servers/1/metadata/key2")
|
||||||
request.accept = "application/xml"
|
request.accept = "application/xml"
|
||||||
response = request.get_response(fakes.wsgi_app())
|
response = request.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(200, response.status_int)
|
self.assertEqual(200, response.status_int)
|
||||||
|
@ -164,14 +164,14 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
|
|
||||||
def test_show_nonexistant_server(self):
|
def test_show_nonexistant_server(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
|
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata/key2')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata/key2')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(404, res.status_int)
|
self.assertEqual(404, res.status_int)
|
||||||
|
|
||||||
def test_show_meta_not_found(self):
|
def test_show_meta_not_found(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_get',
|
self.stubs.Set(nova.db.api, 'instance_metadata_get',
|
||||||
return_empty_server_metadata)
|
return_empty_server_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata/key6')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata/key6')
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(404, res.status_int)
|
self.assertEqual(404, res.status_int)
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
return_server_metadata)
|
return_server_metadata)
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_delete',
|
self.stubs.Set(nova.db.api, 'instance_metadata_delete',
|
||||||
delete_server_metadata)
|
delete_server_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata/key2')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata/key2')
|
||||||
req.method = 'DELETE'
|
req.method = 'DELETE'
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(204, res.status_int)
|
self.assertEqual(204, res.status_int)
|
||||||
|
@ -188,7 +188,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
|
|
||||||
def test_delete_nonexistant_server(self):
|
def test_delete_nonexistant_server(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
|
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata/key1')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata/key1')
|
||||||
req.method = 'DELETE'
|
req.method = 'DELETE'
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(404, res.status_int)
|
self.assertEqual(404, res.status_int)
|
||||||
|
@ -196,7 +196,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_delete_meta_not_found(self):
|
def test_delete_meta_not_found(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_get',
|
self.stubs.Set(nova.db.api, 'instance_metadata_get',
|
||||||
return_empty_server_metadata)
|
return_empty_server_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata/key6')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata/key6')
|
||||||
req.method = 'DELETE'
|
req.method = 'DELETE'
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
self.assertEqual(404, res.status_int)
|
self.assertEqual(404, res.status_int)
|
||||||
|
@ -206,7 +206,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
return_server_metadata)
|
return_server_metadata)
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
||||||
return_create_instance_metadata)
|
return_create_instance_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.content_type = "application/json"
|
req.content_type = "application/json"
|
||||||
input = {"metadata": {"key9": "value9"}}
|
input = {"metadata": {"key9": "value9"}}
|
||||||
|
@ -227,7 +227,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
return_server_metadata)
|
return_server_metadata)
|
||||||
self.stubs.Set(nova.db.api, "instance_metadata_update",
|
self.stubs.Set(nova.db.api, "instance_metadata_update",
|
||||||
return_create_instance_metadata)
|
return_create_instance_metadata)
|
||||||
req = webob.Request.blank("/v1.1/servers/1/metadata")
|
req = webob.Request.blank("/v1.1/fake/servers/1/metadata")
|
||||||
req.method = "POST"
|
req.method = "POST"
|
||||||
req.content_type = "application/xml"
|
req.content_type = "application/xml"
|
||||||
req.accept = "application/xml"
|
req.accept = "application/xml"
|
||||||
|
@ -258,7 +258,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_create_empty_body(self):
|
def test_create_empty_body(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
||||||
return_create_instance_metadata)
|
return_create_instance_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
|
@ -266,7 +266,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
|
|
||||||
def test_create_nonexistant_server(self):
|
def test_create_nonexistant_server(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
|
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
|
||||||
req = webob.Request.blank('/v1.1/servers/100/metadata')
|
req = webob.Request.blank('/v1.1/fake/servers/100/metadata')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = '{"metadata": {"key1": "value1"}}'
|
req.body = '{"metadata": {"key1": "value1"}}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -276,7 +276,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_update_all(self):
|
def test_update_all(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
||||||
return_create_instance_metadata)
|
return_create_instance_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.content_type = "application/json"
|
req.content_type = "application/json"
|
||||||
expected = {
|
expected = {
|
||||||
|
@ -294,7 +294,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_update_all_empty_container(self):
|
def test_update_all_empty_container(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
||||||
return_create_instance_metadata)
|
return_create_instance_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.content_type = "application/json"
|
req.content_type = "application/json"
|
||||||
expected = {'metadata': {}}
|
expected = {'metadata': {}}
|
||||||
|
@ -307,7 +307,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_update_all_malformed_container(self):
|
def test_update_all_malformed_container(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
||||||
return_create_instance_metadata)
|
return_create_instance_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.content_type = "application/json"
|
req.content_type = "application/json"
|
||||||
expected = {'meta': {}}
|
expected = {'meta': {}}
|
||||||
|
@ -318,7 +318,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_update_all_malformed_data(self):
|
def test_update_all_malformed_data(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
||||||
return_create_instance_metadata)
|
return_create_instance_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.content_type = "application/json"
|
req.content_type = "application/json"
|
||||||
expected = {'metadata': ['asdf']}
|
expected = {'metadata': ['asdf']}
|
||||||
|
@ -328,7 +328,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
|
|
||||||
def test_update_all_nonexistant_server(self):
|
def test_update_all_nonexistant_server(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
|
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
|
||||||
req = webob.Request.blank('/v1.1/servers/100/metadata')
|
req = webob.Request.blank('/v1.1/fake/servers/100/metadata')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.content_type = "application/json"
|
req.content_type = "application/json"
|
||||||
req.body = json.dumps({'metadata': {'key10': 'value10'}})
|
req.body = json.dumps({'metadata': {'key10': 'value10'}})
|
||||||
|
@ -338,7 +338,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_update_item(self):
|
def test_update_item(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
||||||
return_create_instance_metadata)
|
return_create_instance_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata/key1')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata/key1')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = '{"meta": {"key1": "value1"}}'
|
req.body = '{"meta": {"key1": "value1"}}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -352,7 +352,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_update_item_xml(self):
|
def test_update_item_xml(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
||||||
return_create_instance_metadata)
|
return_create_instance_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata/key9')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata/key9')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.accept = "application/json"
|
req.accept = "application/json"
|
||||||
req.content_type = "application/xml"
|
req.content_type = "application/xml"
|
||||||
|
@ -369,7 +369,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
|
|
||||||
def test_update_item_nonexistant_server(self):
|
def test_update_item_nonexistant_server(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
|
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
|
||||||
req = webob.Request.blank('/v1.1/servers/asdf/metadata/key1')
|
req = webob.Request.blank('/v1.1/fake/servers/asdf/metadata/key1')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = '{"meta":{"key1": "value1"}}'
|
req.body = '{"meta":{"key1": "value1"}}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -379,7 +379,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_update_item_empty_body(self):
|
def test_update_item_empty_body(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
||||||
return_create_instance_metadata)
|
return_create_instance_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata/key1')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata/key1')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
res = req.get_response(fakes.wsgi_app())
|
res = req.get_response(fakes.wsgi_app())
|
||||||
|
@ -388,7 +388,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_update_item_too_many_keys(self):
|
def test_update_item_too_many_keys(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
||||||
return_create_instance_metadata)
|
return_create_instance_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata/key1')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata/key1')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = '{"meta": {"key1": "value1", "key2": "value2"}}'
|
req.body = '{"meta": {"key1": "value1", "key2": "value2"}}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -398,7 +398,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_update_item_body_uri_mismatch(self):
|
def test_update_item_body_uri_mismatch(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
||||||
return_create_instance_metadata)
|
return_create_instance_metadata)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata/bad')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata/bad')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = '{"meta": {"key1": "value1"}}'
|
req.body = '{"meta": {"key1": "value1"}}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -412,7 +412,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
for num in range(FLAGS.quota_metadata_items + 1):
|
for num in range(FLAGS.quota_metadata_items + 1):
|
||||||
data['metadata']['key%i' % num] = "blah"
|
data['metadata']['key%i' % num] = "blah"
|
||||||
json_string = str(data).replace("\'", "\"")
|
json_string = str(data).replace("\'", "\"")
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata')
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.body = json_string
|
req.body = json_string
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
@ -422,7 +422,7 @@ class ServerMetaDataTest(test.TestCase):
|
||||||
def test_too_many_metadata_items_on_update_item(self):
|
def test_too_many_metadata_items_on_update_item(self):
|
||||||
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
self.stubs.Set(nova.db.api, 'instance_metadata_update',
|
||||||
return_create_instance_metadata_max)
|
return_create_instance_metadata_max)
|
||||||
req = webob.Request.blank('/v1.1/servers/1/metadata/key1')
|
req = webob.Request.blank('/v1.1/fake/servers/1/metadata/key1')
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.body = '{"meta": {"a new key": "a new value"}}'
|
req.body = '{"meta": {"a new key": "a new value"}}'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -48,6 +48,14 @@ class OpenStackApiAuthenticationException(OpenStackApiException):
|
||||||
response)
|
response)
|
||||||
|
|
||||||
|
|
||||||
|
class OpenStackApiAuthorizationException(OpenStackApiException):
|
||||||
|
def __init__(self, response=None, message=None):
|
||||||
|
if not message:
|
||||||
|
message = _("Authorization error")
|
||||||
|
super(OpenStackApiAuthorizationException, self).__init__(message,
|
||||||
|
response)
|
||||||
|
|
||||||
|
|
||||||
class OpenStackApiNotFoundException(OpenStackApiException):
|
class OpenStackApiNotFoundException(OpenStackApiException):
|
||||||
def __init__(self, response=None, message=None):
|
def __init__(self, response=None, message=None):
|
||||||
if not message:
|
if not message:
|
||||||
|
@ -69,6 +77,8 @@ class TestOpenStackClient(object):
|
||||||
self.auth_user = auth_user
|
self.auth_user = auth_user
|
||||||
self.auth_key = auth_key
|
self.auth_key = auth_key
|
||||||
self.auth_uri = auth_uri
|
self.auth_uri = auth_uri
|
||||||
|
# default project_id
|
||||||
|
self.project_id = 'openstack'
|
||||||
|
|
||||||
def request(self, url, method='GET', body=None, headers=None):
|
def request(self, url, method='GET', body=None, headers=None):
|
||||||
_headers = {'Content-Type': 'application/json'}
|
_headers = {'Content-Type': 'application/json'}
|
||||||
|
@ -105,7 +115,8 @@ class TestOpenStackClient(object):
|
||||||
|
|
||||||
auth_uri = self.auth_uri
|
auth_uri = self.auth_uri
|
||||||
headers = {'X-Auth-User': self.auth_user,
|
headers = {'X-Auth-User': self.auth_user,
|
||||||
'X-Auth-Key': self.auth_key}
|
'X-Auth-Key': self.auth_key,
|
||||||
|
'X-Auth-Project-Id': self.project_id}
|
||||||
response = self.request(auth_uri,
|
response = self.request(auth_uri,
|
||||||
headers=headers)
|
headers=headers)
|
||||||
|
|
||||||
|
@ -127,7 +138,8 @@ class TestOpenStackClient(object):
|
||||||
|
|
||||||
# NOTE(justinsb): httplib 'helpfully' converts headers to lower case
|
# NOTE(justinsb): httplib 'helpfully' converts headers to lower case
|
||||||
base_uri = auth_result['x-server-management-url']
|
base_uri = auth_result['x-server-management-url']
|
||||||
full_uri = base_uri + relative_uri
|
|
||||||
|
full_uri = '%s/%s' % (base_uri, relative_uri)
|
||||||
|
|
||||||
headers = kwargs.setdefault('headers', {})
|
headers = kwargs.setdefault('headers', {})
|
||||||
headers['X-Auth-Token'] = auth_result['x-auth-token']
|
headers['X-Auth-Token'] = auth_result['x-auth-token']
|
||||||
|
@ -141,6 +153,8 @@ class TestOpenStackClient(object):
|
||||||
if not http_status in check_response_status:
|
if not http_status in check_response_status:
|
||||||
if http_status == 404:
|
if http_status == 404:
|
||||||
raise OpenStackApiNotFoundException(response=response)
|
raise OpenStackApiNotFoundException(response=response)
|
||||||
|
elif http_status == 401:
|
||||||
|
raise OpenStackApiAuthorizationException(response=response)
|
||||||
else:
|
else:
|
||||||
raise OpenStackApiException(
|
raise OpenStackApiException(
|
||||||
message=_("Unexpected status code"),
|
message=_("Unexpected status code"),
|
||||||
|
@ -256,7 +270,8 @@ class TestOpenStackClient(object):
|
||||||
|
|
||||||
def post_server_volume(self, server_id, volume_attachment):
|
def post_server_volume(self, server_id, volume_attachment):
|
||||||
return self.api_post('/servers/%s/os-volume_attachments' %
|
return self.api_post('/servers/%s/os-volume_attachments' %
|
||||||
(server_id), volume_attachment)['volumeAttachment']
|
(server_id), volume_attachment
|
||||||
|
)['volumeAttachment']
|
||||||
|
|
||||||
def delete_server_volume(self, server_id, attachment_id):
|
def delete_server_volume(self, server_id, attachment_id):
|
||||||
return self.api_delete('/servers/%s/os-volume_attachments/%s' %
|
return self.api_delete('/servers/%s/os-volume_attachments/%s' %
|
||||||
|
|
|
@ -59,6 +59,12 @@ class LoginTest(integrated_helpers._IntegratedTestBase):
|
||||||
self.assertRaises(client.OpenStackApiAuthenticationException,
|
self.assertRaises(client.OpenStackApiAuthenticationException,
|
||||||
bad_credentials_api.get_flavors)
|
bad_credentials_api.get_flavors)
|
||||||
|
|
||||||
|
def test_good_login_bad_project(self):
|
||||||
|
"""Test that I get a 401 with valid user/pass but bad project"""
|
||||||
|
self.api.project_id = 'openstackBAD'
|
||||||
|
|
||||||
|
self.assertRaises(client.OpenStackApiAuthorizationException,
|
||||||
|
self.api.get_flavors)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -347,7 +347,7 @@ class ComputeTestCase(test.TestCase):
|
||||||
self.assertEquals(msg['priority'], 'INFO')
|
self.assertEquals(msg['priority'], 'INFO')
|
||||||
self.assertEquals(msg['event_type'], 'compute.instance.create')
|
self.assertEquals(msg['event_type'], 'compute.instance.create')
|
||||||
payload = msg['payload']
|
payload = msg['payload']
|
||||||
self.assertEquals(payload['tenant_id'], self.project_id)
|
self.assertEquals(payload['project_id'], self.project_id)
|
||||||
self.assertEquals(payload['user_id'], self.user_id)
|
self.assertEquals(payload['user_id'], self.user_id)
|
||||||
self.assertEquals(payload['instance_id'], instance_id)
|
self.assertEquals(payload['instance_id'], instance_id)
|
||||||
self.assertEquals(payload['instance_type'], 'm1.tiny')
|
self.assertEquals(payload['instance_type'], 'm1.tiny')
|
||||||
|
@ -371,7 +371,7 @@ class ComputeTestCase(test.TestCase):
|
||||||
self.assertEquals(msg['priority'], 'INFO')
|
self.assertEquals(msg['priority'], 'INFO')
|
||||||
self.assertEquals(msg['event_type'], 'compute.instance.delete')
|
self.assertEquals(msg['event_type'], 'compute.instance.delete')
|
||||||
payload = msg['payload']
|
payload = msg['payload']
|
||||||
self.assertEquals(payload['tenant_id'], self.project_id)
|
self.assertEquals(payload['project_id'], self.project_id)
|
||||||
self.assertEquals(payload['user_id'], self.user_id)
|
self.assertEquals(payload['user_id'], self.user_id)
|
||||||
self.assertEquals(payload['instance_id'], instance_id)
|
self.assertEquals(payload['instance_id'], instance_id)
|
||||||
self.assertEquals(payload['instance_type'], 'm1.tiny')
|
self.assertEquals(payload['instance_type'], 'm1.tiny')
|
||||||
|
@ -454,7 +454,7 @@ class ComputeTestCase(test.TestCase):
|
||||||
self.assertEquals(msg['priority'], 'INFO')
|
self.assertEquals(msg['priority'], 'INFO')
|
||||||
self.assertEquals(msg['event_type'], 'compute.instance.resize.prep')
|
self.assertEquals(msg['event_type'], 'compute.instance.resize.prep')
|
||||||
payload = msg['payload']
|
payload = msg['payload']
|
||||||
self.assertEquals(payload['tenant_id'], self.project_id)
|
self.assertEquals(payload['project_id'], self.project_id)
|
||||||
self.assertEquals(payload['user_id'], self.user_id)
|
self.assertEquals(payload['user_id'], self.user_id)
|
||||||
self.assertEquals(payload['instance_id'], instance_id)
|
self.assertEquals(payload['instance_id'], instance_id)
|
||||||
self.assertEquals(payload['instance_type'], 'm1.tiny')
|
self.assertEquals(payload['instance_type'], 'm1.tiny')
|
||||||
|
|
|
@ -28,55 +28,35 @@ sys.dont_write_bytecode = True
|
||||||
import imp
|
import imp
|
||||||
nova_manage = imp.load_source('nova_manage.py', NOVA_MANAGE_PATH)
|
nova_manage = imp.load_source('nova_manage.py', NOVA_MANAGE_PATH)
|
||||||
sys.dont_write_bytecode = False
|
sys.dont_write_bytecode = False
|
||||||
|
import mox
|
||||||
|
import stubout
|
||||||
|
|
||||||
import netaddr
|
|
||||||
from nova import context
|
from nova import context
|
||||||
from nova import db
|
from nova import db
|
||||||
from nova import flags
|
from nova import exception
|
||||||
from nova import test
|
from nova import test
|
||||||
|
from nova.tests.db import fakes as db_fakes
|
||||||
FLAGS = flags.FLAGS
|
|
||||||
|
|
||||||
|
|
||||||
class FixedIpCommandsTestCase(test.TestCase):
|
class FixedIpCommandsTestCase(test.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(FixedIpCommandsTestCase, self).setUp()
|
super(FixedIpCommandsTestCase, self).setUp()
|
||||||
cidr = '10.0.0.0/24'
|
self.stubs = stubout.StubOutForTesting()
|
||||||
net = netaddr.IPNetwork(cidr)
|
db_fakes.stub_out_db_network_api(self.stubs)
|
||||||
net_info = {'bridge': 'fakebr',
|
|
||||||
'bridge_interface': 'fakeeth',
|
|
||||||
'dns': FLAGS.flat_network_dns,
|
|
||||||
'cidr': cidr,
|
|
||||||
'netmask': str(net.netmask),
|
|
||||||
'gateway': str(net[1]),
|
|
||||||
'broadcast': str(net.broadcast),
|
|
||||||
'dhcp_start': str(net[2])}
|
|
||||||
self.network = db.network_create_safe(context.get_admin_context(),
|
|
||||||
net_info)
|
|
||||||
num_ips = len(net)
|
|
||||||
for index in range(num_ips):
|
|
||||||
address = str(net[index])
|
|
||||||
reserved = (index == 1 or index == 2)
|
|
||||||
db.fixed_ip_create(context.get_admin_context(),
|
|
||||||
{'network_id': self.network['id'],
|
|
||||||
'address': address,
|
|
||||||
'reserved': reserved})
|
|
||||||
self.commands = nova_manage.FixedIpCommands()
|
self.commands = nova_manage.FixedIpCommands()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
db.network_delete_safe(context.get_admin_context(), self.network['id'])
|
|
||||||
super(FixedIpCommandsTestCase, self).tearDown()
|
super(FixedIpCommandsTestCase, self).tearDown()
|
||||||
|
self.stubs.UnsetAll()
|
||||||
|
|
||||||
def test_reserve(self):
|
def test_reserve(self):
|
||||||
self.commands.reserve('10.0.0.100')
|
self.commands.reserve('192.168.0.100')
|
||||||
address = db.fixed_ip_get_by_address(context.get_admin_context(),
|
address = db.fixed_ip_get_by_address(context.get_admin_context(),
|
||||||
'10.0.0.100')
|
'192.168.0.100')
|
||||||
self.assertEqual(address['reserved'], True)
|
self.assertEqual(address['reserved'], True)
|
||||||
|
|
||||||
def test_unreserve(self):
|
def test_unreserve(self):
|
||||||
db.fixed_ip_update(context.get_admin_context(), '10.0.0.100',
|
self.commands.unreserve('192.168.0.100')
|
||||||
{'reserved': True})
|
|
||||||
self.commands.unreserve('10.0.0.100')
|
|
||||||
address = db.fixed_ip_get_by_address(context.get_admin_context(),
|
address = db.fixed_ip_get_by_address(context.get_admin_context(),
|
||||||
'10.0.0.100')
|
'192.168.0.100')
|
||||||
self.assertEqual(address['reserved'], False)
|
self.assertEqual(address['reserved'], False)
|
||||||
|
|
|
@ -384,3 +384,13 @@ class ToPrimitiveTestCase(test.TestCase):
|
||||||
def test_typeerror(self):
|
def test_typeerror(self):
|
||||||
x = bytearray # Class, not instance
|
x = bytearray # Class, not instance
|
||||||
self.assertEquals(utils.to_primitive(x), u"<type 'bytearray'>")
|
self.assertEquals(utils.to_primitive(x), u"<type 'bytearray'>")
|
||||||
|
|
||||||
|
def test_nasties(self):
|
||||||
|
def foo():
|
||||||
|
pass
|
||||||
|
x = [datetime, foo, dir]
|
||||||
|
ret = utils.to_primitive(x)
|
||||||
|
self.assertEquals(len(ret), 3)
|
||||||
|
self.assertTrue(ret[0].startswith(u"<module 'datetime' from "))
|
||||||
|
self.assertTrue(ret[1].startswith(u'<function foo at 0x'))
|
||||||
|
self.assertEquals(ret[2], u'<built-in function dir>')
|
||||||
|
|
|
@ -295,7 +295,7 @@ EASIER_PASSWORD_SYMBOLS = ('23456789' # Removed: 0, 1
|
||||||
|
|
||||||
def usage_from_instance(instance_ref, **kw):
|
def usage_from_instance(instance_ref, **kw):
|
||||||
usage_info = dict(
|
usage_info = dict(
|
||||||
tenant_id=instance_ref['project_id'],
|
project_id=instance_ref['project_id'],
|
||||||
user_id=instance_ref['user_id'],
|
user_id=instance_ref['user_id'],
|
||||||
instance_id=instance_ref['id'],
|
instance_id=instance_ref['id'],
|
||||||
instance_type=instance_ref['instance_type']['name'],
|
instance_type=instance_ref['instance_type']['name'],
|
||||||
|
@ -547,11 +547,17 @@ def to_primitive(value, convert_instances=False, level=0):
|
||||||
Therefore, convert_instances=True is lossy ... be aware.
|
Therefore, convert_instances=True is lossy ... be aware.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if inspect.isclass(value):
|
nasty = [inspect.ismodule, inspect.isclass, inspect.ismethod,
|
||||||
return unicode(value)
|
inspect.isfunction, inspect.isgeneratorfunction,
|
||||||
|
inspect.isgenerator, inspect.istraceback, inspect.isframe,
|
||||||
|
inspect.iscode, inspect.isbuiltin, inspect.isroutine,
|
||||||
|
inspect.isabstract]
|
||||||
|
for test in nasty:
|
||||||
|
if test(value):
|
||||||
|
return unicode(value)
|
||||||
|
|
||||||
if level > 3:
|
if level > 3:
|
||||||
return []
|
return '?'
|
||||||
|
|
||||||
# The try block may not be necessary after the class check above,
|
# The try block may not be necessary after the class check above,
|
||||||
# but just in case ...
|
# but just in case ...
|
||||||
|
|
Loading…
Reference in New Issue