Check that server exists when interacting with /v1.1/servers/<id>/meta resource

This commit is contained in:
Brian Waldon 2011-06-20 01:47:20 +00:00 committed by Tarmac
commit c2a8d0f1e2
3 changed files with 99 additions and 10 deletions

View File

@ -18,9 +18,10 @@
from webob import exc from webob import exc
from nova import compute from nova import compute
from nova import quota
from nova.api.openstack import faults from nova.api.openstack import faults
from nova.api.openstack import wsgi from nova.api.openstack import wsgi
from nova import exception
from nova import quota
class Controller(object): class Controller(object):
@ -45,7 +46,11 @@ class Controller(object):
def index(self, req, server_id): def index(self, req, server_id):
""" Returns the list of metadata for a given instance """ """ Returns the list of metadata for a given instance """
context = req.environ['nova.context'] context = req.environ['nova.context']
return self._get_metadata(context, server_id) try:
return self._get_metadata(context, server_id)
except exception.InstanceNotFound:
msg = _('Server %(server_id)s does not exist') % locals()
raise exc.HTTPNotFound(explanation=msg)
def create(self, req, server_id, body): def create(self, req, server_id, body):
self._check_body(body) self._check_body(body)
@ -55,8 +60,13 @@ class Controller(object):
self.compute_api.update_or_create_instance_metadata(context, self.compute_api.update_or_create_instance_metadata(context,
server_id, server_id,
metadata) metadata)
except exception.InstanceNotFound:
msg = _('Server %(server_id)s does not exist') % locals()
raise exc.HTTPNotFound(explanation=msg)
except quota.QuotaError as error: except quota.QuotaError as error:
self._handle_quota_error(error) self._handle_quota_error(error)
return body return body
def update(self, req, server_id, id, body): def update(self, req, server_id, id, body):
@ -72,6 +82,10 @@ class Controller(object):
self.compute_api.update_or_create_instance_metadata(context, self.compute_api.update_or_create_instance_metadata(context,
server_id, server_id,
body) body)
except exception.InstanceNotFound:
msg = _('Server %(server_id)s does not exist') % locals()
raise exc.HTTPNotFound(explanation=msg)
except quota.QuotaError as error: except quota.QuotaError as error:
self._handle_quota_error(error) self._handle_quota_error(error)
@ -80,16 +94,26 @@ class Controller(object):
def show(self, req, server_id, id): def show(self, req, server_id, id):
""" Return a single metadata item """ """ Return a single metadata item """
context = req.environ['nova.context'] context = req.environ['nova.context']
data = self._get_metadata(context, server_id) try:
if id in data['metadata']: data = self._get_metadata(context, server_id)
except exception.InstanceNotFound:
msg = _('Server %(server_id)s does not exist') % locals()
raise exc.HTTPNotFound(explanation=msg)
try:
return {id: data['metadata'][id]} return {id: data['metadata'][id]}
else: except KeyError:
return faults.Fault(exc.HTTPNotFound()) msg = _("metadata item %s was not found" % (id))
raise exc.HTTPNotFound(explanation=msg)
def delete(self, req, server_id, id): def delete(self, req, server_id, id):
""" Deletes an existing metadata """ """ Deletes an existing metadata """
context = req.environ['nova.context'] context = req.environ['nova.context']
self.compute_api.delete_instance_metadata(context, server_id, id) try:
self.compute_api.delete_instance_metadata(context, server_id, id)
except exception.InstanceNotFound:
msg = _('Server %(server_id)s does not exist') % locals()
raise exc.HTTPNotFound(explanation=msg)
def _handle_quota_error(self, error): def _handle_quota_error(self, error):
"""Reraise quota errors as api-specific http exceptions.""" """Reraise quota errors as api-specific http exceptions."""

View File

@ -18,7 +18,7 @@
""" """
Implementation of SQLAlchemy backend. Implementation of SQLAlchemy backend.
""" """
import traceback
import warnings import warnings
from nova import db from nova import db
@ -2694,7 +2694,17 @@ def zone_get_all(context):
#################### ####################
def require_instance_exists(func):
def new_func(context, instance_id, *args, **kwargs):
db.api.instance_get(context, instance_id)
return func(context, instance_id, *args, **kwargs)
new_func.__name__ = func.__name__
return new_func
@require_context @require_context
@require_instance_exists
def instance_metadata_get(context, instance_id): def instance_metadata_get(context, instance_id):
session = get_session() session = get_session()
@ -2710,6 +2720,7 @@ def instance_metadata_get(context, instance_id):
@require_context @require_context
@require_instance_exists
def instance_metadata_delete(context, instance_id, key): def instance_metadata_delete(context, instance_id, key):
session = get_session() session = get_session()
session.query(models.InstanceMetadata).\ session.query(models.InstanceMetadata).\
@ -2722,6 +2733,7 @@ def instance_metadata_delete(context, instance_id, key):
@require_context @require_context
@require_instance_exists
def instance_metadata_delete_all(context, instance_id): def instance_metadata_delete_all(context, instance_id):
session = get_session() session = get_session()
session.query(models.InstanceMetadata).\ session.query(models.InstanceMetadata).\
@ -2733,6 +2745,7 @@ def instance_metadata_delete_all(context, instance_id):
@require_context @require_context
@require_instance_exists
def instance_metadata_get_item(context, instance_id, key): def instance_metadata_get_item(context, instance_id, key):
session = get_session() session = get_session()
@ -2749,6 +2762,7 @@ def instance_metadata_get_item(context, instance_id, key):
@require_context @require_context
@require_instance_exists
def instance_metadata_update_or_create(context, instance_id, metadata): def instance_metadata_update_or_create(context, instance_id, metadata):
session = get_session() session = get_session()

View File

@ -21,6 +21,7 @@ import unittest
import webob import webob
from nova import exception
from nova import flags from nova import flags
from nova.api import openstack from nova.api import openstack
from nova.tests.api.openstack import fakes from nova.tests.api.openstack import fakes
@ -67,6 +68,14 @@ def stub_max_server_metadata():
return metadata return metadata
def return_server(context, server_id):
return {'id': server_id}
def return_server_nonexistant(context, server_id):
raise exception.InstanceNotFound()
class ServerMetaDataTest(unittest.TestCase): class ServerMetaDataTest(unittest.TestCase):
def setUp(self): def setUp(self):
@ -76,6 +85,7 @@ class ServerMetaDataTest(unittest.TestCase):
fakes.FakeAuthDatabase.data = {} fakes.FakeAuthDatabase.data = {}
fakes.stub_out_auth(self.stubs) fakes.stub_out_auth(self.stubs)
fakes.stub_out_key_pair_funcs(self.stubs) fakes.stub_out_key_pair_funcs(self.stubs)
self.stubs.Set(nova.db.api, 'instance_get', return_server)
def tearDown(self): def tearDown(self):
self.stubs.UnsetAll() self.stubs.UnsetAll()
@ -92,6 +102,13 @@ class ServerMetaDataTest(unittest.TestCase):
self.assertEqual('application/json', res.headers['Content-Type']) self.assertEqual('application/json', res.headers['Content-Type'])
self.assertEqual('value1', res_dict['metadata']['key1']) self.assertEqual('value1', res_dict['metadata']['key1'])
def test_index_nonexistant_server(self):
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
req = webob.Request.blank('/v1.1/servers/1/meta')
req.environ['api.version'] = '1.1'
res = req.get_response(fakes.wsgi_app())
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)
@ -114,13 +131,19 @@ class ServerMetaDataTest(unittest.TestCase):
self.assertEqual('application/json', res.headers['Content-Type']) self.assertEqual('application/json', res.headers['Content-Type'])
self.assertEqual('value5', res_dict['key5']) self.assertEqual('value5', res_dict['key5'])
def test_show_nonexistant_server(self):
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
req = webob.Request.blank('/v1.1/servers/1/meta/key5')
req.environ['api.version'] = '1.1'
res = req.get_response(fakes.wsgi_app())
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/meta/key6') req = webob.Request.blank('/v1.1/servers/1/meta/key6')
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())
res_dict = json.loads(res.body)
self.assertEqual(404, res.status_int) self.assertEqual(404, res.status_int)
def test_delete(self): def test_delete(self):
@ -132,6 +155,14 @@ class ServerMetaDataTest(unittest.TestCase):
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)
def test_delete_nonexistant_server(self):
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
req = webob.Request.blank('/v1.1/servers/1/meta/key5')
req.environ['api.version'] = '1.1'
req.method = 'DELETE'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(404, res.status_int)
def test_create(self): def test_create(self):
self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
return_create_instance_metadata) return_create_instance_metadata)
@ -141,8 +172,8 @@ class ServerMetaDataTest(unittest.TestCase):
req.body = '{"metadata": {"key1": "value1"}}' req.body = '{"metadata": {"key1": "value1"}}'
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())
res_dict = json.loads(res.body)
self.assertEqual(200, res.status_int) self.assertEqual(200, res.status_int)
res_dict = json.loads(res.body)
self.assertEqual('application/json', res.headers['Content-Type']) self.assertEqual('application/json', res.headers['Content-Type'])
self.assertEqual('value1', res_dict['metadata']['key1']) self.assertEqual('value1', res_dict['metadata']['key1'])
@ -156,6 +187,16 @@ class ServerMetaDataTest(unittest.TestCase):
res = req.get_response(fakes.wsgi_app()) res = req.get_response(fakes.wsgi_app())
self.assertEqual(400, res.status_int) self.assertEqual(400, res.status_int)
def test_create_nonexistant_server(self):
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
req = webob.Request.blank('/v1.1/servers/100/meta')
req.environ['api.version'] = '1.1'
req.method = 'POST'
req.body = '{"metadata": {"key1": "value1"}}'
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(404, res.status_int)
def test_update_item(self): def test_update_item(self):
self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
return_create_instance_metadata) return_create_instance_metadata)
@ -170,6 +211,16 @@ class ServerMetaDataTest(unittest.TestCase):
res_dict = json.loads(res.body) res_dict = json.loads(res.body)
self.assertEqual('value1', res_dict['key1']) self.assertEqual('value1', res_dict['key1'])
def test_update_item_nonexistant_server(self):
self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant)
req = webob.Request.blank('/v1.1/servers/asdf/100/key1')
req.environ['api.version'] = '1.1'
req.method = 'PUT'
req.body = '{"key1": "value1"}'
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(404, res.status_int)
def test_update_item_empty_body(self): def test_update_item_empty_body(self):
self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
return_create_instance_metadata) return_create_instance_metadata)