summaryrefslogtreecommitdiffstats
path: root/nova/tests
diff options
context:
space:
mode:
authorChuck Short <zulcss@ubuntu.com>2011-06-23 09:54:54 -0400
committerChuck Short <zulcss@ubuntu.com>2011-06-23 09:54:54 -0400
commit3b120fe30c0a9999b7ba85e07a262e672a1c8ed2 (patch)
treecf7127582f31a37b2a0beb4f6c8b2ad304e64086 /nova/tests
parenta2cf08c84bc9c4113911534cfe3d4460b56d4124 (diff)
parent6d6720e9b7e52461238ece684c9acc7183673bb8 (diff)
Merge trunk:
Diffstat (limited to 'nova/tests')
-rw-r--r--nova/tests/api/openstack/fakes.py1
-rw-r--r--nova/tests/api/openstack/test_api.py21
-rw-r--r--nova/tests/api/openstack/test_extensions.py13
-rw-r--r--nova/tests/api/openstack/test_images.py30
-rw-r--r--nova/tests/api/openstack/test_limits.py3
-rw-r--r--nova/tests/api/openstack/test_server_metadata.py55
-rw-r--r--nova/tests/api/openstack/test_servers.py220
-rw-r--r--nova/tests/api/openstack/test_wsgi.py24
-rw-r--r--nova/tests/fake_flags.py2
-rw-r--r--nova/tests/integrated/api/client.py16
-rw-r--r--nova/tests/scheduler/test_host_filter.py8
-rw-r--r--nova/tests/scheduler/test_least_cost_scheduler.py8
-rw-r--r--nova/tests/scheduler/test_scheduler.py40
-rw-r--r--nova/tests/scheduler/test_zone_aware_scheduler.py2
-rw-r--r--nova/tests/test_api.py2
-rw-r--r--nova/tests/test_cloud.py364
-rw-r--r--nova/tests/test_compute.py37
-rw-r--r--nova/tests/test_crypto.py83
-rw-r--r--nova/tests/test_utils.py18
-rw-r--r--nova/tests/test_xenapi.py76
20 files changed, 891 insertions, 132 deletions
diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py
index a10fb7433..f8d158ddd 100644
--- a/nova/tests/api/openstack/fakes.py
+++ b/nova/tests/api/openstack/fakes.py
@@ -39,7 +39,6 @@ from nova.api.openstack import limits
from nova.auth.manager import User, Project
import nova.image.fake
from nova.image import glance
-from nova.image import local
from nova.image import service
from nova.tests import fake_flags
from nova.wsgi import Router
diff --git a/nova/tests/api/openstack/test_api.py b/nova/tests/api/openstack/test_api.py
index c63431a45..7321c329f 100644
--- a/nova/tests/api/openstack/test_api.py
+++ b/nova/tests/api/openstack/test_api.py
@@ -15,6 +15,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import json
+
import webob.exc
import webob.dec
@@ -23,6 +25,7 @@ from webob import Request
from nova import test
from nova.api import openstack
from nova.api.openstack import faults
+from nova.tests.api.openstack import fakes
class APITest(test.TestCase):
@@ -31,6 +34,24 @@ class APITest(test.TestCase):
# simpler version of the app than fakes.wsgi_app
return openstack.FaultWrapper(inner_app)
+ def test_malformed_json(self):
+ req = webob.Request.blank('/')
+ req.method = 'POST'
+ req.body = '{'
+ req.headers["content-type"] = "application/json"
+
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 400)
+
+ def test_malformed_xml(self):
+ req = webob.Request.blank('/')
+ req.method = 'POST'
+ req.body = '<hi im not xml>'
+ req.headers["content-type"] = "application/xml"
+
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 400)
+
def test_exceptions_are_converted_to_faults(self):
@webob.dec.wsgify
diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py
index 60914c0a3..697c62e5c 100644
--- a/nova/tests/api/openstack/test_extensions.py
+++ b/nova/tests/api/openstack/test_extensions.py
@@ -128,6 +128,11 @@ class ResourceExtensionTest(unittest.TestCase):
self.assertEqual(response_body, response.body)
+class InvalidExtension(object):
+ def get_alias(self):
+ return "THIRD"
+
+
class ExtensionManagerTest(unittest.TestCase):
response_body = "Try to say this Mr. Knox, sir..."
@@ -144,6 +149,14 @@ class ExtensionManagerTest(unittest.TestCase):
self.assertEqual(200, response.status_int)
self.assertEqual(response_body, response.body)
+ def test_invalid_extensions(self):
+ app = openstack.APIRouterV11()
+ ext_midware = extensions.ExtensionMiddleware(app)
+ ext_mgr = ext_midware.ext_mgr
+ ext_mgr.add_extension(InvalidExtension())
+ self.assertTrue('FOXNSOX' in ext_mgr.extensions)
+ self.assertTrue('THIRD' not in ext_mgr.extensions)
+
class ActionExtensionTest(unittest.TestCase):
diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py
index be777df9b..e4204809f 100644
--- a/nova/tests/api/openstack/test_images.py
+++ b/nova/tests/api/openstack/test_images.py
@@ -135,36 +135,6 @@ class _BaseImageServiceTests(test.TestCase):
return fixture
-class LocalImageServiceTest(_BaseImageServiceTests):
-
- """Tests the local image service"""
-
- def setUp(self):
- super(LocalImageServiceTest, self).setUp()
- self.tempdir = tempfile.mkdtemp()
- self.flags(images_path=self.tempdir)
- self.stubs = stubout.StubOutForTesting()
- service_class = 'nova.image.local.LocalImageService'
- self.service = utils.import_object(service_class)
- self.context = context.RequestContext(None, None)
-
- def tearDown(self):
- shutil.rmtree(self.tempdir)
- self.stubs.UnsetAll()
- super(LocalImageServiceTest, self).tearDown()
-
- def test_get_all_ids_with_incorrect_directory_formats(self):
- # create some old-style image directories (starting with 'ami-')
- for x in [1, 2, 3]:
- tempfile.mkstemp(prefix='ami-', dir=self.tempdir)
- # create some valid image directories names
- for x in ["1485baed", "1a60f0ee", "3123a73d"]:
- os.makedirs(os.path.join(self.tempdir, x))
- found_image_ids = self.service._ids()
- self.assertEqual(True, isinstance(found_image_ids, list))
- self.assertEqual(3, len(found_image_ids), len(found_image_ids))
-
-
class GlanceImageServiceTest(_BaseImageServiceTests):
"""Tests the Glance image service, in particular that metadata translation
diff --git a/nova/tests/api/openstack/test_limits.py b/nova/tests/api/openstack/test_limits.py
index 01613d1d8..38c959fae 100644
--- a/nova/tests/api/openstack/test_limits.py
+++ b/nova/tests/api/openstack/test_limits.py
@@ -672,8 +672,7 @@ class WsgiLimiterTest(BaseLimitTestSuite):
"""Only POSTs should work."""
requests = []
for method in ["GET", "PUT", "DELETE", "HEAD", "OPTIONS"]:
- request = webob.Request.blank("/")
- request.body = self._request_data("GET", "/something")
+ request = webob.Request.blank("/", method=method)
response = request.get_response(self.app)
self.assertEqual(response.status_int, 405)
diff --git a/nova/tests/api/openstack/test_server_metadata.py b/nova/tests/api/openstack/test_server_metadata.py
index b583d40fe..0431e68d2 100644
--- a/nova/tests/api/openstack/test_server_metadata.py
+++ b/nova/tests/api/openstack/test_server_metadata.py
@@ -21,6 +21,7 @@ import unittest
import webob
+from nova import exception
from nova import flags
from nova.api import openstack
from nova.tests.api.openstack import fakes
@@ -67,6 +68,14 @@ def stub_max_server_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):
def setUp(self):
@@ -76,6 +85,7 @@ class ServerMetaDataTest(unittest.TestCase):
fakes.FakeAuthDatabase.data = {}
fakes.stub_out_auth(self.stubs)
fakes.stub_out_key_pair_funcs(self.stubs)
+ self.stubs.Set(nova.db.api, 'instance_get', return_server)
def tearDown(self):
self.stubs.UnsetAll()
@@ -92,6 +102,13 @@ class ServerMetaDataTest(unittest.TestCase):
self.assertEqual('application/json', res.headers['Content-Type'])
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):
self.stubs.Set(nova.db.api, 'instance_metadata_get',
return_empty_server_metadata)
@@ -114,13 +131,19 @@ class ServerMetaDataTest(unittest.TestCase):
self.assertEqual('application/json', res.headers['Content-Type'])
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):
self.stubs.Set(nova.db.api, 'instance_metadata_get',
return_empty_server_metadata)
req = webob.Request.blank('/v1.1/servers/1/meta/key6')
req.environ['api.version'] = '1.1'
res = req.get_response(fakes.wsgi_app())
- res_dict = json.loads(res.body)
self.assertEqual(404, res.status_int)
def test_delete(self):
@@ -132,6 +155,14 @@ class ServerMetaDataTest(unittest.TestCase):
res = req.get_response(fakes.wsgi_app())
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):
self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
return_create_instance_metadata)
@@ -141,8 +172,8 @@ class ServerMetaDataTest(unittest.TestCase):
req.body = '{"metadata": {"key1": "value1"}}'
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
- res_dict = json.loads(res.body)
self.assertEqual(200, res.status_int)
+ res_dict = json.loads(res.body)
self.assertEqual('application/json', res.headers['Content-Type'])
self.assertEqual('value1', res_dict['metadata']['key1'])
@@ -156,6 +187,16 @@ class ServerMetaDataTest(unittest.TestCase):
res = req.get_response(fakes.wsgi_app())
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):
self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
return_create_instance_metadata)
@@ -170,6 +211,16 @@ class ServerMetaDataTest(unittest.TestCase):
res_dict = json.loads(res.body)
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):
self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create',
return_create_instance_metadata)
diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py
index 28ad4a417..b53c6c9be 100644
--- a/nova/tests/api/openstack/test_servers.py
+++ b/nova/tests/api/openstack/test_servers.py
@@ -31,10 +31,12 @@ from nova import test
from nova import utils
import nova.api.openstack
from nova.api.openstack import servers
+from nova.api.openstack import create_instance_helper
import nova.compute.api
from nova.compute import instance_types
from nova.compute import power_state
import nova.db.api
+import nova.scheduler.api
from nova.db.sqlalchemy.models import Instance
from nova.db.sqlalchemy.models import InstanceMetadata
import nova.image.fake
@@ -47,10 +49,22 @@ FLAGS = flags.FLAGS
FLAGS.verbose = True
-def return_server(context, id):
+FAKE_UUID = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
+
+
+def fake_gen_uuid():
+ return FAKE_UUID
+
+
+def return_server_by_id(context, id):
return stub_instance(id)
+def return_server_by_uuid(context, uuid):
+ id = 1
+ return stub_instance(id, uuid=uuid)
+
+
def return_server_with_addresses(private, public):
def _return_server(context, id):
return stub_instance(id, private_address=private,
@@ -68,6 +82,34 @@ def return_servers(context, user_id=1):
return [stub_instance(i, user_id) for i in xrange(5)]
+def return_servers_by_reservation(context, reservation_id=""):
+ return [stub_instance(i, reservation_id) for i in xrange(5)]
+
+
+def return_servers_by_reservation_empty(context, reservation_id=""):
+ return []
+
+
+def return_servers_from_child_zones_empty(*args, **kwargs):
+ return []
+
+
+def return_servers_from_child_zones(*args, **kwargs):
+ class Server(object):
+ pass
+
+ zones = []
+ for zone in xrange(3):
+ servers = []
+ for server_id in xrange(5):
+ server = Server()
+ server._info = stub_instance(server_id, reservation_id="child")
+ servers.append(server)
+
+ zones.append(("Zone%d" % zone, servers))
+ return zones
+
+
def return_security_group(context, instance_id, security_group_id):
pass
@@ -81,7 +123,8 @@ def instance_address(context, instance_id):
def stub_instance(id, user_id=1, private_address=None, public_addresses=None,
- host=None, power_state=0):
+ host=None, power_state=0, reservation_id="",
+ uuid=FAKE_UUID):
metadata = []
metadata.append(InstanceMetadata(key='seq', value=id))
@@ -93,8 +136,13 @@ def stub_instance(id, user_id=1, private_address=None, public_addresses=None,
if host is not None:
host = str(host)
+ # ReservationID isn't sent back, hack it in there.
+ server_name = "server%s" % id
+ if reservation_id != "":
+ server_name = "reservation_%s" % (reservation_id, )
+
instance = {
- "id": id,
+ "id": int(id),
"admin_pass": "",
"user_id": user_id,
"project_id": "",
@@ -113,16 +161,17 @@ def stub_instance(id, user_id=1, private_address=None, public_addresses=None,
"host": host,
"instance_type": dict(inst_type),
"user_data": "",
- "reservation_id": "",
+ "reservation_id": reservation_id,
"mac_address": "",
"scheduled_at": utils.utcnow(),
"launched_at": utils.utcnow(),
"terminated_at": utils.utcnow(),
"availability_zone": "",
- "display_name": "server%s" % id,
+ "display_name": server_name,
"display_description": "",
"locked": False,
- "metadata": metadata}
+ "metadata": metadata,
+ "uuid": uuid}
instance["fixed_ip"] = {
"address": private_address,
@@ -161,8 +210,11 @@ class ServersTest(test.TestCase):
fakes.stub_out_auth(self.stubs)
fakes.stub_out_key_pair_funcs(self.stubs)
fakes.stub_out_image_service(self.stubs)
+ self.stubs.Set(utils, 'gen_uuid', fake_gen_uuid)
self.stubs.Set(nova.db.api, 'instance_get_all', return_servers)
- self.stubs.Set(nova.db.api, 'instance_get', return_server)
+ self.stubs.Set(nova.db.api, 'instance_get', return_server_by_id)
+ self.stubs.Set(nova.db, 'instance_get_by_uuid',
+ return_server_by_uuid)
self.stubs.Set(nova.db.api, 'instance_get_all_by_user',
return_servers)
self.stubs.Set(nova.db.api, 'instance_add_security_group',
@@ -194,6 +246,36 @@ class ServersTest(test.TestCase):
self.assertEqual(res_dict['server']['id'], 1)
self.assertEqual(res_dict['server']['name'], 'server1')
+ def test_get_server_by_uuid(self):
+ """
+ The steps involved with resolving a UUID are pretty complicated;
+ here's what's happening in this scenario:
+
+ 1. Show is calling `routing_get`
+
+ 2. `routing_get` is wrapped by `reroute_compute` which does the work
+ of resolving requests to child zones.
+
+ 3. `reroute_compute` looks up the UUID by hitting the stub
+ (returns_server_by_uuid)
+
+ 4. Since the stub return that the record exists, `reroute_compute`
+ considers the request to be 'zone local', so it replaces the UUID
+ in the argument list with an integer ID and then calls the inner
+ function ('get').
+
+ 5. The call to `get` hits the other stub 'returns_server_by_id` which
+ has the UUID set to FAKE_UUID
+
+ So, counterintuitively, we call `get` twice on the `show` command.
+ """
+ req = webob.Request.blank('/v1.0/servers/%s' % FAKE_UUID)
+ res = req.get_response(fakes.wsgi_app())
+ res_dict = json.loads(res.body)
+ self.assertEqual(res_dict['server']['id'], 1)
+ self.assertEqual(res_dict['server']['uuid'], FAKE_UUID)
+ self.assertEqual(res_dict['server']['name'], 'server1')
+
def test_get_server_by_id_v1_1(self):
req = webob.Request.blank('/v1.1/servers/1')
res = req.get_response(fakes.wsgi_app())
@@ -364,6 +446,57 @@ class ServersTest(test.TestCase):
self.assertEqual(s.get('imageId', None), None)
i += 1
+ def test_get_server_list_with_reservation_id(self):
+ self.stubs.Set(nova.db.api, 'instance_get_all_by_reservation',
+ return_servers_by_reservation)
+ self.stubs.Set(nova.scheduler.api, 'call_zone_method',
+ return_servers_from_child_zones)
+ req = webob.Request.blank('/v1.0/servers?reservation_id=foo')
+ res = req.get_response(fakes.wsgi_app())
+ res_dict = json.loads(res.body)
+
+ i = 0
+ for s in res_dict['servers']:
+ if '_is_precooked' in s:
+ self.assertEqual(s.get('reservation_id'), 'child')
+ else:
+ self.assertEqual(s.get('name'), 'server%d' % i)
+ i += 1
+
+ def test_get_server_list_with_reservation_id_empty(self):
+ self.stubs.Set(nova.db.api, 'instance_get_all_by_reservation',
+ return_servers_by_reservation_empty)
+ self.stubs.Set(nova.scheduler.api, 'call_zone_method',
+ return_servers_from_child_zones_empty)
+ req = webob.Request.blank('/v1.0/servers/detail?reservation_id=foo')
+ res = req.get_response(fakes.wsgi_app())
+ res_dict = json.loads(res.body)
+
+ i = 0
+ for s in res_dict['servers']:
+ if '_is_precooked' in s:
+ self.assertEqual(s.get('reservation_id'), 'child')
+ else:
+ self.assertEqual(s.get('name'), 'server%d' % i)
+ i += 1
+
+ def test_get_server_list_with_reservation_id_details(self):
+ self.stubs.Set(nova.db.api, 'instance_get_all_by_reservation',
+ return_servers_by_reservation)
+ self.stubs.Set(nova.scheduler.api, 'call_zone_method',
+ return_servers_from_child_zones)
+ req = webob.Request.blank('/v1.0/servers/detail?reservation_id=foo')
+ res = req.get_response(fakes.wsgi_app())
+ res_dict = json.loads(res.body)
+
+ i = 0
+ for s in res_dict['servers']:
+ if '_is_precooked' in s:
+ self.assertEqual(s.get('reservation_id'), 'child')
+ else:
+ self.assertEqual(s.get('name'), 'server%d' % i)
+ i += 1
+
def test_get_server_list_v1_1(self):
req = webob.Request.blank('/v1.1/servers')
res = req.get_response(fakes.wsgi_app())
@@ -454,7 +587,8 @@ class ServersTest(test.TestCase):
def _setup_for_create_instance(self):
"""Shared implementation for tests below that create instance"""
def instance_create(context, inst):
- return {'id': '1', 'display_name': 'server_test'}
+ return {'id': 1, 'display_name': 'server_test',
+ 'uuid': FAKE_UUID}
def server_update(context, id, params):
return instance_create(context, id)
@@ -483,7 +617,8 @@ class ServersTest(test.TestCase):
self.stubs.Set(nova.db.api, 'queue_get_for', queue_get_for)
self.stubs.Set(nova.network.manager.VlanManager, 'allocate_fixed_ip',
fake_method)
- self.stubs.Set(nova.api.openstack.servers.Controller,
+ self.stubs.Set(
+ nova.api.openstack.create_instance_helper.CreateInstanceHelper,
"_get_kernel_ramdisk_from_image", kernel_ramdisk_mapping)
self.stubs.Set(nova.compute.api.API, "_find_host", find_host)
@@ -507,11 +642,64 @@ class ServersTest(test.TestCase):
self.assertEqual(1, server['id'])
self.assertEqual(2, server['flavorId'])
self.assertEqual(3, server['imageId'])
+ self.assertEqual(FAKE_UUID, server['uuid'])
self.assertEqual(res.status_int, 200)
def test_create_instance(self):
self._test_create_instance_helper()
+ def test_create_instance_has_uuid(self):
+ """Tests at the db-layer instead of API layer since that's where the
+ UUID is generated
+ """
+ ctxt = context.RequestContext(1, 1)
+ values = {}
+ instance = nova.db.api.instance_create(ctxt, values)
+ expected = FAKE_UUID
+ self.assertEqual(instance['uuid'], expected)
+
+ def test_create_instance_via_zones(self):
+ """Server generated ReservationID"""
+ self._setup_for_create_instance()
+ FLAGS.allow_admin_api = True
+
+ body = dict(server=dict(
+ name='server_test', imageId=3, flavorId=2,
+ metadata={'hello': 'world', 'open': 'stack'},
+ personality={}))
+ req = webob.Request.blank('/v1.0/zones/boot')
+ req.method = 'POST'
+ req.body = json.dumps(body)
+ req.headers["content-type"] = "application/json"
+
+ res = req.get_response(fakes.wsgi_app())
+
+ reservation_id = json.loads(res.body)['reservation_id']
+ self.assertEqual(res.status_int, 200)
+ self.assertNotEqual(reservation_id, "")
+ self.assertNotEqual(reservation_id, None)
+ self.assertTrue(len(reservation_id) > 1)
+
+ def test_create_instance_via_zones_with_resid(self):
+ """User supplied ReservationID"""
+ self._setup_for_create_instance()
+ FLAGS.allow_admin_api = True
+
+ body = dict(server=dict(
+ name='server_test', imageId=3, flavorId=2,
+ metadata={'hello': 'world', 'open': 'stack'},
+ personality={}, reservation_id='myresid'))
+ req = webob.Request.blank('/v1.0/zones/boot')
+ req.method = 'POST'
+ req.body = json.dumps(body)
+ req.headers["content-type"] = "application/json"
+
+ res = req.get_response(fakes.wsgi_app())
+
+ reservation_id = json.loads(res.body)['reservation_id']
+ self.assertEqual(res.status_int, 200)
+ self.assertEqual(reservation_id, "myresid")
+
def test_create_instance_no_key_pair(self):
fakes.stub_out_key_pair_funcs(self.stubs, have_key_pair=False)
self._test_create_instance_helper()
@@ -1314,7 +1502,7 @@ class ServersTest(test.TestCase):
self.assertEqual(res.status_int, 400)
def test_resized_server_has_correct_status(self):
- req = self.webreq('/1', 'GET', dict(resize=dict(flavorId=3)))
+ req = self.webreq('/1', 'GET')
def fake_migration_get(*args):
return {}
@@ -1401,7 +1589,7 @@ class ServersTest(test.TestCase):
class TestServerCreateRequestXMLDeserializer(unittest.TestCase):
def setUp(self):
- self.deserializer = servers.ServerXMLDeserializer()
+ self.deserializer = create_instance_helper.ServerXMLDeserializer()
def test_minimal_request(self):
serial_request = """
@@ -1721,7 +1909,8 @@ class TestServerInstanceCreation(test.TestCase):
self.injected_files = kwargs['injected_files']
else:
self.injected_files = None
- return [{'id': '1234', 'display_name': 'fakeinstance'}]
+ return [{'id': '1234', 'display_name': 'fakeinstance',
+ 'uuid': FAKE_UUID}]
def set_admin_password(self, *args, **kwargs):
pass
@@ -1733,7 +1922,8 @@ class TestServerInstanceCreation(test.TestCase):
compute_api = MockComputeAPI()
self.stubs.Set(nova.compute, 'API', make_stub_method(compute_api))
- self.stubs.Set(nova.api.openstack.servers.Controller,
+ self.stubs.Set(
+ nova.api.openstack.create_instance_helper.CreateInstanceHelper,
'_get_kernel_ramdisk_from_image', make_stub_method((1, 1)))
return compute_api
@@ -1989,6 +2179,6 @@ class TestGetKernelRamdiskFromImage(test.TestCase):
@staticmethod
def _get_k_r(image_meta):
"""Rebinding function to a shorter name for convenience"""
- kernel_id, ramdisk_id = \
- servers.Controller._do_get_kernel_ramdisk_from_image(image_meta)
+ kernel_id, ramdisk_id = create_instance_helper.CreateInstanceHelper. \
+ _do_get_kernel_ramdisk_from_image(image_meta)
return kernel_id, ramdisk_id
diff --git a/nova/tests/api/openstack/test_wsgi.py b/nova/tests/api/openstack/test_wsgi.py
index ebbdc9409..73a26a087 100644
--- a/nova/tests/api/openstack/test_wsgi.py
+++ b/nova/tests/api/openstack/test_wsgi.py
@@ -10,13 +10,13 @@ from nova.api.openstack import wsgi
class RequestTest(test.TestCase):
def test_content_type_missing(self):
- request = wsgi.Request.blank('/tests/123')
+ request = wsgi.Request.blank('/tests/123', method='POST')
request.body = "<body />"
self.assertRaises(exception.InvalidContentType,
request.get_content_type)
def test_content_type_unsupported(self):
- request = wsgi.Request.blank('/tests/123')
+ request = wsgi.Request.blank('/tests/123', method='POST')
request.headers["Content-Type"] = "text/html"
request.body = "asdf<br />"
self.assertRaises(exception.InvalidContentType,
@@ -89,6 +89,12 @@ class DictSerializerTest(test.TestCase):
serializer.default = lambda x: 'trousers'
self.assertEqual(serializer.serialize({}, 'update'), 'trousers')
+ def test_dispatch_action_None(self):
+ serializer = wsgi.DictSerializer()
+ serializer.create = lambda x: 'pants'
+ serializer.default = lambda x: 'trousers'
+ self.assertEqual(serializer.serialize({}, None), 'trousers')
+
class XMLDictSerializerTest(test.TestCase):
def test_xml(self):
@@ -123,6 +129,12 @@ class TextDeserializerTest(test.TestCase):
deserializer.default = lambda x: 'trousers'
self.assertEqual(deserializer.deserialize({}, 'update'), 'trousers')
+ def test_dispatch_action_None(self):
+ deserializer = wsgi.TextDeserializer()
+ deserializer.create = lambda x: 'pants'
+ deserializer.default = lambda x: 'trousers'
+ self.assertEqual(deserializer.deserialize({}, None), 'trousers')
+
class JSONDeserializerTest(test.TestCase):
def test_json(self):
@@ -171,11 +183,11 @@ class XMLDeserializerTest(test.TestCase):
class ResponseSerializerTest(test.TestCase):
def setUp(self):
class JSONSerializer(object):
- def serialize(self, data):
+ def serialize(self, data, action='default'):
return 'pew_json'
class XMLSerializer(object):
- def serialize(self, data):
+ def serialize(self, data, action='default'):
return 'pew_xml'
self.serializers = {
@@ -211,11 +223,11 @@ class ResponseSerializerTest(test.TestCase):
class RequestDeserializerTest(test.TestCase):
def setUp(self):
class JSONDeserializer(object):
- def deserialize(self, data):
+ def deserialize(self, data, action='default'):
return 'pew_json'
class XMLDeserializer(object):
- def deserialize(self, data):
+ def deserialize(self, data, action='default'):
return 'pew_xml'
self.deserializers = {
diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py
index ecefc464a..2297d2f0e 100644
--- a/nova/tests/fake_flags.py
+++ b/nova/tests/fake_flags.py
@@ -32,7 +32,7 @@ flags.DECLARE('fake_network', 'nova.network.manager')
FLAGS['network_size'].SetDefault(8)
FLAGS['num_networks'].SetDefault(2)
FLAGS['fake_network'].SetDefault(True)
-FLAGS['image_service'].SetDefault('nova.image.local.LocalImageService')
+FLAGS['image_service'].SetDefault('nova.image.fake.FakeImageService')
flags.DECLARE('num_shelves', 'nova.volume.driver')
flags.DECLARE('blades_per_shelf', 'nova.volume.driver')
flags.DECLARE('iscsi_num_targets', 'nova.volume.driver')
diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py
index eb9a3056e..76c03c5fa 100644
--- a/nova/tests/integrated/api/client.py
+++ b/nova/tests/integrated/api/client.py
@@ -221,30 +221,30 @@ class TestOpenStackClient(object):
return self.api_delete('/flavors/%s' % flavor_id)
def get_volume(self, volume_id):
- return self.api_get('/volumes/%s' % volume_id)['volume']
+ return self.api_get('/os-volumes/%s' % volume_id)['volume']
def get_volumes(self, detail=True):
- rel_url = '/volumes/detail' if detail else '/volumes'
+ rel_url = '/os-volumes/detail' if detail else '/os-volumes'
return self.api_get(rel_url)['volumes']
def post_volume(self, volume):
- return self.api_post('/volumes', volume)['volume']
+ return self.api_post('/os-volumes', volume)['volume']
def delete_volume(self, volume_id):
- return self.api_delete('/volumes/%s' % volume_id)
+ return self.api_delete('/os-volumes/%s' % volume_id)
def get_server_volume(self, server_id, attachment_id):
- return self.api_get('/servers/%s/volume_attachments/%s' %
+ return self.api_get('/servers/%s/os-volume_attachments/%s' %
(server_id, attachment_id))['volumeAttachment']
def get_server_volumes(self, server_id):
- return self.api_get('/servers/%s/volume_attachments' %
+ return self.api_get('/servers/%s/os-volume_attachments' %
(server_id))['volumeAttachments']
def post_server_volume(self, server_id, volume_attachment):
- return self.api_post('/servers/%s/volume_attachments' %
+ return self.api_post('/servers/%s/os-volume_attachments' %
(server_id), volume_attachment)['volumeAttachment']
def delete_server_volume(self, server_id, attachment_id):
- return self.api_delete('/servers/%s/volume_attachments/%s' %
+ return self.api_delete('/servers/%s/os-volume_attachments/%s' %
(server_id, attachment_id))
diff --git a/nova/tests/scheduler/test_host_filter.py b/nova/tests/scheduler/test_host_filter.py
index 07817cc5a..10eafde08 100644
--- a/nova/tests/scheduler/test_host_filter.py
+++ b/nova/tests/scheduler/test_host_filter.py
@@ -133,11 +133,11 @@ class HostFilterTestCase(test.TestCase):
raw = ['or',
['and',
['<', '$compute.host_memory_free', 30],
- ['<', '$compute.disk_available', 300]
+ ['<', '$compute.disk_available', 300],
],
['and',
['>', '$compute.host_memory_free', 70],
- ['>', '$compute.disk_available', 700]
+ ['>', '$compute.disk_available', 700],
]
]
cooked = json.dumps(raw)
@@ -183,12 +183,12 @@ class HostFilterTestCase(test.TestCase):
self.assertTrue(hf.filter_hosts(self.zone_manager, json.dumps([])))
self.assertTrue(hf.filter_hosts(self.zone_manager, json.dumps({})))
self.assertTrue(hf.filter_hosts(self.zone_manager, json.dumps(
- ['not', True, False, True, False]
+ ['not', True, False, True, False],
)))
try:
hf.filter_hosts(self.zone_manager, json.dumps(
- 'not', True, False, True, False
+ 'not', True, False, True, False,
))
self.fail("Should give KeyError")
except KeyError, e:
diff --git a/nova/tests/scheduler/test_least_cost_scheduler.py b/nova/tests/scheduler/test_least_cost_scheduler.py
index 506fa62fb..9a5318aee 100644
--- a/nova/tests/scheduler/test_least_cost_scheduler.py
+++ b/nova/tests/scheduler/test_least_cost_scheduler.py
@@ -44,7 +44,7 @@ class WeightedSumTestCase(test.TestCase):
hosts = [
FakeHost(1, 512 * MB, 100),
FakeHost(2, 256 * MB, 400),
- FakeHost(3, 512 * MB, 100)
+ FakeHost(3, 512 * MB, 100),
]
weighted_fns = [
@@ -96,7 +96,7 @@ class LeastCostSchedulerTestCase(test.TestCase):
def test_noop_cost_fn(self):
FLAGS.least_cost_scheduler_cost_functions = [
- 'nova.scheduler.least_cost.noop_cost_fn'
+ 'nova.scheduler.least_cost.noop_cost_fn',
]
FLAGS.noop_cost_fn_weight = 1
@@ -110,7 +110,7 @@ class LeastCostSchedulerTestCase(test.TestCase):
def test_cost_fn_weights(self):
FLAGS.least_cost_scheduler_cost_functions = [
- 'nova.scheduler.least_cost.noop_cost_fn'
+ 'nova.scheduler.least_cost.noop_cost_fn',
]
FLAGS.noop_cost_fn_weight = 2
@@ -124,7 +124,7 @@ class LeastCostSchedulerTestCase(test.TestCase):
def test_fill_first_cost_fn(self):
FLAGS.least_cost_scheduler_cost_functions = [
- 'nova.scheduler.least_cost.fill_first_cost_fn'
+ 'nova.scheduler.least_cost.fill_first_cost_fn',
]
FLAGS.fill_first_cost_fn_weight = 1
diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py
index 50b6b52c6..4be59d411 100644
--- a/nova/tests/scheduler/test_scheduler.py
+++ b/nova/tests/scheduler/test_scheduler.py
@@ -48,6 +48,10 @@ flags.DECLARE('stub_network', 'nova.compute.manager')
flags.DECLARE('instances_path', 'nova.compute.manager')
+FAKE_UUID_NOT_FOUND = 'ffffffff-ffff-ffff-ffff-ffffffffffff'
+FAKE_UUID = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
+
+
class TestDriver(driver.Scheduler):
"""Scheduler Driver for Tests"""
def schedule(context, topic, *args, **kwargs):
@@ -926,12 +930,23 @@ def zone_get_all(context):
]
+def fake_instance_get_by_uuid(context, uuid):
+ if FAKE_UUID_NOT_FOUND:
+ raise exception.InstanceNotFound(instance_id=uuid)
+ else:
+ return {'id': 1}
+
+
class FakeRerouteCompute(api.reroute_compute):
+ def __init__(self, method_name, id_to_return=1):
+ super(FakeRerouteCompute, self).__init__(method_name)
+ self.id_to_return = id_to_return
+
def _call_child_zones(self, zones, function):
return []
def get_collection_context_and_id(self, args, kwargs):
- return ("servers", None, 1)
+ return ("servers", None, self.id_to_return)
def unmarshall_result(self, zone_responses):
return dict(magic="found me")
@@ -960,6 +975,8 @@ class ZoneRedirectTest(test.TestCase):
self.stubs = stubout.StubOutForTesting()
self.stubs.Set(db, 'zone_get_all', zone_get_all)
+ self.stubs.Set(db, 'instance_get_by_uuid',
+ fake_instance_get_by_uuid)
self.enable_zone_routing = FLAGS.enable_zone_routing
FLAGS.enable_zone_routing = True
@@ -976,8 +993,19 @@ class ZoneRedirectTest(test.TestCase):
except api.RedirectResult, e:
self.fail(_("Successful database hit should succeed"))
- def test_trap_not_found_locally(self):
+ def test_trap_not_found_locally_id_passed(self):
+ """When an integer ID is not found locally, we cannot reroute to
+ another zone, so just return InstanceNotFound exception
+ """
decorator = FakeRerouteCompute("foo")
+ self.assertRaises(exception.InstanceNotFound,
+ decorator(go_boom), None, None, 1)
+
+ def test_trap_not_found_locally_uuid_passed(self):
+ """When a UUID is found, if the item isn't found locally, we should
+ try to reroute to a child zone to see if they have it
+ """
+ decorator = FakeRerouteCompute("foo", id_to_return=FAKE_UUID_NOT_FOUND)
try:
result = decorator(go_boom)(None, None, 1)
self.assertFail(_("Should have rerouted."))
@@ -1110,10 +1138,4 @@ class CallZoneMethodTest(test.TestCase):
def test_call_zone_method_generates_exception(self):
context = {}
method = 'raises_exception'
- results = api.call_zone_method(context, method)
-
- # FIXME(sirp): for now the _error_trap code is catching errors and
- # converting them to a ("ERROR", "string") tuples. The code (and this
- # test) should eventually handle real exceptions.
- expected = [(1, ('ERROR', 'testing'))]
- self.assertEqual(expected, results)
+ self.assertRaises(Exception, api.call_zone_method, context, method)
diff --git a/nova/tests/scheduler/test_zone_aware_scheduler.py b/nova/tests/scheduler/test_zone_aware_scheduler.py
index 9f70b9dbc..37c6488cc 100644
--- a/nova/tests/scheduler/test_zone_aware_scheduler.py
+++ b/nova/tests/scheduler/test_zone_aware_scheduler.py
@@ -201,7 +201,7 @@ class ZoneAwareSchedulerTestCase(test.TestCase):
'instance_properties': {},
'instance_type': {},
'filter_driver': 'nova.scheduler.host_filter.AllHostsFilter',
- 'blob': "Non-None blob data"
+ 'blob': "Non-None blob data",
}
result = sched.schedule_run_instance(None, 1, request_spec)
diff --git a/nova/tests/test_api.py b/nova/tests/test_api.py
index 7c0331eff..20b20fcbf 100644
--- a/nova/tests/test_api.py
+++ b/nova/tests/test_api.py
@@ -89,7 +89,7 @@ class FakeHttplibConnection(object):
class XmlConversionTestCase(test.TestCase):
"""Unit test api xml conversion"""
def test_number_conversion(self):
- conv = apirequest._try_convert
+ conv = ec2utils._try_convert
self.assertEqual(conv('None'), None)
self.assertEqual(conv('True'), True)
self.assertEqual(conv('False'), False)
diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py
index 13046f861..6327734f5 100644
--- a/nova/tests/test_cloud.py
+++ b/nova/tests/test_cloud.py
@@ -35,7 +35,7 @@ from nova import utils
from nova.auth import manager
from nova.api.ec2 import cloud
from nova.api.ec2 import ec2utils
-from nova.image import local
+from nova.image import fake
FLAGS = flags.FLAGS
@@ -56,6 +56,7 @@ class CloudTestCase(test.TestCase):
self.compute = self.start_service('compute')
self.scheduter = self.start_service('scheduler')
self.network = self.start_service('network')
+ self.volume = self.start_service('volume')
self.image_service = utils.import_object(FLAGS.image_service)
self.manager = manager.AuthManager()
@@ -69,8 +70,8 @@ class CloudTestCase(test.TestCase):
return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1,
'type': 'machine', 'image_state': 'available'}}
- self.stubs.Set(local.LocalImageService, 'show', fake_show)
- self.stubs.Set(local.LocalImageService, 'show_by_name', fake_show)
+ self.stubs.Set(fake._FakeImageService, 'show', fake_show)
+ self.stubs.Set(fake._FakeImageService, 'show_by_name', fake_show)
# NOTE(vish): set up a manual wait so rpc.cast has a chance to finish
rpc_cast = rpc.cast
@@ -303,7 +304,7 @@ class CloudTestCase(test.TestCase):
def fake_show_none(meh, context, id):
raise exception.ImageNotFound(image_id='bad_image_id')
- self.stubs.Set(local.LocalImageService, 'detail', fake_detail)
+ self.stubs.Set(fake._FakeImageService, 'detail', fake_detail)
# list all
result1 = describe_images(self.context)
result1 = result1['imagesSet'][0]
@@ -317,8 +318,8 @@ class CloudTestCase(test.TestCase):
self.assertEqual(2, len(result3['imagesSet']))
# provide an non-existing image_id
self.stubs.UnsetAll()
- self.stubs.Set(local.LocalImageService, 'show', fake_show_none)
- self.stubs.Set(local.LocalImageService, 'show_by_name', fake_show_none)
+ self.stubs.Set(fake._FakeImageService, 'show', fake_show_none)
+ self.stubs.Set(fake._FakeImageService, 'show_by_name', fake_show_none)
self.assertRaises(exception.ImageNotFound, describe_images,
self.context, ['ami-fake'])
@@ -329,8 +330,8 @@ class CloudTestCase(test.TestCase):
return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1,
'type': 'machine'}, 'is_public': True}
- self.stubs.Set(local.LocalImageService, 'show', fake_show)
- self.stubs.Set(local.LocalImageService, 'show_by_name', fake_show)
+ self.stubs.Set(fake._FakeImageService, 'show', fake_show)
+ self.stubs.Set(fake._FakeImageService, 'show_by_name', fake_show)
result = describe_image_attribute(self.context, 'ami-00000001',
'launchPermission')
self.assertEqual([{'group': 'all'}], result['launchPermission'])
@@ -345,9 +346,9 @@ class CloudTestCase(test.TestCase):
def fake_update(meh, context, image_id, metadata, data=None):
return metadata
- self.stubs.Set(local.LocalImageService, 'show', fake_show)
- self.stubs.Set(local.LocalImageService, 'show_by_name', fake_show)
- self.stubs.Set(local.LocalImageService, 'update', fake_update)
+ self.stubs.Set(fake._FakeImageService, 'show', fake_show)
+ self.stubs.Set(fake._FakeImageService, 'show_by_name', fake_show)
+ self.stubs.Set(fake._FakeImageService, 'update', fake_update)
result = modify_image_attribute(self.context, 'ami-00000001',
'launchPermission', 'add',
user_group=['all'])
@@ -359,7 +360,7 @@ class CloudTestCase(test.TestCase):
def fake_delete(self, context, id):
return None
- self.stubs.Set(local.LocalImageService, 'delete', fake_delete)
+ self.stubs.Set(fake._FakeImageService, 'delete', fake_delete)
# valid image
result = deregister_image(self.context, 'ami-00000001')
self.assertEqual(result['imageId'], 'ami-00000001')
@@ -369,18 +370,25 @@ class CloudTestCase(test.TestCase):
def fake_detail_empty(self, context):
return []
- self.stubs.Set(local.LocalImageService, 'detail', fake_detail_empty)
+ self.stubs.Set(fake._FakeImageService, 'detail', fake_detail_empty)
self.assertRaises(exception.ImageNotFound, deregister_image,
self.context, 'ami-bad001')
- def test_console_output(self):
- instance_type = FLAGS.default_instance_type
- max_count = 1
- kwargs = {'image_id': 'ami-1',
- 'instance_type': instance_type,
- 'max_count': max_count}
+ def _run_instance(self, **kwargs):
rv = self.cloud.run_instances(self.context, **kwargs)
instance_id = rv['instancesSet'][0]['instanceId']
+ return instance_id
+
+ def _run_instance_wait(self, **kwargs):
+ ec2_instance_id = self._run_instance(**kwargs)
+ self._wait_for_running(ec2_instance_id)
+ return ec2_instance_id
+
+ def test_console_output(self):
+ instance_id = self._run_instance(
+ image_id='ami-1',
+ instance_type=FLAGS.default_instance_type,
+ max_count=1)
output = self.cloud.get_console_output(context=self.context,
instance_id=[instance_id])
self.assertEquals(b64decode(output['output']), 'FAKE CONSOLE?OUTPUT')
@@ -389,9 +397,7 @@ class CloudTestCase(test.TestCase):
rv = self.cloud.terminate_instances(self.context, [instance_id])
def test_ajax_console(self):
- kwargs = {'image_id': 'ami-1'}
- rv = self.cloud.run_instances(self.context, **kwargs)
- instance_id = rv['instancesSet'][0]['instanceId']
+ instance_id = self._run_instance(image_id='ami-1')
output = self.cloud.get_ajax_console(context=self.context,
instance_id=[instance_id])
self.assertEquals(output['url'],
@@ -457,6 +463,12 @@ class CloudTestCase(test.TestCase):
self.cloud.delete_key_pair(self.context, 'test')
def test_run_instances(self):
+ # stub out the rpc call
+ def stub_cast(*args, **kwargs):
+ pass
+
+ self.stubs.Set(rpc, 'cast', stub_cast)
+
kwargs = {'image_id': FLAGS.default_image,
'instance_type': FLAGS.default_instance_type,
'max_count': 1}
@@ -466,7 +478,7 @@ class CloudTestCase(test.TestCase):
self.assertEqual(instance['imageId'], 'ami-00000001')
self.assertEqual(instance['displayName'], 'Server 1')
self.assertEqual(instance['instanceId'], 'i-00000001')
- self.assertEqual(instance['instanceState']['name'], 'networking')
+ self.assertEqual(instance['instanceState']['name'], 'scheduling')
self.assertEqual(instance['instanceType'], 'm1.small')
def test_run_instances_image_state_none(self):
@@ -480,7 +492,7 @@ class CloudTestCase(test.TestCase):
'type': 'machine'}}
self.stubs.UnsetAll()
- self.stubs.Set(local.LocalImageService, 'show', fake_show_no_state)
+ self.stubs.Set(fake._FakeImageService, 'show', fake_show_no_state)
self.assertRaises(exception.ApiError, run_instances,
self.context, **kwargs)
@@ -495,7 +507,7 @@ class CloudTestCase(test.TestCase):
'type': 'machine', 'image_state': 'decrypting'}}
self.stubs.UnsetAll()
- self.stubs.Set(local.LocalImageService, 'show', fake_show_decrypt)
+ self.stubs.Set(fake._FakeImageService, 'show', fake_show_decrypt)
self.assertRaises(exception.ApiError, run_instances,
self.context, **kwargs)
@@ -509,7 +521,7 @@ class CloudTestCase(test.TestCase):
return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1,
'type': 'machine'}, 'status': 'active'}
- self.stubs.Set(local.LocalImageService, 'show', fake_show_stat_active)
+ self.stubs.Set(fake._FakeImageService, 'show', fake_show_stat_active)
result = run_instances(self.context, **kwargs)
self.assertEqual(len(result['instancesSet']), 1)
@@ -538,7 +550,9 @@ class CloudTestCase(test.TestCase):
def test_update_of_instance_wont_update_private_fields(self):
inst = db.instance_create(self.context, {})
- self.cloud.update_instance(self.context, inst['id'],
+ ec2_id = ec2utils.id_to_ec2_id(inst['id'])
+ self.cloud.update_instance(self.context, ec2_id,
+ display_name='c00l 1m4g3',
mac_address='DE:AD:BE:EF')
inst = db.instance_get(self.context, inst['id'])
self.assertEqual(None, inst['mac_address'])
@@ -561,3 +575,299 @@ class CloudTestCase(test.TestCase):
vol = db.volume_get(self.context, vol['id'])
self.assertEqual(None, vol['mountpoint'])
db.volume_destroy(self.context, vol['id'])
+
+ def _restart_compute_service(self, periodic_interval=None):
+ """restart compute service. NOTE: fake driver forgets all instances."""
+ self.compute.kill()
+ if periodic_interval:
+ self.compute = self.start_service(
+ 'compute', periodic_interval=periodic_interval)
+ else:
+ self.compute = self.start_service('compute')
+
+ def _wait_for_state(self, ctxt, instance_id, predicate):
+ """Wait for an stopping instance to be a given state"""
+ id = ec2utils.ec2_id_to_id(instance_id)
+ while True:
+ info = self.cloud.compute_api.get(context=ctxt, instance_id=id)
+ LOG.debug(info)
+ if predicate(info):
+ break
+ greenthread.sleep(1)
+
+ def _wait_for_running(self, instance_id):
+ def is_running(info):
+ return info['state_description'] == 'running'
+ self._wait_for_state(self.context, instance_id, is_running)
+
+ def _wait_for_stopped(self, instance_id):
+ def is_stopped(info):
+ return info['state_description'] == 'stopped'
+ self._wait_for_state(self.context, instance_id, is_stopped)
+
+ def _wait_for_terminate(self, instance_id):
+ def is_deleted(info):
+ return info['deleted']
+ elevated = self.context.elevated(read_deleted=True)
+ self._wait_for_state(elevated, instance_id, is_deleted)
+
+ def test_stop_start_instance(self):
+ """Makes sure stop/start instance works"""
+ # enforce periodic tasks run in short time to avoid wait for 60s.
+ self._restart_compute_service(periodic_interval=0.3)
+
+ kwargs = {'image_id': 'ami-1',
+ 'instance_type': FLAGS.default_instance_type,
+ 'max_count': 1, }
+ instance_id = self._run_instance_wait(**kwargs)
+
+ # a running instance can't be started. It is just ignored.
+ result = self.cloud.start_instances(self.context, [instance_id])
+ greenthread.sleep(0.3)
+ self.assertTrue(result)
+
+ result = self.cloud.stop_instances(self.context, [instance_id])
+ greenthread.sleep(0.3)
+ self.assertTrue(result)
+ self._wait_for_stopped(instance_id)
+
+ result = self.cloud.start_instances(self.context, [instance_id])
+ greenthread.sleep(0.3)
+ self.assertTrue(result)
+ self._wait_for_running(instance_id)
+
+ result = self.cloud.stop_instances(self.context, [instance_id])
+ greenthread.sleep(0.3)
+ self.assertTrue(result)
+ self._wait_for_stopped(instance_id)
+
+ result = self.cloud.terminate_instances(self.context, [instance_id])
+ greenthread.sleep(0.3)
+ self.assertTrue(result)
+
+ self._restart_compute_service()
+
+ def _volume_create(self):
+ kwargs = {'status': 'available',
+ 'host': self.volume.host,
+ 'size': 1,
+ 'attach_status': 'detached', }
+ return db.volume_create(self.context, kwargs)
+
+ def _assert_volume_attached(self, vol, instance_id, mountpoint):
+ self.assertEqual(vol['instance_id'], instance_id)
+ self.assertEqual(vol['mountpoint'], mountpoint)
+ self.assertEqual(vol['status'], "in-use")
+ self.assertEqual(vol['attach_status'], "attached")
+
+ def _assert_volume_detached(self, vol):
+ self.assertEqual(vol['instance_id'], None)
+ self.assertEqual(vol['mountpoint'], None)
+ self.assertEqual(vol['status'], "available")
+ self.assertEqual(vol['attach_status'], "detached")
+
+ def test_stop_start_with_volume(self):
+ """Make sure run instance with block device mapping works"""
+
+ # enforce periodic tasks run in short time to avoid wait for 60s.
+ self._restart_compute_service(periodic_interval=0.3)
+
+ vol1 = self._volume_create()
+ vol2 = self._volume_create()
+ kwargs = {'image_id': 'ami-1',
+ 'instance_type': FLAGS.default_instance_type,
+ 'max_count': 1,
+ 'block_device_mapping': [{'device_name': '/dev/vdb',
+ 'volume_id': vol1['id'],
+ 'delete_on_termination': False, },
+ {'device_name': '/dev/vdc',
+ 'volume_id': vol2['id'],
+ 'delete_on_termination': True, },
+ ]}
+ ec2_instance_id = self._run_instance_wait(**kwargs)
+ instance_id = ec2utils.ec2_id_to_id(ec2_instance_id)
+
+ vols = db.volume_get_all_by_instance(self.context, instance_id)
+ self.assertEqual(len(vols), 2)
+ for vol in vols:
+ self.assertTrue(vol['id'] == vol1['id'] or vol['id'] == vol2['id'])
+
+ vol = db.volume_get(self.context, vol1['id'])
+ self._assert_volume_attached(vol, instance_id, '/dev/vdb')
+
+ vol = db.volume_get(self.context, vol2['id'])
+ self._assert_volume_attached(vol, instance_id, '/dev/vdc')
+
+ result = self.cloud.stop_instances(self.context, [ec2_instance_id])
+ self.assertTrue(result)
+ self._wait_for_stopped(ec2_instance_id)
+
+ vol = db.volume_get(self.context, vol1['id'])
+ self._assert_volume_detached(vol)
+ vol = db.volume_get(self.context, vol2['id'])
+ self._assert_volume_detached(vol)
+
+ self.cloud.start_instances(self.context, [ec2_instance_id])
+ self._wait_for_running(ec2_instance_id)
+ vols = db.volume_get_all_by_instance(self.context, instance_id)
+ self.assertEqual(len(vols), 2)
+ for vol in vols:
+ self.assertTrue(vol['id'] == vol1['id'] or vol['id'] == vol2['id'])
+ self.assertTrue(vol['mountpoint'] == '/dev/vdb' or
+ vol['mountpoint'] == '/dev/vdc')
+ self.assertEqual(vol['instance_id'], instance_id)
+ self.assertEqual(vol['status'], "in-use")
+ self.assertEqual(vol['attach_status'], "attached")
+
+ self.cloud.terminate_instances(self.context, [ec2_instance_id])
+ greenthread.sleep(0.3)
+
+ admin_ctxt = context.get_admin_context(read_deleted=False)
+ vol = db.volume_get(admin_ctxt, vol1['id'])
+ self.assertFalse(vol['deleted'])
+ db.volume_destroy(self.context, vol1['id'])
+
+ greenthread.sleep(0.3)
+ admin_ctxt = context.get_admin_context(read_deleted=True)
+ vol = db.volume_get(admin_ctxt, vol2['id'])
+ self.assertTrue(vol['deleted'])
+
+ self._restart_compute_service()
+
+ def test_stop_with_attached_volume(self):
+ """Make sure attach info is reflected to block device mapping"""
+ # enforce periodic tasks run in short time to avoid wait for 60s.
+ self._restart_compute_service(periodic_interval=0.3)
+
+ vol1 = self._volume_create()
+ vol2 = self._volume_create()
+ kwargs = {'image_id': 'ami-1',
+ 'instance_type': FLAGS.default_instance_type,
+ 'max_count': 1,
+ 'block_device_mapping': [{'device_name': '/dev/vdb',
+ 'volume_id': vol1['id'],
+ 'delete_on_termination': True}]}
+ ec2_instance_id = self._run_instance_wait(**kwargs)
+ instance_id = ec2utils.ec2_id_to_id(ec2_instance_id)
+
+ vols = db.volume_get_all_by_instance(self.context, instance_id)
+ self.assertEqual(len(vols), 1)
+ for vol in vols:
+ self.assertEqual(vol['id'], vol1['id'])
+ self._assert_volume_attached(vol, instance_id, '/dev/vdb')
+
+ vol = db.volume_get(self.context, vol2['id'])
+ self._assert_volume_detached(vol)
+
+ self.cloud.compute_api.attach_volume(self.context,
+ instance_id=instance_id,
+ volume_id=vol2['id'],
+ device='/dev/vdc')
+ greenthread.sleep(0.3)
+ vol = db.volume_get(self.context, vol2['id'])
+ self._assert_volume_attached(vol, instance_id, '/dev/vdc')
+
+ self.cloud.compute_api.detach_volume(self.context,
+ volume_id=vol1['id'])
+ greenthread.sleep(0.3)
+ vol = db.volume_get(self.context, vol1['id'])
+ self._assert_volume_detached(vol)
+
+ result = self.cloud.stop_instances(self.context, [ec2_instance_id])
+ self.assertTrue(result)
+ self._wait_for_stopped(ec2_instance_id)
+
+ for vol_id in (vol1['id'], vol2['id']):
+ vol = db.volume_get(self.context, vol_id)
+ self._assert_volume_detached(vol)
+
+ self.cloud.start_instances(self.context, [ec2_instance_id])
+ self._wait_for_running(ec2_instance_id)
+ vols = db.volume_get_all_by_instance(self.context, instance_id)
+ self.assertEqual(len(vols), 1)
+ for vol in vols:
+ self.assertEqual(vol['id'], vol2['id'])
+ self._assert_volume_attached(vol, instance_id, '/dev/vdc')
+
+ vol = db.volume_get(self.context, vol1['id'])
+ self._assert_volume_detached(vol)
+
+ self.cloud.terminate_instances(self.context, [ec2_instance_id])
+ greenthread.sleep(0.3)
+
+ for vol_id in (vol1['id'], vol2['id']):
+ vol = db.volume_get(self.context, vol_id)
+ self.assertEqual(vol['id'], vol_id)
+ self._assert_volume_detached(vol)
+ db.volume_destroy(self.context, vol_id)
+
+ self._restart_compute_service()
+
+ def _create_snapshot(self, ec2_volume_id):
+ result = self.cloud.create_snapshot(self.context,
+ volume_id=ec2_volume_id)
+ greenthread.sleep(0.3)
+ return result['snapshotId']
+
+ def test_run_with_snapshot(self):
+ """Makes sure run/stop/start instance with snapshot works."""
+ vol = self._volume_create()
+ ec2_volume_id = ec2utils.id_to_ec2_id(vol['id'], 'vol-%08x')
+
+ ec2_snapshot1_id = self._create_snapshot(ec2_volume_id)
+ snapshot1_id = ec2utils.ec2_id_to_id(ec2_snapshot1_id)
+ ec2_snapshot2_id = self._create_snapshot(ec2_volume_id)
+ snapshot2_id = ec2utils.ec2_id_to_id(ec2_snapshot2_id)
+
+ kwargs = {'image_id': 'ami-1',
+ 'instance_type': FLAGS.default_instance_type,
+ 'max_count': 1,
+ 'block_device_mapping': [{'device_name': '/dev/vdb',
+ 'snapshot_id': snapshot1_id,
+ 'delete_on_termination': False, },
+ {'device_name': '/dev/vdc',
+ 'snapshot_id': snapshot2_id,
+ 'delete_on_termination': True}]}
+ ec2_instance_id = self._run_instance_wait(**kwargs)
+ instance_id = ec2utils.ec2_id_to_id(ec2_instance_id)
+
+ vols = db.volume_get_all_by_instance(self.context, instance_id)
+ self.assertEqual(len(vols), 2)
+ vol1_id = None
+ vol2_id = None
+ for vol in vols:
+ snapshot_id = vol['snapshot_id']
+ if snapshot_id == snapshot1_id:
+ vol1_id = vol['id']
+ mountpoint = '/dev/vdb'
+ elif snapshot_id == snapshot2_id:
+ vol2_id = vol['id']
+ mountpoint = '/dev/vdc'
+ else:
+ self.fail()
+
+ self._assert_volume_attached(vol, instance_id, mountpoint)
+
+ self.assertTrue(vol1_id)
+ self.assertTrue(vol2_id)
+
+ self.cloud.terminate_instances(self.context, [ec2_instance_id])
+ greenthread.sleep(0.3)
+ self._wait_for_terminate(ec2_instance_id)
+
+ greenthread.sleep(0.3)
+ admin_ctxt = context.get_admin_context(read_deleted=False)
+ vol = db.volume_get(admin_ctxt, vol1_id)
+ self._assert_volume_detached(vol)
+ self.assertFalse(vol['deleted'])
+ db.volume_destroy(self.context, vol1_id)
+
+ greenthread.sleep(0.3)
+ admin_ctxt = context.get_admin_context(read_deleted=True)
+ vol = db.volume_get(admin_ctxt, vol2_id)
+ self.assertTrue(vol['deleted'])
+
+ for snapshot_id in (ec2_snapshot1_id, ec2_snapshot2_id):
+ self.cloud.delete_snapshot(self.context, snapshot_id)
+ greenthread.sleep(0.3)
+ db.volume_destroy(self.context, vol['id'])
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index b4ac2dbc4..439508b27 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -22,21 +22,21 @@ Tests For Compute
import mox
import stubout
+from nova.auth import manager
from nova import compute
+from nova.compute import instance_types
+from nova.compute import manager as compute_manager
+from nova.compute import power_state
from nova import context
from nova import db
+from nova.db.sqlalchemy import models
from nova import exception
from nova import flags
+import nova.image.fake
from nova import log as logging
from nova import rpc
from nova import test
from nova import utils
-from nova.auth import manager
-from nova.compute import instance_types
-from nova.compute import manager as compute_manager
-from nova.compute import power_state
-from nova.db.sqlalchemy import models
-from nova.image import local
LOG = logging.getLogger('nova.tests.compute')
FLAGS = flags.FLAGS
@@ -73,7 +73,7 @@ class ComputeTestCase(test.TestCase):
def fake_show(meh, context, id):
return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1}}
- self.stubs.Set(local.LocalImageService, 'show', fake_show)
+ self.stubs.Set(nova.image.fake._FakeImageService, 'show', fake_show)
def tearDown(self):
self.manager.delete_user(self.user)
@@ -228,6 +228,21 @@ class ComputeTestCase(test.TestCase):
self.assert_(instance_ref['launched_at'] < terminate)
self.assert_(instance_ref['deleted_at'] > terminate)
+ def test_stop(self):
+ """Ensure instance can be stopped"""
+ instance_id = self._create_instance()
+ self.compute.run_instance(self.context, instance_id)
+ self.compute.stop_instance(self.context, instance_id)
+ self.compute.terminate_instance(self.context, instance_id)
+
+ def test_start(self):
+ """Ensure instance can be started"""
+ instance_id = self._create_instance()
+ self.compute.run_instance(self.context, instance_id)
+ self.compute.stop_instance(self.context, instance_id)
+ self.compute.start_instance(self.context, instance_id)
+ self.compute.terminate_instance(self.context, instance_id)
+
def test_pause(self):
"""Ensure instance can be paused"""
instance_id = self._create_instance()
@@ -266,6 +281,14 @@ class ComputeTestCase(test.TestCase):
"File Contents")
self.compute.terminate_instance(self.context, instance_id)
+ def test_agent_update(self):
+ """Ensure instance can have its agent updated"""
+ instance_id = self._create_instance()
+ self.compute.run_instance(self.context, instance_id)
+ self.compute.agent_update(self.context, instance_id,
+ 'http://127.0.0.1/agent', '00112233445566778899aabbccddeeff')
+ self.compute.terminate_instance(self.context, instance_id)
+
def test_snapshot(self):
"""Ensure instance can be snapshotted"""
instance_id = self._create_instance()
diff --git a/nova/tests/test_crypto.py b/nova/tests/test_crypto.py
index 945d78794..6c25b396e 100644
--- a/nova/tests/test_crypto.py
+++ b/nova/tests/test_crypto.py
@@ -16,7 +16,11 @@
Tests for Crypto module.
"""
+import mox
+import stubout
+
from nova import crypto
+from nova import db
from nova import test
@@ -46,3 +50,82 @@ class SymmetricKeyTestCase(test.TestCase):
plain = decrypt(cipher_text)
self.assertEquals(plain_text, plain)
+
+
+class RevokeCertsTest(test.TestCase):
+
+ def setUp(self):
+ super(RevokeCertsTest, self).setUp()
+ self.stubs = stubout.StubOutForTesting()
+
+ def tearDown(self):
+ self.stubs.UnsetAll()
+ super(RevokeCertsTest, self).tearDown()
+
+ def test_revoke_certs_by_user_and_project(self):
+ user_id = 'test_user'
+ project_id = 2
+ file_name = 'test_file'
+
+ def mock_certificate_get_all_by_user_and_project(context,
+ user_id,
+ project_id):
+
+ return [{"user_id": user_id, "project_id": project_id,
+ "file_name": file_name}]
+
+ self.stubs.Set(db, 'certificate_get_all_by_user_and_project',
+ mock_certificate_get_all_by_user_and_project)
+
+ self.mox.StubOutWithMock(crypto, 'revoke_cert')
+ crypto.revoke_cert(project_id, file_name)
+
+ self.mox.ReplayAll()
+
+ crypto.revoke_certs_by_user_and_project(user_id, project_id)
+
+ self.mox.VerifyAll()
+
+ def test_revoke_certs_by_user(self):
+ user_id = 'test_user'
+ project_id = 2
+ file_name = 'test_file'
+
+ def mock_certificate_get_all_by_user(context, user_id):
+
+ return [{"user_id": user_id, "project_id": project_id,
+ "file_name": file_name}]
+
+ self.stubs.Set(db, 'certificate_get_all_by_user',
+ mock_certificate_get_all_by_user)
+
+ self.mox.StubOutWithMock(crypto, 'revoke_cert')
+ crypto.revoke_cert(project_id, mox.IgnoreArg())
+
+ self.mox.ReplayAll()
+
+ crypto.revoke_certs_by_user(user_id)
+
+ self.mox.VerifyAll()
+
+ def test_revoke_certs_by_project(self):
+ user_id = 'test_user'
+ project_id = 2
+ file_name = 'test_file'
+
+ def mock_certificate_get_all_by_project(context, project_id):
+
+ return [{"user_id": user_id, "project_id": project_id,
+ "file_name": file_name}]
+
+ self.stubs.Set(db, 'certificate_get_all_by_project',
+ mock_certificate_get_all_by_project)
+
+ self.mox.StubOutWithMock(crypto, 'revoke_cert')
+ crypto.revoke_cert(project_id, mox.IgnoreArg())
+
+ self.mox.ReplayAll()
+
+ crypto.revoke_certs_by_project(project_id)
+
+ self.mox.VerifyAll()
diff --git a/nova/tests/test_utils.py b/nova/tests/test_utils.py
index 8f7e83c3e..3a3f914e4 100644
--- a/nova/tests/test_utils.py
+++ b/nova/tests/test_utils.py
@@ -275,3 +275,21 @@ class GenericUtilsTestCase(test.TestCase):
# error case
result = utils.parse_server_string('www.exa:mple.com:8443')
self.assertEqual(('', ''), result)
+
+
+class IsUUIDLikeTestCase(test.TestCase):
+ def assertUUIDLike(self, val, expected):
+ result = utils.is_uuid_like(val)
+ self.assertEqual(result, expected)
+
+ def test_good_uuid(self):
+ val = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
+ self.assertUUIDLike(val, True)
+
+ def test_integer_passed(self):
+ val = 1
+ self.assertUUIDLike(val, False)
+
+ def test_non_uuid_string_passed(self):
+ val = 'foo-fooo'
+ self.assertUUIDLike(val, False)
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py
index 3a175b106..d9a514745 100644
--- a/nova/tests/test_xenapi.py
+++ b/nova/tests/test_xenapi.py
@@ -33,12 +33,12 @@ from nova import utils
from nova.auth import manager
from nova.compute import instance_types
from nova.compute import power_state
+from nova import exception
from nova.virt import xenapi_conn
from nova.virt.xenapi import fake as xenapi_fake
from nova.virt.xenapi import volume_utils
+from nova.virt.xenapi import vmops
from nova.virt.xenapi import vm_utils
-from nova.virt.xenapi.vmops import SimpleDH
-from nova.virt.xenapi.vmops import VMOps
from nova.tests.db import fakes as db_fakes
from nova.tests.xenapi import stubs
from nova.tests.glance import stubs as glance_stubs
@@ -84,7 +84,8 @@ class XenAPIVolumeTestCase(test.TestCase):
'ramdisk_id': 3,
'instance_type_id': '3', # m1.large
'mac_address': 'aa:bb:cc:dd:ee:ff',
- 'os_type': 'linux'}
+ 'os_type': 'linux',
+ 'architecture': 'x86-64'}
def _create_volume(self, size='0'):
"""Create a volume object."""
@@ -191,7 +192,7 @@ class XenAPIVMTestCase(test.TestCase):
stubs.stubout_get_this_vm_uuid(self.stubs)
stubs.stubout_stream_disk(self.stubs)
stubs.stubout_is_vdi_pv(self.stubs)
- self.stubs.Set(VMOps, 'reset_network', reset_network)
+ self.stubs.Set(vmops.VMOps, 'reset_network', reset_network)
stubs.stub_out_vm_methods(self.stubs)
glance_stubs.stubout_glance_client(self.stubs)
fake_utils.stub_out_utils_execute(self.stubs)
@@ -211,7 +212,8 @@ class XenAPIVMTestCase(test.TestCase):
'ramdisk_id': 3,
'instance_type_id': '3', # m1.large
'mac_address': 'aa:bb:cc:dd:ee:ff',
- 'os_type': 'linux'}
+ 'os_type': 'linux',
+ 'architecture': 'x86-64'}
instance = db.instance_create(self.context, values)
self.conn.spawn(instance)
@@ -228,6 +230,23 @@ class XenAPIVMTestCase(test.TestCase):
instance = self._create_instance()
self.conn.get_diagnostics(instance)
+ def test_instance_snapshot_fails_with_no_primary_vdi(self):
+ def create_bad_vbd(vm_ref, vdi_ref):
+ vbd_rec = {'VM': vm_ref,
+ 'VDI': vdi_ref,
+ 'userdevice': 'fake',
+ 'currently_attached': False}
+ vbd_ref = xenapi_fake._create_object('VBD', vbd_rec)
+ xenapi_fake.after_VBD_create(vbd_ref, vbd_rec)
+ return vbd_ref
+
+ self.stubs.Set(xenapi_fake, 'create_vbd', create_bad_vbd)
+ stubs.stubout_instance_snapshot(self.stubs)
+ instance = self._create_instance()
+
+ name = "MySnapshot"
+ self.assertRaises(exception.Error, self.conn.snapshot, instance, name)
+
def test_instance_snapshot(self):
stubs.stubout_instance_snapshot(self.stubs)
instance = self._create_instance()
@@ -331,7 +350,7 @@ class XenAPIVMTestCase(test.TestCase):
def check_vm_params_for_linux(self):
self.assertEquals(self.vm['platform']['nx'], 'false')
- self.assertEquals(self.vm['PV_args'], 'clocksource=jiffies')
+ self.assertEquals(self.vm['PV_args'], '')
self.assertEquals(self.vm['PV_bootloader'], 'pygrub')
# check that these are not set
@@ -352,7 +371,8 @@ class XenAPIVMTestCase(test.TestCase):
def _test_spawn(self, image_ref, kernel_id, ramdisk_id,
instance_type_id="3", os_type="linux",
- instance_id=1, check_injection=False):
+ architecture="x86-64", instance_id=1,
+ check_injection=False):
stubs.stubout_loopingcall_start(self.stubs)
values = {'id': instance_id,
'project_id': self.project.id,
@@ -362,11 +382,14 @@ class XenAPIVMTestCase(test.TestCase):
'ramdisk_id': ramdisk_id,
'instance_type_id': instance_type_id,
'mac_address': 'aa:bb:cc:dd:ee:ff',
- 'os_type': os_type}
+ 'os_type': os_type,
+ 'architecture': architecture}
instance = db.instance_create(self.context, values)
self.conn.spawn(instance)
self.create_vm_record(self.conn, os_type, instance_id)
self.check_vm_record(self.conn, check_injection)
+ self.assertTrue(instance.os_type)
+ self.assertTrue(instance.architecture)
def test_spawn_not_enough_memory(self):
FLAGS.xenapi_image_service = 'glance'
@@ -391,7 +414,7 @@ class XenAPIVMTestCase(test.TestCase):
def test_spawn_vhd_glance_linux(self):
FLAGS.xenapi_image_service = 'glance'
self._test_spawn(glance_stubs.FakeGlance.IMAGE_VHD, None, None,
- os_type="linux")
+ os_type="linux", architecture="x86-64")
self.check_vm_params_for_linux()
def test_spawn_vhd_glance_swapdisk(self):
@@ -420,7 +443,7 @@ class XenAPIVMTestCase(test.TestCase):
def test_spawn_vhd_glance_windows(self):
FLAGS.xenapi_image_service = 'glance'
self._test_spawn(glance_stubs.FakeGlance.IMAGE_VHD, None, None,
- os_type="windows")
+ os_type="windows", architecture="i386")
self.check_vm_params_for_windows()
def test_spawn_glance(self):
@@ -571,7 +594,8 @@ class XenAPIVMTestCase(test.TestCase):
'ramdisk_id': 3,
'instance_type_id': '3', # m1.large
'mac_address': 'aa:bb:cc:dd:ee:ff',
- 'os_type': 'linux'}
+ 'os_type': 'linux',
+ 'architecture': 'x86-64'}
instance = db.instance_create(self.context, values)
self.conn.spawn(instance)
return instance
@@ -581,8 +605,8 @@ class XenAPIDiffieHellmanTestCase(test.TestCase):
"""Unit tests for Diffie-Hellman code."""
def setUp(self):
super(XenAPIDiffieHellmanTestCase, self).setUp()
- self.alice = SimpleDH()
- self.bob = SimpleDH()
+ self.alice = vmops.SimpleDH()
+ self.bob = vmops.SimpleDH()
def test_shared(self):
alice_pub = self.alice.get_public()
@@ -646,7 +670,8 @@ class XenAPIMigrateInstance(test.TestCase):
'local_gb': 5,
'instance_type_id': '3', # m1.large
'mac_address': 'aa:bb:cc:dd:ee:ff',
- 'os_type': 'linux'}
+ 'os_type': 'linux',
+ 'architecture': 'x86-64'}
fake_utils.stub_out_utils_execute(self.stubs)
stubs.stub_out_migration_methods(self.stubs)
@@ -685,6 +710,7 @@ class XenAPIDetermineDiskImageTestCase(test.TestCase):
self.fake_instance = FakeInstance()
self.fake_instance.id = 42
self.fake_instance.os_type = 'linux'
+ self.fake_instance.architecture = 'x86-64'
def assert_disk_type(self, disk_type):
dt = vm_utils.VMHelper.determine_disk_image_type(
@@ -729,6 +755,28 @@ class XenAPIDetermineDiskImageTestCase(test.TestCase):
self.assert_disk_type(vm_utils.ImageType.DISK_VHD)
+class CompareVersionTestCase(test.TestCase):
+ def test_less_than(self):
+ """Test that cmp_version compares a as less than b"""
+ self.assertTrue(vmops.cmp_version('1.2.3.4', '1.2.3.5') < 0)
+
+ def test_greater_than(self):
+ """Test that cmp_version compares a as greater than b"""
+ self.assertTrue(vmops.cmp_version('1.2.3.5', '1.2.3.4') > 0)
+
+ def test_equal(self):
+ """Test that cmp_version compares a as equal to b"""
+ self.assertTrue(vmops.cmp_version('1.2.3.4', '1.2.3.4') == 0)
+
+ def test_non_lexical(self):
+ """Test that cmp_version compares non-lexically"""
+ self.assertTrue(vmops.cmp_version('1.2.3.10', '1.2.3.4') > 0)
+
+ def test_length(self):
+ """Test that cmp_version compares by length as last resort"""
+ self.assertTrue(vmops.cmp_version('1.2.3', '1.2.3.4') < 0)
+
+
class FakeXenApi(object):
"""Fake XenApi for testing HostState."""