Created simple test case for server creation, so that we can have something to attach to...
This commit is contained in:
parent
143a8387fc
commit
694c2cfd2a
@ -16,3 +16,6 @@ nova/vcsversion.py
|
||||
*.DS_Store
|
||||
.project
|
||||
.pydevproject
|
||||
clean.sqlite
|
||||
run_tests.log
|
||||
tests.sqlite
|
||||
|
109
nova/image/fake.py
Normal file
109
nova/image/fake.py
Normal file
@ -0,0 +1,109 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2011 Justin Santa Barbara
|
||||
# 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.
|
||||
"""Implementation of an fake image service"""
|
||||
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
from nova import log as logging
|
||||
from nova.image import service
|
||||
|
||||
|
||||
LOG = logging.getLogger('nova.image.fake')
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
|
||||
|
||||
class MockImageService(service.BaseImageService):
|
||||
"""Mock (fake) image service for unit testing"""
|
||||
|
||||
def __init__(self):
|
||||
self.images = {}
|
||||
# NOTE(justinsb): The OpenStack API can't upload an image???
|
||||
# So, make sure we've got one..
|
||||
image = {'id': '123456',
|
||||
'status': 'active',
|
||||
'type': 'machine',
|
||||
'disk_format': 'ami',
|
||||
'properties': {'kernel_id': FLAGS.null_kernel,
|
||||
'ramdisk_id': FLAGS.null_kernel,
|
||||
}
|
||||
}
|
||||
self.create(None, image)
|
||||
super(MockImageService, self).__init__()
|
||||
|
||||
def index(self, context):
|
||||
"""Returns list of images"""
|
||||
return self.images.values()
|
||||
|
||||
def detail(self, context):
|
||||
"""Return list of detailed image information"""
|
||||
return self.images.values()
|
||||
|
||||
def show(self, context, image_id):
|
||||
"""
|
||||
Returns a dict containing image data for the given opaque image id.
|
||||
"""
|
||||
image_id = int(image_id)
|
||||
image = self.images.get(image_id)
|
||||
if image:
|
||||
return image
|
||||
LOG.warn("Unable to find image id %s. Have images: %s",
|
||||
image_id, self.images)
|
||||
raise exception.NotFound
|
||||
|
||||
def create(self, context, data):
|
||||
"""
|
||||
Store the image data and return the new image id.
|
||||
|
||||
:raises AlreadyExists if the image already exist.
|
||||
|
||||
"""
|
||||
image_id = int(data['id'])
|
||||
if self.images.get(image_id):
|
||||
#TODO(justinsb): Where is this AlreadyExists exception??
|
||||
raise exception.Error("AlreadyExists")
|
||||
|
||||
self.images[image_id] = data
|
||||
|
||||
def update(self, context, image_id, data):
|
||||
"""Replace the contents of the given image with the new data.
|
||||
|
||||
:raises NotFound if the image does not exist.
|
||||
|
||||
"""
|
||||
image_id = int(image_id)
|
||||
if not self.images.get(image_id):
|
||||
raise exception.NotFound
|
||||
self.images[image_id] = data
|
||||
|
||||
def delete(self, context, image_id):
|
||||
"""
|
||||
Delete the given image.
|
||||
|
||||
:raises NotFound if the image does not exist.
|
||||
|
||||
"""
|
||||
image_id = int(image_id)
|
||||
removed = self.images.pop(image_id, None)
|
||||
if not removed:
|
||||
raise exception.NotFound
|
||||
|
||||
def delete_all(self):
|
||||
"""
|
||||
Clears out all images
|
||||
"""
|
||||
self.images.clear()
|
@ -73,6 +73,28 @@ class TestUser(object):
|
||||
self.secret,
|
||||
self.auth_url)
|
||||
|
||||
def get_unused_server_name(self):
|
||||
servers = self.openstack_api.get_servers()
|
||||
server_names = [server['name'] for server in servers]
|
||||
return generate_new_element(server_names, 'server')
|
||||
|
||||
def get_invalid_image(self):
|
||||
images = self.openstack_api.get_images()
|
||||
image_ids = [image['id'] for image in images]
|
||||
return generate_new_element(image_ids, '', numeric=True)
|
||||
|
||||
def get_valid_image(self, create=False):
|
||||
images = self.openstack_api.get_images()
|
||||
if create and not images:
|
||||
# TODO(justinsb): No way to create an image through API???
|
||||
#created_image = self.openstack_api.post_image(image)
|
||||
#images.append(created_image)
|
||||
raise exception.Error("No way to create an image through API??")
|
||||
|
||||
if images:
|
||||
return images[0]
|
||||
return None
|
||||
|
||||
|
||||
class IntegratedUnitTestContext(object):
|
||||
__INSTANCE = None
|
||||
|
218
nova/tests/integrated/test_servers.py
Normal file
218
nova/tests/integrated/test_servers.py
Normal file
@ -0,0 +1,218 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2011 Justin Santa Barbara
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
import unittest
|
||||
|
||||
from nova import flags
|
||||
from nova import test
|
||||
from nova.log import logging
|
||||
from nova.tests.integrated import integrated_helpers
|
||||
from nova.tests.integrated.api import client
|
||||
|
||||
|
||||
LOG = logging.getLogger('nova.tests.integrated')
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
FLAGS.verbose = True
|
||||
|
||||
|
||||
class ServersTest(test.TestCase):
|
||||
def setUp(self):
|
||||
super(ServersTest, self).setUp()
|
||||
|
||||
self.flags(image_service='nova.image.fake.MockImageService')
|
||||
|
||||
context = integrated_helpers.IntegratedUnitTestContext.startup()
|
||||
self.user = context.test_user
|
||||
self.api = self.user.openstack_api
|
||||
|
||||
def tearDown(self):
|
||||
integrated_helpers.IntegratedUnitTestContext.shutdown()
|
||||
super(ServersTest, self).tearDown()
|
||||
|
||||
def test_get_servers(self):
|
||||
"""Simple check that listing servers works."""
|
||||
servers = self.api.get_servers()
|
||||
for server in servers:
|
||||
LOG.debug("server: %s" % server)
|
||||
|
||||
def test_create_and_delete_server(self):
|
||||
"""Creates and deletes a server"""
|
||||
|
||||
# Create server
|
||||
|
||||
# Build the server data gradually, checking errors along the way
|
||||
server = {}
|
||||
good_server = self._build_minimal_create_server_request()
|
||||
|
||||
post = {'server': server}
|
||||
|
||||
# Without an imageId, this throws 500.
|
||||
# TODO(justinsb): Check whatever the spec says should be thrown here
|
||||
self.assertRaises(client.OpenStackApiException,
|
||||
self.api.post_server, post)
|
||||
|
||||
# With an invalid imageId, this throws 500.
|
||||
server['imageId'] = self.user.get_invalid_image()
|
||||
# TODO(justinsb): Check whatever the spec says should be thrown here
|
||||
self.assertRaises(client.OpenStackApiException,
|
||||
self.api.post_server, post)
|
||||
|
||||
# Add a valid imageId
|
||||
server['imageId'] = good_server['imageId']
|
||||
|
||||
# Without flavorId, this throws 500
|
||||
# TODO(justinsb): Check whatever the spec says should be thrown here
|
||||
self.assertRaises(client.OpenStackApiException,
|
||||
self.api.post_server, post)
|
||||
|
||||
# Set a valid flavorId
|
||||
server['flavorId'] = good_server['flavorId']
|
||||
|
||||
# Without a name, this throws 500
|
||||
# TODO(justinsb): Check whatever the spec says should be thrown here
|
||||
self.assertRaises(client.OpenStackApiException,
|
||||
self.api.post_server, post)
|
||||
|
||||
# Set a valid server name
|
||||
server['name'] = good_server['name']
|
||||
|
||||
created_server = self.api.post_server(post)
|
||||
LOG.debug("created_server: %s" % created_server)
|
||||
self.assertTrue(created_server['id'])
|
||||
created_server_id = created_server['id']
|
||||
|
||||
# Check it's there
|
||||
found_server = self.api.get_server(created_server_id)
|
||||
self.assertEqual(created_server_id, found_server['id'])
|
||||
|
||||
# It should also be in the all-servers list
|
||||
servers = self.api.get_servers()
|
||||
server_ids = [server['id'] for server in servers]
|
||||
self.assertTrue(created_server_id in server_ids)
|
||||
|
||||
# Wait (briefly) for creation
|
||||
retries = 0
|
||||
while found_server['status'] == 'build':
|
||||
LOG.debug("found server: %s" % found_server)
|
||||
time.sleep(1)
|
||||
found_server = self.api.get_server(created_server_id)
|
||||
retries = retries + 1
|
||||
if retries > 5:
|
||||
break
|
||||
|
||||
# It should be available...
|
||||
# TODO(justinsb): Mock doesn't yet do this...
|
||||
#self.assertEqual('available', found_server['status'])
|
||||
|
||||
self._delete_server(created_server_id)
|
||||
|
||||
def _delete_server(self, server_id):
|
||||
# Delete the server
|
||||
self.api.delete_server(server_id)
|
||||
|
||||
# Wait (briefly) for deletion
|
||||
for _retries in range(5):
|
||||
try:
|
||||
found_server = self.api.get_server(server_id)
|
||||
except client.OpenStackApiNotFoundException:
|
||||
found_server = None
|
||||
LOG.debug("Got 404, proceeding")
|
||||
break
|
||||
|
||||
LOG.debug("Found_server=%s" % found_server)
|
||||
|
||||
# TODO(justinsb): Mock doesn't yet do accurate state changes
|
||||
#if found_server['status'] != 'deleting':
|
||||
# break
|
||||
time.sleep(1)
|
||||
|
||||
# Should be gone
|
||||
self.assertFalse(found_server)
|
||||
|
||||
def _build_minimal_create_server_request(self):
|
||||
server = {}
|
||||
|
||||
image = self.user.get_valid_image(create=True)
|
||||
image_id = image['id']
|
||||
|
||||
#TODO(justinsb): This is FUBAR
|
||||
image_id = abs(hash(image_id))
|
||||
|
||||
# We now have a valid imageId
|
||||
server['imageId'] = image_id
|
||||
|
||||
# Set a valid flavorId
|
||||
flavor = self.api.get_flavors()[0]
|
||||
LOG.debug("Using flavor: %s" % flavor)
|
||||
server['flavorId'] = flavor['id']
|
||||
|
||||
# Set a valid server name
|
||||
server_name = self.user.get_unused_server_name()
|
||||
server['name'] = server_name
|
||||
|
||||
return server
|
||||
|
||||
# TODO(justinsb): Enable this unit test when the metadata bug is fixed
|
||||
# def test_create_server_with_metadata(self):
|
||||
# """Creates a server with metadata"""
|
||||
#
|
||||
# # Build the server data gradually, checking errors along the way
|
||||
# server = self._build_minimal_create_server_request()
|
||||
#
|
||||
# for metadata_count in range(30):
|
||||
# metadata = {}
|
||||
# for i in range(metadata_count):
|
||||
# metadata['key_%s' % i] = 'value_%s' % i
|
||||
# server['metadata'] = metadata
|
||||
#
|
||||
# post = {'server': server}
|
||||
# created_server = self.api.post_server(post)
|
||||
# LOG.debug("created_server: %s" % created_server)
|
||||
# self.assertTrue(created_server['id'])
|
||||
# created_server_id = created_server['id']
|
||||
# # Reenable when bug fixed
|
||||
# # self.assertEqual(metadata, created_server.get('metadata'))
|
||||
#
|
||||
# # Check it's there
|
||||
# found_server = self.api.get_server(created_server_id)
|
||||
# self.assertEqual(created_server_id, found_server['id'])
|
||||
# self.assertEqual(metadata, found_server.get('metadata'))
|
||||
#
|
||||
# # The server should also be in the all-servers details list
|
||||
# servers = self.api.get_servers(detail=True)
|
||||
# server_map = dict((server['id'], server) for server in servers)
|
||||
# found_server = server_map.get(created_server_id)
|
||||
# self.assertTrue(found_server)
|
||||
# # Details do include metadata
|
||||
# self.assertEqual(metadata, found_server.get('metadata'))
|
||||
#
|
||||
# # The server should also be in the all-servers summary list
|
||||
# servers = self.api.get_servers(detail=False)
|
||||
# server_map = dict((server['id'], server) for server in servers)
|
||||
# found_server = server_map.get(created_server_id)
|
||||
# self.assertTrue(found_server)
|
||||
# # Summary should not include metadata
|
||||
# self.assertFalse(found_server.get('metadata'))
|
||||
#
|
||||
# # Cleanup
|
||||
# self._delete_server(created_server_id)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
Loading…
Reference in New Issue
Block a user