summaryrefslogtreecommitdiffstats
path: root/nova/tests
diff options
context:
space:
mode:
authorChris Behrens <cbehrens@codestud.com>2011-07-07 05:56:15 -0700
committerChris Behrens <cbehrens@codestud.com>2011-07-07 05:56:15 -0700
commite817896c7aaf43822cf363a48fac60f013a5ecb0 (patch)
tree0035dcc42ce5b2737d0a424975980cad4e8e0b77 /nova/tests
parentace9aa5d91d839f66998c39a977857b7a7c466a4 (diff)
parent44d4994eadc7413e27ebe60d7880278fc0365b6f (diff)
merged trunk
Diffstat (limited to 'nova/tests')
-rw-r--r--nova/tests/api/openstack/test_extensions.py23
-rw-r--r--nova/tests/api/openstack/test_server_actions.py44
-rw-r--r--nova/tests/api/openstack/test_server_metadata.py62
-rw-r--r--nova/tests/api/openstack/test_servers.py26
-rw-r--r--nova/tests/image/test_glance.py36
-rw-r--r--nova/tests/test_api.py36
-rw-r--r--nova/tests/test_block_device.py87
-rw-r--r--nova/tests/test_cloud.py157
-rw-r--r--nova/tests/test_compute.py40
-rw-r--r--nova/tests/test_libvirt.py37
-rw-r--r--nova/tests/test_metadata.py1
-rw-r--r--nova/tests/test_virt.py83
12 files changed, 568 insertions, 64 deletions
diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py
index 409fa0e71..49f0ea8b3 100644
--- a/nova/tests/api/openstack/test_extensions.py
+++ b/nova/tests/api/openstack/test_extensions.py
@@ -18,7 +18,7 @@
import json
import os.path
import webob
-from xml.etree import ElementTree
+from lxml import etree
from nova import context
from nova import test
@@ -26,6 +26,7 @@ from nova.api import openstack
from nova.api.openstack import extensions
from nova.api.openstack import flavors
from nova.api.openstack import wsgi
+from nova.api.openstack import xmlutil
from nova.tests.api.openstack import fakes
NS = "{http://docs.openstack.org/compute/api/v1.1}"
@@ -138,7 +139,7 @@ class ExtensionControllerTest(test.TestCase):
self.assertEqual(200, response.status_int)
print response.body
- root = ElementTree.XML(response.body)
+ root = etree.XML(response.body)
self.assertEqual(root.tag.split('extensions')[0], NS)
# Make sure we have all the extensions.
@@ -154,6 +155,8 @@ class ExtensionControllerTest(test.TestCase):
self.assertEqual(fox_ext.findtext('{0}description'.format(NS)),
'The Fox In Socks Extension')
+ xmlutil.validate_schema(root, 'extensions')
+
def test_get_extension_xml(self):
app = openstack.APIRouterV11()
ext_midware = extensions.ExtensionMiddleware(app)
@@ -161,9 +164,10 @@ class ExtensionControllerTest(test.TestCase):
request.accept = "application/xml"
response = request.get_response(ext_midware)
self.assertEqual(200, response.status_int)
- print response.body
+ xml = response.body
+ print xml
- root = ElementTree.XML(response.body)
+ root = etree.XML(xml)
self.assertEqual(root.tag.split('extension')[0], NS)
self.assertEqual(root.get('alias'), 'FOXNSOX')
self.assertEqual(root.get('name'), 'Fox In Socks')
@@ -173,6 +177,8 @@ class ExtensionControllerTest(test.TestCase):
self.assertEqual(root.findtext('{0}description'.format(NS)),
'The Fox In Socks Extension')
+ xmlutil.validate_schema(root, 'extension')
+
class ResourceExtensionTest(test.TestCase):
@@ -352,7 +358,8 @@ class ExtensionsXMLSerializerTest(test.TestCase):
}
xml = serializer.serialize(data, 'show')
- root = ElementTree.XML(xml)
+ print xml
+ root = etree.XML(xml)
ext_dict = data['extension']
self.assertEqual(root.findtext('{0}description'.format(NS)),
ext_dict['description'])
@@ -366,6 +373,8 @@ class ExtensionsXMLSerializerTest(test.TestCase):
for key, value in link.items():
self.assertEqual(link_nodes[i].get(key), value)
+ xmlutil.validate_schema(root, 'extension')
+
def test_serialize_extensions(self):
serializer = extensions.ExtensionsXMLSerializer()
data = {
@@ -413,7 +422,7 @@ class ExtensionsXMLSerializerTest(test.TestCase):
xml = serializer.serialize(data, 'index')
print xml
- root = ElementTree.XML(xml)
+ root = etree.XML(xml)
ext_elems = root.findall('{0}extension'.format(NS))
self.assertEqual(len(ext_elems), 2)
for i, ext_elem in enumerate(ext_elems):
@@ -429,3 +438,5 @@ class ExtensionsXMLSerializerTest(test.TestCase):
for i, link in enumerate(ext_dict['links']):
for key, value in link.items():
self.assertEqual(link_nodes[i].get(key), value)
+
+ xmlutil.validate_schema(root, 'extensions')
diff --git a/nova/tests/api/openstack/test_server_actions.py b/nova/tests/api/openstack/test_server_actions.py
index bf18bc1b0..717e11c00 100644
--- a/nova/tests/api/openstack/test_server_actions.py
+++ b/nova/tests/api/openstack/test_server_actions.py
@@ -9,6 +9,7 @@ import webob
from nova import context
from nova import db
from nova import utils
+from nova import flags
from nova.api.openstack import create_instance_helper
from nova.compute import instance_types
from nova.compute import power_state
@@ -18,6 +19,9 @@ from nova.tests.api.openstack import common
from nova.tests.api.openstack import fakes
+FLAGS = flags.FLAGS
+
+
def return_server_by_id(context, id):
return _get_instance()
@@ -370,6 +374,26 @@ class ServerActionsTest(test.TestCase):
self.assertEqual(202, response.status_int)
self.assertTrue(response.headers['Location'])
+ def test_create_backup_with_too_much_metadata(self):
+ self.flags(allow_admin_api=True)
+
+ body = {
+ 'createBackup': {
+ 'name': 'Backup 1',
+ 'backup_type': 'daily',
+ 'rotation': 1,
+ 'metadata': {'123': 'asdf'},
+ },
+ }
+ for num in range(FLAGS.quota_metadata_items + 1):
+ body['createBackup']['metadata']['foo%i' % num] = "bar"
+ req = webob.Request.blank('/v1.0/servers/1/action')
+ req.method = 'POST'
+ req.body = json.dumps(body)
+ req.headers["content-type"] = "application/json"
+ response = req.get_response(fakes.wsgi_app())
+ self.assertEqual(400, response.status_int)
+
def test_create_backup_no_name(self):
"""Name is required for backups"""
self.flags(allow_admin_api=True)
@@ -809,6 +833,22 @@ class ServerActionsTestV11(test.TestCase):
location = response.headers['Location']
self.assertEqual('http://localhost/v1.1/images/123', location)
+ def test_create_image_with_too_much_metadata(self):
+ body = {
+ 'createImage': {
+ 'name': 'Snapshot 1',
+ 'metadata': {},
+ },
+ }
+ for num in range(FLAGS.quota_metadata_items + 1):
+ body['createImage']['metadata']['foo%i' % num] = "bar"
+ req = webob.Request.blank('/v1.1/servers/1/action')
+ req.method = 'POST'
+ req.body = json.dumps(body)
+ req.headers["content-type"] = "application/json"
+ response = req.get_response(fakes.wsgi_app())
+ self.assertEqual(400, response.status_int)
+
def test_create_image_no_name(self):
body = {
'createImage': {},
@@ -943,9 +983,7 @@ class TestServerActionXMLDeserializerV11(test.TestCase):
flavorRef="http://localhost/flavors/3"/>"""
request = self.deserializer.deserialize(serial_request, 'action')
expected = {
- "resize": {
- "flavorRef": "http://localhost/flavors/3"
- },
+ "resize": {"flavorRef": "http://localhost/flavors/3"},
}
self.assertEquals(request['body'], expected)
diff --git a/nova/tests/api/openstack/test_server_metadata.py b/nova/tests/api/openstack/test_server_metadata.py
index 08a6a062a..ec446f0f0 100644
--- a/nova/tests/api/openstack/test_server_metadata.py
+++ b/nova/tests/api/openstack/test_server_metadata.py
@@ -29,11 +29,11 @@ import nova.wsgi
FLAGS = flags.FLAGS
-def return_create_instance_metadata_max(context, server_id, metadata):
+def return_create_instance_metadata_max(context, server_id, metadata, delete):
return stub_max_server_metadata()
-def return_create_instance_metadata(context, server_id, metadata):
+def return_create_instance_metadata(context, server_id, metadata, delete):
return stub_server_metadata()
@@ -202,21 +202,30 @@ class ServerMetaDataTest(test.TestCase):
self.assertEqual(404, res.status_int)
def test_create(self):
- self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
+ self.stubs.Set(nova.db.api, 'instance_metadata_get',
+ return_server_metadata)
+ self.stubs.Set(nova.db.api, 'instance_metadata_update',
return_create_instance_metadata)
req = webob.Request.blank('/v1.1/servers/1/metadata')
req.method = 'POST'
req.content_type = "application/json"
- expected = {"metadata": {"key1": "value1"}}
- req.body = json.dumps(expected)
+ input = {"metadata": {"key9": "value9"}}
+ req.body = json.dumps(input)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(200, res.status_int)
res_dict = json.loads(res.body)
- self.assertEqual(expected, res_dict)
+ input['metadata'].update({
+ "key1": "value1",
+ "key2": "value2",
+ "key3": "value3",
+ })
+ self.assertEqual(input, res_dict)
def test_create_xml(self):
- self.stubs.Set(nova.db.api, "instance_metadata_update_or_create",
+ self.stubs.Set(nova.db.api, 'instance_metadata_get',
+ return_server_metadata)
+ self.stubs.Set(nova.db.api, "instance_metadata_update",
return_create_instance_metadata)
req = webob.Request.blank("/v1.1/servers/1/metadata")
req.method = "POST"
@@ -225,22 +234,29 @@ class ServerMetaDataTest(test.TestCase):
request_metadata = minidom.parseString("""
<metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
- <meta key="key3">value3</meta>
- <meta key="key2">value2</meta>
- <meta key="key1">value1</meta>
+ <meta key="key5">value5</meta>
</metadata>
""".replace(" ", "").replace("\n", ""))
req.body = str(request_metadata.toxml())
response = req.get_response(fakes.wsgi_app())
+ expected_metadata = minidom.parseString("""
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key="key3">value3</meta>
+ <meta key="key2">value2</meta>
+ <meta key="key1">value1</meta>
+ <meta key="key5">value5</meta>
+ </metadata>
+ """.replace(" ", "").replace("\n", ""))
+
self.assertEqual(200, response.status_int)
actual_metadata = minidom.parseString(response.body)
- self.assertEqual(request_metadata.toxml(), actual_metadata.toxml())
+ self.assertEqual(expected_metadata.toxml(), actual_metadata.toxml())
def test_create_empty_body(self):
- self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
+ self.stubs.Set(nova.db.api, 'instance_metadata_update',
return_create_instance_metadata)
req = webob.Request.blank('/v1.1/servers/1/metadata')
req.method = 'POST'
@@ -258,7 +274,7 @@ class ServerMetaDataTest(test.TestCase):
self.assertEqual(404, res.status_int)
def test_update_all(self):
- self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
+ self.stubs.Set(nova.db.api, 'instance_metadata_update',
return_create_instance_metadata)
req = webob.Request.blank('/v1.1/servers/1/metadata')
req.method = 'PUT'
@@ -276,7 +292,7 @@ class ServerMetaDataTest(test.TestCase):
self.assertEqual(expected, res_dict)
def test_update_all_empty_container(self):
- self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
+ self.stubs.Set(nova.db.api, 'instance_metadata_update',
return_create_instance_metadata)
req = webob.Request.blank('/v1.1/servers/1/metadata')
req.method = 'PUT'
@@ -289,7 +305,7 @@ class ServerMetaDataTest(test.TestCase):
self.assertEqual(expected, res_dict)
def test_update_all_malformed_container(self):
- self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
+ self.stubs.Set(nova.db.api, 'instance_metadata_update',
return_create_instance_metadata)
req = webob.Request.blank('/v1.1/servers/1/metadata')
req.method = 'PUT'
@@ -300,7 +316,7 @@ class ServerMetaDataTest(test.TestCase):
self.assertEqual(400, res.status_int)
def test_update_all_malformed_data(self):
- self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
+ self.stubs.Set(nova.db.api, 'instance_metadata_update',
return_create_instance_metadata)
req = webob.Request.blank('/v1.1/servers/1/metadata')
req.method = 'PUT'
@@ -320,7 +336,7 @@ class ServerMetaDataTest(test.TestCase):
self.assertEqual(404, res.status_int)
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',
return_create_instance_metadata)
req = webob.Request.blank('/v1.1/servers/1/metadata/key1')
req.method = 'PUT'
@@ -334,7 +350,7 @@ class ServerMetaDataTest(test.TestCase):
self.assertEqual(expected, res_dict)
def test_update_item_xml(self):
- self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
+ self.stubs.Set(nova.db.api, 'instance_metadata_update',
return_create_instance_metadata)
req = webob.Request.blank('/v1.1/servers/1/metadata/key9')
req.method = 'PUT'
@@ -361,7 +377,7 @@ class ServerMetaDataTest(test.TestCase):
self.assertEqual(404, res.status_int)
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',
return_create_instance_metadata)
req = webob.Request.blank('/v1.1/servers/1/metadata/key1')
req.method = 'PUT'
@@ -370,7 +386,7 @@ class ServerMetaDataTest(test.TestCase):
self.assertEqual(400, res.status_int)
def test_update_item_too_many_keys(self):
- self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
+ self.stubs.Set(nova.db.api, 'instance_metadata_update',
return_create_instance_metadata)
req = webob.Request.blank('/v1.1/servers/1/metadata/key1')
req.method = 'PUT'
@@ -380,7 +396,7 @@ class ServerMetaDataTest(test.TestCase):
self.assertEqual(400, res.status_int)
def test_update_item_body_uri_mismatch(self):
- self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
+ self.stubs.Set(nova.db.api, 'instance_metadata_update',
return_create_instance_metadata)
req = webob.Request.blank('/v1.1/servers/1/metadata/bad')
req.method = 'PUT'
@@ -390,7 +406,7 @@ class ServerMetaDataTest(test.TestCase):
self.assertEqual(400, res.status_int)
def test_too_many_metadata_items_on_create(self):
- self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
+ self.stubs.Set(nova.db.api, 'instance_metadata_update',
return_create_instance_metadata)
data = {"metadata": {}}
for num in range(FLAGS.quota_metadata_items + 1):
@@ -404,7 +420,7 @@ class ServerMetaDataTest(test.TestCase):
self.assertEqual(400, res.status_int)
def test_to_many_metadata_items_on_update_item(self):
- self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
+ self.stubs.Set(nova.db.api, 'instance_metadata_update',
return_create_instance_metadata_max)
req = webob.Request.blank('/v1.1/servers/1/metadata/key1')
req.method = 'PUT'
diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py
index cfb1f9382..b6342ae2f 100644
--- a/nova/tests/api/openstack/test_servers.py
+++ b/nova/tests/api/openstack/test_servers.py
@@ -1431,7 +1431,7 @@ class ServersTest(test.TestCase):
res = req.get_response(fakes.wsgi_app())
- self.assertEqual(res.status_int, 200)
+ self.assertEqual(res.status_int, 202)
server = json.loads(res.body)['server']
self.assertEqual(16, len(server['adminPass']))
self.assertEqual('server_test', server['name'])
@@ -1628,7 +1628,7 @@ class ServersTest(test.TestCase):
res = req.get_response(fakes.wsgi_app())
- self.assertEqual(res.status_int, 200)
+ self.assertEqual(res.status_int, 202)
server = json.loads(res.body)['server']
self.assertEqual(16, len(server['adminPass']))
self.assertEqual(1, server['id'])
@@ -1723,7 +1723,7 @@ class ServersTest(test.TestCase):
res = req.get_response(fakes.wsgi_app())
- self.assertEqual(res.status_int, 200)
+ self.assertEqual(res.status_int, 202)
server = json.loads(res.body)['server']
self.assertEqual(expected_flavor, server['flavor'])
self.assertEqual(expected_image, server['image'])
@@ -1768,7 +1768,7 @@ class ServersTest(test.TestCase):
req.body = json.dumps(body)
req.headers['content-type'] = "application/json"
res = req.get_response(fakes.wsgi_app())
- self.assertEqual(res.status_int, 200)
+ self.assertEqual(res.status_int, 202)
server = json.loads(res.body)['server']
self.assertEqual(server['adminPass'], body['server']['adminPass'])
@@ -2786,13 +2786,13 @@ class TestServerInstanceCreation(test.TestCase):
def test_create_instance_with_no_personality(self):
request, response, injected_files = \
self._create_instance_with_personality_json(personality=None)
- self.assertEquals(response.status_int, 200)
+ self.assertEquals(response.status_int, 202)
self.assertEquals(injected_files, [])
def test_create_instance_with_no_personality_xml(self):
request, response, injected_files = \
self._create_instance_with_personality_xml(personality=None)
- self.assertEquals(response.status_int, 200)
+ self.assertEquals(response.status_int, 202)
self.assertEquals(injected_files, [])
def test_create_instance_with_personality(self):
@@ -2802,7 +2802,7 @@ class TestServerInstanceCreation(test.TestCase):
personality = [(path, b64contents)]
request, response, injected_files = \
self._create_instance_with_personality_json(personality)
- self.assertEquals(response.status_int, 200)
+ self.assertEquals(response.status_int, 202)
self.assertEquals(injected_files, [(path, contents)])
def test_create_instance_with_personality_xml(self):
@@ -2812,7 +2812,7 @@ class TestServerInstanceCreation(test.TestCase):
personality = [(path, b64contents)]
request, response, injected_files = \
self._create_instance_with_personality_xml(personality)
- self.assertEquals(response.status_int, 200)
+ self.assertEquals(response.status_int, 202)
self.assertEquals(injected_files, [(path, contents)])
def test_create_instance_with_personality_no_path(self):
@@ -2875,7 +2875,7 @@ class TestServerInstanceCreation(test.TestCase):
request = self._get_create_request_json(body_dict)
compute_api, response = \
self._run_create_instance_with_mock_compute_api(request)
- self.assertEquals(response.status_int, 200)
+ self.assertEquals(response.status_int, 202)
def test_create_instance_with_three_personalities(self):
files = [
@@ -2888,7 +2888,7 @@ class TestServerInstanceCreation(test.TestCase):
personality.append((path, base64.b64encode(content)))
request, response, injected_files = \
self._create_instance_with_personality_json(personality)
- self.assertEquals(response.status_int, 200)
+ self.assertEquals(response.status_int, 202)
self.assertEquals(injected_files, files)
def test_create_instance_personality_empty_content(self):
@@ -2897,13 +2897,13 @@ class TestServerInstanceCreation(test.TestCase):
personality = [(path, contents)]
request, response, injected_files = \
self._create_instance_with_personality_json(personality)
- self.assertEquals(response.status_int, 200)
+ self.assertEquals(response.status_int, 202)
self.assertEquals(injected_files, [(path, contents)])
def test_create_instance_admin_pass_json(self):
request, response, dummy = \
self._create_instance_with_personality_json(None)
- self.assertEquals(response.status_int, 200)
+ self.assertEquals(response.status_int, 202)
response = json.loads(response.body)
self.assertTrue('adminPass' in response['server'])
self.assertEqual(16, len(response['server']['adminPass']))
@@ -2911,7 +2911,7 @@ class TestServerInstanceCreation(test.TestCase):
def test_create_instance_admin_pass_xml(self):
request, response, dummy = \
self._create_instance_with_personality_xml(None)
- self.assertEquals(response.status_int, 200)
+ self.assertEquals(response.status_int, 202)
dom = minidom.parseString(response.body)
server = dom.childNodes[0]
self.assertEquals(server.nodeName, 'server')
diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py
index 5a40f578f..0ff508ffa 100644
--- a/nova/tests/image/test_glance.py
+++ b/nova/tests/image/test_glance.py
@@ -235,3 +235,39 @@ class TestMutatorDateTimeTests(BaseGlanceTest):
'updated_at': None,
'deleted_at': None}
return fixture
+
+
+class TestGlanceSerializer(unittest.TestCase):
+ def test_serialize(self):
+ metadata = {'name': 'image1',
+ 'is_public': True,
+ 'foo': 'bar',
+ 'properties': {
+ 'prop1': 'propvalue1',
+ 'mappings': [
+ {'virtual': 'aaa',
+ 'device': 'bbb'},
+ {'virtual': 'xxx',
+ 'device': 'yyy'}],
+ 'block_device_mapping': [
+ {'virtual_device': 'fake',
+ 'device_name': '/dev/fake'},
+ {'virtual_device': 'ephemeral0',
+ 'device_name': '/dev/fake0'}]}}
+
+ converted_expected = {
+ 'name': 'image1',
+ 'is_public': True,
+ 'foo': 'bar',
+ 'properties': {
+ 'prop1': 'propvalue1',
+ 'mappings':
+ '[{"device": "bbb", "virtual": "aaa"}, '
+ '{"device": "yyy", "virtual": "xxx"}]',
+ 'block_device_mapping':
+ '[{"virtual_device": "fake", "device_name": "/dev/fake"}, '
+ '{"virtual_device": "ephemeral0", '
+ '"device_name": "/dev/fake0"}]'}}
+ converted = glance._convert_to_string(metadata)
+ self.assertEqual(converted, converted_expected)
+ self.assertEqual(glance._convert_from_string(converted), metadata)
diff --git a/nova/tests/test_api.py b/nova/tests/test_api.py
index d9b1d39c9..2011ae756 100644
--- a/nova/tests/test_api.py
+++ b/nova/tests/test_api.py
@@ -27,6 +27,7 @@ import random
import StringIO
import webob
+from nova import block_device
from nova import context
from nova import exception
from nova import test
@@ -147,10 +148,12 @@ class Ec2utilsTestCase(test.TestCase):
properties0 = {'mappings': mappings}
properties1 = {'root_device_name': '/dev/sdb', 'mappings': mappings}
- root_device_name = ec2utils.properties_root_device_name(properties0)
+ root_device_name = block_device.properties_root_device_name(
+ properties0)
self.assertEqual(root_device_name, '/dev/sda1')
- root_device_name = ec2utils.properties_root_device_name(properties1)
+ root_device_name = block_device.properties_root_device_name(
+ properties1)
self.assertEqual(root_device_name, '/dev/sdb')
def test_mapping_prepend_dev(self):
@@ -184,7 +187,7 @@ class Ec2utilsTestCase(test.TestCase):
'device': '/dev/sdc1'},
{'virtual': 'ephemeral1',
'device': '/dev/sdc1'}]
- self.assertDictListMatch(ec2utils.mappings_prepend_dev(mappings),
+ self.assertDictListMatch(block_device.mappings_prepend_dev(mappings),
expected_result)
@@ -336,6 +339,33 @@ class ApiEc2TestCase(test.TestCase):
self.ec2.delete_security_group(security_group_name)
+ def test_group_name_valid_chars_security_group(self):
+ """ Test that we sanely handle invalid security group names.
+ API Spec states we should only accept alphanumeric characters,
+ spaces, dashes, and underscores. """
+ self.expect_http()
+ self.mox.ReplayAll()
+
+ # Test block group_name of non alphanumeric characters, spaces,
+ # dashes, and underscores.
+ security_group_name = "aa #^% -=99"
+
+ self.assertRaises(EC2ResponseError, self.ec2.create_security_group,
+ security_group_name, 'test group')
+
+ def test_group_name_valid_length_security_group(self):
+ """Test that we sanely handle invalid security group names.
+ API Spec states that the length should not exceed 255 chars """
+ self.expect_http()
+ self.mox.ReplayAll()
+
+ # Test block group_name > 255 chars
+ security_group_name = "".join(random.choice("poiuytrewqasdfghjklmnbvc")
+ for x in range(random.randint(256, 266)))
+
+ self.assertRaises(EC2ResponseError, self.ec2.create_security_group,
+ security_group_name, 'test group')
+
def test_authorize_revoke_security_group_cidr(self):
"""
Test that we can add and remove CIDR based rules
diff --git a/nova/tests/test_block_device.py b/nova/tests/test_block_device.py
new file mode 100644
index 000000000..b8e9b35e2
--- /dev/null
+++ b/nova/tests/test_block_device.py
@@ -0,0 +1,87 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 Isaku Yamahata
+# 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.
+
+"""
+Tests for Block Device utility functions.
+"""
+
+from nova import block_device
+from nova import test
+
+
+class BlockDeviceTestCase(test.TestCase):
+ def test_properties(self):
+ root_device0 = '/dev/sda'
+ root_device1 = '/dev/sdb'
+ mappings = [{'virtual': 'root',
+ 'device': root_device0}]
+
+ properties0 = {'mappings': mappings}
+ properties1 = {'mappings': mappings,
+ 'root_device_name': root_device1}
+
+ self.assertEqual(block_device.properties_root_device_name({}), None)
+ self.assertEqual(
+ block_device.properties_root_device_name(properties0),
+ root_device0)
+ self.assertEqual(
+ block_device.properties_root_device_name(properties1),
+ root_device1)
+
+ def test_ephemeral(self):
+ self.assertFalse(block_device.is_ephemeral('ephemeral'))
+ self.assertTrue(block_device.is_ephemeral('ephemeral0'))
+ self.assertTrue(block_device.is_ephemeral('ephemeral1'))
+ self.assertTrue(block_device.is_ephemeral('ephemeral11'))
+ self.assertFalse(block_device.is_ephemeral('root'))
+ self.assertFalse(block_device.is_ephemeral('swap'))
+ self.assertFalse(block_device.is_ephemeral('/dev/sda1'))
+
+ self.assertEqual(block_device.ephemeral_num('ephemeral0'), 0)
+ self.assertEqual(block_device.ephemeral_num('ephemeral1'), 1)
+ self.assertEqual(block_device.ephemeral_num('ephemeral11'), 11)
+
+ self.assertFalse(block_device.is_swap_or_ephemeral('ephemeral'))
+ self.assertTrue(block_device.is_swap_or_ephemeral('ephemeral0'))
+ self.assertTrue(block_device.is_swap_or_ephemeral('ephemeral1'))
+ self.assertTrue(block_device.is_swap_or_ephemeral('swap'))
+ self.assertFalse(block_device.is_swap_or_ephemeral('root'))
+ self.assertFalse(block_device.is_swap_or_ephemeral('/dev/sda1'))
+
+ def test_mappings_prepend_dev(self):
+ mapping = [
+ {'virtual': 'ami', 'device': '/dev/sda'},
+ {'virtual': 'root', 'device': 'sda'},
+ {'virtual': 'ephemeral0', 'device': 'sdb'},
+ {'virtual': 'swap', 'device': 'sdc'},
+ {'virtual': 'ephemeral1', 'device': 'sdd'},
+ {'virtual': 'ephemeral2', 'device': 'sde'}]
+
+ expected = [
+ {'virtual': 'ami', 'device': '/dev/sda'},
+ {'virtual': 'root', 'device': 'sda'},
+ {'virtual': 'ephemeral0', 'device': '/dev/sdb'},
+ {'virtual': 'swap', 'device': '/dev/sdc'},
+ {'virtual': 'ephemeral1', 'device': '/dev/sdd'},
+ {'virtual': 'ephemeral2', 'device': '/dev/sde'}]
+
+ prepended = block_device.mappings_prepend_dev(mapping)
+ self.assertEqual(prepended.sort(), expected.sort())
+
+ def test_strip_dev(self):
+ self.assertEqual(block_device.strip_dev('/dev/sda'), 'sda')
+ self.assertEqual(block_device.strip_dev('sda'), 'sda')
diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py
index e891fa197..b2afc53c9 100644
--- a/nova/tests/test_cloud.py
+++ b/nova/tests/test_cloud.py
@@ -17,6 +17,8 @@
# under the License.
import mox
+import functools
+
from base64 import b64decode
from M2Crypto import BIO
from M2Crypto import RSA
@@ -892,13 +894,16 @@ class CloudTestCase(test.TestCase):
def test_modify_image_attribute(self):
modify_image_attribute = self.cloud.modify_image_attribute
+ fake_metadata = {'id': 1, 'container_format': 'ami',
+ 'properties': {'kernel_id': 1, 'ramdisk_id': 1,
+ 'type': 'machine'}, 'is_public': False}
+
def fake_show(meh, context, id):
- return {'id': 1, 'container_format': 'ami',
- 'properties': {'kernel_id': 1, 'ramdisk_id': 1,
- 'type': 'machine'}, 'is_public': False}
+ return fake_metadata
def fake_update(meh, context, image_id, metadata, data=None):
- return metadata
+ fake_metadata.update(metadata)
+ return fake_metadata
self.stubs.Set(fake._FakeImageService, 'show', fake_show)
self.stubs.Set(fake._FakeImageService, 'show_by_name', fake_show)
@@ -1464,3 +1469,147 @@ class CloudTestCase(test.TestCase):
# TODO(yamahata): clean up snapshot created by CreateImage.
self._restart_compute_service()
+
+ @staticmethod
+ def _fake_bdm_get(ctxt, id):
+ return [{'volume_id': 87654321,
+ 'snapshot_id': None,
+ 'no_device': None,
+ 'virtual_name': None,
+ 'delete_on_termination': True,
+ 'device_name': '/dev/sdh'},
+ {'volume_id': None,
+ 'snapshot_id': 98765432,
+ 'no_device': None,
+ 'virtual_name': None,
+ 'delete_on_termination': True,
+ 'device_name': '/dev/sdi'},
+ {'volume_id': None,
+ 'snapshot_id': None,
+ 'no_device': True,
+ 'virtual_name': None,
+ 'delete_on_termination': None,
+ 'device_name': None},
+ {'volume_id': None,
+ 'snapshot_id': None,
+ 'no_device': None,
+ 'virtual_name': 'ephemeral0',
+ 'delete_on_termination': None,
+ 'device_name': '/dev/sdb'},
+ {'volume_id': None,
+ 'snapshot_id': None,
+ 'no_device': None,
+ 'virtual_name': 'swap',
+ 'delete_on_termination': None,
+ 'device_name': '/dev/sdc'},
+ {'volume_id': None,
+ 'snapshot_id': None,
+ 'no_device': None,
+ 'virtual_name': 'ephemeral1',
+ 'delete_on_termination': None,
+ 'device_name': '/dev/sdd'},
+ {'volume_id': None,
+ 'snapshot_id': None,
+ 'no_device': None,
+ 'virtual_name': 'ephemeral2',
+ 'delete_on_termination': None,
+ 'device_name': '/dev/sd3'},
+ ]
+
+ def test_get_instance_mapping(self):
+ """Make sure that _get_instance_mapping works"""
+ ctxt = None
+ instance_ref0 = {'id': 0,
+ 'root_device_name': None}
+ instance_ref1 = {'id': 0,
+ 'root_device_name': '/dev/sda1'}
+
+ self.stubs.Set(db, 'block_device_mapping_get_all_by_instance',
+ self._fake_bdm_get)
+
+ expected = {'ami': 'sda1',
+ 'root': '/dev/sda1',
+ 'ephemeral0': '/dev/sdb',
+ 'swap': '/dev/sdc',
+ 'ephemeral1': '/dev/sdd',
+ 'ephemeral2': '/dev/sd3'}
+
+ self.assertEqual(self.cloud._format_instance_mapping(ctxt,
+ instance_ref0),
+ cloud._DEFAULT_MAPPINGS)
+ self.assertEqual(self.cloud._format_instance_mapping(ctxt,
+ instance_ref1),
+ expected)
+
+ def test_describe_instance_attribute(self):
+ """Make sure that describe_instance_attribute works"""
+ self.stubs.Set(db, 'block_device_mapping_get_all_by_instance',
+ self._fake_bdm_get)
+
+ def fake_get(ctxt, instance_id):
+ return {
+ 'id': 0,
+ 'root_device_name': '/dev/sdh',
+ 'security_groups': [{'name': 'fake0'}, {'name': 'fake1'}],
+ 'state_description': 'stopping',
+ 'instance_type': {'name': 'fake_type'},
+ 'kernel_id': 1,
+ 'ramdisk_id': 2,
+ 'user_data': 'fake-user data',
+ }
+ self.stubs.Set(self.cloud.compute_api, 'get', fake_get)
+
+ def fake_volume_get(ctxt, volume_id, session=None):
+ if volume_id == 87654321:
+ return {'id': volume_id,
+ 'attach_time': '13:56:24',
+ 'status': 'in-use'}
+ raise exception.VolumeNotFound(volume_id=volume_id)
+ self.stubs.Set(db.api, 'volume_get', fake_volume_get)
+
+ get_attribute = functools.partial(
+ self.cloud.describe_instance_attribute,
+ self.context, 'i-12345678')
+
+ bdm = get_attribute('blockDeviceMapping')
+ bdm['blockDeviceMapping'].sort()
+
+ expected_bdm = {'instance_id': 'i-12345678',
+ 'rootDeviceType': 'ebs',
+ 'blockDeviceMapping': [
+ {'deviceName': '/dev/sdh',
+ 'ebs': {'status': 'in-use',
+ 'deleteOnTermination': True,
+ 'volumeId': 87654321,
+ 'attachTime': '13:56:24'}}]}
+ expected_bdm['blockDeviceMapping'].sort()
+ self.assertEqual(bdm, expected_bdm)
+ # NOTE(yamahata): this isn't supported
+ # get_attribute('disableApiTermination')
+ groupSet = get_attribute('groupSet')
+ groupSet['groupSet'].sort()
+ expected_groupSet = {'instance_id': 'i-12345678',
+ 'groupSet': [{'groupId': 'fake0'},
+ {'groupId': 'fake1'}]}
+ expected_groupSet['groupSet'].sort()
+ self.assertEqual(groupSet, expected_groupSet)
+ self.assertEqual(get_attribute('instanceInitiatedShutdownBehavior'),
+ {'instance_id': 'i-12345678',
+ 'instanceInitiatedShutdownBehavior': 'stop'})
+ self.assertEqual(get_attribute('instanceType'),
+ {'instance_id': 'i-12345678',
+ 'instanceType': 'fake_type'})
+ self.assertEqual(get_attribute('kernel'),
+ {'instance_id': 'i-12345678',
+ 'kernel': 'aki-00000001'})
+ self.assertEqual(get_attribute('ramdisk'),
+ {'instance_id': 'i-12345678',
+ 'ramdisk': 'ari-00000002'})
+ self.assertEqual(get_attribute('rootDeviceName'),
+ {'instance_id': 'i-12345678',
+ 'rootDeviceName': '/dev/sdh'})
+ # NOTE(yamahata): this isn't supported
+ # get_attribute('sourceDestCheck')
+ self.assertEqual(get_attribute('userData'),
+ {'instance_id': 'i-12345678',
+ 'userData': '}\xa9\x1e\xba\xc7\xabu\xabZ'})
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index 18ec08597..80f7ff489 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -1333,15 +1333,17 @@ class ComputeTestCase(test.TestCase):
return bdm
def test_update_block_device_mapping(self):
+ swap_size = 1
+ instance_type = {'swap': swap_size}
instance_id = self._create_instance()
mappings = [
{'virtual': 'ami', 'device': 'sda1'},
{'virtual': 'root', 'device': '/dev/sda1'},
- {'virtual': 'swap', 'device': 'sdb1'},
- {'virtual': 'swap', 'device': 'sdb2'},
- {'virtual': 'swap', 'device': 'sdb3'},
{'virtual': 'swap', 'device': 'sdb4'},
+ {'virtual': 'swap', 'device': 'sdb3'},
+ {'virtual': 'swap', 'device': 'sdb2'},
+ {'virtual': 'swap', 'device': 'sdb1'},
{'virtual': 'ephemeral0', 'device': 'sdc1'},
{'virtual': 'ephemeral1', 'device': 'sdc2'},
@@ -1383,32 +1385,36 @@ class ComputeTestCase(test.TestCase):
'no_device': True}]
self.compute_api._update_image_block_device_mapping(
- self.context, instance_id, mappings)
+ self.context, instance_type, instance_id, mappings)
bdms = [self._parse_db_block_device_mapping(bdm_ref)
for bdm_ref in db.block_device_mapping_get_all_by_instance(
self.context, instance_id)]
expected_result = [
- {'virtual_name': 'swap', 'device_name': '/dev/sdb1'},
- {'virtual_name': 'swap', 'device_name': '/dev/sdb2'},
- {'virtual_name': 'swap', 'device_name': '/dev/sdb3'},
- {'virtual_name': 'swap', 'device_name': '/dev/sdb4'},
+ {'virtual_name': 'swap', 'device_name': '/dev/sdb1',
+ 'volume_size': swap_size},
{'virtual_name': 'ephemeral0', 'device_name': '/dev/sdc1'},
- {'virtual_name': 'ephemeral1', 'device_name': '/dev/sdc2'},
- {'virtual_name': 'ephemeral2', 'device_name': '/dev/sdc3'}]
+
+ # NOTE(yamahata): ATM only ephemeral0 is supported.
+ # they're ignored for now
+ #{'virtual_name': 'ephemeral1', 'device_name': '/dev/sdc2'},
+ #{'virtual_name': 'ephemeral2', 'device_name': '/dev/sdc3'}
+ ]
bdms.sort()
expected_result.sort()
self.assertDictListMatch(bdms, expected_result)
self.compute_api._update_block_device_mapping(
- self.context, instance_id, block_device_mapping)
+ self.context, instance_types.get_default_instance_type(),
+ instance_id, block_device_mapping)
bdms = [self._parse_db_block_device_mapping(bdm_ref)
for bdm_ref in db.block_device_mapping_get_all_by_instance(
self.context, instance_id)]
expected_result = [
{'snapshot_id': 0x12345678, 'device_name': '/dev/sda1'},
- {'virtual_name': 'swap', 'device_name': '/dev/sdb1'},
+ {'virtual_name': 'swap', 'device_name': '/dev/sdb1',
+ 'volume_size': swap_size},
{'snapshot_id': 0x23456789, 'device_name': '/dev/sdb2'},
{'snapshot_id': 0x3456789A, 'device_name': '/dev/sdb3'},
{'no_device': True, 'device_name': '/dev/sdb4'},
@@ -1430,3 +1436,13 @@ class ComputeTestCase(test.TestCase):
self.context, instance_id):
db.block_device_mapping_destroy(self.context, bdm['id'])
self.compute.terminate_instance(self.context, instance_id)
+
+ def test_ephemeral_size(self):
+ local_size = 2
+ inst_type = {'local_gb': local_size}
+ self.assertEqual(self.compute_api._ephemeral_size(inst_type,
+ 'ephemeral0'),
+ local_size)
+ self.assertEqual(self.compute_api._ephemeral_size(inst_type,
+ 'ephemeral1'),
+ 0)
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index f8b866985..c04851d59 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -169,6 +169,7 @@ class LibvirtConnTestCase(test.TestCase):
'project_id': 'fake',
'bridge': 'br101',
'image_ref': '123456',
+ 'local_gb': 20,
'instance_type_id': '5'} # m1.small
def lazy_load_library_exists(self):
@@ -744,6 +745,42 @@ class LibvirtConnTestCase(test.TestCase):
ip = conn.get_host_ip_addr()
self.assertEquals(ip, FLAGS.my_ip)
+ def test_volume_in_mapping(self):
+ conn = connection.LibvirtConnection(False)
+ swap = {'device_name': '/dev/sdb',
+ 'swap_size': 1}
+ ephemerals = [{'num': 0,
+ 'virtual_name': 'ephemeral0',
+ 'device_name': '/dev/sdc1',
+ 'size': 1},
+ {'num': 2,
+ 'virtual_name': 'ephemeral2',
+ 'device_name': '/dev/sdd',
+ 'size': 1}]
+ block_device_mapping = [{'mount_device': '/dev/sde',
+ 'device_path': 'fake_device'},
+ {'mount_device': '/dev/sdf',
+ 'device_path': 'fake_device'}]
+ block_device_info = {
+ 'root_device_name': '/dev/sda',
+ 'swap': swap,
+ 'ephemerals': ephemerals,
+ 'block_device_mapping': block_device_mapping}
+
+ def _assert_volume_in_mapping(device_name, true_or_false):
+ self.assertEquals(conn._volume_in_mapping(device_name,
+ block_device_info),
+ true_or_false)
+
+ _assert_volume_in_mapping('sda', False)
+ _assert_volume_in_mapping('sdb', True)
+ _assert_volume_in_mapping('sdc1', True)
+ _assert_volume_in_mapping('sdd', True)
+ _assert_volume_in_mapping('sde', True)
+ _assert_volume_in_mapping('sdf', True)
+ _assert_volume_in_mapping('sdg', False)
+ _assert_volume_in_mapping('sdh1', False)
+
class NWFilterFakes:
def __init__(self):
diff --git a/nova/tests/test_metadata.py b/nova/tests/test_metadata.py
index d63394ad6..ad678714e 100644
--- a/nova/tests/test_metadata.py
+++ b/nova/tests/test_metadata.py
@@ -44,6 +44,7 @@ class MetadataTestCase(test.TestCase):
'user_data': '',
'image_ref': 7,
'fixed_ips': [],
+ 'root_device_name': '/dev/sda1',
'hostname': 'test'})
def instance_get(*args, **kwargs):
diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py
new file mode 100644
index 000000000..388f075af
--- /dev/null
+++ b/nova/tests/test_virt.py
@@ -0,0 +1,83 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 Isaku Yamahata
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from nova import flags
+from nova import test
+from nova.virt import driver
+
+FLAGS = flags.FLAGS
+
+
+class TestVirtDriver(test.TestCase):
+ def test_block_device(self):
+ swap = {'device_name': '/dev/sdb',
+ 'swap_size': 1}
+ ephemerals = [{'num': 0,
+ 'virtual_name': 'ephemeral0',
+ 'device_name': '/dev/sdc1',
+ 'size': 1}]
+ block_device_mapping = [{'mount_device': '/dev/sde',
+ 'device_path': 'fake_device'}]
+ block_device_info = {
+ 'root_device_name': '/dev/sda',
+ 'swap': swap,
+ 'ephemerals': ephemerals,
+ 'block_device_mapping': block_device_mapping}
+
+ empty_block_device_info = {}
+
+ self.assertEqual(
+ driver.block_device_info_get_root(block_device_info), '/dev/sda')
+ self.assertEqual(
+ driver.block_device_info_get_root(empty_block_device_info), None)
+ self.assertEqual(
+ driver.block_device_info_get_root(None), None)
+
+ self.assertEqual(
+ driver.block_device_info_get_swap(block_device_info), swap)
+ self.assertEqual(driver.block_device_info_get_swap(
+ empty_block_device_info)['device_name'], None)
+ self.assertEqual(driver.block_device_info_get_swap(
+ empty_block_device_info)['swap_size'], 0)
+ self.assertEqual(
+ driver.block_device_info_get_swap({'swap': None})['device_name'],
+ None)
+ self.assertEqual(
+ driver.block_device_info_get_swap({'swap': None})['swap_size'],
+ 0)
+ self.assertEqual(
+ driver.block_device_info_get_swap(None)['device_name'], None)
+ self.assertEqual(
+ driver.block_device_info_get_swap(None)['swap_size'], 0)
+
+ self.assertEqual(
+ driver.block_device_info_get_ephemerals(block_device_info),
+ ephemerals)
+ self.assertEqual(
+ driver.block_device_info_get_ephemerals(empty_block_device_info),
+ [])
+ self.assertEqual(
+ driver.block_device_info_get_ephemerals(None),
+ [])
+
+ def test_swap_is_usable(self):
+ self.assertFalse(driver.swap_is_usable(None))
+ self.assertFalse(driver.swap_is_usable({'device_name': None}))
+ self.assertFalse(driver.swap_is_usable({'device_name': '/dev/sdb',
+ 'swap_size': 0}))
+ self.assertTrue(driver.swap_is_usable({'device_name': '/dev/sdb',
+ 'swap_size': 1}))