glance/tests/unit/test_api.py
2011-01-11 11:04:14 -06:00

342 lines
11 KiB
Python

# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 OpenStack, LLC
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import httplib
import json
import unittest
import stubout
import webob
from glance import server
from glance.common import flags
from glance.registry import server as rserver
from tests import stubs
FLAGS = flags.FLAGS
class TestRegistryAPI(unittest.TestCase):
def setUp(self):
"""Establish a clean test environment"""
self.stubs = stubout.StubOutForTesting()
stubs.stub_out_registry_and_store_server(self.stubs)
stubs.stub_out_registry_db_image_api(self.stubs)
stubs.stub_out_filesystem_backend()
def tearDown(self):
"""Clear the test environment"""
stubs.clean_out_fake_filesystem_backend()
self.stubs.UnsetAll()
def test_get_root(self):
"""Tests that the root registry API returns "index",
which is a list of public images
"""
fixture = {'id': 2,
'name': 'fake image #2'}
req = webob.Request.blank('/')
res = req.get_response(rserver.API())
res_dict = json.loads(res.body)
self.assertEquals(res.status_int, 200)
images = res_dict['images']
self.assertEquals(len(images), 1)
for k, v in fixture.iteritems():
self.assertEquals(v, images[0][k])
def test_get_index(self):
"""Tests that the /images registry API returns list of
public images
"""
fixture = {'id': 2,
'name': 'fake image #2'}
req = webob.Request.blank('/images')
res = req.get_response(rserver.API())
res_dict = json.loads(res.body)
self.assertEquals(res.status_int, 200)
images = res_dict['images']
self.assertEquals(len(images), 1)
for k, v in fixture.iteritems():
self.assertEquals(v, images[0][k])
def test_get_details(self):
"""Tests that the /images/detail registry API returns
a mapping containing a list of detailed image information
"""
fixture = {'id': 2,
'name': 'fake image #2',
'is_public': True,
'type': 'kernel',
'status': 'active'
}
req = webob.Request.blank('/images/detail')
res = req.get_response(rserver.API())
res_dict = json.loads(res.body)
self.assertEquals(res.status_int, 200)
images = res_dict['images']
self.assertEquals(len(images), 1)
for k, v in fixture.iteritems():
self.assertEquals(v, images[0][k])
def test_create_image(self):
"""Tests that the /images POST registry API creates the image"""
fixture = {'name': 'fake public image',
'is_public': True,
'type': 'kernel'
}
req = webob.Request.blank('/images')
req.method = 'POST'
req.body = json.dumps(dict(image=fixture))
res = req.get_response(rserver.API())
self.assertEquals(res.status_int, 200)
res_dict = json.loads(res.body)
for k, v in fixture.iteritems():
self.assertEquals(v, res_dict['image'][k])
# Test ID auto-assigned properly
self.assertEquals(3, res_dict['image']['id'])
# Test status was updated properly
self.assertEquals('active', res_dict['image']['status'])
def test_create_image_with_bad_status(self):
"""Tests proper exception is raised if a bad status is set"""
fixture = {'id': 3,
'name': 'fake public image',
'is_public': True,
'type': 'kernel',
'status': 'bad status'
}
req = webob.Request.blank('/images')
req.method = 'POST'
req.body = json.dumps(dict(image=fixture))
# TODO(jaypipes): Port Nova's Fault infrastructure
# over to Glance to support exception catching into
# standard HTTP errors.
res = req.get_response(rserver.API())
self.assertEquals(res.status_int, webob.exc.HTTPBadRequest.code)
def test_update_image(self):
"""Tests that the /images PUT registry API updates the image"""
fixture = {'name': 'fake public image #2',
'type': 'ramdisk'
}
req = webob.Request.blank('/images/2')
req.method = 'PUT'
req.body = json.dumps(dict(image=fixture))
res = req.get_response(rserver.API())
self.assertEquals(res.status_int, 200)
res_dict = json.loads(res.body)
for k, v in fixture.iteritems():
self.assertEquals(v, res_dict['image'][k])
def test_update_image_not_existing(self):
"""Tests proper exception is raised if attempt to update non-existing
image"""
fixture = {'id': 3,
'name': 'fake public image',
'is_public': True,
'type': 'kernel',
'status': 'bad status'
}
req = webob.Request.blank('/images/3')
req.method = 'PUT'
req.body = json.dumps(dict(image=fixture))
# TODO(jaypipes): Port Nova's Fault infrastructure
# over to Glance to support exception catching into
# standard HTTP errors.
res = req.get_response(rserver.API())
self.assertEquals(res.status_int,
webob.exc.HTTPNotFound.code)
def test_delete_image(self):
"""Tests that the /images DELETE registry API deletes the image"""
# Grab the original number of images
req = webob.Request.blank('/images')
res = req.get_response(rserver.API())
res_dict = json.loads(res.body)
self.assertEquals(res.status_int, 200)
orig_num_images = len(res_dict['images'])
# Delete image #2
req = webob.Request.blank('/images/2')
req.method = 'DELETE'
res = req.get_response(rserver.API())
self.assertEquals(res.status_int, 200)
# Verify one less image
req = webob.Request.blank('/images')
res = req.get_response(rserver.API())
res_dict = json.loads(res.body)
self.assertEquals(res.status_int, 200)
new_num_images = len(res_dict['images'])
self.assertEquals(new_num_images, orig_num_images - 1)
def test_delete_image_not_existing(self):
"""Tests proper exception is raised if attempt to delete non-existing
image"""
req = webob.Request.blank('/images/3')
req.method = 'DELETE'
# TODO(jaypipes): Port Nova's Fault infrastructure
# over to Glance to support exception catching into
# standard HTTP errors.
res = req.get_response(rserver.API())
self.assertEquals(res.status_int,
webob.exc.HTTPNotFound.code)
class TestGlanceAPI(unittest.TestCase):
def setUp(self):
"""Establish a clean test environment"""
self.stubs = stubout.StubOutForTesting()
stubs.stub_out_registry_and_store_server(self.stubs)
stubs.stub_out_registry_db_image_api(self.stubs)
stubs.stub_out_filesystem_backend()
self.orig_filesystem_store_datadir = FLAGS.filesystem_store_datadir
FLAGS.filesystem_store_datadir = stubs.FAKE_FILESYSTEM_ROOTDIR
def tearDown(self):
"""Clear the test environment"""
FLAGS.filesystem_store_datadir = self.orig_filesystem_store_datadir
stubs.clean_out_fake_filesystem_backend()
self.stubs.UnsetAll()
def test_add_image_no_location_no_image_as_body(self):
"""Tests creates a queued image for no body and no loc header"""
fixture_headers = {'x-image-meta-store': 'file',
'x-image-meta-name': 'fake image #3'}
req = webob.Request.blank("/images")
req.method = 'POST'
for k, v in fixture_headers.iteritems():
req.headers[k] = v
res = req.get_response(server.API())
self.assertEquals(res.status_int, httplib.OK)
res_body = json.loads(res.body)['image']
self.assertEquals('queued', res_body['status'])
def test_add_image_bad_store(self):
"""Tests raises BadRequest for invalid store header"""
fixture_headers = {'x-image-meta-store': 'bad',
'x-image-meta-name': 'fake image #3'}
req = webob.Request.blank("/images")
req.method = 'POST'
for k, v in fixture_headers.iteritems():
req.headers[k] = v
req.headers['Content-Type'] = 'application/octet-stream'
req.body = "chunk00000remainder"
res = req.get_response(server.API())
self.assertEquals(res.status_int, webob.exc.HTTPBadRequest.code)
def test_add_image_basic_file_store(self):
"""Tests raises BadRequest for invalid store header"""
fixture_headers = {'x-image-meta-store': 'file',
'x-image-meta-name': 'fake image #3'}
req = webob.Request.blank("/images")
req.method = 'POST'
for k, v in fixture_headers.iteritems():
req.headers[k] = v
req.headers['Content-Type'] = 'application/octet-stream'
req.body = "chunk00000remainder"
res = req.get_response(server.API())
self.assertEquals(res.status_int, 200)
res_body = json.loads(res.body)['image']
self.assertEquals(res_body['location'],
'file:///tmp/glance-tests/3')
def test_image_meta(self):
"""Test for HEAD /images/<ID>"""
expected_headers = {'x-image-meta-id': 2,
'x-image-meta-name': 'fake image #2'}
req = webob.Request.blank("/images/2")
req.method = 'HEAD'
res = req.get_response(server.API())
self.assertEquals(res.status_int, 200)
for key, value in expected_headers.iteritems():
self.assertEquals(value, res.headers[key])
def test_show_image_basic(self):
req = webob.Request.blank("/images/2")
res = req.get_response(server.API())
self.assertEqual('chunk00000remainder', res.body)
def test_show_non_exists_image(self):
req = webob.Request.blank("/images/42")
res = req.get_response(server.API())
self.assertEquals(res.status_int, webob.exc.HTTPNotFound.code)
def test_delete_image(self):
req = webob.Request.blank("/images/2")
req.method = 'DELETE'
res = req.get_response(server.API())
self.assertEquals(res.status_int, 200)
req = webob.Request.blank("/images/2")
req.method = 'GET'
res = req.get_response(server.API())
self.assertEquals(res.status_int, webob.exc.HTTPNotFound.code,
res.body)
def test_delete_non_exists_image(self):
req = webob.Request.blank("/images/42")
req.method = 'DELETE'
res = req.get_response(server.API())
self.assertEquals(res.status_int, webob.exc.HTTPNotFound.code)