diff options
| author | Isaku Yamahata <yamahata@valinux.co.jp> | 2011-08-02 11:36:58 +0900 |
|---|---|---|
| committer | Isaku Yamahata <yamahata@valinux.co.jp> | 2011-08-02 11:36:58 +0900 |
| commit | 0ffc3b80490c24ee116f5be070249dcbbed9357b (patch) | |
| tree | 74b5a542119899a9b483288d2fa6a354751d4090 /nova/tests | |
| parent | a52b643b18e1bac18b642ecfd781809eb5612763 (diff) | |
| parent | bdcfaa5b927a096f507fb0f7e2d81989173957f8 (diff) | |
merged with nova trunk
Diffstat (limited to 'nova/tests')
45 files changed, 2914 insertions, 1316 deletions
diff --git a/nova/tests/api/openstack/contrib/test_floating_ips.py b/nova/tests/api/openstack/contrib/test_floating_ips.py index de006d088..50ad7de08 100644 --- a/nova/tests/api/openstack/contrib/test_floating_ips.py +++ b/nova/tests/api/openstack/contrib/test_floating_ips.py @@ -74,12 +74,8 @@ class FloatingIpTest(test.TestCase): def setUp(self): super(FloatingIpTest, self).setUp() self.controller = FloatingIPController() - self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.reset_fake_data() - fakes.FakeAuthDatabase.data = {} fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) - fakes.stub_out_auth(self.stubs) self.stubs.Set(network.api.API, "get_floating_ip", network_api_get_floating_ip) self.stubs.Set(network.api.API, "list_floating_ips", @@ -96,7 +92,6 @@ class FloatingIpTest(test.TestCase): self._create_floating_ip() def tearDown(self): - self.stubs.UnsetAll() self._delete_floating_ip() super(FloatingIpTest, self).tearDown() diff --git a/nova/tests/api/openstack/contrib/test_multinic_xs.py b/nova/tests/api/openstack/contrib/test_multinic_xs.py index b0a9f7676..ac28f6be6 100644 --- a/nova/tests/api/openstack/contrib/test_multinic_xs.py +++ b/nova/tests/api/openstack/contrib/test_multinic_xs.py @@ -42,22 +42,14 @@ def compute_api_remove_fixed_ip(self, context, instance_id, address): class FixedIpTest(test.TestCase): def setUp(self): super(FixedIpTest, self).setUp() - self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.reset_fake_data() - fakes.FakeAuthDatabase.data = {} fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) - fakes.stub_out_auth(self.stubs) self.stubs.Set(compute.api.API, "add_fixed_ip", compute_api_add_fixed_ip) self.stubs.Set(compute.api.API, "remove_fixed_ip", compute_api_remove_fixed_ip) self.context = context.get_admin_context() - def tearDown(self): - self.stubs.UnsetAll() - super(FixedIpTest, self).tearDown() - def test_add_fixed_ip(self): global last_add_fixed_ip last_add_fixed_ip = (None, None) diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 26b1de818..28969d5f8 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -29,6 +29,7 @@ from glance.common import exception as glance_exc from nova import context from nova import exception as exc from nova import utils +from nova import wsgi import nova.api.openstack.auth from nova.api import openstack from nova.api.openstack import auth @@ -40,14 +41,13 @@ import nova.image.fake from nova.image import glance from nova.image import service from nova.tests import fake_flags -from nova.wsgi import Router class Context(object): pass -class FakeRouter(Router): +class FakeRouter(wsgi.Router): def __init__(self): pass @@ -68,21 +68,30 @@ def fake_auth_init(self, application): @webob.dec.wsgify def fake_wsgi(self, req): - req.environ['nova.context'] = context.RequestContext(1, 1) return self.application -def wsgi_app(inner_app10=None, inner_app11=None): +def wsgi_app(inner_app10=None, inner_app11=None, fake_auth=True): if not inner_app10: inner_app10 = openstack.APIRouterV10() if not inner_app11: inner_app11 = openstack.APIRouterV11() - mapper = urlmap.URLMap() - api10 = openstack.FaultWrapper(auth.AuthMiddleware( + + if fake_auth: + ctxt = context.RequestContext('fake', 'fake') + api10 = openstack.FaultWrapper(wsgi.InjectContext(ctxt, + limits.RateLimitingMiddleware(inner_app10))) + api11 = openstack.FaultWrapper(wsgi.InjectContext(ctxt, + limits.RateLimitingMiddleware( + extensions.ExtensionMiddleware(inner_app11)))) + else: + api10 = openstack.FaultWrapper(auth.AuthMiddleware( limits.RateLimitingMiddleware(inner_app10))) - api11 = openstack.FaultWrapper(auth.AuthMiddleware( + api11 = openstack.FaultWrapper(auth.AuthMiddleware( limits.RateLimitingMiddleware( extensions.ExtensionMiddleware(inner_app11)))) + Auth = auth + mapper = urlmap.URLMap() mapper['/v1.0'] = api10 mapper['/v1.1'] = api11 mapper['/'] = openstack.FaultWrapper(versions.Versions()) @@ -359,17 +368,18 @@ class FakeAuthManager(object): if admin is not None: user.admin = admin - def is_admin(self, user): + def is_admin(self, user_id): + user = self.get_user(user_id) return user.admin - def is_project_member(self, user, project): + def is_project_member(self, user_id, project): if not isinstance(project, Project): try: project = self.get_project(project) except exc.NotFound: raise webob.exc.HTTPUnauthorized() - return ((user.id in project.member_ids) or - (user.id == project.project_manager_id)) + return ((user_id in project.member_ids) or + (user_id == project.project_manager_id)) def create_project(self, name, manager_user, description=None, member_users=None): @@ -396,13 +406,13 @@ class FakeAuthManager(object): else: raise exc.NotFound - def get_projects(self, user=None): - if not user: + def get_projects(self, user_id=None): + if not user_id: return FakeAuthManager.projects.values() else: return [p for p in FakeAuthManager.projects.values() - if (user.id in p.member_ids) or - (user.id == p.project_manager_id)] + if (user_id in p.member_ids) or + (user_id == p.project_manager_id)] class FakeRateLimiter(object): diff --git a/nova/tests/api/openstack/test_accounts.py b/nova/tests/api/openstack/test_accounts.py index 64abcf48c..89dbf5213 100644 --- a/nova/tests/api/openstack/test_accounts.py +++ b/nova/tests/api/openstack/test_accounts.py @@ -16,7 +16,6 @@ import json -import stubout import webob from nova import flags @@ -41,7 +40,7 @@ def fake_admin_check(self, req): class AccountsTest(test.TestCase): def setUp(self): super(AccountsTest, self).setUp() - self.stubs = stubout.StubOutForTesting() + self.flags(allow_admin_api=True) self.stubs.Set(accounts.Controller, '__init__', fake_init) self.stubs.Set(accounts.Controller, '_check_admin', @@ -52,8 +51,6 @@ class AccountsTest(test.TestCase): fakes.stub_out_rate_limiting(self.stubs) fakes.stub_out_auth(self.stubs) - self.allow_admin = FLAGS.allow_admin_api - FLAGS.allow_admin_api = True fakemgr = fakes.FakeAuthManager() joeuser = User('id1', 'guy1', 'acc1', 'secret1', False) superuser = User('id2', 'guy2', 'acc2', 'secret2', True) @@ -62,11 +59,6 @@ class AccountsTest(test.TestCase): fakemgr.create_project('test1', joeuser) fakemgr.create_project('test2', superuser) - def tearDown(self): - self.stubs.UnsetAll() - FLAGS.allow_admin_api = self.allow_admin - super(AccountsTest, self).tearDown() - def test_get_account(self): req = webob.Request.blank('/v1.0/accounts/test1') res = req.get_response(fakes.wsgi_app()) diff --git a/nova/tests/api/openstack/test_adminapi.py b/nova/tests/api/openstack/test_adminapi.py index e87255b18..b83de40cf 100644 --- a/nova/tests/api/openstack/test_adminapi.py +++ b/nova/tests/api/openstack/test_adminapi.py @@ -16,14 +16,10 @@ # under the License. -import stubout import webob -from paste import urlmap from nova import flags from nova import test -from nova.api import openstack -from nova.api.openstack import auth from nova.tests.api.openstack import fakes FLAGS = flags.FLAGS @@ -33,21 +29,12 @@ class AdminAPITest(test.TestCase): def setUp(self): super(AdminAPITest, self).setUp() - self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.reset_fake_data() - fakes.FakeAuthDatabase.data = {} fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) - fakes.stub_out_auth(self.stubs) self.allow_admin = FLAGS.allow_admin_api - def tearDown(self): - self.stubs.UnsetAll() - FLAGS.allow_admin_api = self.allow_admin - super(AdminAPITest, self).tearDown() - def test_admin_enabled(self): - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) # We should still be able to access public operations. req = webob.Request.blank('/v1.0/flavors') res = req.get_response(fakes.wsgi_app()) @@ -55,7 +42,7 @@ class AdminAPITest(test.TestCase): # TODO: Confirm admin operations are available. def test_admin_disabled(self): - FLAGS.allow_admin_api = False + self.flags(allow_admin_api=False) # We should still be able to access public operations. req = webob.Request.blank('/v1.0/flavors') res = req.get_response(fakes.wsgi_app()) diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index af3478c7d..306ae1aa0 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -17,14 +17,12 @@ import datetime -import stubout import webob import webob.dec import nova.api import nova.api.openstack.auth import nova.auth.manager -from nova import auth from nova import context from nova import db from nova import test @@ -35,7 +33,6 @@ class Test(test.TestCase): def setUp(self): super(Test, self).setUp() - self.stubs = stubout.StubOutForTesting() self.stubs.Set(nova.api.openstack.auth.AuthMiddleware, '__init__', fakes.fake_auth_init) self.stubs.Set(context, 'RequestContext', fakes.FakeRequestContext) @@ -45,7 +42,6 @@ class Test(test.TestCase): fakes.stub_out_networking(self.stubs) def tearDown(self): - self.stubs.UnsetAll() fakes.fake_data_store = {} super(Test, self).tearDown() @@ -57,7 +53,7 @@ class Test(test.TestCase): req = webob.Request.blank('/v1.0/') req.headers['X-Auth-User'] = 'user1' req.headers['X-Auth-Key'] = 'user1_key' - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '204 No Content') self.assertEqual(len(result.headers['X-Auth-Token']), 40) self.assertEqual(result.headers['X-CDN-Management-Url'], @@ -73,7 +69,7 @@ class Test(test.TestCase): req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'}) req.headers['X-Auth-User'] = 'user1' req.headers['X-Auth-Key'] = 'user1_key' - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '204 No Content') self.assertEqual(len(result.headers['X-Auth-Token']), 40) self.assertEqual(result.headers['X-Server-Management-Url'], @@ -86,7 +82,7 @@ class Test(test.TestCase): self.stubs.Set(nova.api.openstack, 'APIRouterV10', fakes.FakeRouter) req = webob.Request.blank('/v1.0/fake') req.headers['X-Auth-Token'] = token - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '200 OK') self.assertEqual(result.headers['X-Test-Success'], 'True') @@ -110,7 +106,7 @@ class Test(test.TestCase): req = webob.Request.blank('/v1.0/') req.headers['X-Auth-Token'] = 'token_hash' - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '401 Unauthorized') self.assertEqual(self.destroy_called, True) @@ -124,7 +120,7 @@ class Test(test.TestCase): req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'}) req.headers['X-Auth-User'] = 'user1' req.headers['X-Auth-Key'] = 'user1_key' - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '204 No Content') token = result.headers['X-Auth-Token'] @@ -132,7 +128,7 @@ class Test(test.TestCase): req = webob.Request.blank('/v1.0/fake') req.headers['X-Auth-Token'] = token req.headers['X-Auth-Project-Id'] = 'user2_project' - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '200 OK') self.assertEqual(result.headers['X-Test-Success'], 'True') @@ -140,7 +136,7 @@ class Test(test.TestCase): req = webob.Request.blank('/v1.0/') req.headers['X-Auth-User'] = 'unknown_user' req.headers['X-Auth-Key'] = 'unknown_user_key' - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '401 Unauthorized') def test_bad_user_good_key(self): @@ -151,18 +147,18 @@ class Test(test.TestCase): req = webob.Request.blank('/v1.0/') req.headers['X-Auth-User'] = 'unknown_user' req.headers['X-Auth-Key'] = 'user1_key' - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '401 Unauthorized') def test_no_user(self): req = webob.Request.blank('/v1.0/') - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '401 Unauthorized') def test_bad_token(self): req = webob.Request.blank('/v1.0/') req.headers['X-Auth-Token'] = 'unknown_token' - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '401 Unauthorized') def test_bad_project(self): @@ -177,7 +173,7 @@ class Test(test.TestCase): req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'}) req.headers['X-Auth-User'] = 'user1' req.headers['X-Auth-Key'] = 'user1_key' - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '204 No Content') token = result.headers['X-Auth-Token'] @@ -185,7 +181,7 @@ class Test(test.TestCase): req = webob.Request.blank('/v1.0/fake') req.headers['X-Auth-Token'] = token req.headers['X-Auth-Project-Id'] = 'user2_project' - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '401 Unauthorized') def test_not_existing_project(self): @@ -197,7 +193,7 @@ class Test(test.TestCase): req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'}) req.headers['X-Auth-User'] = 'user1' req.headers['X-Auth-Key'] = 'user1_key' - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '204 No Content') token = result.headers['X-Auth-Token'] @@ -205,7 +201,7 @@ class Test(test.TestCase): req = webob.Request.blank('/v1.0/fake') req.headers['X-Auth-Token'] = token req.headers['X-Auth-Project-Id'] = 'unknown_project' - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '401 Unauthorized') @@ -226,20 +222,19 @@ class TestFunctional(test.TestCase): req = webob.Request.blank('/v1.0/') req.headers['X-Auth-Token'] = 'test_token_hash' - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '401 Unauthorized') def test_token_doesnotexist(self): req = webob.Request.blank('/v1.0/') req.headers['X-Auth-Token'] = 'nonexistant_token_hash' - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '401 Unauthorized') class TestLimiter(test.TestCase): def setUp(self): super(TestLimiter, self).setUp() - self.stubs = stubout.StubOutForTesting() self.stubs.Set(nova.api.openstack.auth.AuthMiddleware, '__init__', fakes.fake_auth_init) self.stubs.Set(context, 'RequestContext', fakes.FakeRequestContext) @@ -248,7 +243,6 @@ class TestLimiter(test.TestCase): fakes.stub_out_networking(self.stubs) def tearDown(self): - self.stubs.UnsetAll() fakes.fake_data_store = {} super(TestLimiter, self).tearDown() @@ -261,7 +255,7 @@ class TestLimiter(test.TestCase): req = webob.Request.blank('/v1.0/') req.headers['X-Auth-User'] = 'user1' req.headers['X-Auth-Key'] = 'user1_key' - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(len(result.headers['X-Auth-Token']), 40) token = result.headers['X-Auth-Token'] @@ -269,6 +263,6 @@ class TestLimiter(test.TestCase): req = webob.Request.blank('/v1.0/fake') req.method = 'POST' req.headers['X-Auth-Token'] = token - result = req.get_response(fakes.wsgi_app()) + result = req.get_response(fakes.wsgi_app(fake_auth=False)) self.assertEqual(result.status, '200 OK') self.assertEqual(result.headers['X-Test-Success'], 'True') diff --git a/nova/tests/api/openstack/test_common.py b/nova/tests/api/openstack/test_common.py index 4c4d03995..0b76841f0 100644 --- a/nova/tests/api/openstack/test_common.py +++ b/nova/tests/api/openstack/test_common.py @@ -20,6 +20,7 @@ Test suites for 'common' code used throughout the OpenStack HTTP API. """ import webob.exc +import xml.dom.minidom as minidom from webob import Request @@ -247,3 +248,221 @@ class MiscFunctionsTest(test.TestCase): self.assertRaises(ValueError, common.get_id_from_href, fixture) + + def test_get_version_from_href(self): + fixture = 'http://www.testsite.com/v1.1/images' + expected = '1.1' + actual = common.get_version_from_href(fixture) + self.assertEqual(actual, expected) + + def test_get_version_from_href_2(self): + fixture = 'http://www.testsite.com/v1.1' + expected = '1.1' + actual = common.get_version_from_href(fixture) + self.assertEqual(actual, expected) + + def test_get_version_from_href_default(self): + fixture = 'http://www.testsite.com/images' + expected = '1.0' + actual = common.get_version_from_href(fixture) + self.assertEqual(actual, expected) + + +class MetadataXMLDeserializationTest(test.TestCase): + + deserializer = common.MetadataXMLDeserializer() + + def test_create(self): + request_body = """ + <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> + <meta key='123'>asdf</meta> + <meta key='567'>jkl;</meta> + </metadata>""" + output = self.deserializer.deserialize(request_body, 'create') + expected = {"body": {"metadata": {"123": "asdf", "567": "jkl;"}}} + self.assertEquals(output, expected) + + def test_create_empty(self): + request_body = """ + <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"/>""" + output = self.deserializer.deserialize(request_body, 'create') + expected = {"body": {"metadata": {}}} + self.assertEquals(output, expected) + + def test_update_all(self): + request_body = """ + <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> + <meta key='123'>asdf</meta> + <meta key='567'>jkl;</meta> + </metadata>""" + output = self.deserializer.deserialize(request_body, 'update_all') + expected = {"body": {"metadata": {"123": "asdf", "567": "jkl;"}}} + self.assertEquals(output, expected) + + def test_update(self): + request_body = """ + <meta xmlns="http://docs.openstack.org/compute/api/v1.1" + key='123'>asdf</meta>""" + output = self.deserializer.deserialize(request_body, 'update') + expected = {"body": {"meta": {"123": "asdf"}}} + self.assertEquals(output, expected) + + +class MetadataXMLSerializationTest(test.TestCase): + + def test_index(self): + serializer = common.MetadataXMLSerializer() + fixture = { + 'metadata': { + 'one': 'two', + 'three': 'four', + }, + } + output = serializer.serialize(fixture, 'index') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(""" + <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> + <meta key="three"> + four + </meta> + <meta key="one"> + two + </meta> + </metadata> + """.replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_index_null(self): + serializer = common.MetadataXMLSerializer() + fixture = { + 'metadata': { + None: None, + }, + } + output = serializer.serialize(fixture, 'index') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(""" + <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> + <meta key="None"> + None + </meta> + </metadata> + """.replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_index_unicode(self): + serializer = common.MetadataXMLSerializer() + fixture = { + 'metadata': { + u'three': u'Jos\xe9', + }, + } + output = serializer.serialize(fixture, 'index') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(u""" + <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> + <meta key="three"> + Jos\xe9 + </meta> + </metadata> + """.encode("UTF-8").replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_show(self): + serializer = common.MetadataXMLSerializer() + fixture = { + 'meta': { + 'one': 'two', + }, + } + output = serializer.serialize(fixture, 'show') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(""" + <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one"> + two + </meta> + """.replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_update_all(self): + serializer = common.MetadataXMLSerializer() + fixture = { + 'metadata': { + 'key6': 'value6', + 'key4': 'value4', + }, + } + output = serializer.serialize(fixture, 'update_all') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(""" + <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> + <meta key="key6"> + value6 + </meta> + <meta key="key4"> + value4 + </meta> + </metadata> + """.replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_update_item(self): + serializer = common.MetadataXMLSerializer() + fixture = { + 'meta': { + 'one': 'two', + }, + } + output = serializer.serialize(fixture, 'update') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(""" + <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one"> + two + </meta> + """.replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_create(self): + serializer = common.MetadataXMLSerializer() + fixture = { + 'metadata': { + 'key9': 'value9', + 'key2': 'value2', + 'key1': 'value1', + }, + } + output = serializer.serialize(fixture, 'create') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(""" + <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> + <meta key="key2"> + value2 + </meta> + <meta key="key9"> + value9 + </meta> + <meta key="key1"> + value1 + </meta> + </metadata> + """.replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_delete(self): + serializer = common.MetadataXMLSerializer() + output = serializer.serialize(None, 'delete') + self.assertEqual(output, '') diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py index 697c62e5c..47c37225c 100644 --- a/nova/tests/api/openstack/test_extensions.py +++ b/nova/tests/api/openstack/test_extensions.py @@ -16,13 +16,13 @@ # under the License. import json -import stubout -import unittest -import webob import os.path +import webob +from xml.etree import ElementTree from nova import context from nova import flags +from nova import test from nova.api import openstack from nova.api.openstack import extensions from nova.api.openstack import flavors @@ -30,7 +30,8 @@ from nova.api.openstack import wsgi from nova.tests.api.openstack import fakes FLAGS = flags.FLAGS - +NS = "{http://docs.openstack.org/compute/api/v1.1}" +ATOMNS = "{http://www.w3.org/2005/Atom}" response_body = "Try to say this Mr. Knox, sir..." @@ -78,24 +79,109 @@ class StubExtensionManager(object): return request_extensions -class ExtensionControllerTest(unittest.TestCase): +class ExtensionControllerTest(test.TestCase): + + def setUp(self): + super(ExtensionControllerTest, self).setUp() + ext_path = os.path.join(os.path.dirname(__file__), "extensions") + self.flags(osapi_extensions_path=ext_path) + + def test_list_extensions_json(self): + app = openstack.APIRouterV11() + ext_midware = extensions.ExtensionMiddleware(app) + request = webob.Request.blank("/extensions") + response = request.get_response(ext_midware) + self.assertEqual(200, response.status_int) + + # Make sure we have all the extensions. + data = json.loads(response.body) + names = [x['name'] for x in data['extensions']] + names.sort() + self.assertEqual(names, ["FlavorExtraSpecs", "Floating_ips", + "Fox In Socks", "Hosts", "Multinic", "Volumes"]) + + # Make sure that at least Fox in Sox is correct. + (fox_ext,) = [ + x for x in data['extensions'] if x['alias'] == 'FOXNSOX'] + self.assertEqual(fox_ext, { + 'namespace': 'http://www.fox.in.socks/api/ext/pie/v1.0', + 'name': 'Fox In Socks', + 'updated': '2011-01-22T13:25:27-06:00', + 'description': 'The Fox In Socks Extension', + 'alias': 'FOXNSOX', + 'links': [], + }, + ) + + def test_get_extension_json(self): + app = openstack.APIRouterV11() + ext_midware = extensions.ExtensionMiddleware(app) + request = webob.Request.blank("/extensions/FOXNSOX") + response = request.get_response(ext_midware) + self.assertEqual(200, response.status_int) - def test_index(self): + data = json.loads(response.body) + self.assertEqual(data['extension'], { + "namespace": "http://www.fox.in.socks/api/ext/pie/v1.0", + "name": "Fox In Socks", + "updated": "2011-01-22T13:25:27-06:00", + "description": "The Fox In Socks Extension", + "alias": "FOXNSOX", + "links": [], + }, + ) + + def test_list_extensions_xml(self): app = openstack.APIRouterV11() ext_midware = extensions.ExtensionMiddleware(app) request = webob.Request.blank("/extensions") + request.accept = "application/xml" response = request.get_response(ext_midware) self.assertEqual(200, response.status_int) + print response.body + + root = ElementTree.XML(response.body) + self.assertEqual(root.tag.split('extensions')[0], NS) + + # Make sure we have all the extensions. + exts = root.findall('{0}extension'.format(NS)) + self.assertEqual(len(exts), 6) + + # Make sure that at least Fox in Sox is correct. + (fox_ext,) = [x for x in exts if x.get('alias') == 'FOXNSOX'] + self.assertEqual(fox_ext.get('name'), 'Fox In Socks') + self.assertEqual(fox_ext.get('namespace'), + 'http://www.fox.in.socks/api/ext/pie/v1.0') + self.assertEqual(fox_ext.get('updated'), '2011-01-22T13:25:27-06:00') + self.assertEqual(fox_ext.findtext('{0}description'.format(NS)), + 'The Fox In Socks Extension') - def test_get_by_alias(self): + def test_get_extension_xml(self): app = openstack.APIRouterV11() ext_midware = extensions.ExtensionMiddleware(app) request = webob.Request.blank("/extensions/FOXNSOX") + request.accept = "application/xml" response = request.get_response(ext_midware) self.assertEqual(200, response.status_int) + print response.body + root = ElementTree.XML(response.body) + self.assertEqual(root.tag.split('extension')[0], NS) + self.assertEqual(root.get('alias'), 'FOXNSOX') + self.assertEqual(root.get('name'), 'Fox In Socks') + self.assertEqual(root.get('namespace'), + 'http://www.fox.in.socks/api/ext/pie/v1.0') + self.assertEqual(root.get('updated'), '2011-01-22T13:25:27-06:00') + self.assertEqual(root.findtext('{0}description'.format(NS)), + 'The Fox In Socks Extension') -class ResourceExtensionTest(unittest.TestCase): + +class ResourceExtensionTest(test.TestCase): + + def setUp(self): + super(ResourceExtensionTest, self).setUp() + ext_path = os.path.join(os.path.dirname(__file__), "extensions") + self.flags(osapi_extensions_path=ext_path) def test_no_extension_present(self): manager = StubExtensionManager(None) @@ -133,13 +219,14 @@ class InvalidExtension(object): return "THIRD" -class ExtensionManagerTest(unittest.TestCase): +class ExtensionManagerTest(test.TestCase): response_body = "Try to say this Mr. Knox, sir..." def setUp(self): - FLAGS.osapi_extensions_path = os.path.join(os.path.dirname(__file__), - "extensions") + super(ExtensionManagerTest, self).setUp() + ext_path = os.path.join(os.path.dirname(__file__), "extensions") + self.flags(osapi_extensions_path=ext_path) def test_get_resources(self): app = openstack.APIRouterV11() @@ -158,11 +245,12 @@ class ExtensionManagerTest(unittest.TestCase): self.assertTrue('THIRD' not in ext_mgr.extensions) -class ActionExtensionTest(unittest.TestCase): +class ActionExtensionTest(test.TestCase): def setUp(self): - FLAGS.osapi_extensions_path = os.path.join(os.path.dirname(__file__), - "extensions") + super(ActionExtensionTest, self).setUp() + ext_path = os.path.join(os.path.dirname(__file__), "extensions") + self.flags(osapi_extensions_path=ext_path) def _send_server_action_request(self, url, body): app = openstack.APIRouterV11() @@ -192,23 +280,16 @@ class ActionExtensionTest(unittest.TestCase): def test_invalid_action(self): body = dict(blah=dict(name="test")) - response = self._send_server_action_request("/asdf/1/action", body) + response = self._send_server_action_request("/fdsa/1/action", body) self.assertEqual(404, response.status_int) -class RequestExtensionTest(unittest.TestCase): +class RequestExtensionTest(test.TestCase): def setUp(self): super(RequestExtensionTest, self).setUp() - self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.reset_fake_data() - fakes.FakeAuthDatabase.data = {} - fakes.stub_out_auth(self.stubs) - self.context = context.get_admin_context() - - def tearDown(self): - self.stubs.UnsetAll() - super(RequestExtensionTest, self).tearDown() + ext_path = os.path.join(os.path.dirname(__file__), "extensions") + self.flags(osapi_extensions_path=ext_path) def test_get_resources_with_stub_mgr(self): @@ -244,3 +325,109 @@ class RequestExtensionTest(unittest.TestCase): response_data = json.loads(response.body) self.assertEqual('newblue', response_data['flavor']['googoose']) self.assertEqual("Pig Bands!", response_data['big_bands']) + + +class ExtensionsXMLSerializerTest(test.TestCase): + + def test_serialize_extenstion(self): + serializer = extensions.ExtensionsXMLSerializer() + data = { + 'extension': { + 'name': 'ext1', + 'namespace': 'http://docs.rack.com/servers/api/ext/pie/v1.0', + 'alias': 'RS-PIE', + 'updated': '2011-01-22T13:25:27-06:00', + 'description': 'Adds the capability to share an image.', + 'links': [ + { + 'rel': 'describedby', + 'type': 'application/pdf', + 'href': 'http://docs.rack.com/servers/api/ext/cs.pdf', + }, + { + 'rel': 'describedby', + 'type': 'application/vnd.sun.wadl+xml', + 'href': 'http://docs.rack.com/servers/api/ext/cs.wadl', + }, + ], + }, + } + + xml = serializer.serialize(data, 'show') + root = ElementTree.XML(xml) + ext_dict = data['extension'] + self.assertEqual(root.findtext('{0}description'.format(NS)), + ext_dict['description']) + + for key in ['name', 'namespace', 'alias', 'updated']: + self.assertEqual(root.get(key), ext_dict[key]) + + link_nodes = root.findall('{0}link'.format(ATOMNS)) + self.assertEqual(len(link_nodes), 2) + for i, link in enumerate(ext_dict['links']): + for key, value in link.items(): + self.assertEqual(link_nodes[i].get(key), value) + + def test_serialize_extensions(self): + serializer = extensions.ExtensionsXMLSerializer() + data = { + "extensions": [ + { + "name": "Public Image Extension", + "namespace": "http://foo.com/api/ext/pie/v1.0", + "alias": "RS-PIE", + "updated": "2011-01-22T13:25:27-06:00", + "description": "Adds the capability to share an image.", + "links": [ + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://foo.com/api/ext/cs-pie.pdf", + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://foo.com/api/ext/cs-pie.wadl", + }, + ], + }, + { + "name": "Cloud Block Storage", + "namespace": "http://foo.com/api/ext/cbs/v1.0", + "alias": "RS-CBS", + "updated": "2011-01-12T11:22:33-06:00", + "description": "Allows mounting cloud block storage.", + "links": [ + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://foo.com/api/ext/cs-cbs.pdf", + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://foo.com/api/ext/cs-cbs.wadl", + }, + ], + }, + ], + } + + xml = serializer.serialize(data, 'index') + print xml + root = ElementTree.XML(xml) + ext_elems = root.findall('{0}extension'.format(NS)) + self.assertEqual(len(ext_elems), 2) + for i, ext_elem in enumerate(ext_elems): + ext_dict = data['extensions'][i] + self.assertEqual(ext_elem.findtext('{0}description'.format(NS)), + ext_dict['description']) + + for key in ['name', 'namespace', 'alias', 'updated']: + self.assertEqual(ext_elem.get(key), ext_dict[key]) + + link_nodes = ext_elem.findall('{0}link'.format(ATOMNS)) + self.assertEqual(len(link_nodes), 2) + for i, link in enumerate(ext_dict['links']): + for key, value in link.items(): + self.assertEqual(link_nodes[i].get(key), value) diff --git a/nova/tests/api/openstack/test_faults.py b/nova/tests/api/openstack/test_faults.py index 927009e77..6da27540a 100644 --- a/nova/tests/api/openstack/test_faults.py +++ b/nova/tests/api/openstack/test_faults.py @@ -16,6 +16,7 @@ # under the License. import json +from xml.dom import minidom import webob import webob.dec @@ -24,6 +25,7 @@ import webob.exc from nova import test from nova.api.openstack import common from nova.api.openstack import faults +from nova.api.openstack import wsgi class TestFaults(test.TestCase): @@ -144,3 +146,108 @@ class TestFaults(test.TestCase): """Ensure the status_int is set correctly on faults""" fault = faults.Fault(webob.exc.HTTPBadRequest(explanation='what?')) self.assertEqual(fault.status_int, 400) + + def test_v10_xml_serializer(self): + """Ensure that a v1.0 request responds with a v1.0 xmlns""" + request = webob.Request.blank('/', + headers={"Accept": "application/xml"}) + + fault = faults.Fault(webob.exc.HTTPBadRequest(explanation='scram')) + response = request.get_response(fault) + + self.assertTrue(common.XML_NS_V10 in response.body) + self.assertEqual(response.content_type, "application/xml") + self.assertEqual(response.status_int, 400) + + def test_v11_xml_serializer(self): + """Ensure that a v1.1 request responds with a v1.1 xmlns""" + request = webob.Request.blank('/v1.1', + headers={"Accept": "application/xml"}) + + fault = faults.Fault(webob.exc.HTTPBadRequest(explanation='scram')) + response = request.get_response(fault) + + self.assertTrue(common.XML_NS_V11 in response.body) + self.assertEqual(response.content_type, "application/xml") + self.assertEqual(response.status_int, 400) + + +class FaultsXMLSerializationTestV11(test.TestCase): + """Tests covering `nova.api.openstack.faults:Fault` class.""" + + def _prepare_xml(self, xml_string): + xml_string = xml_string.replace(" ", "") + xml_string = xml_string.replace("\n", "") + xml_string = xml_string.replace("\t", "") + return xml_string + + def test_400_fault(self): + metadata = {'attributes': {"badRequest": 'code'}} + serializer = wsgi.XMLDictSerializer(metadata=metadata, + xmlns=common.XML_NS_V11) + + fixture = { + "badRequest": { + "message": "scram", + "code": 400, + }, + } + + output = serializer.serialize(fixture) + actual = minidom.parseString(self._prepare_xml(output)) + + expected = minidom.parseString(self._prepare_xml(""" + <badRequest code="400" xmlns="%s"> + <message>scram</message> + </badRequest> + """) % common.XML_NS_V11) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_413_fault(self): + metadata = {'attributes': {"overLimit": 'code'}} + serializer = wsgi.XMLDictSerializer(metadata=metadata, + xmlns=common.XML_NS_V11) + + fixture = { + "overLimit": { + "message": "sorry", + "code": 413, + "retryAfter": 4, + }, + } + + output = serializer.serialize(fixture) + actual = minidom.parseString(self._prepare_xml(output)) + + expected = minidom.parseString(self._prepare_xml(""" + <overLimit code="413" xmlns="%s"> + <message>sorry</message> + <retryAfter>4</retryAfter> + </overLimit> + """) % common.XML_NS_V11) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_404_fault(self): + metadata = {'attributes': {"itemNotFound": 'code'}} + serializer = wsgi.XMLDictSerializer(metadata=metadata, + xmlns=common.XML_NS_V11) + + fixture = { + "itemNotFound": { + "message": "sorry", + "code": 404, + }, + } + + output = serializer.serialize(fixture) + actual = minidom.parseString(self._prepare_xml(output)) + + expected = minidom.parseString(self._prepare_xml(""" + <itemNotFound code="404" xmlns="%s"> + <message>sorry</message> + </itemNotFound> + """) % common.XML_NS_V11) + + self.assertEqual(expected.toxml(), actual.toxml()) diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 4ac35b26b..d0fe72001 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -16,7 +16,6 @@ # under the License. import json -import stubout import webob import xml.dom.minidom as minidom @@ -56,12 +55,8 @@ def return_instance_type_not_found(context, flavor_id): class FlavorsTest(test.TestCase): def setUp(self): super(FlavorsTest, self).setUp() - self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.reset_fake_data() - fakes.FakeAuthDatabase.data = {} fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) - fakes.stub_out_auth(self.stubs) self.stubs.Set(nova.db.api, "instance_type_get_all", return_instance_types) self.stubs.Set(nova.db.api, "instance_type_get_by_flavor_id", diff --git a/nova/tests/api/openstack/extensions/test_flavors_extra_specs.py b/nova/tests/api/openstack/test_flavors_extra_specs.py index 2c1c335b0..d386958db 100644 --- a/nova/tests/api/openstack/extensions/test_flavors_extra_specs.py +++ b/nova/tests/api/openstack/test_flavors_extra_specs.py @@ -17,14 +17,13 @@ import json import stubout -import unittest import webob import os.path from nova import flags +from nova import test from nova.api import openstack -from nova.api.openstack import auth from nova.api.openstack import extensions from nova.tests.api.openstack import fakes import nova.wsgi @@ -40,10 +39,6 @@ def return_flavor_extra_specs(context, flavor_id): return stub_flavor_extra_specs() -def return_flavor_extra_specs(context, flavor_id): - return stub_flavor_extra_specs() - - def return_empty_flavor_extra_specs(context, flavor_id): return {} @@ -62,30 +57,17 @@ def stub_flavor_extra_specs(): return specs -class FlavorsExtraSpecsTest(unittest.TestCase): +class FlavorsExtraSpecsTest(test.TestCase): def setUp(self): super(FlavorsExtraSpecsTest, self).setUp() - FLAGS.osapi_extensions_path = os.path.join(os.path.dirname(__file__), - "extensions") - self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.auth_data = {} - fakes.FakeAuthDatabase.data = {} - fakes.stub_out_auth(self.stubs) fakes.stub_out_key_pair_funcs(self.stubs) - self.mware = auth.AuthMiddleware( - extensions.ExtensionMiddleware( - openstack.APIRouterV11())) - - def tearDown(self): - self.stubs.UnsetAll() - super(FlavorsExtraSpecsTest, self).tearDown() def test_index(self): self.stubs.Set(nova.db.api, 'instance_type_extra_specs_get', return_flavor_extra_specs) - request = webob.Request.blank('/flavors/1/os-extra_specs') - res = request.get_response(self.mware) + request = webob.Request.blank('/v1.1/flavors/1/os-extra_specs') + res = request.get_response(fakes.wsgi_app()) self.assertEqual(200, res.status_int) res_dict = json.loads(res.body) self.assertEqual('application/json', res.headers['Content-Type']) @@ -94,8 +76,8 @@ class FlavorsExtraSpecsTest(unittest.TestCase): def test_index_no_data(self): self.stubs.Set(nova.db.api, 'instance_type_extra_specs_get', return_empty_flavor_extra_specs) - req = webob.Request.blank('/flavors/1/os-extra_specs') - res = req.get_response(self.mware) + req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs') + res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(200, res.status_int) self.assertEqual('application/json', res.headers['Content-Type']) @@ -104,8 +86,8 @@ class FlavorsExtraSpecsTest(unittest.TestCase): def test_show(self): self.stubs.Set(nova.db.api, 'instance_type_extra_specs_get', return_flavor_extra_specs) - req = webob.Request.blank('/flavors/1/os-extra_specs/key5') - res = req.get_response(self.mware) + req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs/key5') + res = req.get_response(fakes.wsgi_app()) self.assertEqual(200, res.status_int) res_dict = json.loads(res.body) self.assertEqual('application/json', res.headers['Content-Type']) @@ -114,28 +96,28 @@ class FlavorsExtraSpecsTest(unittest.TestCase): def test_show_spec_not_found(self): self.stubs.Set(nova.db.api, 'instance_type_extra_specs_get', return_empty_flavor_extra_specs) - req = webob.Request.blank('/flavors/1/os-extra_specs/key6') - res = req.get_response(self.mware) + req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs/key6') + res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(404, res.status_int) def test_delete(self): self.stubs.Set(nova.db.api, 'instance_type_extra_specs_delete', delete_flavor_extra_specs) - req = webob.Request.blank('/flavors/1/os-extra_specs/key5') + req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs/key5') req.method = 'DELETE' - res = req.get_response(self.mware) + res = req.get_response(fakes.wsgi_app()) self.assertEqual(200, res.status_int) def test_create(self): self.stubs.Set(nova.db.api, 'instance_type_extra_specs_update_or_create', return_create_flavor_extra_specs) - req = webob.Request.blank('/flavors/1/os-extra_specs') + req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs') req.method = 'POST' req.body = '{"extra_specs": {"key1": "value1"}}' req.headers["content-type"] = "application/json" - res = req.get_response(self.mware) + res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(200, res.status_int) self.assertEqual('application/json', res.headers['Content-Type']) @@ -145,21 +127,21 @@ class FlavorsExtraSpecsTest(unittest.TestCase): self.stubs.Set(nova.db.api, 'instance_type_extra_specs_update_or_create', return_create_flavor_extra_specs) - req = webob.Request.blank('/flavors/1/os-extra_specs') + req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs') req.method = 'POST' req.headers["content-type"] = "application/json" - res = req.get_response(self.mware) + res = req.get_response(fakes.wsgi_app()) self.assertEqual(400, res.status_int) def test_update_item(self): self.stubs.Set(nova.db.api, 'instance_type_extra_specs_update_or_create', return_create_flavor_extra_specs) - req = webob.Request.blank('/flavors/1/os-extra_specs/key1') + req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs/key1') req.method = 'PUT' req.body = '{"key1": "value1"}' req.headers["content-type"] = "application/json" - res = req.get_response(self.mware) + res = req.get_response(fakes.wsgi_app()) self.assertEqual(200, res.status_int) self.assertEqual('application/json', res.headers['Content-Type']) res_dict = json.loads(res.body) @@ -169,30 +151,30 @@ class FlavorsExtraSpecsTest(unittest.TestCase): self.stubs.Set(nova.db.api, 'instance_type_extra_specs_update_or_create', return_create_flavor_extra_specs) - req = webob.Request.blank('/flavors/1/os-extra_specs/key1') + req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs/key1') req.method = 'PUT' req.headers["content-type"] = "application/json" - res = req.get_response(self.mware) + res = req.get_response(fakes.wsgi_app()) self.assertEqual(400, res.status_int) def test_update_item_too_many_keys(self): self.stubs.Set(nova.db.api, 'instance_type_extra_specs_update_or_create', return_create_flavor_extra_specs) - req = webob.Request.blank('/flavors/1/os-extra_specs/key1') + req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs/key1') req.method = 'PUT' req.body = '{"key1": "value1", "key2": "value2"}' req.headers["content-type"] = "application/json" - res = req.get_response(self.mware) + res = req.get_response(fakes.wsgi_app()) self.assertEqual(400, res.status_int) def test_update_item_body_uri_mismatch(self): self.stubs.Set(nova.db.api, 'instance_type_extra_specs_update_or_create', return_create_flavor_extra_specs) - req = webob.Request.blank('/flavors/1/os-extra_specs/bad') + req = webob.Request.blank('/v1.1/flavors/1/os-extra_specs/bad') req.method = 'PUT' req.body = '{"key1": "value1"}' req.headers["content-type"] = "application/json" - res = req.get_response(self.mware) + res = req.get_response(fakes.wsgi_app()) self.assertEqual(400, res.status_int) diff --git a/nova/tests/api/openstack/test_image_metadata.py b/nova/tests/api/openstack/test_image_metadata.py index d9fb61e2a..56a0932e7 100644 --- a/nova/tests/api/openstack/test_image_metadata.py +++ b/nova/tests/api/openstack/test_image_metadata.py @@ -16,10 +16,7 @@ # under the License. import json -import stubout -import unittest import webob -import xml.dom.minidom as minidom from nova import flags @@ -85,26 +82,15 @@ class ImageMetaDataTest(test.TestCase): def setUp(self): super(ImageMetaDataTest, self).setUp() - self.stubs = stubout.StubOutForTesting() - self.orig_image_service = FLAGS.image_service - FLAGS.image_service = 'nova.image.glance.GlanceImageService' - fakes.FakeAuthManager.auth_data = {} - fakes.FakeAuthDatabase.data = {} - fakes.stub_out_auth(self.stubs) + self.flags(image_service='nova.image.glance.GlanceImageService') # NOTE(dprince) max out properties/metadata in image 3 for testing img3 = self.IMAGE_FIXTURES[2] for num in range(FLAGS.quota_metadata_items): img3['properties']['key%i' % num] = "blah" fakes.stub_out_glance(self.stubs, self.IMAGE_FIXTURES) - def tearDown(self): - self.stubs.UnsetAll() - FLAGS.image_service = self.orig_image_service - super(ImageMetaDataTest, self).tearDown() - def test_index(self): - req = webob.Request.blank('/v1.1/images/1/meta') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/images/1/metadata') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(200, res.status_int) @@ -114,8 +100,7 @@ class ImageMetaDataTest(test.TestCase): self.assertEqual(value, res_dict['metadata'][key]) def test_show(self): - req = webob.Request.blank('/v1.1/images/1/meta/key1') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/images/1/metadata/key1') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(200, res.status_int) @@ -124,42 +109,66 @@ class ImageMetaDataTest(test.TestCase): self.assertEqual('value1', res_dict['meta']['key1']) def test_show_not_found(self): - req = webob.Request.blank('/v1.1/images/1/meta/key9') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/images/1/metadata/key9') res = req.get_response(fakes.wsgi_app()) self.assertEqual(404, res.status_int) def test_create(self): - req = webob.Request.blank('/v1.1/images/2/meta') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/images/2/metadata') req.method = 'POST' req.body = '{"metadata": {"key9": "value9"}}' 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) + actual_output = json.loads(res.body) + + expected_output = { + 'metadata': { + 'key1': 'value1', + 'key2': 'value2', + 'key9': 'value9', + }, + } + + self.assertEqual(expected_output, actual_output) + + def test_update_all(self): + req = webob.Request.blank('/v1.1/images/2/metadata') + req.method = 'PUT' + req.body = '{"metadata": {"key9": "value9"}}' + req.headers["content-type"] = "application/json" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(200, res.status_int) - self.assertEqual('value9', res_dict['metadata']['key9']) - # other items should not be modified - self.assertEqual('value1', res_dict['metadata']['key1']) - self.assertEqual('value2', res_dict['metadata']['key2']) - self.assertEqual(1, len(res_dict)) + actual_output = json.loads(res.body) + + expected_output = { + 'metadata': { + 'key9': 'value9', + }, + } + + self.assertEqual(expected_output, actual_output) def test_update_item(self): - req = webob.Request.blank('/v1.1/images/1/meta/key1') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/images/1/metadata/key1') req.method = 'PUT' req.body = '{"meta": {"key1": "zz"}}' req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) + self.assertEqual(200, res.status_int) - res_dict = json.loads(res.body) - self.assertTrue('meta' in res_dict) - self.assertEqual(len(res_dict['meta']), 1) - self.assertEqual('zz', res_dict['meta']['key1']) + actual_output = json.loads(res.body) + expected_output = { + 'meta': { + 'key1': 'zz', + }, + } + self.assertEqual(actual_output, expected_output) def test_update_item_bad_body(self): - req = webob.Request.blank('/v1.1/images/1/meta/key1') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/images/1/metadata/key1') req.method = 'PUT' req.body = '{"key1": "zz"}' req.headers["content-type"] = "application/json" @@ -167,8 +176,7 @@ class ImageMetaDataTest(test.TestCase): self.assertEqual(400, res.status_int) def test_update_item_too_many_keys(self): - req = webob.Request.blank('/v1.1/images/1/meta/key1') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/images/1/metadata/key1') req.method = 'PUT' req.body = '{"meta": {"key1": "value1", "key2": "value2"}}' req.headers["content-type"] = "application/json" @@ -176,24 +184,38 @@ class ImageMetaDataTest(test.TestCase): self.assertEqual(400, res.status_int) def test_update_item_body_uri_mismatch(self): - req = webob.Request.blank('/v1.1/images/1/meta/bad') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/images/1/metadata/bad') req.method = 'PUT' req.body = '{"meta": {"key1": "value1"}}' req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(400, res.status_int) + def test_update_item_xml(self): + req = webob.Request.blank('/v1.1/images/1/metadata/key1') + req.method = 'PUT' + req.body = '<meta key="key1">five</meta>' + req.headers["content-type"] = "application/xml" + res = req.get_response(fakes.wsgi_app()) + + self.assertEqual(200, res.status_int) + actual_output = json.loads(res.body) + expected_output = { + 'meta': { + 'key1': 'five', + }, + } + self.assertEqual(actual_output, expected_output) + def test_delete(self): - req = webob.Request.blank('/v1.1/images/2/meta/key1') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/images/2/metadata/key1') req.method = 'DELETE' res = req.get_response(fakes.wsgi_app()) - self.assertEqual(200, res.status_int) + self.assertEqual(204, res.status_int) + self.assertEqual('', res.body) def test_delete_not_found(self): - req = webob.Request.blank('/v1.1/images/2/meta/blah') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/images/2/metadata/blah') req.method = 'DELETE' res = req.get_response(fakes.wsgi_app()) self.assertEqual(404, res.status_int) @@ -203,8 +225,7 @@ class ImageMetaDataTest(test.TestCase): for num in range(FLAGS.quota_metadata_items + 1): data['metadata']['key%i' % num] = "blah" json_string = str(data).replace("\'", "\"") - req = webob.Request.blank('/v1.1/images/2/meta') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/images/2/metadata') req.method = 'POST' req.body = json_string req.headers["content-type"] = "application/json" @@ -212,141 +233,9 @@ class ImageMetaDataTest(test.TestCase): self.assertEqual(400, res.status_int) def test_too_many_metadata_items_on_put(self): - req = webob.Request.blank('/v1.1/images/3/meta/blah') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/images/3/metadata/blah') req.method = 'PUT' req.body = '{"meta": {"blah": "blah"}}' req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(400, res.status_int) - - -class ImageMetadataXMLSerializationTest(test.TestCase): - - def test_index_xml(self): - serializer = openstack.image_metadata.ImageMetadataXMLSerializer() - fixture = { - 'metadata': { - 'one': 'two', - 'three': 'four', - }, - } - output = serializer.serialize(fixture, 'index') - actual = minidom.parseString(output.replace(" ", "")) - - expected = minidom.parseString(""" - <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> - <meta key="three"> - four - </meta> - <meta key="one"> - two - </meta> - </metadata> - """.replace(" ", "")) - - self.assertEqual(expected.toxml(), actual.toxml()) - - def test_index_xml_null(self): - serializer = openstack.image_metadata.ImageMetadataXMLSerializer() - fixture = { - 'metadata': { - None: None, - }, - } - output = serializer.serialize(fixture, 'index') - actual = minidom.parseString(output.replace(" ", "")) - - expected = minidom.parseString(""" - <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> - <meta key="None"> - None - </meta> - </metadata> - """.replace(" ", "")) - - self.assertEqual(expected.toxml(), actual.toxml()) - - def test_index_xml_unicode(self): - serializer = openstack.image_metadata.ImageMetadataXMLSerializer() - fixture = { - 'metadata': { - u'three': u'Jos\xe9', - }, - } - output = serializer.serialize(fixture, 'index') - actual = minidom.parseString(output.replace(" ", "")) - - expected = minidom.parseString(u""" - <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> - <meta key="three"> - Jos\xe9 - </meta> - </metadata> - """.encode("UTF-8").replace(" ", "")) - - self.assertEqual(expected.toxml(), actual.toxml()) - - def test_show_xml(self): - serializer = openstack.image_metadata.ImageMetadataXMLSerializer() - fixture = { - 'meta': { - 'one': 'two', - }, - } - output = serializer.serialize(fixture, 'show') - actual = minidom.parseString(output.replace(" ", "")) - - expected = minidom.parseString(""" - <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one"> - two - </meta> - """.replace(" ", "")) - - self.assertEqual(expected.toxml(), actual.toxml()) - - def test_update_item_xml(self): - serializer = openstack.image_metadata.ImageMetadataXMLSerializer() - fixture = { - 'meta': { - 'one': 'two', - }, - } - output = serializer.serialize(fixture, 'update') - actual = minidom.parseString(output.replace(" ", "")) - - expected = minidom.parseString(""" - <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one"> - two - </meta> - """.replace(" ", "")) - - self.assertEqual(expected.toxml(), actual.toxml()) - - def test_create_xml(self): - serializer = openstack.image_metadata.ImageMetadataXMLSerializer() - fixture = { - 'metadata': { - 'key9': 'value9', - 'key2': 'value2', - 'key1': 'value1', - }, - } - output = serializer.serialize(fixture, 'create') - actual = minidom.parseString(output.replace(" ", "")) - - expected = minidom.parseString(""" - <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> - <meta key="key2"> - value2 - </meta> - <meta key="key9"> - value9 - </meta> - <meta key="key1"> - value1 - </meta> - </metadata> - """.replace(" ", "")) - - self.assertEqual(expected.toxml(), actual.toxml()) diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 17f2fb755..8c5ad7f8d 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -155,7 +155,7 @@ class GlanceImageServiceTest(_BaseImageServiceTests): fakes.stub_out_compute_api_snapshot(self.stubs) service_class = 'nova.image.glance.GlanceImageService' self.service = utils.import_object(service_class) - self.context = context.RequestContext(1, None) + self.context = context.RequestContext('fake', 'fake') self.service.delete_all() self.sent_to_glance = {} fakes.stub_out_glance_add_image(self.stubs, self.sent_to_glance) @@ -168,7 +168,7 @@ class GlanceImageServiceTest(_BaseImageServiceTests): """Ensure instance_id is persisted as an image-property""" fixture = {'name': 'test image', 'is_public': False, - 'properties': {'instance_id': '42', 'user_id': '1'}} + 'properties': {'instance_id': '42', 'user_id': 'fake'}} image_id = self.service.create(self.context, fixture)['id'] expected = fixture @@ -178,7 +178,7 @@ class GlanceImageServiceTest(_BaseImageServiceTests): expected = {'id': image_id, 'name': 'test image', 'is_public': False, - 'properties': {'instance_id': '42', 'user_id': '1'}} + 'properties': {'instance_id': '42', 'user_id': 'fake'}} self.assertDictMatch(image_meta, expected) image_metas = self.service.detail(self.context) @@ -331,11 +331,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): self.orig_image_service = FLAGS.image_service FLAGS.image_service = 'nova.image.glance.GlanceImageService' self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.reset_fake_data() - fakes.FakeAuthDatabase.data = {} fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) - fakes.stub_out_auth(self.stubs) fakes.stub_out_key_pair_funcs(self.stubs) self.fixtures = self._make_image_fixtures() fakes.stub_out_glance(self.stubs, initial_fixtures=self.fixtures) @@ -352,7 +349,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): """Determine if this fixture is applicable for given user id.""" is_public = fixture["is_public"] try: - uid = int(fixture["properties"]["user_id"]) + uid = fixture["properties"]["user_id"] except KeyError: uid = None return uid == user_id or is_public @@ -424,7 +421,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): }, "metadata": { "instance_ref": "http://localhost/v1.1/servers/42", - "user_id": "1", + "user_id": "fake", }, "links": [{ "rel": "self", @@ -538,7 +535,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): # because the element hasn't changed definition expected = minidom.parseString(""" <itemNotFound code="404" - xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"> + xmlns="http://docs.openstack.org/compute/api/v1.1"> <message> Image not found. </message> @@ -559,7 +556,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): fixtures = copy.copy(self.fixtures) for image in fixtures: - if not self._applicable_fixture(image, 1): + if not self._applicable_fixture(image, "fake"): fixtures.remove(image) continue @@ -666,7 +663,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): 'name': 'queued snapshot', 'metadata': { u'instance_ref': u'http://localhost/v1.1/servers/42', - u'user_id': u'1', + u'user_id': u'fake', }, 'updated': self.NOW_API_FORMAT, 'created': self.NOW_API_FORMAT, @@ -696,7 +693,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): 'name': 'saving snapshot', 'metadata': { u'instance_ref': u'http://localhost/v1.1/servers/42', - u'user_id': u'1', + u'user_id': u'fake', }, 'updated': self.NOW_API_FORMAT, 'created': self.NOW_API_FORMAT, @@ -727,7 +724,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): 'name': 'active snapshot', 'metadata': { u'instance_ref': u'http://localhost/v1.1/servers/42', - u'user_id': u'1', + u'user_id': u'fake', }, 'updated': self.NOW_API_FORMAT, 'created': self.NOW_API_FORMAT, @@ -757,7 +754,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): 'name': 'killed snapshot', 'metadata': { u'instance_ref': u'http://localhost/v1.1/servers/42', - u'user_id': u'1', + u'user_id': u'fake', }, 'updated': self.NOW_API_FORMAT, 'created': self.NOW_API_FORMAT, @@ -1259,7 +1256,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): # Snapshot for User 1 server_ref = 'http://localhost/v1.1/servers/42' - snapshot_properties = {'instance_ref': server_ref, 'user_id': '1'} + snapshot_properties = {'instance_ref': server_ref, 'user_id': 'fake'} for status in ('queued', 'saving', 'active', 'killed'): add_fixture(id=image_id, name='%s snapshot' % status, is_public=False, status=status, @@ -1267,7 +1264,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): image_id += 1 # Snapshot for User 2 - other_snapshot_properties = {'instance_id': '43', 'user_id': '2'} + other_snapshot_properties = {'instance_id': '43', 'user_id': 'other'} add_fixture(id=image_id, name='someone elses snapshot', is_public=False, status='active', properties=other_snapshot_properties) diff --git a/nova/tests/api/openstack/test_limits.py b/nova/tests/api/openstack/test_limits.py index 8a3fe681a..6c3d531e3 100644 --- a/nova/tests/api/openstack/test_limits.py +++ b/nova/tests/api/openstack/test_limits.py @@ -920,7 +920,7 @@ class LimitsViewBuilderV11Test(test.TestCase): "verb": "POST", "remaining": 2, "unit": "MINUTE", - "resetTime": 1311272226 + "resetTime": 1311272226, }, { "URI": "*/servers", @@ -929,7 +929,7 @@ class LimitsViewBuilderV11Test(test.TestCase): "verb": "POST", "remaining": 10, "unit": "DAY", - "resetTime": 1311272226 + "resetTime": 1311272226, }, ] self.absolute_limits = { @@ -954,7 +954,7 @@ class LimitsViewBuilderV11Test(test.TestCase): "verb": "POST", "remaining": 2, "unit": "MINUTE", - "next-available": "2011-07-21T18:17:06Z" + "next-available": "2011-07-21T18:17:06Z", }, ] }, @@ -967,7 +967,7 @@ class LimitsViewBuilderV11Test(test.TestCase): "verb": "POST", "remaining": 10, "unit": "DAY", - "next-available": "2011-07-21T18:17:06Z" + "next-available": "2011-07-21T18:17:06Z", }, ] }, @@ -989,7 +989,7 @@ class LimitsViewBuilderV11Test(test.TestCase): expected_limits = { "limits": { "rate": [], - "absolute": {} + "absolute": {}, } } @@ -1022,7 +1022,7 @@ class LimitsXMLSerializationTest(test.TestCase): "verb": "POST", "remaining": 2, "unit": "MINUTE", - "next-available": "2011-12-15T22:42:45Z" + "next-available": "2011-12-15T22:42:45Z", }, ] }, @@ -1083,7 +1083,7 @@ class LimitsXMLSerializationTest(test.TestCase): fixture = { "limits": { "rate": [], - "absolute": {} + "absolute": {}, } } diff --git a/nova/tests/api/openstack/test_server_metadata.py b/nova/tests/api/openstack/test_server_metadata.py index 0431e68d2..f90485067 100644 --- a/nova/tests/api/openstack/test_server_metadata.py +++ b/nova/tests/api/openstack/test_server_metadata.py @@ -16,14 +16,12 @@ # under the License. import json -import stubout -import unittest import webob from nova import exception from nova import flags -from nova.api import openstack +from nova import test from nova.tests.api.openstack import fakes import nova.wsgi @@ -76,21 +74,13 @@ def return_server_nonexistant(context, server_id): raise exception.InstanceNotFound() -class ServerMetaDataTest(unittest.TestCase): +class ServerMetaDataTest(test.TestCase): def setUp(self): super(ServerMetaDataTest, self).setUp() - self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.auth_data = {} - 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() - super(ServerMetaDataTest, self).tearDown() - def test_index(self): self.stubs.Set(nova.db.api, 'instance_metadata_get', return_server_metadata) diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 1c66c1aa6..14ce42837 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -16,11 +16,11 @@ # under the License. import base64 +import datetime import json import unittest from xml.dom import minidom -import stubout import webob from nova import context @@ -30,8 +30,9 @@ from nova import flags 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 +from nova.api.openstack import servers +from nova.api.openstack import wsgi import nova.compute.api from nova.compute import instance_types from nova.compute import power_state @@ -77,6 +78,12 @@ def return_virtual_interface_instance_nonexistant(interfaces): return _return_virtual_interface_by_instance +def return_server_with_attributes(**kwargs): + def _return_server(context, id): + return stub_instance(id, **kwargs) + return _return_server + + def return_server_with_addresses(private, public): def _return_server(context, id): return stub_instance(id, private_address=private, @@ -84,20 +91,20 @@ def return_server_with_addresses(private, public): return _return_server -def return_server_with_interfaces(interfaces): +def return_server_with_power_state(power_state): def _return_server(context, id): - return stub_instance(id, interfaces=interfaces) + return stub_instance(id, power_state=power_state) return _return_server -def return_server_with_power_state(power_state): +def return_server_with_uuid_and_power_state(power_state): def _return_server(context, id): - return stub_instance(id, power_state=power_state) + return stub_instance(id, uuid=FAKE_UUID, power_state=power_state) return _return_server -def return_servers(context, user_id=1): - return [stub_instance(i, user_id) for i in xrange(5)] +def return_servers(context, *args, **kwargs): + return [stub_instance(i, 'fake', 'fake') for i in xrange(5)] def return_servers_by_reservation(context, reservation_id=""): @@ -140,16 +147,17 @@ def instance_addresses(context, instance_id): return None -def stub_instance(id, user_id=1, private_address=None, public_addresses=None, - host=None, power_state=0, reservation_id="", - uuid=FAKE_UUID, interfaces=None): +def stub_instance(id, user_id='fake', project_id='fake', private_address=None, + public_addresses=None, host=None, power_state=0, + reservation_id="", uuid=FAKE_UUID, image_ref="10", + flavor_id="1", interfaces=None): metadata = [] metadata.append(InstanceMetadata(key='seq', value=id)) if interfaces is None: interfaces = [] - inst_type = instance_types.get_instance_type_by_flavor_id(1) + inst_type = instance_types.get_instance_type_by_flavor_id(int(flavor_id)) if public_addresses is None: public_addresses = list() @@ -164,10 +172,12 @@ def stub_instance(id, user_id=1, private_address=None, public_addresses=None, instance = { "id": int(id), + "created_at": datetime.datetime(2010, 10, 10, 12, 0, 0), + "updated_at": datetime.datetime(2010, 11, 11, 11, 0, 0), "admin_pass": "", "user_id": user_id, - "project_id": "", - "image_ref": "10", + "project_id": project_id, + "image_ref": image_ref, "kernel_id": "", "ramdisk_id": "", "launch_index": 0, @@ -223,13 +233,10 @@ class MockSetAdminPassword(object): class ServersTest(test.TestCase): def setUp(self): + self.maxDiff = None super(ServersTest, self).setUp() - self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.reset_fake_data() - fakes.FakeAuthDatabase.data = {} fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) - 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) @@ -237,7 +244,7 @@ class ServersTest(test.TestCase): 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', + self.stubs.Set(nova.db.api, 'instance_get_all_by_project', return_servers) self.stubs.Set(nova.db.api, 'instance_add_security_group', return_security_group) @@ -252,15 +259,9 @@ class ServersTest(test.TestCase): self.stubs.Set(nova.compute.API, 'resume', fake_compute_api) self.stubs.Set(nova.compute.API, "get_diagnostics", fake_compute_api) self.stubs.Set(nova.compute.API, "get_actions", fake_compute_api) - self.allow_admin = FLAGS.allow_admin_api self.webreq = common.webob_factory('/v1.0/servers') - def tearDown(self): - self.stubs.UnsetAll() - FLAGS.allow_admin_api = self.allow_admin - super(ServersTest, self).tearDown() - def test_get_server_by_id(self): req = webob.Request.blank('/v1.0/servers/1') res = req.get_response(fakes.wsgi_app()) @@ -299,24 +300,346 @@ class ServersTest(test.TestCase): self.assertEqual(res_dict['server']['name'], 'server1') def test_get_server_by_id_v1_1(self): + image_bookmark = "http://localhost/images/10" + flavor_ref = "http://localhost/v1.1/flavors/1" + flavor_id = "1" + flavor_bookmark = "http://localhost/flavors/1" + + public_ip = '192.168.0.3' + private_ip = '172.19.0.1' + interfaces = [ + { + 'network': {'label': 'public'}, + 'fixed_ips': [ + {'address': public_ip}, + ], + }, + { + 'network': {'label': 'private'}, + 'fixed_ips': [ + {'address': private_ip}, + ], + }, + ] + new_return_server = return_server_with_attributes( + interfaces=interfaces) + self.stubs.Set(nova.db.api, 'instance_get', new_return_server) + req = webob.Request.blank('/v1.1/servers/1') 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']['name'], 'server1') + expected_server = { + "server": { + "id": 1, + "uuid": FAKE_UUID, + "updated": "2010-11-11T11:00:00Z", + "created": "2010-10-10T12:00:00Z", + "progress": 0, + "name": "server1", + "status": "BUILD", + "hostId": '', + "image": { + "id": "10", + "links": [ + { + "rel": "bookmark", + "href": image_bookmark, + }, + ], + }, + "flavor": { + "id": "1", + "links": [ + { + "rel": "bookmark", + "href": flavor_bookmark, + }, + ], + }, + "addresses": { + "public": [ + { + "version": 4, + "addr": public_ip, + }, + ], + "private": [ + { + "version": 4, + "addr": private_ip, + }, + ], + }, + "metadata": { + "seq": "1", + }, + "links": [ + { + "rel": "self", + #FIXME(wwolf) Do we want the links to be id or uuid? + "href": "http://localhost/v1.1/servers/1", + }, + { + "rel": "bookmark", + "href": "http://localhost/servers/1", + }, + ], + } + } + + self.assertDictMatch(res_dict, expected_server) - expected_links = [ + def test_get_server_by_id_v1_1_xml(self): + image_bookmark = "http://localhost/images/10" + flavor_ref = "http://localhost/v1.1/flavors/1" + flavor_id = "1" + flavor_bookmark = "http://localhost/flavors/1" + server_href = "http://localhost/v1.1/servers/1" + server_bookmark = "http://localhost/servers/1" + + public_ip = '192.168.0.3' + private_ip = '172.19.0.1' + interfaces = [ { - "rel": "self", - "href": "http://localhost/v1.1/servers/1", + 'network': {'label': 'public'}, + 'fixed_ips': [ + {'address': public_ip}, + ], }, { - "rel": "bookmark", - "href": "http://localhost/servers/1", + 'network': {'label': 'private'}, + 'fixed_ips': [ + {'address': private_ip}, + ], }, ] + new_return_server = return_server_with_attributes( + interfaces=interfaces) + self.stubs.Set(nova.db.api, 'instance_get', new_return_server) - self.assertEqual(res_dict['server']['links'], expected_links) + req = webob.Request.blank('/v1.1/servers/1') + req.headers['Accept'] = 'application/xml' + res = req.get_response(fakes.wsgi_app()) + actual = minidom.parseString(res.body.replace(' ', '')) + expected_uuid = FAKE_UUID + expected_updated = "2010-11-11T11:00:00Z" + expected_created = "2010-10-10T12:00:00Z" + expected = minidom.parseString(""" + <server id="1" + uuid="%(expected_uuid)s" + xmlns="http://docs.openstack.org/compute/api/v1.1" + xmlns:atom="http://www.w3.org/2005/Atom" + name="server1" + updated="%(expected_updated)s" + created="%(expected_created)s" + hostId="" + status="BUILD" + progress="0"> + <atom:link href="%(server_href)s" rel="self"/> + <atom:link href="%(server_bookmark)s" rel="bookmark"/> + <image id="10"> + <atom:link rel="bookmark" href="%(image_bookmark)s"/> + </image> + <flavor id="1"> + <atom:link rel="bookmark" href="%(flavor_bookmark)s"/> + </flavor> + <metadata> + <meta key="seq"> + 1 + </meta> + </metadata> + <addresses> + <network id="public"> + <ip version="4" addr="%(public_ip)s"/> + </network> + <network id="private"> + <ip version="4" addr="%(private_ip)s"/> + </network> + </addresses> + </server> + """.replace(" ", "") % (locals())) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_get_server_with_active_status_by_id_v1_1(self): + image_bookmark = "http://localhost/images/10" + flavor_ref = "http://localhost/v1.1/flavors/1" + flavor_id = "1" + flavor_bookmark = "http://localhost/flavors/1" + private_ip = "192.168.0.3" + public_ip = "1.2.3.4" + + interfaces = [ + { + 'network': {'label': 'public'}, + 'fixed_ips': [ + {'address': public_ip}, + ], + }, + { + 'network': {'label': 'private'}, + 'fixed_ips': [ + {'address': private_ip}, + ], + }, + ] + new_return_server = return_server_with_attributes( + interfaces=interfaces, power_state=1) + self.stubs.Set(nova.db.api, 'instance_get', new_return_server) + + req = webob.Request.blank('/v1.1/servers/1') + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + expected_server = { + "server": { + "id": 1, + "uuid": FAKE_UUID, + "updated": "2010-11-11T11:00:00Z", + "created": "2010-10-10T12:00:00Z", + "progress": 100, + "name": "server1", + "status": "ACTIVE", + "hostId": '', + "image": { + "id": "10", + "links": [ + { + "rel": "bookmark", + "href": image_bookmark, + }, + ], + }, + "flavor": { + "id": "1", + "links": [ + { + "rel": "bookmark", + "href": flavor_bookmark, + }, + ], + }, + "addresses": { + "public": [ + { + "version": 4, + "addr": public_ip, + }, + ], + "private": [ + { + "version": 4, + "addr": private_ip, + }, + ], + }, + "metadata": { + "seq": "1", + }, + "links": [ + { + "rel": "self", + "href": "http://localhost/v1.1/servers/1", + }, + { + "rel": "bookmark", + "href": "http://localhost/servers/1", + }, + ], + } + } + + self.assertDictMatch(res_dict, expected_server) + + def test_get_server_with_id_image_ref_by_id_v1_1(self): + image_ref = "10" + image_bookmark = "http://localhost/images/10" + flavor_ref = "http://localhost/v1.1/flavors/1" + flavor_id = "1" + flavor_bookmark = "http://localhost/flavors/1" + private_ip = "192.168.0.3" + public_ip = "1.2.3.4" + + interfaces = [ + { + 'network': {'label': 'public'}, + 'fixed_ips': [ + {'address': public_ip}, + ], + }, + { + 'network': {'label': 'private'}, + 'fixed_ips': [ + {'address': private_ip}, + ], + }, + ] + new_return_server = return_server_with_attributes( + interfaces=interfaces, power_state=1, image_ref=image_ref, + flavor_id=flavor_id) + self.stubs.Set(nova.db.api, 'instance_get', new_return_server) + + req = webob.Request.blank('/v1.1/servers/1') + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + expected_server = { + "server": { + "id": 1, + "uuid": FAKE_UUID, + "updated": "2010-11-11T11:00:00Z", + "created": "2010-10-10T12:00:00Z", + "progress": 100, + "name": "server1", + "status": "ACTIVE", + "hostId": '', + "image": { + "id": "10", + "links": [ + { + "rel": "bookmark", + "href": image_bookmark, + }, + ], + }, + "flavor": { + "id": "1", + "links": [ + { + "rel": "bookmark", + "href": flavor_bookmark, + }, + ], + }, + "addresses": { + "public": [ + { + "version": 4, + "addr": public_ip, + }, + ], + "private": [ + { + "version": 4, + "addr": private_ip, + }, + ], + }, + "metadata": { + "seq": "1", + }, + "links": [ + { + "rel": "self", + "href": "http://localhost/v1.1/servers/1", + }, + { + "rel": "bookmark", + "href": "http://localhost/servers/1", + }, + ], + } + } + + self.assertDictMatch(res_dict, expected_server) def test_get_server_by_id_with_addresses_xml(self): private = "192.168.0.3" @@ -451,7 +774,8 @@ class ServersTest(test.TestCase): 'fixed_ipv6': '2001:4860::12', }, ] - new_return_server = return_server_with_interfaces(interfaces) + new_return_server = return_server_with_attributes( + interfaces=interfaces) self.stubs.Set(nova.db.api, 'instance_get', new_return_server) req = webob.Request.blank('/v1.1/servers/1') @@ -494,7 +818,8 @@ class ServersTest(test.TestCase): 'fixed_ipv6': '2001:4860::12', }, ] - new_return_server = return_server_with_interfaces(interfaces) + new_return_server = return_server_with_attributes( + interfaces=interfaces) self.stubs.Set(nova.db.api, 'instance_get', new_return_server) req = webob.Request.blank('/v1.1/servers/1') @@ -636,6 +961,7 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) + self.assertEqual(len(res_dict['servers']), 5) i = 0 for s in res_dict['servers']: self.assertEqual(s['id'], i) @@ -699,23 +1025,24 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) + self.assertEqual(len(res_dict['servers']), 5) for i, s in enumerate(res_dict['servers']): self.assertEqual(s['id'], i) self.assertEqual(s['name'], 'server%d' % i) - self.assertEqual(s.get('imageId', None), None) + self.assertEqual(s.get('image', None), None) expected_links = [ - { - "rel": "self", - "href": "http://localhost/v1.1/servers/%d" % (i,), - }, - { - "rel": "bookmark", - "href": "http://localhost/servers/%d" % (i,), - }, - ] + { + "rel": "self", + "href": "http://localhost/v1.1/servers/%s" % s['id'], + }, + { + "rel": "bookmark", + "href": "http://localhost/servers/%s" % s['id'], + }, + ] - self.assertEqual(s['links'], expected_links) + self.assertEqual(s['links'], expected_links) def test_get_servers_with_limit(self): req = webob.Request.blank('/v1.0/servers?limit=3') @@ -761,13 +1088,13 @@ class ServersTest(test.TestCase): req = webob.Request.blank('/v1.1/servers?marker=2') res = req.get_response(fakes.wsgi_app()) servers = json.loads(res.body)['servers'] - self.assertEqual([s['id'] for s in servers], [3, 4]) + self.assertEqual([s['name'] for s in servers], ["server3", "server4"]) def test_get_servers_with_limit_and_marker(self): req = webob.Request.blank('/v1.1/servers?limit=2&marker=1') res = req.get_response(fakes.wsgi_app()) servers = json.loads(res.body)['servers'] - self.assertEqual([s['id'] for s in servers], [2, 3]) + self.assertEqual([s['name'] for s in servers], ['server2', 'server3']) def test_get_servers_with_bad_marker(self): req = webob.Request.blank('/v1.1/servers?limit=2&marker=asdf') @@ -778,8 +1105,16 @@ 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', - 'uuid': FAKE_UUID} + inst_type = instance_types.get_instance_type_by_flavor_id(3) + image_ref = 'http://localhost/images/2' + return {'id': 1, + 'display_name': 'server_test', + 'uuid': FAKE_UUID, + 'instance_type': dict(inst_type), + 'image_ref': image_ref, + "created_at": datetime.datetime(2010, 10, 10, 12, 0, 0), + "updated_at": datetime.datetime(2010, 11, 11, 11, 0, 0), + } def server_update(context, id, params): return instance_create(context, id) @@ -828,6 +1163,7 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) server = json.loads(res.body)['server'] self.assertEqual(16, len(server['adminPass'])) self.assertEqual('server_test', server['name']) @@ -835,7 +1171,6 @@ class ServersTest(test.TestCase): 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() @@ -853,7 +1188,7 @@ class ServersTest(test.TestCase): def test_create_instance_via_zones(self): """Server generated ReservationID""" self._setup_for_create_instance() - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = dict(server=dict( name='server_test', imageId=3, flavorId=2, @@ -875,7 +1210,7 @@ class ServersTest(test.TestCase): def test_create_instance_via_zones_with_resid(self): """User supplied ReservationID""" self._setup_for_create_instance() - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = dict(server=dict( name='server_test', imageId=3, flavorId=2, @@ -941,6 +1276,18 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400) + def test_create_instance_no_server_entity(self): + self._setup_for_create_instance() + + body = {} + + req = webob.Request.blank('/v1.0/servers') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 422) + def test_create_instance_whitespace_name(self): self._setup_for_create_instance() @@ -967,8 +1314,26 @@ class ServersTest(test.TestCase): def test_create_instance_v1_1(self): self._setup_for_create_instance() - image_href = 'http://localhost/v1.1/images/2' - flavor_ref = 'http://localhost/v1.1/flavors/3' + image_href = 'http://localhost/images/2' + flavor_ref = 'http://localhost/flavors/3' + expected_flavor = { + "id": "3", + "links": [ + { + "rel": "bookmark", + "href": 'http://localhost/flavors/3', + }, + ], + } + expected_image = { + "id": "2", + "links": [ + { + "rel": "bookmark", + "href": 'http://localhost/images/2', + }, + ], + } body = { 'server': { 'name': 'server_test', @@ -978,7 +1343,12 @@ class ServersTest(test.TestCase): 'hello': 'world', 'open': 'stack', }, - 'personality': {}, + 'personality': [ + { + "path": "/etc/banner.txt", + "contents": "MQ==", + }, + ], }, } @@ -992,10 +1362,11 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 200) server = json.loads(res.body)['server'] self.assertEqual(16, len(server['adminPass'])) - self.assertEqual('server_test', server['name']) self.assertEqual(1, server['id']) - self.assertEqual(flavor_ref, server['flavorRef']) - self.assertEqual(image_href, server['imageRef']) + self.assertEqual(0, server['progress']) + self.assertEqual('server_test', server['name']) + self.assertEqual(expected_flavor, server['flavor']) + self.assertEqual(expected_image, server['image']) def test_create_instance_v1_1_invalid_flavor_href(self): self._setup_for_create_instance() @@ -1048,8 +1419,26 @@ class ServersTest(test.TestCase): def test_create_instance_v1_1_local_href(self): self._setup_for_create_instance() - image_id = 2 + image_id = "2" flavor_ref = 'http://localhost/v1.1/flavors/3' + expected_flavor = { + "id": "3", + "links": [ + { + "rel": "bookmark", + "href": 'http://localhost/flavors/3', + }, + ], + } + expected_image = { + "id": "2", + "links": [ + { + "rel": "bookmark", + "href": 'http://localhost/images/2', + }, + ], + } body = { 'server': { 'name': 'server_test', @@ -1065,11 +1454,10 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) - server = json.loads(res.body)['server'] - self.assertEqual(1, server['id']) - self.assertEqual(flavor_ref, server['flavorRef']) - self.assertEqual(image_id, server['imageRef']) self.assertEqual(res.status_int, 200) + server = json.loads(res.body)['server'] + self.assertEqual(expected_flavor, server['flavor']) + self.assertEqual(expected_image, server['image']) def test_create_instance_with_admin_pass_v1_0(self): self._setup_for_create_instance() @@ -1092,7 +1480,7 @@ class ServersTest(test.TestCase): self.assertNotEqual(res['server']['adminPass'], body['server']['adminPass']) - def test_create_instance_with_admin_pass_v1_1(self): + def test_create_instance_v1_1_admin_pass(self): self._setup_for_create_instance() image_href = 'http://localhost/v1.1/images/2' @@ -1100,8 +1488,8 @@ class ServersTest(test.TestCase): body = { 'server': { 'name': 'server_test', - 'imageRef': image_href, - 'flavorRef': flavor_ref, + 'imageRef': 3, + 'flavorRef': 3, 'adminPass': 'testpass', }, } @@ -1111,19 +1499,18 @@ 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) server = json.loads(res.body)['server'] self.assertEqual(server['adminPass'], body['server']['adminPass']) - def test_create_instance_with_empty_admin_pass_v1_1(self): + def test_create_instance_v1_1_admin_pass_empty(self): self._setup_for_create_instance() - image_href = 'http://localhost/v1.1/images/2' - flavor_ref = 'http://localhost/v1.1/flavors/3' body = { 'server': { 'name': 'server_test', - 'imageRef': image_href, - 'flavorRef': flavor_ref, + 'imageRef': 3, + 'flavorRef': 3, 'adminPass': '', }, } @@ -1293,6 +1680,24 @@ class ServersTest(test.TestCase): self.assertEqual(s['metadata']['seq'], str(i)) def test_get_all_server_details_v1_1(self): + expected_flavor = { + "id": "1", + "links": [ + { + "rel": "bookmark", + "href": 'http://localhost/flavors/1', + }, + ], + } + expected_image = { + "id": "10", + "links": [ + { + "rel": "bookmark", + "href": 'http://localhost/images/10', + }, + ], + } req = webob.Request.blank('/v1.1/servers/detail') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -1301,8 +1706,8 @@ class ServersTest(test.TestCase): self.assertEqual(s['id'], i) self.assertEqual(s['hostId'], '') self.assertEqual(s['name'], 'server%d' % i) - self.assertEqual(s['imageRef'], 10) - self.assertEqual(s['flavorRef'], 'http://localhost/v1.1/flavors/1') + self.assertEqual(s['image'], expected_image) + self.assertEqual(s['flavor'], expected_flavor) self.assertEqual(s['status'], 'BUILD') self.assertEqual(s['metadata']['seq'], str(i)) @@ -1314,10 +1719,11 @@ class ServersTest(test.TestCase): instances - 2 on one host and 3 on another. ''' - def return_servers_with_host(context, user_id=1): - return [stub_instance(i, 1, None, None, i % 2) for i in xrange(5)] + def return_servers_with_host(context, *args, **kwargs): + return [stub_instance(i, 'fake', 'fake', None, None, i % 2) + for i in xrange(5)] - self.stubs.Set(nova.db.api, 'instance_get_all_by_user', + self.stubs.Set(nova.db.api, 'instance_get_all_by_project', return_servers_with_host) req = webob.Request.blank('/v1.0/servers/detail') @@ -1337,7 +1743,7 @@ class ServersTest(test.TestCase): self.assertEqual(s['flavorId'], 1) def test_server_pause(self): - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) @@ -1349,7 +1755,7 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 202) def test_server_unpause(self): - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) @@ -1361,7 +1767,7 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 202) def test_server_suspend(self): - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) @@ -1373,7 +1779,7 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 202) def test_server_resume(self): - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) @@ -1385,7 +1791,7 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 202) def test_server_reset_network(self): - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) @@ -1397,7 +1803,7 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 202) def test_server_inject_network_info(self): - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) @@ -1523,6 +1929,8 @@ class ServersTest(test.TestCase): state = power_state.BUILDING new_return_server = return_server_with_power_state(state) self.stubs.Set(nova.db.api, 'instance_get', new_return_server) + self.stubs.Set(nova.db, 'instance_get_by_uuid', + return_server_with_uuid_and_power_state(state)) req = webob.Request.blank('/v1.0/servers/1/action') req.method = 'POST' @@ -1571,6 +1979,8 @@ class ServersTest(test.TestCase): state = power_state.BUILDING new_return_server = return_server_with_power_state(state) self.stubs.Set(nova.db.api, 'instance_get', new_return_server) + self.stubs.Set(nova.db, 'instance_get_by_uuid', + return_server_with_uuid_and_power_state(state)) req = webob.Request.blank('/v1.1/servers/1/action') req.method = 'POST' @@ -1684,7 +2094,7 @@ class ServersTest(test.TestCase): self.assertEqual(self.server_delete_called, True) def test_rescue_accepted(self): - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = {} self.called = False @@ -1703,7 +2113,7 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 202) def test_rescue_raises_handled(self): - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = {} def rescue_mock(*args, **kwargs): @@ -1749,11 +2159,14 @@ class ServersTest(test.TestCase): self.assertEqual(self.resize_called, True) def test_resize_server_v11(self): - req = webob.Request.blank('/v1.1/servers/1/action') req.content_type = 'application/json' req.method = 'POST' - body_dict = dict(resize=dict(flavorRef="http://localhost/3")) + body_dict = { + "resize": { + "flavorRef": 3, + }, + } req.body = json.dumps(body_dict) self.resize_called = False @@ -1767,8 +2180,8 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 202) self.assertEqual(self.resize_called, True) - def test_resize_bad_flavor_fails(self): - req = self.webreq('/1/action', 'POST', dict(resize=dict(derp=3))) + def test_resize_bad_flavor_data(self): + req = self.webreq('/1/action', 'POST', {"resize": "bad_data"}) self.resize_called = False @@ -1778,14 +2191,54 @@ class ServersTest(test.TestCase): self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 422) + self.assertEqual(res.status_int, 400) self.assertEqual(self.resize_called, False) + def test_resize_invalid_flavorid(self): + req = self.webreq('/1/action', 'POST', {"resize": {"flavorId": 300}}) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_resize_nonint_flavorid(self): + req = self.webreq('/1/action', 'POST', {"resize": {"flavorId": "a"}}) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_resize_invalid_flavorid_v1_1(self): + req = webob.Request.blank('/v1.1/servers/1/action') + req.content_type = 'application/json' + req.method = 'POST' + resize_body = { + "resize": { + "image": { + "id": 300, + }, + }, + } + req.body = json.dumps(resize_body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_resize_nonint_flavorid_v1_1(self): + req = webob.Request.blank('/v1.1/servers/1/action') + req.content_type = 'application/json' + req.method = 'POST' + resize_body = { + "resize": { + "image": { + "id": "a", + }, + }, + } + req.body = json.dumps(resize_body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + def test_resize_raises_fails(self): req = self.webreq('/1/action', 'POST', dict(resize=dict(flavorId=3))) def resize_mock(*args): - raise Exception('hurr durr') + raise Exception("An error occurred.") self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) @@ -1823,7 +2276,7 @@ class ServersTest(test.TestCase): req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) def confirm_resize_mock(*args): - raise Exception('hurr durr') + raise Exception("An error occurred.") self.stubs.Set(nova.compute.api.API, 'confirm_resize', confirm_resize_mock) @@ -1850,7 +2303,7 @@ class ServersTest(test.TestCase): req = self.webreq('/1/action', 'POST', dict(revertResize=None)) def revert_resize_mock(*args): - raise Exception('hurr durr') + raise Exception("An error occurred.") self.stubs.Set(nova.compute.api.API, 'revert_resize', revert_resize_mock) @@ -1894,7 +2347,7 @@ class ServersTest(test.TestCase): self.assertEqual(res_dict['server']['status'], 'SHUTOFF') -class TestServerCreateRequestXMLDeserializer(unittest.TestCase): +class TestServerCreateRequestXMLDeserializerV10(unittest.TestCase): def setUp(self): self.deserializer = create_instance_helper.ServerXMLDeserializer() @@ -1908,6 +2361,8 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase): "name": "new-server-test", "imageId": "1", "flavorId": "1", + "metadata": {}, + "personality": [], }} self.assertEquals(request['body'], expected) @@ -1923,6 +2378,7 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase): "imageId": "1", "flavorId": "1", "metadata": {}, + "personality": [], }} self.assertEquals(request['body'], expected) @@ -1937,6 +2393,7 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase): "name": "new-server-test", "imageId": "1", "flavorId": "1", + "metadata": {}, "personality": [], }} self.assertEquals(request['body'], expected) @@ -2174,36 +2631,252 @@ b25zLiINCg0KLVJpY2hhcmQgQmFjaA==""", request = self.deserializer.deserialize(serial_request, 'create') self.assertEqual(request['body'], expected) - def test_request_xmlser_with_flavor_image_href(self): + +class TestServerCreateRequestXMLDeserializerV11(unittest.TestCase): + + def setUp(self): + self.deserializer = create_instance_helper.ServerXMLDeserializer() + + def test_minimal_request(self): + serial_request = """ +<server xmlns="http://docs.openstack.org/compute/api/v1.1" + name="new-server-test" + imageRef="1" + flavorRef="2"/>""" + request = self.deserializer.deserialize(serial_request, 'create') + expected = { + "server": { + "name": "new-server-test", + "imageRef": "1", + "flavorRef": "2", + "metadata": {}, + "personality": [], + }, + } + self.assertEquals(request['body'], expected) + + def test_admin_pass(self): serial_request = """ - <server xmlns="http://docs.openstack.org/compute/api/v1.1" - name="new-server-test" - imageRef="http://localhost:8774/v1.1/images/1" - flavorRef="http://localhost:8774/v1.1/flavors/1"> - </server>""" +<server xmlns="http://docs.openstack.org/compute/api/v1.1" + name="new-server-test" + imageRef="1" + flavorRef="2" + adminPass="1234"/>""" request = self.deserializer.deserialize(serial_request, 'create') - self.assertEquals(request['body']["server"]["flavorRef"], - "http://localhost:8774/v1.1/flavors/1") - self.assertEquals(request['body']["server"]["imageRef"], - "http://localhost:8774/v1.1/images/1") + expected = { + "server": { + "name": "new-server-test", + "imageRef": "1", + "flavorRef": "2", + "adminPass": "1234", + "metadata": {}, + "personality": [], + }, + } + self.assertEquals(request['body'], expected) + + def test_image_link(self): + serial_request = """ +<server xmlns="http://docs.openstack.org/compute/api/v1.1" + name="new-server-test" + imageRef="http://localhost:8774/v1.1/images/2" + flavorRef="3"/>""" + request = self.deserializer.deserialize(serial_request, 'create') + expected = { + "server": { + "name": "new-server-test", + "imageRef": "http://localhost:8774/v1.1/images/2", + "flavorRef": "3", + "metadata": {}, + "personality": [], + }, + } + self.assertEquals(request['body'], expected) + + def test_flavor_link(self): + serial_request = """ +<server xmlns="http://docs.openstack.org/compute/api/v1.1" + name="new-server-test" + imageRef="1" + flavorRef="http://localhost:8774/v1.1/flavors/3"/>""" + request = self.deserializer.deserialize(serial_request, 'create') + expected = { + "server": { + "name": "new-server-test", + "imageRef": "1", + "flavorRef": "http://localhost:8774/v1.1/flavors/3", + "metadata": {}, + "personality": [], + }, + } + self.assertEquals(request['body'], expected) + + def test_empty_metadata_personality(self): + serial_request = """ +<server xmlns="http://docs.openstack.org/compute/api/v1.1" + name="new-server-test" + imageRef="1" + flavorRef="2"> + <metadata/> + <personality/> +</server>""" + request = self.deserializer.deserialize(serial_request, 'create') + expected = { + "server": { + "name": "new-server-test", + "imageRef": "1", + "flavorRef": "2", + "metadata": {}, + "personality": [], + }, + } + self.assertEquals(request['body'], expected) + + def test_multiple_metadata_items(self): + serial_request = """ +<server xmlns="http://docs.openstack.org/compute/api/v1.1" + name="new-server-test" + imageRef="1" + flavorRef="2"> + <metadata> + <meta key="one">two</meta> + <meta key="open">snack</meta> + </metadata> +</server>""" + request = self.deserializer.deserialize(serial_request, 'create') + expected = { + "server": { + "name": "new-server-test", + "imageRef": "1", + "flavorRef": "2", + "metadata": {"one": "two", "open": "snack"}, + "personality": [], + }, + } + self.assertEquals(request['body'], expected) + + def test_multiple_personality_files(self): + serial_request = """ +<server xmlns="http://docs.openstack.org/compute/api/v1.1" + name="new-server-test" + imageRef="1" + flavorRef="2"> + <personality> + <file path="/etc/banner.txt">MQ==</file> + <file path="/etc/hosts">Mg==</file> + </personality> +</server>""" + request = self.deserializer.deserialize(serial_request, 'create') + expected = { + "server": { + "name": "new-server-test", + "imageRef": "1", + "flavorRef": "2", + "metadata": {}, + "personality": [ + {"path": "/etc/banner.txt", "contents": "MQ=="}, + {"path": "/etc/hosts", "contents": "Mg=="}, + ], + }, + } + self.assertEquals(request['body'], expected) + + def test_spec_request(self): + image_bookmark_link = "http://servers.api.openstack.org/1234/" + \ + "images/52415800-8b69-11e0-9b19-734f6f006e54" + serial_request = """ +<server xmlns="http://docs.openstack.org/compute/api/v1.1" + imageRef="%s" + flavorRef="52415800-8b69-11e0-9b19-734f1195ff37" + name="new-server-test"> + <metadata> + <meta key="My Server Name">Apache1</meta> + </metadata> + <personality> + <file path="/etc/banner.txt">Mg==</file> + </personality> +</server>""" % (image_bookmark_link) + request = self.deserializer.deserialize(serial_request, 'create') + expected = { + "server": { + "name": "new-server-test", + "imageRef": "http://servers.api.openstack.org/1234/" + \ + "images/52415800-8b69-11e0-9b19-734f6f006e54", + "flavorRef": "52415800-8b69-11e0-9b19-734f1195ff37", + "metadata": {"My Server Name": "Apache1"}, + "personality": [ + { + "path": "/etc/banner.txt", + "contents": "Mg==", + }, + ], + }, + } + self.assertEquals(request['body'], expected) + + +class TextAddressesXMLSerialization(test.TestCase): + + serializer = nova.api.openstack.ips.IPXMLSerializer() + + def test_show(self): + fixture = { + 'network_2': [ + {'addr': '192.168.0.1', 'version': 4}, + {'addr': 'fe80::beef', 'version': 6}, + ], + } + output = self.serializer.serialize(fixture, 'show') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(""" + <network xmlns="http://docs.openstack.org/compute/api/v1.1" + id="network_2"> + <ip version="4" addr="192.168.0.1"/> + <ip version="6" addr="fe80::beef"/> + </network> + """.replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_index(self): + fixture = { + 'addresses': { + 'network_1': [ + {'addr': '192.168.0.3', 'version': 4}, + {'addr': '192.168.0.5', 'version': 4}, + ], + 'network_2': [ + {'addr': '192.168.0.1', 'version': 4}, + {'addr': 'fe80::beef', 'version': 6}, + ], + }, + } + output = self.serializer.serialize(fixture, 'index') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(""" + <addresses xmlns="http://docs.openstack.org/compute/api/v1.1"> + <network id="network_2"> + <ip version="4" addr="192.168.0.1"/> + <ip version="6" addr="fe80::beef"/> + </network> + <network id="network_1"> + <ip version="4" addr="192.168.0.3"/> + <ip version="4" addr="192.168.0.5"/> + </network> + </addresses> + """.replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) class TestServerInstanceCreation(test.TestCase): def setUp(self): super(TestServerInstanceCreation, self).setUp() - self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.auth_data = {} - fakes.FakeAuthDatabase.data = {} - fakes.stub_out_auth(self.stubs) fakes.stub_out_image_service(self.stubs) fakes.stub_out_key_pair_funcs(self.stubs) - self.allow_admin = FLAGS.allow_admin_api - - def tearDown(self): - self.stubs.UnsetAll() - FLAGS.allow_admin_api = self.allow_admin - super(TestServerInstanceCreation, self).tearDown() def _setup_mock_compute_api_for_personality(self): @@ -2490,3 +3163,753 @@ class TestGetKernelRamdiskFromImage(test.TestCase): kernel_id, ramdisk_id = create_instance_helper.CreateInstanceHelper. \ _do_get_kernel_ramdisk_from_image(image_meta) return kernel_id, ramdisk_id + + +class ServersViewBuilderV11Test(test.TestCase): + + def setUp(self): + self.instance = self._get_instance() + self.view_builder = self._get_view_builder() + + def tearDown(self): + pass + + def _get_instance(self): + created_at = datetime.datetime(2010, 10, 10, 12, 0, 0) + updated_at = datetime.datetime(2010, 11, 11, 11, 0, 0) + instance = { + "id": 1, + "created_at": created_at, + "updated_at": updated_at, + "admin_pass": "", + "user_id": "", + "project_id": "", + "image_ref": "5", + "kernel_id": "", + "ramdisk_id": "", + "launch_index": 0, + "key_name": "", + "key_data": "", + "state": 0, + "state_description": "", + "memory_mb": 0, + "vcpus": 0, + "local_gb": 0, + "hostname": "", + "host": "", + "instance_type": { + "flavorid": 1, + }, + "user_data": "", + "reservation_id": "", + "mac_address": "", + "scheduled_at": utils.utcnow(), + "launched_at": utils.utcnow(), + "terminated_at": utils.utcnow(), + "availability_zone": "", + "display_name": "test_server", + "display_description": "", + "locked": False, + "metadata": [], + #"address": , + #"floating_ips": [{"address":ip} for ip in public_addresses]} + "uuid": "deadbeef-feed-edee-beef-d0ea7beefedd"} + + return instance + + def _get_view_builder(self): + base_url = "http://localhost/v1.1" + views = nova.api.openstack.views + address_builder = views.addresses.ViewBuilderV11() + flavor_builder = views.flavors.ViewBuilderV11(base_url) + image_builder = views.images.ViewBuilderV11(base_url) + + view_builder = nova.api.openstack.views.servers.ViewBuilderV11( + address_builder, + flavor_builder, + image_builder, + base_url, + ) + return view_builder + + def test_build_server(self): + expected_server = { + "server": { + "id": 1, + "uuid": self.instance['uuid'], + "name": "test_server", + "links": [ + { + "rel": "self", + "href": "http://localhost/v1.1/servers/1", + }, + { + "rel": "bookmark", + "href": "http://localhost/servers/1", + }, + ], + } + } + + output = self.view_builder.build(self.instance, False) + self.assertDictMatch(output, expected_server) + + def test_build_server_detail(self): + image_bookmark = "http://localhost/images/5" + flavor_bookmark = "http://localhost/flavors/1" + expected_server = { + "server": { + "id": 1, + "uuid": self.instance['uuid'], + "updated": "2010-11-11T11:00:00Z", + "created": "2010-10-10T12:00:00Z", + "progress": 0, + "name": "test_server", + "status": "BUILD", + "hostId": '', + "image": { + "id": "5", + "links": [ + { + "rel": "bookmark", + "href": image_bookmark, + }, + ], + }, + "flavor": { + "id": "1", + "links": [ + { + "rel": "bookmark", + "href": flavor_bookmark, + }, + ], + }, + "addresses": {}, + "metadata": {}, + "links": [ + { + "rel": "self", + "href": "http://localhost/v1.1/servers/1", + }, + { + "rel": "bookmark", + "href": "http://localhost/servers/1", + }, + ], + } + } + + output = self.view_builder.build(self.instance, True) + self.assertDictMatch(output, expected_server) + + def test_build_server_detail_active_status(self): + #set the power state of the instance to running + self.instance['state'] = 1 + image_bookmark = "http://localhost/images/5" + flavor_bookmark = "http://localhost/flavors/1" + expected_server = { + "server": { + "id": 1, + "uuid": self.instance['uuid'], + "updated": "2010-11-11T11:00:00Z", + "created": "2010-10-10T12:00:00Z", + "progress": 100, + "name": "test_server", + "status": "ACTIVE", + "hostId": '', + "image": { + "id": "5", + "links": [ + { + "rel": "bookmark", + "href": image_bookmark, + }, + ], + }, + "flavor": { + "id": "1", + "links": [ + { + "rel": "bookmark", + "href": flavor_bookmark, + }, + ], + }, + "addresses": {}, + "metadata": {}, + "links": [ + { + "rel": "self", + "href": "http://localhost/v1.1/servers/1", + }, + { + "rel": "bookmark", + "href": "http://localhost/servers/1", + }, + ], + } + } + + output = self.view_builder.build(self.instance, True) + self.assertDictMatch(output, expected_server) + + def test_build_server_detail_with_metadata(self): + + metadata = [] + metadata.append(InstanceMetadata(key="Open", value="Stack")) + metadata.append(InstanceMetadata(key="Number", value=1)) + self.instance['metadata'] = metadata + + image_bookmark = "http://localhost/images/5" + flavor_bookmark = "http://localhost/flavors/1" + expected_server = { + "server": { + "id": 1, + "uuid": self.instance['uuid'], + "updated": "2010-11-11T11:00:00Z", + "created": "2010-10-10T12:00:00Z", + "progress": 0, + "name": "test_server", + "status": "BUILD", + "hostId": '', + "image": { + "id": "5", + "links": [ + { + "rel": "bookmark", + "href": image_bookmark, + }, + ], + }, + "flavor": { + "id": "1", + "links": [ + { + "rel": "bookmark", + "href": flavor_bookmark, + }, + ], + }, + "addresses": {}, + "metadata": { + "Open": "Stack", + "Number": "1", + }, + "links": [ + { + "rel": "self", + "href": "http://localhost/v1.1/servers/1", + }, + { + "rel": "bookmark", + "href": "http://localhost/servers/1", + }, + ], + } + } + + output = self.view_builder.build(self.instance, True) + self.assertDictMatch(output, expected_server) + + +class ServerXMLSerializationTest(test.TestCase): + + TIMESTAMP = "2010-10-11T10:30:22Z" + SERVER_HREF = 'http://localhost/v1.1/servers/123' + SERVER_BOOKMARK = 'http://localhost/servers/123' + IMAGE_BOOKMARK = 'http://localhost/images/5' + FLAVOR_BOOKMARK = 'http://localhost/flavors/1' + + def setUp(self): + self.maxDiff = None + test.TestCase.setUp(self) + + def test_show(self): + serializer = servers.ServerXMLSerializer() + + fixture = { + "server": { + "id": 1, + "uuid": FAKE_UUID, + 'created': self.TIMESTAMP, + 'updated': self.TIMESTAMP, + "progress": 0, + "name": "test_server", + "status": "BUILD", + "hostId": 'e4d909c290d0fb1ca068ffaddf22cbd0', + "image": { + "id": "5", + "links": [ + { + "rel": "bookmark", + "href": self.IMAGE_BOOKMARK, + }, + ], + }, + "flavor": { + "id": "1", + "links": [ + { + "rel": "bookmark", + "href": self.FLAVOR_BOOKMARK, + }, + ], + }, + "addresses": { + "network_one": [ + { + "version": 4, + "addr": "67.23.10.138", + }, + { + "version": 6, + "addr": "::babe:67.23.10.138", + }, + ], + "network_two": [ + { + "version": 4, + "addr": "67.23.10.139", + }, + { + "version": 6, + "addr": "::babe:67.23.10.139", + }, + ], + }, + "metadata": { + "Open": "Stack", + "Number": "1", + }, + 'links': [ + { + 'href': self.SERVER_HREF, + 'rel': 'self', + }, + { + 'href': self.SERVER_BOOKMARK, + 'rel': 'bookmark', + }, + ], + } + } + + output = serializer.serialize(fixture, 'show') + actual = minidom.parseString(output.replace(" ", "")) + + expected_server_href = self.SERVER_HREF + expected_server_bookmark = self.SERVER_BOOKMARK + expected_image_bookmark = self.IMAGE_BOOKMARK + expected_flavor_bookmark = self.FLAVOR_BOOKMARK + expected_now = self.TIMESTAMP + expected_uuid = FAKE_UUID + expected = minidom.parseString(""" + <server id="1" + uuid="%(expected_uuid)s" + xmlns="http://docs.openstack.org/compute/api/v1.1" + xmlns:atom="http://www.w3.org/2005/Atom" + name="test_server" + updated="%(expected_now)s" + created="%(expected_now)s" + hostId="e4d909c290d0fb1ca068ffaddf22cbd0" + status="BUILD" + progress="0"> + <atom:link href="%(expected_server_href)s" rel="self"/> + <atom:link href="%(expected_server_bookmark)s" rel="bookmark"/> + <image id="5"> + <atom:link rel="bookmark" href="%(expected_image_bookmark)s"/> + </image> + <flavor id="1"> + <atom:link rel="bookmark" href="%(expected_flavor_bookmark)s"/> + </flavor> + <metadata> + <meta key="Open"> + Stack + </meta> + <meta key="Number"> + 1 + </meta> + </metadata> + <addresses> + <network id="network_one"> + <ip version="4" addr="67.23.10.138"/> + <ip version="6" addr="::babe:67.23.10.138"/> + </network> + <network id="network_two"> + <ip version="4" addr="67.23.10.139"/> + <ip version="6" addr="::babe:67.23.10.139"/> + </network> + </addresses> + </server> + """.replace(" ", "") % (locals())) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_create(self): + serializer = servers.ServerXMLSerializer() + + fixture = { + "server": { + "id": 1, + "uuid": FAKE_UUID, + 'created': self.TIMESTAMP, + 'updated': self.TIMESTAMP, + "progress": 0, + "name": "test_server", + "status": "BUILD", + "hostId": "e4d909c290d0fb1ca068ffaddf22cbd0", + "adminPass": "test_password", + "image": { + "id": "5", + "links": [ + { + "rel": "bookmark", + "href": self.IMAGE_BOOKMARK, + }, + ], + }, + "flavor": { + "id": "1", + "links": [ + { + "rel": "bookmark", + "href": self.FLAVOR_BOOKMARK, + }, + ], + }, + "addresses": { + "network_one": [ + { + "version": 4, + "addr": "67.23.10.138", + }, + { + "version": 6, + "addr": "::babe:67.23.10.138", + }, + ], + "network_two": [ + { + "version": 4, + "addr": "67.23.10.139", + }, + { + "version": 6, + "addr": "::babe:67.23.10.139", + }, + ], + }, + "metadata": { + "Open": "Stack", + "Number": "1", + }, + 'links': [ + { + 'href': self.SERVER_HREF, + 'rel': 'self', + }, + { + 'href': self.SERVER_BOOKMARK, + 'rel': 'bookmark', + }, + ], + } + } + + output = serializer.serialize(fixture, 'create') + actual = minidom.parseString(output.replace(" ", "")) + + expected_server_href = self.SERVER_HREF + expected_server_bookmark = self.SERVER_BOOKMARK + expected_image_bookmark = self.IMAGE_BOOKMARK + expected_flavor_bookmark = self.FLAVOR_BOOKMARK + expected_now = self.TIMESTAMP + expected_uuid = FAKE_UUID + expected = minidom.parseString(""" + <server id="1" + uuid="%(expected_uuid)s" + xmlns="http://docs.openstack.org/compute/api/v1.1" + xmlns:atom="http://www.w3.org/2005/Atom" + name="test_server" + updated="%(expected_now)s" + created="%(expected_now)s" + hostId="e4d909c290d0fb1ca068ffaddf22cbd0" + status="BUILD" + adminPass="test_password" + progress="0"> + <atom:link href="%(expected_server_href)s" rel="self"/> + <atom:link href="%(expected_server_bookmark)s" rel="bookmark"/> + <image id="5"> + <atom:link rel="bookmark" href="%(expected_image_bookmark)s"/> + </image> + <flavor id="1"> + <atom:link rel="bookmark" href="%(expected_flavor_bookmark)s"/> + </flavor> + <metadata> + <meta key="Open"> + Stack + </meta> + <meta key="Number"> + 1 + </meta> + </metadata> + <addresses> + <network id="network_one"> + <ip version="4" addr="67.23.10.138"/> + <ip version="6" addr="::babe:67.23.10.138"/> + </network> + <network id="network_two"> + <ip version="4" addr="67.23.10.139"/> + <ip version="6" addr="::babe:67.23.10.139"/> + </network> + </addresses> + </server> + """.replace(" ", "") % (locals())) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_index(self): + serializer = servers.ServerXMLSerializer() + + expected_server_href = 'http://localhost/v1.1/servers/1' + expected_server_bookmark = 'http://localhost/servers/1' + expected_server_href_2 = 'http://localhost/v1.1/servers/2' + expected_server_bookmark_2 = 'http://localhost/servers/2' + fixture = {"servers": [ + { + "id": 1, + "name": "test_server", + 'links': [ + { + 'href': expected_server_href, + 'rel': 'self', + }, + { + 'href': expected_server_bookmark, + 'rel': 'bookmark', + }, + ], + }, + { + "id": 2, + "name": "test_server_2", + 'links': [ + { + 'href': expected_server_href_2, + 'rel': 'self', + }, + { + 'href': expected_server_bookmark_2, + 'rel': 'bookmark', + }, + ], + }, + ]} + + output = serializer.serialize(fixture, 'index') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(""" + <servers xmlns="http://docs.openstack.org/compute/api/v1.1" + xmlns:atom="http://www.w3.org/2005/Atom"> + <server id="1" name="test_server"> + <atom:link href="%(expected_server_href)s" rel="self"/> + <atom:link href="%(expected_server_bookmark)s" rel="bookmark"/> + </server> + <server id="2" name="test_server_2"> + <atom:link href="%(expected_server_href_2)s" rel="self"/> + <atom:link href="%(expected_server_bookmark_2)s" rel="bookmark"/> + </server> + </servers> + """.replace(" ", "") % (locals())) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_detail(self): + serializer = servers.ServerXMLSerializer() + + expected_server_href = 'http://localhost/v1.1/servers/1' + expected_server_bookmark = 'http://localhost/servers/1' + expected_image_bookmark = self.IMAGE_BOOKMARK + expected_flavor_bookmark = self.FLAVOR_BOOKMARK + expected_now = self.TIMESTAMP + expected_uuid = FAKE_UUID + + expected_server_href_2 = 'http://localhost/v1.1/servers/2' + expected_server_bookmark_2 = 'http://localhost/servers/2' + fixture = {"servers": [ + { + "id": 1, + "uuid": FAKE_UUID, + 'created': self.TIMESTAMP, + 'updated': self.TIMESTAMP, + "progress": 0, + "name": "test_server", + "status": "BUILD", + "hostId": 'e4d909c290d0fb1ca068ffaddf22cbd0', + "image": { + "id": "5", + "links": [ + { + "rel": "bookmark", + "href": expected_image_bookmark, + }, + ], + }, + "flavor": { + "id": "1", + "links": [ + { + "rel": "bookmark", + "href": expected_flavor_bookmark, + }, + ], + }, + "addresses": { + "network_one": [ + { + "version": 4, + "addr": "67.23.10.138", + }, + { + "version": 6, + "addr": "::babe:67.23.10.138", + }, + ], + }, + "metadata": { + "Number": "1", + }, + "links": [ + { + "href": expected_server_href, + "rel": "self", + }, + { + "href": expected_server_bookmark, + "rel": "bookmark", + }, + ], + }, + { + "id": 2, + "uuid": FAKE_UUID, + 'created': self.TIMESTAMP, + 'updated': self.TIMESTAMP, + "progress": 100, + "name": "test_server_2", + "status": "ACTIVE", + "hostId": 'e4d909c290d0fb1ca068ffaddf22cbd0', + "image": { + "id": "5", + "links": [ + { + "rel": "bookmark", + "href": expected_image_bookmark, + }, + ], + }, + "flavor": { + "id": "1", + "links": [ + { + "rel": "bookmark", + "href": expected_flavor_bookmark, + }, + ], + }, + "addresses": { + "network_one": [ + { + "version": 4, + "addr": "67.23.10.138", + }, + { + "version": 6, + "addr": "::babe:67.23.10.138", + }, + ], + }, + "metadata": { + "Number": "2", + }, + "links": [ + { + "href": expected_server_href_2, + "rel": "self", + }, + { + "href": expected_server_bookmark_2, + "rel": "bookmark", + }, + ], + }, + ]} + + output = serializer.serialize(fixture, 'detail') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(""" + <servers xmlns="http://docs.openstack.org/compute/api/v1.1" + xmlns:atom="http://www.w3.org/2005/Atom"> + <server id="1" + uuid="%(expected_uuid)s" + name="test_server" + updated="%(expected_now)s" + created="%(expected_now)s" + hostId="e4d909c290d0fb1ca068ffaddf22cbd0" + status="BUILD" + progress="0"> + <atom:link href="%(expected_server_href)s" rel="self"/> + <atom:link href="%(expected_server_bookmark)s" rel="bookmark"/> + <image id="5"> + <atom:link rel="bookmark" href="%(expected_image_bookmark)s"/> + </image> + <flavor id="1"> + <atom:link rel="bookmark" href="%(expected_flavor_bookmark)s"/> + </flavor> + <metadata> + <meta key="Number"> + 1 + </meta> + </metadata> + <addresses> + <network id="network_one"> + <ip version="4" addr="67.23.10.138"/> + <ip version="6" addr="::babe:67.23.10.138"/> + </network> + </addresses> + </server> + <server id="2" + uuid="%(expected_uuid)s" + name="test_server_2" + updated="%(expected_now)s" + created="%(expected_now)s" + hostId="e4d909c290d0fb1ca068ffaddf22cbd0" + status="ACTIVE" + progress="100"> + <atom:link href="%(expected_server_href_2)s" rel="self"/> + <atom:link href="%(expected_server_bookmark_2)s" rel="bookmark"/> + <image id="5"> + <atom:link rel="bookmark" href="%(expected_image_bookmark)s"/> + </image> + <flavor id="1"> + <atom:link rel="bookmark" href="%(expected_flavor_bookmark)s"/> + </flavor> + <metadata> + <meta key="Number"> + 2 + </meta> + </metadata> + <addresses> + <network id="network_one"> + <ip version="4" addr="67.23.10.138"/> + <ip version="6" addr="::babe:67.23.10.138"/> + </network> + </addresses> + </server> + </servers> + """.replace(" ", "") % (locals())) + + self.assertEqual(expected.toxml(), actual.toxml()) diff --git a/nova/tests/api/openstack/test_shared_ip_groups.py b/nova/tests/api/openstack/test_shared_ip_groups.py index c2bd7e45a..36fa1de0f 100644 --- a/nova/tests/api/openstack/test_shared_ip_groups.py +++ b/nova/tests/api/openstack/test_shared_ip_groups.py @@ -15,26 +15,13 @@ # License for the specific language governing permissions and limitations # under the License. -import stubout import webob from nova import test -from nova.api.openstack import shared_ip_groups from nova.tests.api.openstack import fakes class SharedIpGroupsTest(test.TestCase): - def setUp(self): - super(SharedIpGroupsTest, self).setUp() - self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.reset_fake_data() - fakes.FakeAuthDatabase.data = {} - fakes.stub_out_auth(self.stubs) - - def tearDown(self): - self.stubs.UnsetAll() - super(SharedIpGroupsTest, self).tearDown() - def test_get_shared_ip_groups(self): req = webob.Request.blank('/v1.0/shared_ip_groups') res = req.get_response(fakes.wsgi_app()) diff --git a/nova/tests/api/openstack/test_users.py b/nova/tests/api/openstack/test_users.py index effb2f592..705c02f6b 100644 --- a/nova/tests/api/openstack/test_users.py +++ b/nova/tests/api/openstack/test_users.py @@ -15,7 +15,6 @@ import json -import stubout import webob from nova import flags @@ -41,7 +40,7 @@ def fake_admin_check(self, req): class UsersTest(test.TestCase): def setUp(self): super(UsersTest, self).setUp() - self.stubs = stubout.StubOutForTesting() + self.flags(allow_admin_api=True) self.stubs.Set(users.Controller, '__init__', fake_init) self.stubs.Set(users.Controller, '_check_admin', @@ -58,16 +57,10 @@ class UsersTest(test.TestCase): fakes.stub_out_auth(self.stubs) self.allow_admin = FLAGS.allow_admin_api - FLAGS.allow_admin_api = True fakemgr = fakes.FakeAuthManager() fakemgr.add_user(User('id1', 'guy1', 'acc1', 'secret1', False)) fakemgr.add_user(User('id2', 'guy2', 'acc2', 'secret2', True)) - def tearDown(self): - self.stubs.UnsetAll() - FLAGS.allow_admin_api = self.allow_admin - super(UsersTest, self).tearDown() - def test_get_user_list(self): req = webob.Request.blank('/v1.0/users') res = req.get_response(fakes.wsgi_app()) diff --git a/nova/tests/api/openstack/test_wsgi.py b/nova/tests/api/openstack/test_wsgi.py index 5bdda7c7e..6dea78d17 100644 --- a/nova/tests/api/openstack/test_wsgi.py +++ b/nova/tests/api/openstack/test_wsgi.py @@ -256,6 +256,13 @@ class ResponseSerializerTest(test.TestCase): self.assertEqual(response.body, 'pew_json') self.assertEqual(response.status_int, 404) + def test_serialize_response_None(self): + response = self.serializer.serialize(None, 'application/json') + print response + self.assertEqual(response.headers['Content-Type'], 'application/json') + self.assertEqual(response.body, '') + self.assertEqual(response.status_int, 404) + def test_serialize_response_dict_to_unknown_content_type(self): self.assertRaises(exception.InvalidContentType, self.serializer.serialize, diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 6a6e13d93..3deb844aa 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -95,31 +95,15 @@ def zone_select(context, specs): class ZonesTest(test.TestCase): def setUp(self): super(ZonesTest, self).setUp() - self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.reset_fake_data() - fakes.FakeAuthDatabase.data = {} + self.flags(allow_admin_api=True) fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) - fakes.stub_out_auth(self.stubs) - - self.allow_admin = FLAGS.allow_admin_api - FLAGS.allow_admin_api = True self.stubs.Set(nova.db, 'zone_get', zone_get) self.stubs.Set(nova.db, 'zone_update', zone_update) self.stubs.Set(nova.db, 'zone_create', zone_create) self.stubs.Set(nova.db, 'zone_delete', zone_delete) - self.old_zone_name = FLAGS.zone_name - self.old_zone_capabilities = FLAGS.zone_capabilities - - def tearDown(self): - self.stubs.UnsetAll() - FLAGS.allow_admin_api = self.allow_admin - FLAGS.zone_name = self.old_zone_name - FLAGS.zone_capabilities = self.old_zone_capabilities - super(ZonesTest, self).tearDown() - def test_get_zone_list_scheduler(self): self.stubs.Set(api, '_call_scheduler', zone_get_all_scheduler) req = webob.Request.blank('/v1.0/zones') @@ -190,8 +174,8 @@ class ZonesTest(test.TestCase): self.assertFalse('username' in res_dict['zone']) def test_zone_info(self): - FLAGS.zone_name = 'darksecret' - FLAGS.zone_capabilities = ['cap1=a;b', 'cap2=c;d'] + caps = ['cap1=a;b', 'cap2=c;d'] + self.flags(zone_name='darksecret', zone_capabilities=caps) self.stubs.Set(api, '_call_scheduler', zone_capabilities) body = dict(zone=dict(username='zeb', password='sneaky')) @@ -205,7 +189,8 @@ class ZonesTest(test.TestCase): self.assertEqual(res_dict['zone']['cap2'], 'c;d') def test_zone_select(self): - FLAGS.build_plan_encryption_key = 'c286696d887c9aa0611bbb3e2025a45a' + key = 'c286696d887c9aa0611bbb3e2025a45a' + self.flags(build_plan_encryption_key=key) self.stubs.Set(api, 'select', zone_select) req = webob.Request.blank('/v1.0/zones/select') diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py index 2297d2f0e..073216495 100644 --- a/nova/tests/fake_flags.py +++ b/nova/tests/fake_flags.py @@ -42,3 +42,4 @@ FLAGS['iscsi_num_targets'].SetDefault(8) FLAGS['verbose'].SetDefault(True) FLAGS['sqlite_db'].SetDefault("tests.sqlite") FLAGS['use_ipv6'].SetDefault(True) +FLAGS['flat_network_bridge'].SetDefault('br100') diff --git a/nova/tests/hyperv_unittest.py b/nova/tests/hyperv_unittest.py index 042819b9c..0ea196950 100644 --- a/nova/tests/hyperv_unittest.py +++ b/nova/tests/hyperv_unittest.py @@ -23,7 +23,6 @@ from nova import context from nova import db from nova import flags from nova import test -from nova.auth import manager from nova.virt import hyperv FLAGS = flags.FLAGS @@ -34,11 +33,9 @@ class HyperVTestCase(test.TestCase): """Test cases for the Hyper-V driver""" def setUp(self): super(HyperVTestCase, self).setUp() - self.manager = manager.AuthManager() - self.user = self.manager.create_user('fake', 'fake', 'fake', - admin=True) - self.project = self.manager.create_project('fake', 'fake', 'fake') - self.context = context.RequestContext(self.user, self.project) + self.user_id = 'fake' + self.project_id = 'fake' + self.context = context.RequestContext(self.user_id, self.project_id) def test_create_destroy(self): """Create a VM and destroy it""" diff --git a/nova/tests/integrated/test_servers.py b/nova/tests/integrated/test_servers.py index 4e8e85c7b..67b3c485a 100644 --- a/nova/tests/integrated/test_servers.py +++ b/nova/tests/integrated/test_servers.py @@ -305,5 +305,6 @@ class ServersTest(integrated_helpers._IntegratedTestBase): # Cleanup self._delete_server(server_id) + if __name__ == "__main__": unittest.main() diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py index daea826fd..6a56a57db 100644 --- a/nova/tests/scheduler/test_scheduler.py +++ b/nova/tests/scheduler/test_scheduler.py @@ -23,7 +23,6 @@ import datetime import mox import novaclient.exceptions import stubout -import webob from mox import IgnoreArg from nova import context @@ -34,12 +33,10 @@ from nova import service from nova import test from nova import rpc from nova import utils -from nova.auth import manager as auth_manager from nova.scheduler import api from nova.scheduler import manager from nova.scheduler import driver from nova.compute import power_state -from nova.db.sqlalchemy import models FLAGS = flags.FLAGS @@ -250,23 +247,17 @@ class SimpleDriverTestCase(test.TestCase): volume_driver='nova.volume.driver.FakeISCSIDriver', scheduler_driver='nova.scheduler.simple.SimpleScheduler') self.scheduler = manager.SchedulerManager() - self.manager = auth_manager.AuthManager() - self.user = self.manager.create_user('fake', 'fake', 'fake') - self.project = self.manager.create_project('fake', 'fake', 'fake') self.context = context.get_admin_context() - - def tearDown(self): - self.manager.delete_user(self.user) - self.manager.delete_project(self.project) - super(SimpleDriverTestCase, self).tearDown() + self.user_id = 'fake' + self.project_id = 'fake' def _create_instance(self, **kwargs): """Create a test instance""" inst = {} inst['image_id'] = 1 inst['reservation_id'] = 'r-fakeres' - inst['user_id'] = self.user.id - inst['project_id'] = self.project.id + inst['user_id'] = self.user_id + inst['project_id'] = self.project_id inst['instance_type_id'] = '1' inst['vcpus'] = kwargs.get('vcpus', 1) inst['ami_launch_index'] = 0 @@ -485,11 +476,6 @@ class SimpleDriverTestCase(test.TestCase): self.assertEqual(host, 'host2') volume1.delete_volume(self.context, volume_id1) db.volume_destroy(self.context, volume_id2) - dic = {'service_id': s_ref['id'], - 'vcpus': 16, 'memory_mb': 32, 'local_gb': 100, - 'vcpus_used': 16, 'memory_mb_used': 12, 'local_gb_used': 10, - 'hypervisor_type': 'qemu', 'hypervisor_version': 12003, - 'cpu_info': ''} def test_doesnt_report_disabled_hosts_as_up(self): """Ensures driver doesn't find hosts before they are enabled""" diff --git a/nova/tests/scheduler/test_zone_aware_scheduler.py b/nova/tests/scheduler/test_zone_aware_scheduler.py index d74b71fb6..7833028c3 100644 --- a/nova/tests/scheduler/test_zone_aware_scheduler.py +++ b/nova/tests/scheduler/test_zone_aware_scheduler.py @@ -16,6 +16,8 @@ Tests For Zone Aware Scheduler. """ +import json + import nova.db from nova import exception @@ -327,3 +329,19 @@ class ZoneAwareSchedulerTestCase(test.TestCase): sched._provision_resource_from_blob(None, request_spec, 1, request_spec, {}) self.assertTrue(was_called) + + def test_decrypt_blob(self): + """Test that the decrypt method works.""" + + fixture = FakeZoneAwareScheduler() + test_data = {"foo": "bar"} + + class StubDecryptor(object): + def decryptor(self, key): + return lambda blob: blob + + self.stubs.Set(zone_aware_scheduler, 'crypto', + StubDecryptor()) + + self.assertEqual(fixture._decrypt_blob(test_data), + json.dumps(test_data)) diff --git a/nova/tests/test_access.py b/nova/tests/test_access.py index e170ccee6..3b54fc249 100644 --- a/nova/tests/test_access.py +++ b/nova/tests/test_access.py @@ -16,7 +16,6 @@ # License for the specific language governing permissions and limitations # under the License. -import unittest import webob from nova import context @@ -41,7 +40,7 @@ class FakeApiRequest(object): class AccessTestCase(test.TestCase): def _env_for(self, ctxt, action): env = {} - env['ec2.context'] = ctxt + env['nova.context'] = ctxt env['ec2.request'] = FakeApiRequest(action) return env @@ -93,7 +92,11 @@ class AccessTestCase(test.TestCase): super(AccessTestCase, self).tearDown() def response_status(self, user, methodName): - ctxt = context.RequestContext(user, self.project) + roles = manager.AuthManager().get_active_roles(user, self.project) + ctxt = context.RequestContext(user.id, + self.project.id, + is_admin=user.is_admin(), + roles=roles) environ = self._env_for(ctxt, methodName) req = webob.Request.blank('/', environ) resp = req.get_response(self.mw) @@ -105,30 +108,26 @@ class AccessTestCase(test.TestCase): def shouldDeny(self, user, methodName): self.assertEqual(401, self.response_status(user, methodName)) - def test_001_allow_all(self): + def test_allow_all(self): users = [self.testadmin, self.testpmsys, self.testnet, self.testsys] for user in users: self.shouldAllow(user, '_allow_all') - def test_002_allow_none(self): + def test_allow_none(self): self.shouldAllow(self.testadmin, '_allow_none') users = [self.testpmsys, self.testnet, self.testsys] for user in users: self.shouldDeny(user, '_allow_none') - def test_003_allow_project_manager(self): + def test_allow_project_manager(self): for user in [self.testadmin, self.testpmsys]: self.shouldAllow(user, '_allow_project_manager') for user in [self.testnet, self.testsys]: self.shouldDeny(user, '_allow_project_manager') - def test_004_allow_sys_and_net(self): + def test_allow_sys_and_net(self): for user in [self.testadmin, self.testnet, self.testsys]: self.shouldAllow(user, '_allow_sys_and_net') # denied because it doesn't have the per project sysadmin for user in [self.testpmsys]: self.shouldDeny(user, '_allow_sys_and_net') - -if __name__ == "__main__": - # TODO: Implement use_fake as an option - unittest.main() diff --git a/nova/tests/test_adminapi.py b/nova/tests/test_adminapi.py index 877cf4ea1..06cc498ac 100644 --- a/nova/tests/test_adminapi.py +++ b/nova/tests/test_adminapi.py @@ -25,7 +25,6 @@ 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.api.ec2 import admin from nova.image import fake @@ -39,7 +38,7 @@ class AdminApiTestCase(test.TestCase): super(AdminApiTestCase, self).setUp() self.flags(connection_type='fake') - self.conn = rpc.Connection.instance() + self.conn = rpc.create_connection() # set up our cloud self.api = admin.AdminController() @@ -51,11 +50,11 @@ class AdminApiTestCase(test.TestCase): self.volume = self.start_service('volume') self.image_service = utils.import_object(FLAGS.image_service) - self.manager = manager.AuthManager() - self.user = self.manager.create_user('admin', 'admin', 'admin', True) - self.project = self.manager.create_project('proj', 'admin', 'proj') - self.context = context.RequestContext(user=self.user, - project=self.project) + self.user_id = 'admin' + self.project_id = 'admin' + self.context = context.RequestContext(self.user_id, + self.project_id, + True) def fake_show(meh, context, id): return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1, @@ -73,11 +72,6 @@ class AdminApiTestCase(test.TestCase): self.stubs.Set(rpc, 'cast', finish_cast) - def tearDown(self): - self.manager.delete_project(self.project) - self.manager.delete_user(self.user) - super(AdminApiTestCase, self).tearDown() - def test_block_external_ips(self): """Make sure provider firewall rules are created.""" result = self.api.block_external_addresses(self.context, '1.1.1.1/32') diff --git a/nova/tests/test_api.py b/nova/tests/test_api.py index e3d2ee2fc..13edcb10d 100644 --- a/nova/tests/test_api.py +++ b/nova/tests/test_api.py @@ -31,11 +31,11 @@ from nova import block_device from nova import context from nova import exception from nova import test +from nova import wsgi from nova.api import ec2 from nova.api.ec2 import apirequest from nova.api.ec2 import cloud from nova.api.ec2 import ec2utils -from nova.auth import manager class FakeHttplibSocket(object): @@ -195,10 +195,13 @@ class ApiEc2TestCase(test.TestCase): """Unit test for the cloud controller on an EC2 API""" def setUp(self): super(ApiEc2TestCase, self).setUp() - self.manager = manager.AuthManager() self.host = '127.0.0.1' - self.app = ec2.Authenticate(ec2.Requestify(ec2.Executor(), - 'nova.api.ec2.cloud.CloudController')) + # NOTE(vish): skipping the Authorizer + roles = ['sysadmin', 'netadmin'] + ctxt = context.RequestContext('fake', 'fake', roles=roles) + self.app = wsgi.InjectContext(ctxt, + ec2.Requestify(ec2.Authorizer(ec2.Executor()), + 'nova.api.ec2.cloud.CloudController')) def expect_http(self, host=None, is_secure=False, api_version=None): """Returns a new EC2 connection""" @@ -216,7 +219,11 @@ class ApiEc2TestCase(test.TestCase): self.http = FakeHttplibConnection( self.app, '%s:8773' % (self.host), False) # pylint: disable=E1103 - self.ec2.new_http_connection(host, is_secure).AndReturn(self.http) + if boto.Version >= '2': + self.ec2.new_http_connection(host or '%s:8773' % (self.host), + is_secure).AndReturn(self.http) + else: + self.ec2.new_http_connection(host, is_secure).AndReturn(self.http) return self.http def test_return_valid_isoformat(self): @@ -245,39 +252,25 @@ class ApiEc2TestCase(test.TestCase): self.expect_http(api_version='2010-10-30') self.mox.ReplayAll() - user = self.manager.create_user('fake', 'fake', 'fake') - project = self.manager.create_project('fake', 'fake', 'fake') - # Any request should be fine self.ec2.get_all_instances() self.assertTrue(self.ec2.APIVersion in self.http.getresponsebody(), 'The version in the xmlns of the response does ' 'not match the API version given in the request.') - self.manager.delete_project(project) - self.manager.delete_user(user) - def test_describe_instances(self): """Test that, after creating a user and a project, the describe instances call to the API works properly""" self.expect_http() self.mox.ReplayAll() - user = self.manager.create_user('fake', 'fake', 'fake') - project = self.manager.create_project('fake', 'fake', 'fake') self.assertEqual(self.ec2.get_all_instances(), []) - self.manager.delete_project(project) - self.manager.delete_user(user) def test_terminate_invalid_instance(self): """Attempt to terminate an invalid instance""" self.expect_http() self.mox.ReplayAll() - user = self.manager.create_user('fake', 'fake', 'fake') - project = self.manager.create_project('fake', 'fake', 'fake') self.assertRaises(EC2ResponseError, self.ec2.terminate_instances, "i-00000005") - self.manager.delete_project(project) - self.manager.delete_user(user) def test_get_all_key_pairs(self): """Test that, after creating a user and project and generating @@ -286,16 +279,12 @@ class ApiEc2TestCase(test.TestCase): self.mox.ReplayAll() keyname = "".join(random.choice("sdiuisudfsdcnpaqwertasd") \ for x in range(random.randint(4, 8))) - user = self.manager.create_user('fake', 'fake', 'fake') - project = self.manager.create_project('fake', 'fake', 'fake') # NOTE(vish): create depends on pool, so call helper directly - cloud._gen_key(context.get_admin_context(), user.id, keyname) + cloud._gen_key(context.get_admin_context(), 'fake', keyname) rv = self.ec2.get_all_key_pairs() results = [k for k in rv if k.name == keyname] self.assertEquals(len(results), 1) - self.manager.delete_project(project) - self.manager.delete_user(user) def test_create_duplicate_key_pair(self): """Test that, after successfully generating a keypair, @@ -304,8 +293,6 @@ class ApiEc2TestCase(test.TestCase): self.mox.ReplayAll() keyname = "".join(random.choice("sdiuisudfsdcnpaqwertasd") \ for x in range(random.randint(4, 8))) - user = self.manager.create_user('fake', 'fake', 'fake') - project = self.manager.create_project('fake', 'fake', 'fake') # NOTE(vish): create depends on pool, so call helper directly self.ec2.create_key_pair('test') @@ -324,27 +311,16 @@ class ApiEc2TestCase(test.TestCase): """Test that we can retrieve security groups""" self.expect_http() self.mox.ReplayAll() - user = self.manager.create_user('fake', 'fake', 'fake', admin=True) - project = self.manager.create_project('fake', 'fake', 'fake') rv = self.ec2.get_all_security_groups() self.assertEquals(len(rv), 1) self.assertEquals(rv[0].name, 'default') - self.manager.delete_project(project) - self.manager.delete_user(user) - def test_create_delete_security_group(self): """Test that we can create a security group""" self.expect_http() self.mox.ReplayAll() - user = self.manager.create_user('fake', 'fake', 'fake', admin=True) - project = self.manager.create_project('fake', 'fake', 'fake') - - # At the moment, you need both of these to actually be netadmin - self.manager.add_role('fake', 'netadmin') - project.add_role('fake', 'netadmin') security_group_name = "".join(random.choice("sdiuisudfsdcnpaqwertasd") for x in range(random.randint(4, 8))) @@ -363,9 +339,6 @@ class ApiEc2TestCase(test.TestCase): self.ec2.delete_security_group(security_group_name) - self.manager.delete_project(project) - self.manager.delete_user(user) - def test_authorize_revoke_security_group_cidr(self): """ Test that we can add and remove CIDR based rules @@ -373,12 +346,6 @@ class ApiEc2TestCase(test.TestCase): """ self.expect_http() self.mox.ReplayAll() - user = self.manager.create_user('fake', 'fake', 'fake') - project = self.manager.create_project('fake', 'fake', 'fake') - - # At the moment, you need both of these to actually be netadmin - self.manager.add_role('fake', 'netadmin') - project.add_role('fake', 'netadmin') security_group_name = "".join(random.choice("sdiuisudfsdcnpaqwertasd") for x in range(random.randint(4, 8))) @@ -425,9 +392,6 @@ class ApiEc2TestCase(test.TestCase): self.assertEqual(len(rv), 1) self.assertEqual(rv[0].name, 'default') - self.manager.delete_project(project) - self.manager.delete_user(user) - return def test_authorize_revoke_security_group_cidr_v6(self): @@ -437,12 +401,6 @@ class ApiEc2TestCase(test.TestCase): """ self.expect_http() self.mox.ReplayAll() - user = self.manager.create_user('fake', 'fake', 'fake') - project = self.manager.create_project('fake', 'fake', 'fake') - - # At the moment, you need both of these to actually be netadmin - self.manager.add_role('fake', 'netadmin') - project.add_role('fake', 'netadmin') security_group_name = "".join(random.choice("sdiuisudfsdcnpaqwertasd") for x in range(random.randint(4, 8))) @@ -488,9 +446,6 @@ class ApiEc2TestCase(test.TestCase): self.assertEqual(len(rv), 1) self.assertEqual(rv[0].name, 'default') - self.manager.delete_project(project) - self.manager.delete_user(user) - return def test_authorize_revoke_security_group_foreign_group(self): @@ -500,12 +455,6 @@ class ApiEc2TestCase(test.TestCase): """ self.expect_http() self.mox.ReplayAll() - user = self.manager.create_user('fake', 'fake', 'fake', admin=True) - project = self.manager.create_project('fake', 'fake', 'fake') - - # At the moment, you need both of these to actually be netadmin - self.manager.add_role('fake', 'netadmin') - project.add_role('fake', 'netadmin') rand_string = 'sdiuisudfsdcnpaqwertasd' security_group_name = "".join(random.choice(rand_string) @@ -559,8 +508,3 @@ class ApiEc2TestCase(test.TestCase): self.mox.ReplayAll() self.ec2.delete_security_group(security_group_name) - - self.manager.delete_project(project) - self.manager.delete_user(user) - - return diff --git a/nova/tests/test_auth.py b/nova/tests/test_auth.py index 71e0d17c9..7c0f783bb 100644 --- a/nova/tests/test_auth.py +++ b/nova/tests/test_auth.py @@ -102,7 +102,7 @@ class _AuthManagerBaseTestCase(test.TestCase): self.assertEqual('classified', u.secret) self.assertEqual('private-party', u.access) - def test_004_signature_is_valid(self): + def test_signature_is_valid(self): with user_generator(self.manager, name='admin', secret='admin', access='admin'): with project_generator(self.manager, name="admin", @@ -141,15 +141,14 @@ class _AuthManagerBaseTestCase(test.TestCase): '127.0.0.1', '/services/Cloud')) - def test_005_can_get_credentials(self): - return - credentials = self.manager.get_user('test1').get_credentials() - self.assertEqual(credentials, - 'export EC2_ACCESS_KEY="access"\n' + - 'export EC2_SECRET_KEY="secret"\n' + - 'export EC2_URL="http://127.0.0.1:8773/services/Cloud"\n' + - 'export S3_URL="http://127.0.0.1:3333/"\n' + - 'export EC2_USER_ID="test1"\n') + def test_can_get_credentials(self): + st = {'access': 'access', 'secret': 'secret'} + with user_and_project_generator(self.manager, user_state=st) as (u, p): + credentials = self.manager.get_environment_rc(u, p) + LOG.debug(credentials) + self.assertTrue('export EC2_ACCESS_KEY="access:testproj"\n' + in credentials) + self.assertTrue('export EC2_SECRET_KEY="secret"\n' in credentials) def test_can_list_users(self): with user_generator(self.manager): diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index ac959bd63..a2c8cafc0 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -36,7 +36,6 @@ from nova import network from nova import rpc from nova import test 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 fake @@ -52,7 +51,7 @@ class CloudTestCase(test.TestCase): self.flags(connection_type='fake', stub_network=True) - self.conn = rpc.Connection.instance() + self.conn = rpc.create_connection() # set up our cloud self.cloud = cloud.CloudController() @@ -64,12 +63,11 @@ class CloudTestCase(test.TestCase): self.volume = self.start_service('volume') self.image_service = utils.import_object(FLAGS.image_service) - self.manager = manager.AuthManager() - self.user = self.manager.create_user('admin', 'admin', 'admin', True) - self.project = self.manager.create_project('proj', 'admin', 'proj') - self.context = context.RequestContext(user=self.user, - project=self.project) - host = self.network.host + self.user_id = 'fake' + self.project_id = 'fake' + self.context = context.RequestContext(self.user_id, + self.project_id, + True) def fake_show(meh, context, id): return {'id': 1, 'container_format': 'ami', @@ -89,17 +87,15 @@ class CloudTestCase(test.TestCase): self.stubs.Set(rpc, 'cast', finish_cast) def tearDown(self): - networks = db.project_get_networks(self.context, self.project.id, + networks = db.project_get_networks(self.context, self.project_id, associate=False) for network in networks: db.network_disassociate(self.context, network['id']) - self.manager.delete_project(self.project) - self.manager.delete_user(self.user) super(CloudTestCase, self).tearDown() def _create_key(self, name): # NOTE(vish): create depends on pool, so just call helper directly - return cloud._gen_key(self.context, self.context.user.id, name) + return cloud._gen_key(self.context, self.context.user_id, name) def test_describe_regions(self): """Makes sure describe regions runs without raising an exception""" @@ -123,7 +119,6 @@ class CloudTestCase(test.TestCase): public_ip=address) db.floating_ip_destroy(self.context, address) - @test.skip_test("Skipping this pending future merge") def test_allocate_address(self): address = "10.10.10.10" allocate = self.cloud.allocate_address @@ -163,13 +158,10 @@ class CloudTestCase(test.TestCase): # ApiError: Floating ip is in use. Disassociate it before releasing. self.assertRaises(exception.ApiError, release, self.context, address) - @test.skip_test("Skipping this pending future merge") def test_associate_disassociate_address(self): """Verifies associate runs cleanly without raising an exception""" address = "10.10.10.10" - db.floating_ip_create(self.context, - {'address': address, - 'host': self.network.host}) + db.floating_ip_create(self.context, {'address': address}) self.cloud.allocate_address(self.context) # TODO(jkoelker) Probably need to query for instance_type_id and # make sure we get a valid one @@ -177,11 +169,14 @@ class CloudTestCase(test.TestCase): 'instance_type_id': 1}) networks = db.network_get_all(self.context) for network in networks: - self.network.set_network_host(self.context, network['id']) + db.network_update(self.context, network['id'], + {'host': self.network.host}) project_id = self.context.project_id type_id = inst['instance_type_id'] ips = self.network.allocate_for_instance(self.context, instance_id=inst['id'], + host=inst['host'], + vpn=None, instance_type_id=type_id, project_id=project_id) # TODO(jkoelker) Make this mas bueno @@ -271,12 +266,61 @@ class CloudTestCase(test.TestCase): delete = self.cloud.delete_security_group self.assertRaises(exception.ApiError, delete, self.context) - def test_authorize_revoke_security_group_ingress(self): + def test_authorize_security_group_ingress(self): kwargs = {'project_id': self.context.project_id, 'name': 'test'} sec = db.security_group_create(self.context, kwargs) authz = self.cloud.authorize_security_group_ingress kwargs = {'to_port': '999', 'from_port': '999', 'ip_protocol': 'tcp'} - authz(self.context, group_name=sec['name'], **kwargs) + self.assertTrue(authz(self.context, group_name=sec['name'], **kwargs)) + + def test_authorize_security_group_ingress_ip_permissions_ip_ranges(self): + kwargs = {'project_id': self.context.project_id, 'name': 'test'} + sec = db.security_group_create(self.context, kwargs) + authz = self.cloud.authorize_security_group_ingress + kwargs = {'ip_permissions': [{'to_port': 81, 'from_port': 81, + 'ip_ranges': + {'1': {'cidr_ip': u'0.0.0.0/0'}, + '2': {'cidr_ip': u'10.10.10.10/32'}}, + 'ip_protocol': u'tcp'}]} + self.assertTrue(authz(self.context, group_name=sec['name'], **kwargs)) + + def test_authorize_security_group_fail_missing_source_group(self): + kwargs = {'project_id': self.context.project_id, 'name': 'test'} + sec = db.security_group_create(self.context, kwargs) + authz = self.cloud.authorize_security_group_ingress + kwargs = {'ip_permissions': [{'to_port': 81, 'from_port': 81, + 'ip_ranges':{'1': {'cidr_ip': u'0.0.0.0/0'}, + '2': {'cidr_ip': u'10.10.10.10/32'}}, + 'groups': {'1': {'user_id': u'someuser', + 'group_name': u'somegroup1'}}, + 'ip_protocol': u'tcp'}]} + self.assertRaises(exception.SecurityGroupNotFound, authz, + self.context, group_name=sec['name'], **kwargs) + + def test_authorize_security_group_ingress_ip_permissions_groups(self): + kwargs = {'project_id': self.context.project_id, 'name': 'test'} + sec = db.security_group_create(self.context, + {'project_id': 'someuser', + 'name': 'somegroup1'}) + sec = db.security_group_create(self.context, + {'project_id': 'someuser', + 'name': 'othergroup2'}) + sec = db.security_group_create(self.context, kwargs) + authz = self.cloud.authorize_security_group_ingress + kwargs = {'ip_permissions': [{'to_port': 81, 'from_port': 81, + 'groups': {'1': {'user_id': u'someuser', + 'group_name': u'somegroup1'}, + '2': {'user_id': u'someuser', + 'group_name': u'othergroup2'}}, + 'ip_protocol': u'tcp'}]} + self.assertTrue(authz(self.context, group_name=sec['name'], **kwargs)) + + def test_revoke_security_group_ingress(self): + kwargs = {'project_id': self.context.project_id, 'name': 'test'} + sec = db.security_group_create(self.context, kwargs) + authz = self.cloud.authorize_security_group_ingress + kwargs = {'to_port': '999', 'from_port': '999', 'ip_protocol': 'tcp'} + authz(self.context, group_id=sec['id'], **kwargs) revoke = self.cloud.revoke_security_group_ingress self.assertTrue(revoke(self.context, group_name=sec['name'], **kwargs)) @@ -368,8 +412,6 @@ class CloudTestCase(test.TestCase): db.service_destroy(self.context, service1['id']) db.service_destroy(self.context, service2['id']) - # NOTE(jkoelker): this test relies on fixed_ip being in instances - @test.skip_test("EC2 stuff needs fixed_ip in instance_ref") def test_describe_snapshots(self): """Makes sure describe_snapshots works and filters results.""" vol = db.volume_create(self.context, {}) @@ -941,7 +983,7 @@ class CloudTestCase(test.TestCase): key = RSA.load_key_string(private_key, callback=lambda: None) bio = BIO.MemoryBuffer() public_key = db.key_pair_get(self.context, - self.context.user.id, + self.context.user_id, 'test')['public_key'] key.save_pub_key_bio(bio) converted = crypto.ssl_pub_to_ssh_pub(bio.read()) @@ -965,7 +1007,7 @@ class CloudTestCase(test.TestCase): 'mytestfprint') self.assertTrue(result1) keydata = db.key_pair_get(self.context, - self.context.user.id, + self.context.user_id, 'testimportkey1') self.assertEqual('mytestpubkey', keydata['public_key']) self.assertEqual('mytestfprint', keydata['fingerprint']) @@ -982,7 +1024,7 @@ class CloudTestCase(test.TestCase): dummypub) self.assertTrue(result2) keydata = db.key_pair_get(self.context, - self.context.user.id, + self.context.user_id, 'testimportkey2') self.assertEqual(dummypub, keydata['public_key']) self.assertEqual(dummyfprint, keydata['fingerprint']) @@ -992,12 +1034,6 @@ 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} @@ -1007,7 +1043,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'], 'scheduling') + self.assertEqual(instance['instanceState']['name'], 'running') self.assertEqual(instance['instanceType'], 'm1.small') def test_run_instances_image_state_none(self): @@ -1079,16 +1115,15 @@ class CloudTestCase(test.TestCase): self.assertEqual('c00l 1m4g3', inst['display_name']) db.instance_destroy(self.context, inst['id']) - # NOTE(jkoelker): This test relies on mac_address in instance - @test.skip_test("EC2 stuff needs mac_address in instance_ref") def test_update_of_instance_wont_update_private_fields(self): inst = db.instance_create(self.context, {}) + host = inst['host'] 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') + host='otherhost') inst = db.instance_get(self.context, inst['id']) - self.assertEqual(None, inst['mac_address']) + self.assertEqual(host, inst['host']) db.instance_destroy(self.context, inst['id']) def test_update_of_volume_display_fields(self): @@ -1144,7 +1179,6 @@ class CloudTestCase(test.TestCase): elevated = self.context.elevated(read_deleted=True) self._wait_for_state(elevated, instance_id, is_deleted) - @test.skip_test("skipping, test is hanging with multinic for rpc reasons") def test_stop_start_instance(self): """Makes sure stop/start instance works""" # enforce periodic tasks run in short time to avoid wait for 60s. @@ -1202,7 +1236,6 @@ class CloudTestCase(test.TestCase): self.assertEqual(vol['status'], "available") self.assertEqual(vol['attach_status'], "detached") - @test.skip_test("skipping, test is hanging with multinic for rpc reasons") def test_stop_start_with_volume(self): """Make sure run instance with block device mapping works""" @@ -1271,7 +1304,6 @@ class CloudTestCase(test.TestCase): self._restart_compute_service() - @test.skip_test("skipping, test is hanging with multinic for rpc reasons") 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. @@ -1347,7 +1379,6 @@ class CloudTestCase(test.TestCase): greenthread.sleep(0.3) return result['snapshotId'] - @test.skip_test("skipping, test is hanging with multinic for rpc reasons") def test_run_with_snapshot(self): """Makes sure run/stop/start instance with snapshot works.""" vol = self._volume_create() diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 32f55c6e2..24cfbd511 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -19,10 +19,6 @@ 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 @@ -67,10 +63,9 @@ class ComputeTestCase(test.TestCase): network_manager='nova.network.manager.FlatManager') self.compute = utils.import_object(FLAGS.compute_manager) self.compute_api = compute.API() - self.manager = manager.AuthManager() - self.user = self.manager.create_user('fake', 'fake', 'fake') - self.project = self.manager.create_project('fake', 'fake', 'fake') - self.context = context.RequestContext('fake', 'fake', False) + self.user_id = 'fake' + self.project_id = 'fake' + self.context = context.RequestContext(self.user_id, self.project_id) test_notifier.NOTIFICATIONS = [] def fake_show(meh, context, id): @@ -78,19 +73,14 @@ class ComputeTestCase(test.TestCase): self.stubs.Set(nova.image.fake._FakeImageService, 'show', fake_show) - def tearDown(self): - self.manager.delete_user(self.user) - self.manager.delete_project(self.project) - super(ComputeTestCase, self).tearDown() - def _create_instance(self, params={}): """Create a test instance""" inst = {} inst['image_ref'] = 1 inst['reservation_id'] = 'r-fakeres' inst['launch_time'] = '10' - inst['user_id'] = self.user.id - inst['project_id'] = self.project.id + inst['user_id'] = self.user_id + inst['project_id'] = self.project_id type_id = instance_types.get_instance_type_by_name('m1.tiny')['id'] inst['instance_type_id'] = type_id inst['ami_launch_index'] = 0 @@ -115,8 +105,8 @@ class ComputeTestCase(test.TestCase): def _create_group(self): values = {'name': 'testgroup', 'description': 'testgroup', - 'user_id': self.user.id, - 'project_id': self.project.id} + 'user_id': self.user_id, + 'project_id': self.project_id} return db.security_group_create(self.context, values) def _get_dummy_instance(self): @@ -350,8 +340,8 @@ class ComputeTestCase(test.TestCase): self.assertEquals(msg['priority'], 'INFO') self.assertEquals(msg['event_type'], 'compute.instance.create') payload = msg['payload'] - self.assertEquals(payload['tenant_id'], self.project.id) - self.assertEquals(payload['user_id'], self.user.id) + self.assertEquals(payload['tenant_id'], self.project_id) + self.assertEquals(payload['user_id'], self.user_id) self.assertEquals(payload['instance_id'], instance_id) self.assertEquals(payload['instance_type'], 'm1.tiny') type_id = instance_types.get_instance_type_by_name('m1.tiny')['id'] @@ -374,8 +364,8 @@ class ComputeTestCase(test.TestCase): self.assertEquals(msg['priority'], 'INFO') self.assertEquals(msg['event_type'], 'compute.instance.delete') payload = msg['payload'] - self.assertEquals(payload['tenant_id'], self.project.id) - self.assertEquals(payload['user_id'], self.user.id) + self.assertEquals(payload['tenant_id'], self.project_id) + self.assertEquals(payload['user_id'], self.user_id) self.assertEquals(payload['instance_id'], instance_id) self.assertEquals(payload['instance_type'], 'm1.tiny') type_id = instance_types.get_instance_type_by_name('m1.tiny')['id'] @@ -420,7 +410,7 @@ class ComputeTestCase(test.TestCase): def fake(*args, **kwargs): pass - self.stubs.Set(self.compute.driver, 'finish_resize', fake) + self.stubs.Set(self.compute.driver, 'finish_migration', fake) self.stubs.Set(self.compute.network_api, 'get_instance_nw_info', fake) context = self.context.elevated() instance_id = self._create_instance() @@ -457,8 +447,8 @@ class ComputeTestCase(test.TestCase): self.assertEquals(msg['priority'], 'INFO') self.assertEquals(msg['event_type'], 'compute.instance.resize.prep') payload = msg['payload'] - self.assertEquals(payload['tenant_id'], self.project.id) - self.assertEquals(payload['user_id'], self.user.id) + self.assertEquals(payload['tenant_id'], self.project_id) + self.assertEquals(payload['user_id'], self.user_id) self.assertEquals(payload['instance_id'], instance_id) self.assertEquals(payload['instance_type'], 'm1.tiny') type_id = instance_types.get_instance_type_by_name('m1.tiny')['id'] @@ -531,8 +521,8 @@ class ComputeTestCase(test.TestCase): def fake(*args, **kwargs): pass - self.stubs.Set(self.compute.driver, 'finish_resize', fake) - self.stubs.Set(self.compute.driver, 'revert_resize', fake) + self.stubs.Set(self.compute.driver, 'finish_migration', fake) + self.stubs.Set(self.compute.driver, 'revert_migration', fake) self.stubs.Set(self.compute.network_api, 'get_instance_nw_info', fake) self.compute.run_instance(self.context, instance_id) @@ -583,8 +573,9 @@ class ComputeTestCase(test.TestCase): the same host""" instance_id = self._create_instance() self.compute.run_instance(self.context, instance_id) + inst_ref = db.instance_get(self.context, instance_id) self.assertRaises(exception.Error, self.compute.prep_resize, - self.context, instance_id, 1) + self.context, inst_ref['uuid'], 1) self.compute.terminate_instance(self.context, instance_id) def test_migrate(self): @@ -624,7 +615,6 @@ class ComputeTestCase(test.TestCase): self._setup_other_managers() dbmock = self.mox.CreateMock(db) volmock = self.mox.CreateMock(self.volume_manager) - netmock = self.mox.CreateMock(self.network_manager) drivermock = self.mox.CreateMock(self.compute_driver) dbmock.instance_get(c, i_ref['id']).AndReturn(i_ref) @@ -632,12 +622,11 @@ class ComputeTestCase(test.TestCase): for i in range(len(i_ref['volumes'])): vid = i_ref['volumes'][i]['id'] volmock.setup_compute_volume(c, vid).InAnyOrder('g1') - netmock.setup_compute_network(c, i_ref['id']) + drivermock.plug_vifs(i_ref, []) drivermock.ensure_filtering_rules_for_instance(i_ref) self.compute.db = dbmock self.compute.volume_manager = volmock - self.compute.network_manager = netmock self.compute.driver = drivermock self.mox.ReplayAll() @@ -652,18 +641,16 @@ class ComputeTestCase(test.TestCase): self._setup_other_managers() dbmock = self.mox.CreateMock(db) - netmock = self.mox.CreateMock(self.network_manager) drivermock = self.mox.CreateMock(self.compute_driver) dbmock.instance_get(c, i_ref['id']).AndReturn(i_ref) dbmock.instance_get_fixed_addresses(c, i_ref['id']).AndReturn('dummy') self.mox.StubOutWithMock(compute_manager.LOG, 'info') compute_manager.LOG.info(_("%s has no volume."), i_ref['hostname']) - netmock.setup_compute_network(c, i_ref['id']) + drivermock.plug_vifs(i_ref, []) drivermock.ensure_filtering_rules_for_instance(i_ref) self.compute.db = dbmock - self.compute.network_manager = netmock self.compute.driver = drivermock self.mox.ReplayAll() @@ -684,18 +671,20 @@ class ComputeTestCase(test.TestCase): dbmock = self.mox.CreateMock(db) netmock = self.mox.CreateMock(self.network_manager) volmock = self.mox.CreateMock(self.volume_manager) + drivermock = self.mox.CreateMock(self.compute_driver) dbmock.instance_get(c, i_ref['id']).AndReturn(i_ref) dbmock.instance_get_fixed_addresses(c, i_ref['id']).AndReturn('dummy') for i in range(len(i_ref['volumes'])): volmock.setup_compute_volume(c, i_ref['volumes'][i]['id']) for i in range(FLAGS.live_migration_retry_count): - netmock.setup_compute_network(c, i_ref['id']).\ + drivermock.plug_vifs(i_ref, []).\ AndRaise(exception.ProcessExecutionError()) self.compute.db = dbmock self.compute.network_manager = netmock self.compute.volume_manager = volmock + self.compute.driver = drivermock self.mox.ReplayAll() self.assertRaises(exception.ProcessExecutionError, @@ -830,7 +819,7 @@ class ComputeTestCase(test.TestCase): for v in i_ref['volumes']: self.compute.volume_manager.remove_compute_volume(c, v['id']) self.mox.StubOutWithMock(self.compute.driver, 'unfilter_instance') - self.compute.driver.unfilter_instance(i_ref) + self.compute.driver.unfilter_instance(i_ref, []) # executing self.mox.ReplayAll() @@ -850,7 +839,6 @@ class ComputeTestCase(test.TestCase): def test_run_kill_vm(self): """Detect when a vm is terminated behind the scenes""" - self.stubs = stubout.StubOutForTesting() self.stubs.Set(compute_manager.ComputeManager, '_report_driver_status', nop_report_driver_status) diff --git a/nova/tests/test_console.py b/nova/tests/test_console.py index 1806cc1ea..cf7f592cf 100644 --- a/nova/tests/test_console.py +++ b/nova/tests/test_console.py @@ -26,10 +26,9 @@ from nova import exception from nova import flags from nova import test from nova import utils -from nova.auth import manager -from nova.console import manager as console_manager FLAGS = flags.FLAGS +flags.DECLARE('console_driver', 'nova.console.manager') class ConsoleTestCase(test.TestCase): @@ -39,17 +38,11 @@ class ConsoleTestCase(test.TestCase): self.flags(console_driver='nova.console.fake.FakeConsoleProxy', stub_compute=True) self.console = utils.import_object(FLAGS.console_manager) - self.manager = manager.AuthManager() - self.user = self.manager.create_user('fake', 'fake', 'fake') - self.project = self.manager.create_project('fake', 'fake', 'fake') - self.context = context.get_admin_context() + self.user_id = 'fake' + self.project_id = 'fake' + self.context = context.RequestContext(self.user_id, self.project_id) self.host = 'test_compute_host' - def tearDown(self): - self.manager.delete_user(self.user) - self.manager.delete_project(self.project) - super(ConsoleTestCase, self).tearDown() - def _create_instance(self): """Create a test instance""" inst = {} @@ -58,8 +51,8 @@ class ConsoleTestCase(test.TestCase): inst['image_id'] = 1 inst['reservation_id'] = 'r-fakeres' inst['launch_time'] = '10' - inst['user_id'] = self.user.id - inst['project_id'] = self.project.id + inst['user_id'] = self.user_id + inst['project_id'] = self.project_id inst['instance_type_id'] = 1 inst['ami_launch_index'] = 0 return db.instance_create(self.context, inst)['id'] diff --git a/nova/tests/test_db_api.py b/nova/tests/test_db_api.py new file mode 100644 index 000000000..54448f9d6 --- /dev/null +++ b/nova/tests/test_db_api.py @@ -0,0 +1,78 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# 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. + +"""Unit tests for the DB API""" + +from nova import test +from nova import context +from nova import db +from nova import flags + +FLAGS = flags.FLAGS + + +def _setup_networking(instance_id, ip='1.2.3.4', flo_addr='1.2.1.2'): + ctxt = context.get_admin_context() + network_ref = db.project_get_networks(ctxt, + 'fake', + associate=True)[0] + vif = {'address': '56:12:12:12:12:12', + 'network_id': network_ref['id'], + 'instance_id': instance_id} + vif_ref = db.virtual_interface_create(ctxt, vif) + + fixed_ip = {'address': ip, + 'network_id': network_ref['id'], + 'virtual_interface_id': vif_ref['id'], + 'allocated': True, + 'instance_id': instance_id} + db.fixed_ip_create(ctxt, fixed_ip) + fix_ref = db.fixed_ip_get_by_address(ctxt, ip) + db.floating_ip_create(ctxt, {'address': flo_addr, + 'fixed_ip_id': fix_ref['id']}) + + +class DbApiTestCase(test.TestCase): + def setUp(self): + super(DbApiTestCase, self).setUp() + self.user_id = 'fake' + self.project_id = 'fake' + self.context = context.RequestContext(self.user_id, self.project_id) + + def test_instance_get_project_vpn(self): + values = {'instance_type_id': FLAGS.default_instance_type, + 'image_ref': FLAGS.vpn_image_id, + 'project_id': self.project_id + } + instance = db.instance_create(self.context, values) + result = db.instance_get_project_vpn(self.context.elevated(), + self.project_id) + self.assertEqual(instance['id'], result['id']) + + def test_instance_get_project_vpn_joins(self): + values = {'instance_type_id': FLAGS.default_instance_type, + 'image_ref': FLAGS.vpn_image_id, + 'project_id': self.project_id + } + instance = db.instance_create(self.context, values) + _setup_networking(instance['id']) + result = db.instance_get_project_vpn(self.context.elevated(), + self.project_id) + self.assertEqual(instance['id'], result['id']) + self.assertEqual(result['fixed_ips'][0]['floating_ips'][0].address, + '1.2.1.2') diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index 0c198f1b5..156582970 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -32,7 +32,6 @@ from nova import flags from nova import test from nova import utils from nova.api.ec2 import cloud -from nova.auth import manager from nova.compute import power_state from nova.virt.libvirt import connection from nova.virt.libvirt import firewall @@ -54,9 +53,13 @@ def _create_network_info(count=1, ipv6=None): fake_ip = '0.0.0.0/0' fake_ip_2 = '0.0.0.1/0' fake_ip_3 = '0.0.0.1/0' + fake_vlan = 100 + fake_bridge_interface = 'eth0' network = {'bridge': fake, 'cidr': fake_ip, - 'cidr_v6': fake_ip} + 'cidr_v6': fake_ip, + 'vlan': fake_vlan, + 'bridge_interface': fake_bridge_interface} mapping = {'mac': fake, 'dhcp_server': fake, 'gateway': fake, @@ -84,7 +87,7 @@ def _setup_networking(instance_id, ip='1.2.3.4'): 'virtual_interface_id': vif_ref['id']} db.fixed_ip_create(ctxt, fixed_ip) db.fixed_ip_update(ctxt, ip, {'allocated': True, - 'instance_id': instance_id}) + 'instance_id': instance_id}) class CacheConcurrencyTestCase(test.TestCase): @@ -150,36 +153,15 @@ class LibvirtConnTestCase(test.TestCase): super(LibvirtConnTestCase, self).setUp() connection._late_load_cheetah() self.flags(fake_call=True) - self.manager = manager.AuthManager() - - try: - pjs = self.manager.get_projects() - pjs = [p for p in pjs if p.name == 'fake'] - if 0 != len(pjs): - self.manager.delete_project(pjs[0]) - - users = self.manager.get_users() - users = [u for u in users if u.name == 'fake'] - if 0 != len(users): - self.manager.delete_user(users[0]) - except Exception, e: - pass - - users = self.manager.get_users() - self.user = self.manager.create_user('fake', 'fake', 'fake', - admin=True) - self.project = self.manager.create_project('fake', 'fake', 'fake') + self.user_id = 'fake' + self.project_id = 'fake' + self.context = context.RequestContext(self.user_id, self.project_id) self.network = utils.import_object(FLAGS.network_manager) self.context = context.get_admin_context() FLAGS.instances_path = '' self.call_libvirt_dependant_setup = False + self.test_ip = '10.11.12.13' - def tearDown(self): - self.manager.delete_project(self.project) - self.manager.delete_user(self.user) - super(LibvirtConnTestCase, self).tearDown() - - test_ip = '10.11.12.13' test_instance = {'memory_kb': '1024000', 'basepath': '/some/path', 'bridge_name': 'br100', @@ -220,9 +202,29 @@ class LibvirtConnTestCase(test.TestCase): def setattr(self, key, val): self.__setattr__(key, val) + # A fake VIF driver + class FakeVIFDriver(object): + + def __init__(self, **kwargs): + pass + + def setattr(self, key, val): + self.__setattr__(key, val) + + def plug(self, instance, network, mapping): + return { + 'id': 'fake', + 'bridge_name': 'fake', + 'mac_address': 'fake', + 'ip_address': 'fake', + 'dhcp_server': 'fake', + 'extra_params': 'fake', + } + # Creating mocks fake = FakeLibvirtConnection() fakeip = FakeIptablesFirewallDriver + fakevif = FakeVIFDriver() # Customizing above fake if necessary for key, val in kwargs.items(): fake.__setattr__(key, val) @@ -230,6 +232,8 @@ class LibvirtConnTestCase(test.TestCase): # Inevitable mocks for connection.LibvirtConnection self.mox.StubOutWithMock(connection.utils, 'import_class') connection.utils.import_class(mox.IgnoreArg()).AndReturn(fakeip) + self.mox.StubOutWithMock(connection.utils, 'import_object') + connection.utils.import_object(mox.IgnoreArg()).AndReturn(fakevif) self.mox.StubOutWithMock(connection.LibvirtConnection, '_conn') connection.LibvirtConnection._conn = fake @@ -265,7 +269,6 @@ class LibvirtConnTestCase(test.TestCase): return db.service_create(context.get_admin_context(), service_ref) - @test.skip_test("Please review this test to ensure intent") def test_preparing_xml_info(self): conn = connection.LibvirtConnection(True) instance_ref = db.instance_create(self.context, self.test_instance) @@ -281,43 +284,23 @@ class LibvirtConnTestCase(test.TestCase): _create_network_info(2)) self.assertTrue(len(result['nics']) == 2) - def test_get_nic_for_xml_v4(self): - conn = connection.LibvirtConnection(True) - network, mapping = _create_network_info()[0] - self.flags(use_ipv6=False) - params = conn._get_nic_for_xml(network, mapping)['extra_params'] - self.assertTrue(params.find('PROJNETV6') == -1) - self.assertTrue(params.find('PROJMASKV6') == -1) - - def test_get_nic_for_xml_v6(self): - conn = connection.LibvirtConnection(True) - network, mapping = _create_network_info()[0] - self.flags(use_ipv6=True) - params = conn._get_nic_for_xml(network, mapping)['extra_params'] - self.assertTrue(params.find('PROJNETV6') > -1) - self.assertTrue(params.find('PROJMASKV6') > -1) - - @test.skip_test("skipping libvirt tests depends on get_network_info shim") def test_xml_and_uri_no_ramdisk_no_kernel(self): instance_data = dict(self.test_instance) self._check_xml_and_uri(instance_data, expect_kernel=False, expect_ramdisk=False) - @test.skip_test("skipping libvirt tests depends on get_network_info shim") def test_xml_and_uri_no_ramdisk(self): instance_data = dict(self.test_instance) instance_data['kernel_id'] = 'aki-deadbeef' self._check_xml_and_uri(instance_data, expect_kernel=True, expect_ramdisk=False) - @test.skip_test("skipping libvirt tests depends on get_network_info shim") def test_xml_and_uri_no_kernel(self): instance_data = dict(self.test_instance) instance_data['ramdisk_id'] = 'ari-deadbeef' self._check_xml_and_uri(instance_data, expect_kernel=False, expect_ramdisk=False) - @test.skip_test("skipping libvirt tests depends on get_network_info shim") def test_xml_and_uri(self): instance_data = dict(self.test_instance) instance_data['ramdisk_id'] = 'ari-deadbeef' @@ -325,7 +308,6 @@ class LibvirtConnTestCase(test.TestCase): self._check_xml_and_uri(instance_data, expect_kernel=True, expect_ramdisk=True) - @test.skip_test("skipping libvirt tests depends on get_network_info shim") def test_xml_and_uri_rescue(self): instance_data = dict(self.test_instance) instance_data['ramdisk_id'] = 'ari-deadbeef' @@ -333,7 +315,6 @@ class LibvirtConnTestCase(test.TestCase): self._check_xml_and_uri(instance_data, expect_kernel=True, expect_ramdisk=True, rescue=True) - @test.skip_test("skipping libvirt tests depends on get_network_info shim") def test_lxc_container_and_uri(self): instance_data = dict(self.test_instance) self._check_xml_and_container(instance_data) @@ -413,6 +394,15 @@ class LibvirtConnTestCase(test.TestCase): self.assertEquals(snapshot['status'], 'active') self.assertEquals(snapshot['name'], snapshot_name) + def test_attach_invalid_device(self): + self.create_fake_libvirt_mock() + connection.LibvirtConnection._conn.lookupByName = self.fake_lookup + self.mox.ReplayAll() + conn = connection.LibvirtConnection(False) + self.assertRaises(exception.InvalidDevicePath, + conn.attach_volume, + "fake", "bad/device/path", "/dev/fake") + def test_multi_nic(self): instance_data = dict(self.test_instance) network_info = _create_network_info(2) @@ -430,27 +420,10 @@ class LibvirtConnTestCase(test.TestCase): self.assertEquals(parameters[1].get('value'), 'fake') def _check_xml_and_container(self, instance): - user_context = context.RequestContext(project=self.project, - user=self.user) + user_context = context.RequestContext(self.user_id, + self.project_id) instance_ref = db.instance_create(user_context, instance) - # Re-get the instance so it's bound to an actual session - instance_ref = db.instance_get(user_context, instance_ref['id']) - network_ref = db.project_get_networks(context.get_admin_context(), - self.project.id)[0] - - vif = {'address': '56:12:12:12:12:12', - 'network_id': network_ref['id'], - 'instance_id': instance_ref['id']} - vif_ref = db.virtual_interface_create(self.context, vif) - fixed_ip = {'address': self.test_ip, - 'network_id': network_ref['id'], - 'virtual_interface_id': vif_ref['id']} - - ctxt = context.get_admin_context() - fixed_ip_ref = db.fixed_ip_create(ctxt, fixed_ip) - db.fixed_ip_update(ctxt, self.test_ip, - {'allocated': True, - 'instance_id': instance_ref['id']}) + _setup_networking(instance_ref['id'], self.test_ip) self.flags(libvirt_type='lxc') conn = connection.LibvirtConnection(True) @@ -476,13 +449,12 @@ class LibvirtConnTestCase(test.TestCase): def _check_xml_and_uri(self, instance, expect_ramdisk, expect_kernel, rescue=False): - user_context = context.RequestContext(project=self.project, - user=self.user) + user_context = context.RequestContext(self.user_id, self.project_id) instance_ref = db.instance_create(user_context, instance) network_ref = db.project_get_networks(context.get_admin_context(), - self.project.id)[0] + self.project_id)[0] - _setup_networking(instance_ref['id'], ip=self.test_ip) + _setup_networking(instance_ref['id'], self.test_ip) type_uri_map = {'qemu': ('qemu:///system', [(lambda t: t.find('.').get('type'), 'qemu'), @@ -723,6 +695,9 @@ class LibvirtConnTestCase(test.TestCase): return vdmock self.create_fake_libvirt_mock(lookupByName=fake_lookup) + self.mox.StubOutWithMock(self.compute, "recover_live_migration") + self.compute.recover_live_migration(self.context, instance_ref, + dest='dest') # Start test self.mox.ReplayAll() @@ -741,7 +716,6 @@ class LibvirtConnTestCase(test.TestCase): db.volume_destroy(self.context, volume_ref['id']) db.instance_destroy(self.context, instance_ref['id']) - @test.skip_test("test needs rewrite: instance no longer has mac_address") def test_spawn_with_network_info(self): # Skip if non-libvirt environment if not self.lazy_load_library_exists(): @@ -760,17 +734,7 @@ class LibvirtConnTestCase(test.TestCase): conn.firewall_driver.setattr('setup_basic_filtering', fake_none) conn.firewall_driver.setattr('prepare_instance_filter', fake_none) - network = db.project_get_networks(context.get_admin_context(), - self.project.id)[0] - ip_dict = {'ip': self.test_ip, - 'netmask': network['netmask'], - 'enabled': '1'} - mapping = {'label': network['label'], - 'gateway': network['gateway'], - 'mac': instance['mac_address'], - 'dns': [network['dns']], - 'ips': [ip_dict]} - network_info = [(network, mapping)] + network_info = _create_network_info() try: conn.spawn(instance, network_info) @@ -852,11 +816,9 @@ class IptablesFirewallTestCase(test.TestCase): def setUp(self): super(IptablesFirewallTestCase, self).setUp() - self.manager = manager.AuthManager() - self.user = self.manager.create_user('fake', 'fake', 'fake', - admin=True) - self.project = self.manager.create_project('fake', 'fake', 'fake') - self.context = context.RequestContext('fake', 'fake') + self.user_id = 'fake' + self.project_id = 'fake' + self.context = context.RequestContext(self.user_id, self.project_id) self.network = utils.import_object(FLAGS.network_manager) class FakeLibvirtConnection(object): @@ -864,6 +826,7 @@ class IptablesFirewallTestCase(test.TestCase): """setup_basic_rules in nwfilter calls this.""" pass self.fake_libvirt_connection = FakeLibvirtConnection() + self.test_ip = '10.11.12.13' self.fw = firewall.IptablesFirewallDriver( get_connection=lambda: self.fake_libvirt_connection) @@ -881,11 +844,6 @@ class IptablesFirewallTestCase(test.TestCase): connection.libxml2 = __import__('libxml2') return True - def tearDown(self): - self.manager.delete_project(self.project) - self.manager.delete_user(self.user) - super(IptablesFirewallTestCase, self).tearDown() - in_nat_rules = [ '# Generated by iptables-save v1.4.10 on Sat Feb 19 00:03:19 2011', '*nat', @@ -929,27 +887,11 @@ class IptablesFirewallTestCase(test.TestCase): 'project_id': 'fake', 'instance_type_id': 1}) - @test.skip_test("skipping libvirt tests depends on get_network_info shim") def test_static_filters(self): instance_ref = self._create_instance_ref() - ip = '10.11.12.13' - - network_ref = db.project_get_networks(self.context, - 'fake', - associate=True)[0] - vif = {'address': '56:12:12:12:12:12', - 'network_id': network_ref['id'], - 'instance_id': instance_ref['id']} - vif_ref = db.virtual_interface_create(self.context, vif) - - fixed_ip = {'address': ip, - 'network_id': network_ref['id'], - 'virtual_interface_id': vif_ref['id']} - admin_ctxt = context.get_admin_context() - db.fixed_ip_create(admin_ctxt, fixed_ip) - db.fixed_ip_update(admin_ctxt, ip, {'allocated': True, - 'instance_id': instance_ref['id']}) + _setup_networking(instance_ref['id'], self.test_ip) + admin_ctxt = context.get_admin_context() secgroup = db.security_group_create(admin_ctxt, {'user_id': 'fake', 'project_id': 'fake', @@ -1081,7 +1023,6 @@ class IptablesFirewallTestCase(test.TestCase): self.assertEquals(ipv6_network_rules, ipv6_rules_per_network * networks_count) - @test.skip_test("skipping libvirt tests") def test_do_refresh_security_group_rules(self): instance_ref = self._create_instance_ref() self.mox.StubOutWithMock(self.fw, @@ -1092,7 +1033,6 @@ class IptablesFirewallTestCase(test.TestCase): self.mox.ReplayAll() self.fw.do_refresh_security_group_rules("fake") - @test.skip_test("skip libvirt test project_get_network no longer exists") def test_unfilter_instance_undefines_nwfilter(self): # Skip if non-libvirt environment if not self.lazy_load_library_exists(): @@ -1106,38 +1046,24 @@ class IptablesFirewallTestCase(test.TestCase): self.fw.nwfilter._conn.nwfilterLookupByName =\ fakefilter.nwfilterLookupByName instance_ref = self._create_instance_ref() - inst_id = instance_ref['id'] - instance = db.instance_get(self.context, inst_id) - ip = '10.11.12.13' - network_ref = db.project_get_network(self.context, 'fake') - fixed_ip = {'address': ip, 'network_id': network_ref['id']} - db.fixed_ip_create(admin_ctxt, fixed_ip) - db.fixed_ip_update(admin_ctxt, ip, {'allocated': True, - 'instance_id': inst_id}) - self.fw.setup_basic_filtering(instance) - self.fw.prepare_instance_filter(instance) - self.fw.apply_instance_filter(instance) + _setup_networking(instance_ref['id'], self.test_ip) + self.fw.setup_basic_filtering(instance_ref) + self.fw.prepare_instance_filter(instance_ref) + self.fw.apply_instance_filter(instance_ref) original_filter_count = len(fakefilter.filters) - self.fw.unfilter_instance(instance) + self.fw.unfilter_instance(instance_ref) # should undefine just the instance filter self.assertEqual(original_filter_count - len(fakefilter.filters), 1) db.instance_destroy(admin_ctxt, instance_ref['id']) - @test.skip_test("skip libvirt test project_get_network no longer exists") def test_provider_firewall_rules(self): # setup basic instance data instance_ref = self._create_instance_ref() nw_info = _create_network_info(1) - ip = '10.11.12.13' - network_ref = db.project_get_network(self.context, 'fake') - admin_ctxt = context.get_admin_context() - fixed_ip = {'address': ip, 'network_id': network_ref['id']} - db.fixed_ip_create(admin_ctxt, fixed_ip) - db.fixed_ip_update(admin_ctxt, ip, {'allocated': True, - 'instance_id': instance_ref['id']}) + _setup_networking(instance_ref['id'], self.test_ip) # FRAGILE: peeks at how the firewall names chains chain_name = 'inst-%s' % instance_ref['id'] @@ -1149,6 +1075,7 @@ class IptablesFirewallTestCase(test.TestCase): if rule.chain == 'provider'] self.assertEqual(0, len(rules)) + admin_ctxt = context.get_admin_context() # add a rule and send the update message, check for 1 rule provider_fw0 = db.provider_fw_rule_create(admin_ctxt, {'protocol': 'tcp', @@ -1199,22 +1126,16 @@ class NWFilterTestCase(test.TestCase): class Mock(object): pass - self.manager = manager.AuthManager() - self.user = self.manager.create_user('fake', 'fake', 'fake', - admin=True) - self.project = self.manager.create_project('fake', 'fake', 'fake') - self.context = context.RequestContext(self.user, self.project) + self.user_id = 'fake' + self.project_id = 'fake' + self.context = context.RequestContext(self.user_id, self.project_id) self.fake_libvirt_connection = Mock() + self.test_ip = '10.11.12.13' self.fw = firewall.NWFilterFirewall( lambda: self.fake_libvirt_connection) - def tearDown(self): - self.manager.delete_project(self.project) - self.manager.delete_user(self.user) - super(NWFilterTestCase, self).tearDown() - def test_cidr_rule_nwfilter_xml(self): cloud_controller = cloud.CloudController() cloud_controller.create_security_group(self.context, @@ -1293,7 +1214,6 @@ class NWFilterTestCase(test.TestCase): inst.update(params) return db.instance_type_create(context, inst)['id'] - @test.skip_test('Skipping this test') def test_creates_base_rule_first(self): # These come pre-defined by libvirt self.defined_filters = ['no-mac-spoofing', @@ -1325,21 +1245,11 @@ class NWFilterTestCase(test.TestCase): instance_ref = self._create_instance() inst_id = instance_ref['id'] - ip = '10.11.12.13' - - #network_ref = db.project_get_networks(self.context, 'fake')[0] - #fixed_ip = {'address': ip, 'network_id': network_ref['id']} - - #admin_ctxt = context.get_admin_context() - #db.fixed_ip_create(admin_ctxt, fixed_ip) - #db.fixed_ip_update(admin_ctxt, ip, {'allocated': True, - # 'instance_id': inst_id}) - - self._setup_networking(instance_ref['id'], ip=ip) + _setup_networking(instance_ref['id'], self.test_ip) def _ensure_all_called(): instance_filter = 'nova-instance-%s-%s' % (instance_ref['name'], - '00A0C914C829') + '561212121212') secgroup_filter = 'nova-secgroup-%s' % self.security_group['id'] for required in [secgroup_filter, 'allow-dhcp-server', 'no-arp-spoofing', 'no-ip-spoofing', @@ -1360,7 +1270,7 @@ class NWFilterTestCase(test.TestCase): self.fw.apply_instance_filter(instance) _ensure_all_called() self.teardown_security_group() - db.instance_destroy(admin_ctxt, instance_ref['id']) + db.instance_destroy(context.get_admin_context(), instance_ref['id']) def test_create_network_filters(self): instance_ref = self._create_instance() @@ -1370,7 +1280,6 @@ class NWFilterTestCase(test.TestCase): "fake") self.assertEquals(len(result), 3) - @test.skip_test("skip libvirt test project_get_network no longer exists") def test_unfilter_instance_undefines_nwfilters(self): admin_ctxt = context.get_admin_context() @@ -1388,12 +1297,7 @@ class NWFilterTestCase(test.TestCase): instance = db.instance_get(self.context, inst_id) - ip = '10.11.12.13' - network_ref = db.project_get_network(self.context, 'fake') - fixed_ip = {'address': ip, 'network_id': network_ref['id']} - db.fixed_ip_create(admin_ctxt, fixed_ip) - db.fixed_ip_update(admin_ctxt, ip, {'allocated': True, - 'instance_id': inst_id}) + _setup_networking(instance_ref['id'], self.test_ip) self.fw.setup_basic_filtering(instance) self.fw.prepare_instance_filter(instance) self.fw.apply_instance_filter(instance) diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index fbe7d769e..28f50d328 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -149,7 +149,10 @@ class FlatNetworkTestCase(test.TestCase): 'cidr': '192.168.%s.0/24' % i, 'cidr_v6': '2001:db%s::/64' % i8, 'id': i, - 'injected': 'DONTCARE'} + 'multi_host': False, + 'injected': 'DONTCARE', + 'bridge_interface': 'fake_fa%s' % i, + 'vlan': None} self.assertDictMatch(nw[0], check) @@ -162,7 +165,9 @@ class FlatNetworkTestCase(test.TestCase): 'ips': 'DONTCARE', 'label': 'test%s' % i, 'mac': 'DE:AD:BE:EF:00:0%s' % i, - 'rxtx_cap': 'DONTCARE'} + 'rxtx_cap': 'DONTCARE', + 'should_create_vlan': False, + 'should_create_bridge': False} self.assertDictMatch(nw[1], check) check = [{'enabled': 'DONTCARE', diff --git a/nova/tests/test_objectstore.py b/nova/tests/test_objectstore.py index 39b4e18d7..0b2dce20e 100644 --- a/nova/tests/test_objectstore.py +++ b/nova/tests/test_objectstore.py @@ -21,8 +21,6 @@ Unittets for S3 objectstore clone. """ import boto -import glob -import hashlib import os import shutil import tempfile @@ -30,12 +28,9 @@ import tempfile from boto import exception as boto_exception from boto.s3 import connection as s3 -from nova import context -from nova import exception from nova import flags from nova import wsgi from nova import test -from nova.auth import manager from nova.objectstore import s3server @@ -57,15 +52,9 @@ class S3APITestCase(test.TestCase): def setUp(self): """Setup users, projects, and start a test server.""" super(S3APITestCase, self).setUp() - self.flags(auth_driver='nova.auth.ldapdriver.FakeLdapDriver', - buckets_path=os.path.join(OSS_TEMPDIR, 'buckets'), + self.flags(buckets_path=os.path.join(OSS_TEMPDIR, 'buckets'), s3_host='127.0.0.1') - self.auth_manager = manager.AuthManager() - self.admin_user = self.auth_manager.create_user('admin', admin=True) - self.admin_project = self.auth_manager.create_project('admin', - self.admin_user) - shutil.rmtree(FLAGS.buckets_path) os.mkdir(FLAGS.buckets_path) @@ -80,8 +69,8 @@ class S3APITestCase(test.TestCase): boto.config.add_section('Boto') boto.config.set('Boto', 'num_retries', '0') - conn = s3.S3Connection(aws_access_key_id=self.admin_user.access, - aws_secret_access_key=self.admin_user.secret, + conn = s3.S3Connection(aws_access_key_id='fake', + aws_secret_access_key='fake', host=FLAGS.s3_host, port=FLAGS.s3_port, is_secure=False, @@ -104,11 +93,11 @@ class S3APITestCase(test.TestCase): self.assertEquals(buckets[0].name, name, "Wrong name") return True - def test_000_list_buckets(self): + def test_list_buckets(self): """Make sure we are starting with no buckets.""" self._ensure_no_buckets(self.conn.get_all_buckets()) - def test_001_create_and_delete_bucket(self): + def test_create_and_delete_bucket(self): """Test bucket creation and deletion.""" bucket_name = 'testbucket' @@ -117,7 +106,7 @@ class S3APITestCase(test.TestCase): self.conn.delete_bucket(bucket_name) self._ensure_no_buckets(self.conn.get_all_buckets()) - def test_002_create_bucket_and_key_and_delete_key_again(self): + def test_create_bucket_and_key_and_delete_key_again(self): """Test key operations on buckets.""" bucket_name = 'testbucket' key_name = 'somekey' @@ -146,8 +135,6 @@ class S3APITestCase(test.TestCase): bucket_name) def tearDown(self): - """Tear down auth and test server.""" - self.auth_manager.delete_user('admin') - self.auth_manager.delete_project('admin') + """Tear down test server.""" self.server.stop() super(S3APITestCase, self).tearDown() diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index 69d2deafe..92393b536 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -20,12 +20,9 @@ from nova import compute from nova import context from nova import db from nova import flags -from nova import network from nova import quota from nova import test -from nova import utils from nova import volume -from nova.auth import manager from nova.compute import instance_types @@ -48,25 +45,20 @@ class QuotaTestCase(test.TestCase): quota_gigabytes=20, quota_floating_ips=1) - self.manager = manager.AuthManager() - self.user = self.manager.create_user('admin', 'admin', 'admin', True) - self.project = self.manager.create_project('admin', 'admin', 'admin') self.network = self.network = self.start_service('network') - self.context = context.RequestContext(project=self.project, - user=self.user) - - def tearDown(self): - manager.AuthManager().delete_project(self.project) - manager.AuthManager().delete_user(self.user) - super(QuotaTestCase, self).tearDown() + self.user_id = 'admin' + self.project_id = 'admin' + self.context = context.RequestContext(self.user_id, + self.project_id, + True) def _create_instance(self, cores=2): """Create a test instance""" inst = {} inst['image_id'] = 1 inst['reservation_id'] = 'r-fakeres' - inst['user_id'] = self.user.id - inst['project_id'] = self.project.id + inst['user_id'] = self.user_id + inst['project_id'] = self.project_id inst['instance_type_id'] = '3' # m1.large inst['vcpus'] = cores return db.instance_create(self.context, inst)['id'] @@ -74,8 +66,8 @@ class QuotaTestCase(test.TestCase): def _create_volume(self, size=10): """Create a test volume""" vol = {} - vol['user_id'] = self.user.id - vol['project_id'] = self.project.id + vol['user_id'] = self.user_id + vol['project_id'] = self.project_id vol['size'] = size return db.volume_create(self.context, vol)['id'] @@ -95,15 +87,15 @@ class QuotaTestCase(test.TestCase): num_instances = quota.allowed_instances(self.context, 100, self._get_instance_type('m1.small')) self.assertEqual(num_instances, 2) - db.quota_create(self.context, self.project.id, 'instances', 10) + db.quota_create(self.context, self.project_id, 'instances', 10) num_instances = quota.allowed_instances(self.context, 100, self._get_instance_type('m1.small')) self.assertEqual(num_instances, 4) - db.quota_create(self.context, self.project.id, 'cores', 100) + db.quota_create(self.context, self.project_id, 'cores', 100) num_instances = quota.allowed_instances(self.context, 100, self._get_instance_type('m1.small')) self.assertEqual(num_instances, 10) - db.quota_create(self.context, self.project.id, 'ram', 3 * 2048) + db.quota_create(self.context, self.project_id, 'ram', 3 * 2048) num_instances = quota.allowed_instances(self.context, 100, self._get_instance_type('m1.small')) self.assertEqual(num_instances, 3) @@ -113,13 +105,13 @@ class QuotaTestCase(test.TestCase): num_metadata_items = quota.allowed_metadata_items(self.context, too_many_items) self.assertEqual(num_metadata_items, FLAGS.quota_metadata_items) - db.quota_create(self.context, self.project.id, 'metadata_items', 5) + db.quota_create(self.context, self.project_id, 'metadata_items', 5) num_metadata_items = quota.allowed_metadata_items(self.context, too_many_items) self.assertEqual(num_metadata_items, 5) # Cleanup - db.quota_destroy_all_by_project(self.context, self.project.id) + db.quota_destroy_all_by_project(self.context, self.project_id) def test_unlimited_instances(self): FLAGS.quota_instances = 2 @@ -129,7 +121,7 @@ class QuotaTestCase(test.TestCase): num_instances = quota.allowed_instances(self.context, 100, instance_type) self.assertEqual(num_instances, 2) - db.quota_create(self.context, self.project.id, 'instances', None) + db.quota_create(self.context, self.project_id, 'instances', None) num_instances = quota.allowed_instances(self.context, 100, instance_type) self.assertEqual(num_instances, 100) @@ -145,7 +137,7 @@ class QuotaTestCase(test.TestCase): num_instances = quota.allowed_instances(self.context, 100, instance_type) self.assertEqual(num_instances, 2) - db.quota_create(self.context, self.project.id, 'ram', None) + db.quota_create(self.context, self.project_id, 'ram', None) num_instances = quota.allowed_instances(self.context, 100, instance_type) self.assertEqual(num_instances, 100) @@ -161,7 +153,7 @@ class QuotaTestCase(test.TestCase): num_instances = quota.allowed_instances(self.context, 100, instance_type) self.assertEqual(num_instances, 2) - db.quota_create(self.context, self.project.id, 'cores', None) + db.quota_create(self.context, self.project_id, 'cores', None) num_instances = quota.allowed_instances(self.context, 100, instance_type) self.assertEqual(num_instances, 100) @@ -174,7 +166,7 @@ class QuotaTestCase(test.TestCase): FLAGS.quota_gigabytes = -1 volumes = quota.allowed_volumes(self.context, 100, 1) self.assertEqual(volumes, 10) - db.quota_create(self.context, self.project.id, 'volumes', None) + db.quota_create(self.context, self.project_id, 'volumes', None) volumes = quota.allowed_volumes(self.context, 100, 1) self.assertEqual(volumes, 100) volumes = quota.allowed_volumes(self.context, 101, 1) @@ -185,7 +177,7 @@ class QuotaTestCase(test.TestCase): FLAGS.quota_gigabytes = 10 volumes = quota.allowed_volumes(self.context, 100, 1) self.assertEqual(volumes, 10) - db.quota_create(self.context, self.project.id, 'gigabytes', None) + db.quota_create(self.context, self.project_id, 'gigabytes', None) volumes = quota.allowed_volumes(self.context, 100, 1) self.assertEqual(volumes, 100) volumes = quota.allowed_volumes(self.context, 101, 1) @@ -195,7 +187,7 @@ class QuotaTestCase(test.TestCase): FLAGS.quota_floating_ips = 10 floating_ips = quota.allowed_floating_ips(self.context, 100) self.assertEqual(floating_ips, 10) - db.quota_create(self.context, self.project.id, 'floating_ips', None) + db.quota_create(self.context, self.project_id, 'floating_ips', None) floating_ips = quota.allowed_floating_ips(self.context, 100) self.assertEqual(floating_ips, 100) floating_ips = quota.allowed_floating_ips(self.context, 101) @@ -205,7 +197,7 @@ class QuotaTestCase(test.TestCase): FLAGS.quota_metadata_items = 10 items = quota.allowed_metadata_items(self.context, 100) self.assertEqual(items, 10) - db.quota_create(self.context, self.project.id, 'metadata_items', None) + db.quota_create(self.context, self.project_id, 'metadata_items', None) items = quota.allowed_metadata_items(self.context, 100) self.assertEqual(items, 100) items = quota.allowed_metadata_items(self.context, 101) @@ -269,16 +261,15 @@ class QuotaTestCase(test.TestCase): for volume_id in volume_ids: db.volume_destroy(self.context, volume_id) - @test.skip_test def test_too_many_addresses(self): address = '192.168.0.100' db.floating_ip_create(context.get_admin_context(), - {'address': address, 'host': FLAGS.host, - 'project_id': self.project.id}) + {'address': address, + 'project_id': self.project_id}) self.assertRaises(quota.QuotaError, self.network.allocate_floating_ip, self.context, - self.project.id) + self.project_id) db.floating_ip_destroy(context.get_admin_context(), address) def test_too_many_metadata_items(self): @@ -300,7 +291,7 @@ class QuotaTestCase(test.TestCase): def test_overridden_allowed_injected_files(self): FLAGS.quota_max_injected_files = 5 - db.quota_create(self.context, self.project.id, 'injected_files', 77) + db.quota_create(self.context, self.project_id, 'injected_files', 77) self.assertEqual(quota.allowed_injected_files(self.context, 100), 77) def test_unlimited_default_allowed_injected_files(self): @@ -309,7 +300,7 @@ class QuotaTestCase(test.TestCase): def test_unlimited_db_allowed_injected_files(self): FLAGS.quota_max_injected_files = 5 - db.quota_create(self.context, self.project.id, 'injected_files', None) + db.quota_create(self.context, self.project_id, 'injected_files', None) self.assertEqual(quota.allowed_injected_files(self.context, 100), 100) def test_default_allowed_injected_file_content_bytes(self): @@ -319,7 +310,7 @@ class QuotaTestCase(test.TestCase): def test_overridden_allowed_injected_file_content_bytes(self): FLAGS.quota_max_injected_file_content_bytes = 12345 - db.quota_create(self.context, self.project.id, + db.quota_create(self.context, self.project_id, 'injected_file_content_bytes', 5678) limit = quota.allowed_injected_file_content_bytes(self.context, 23456) self.assertEqual(limit, 5678) @@ -331,7 +322,7 @@ class QuotaTestCase(test.TestCase): def test_unlimited_db_allowed_injected_file_content_bytes(self): FLAGS.quota_max_injected_file_content_bytes = 12345 - db.quota_create(self.context, self.project.id, + db.quota_create(self.context, self.project_id, 'injected_file_content_bytes', None) limit = quota.allowed_injected_file_content_bytes(self.context, 23456) self.assertEqual(limit, 23456) diff --git a/nova/tests/test_rpc.py b/nova/tests/test_rpc.py index ffd748efe..2d2436175 100644 --- a/nova/tests/test_rpc.py +++ b/nova/tests/test_rpc.py @@ -33,11 +33,12 @@ LOG = logging.getLogger('nova.tests.rpc') class RpcTestCase(test.TestCase): def setUp(self): super(RpcTestCase, self).setUp() - self.conn = rpc.Connection.instance(True) + self.conn = rpc.create_connection(True) self.receiver = TestReceiver() - self.consumer = rpc.TopicAdapterConsumer(connection=self.conn, - topic='test', - proxy=self.receiver) + self.consumer = rpc.create_consumer(self.conn, + 'test', + self.receiver, + False) self.consumer.attach_to_eventlet() self.context = context.get_admin_context() @@ -129,6 +130,8 @@ class RpcTestCase(test.TestCase): """Calls echo in the passed queue""" LOG.debug(_("Nested received %(queue)s, %(value)s") % locals()) + # TODO: so, it will replay the context and use the same REQID? + # that's bizarre. ret = rpc.call(context, queue, {"method": "echo", @@ -137,10 +140,11 @@ class RpcTestCase(test.TestCase): return value nested = Nested() - conn = rpc.Connection.instance(True) - consumer = rpc.TopicAdapterConsumer(connection=conn, - topic='nested', - proxy=nested) + conn = rpc.create_connection(True) + consumer = rpc.create_consumer(conn, + 'nested', + nested, + False) consumer.attach_to_eventlet() value = 42 result = rpc.call(self.context, @@ -149,47 +153,6 @@ class RpcTestCase(test.TestCase): "value": value}}) self.assertEqual(value, result) - def test_connectionpool_single(self): - """Test that ConnectionPool recycles a single connection.""" - conn1 = rpc.ConnectionPool.get() - rpc.ConnectionPool.put(conn1) - conn2 = rpc.ConnectionPool.get() - rpc.ConnectionPool.put(conn2) - self.assertEqual(conn1, conn2) - - def test_connectionpool_double(self): - """Test that ConnectionPool returns and reuses separate connections. - - When called consecutively we should get separate connections and upon - returning them those connections should be reused for future calls - before generating a new connection. - - """ - conn1 = rpc.ConnectionPool.get() - conn2 = rpc.ConnectionPool.get() - - self.assertNotEqual(conn1, conn2) - rpc.ConnectionPool.put(conn1) - rpc.ConnectionPool.put(conn2) - - conn3 = rpc.ConnectionPool.get() - conn4 = rpc.ConnectionPool.get() - self.assertEqual(conn1, conn3) - self.assertEqual(conn2, conn4) - - def test_connectionpool_limit(self): - """Test connection pool limit and connection uniqueness.""" - max_size = FLAGS.rpc_conn_pool_size - conns = [] - - for i in xrange(max_size): - conns.append(rpc.ConnectionPool.get()) - - self.assertFalse(rpc.ConnectionPool.free_items) - self.assertEqual(rpc.ConnectionPool.current_size, - rpc.ConnectionPool.max_size) - self.assertEqual(len(set(conns)), max_size) - class TestReceiver(object): """Simple Proxy class so the consumer has methods to call. diff --git a/nova/tests/test_rpc_amqp.py b/nova/tests/test_rpc_amqp.py new file mode 100644 index 000000000..d29f7ae32 --- /dev/null +++ b/nova/tests/test_rpc_amqp.py @@ -0,0 +1,68 @@ +from nova import context +from nova import flags +from nova import log as logging +from nova import rpc +from nova.rpc import amqp +from nova import test + + +FLAGS = flags.FLAGS +LOG = logging.getLogger('nova.tests.rpc') + + +class RpcAMQPTestCase(test.TestCase): + def setUp(self): + super(RpcAMQPTestCase, self).setUp() + self.conn = rpc.create_connection(True) + self.receiver = TestReceiver() + self.consumer = rpc.create_consumer(self.conn, + 'test', + self.receiver, + False) + self.consumer.attach_to_eventlet() + self.context = context.get_admin_context() + + def test_connectionpool_single(self): + """Test that ConnectionPool recycles a single connection.""" + conn1 = amqp.ConnectionPool.get() + amqp.ConnectionPool.put(conn1) + conn2 = amqp.ConnectionPool.get() + amqp.ConnectionPool.put(conn2) + self.assertEqual(conn1, conn2) + + +class TestReceiver(object): + """Simple Proxy class so the consumer has methods to call. + + Uses static methods because we aren't actually storing any state. + + """ + + @staticmethod + def echo(context, value): + """Simply returns whatever value is sent in.""" + LOG.debug(_("Received %s"), value) + return value + + @staticmethod + def context(context, value): + """Returns dictionary version of context.""" + LOG.debug(_("Received %s"), context) + return context.to_dict() + + @staticmethod + def echo_three_times(context, value): + context.reply(value) + context.reply(value + 1) + context.reply(value + 2) + + @staticmethod + def echo_three_times_yield(context, value): + yield value + yield value + 1 + yield value + 2 + + @staticmethod + def fail(context, value): + """Raises an exception with the value sent in.""" + raise Exception(value) diff --git a/nova/tests/test_service.py b/nova/tests/test_service.py index f45f76b73..bbf47b50f 100644 --- a/nova/tests/test_service.py +++ b/nova/tests/test_service.py @@ -109,103 +109,8 @@ class ServiceTestCase(test.TestCase): # the looping calls are created in StartService. app = service.Service.create(host=host, binary=binary, topic=topic) - self.mox.StubOutWithMock(service.rpc.Connection, 'instance') - service.rpc.Connection.instance(new=mox.IgnoreArg()) - - self.mox.StubOutWithMock(rpc, - 'TopicAdapterConsumer', - use_mock_anything=True) - self.mox.StubOutWithMock(rpc, - 'FanoutAdapterConsumer', - use_mock_anything=True) - - self.mox.StubOutWithMock(rpc, - 'ConsumerSet', - use_mock_anything=True) - - rpc.TopicAdapterConsumer(connection=mox.IgnoreArg(), - topic=topic, - proxy=mox.IsA(service.Service)).AndReturn( - rpc.TopicAdapterConsumer) - - rpc.TopicAdapterConsumer(connection=mox.IgnoreArg(), - topic='%s.%s' % (topic, host), - proxy=mox.IsA(service.Service)).AndReturn( - rpc.TopicAdapterConsumer) - - rpc.FanoutAdapterConsumer(connection=mox.IgnoreArg(), - topic=topic, - proxy=mox.IsA(service.Service)).AndReturn( - rpc.FanoutAdapterConsumer) - - def wait_func(self, limit=None): - return None - - mock_cset = self.mox.CreateMock(rpc.ConsumerSet, - {'wait': wait_func}) - rpc.ConsumerSet(connection=mox.IgnoreArg(), - consumer_list=mox.IsA(list)).AndReturn(mock_cset) - wait_func(mox.IgnoreArg()) - - service_create = {'host': host, - 'binary': binary, - 'topic': topic, - 'report_count': 0, - 'availability_zone': 'nova'} - service_ref = {'host': host, - 'binary': binary, - 'report_count': 0, - 'id': 1} - - service.db.service_get_by_args(mox.IgnoreArg(), - host, - binary).AndRaise(exception.NotFound()) - service.db.service_create(mox.IgnoreArg(), - service_create).AndReturn(service_ref) - self.mox.ReplayAll() - - app.start() - app.stop() self.assert_(app) - # We're testing sort of weird behavior in how report_state decides - # whether it is disconnected, it looks for a variable on itself called - # 'model_disconnected' and report_state doesn't really do much so this - # these are mostly just for coverage - def test_report_state_no_service(self): - host = 'foo' - binary = 'bar' - topic = 'test' - service_create = {'host': host, - 'binary': binary, - 'topic': topic, - 'report_count': 0, - 'availability_zone': 'nova'} - service_ref = {'host': host, - 'binary': binary, - 'topic': topic, - 'report_count': 0, - 'availability_zone': 'nova', - 'id': 1} - - service.db.service_get_by_args(mox.IgnoreArg(), - host, - binary).AndRaise(exception.NotFound()) - service.db.service_create(mox.IgnoreArg(), - service_create).AndReturn(service_ref) - service.db.service_get(mox.IgnoreArg(), - service_ref['id']).AndReturn(service_ref) - service.db.service_update(mox.IgnoreArg(), service_ref['id'], - mox.ContainsKeyValue('report_count', 1)) - - self.mox.ReplayAll() - serv = service.Service(host, - binary, - topic, - 'nova.tests.test_service.FakeManager') - serv.start() - serv.report_state() - def test_report_state_newly_disconnected(self): host = 'foo' binary = 'bar' @@ -276,81 +181,6 @@ class ServiceTestCase(test.TestCase): self.assert_(not serv.model_disconnected) - def test_compute_can_update_available_resource(self): - """Confirm compute updates their record of compute-service table.""" - host = 'foo' - binary = 'nova-compute' - topic = 'compute' - - # Any mocks are not working without UnsetStubs() here. - self.mox.UnsetStubs() - ctxt = context.get_admin_context() - service_ref = db.service_create(ctxt, {'host': host, - 'binary': binary, - 'topic': topic}) - serv = service.Service(host, - binary, - topic, - 'nova.compute.manager.ComputeManager') - - # This testcase want to test calling update_available_resource. - # No need to call periodic call, then below variable must be set 0. - serv.report_interval = 0 - serv.periodic_interval = 0 - - # Creating mocks - self.mox.StubOutWithMock(service.rpc.Connection, 'instance') - service.rpc.Connection.instance(new=mox.IgnoreArg()) - - self.mox.StubOutWithMock(rpc, - 'TopicAdapterConsumer', - use_mock_anything=True) - self.mox.StubOutWithMock(rpc, - 'FanoutAdapterConsumer', - use_mock_anything=True) - - self.mox.StubOutWithMock(rpc, - 'ConsumerSet', - use_mock_anything=True) - - rpc.TopicAdapterConsumer(connection=mox.IgnoreArg(), - topic=topic, - proxy=mox.IsA(service.Service)).AndReturn( - rpc.TopicAdapterConsumer) - - rpc.TopicAdapterConsumer(connection=mox.IgnoreArg(), - topic='%s.%s' % (topic, host), - proxy=mox.IsA(service.Service)).AndReturn( - rpc.TopicAdapterConsumer) - - rpc.FanoutAdapterConsumer(connection=mox.IgnoreArg(), - topic=topic, - proxy=mox.IsA(service.Service)).AndReturn( - rpc.FanoutAdapterConsumer) - - def wait_func(self, limit=None): - return None - - mock_cset = self.mox.CreateMock(rpc.ConsumerSet, - {'wait': wait_func}) - rpc.ConsumerSet(connection=mox.IgnoreArg(), - consumer_list=mox.IsA(list)).AndReturn(mock_cset) - wait_func(mox.IgnoreArg()) - - self.mox.StubOutWithMock(serv.manager.driver, - 'update_available_resource') - serv.manager.driver.update_available_resource(mox.IgnoreArg(), host) - - # Just doing start()-stop(), not confirm new db record is created, - # because update_available_resource() works only in - # libvirt environment. This testcase confirms - # update_available_resource() is called. Otherwise, mox complains. - self.mox.ReplayAll() - serv.start() - serv.stop() - - db.service_destroy(ctxt, service_ref['id']) - class TestWSGIService(test.TestCase): diff --git a/nova/tests/test_test.py b/nova/tests/test_test.py index 35c838065..64f11fa45 100644 --- a/nova/tests/test_test.py +++ b/nova/tests/test_test.py @@ -33,8 +33,13 @@ class IsolationTestCase(test.TestCase): self.start_service('compute') def test_rpc_consumer_isolation(self): - connection = rpc.Connection.instance(new=True) - consumer = rpc.TopicAdapterConsumer(connection, topic='compute') - consumer.register_callback( - lambda x, y: self.fail('I should never be called')) + class NeverCalled(object): + + def __getattribute__(*args): + assert False, "I should never get called." + + connection = rpc.create_connection(new=True) + proxy = NeverCalled() + consumer = rpc.create_consumer(connection, 'compute', + proxy, fanout=False) consumer.attach_to_eventlet() diff --git a/nova/tests/test_vmwareapi.py b/nova/tests/test_vmwareapi.py index cbf7801cf..3d87d67ad 100644 --- a/nova/tests/test_vmwareapi.py +++ b/nova/tests/test_vmwareapi.py @@ -19,14 +19,11 @@ Test suite for VMWareAPI. """ -import stubout - from nova import context from nova import db from nova import flags from nova import test from nova import utils -from nova.auth import manager from nova.compute import power_state from nova.tests.glance import stubs as glance_stubs from nova.tests.vmwareapi import db_fakes @@ -41,51 +38,63 @@ FLAGS = flags.FLAGS class VMWareAPIVMTestCase(test.TestCase): """Unit tests for Vmware API connection calls.""" - # NOTE(jkoelker): This is leaking stubs into the db module. - # Commenting out until updated for multi-nic. - #def setUp(self): - # super(VMWareAPIVMTestCase, self).setUp() - # self.flags(vmwareapi_host_ip='test_url', - # vmwareapi_host_username='test_username', - # vmwareapi_host_password='test_pass') - # self.manager = manager.AuthManager() - # self.user = self.manager.create_user('fake', 'fake', 'fake', - # admin=True) - # self.project = self.manager.create_project('fake', 'fake', 'fake') - # self.network = utils.import_object(FLAGS.network_manager) - # self.stubs = stubout.StubOutForTesting() - # vmwareapi_fake.reset() - # db_fakes.stub_out_db_instance_api(self.stubs) - # stubs.set_stubs(self.stubs) - # glance_stubs.stubout_glance_client(self.stubs, - # glance_stubs.FakeGlance) - # self.conn = vmwareapi_conn.get_connection(False) - - #def tearDown(self): - # super(VMWareAPIVMTestCase, self).tearDown() - # vmwareapi_fake.cleanup() - # self.manager.delete_project(self.project) - # self.manager.delete_user(self.user) - # self.stubs.UnsetAll() + def setUp(self): + super(VMWareAPIVMTestCase, self).setUp() + self.flags(vmwareapi_host_ip='test_url', + vmwareapi_host_username='test_username', + vmwareapi_host_password='test_pass') + self.user_id = 'fake' + self.project_id = 'fake' + self.context = context.RequestContext(self.user_id, self.project_id) + self.network = utils.import_object(FLAGS.network_manager) + vmwareapi_fake.reset() + db_fakes.stub_out_db_instance_api(self.stubs) + stubs.set_stubs(self.stubs) + glance_stubs.stubout_glance_client(self.stubs) + self.conn = vmwareapi_conn.get_connection(False) + # NOTE(vish): none of the network plugging code is actually + # being tested + self.network_info = [({'bridge': 'fa0', + 'id': 0, + 'vlan': None, + 'bridge_interface': None, + 'injected': True}, + {'broadcast': '192.168.0.255', + 'dns': ['192.168.0.1'], + 'gateway': '192.168.0.1', + 'gateway6': 'dead:beef::1', + 'ip6s': [{'enabled': '1', + 'ip': 'dead:beef::dcad:beff:feef:0', + 'netmask': '64'}], + 'ips': [{'enabled': '1', + 'ip': '192.168.0.100', + 'netmask': '255.255.255.0'}], + 'label': 'fake', + 'mac': 'DE:AD:BE:EF:00:00', + 'rxtx_cap': 3})] + + def tearDown(self): + super(VMWareAPIVMTestCase, self).tearDown() + vmwareapi_fake.cleanup() def _create_instance_in_the_db(self): values = {'name': 1, 'id': 1, - 'project_id': self.project.id, - 'user_id': self.user.id, - 'image_id': "1", + 'project_id': self.project_id, + 'user_id': self.user_id, + 'image_ref': "1", 'kernel_id': "1", 'ramdisk_id': "1", + 'mac_address': "de:ad:be:ef:be:ef", 'instance_type': 'm1.large', - 'mac_address': 'aa:bb:cc:dd:ee:ff', } - self.instance = db.instance_create(values) + self.instance = db.instance_create(None, values) def _create_vm(self): """Create and spawn the VM.""" self._create_instance_in_the_db() self.type_data = db.instance_type_get_by_name(None, 'm1.large') - self.conn.spawn(self.instance) + self.conn.spawn(self.instance, self.network_info) self._check_vm_record() def _check_vm_record(self): @@ -129,24 +138,20 @@ class VMWareAPIVMTestCase(test.TestCase): self.assertEquals(info["mem"], mem_kib) self.assertEquals(info["num_cpu"], self.type_data['vcpus']) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_list_instances(self): instances = self.conn.list_instances() self.assertEquals(len(instances), 0) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_list_instances_1(self): self._create_vm() instances = self.conn.list_instances() self.assertEquals(len(instances), 1) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_spawn(self): self._create_vm() info = self.conn.get_info(1) self._check_vm_info(info, power_state.RUNNING) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_snapshot(self): self._create_vm() info = self.conn.get_info(1) @@ -155,27 +160,23 @@ class VMWareAPIVMTestCase(test.TestCase): info = self.conn.get_info(1) self._check_vm_info(info, power_state.RUNNING) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_snapshot_non_existent(self): self._create_instance_in_the_db() self.assertRaises(Exception, self.conn.snapshot, self.instance, "Test-Snapshot") - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_reboot(self): self._create_vm() info = self.conn.get_info(1) self._check_vm_info(info, power_state.RUNNING) - self.conn.reboot(self.instance) + self.conn.reboot(self.instance, self.network_info) info = self.conn.get_info(1) self._check_vm_info(info, power_state.RUNNING) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_reboot_non_existent(self): self._create_instance_in_the_db() self.assertRaises(Exception, self.conn.reboot, self.instance) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_reboot_not_poweredon(self): self._create_vm() info = self.conn.get_info(1) @@ -185,7 +186,6 @@ class VMWareAPIVMTestCase(test.TestCase): self._check_vm_info(info, power_state.PAUSED) self.assertRaises(Exception, self.conn.reboot, self.instance) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_suspend(self): self._create_vm() info = self.conn.get_info(1) @@ -194,13 +194,11 @@ class VMWareAPIVMTestCase(test.TestCase): info = self.conn.get_info(1) self._check_vm_info(info, power_state.PAUSED) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_suspend_non_existent(self): self._create_instance_in_the_db() self.assertRaises(Exception, self.conn.suspend, self.instance, self.dummy_callback_handler) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_resume(self): self._create_vm() info = self.conn.get_info(1) @@ -212,13 +210,11 @@ class VMWareAPIVMTestCase(test.TestCase): info = self.conn.get_info(1) self._check_vm_info(info, power_state.RUNNING) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_resume_non_existent(self): self._create_instance_in_the_db() self.assertRaises(Exception, self.conn.resume, self.instance, self.dummy_callback_handler) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_resume_not_suspended(self): self._create_vm() info = self.conn.get_info(1) @@ -226,49 +222,41 @@ class VMWareAPIVMTestCase(test.TestCase): self.assertRaises(Exception, self.conn.resume, self.instance, self.dummy_callback_handler) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_get_info(self): self._create_vm() info = self.conn.get_info(1) self._check_vm_info(info, power_state.RUNNING) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_destroy(self): self._create_vm() info = self.conn.get_info(1) self._check_vm_info(info, power_state.RUNNING) instances = self.conn.list_instances() self.assertEquals(len(instances), 1) - self.conn.destroy(self.instance) + self.conn.destroy(self.instance, self.network_info) instances = self.conn.list_instances() self.assertEquals(len(instances), 0) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_destroy_non_existent(self): self._create_instance_in_the_db() - self.assertEquals(self.conn.destroy(self.instance), None) + self.assertEquals(self.conn.destroy(self.instance, self.network_info), + None) - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_pause(self): pass - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_unpause(self): pass - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_diagnostics(self): pass - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_get_console_output(self): pass - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def test_get_ajax_console(self): pass - @test.skip_test("DB stubbing not removed, needs updating for multi-nic") def dummy_callback_handler(self, ret): """ Dummy callback function to be passed to suspend, resume, etc., calls. diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 4cb7447d3..d4bca1281 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -30,7 +30,6 @@ from nova import flags from nova import log as logging from nova import test 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 @@ -69,7 +68,9 @@ class XenAPIVolumeTestCase(test.TestCase): def setUp(self): super(XenAPIVolumeTestCase, self).setUp() self.stubs = stubout.StubOutForTesting() - self.context = context.RequestContext('fake', 'fake', False) + self.user_id = 'fake' + self.project_id = 'fake' + self.context = context.RequestContext(self.user_id, self.project_id) FLAGS.target_host = '127.0.0.1' FLAGS.xenapi_connection_url = 'test_url' FLAGS.xenapi_connection_password = 'test_pass' @@ -77,7 +78,7 @@ class XenAPIVolumeTestCase(test.TestCase): stubs.stub_out_get_target(self.stubs) xenapi_fake.reset() self.values = {'id': 1, - 'project_id': 'fake', + 'project_id': self.user_id, 'user_id': 'fake', 'image_ref': 1, 'kernel_id': 2, @@ -173,10 +174,6 @@ class XenAPIVMTestCase(test.TestCase): """Unit tests for VM operations.""" def setUp(self): super(XenAPIVMTestCase, self).setUp() - self.manager = manager.AuthManager() - self.user = self.manager.create_user('fake', 'fake', 'fake', - admin=True) - self.project = self.manager.create_project('fake', 'fake', 'fake') self.network = utils.import_object(FLAGS.network_manager) self.stubs = stubout.StubOutForTesting() self.flags(xenapi_connection_url='test_url', @@ -195,7 +192,9 @@ class XenAPIVMTestCase(test.TestCase): stubs.stub_out_vm_methods(self.stubs) glance_stubs.stubout_glance_client(self.stubs) fake_utils.stub_out_utils_execute(self.stubs) - self.context = context.RequestContext('fake', 'fake', False) + self.user_id = 'fake' + self.project_id = 'fake' + self.context = context.RequestContext(self.user_id, self.project_id) self.conn = xenapi_conn.get_connection(False) def test_parallel_builds(self): @@ -229,8 +228,8 @@ class XenAPIVMTestCase(test.TestCase): instance = db.instance_create(self.context, values) self.conn.spawn(instance, network_info) - gt1 = eventlet.spawn(_do_build, 1, self.project.id, self.user.id) - gt2 = eventlet.spawn(_do_build, 2, self.project.id, self.user.id) + gt1 = eventlet.spawn(_do_build, 1, self.project_id, self.user_id) + gt2 = eventlet.spawn(_do_build, 2, self.project_id, self.user_id) gt1.wait() gt2.wait() @@ -396,18 +395,22 @@ class XenAPIVMTestCase(test.TestCase): def _test_spawn(self, image_ref, kernel_id, ramdisk_id, instance_type_id="3", os_type="linux", architecture="x86-64", instance_id=1, - check_injection=False): + check_injection=False, + create_record=True): stubs.stubout_loopingcall_start(self.stubs) - values = {'id': instance_id, - 'project_id': self.project.id, - 'user_id': self.user.id, - 'image_ref': image_ref, - 'kernel_id': kernel_id, - 'ramdisk_id': ramdisk_id, - 'instance_type_id': instance_type_id, - 'os_type': os_type, - 'architecture': architecture} - instance = db.instance_create(self.context, values) + if create_record: + values = {'id': instance_id, + 'project_id': self.project_id, + 'user_id': self.user_id, + 'image_ref': image_ref, + 'kernel_id': kernel_id, + 'ramdisk_id': ramdisk_id, + 'instance_type_id': instance_type_id, + 'os_type': os_type, + 'architecture': architecture} + instance = db.instance_create(self.context, values) + else: + instance = db.instance_get(self.context, instance_id) network_info = [({'bridge': 'fa0', 'id': 0, 'injected': True}, {'broadcast': '192.168.0.255', 'dns': ['192.168.0.1'], @@ -465,12 +468,30 @@ class XenAPIVMTestCase(test.TestCase): self._check_vdis(vdi_recs_start, vdi_recs_end) def test_spawn_raw_objectstore(self): - FLAGS.xenapi_image_service = 'objectstore' - self._test_spawn(1, None, None) + # TODO(vish): deprecated + from nova.auth import manager + authman = manager.AuthManager() + authman.create_user('fake', 'fake') + authman.create_project('fake', 'fake') + try: + FLAGS.xenapi_image_service = 'objectstore' + self._test_spawn(1, None, None) + finally: + authman.delete_project('fake') + authman.delete_user('fake') def test_spawn_objectstore(self): - FLAGS.xenapi_image_service = 'objectstore' - self._test_spawn(1, 2, 3) + # TODO(vish): deprecated + from nova.auth import manager + authman = manager.AuthManager() + authman.create_user('fake', 'fake') + authman.create_project('fake', 'fake') + try: + FLAGS.xenapi_image_service = 'objectstore' + self._test_spawn(1, 2, 3) + finally: + authman.delete_project('fake') + authman.delete_user('fake') @stub_vm_utils_with_vdi_attached_here def test_spawn_raw_glance(self): @@ -599,41 +620,38 @@ class XenAPIVMTestCase(test.TestCase): # guest agent is detected self.assertFalse(self._tee_executed) - @test.skip_test("Never gets an address, not sure why") def test_spawn_vlanmanager(self): self.flags(xenapi_image_service='glance', network_manager='nova.network.manager.VlanManager', - network_driver='nova.network.xenapi_net', vlan_interface='fake0') def dummy(*args, **kwargs): pass - self.stubs.Set(VMOps, 'create_vifs', dummy) + self.stubs.Set(vmops.VMOps, 'create_vifs', dummy) # Reset network table xenapi_fake.reset_table('network') # Instance id = 2 will use vlan network (see db/fakes.py) ctxt = self.context.elevated() - instance_ref = self._create_instance(2) - network_bk = self.network - # Ensure we use xenapi_net driver - self.network = utils.import_object(FLAGS.network_manager) + instance = self._create_instance(2, False) networks = self.network.db.network_get_all(ctxt) for network in networks: - self.network.set_network_host(ctxt, network['id']) - - self.network.allocate_for_instance(ctxt, instance_id=instance_ref.id, - instance_type_id=1, project_id=self.project.id) - self.network.setup_compute_network(ctxt, instance_ref.id) + self.network.set_network_host(ctxt, network) + + self.network.allocate_for_instance(ctxt, + instance_id=2, + host=FLAGS.host, + vpn=None, + instance_type_id=1, + project_id=self.project_id) self._test_spawn(glance_stubs.FakeGlance.IMAGE_MACHINE, glance_stubs.FakeGlance.IMAGE_KERNEL, glance_stubs.FakeGlance.IMAGE_RAMDISK, - instance_id=instance_ref.id, + instance_id=2, create_record=False) # TODO(salvatore-orlando): a complete test here would require # a check for making sure the bridge for the VM's VIF is # consistent with bridge specified in nova db - self.network = network_bk def test_spawn_with_network_qos(self): self._create_instance() @@ -644,10 +662,10 @@ class XenAPIVMTestCase(test.TestCase): str(3 * 1024)) def test_rescue(self): - self.flags(xenapi_inject_image=False) + self.flags(flat_injected=False) instance = self._create_instance() conn = xenapi_conn.get_connection(False) - conn.rescue(instance, None) + conn.rescue(instance, None, []) def test_unrescue(self): instance = self._create_instance() @@ -655,21 +673,13 @@ class XenAPIVMTestCase(test.TestCase): # Ensure that it will not unrescue a non-rescued instance. self.assertRaises(Exception, conn.unrescue, instance, None) - def tearDown(self): - super(XenAPIVMTestCase, self).tearDown() - self.manager.delete_project(self.project) - self.manager.delete_user(self.user) - self.vm_info = None - self.vm = None - self.stubs.UnsetAll() - - def _create_instance(self, instance_id=1): + def _create_instance(self, instance_id=1, spawn=True): """Creates and spawns a test instance.""" stubs.stubout_loopingcall_start(self.stubs) values = { 'id': instance_id, - 'project_id': self.project.id, - 'user_id': self.user.id, + 'project_id': self.project_id, + 'user_id': self.user_id, 'image_ref': 1, 'kernel_id': 2, 'ramdisk_id': 3, @@ -691,7 +701,8 @@ class XenAPIVMTestCase(test.TestCase): 'label': 'fake', 'mac': 'DE:AD:BE:EF:00:00', 'rxtx_cap': 3})] - self.conn.spawn(instance, network_info) + if spawn: + self.conn.spawn(instance, network_info) return instance @@ -750,14 +761,12 @@ class XenAPIMigrateInstance(test.TestCase): stubs.stub_out_get_target(self.stubs) xenapi_fake.reset() xenapi_fake.create_network('fake', FLAGS.flat_network_bridge) - self.manager = manager.AuthManager() - self.user = self.manager.create_user('fake', 'fake', 'fake', - admin=True) - self.project = self.manager.create_project('fake', 'fake', 'fake') - self.context = context.RequestContext('fake', 'fake', False) + self.user_id = 'fake' + self.project_id = 'fake' + self.context = context.RequestContext(self.user_id, self.project_id) self.values = {'id': 1, - 'project_id': self.project.id, - 'user_id': self.user.id, + 'project_id': self.project_id, + 'user_id': self.user_id, 'image_ref': 1, 'kernel_id': None, 'ramdisk_id': None, @@ -771,20 +780,81 @@ class XenAPIMigrateInstance(test.TestCase): stubs.stubout_get_this_vm_uuid(self.stubs) glance_stubs.stubout_glance_client(self.stubs) - def tearDown(self): - super(XenAPIMigrateInstance, self).tearDown() - self.manager.delete_project(self.project) - self.manager.delete_user(self.user) - self.stubs.UnsetAll() - def test_migrate_disk_and_power_off(self): instance = db.instance_create(self.context, self.values) stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) conn = xenapi_conn.get_connection(False) conn.migrate_disk_and_power_off(instance, '127.0.0.1') - def test_finish_resize(self): + def test_finish_migrate(self): + instance = db.instance_create(self.context, self.values) + self.called = False + + def fake_vdi_resize(*args, **kwargs): + self.called = True + + self.stubs.Set(stubs.FakeSessionForMigrationTests, + "VDI_resize_online", fake_vdi_resize) + stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) + stubs.stubout_loopingcall_start(self.stubs) + conn = xenapi_conn.get_connection(False) + network_info = [({'bridge': 'fa0', 'id': 0, 'injected': False}, + {'broadcast': '192.168.0.255', + 'dns': ['192.168.0.1'], + 'gateway': '192.168.0.1', + 'gateway6': 'dead:beef::1', + 'ip6s': [{'enabled': '1', + 'ip': 'dead:beef::dcad:beff:feef:0', + 'netmask': '64'}], + 'ips': [{'enabled': '1', + 'ip': '192.168.0.100', + 'netmask': '255.255.255.0'}], + 'label': 'fake', + 'mac': 'DE:AD:BE:EF:00:00', + 'rxtx_cap': 3})] + conn.finish_migration(instance, dict(base_copy='hurr', cow='durr'), + network_info, resize_instance=True) + self.assertEqual(self.called, True) + + def test_finish_migrate_no_local_storage(self): + tiny_type_id = \ + instance_types.get_instance_type_by_name('m1.tiny')['id'] + self.values.update({'instance_type_id': tiny_type_id, 'local_gb': 0}) + instance = db.instance_create(self.context, self.values) + + def fake_vdi_resize(*args, **kwargs): + raise Exception("This shouldn't be called") + + self.stubs.Set(stubs.FakeSessionForMigrationTests, + "VDI_resize_online", fake_vdi_resize) + stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) + stubs.stubout_loopingcall_start(self.stubs) + conn = xenapi_conn.get_connection(False) + network_info = [({'bridge': 'fa0', 'id': 0, 'injected': False}, + {'broadcast': '192.168.0.255', + 'dns': ['192.168.0.1'], + 'gateway': '192.168.0.1', + 'gateway6': 'dead:beef::1', + 'ip6s': [{'enabled': '1', + 'ip': 'dead:beef::dcad:beff:feef:0', + 'netmask': '64'}], + 'ips': [{'enabled': '1', + 'ip': '192.168.0.100', + 'netmask': '255.255.255.0'}], + 'label': 'fake', + 'mac': 'DE:AD:BE:EF:00:00', + 'rxtx_cap': 3})] + conn.finish_migration(instance, dict(base_copy='hurr', cow='durr'), + network_info, resize_instance=True) + + def test_finish_migrate_no_resize_vdi(self): instance = db.instance_create(self.context, self.values) + + def fake_vdi_resize(*args, **kwargs): + raise Exception("This shouldn't be called") + + self.stubs.Set(stubs.FakeSessionForMigrationTests, + "VDI_resize_online", fake_vdi_resize) stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) stubs.stubout_loopingcall_start(self.stubs) conn = xenapi_conn.get_connection(False) @@ -802,8 +872,26 @@ class XenAPIMigrateInstance(test.TestCase): 'label': 'fake', 'mac': 'DE:AD:BE:EF:00:00', 'rxtx_cap': 3})] - conn.finish_resize(instance, dict(base_copy='hurr', cow='durr'), - network_info) + + # Resize instance would be determined by the compute call + conn.finish_migration(instance, dict(base_copy='hurr', cow='durr'), + network_info, resize_instance=False) + + +class XenAPIImageTypeTestCase(test.TestCase): + """Test ImageType class.""" + + def test_to_string(self): + """Can convert from type id to type string.""" + self.assertEquals( + vm_utils.ImageType.to_string(vm_utils.ImageType.KERNEL), + vm_utils.ImageType.KERNEL_STR) + + def test_from_string(self): + """Can convert from string to type id.""" + self.assertEquals( + vm_utils.ImageType.from_string(vm_utils.ImageType.KERNEL_STR), + vm_utils.ImageType.KERNEL) class XenAPIDetermineDiskImageTestCase(test.TestCase): diff --git a/nova/tests/vmwareapi/db_fakes.py b/nova/tests/vmwareapi/db_fakes.py index d4eb87daf..afd672c7a 100644 --- a/nova/tests/vmwareapi/db_fakes.py +++ b/nova/tests/vmwareapi/db_fakes.py @@ -70,8 +70,8 @@ def stub_out_db_instance_api(stubs): 'launch_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()),
'instance_type': values['instance_type'],
'memory_mb': type_data['memory_mb'],
- 'mac_address': values['mac_address'],
'vcpus': type_data['vcpus'],
+ 'mac_addresses': [{'address': values['mac_address']}],
'local_gb': type_data['local_gb'],
}
return FakeModel(base_options)
@@ -83,6 +83,8 @@ def stub_out_db_instance_api(stubs): 'bridge': 'vmnet0',
'netmask': '255.255.255.0',
'gateway': '10.10.10.1',
+ 'broadcast': '10.10.10.255',
+ 'dns1': 'fake',
'vlan': 100}
return FakeModel(fields)
@@ -90,7 +92,7 @@ def stub_out_db_instance_api(stubs): """Stubs out the db.instance_action_create method."""
pass
- def fake_instance_get_fixed_address(context, instance_id):
+ def fake_instance_get_fixed_addresses(context, instance_id):
"""Stubs out the db.instance_get_fixed_address method."""
return '10.10.10.10'
@@ -103,7 +105,7 @@ def stub_out_db_instance_api(stubs): stubs.Set(db, 'instance_create', fake_instance_create)
stubs.Set(db, 'network_get_by_instance', fake_network_get_by_instance)
stubs.Set(db, 'instance_action_create', fake_instance_action_create)
- stubs.Set(db, 'instance_get_fixed_address',
- fake_instance_get_fixed_address)
+ stubs.Set(db, 'instance_get_fixed_addresses',
+ fake_instance_get_fixed_addresses)
stubs.Set(db, 'instance_type_get_all', fake_instance_type_get_all)
stubs.Set(db, 'instance_type_get_by_name', fake_instance_type_get_by_name)
diff --git a/nova/tests/vmwareapi/stubs.py b/nova/tests/vmwareapi/stubs.py index a648efb16..0ed5e9b68 100644 --- a/nova/tests/vmwareapi/stubs.py +++ b/nova/tests/vmwareapi/stubs.py @@ -22,6 +22,8 @@ Stubouts for the test suite from nova.virt import vmwareapi_conn
from nova.virt.vmwareapi import fake
from nova.virt.vmwareapi import vmware_images
+from nova.virt.vmwareapi import vmops
+from nova.virt.vmwareapi import network_utils
def fake_get_vim_object(arg):
@@ -36,11 +38,16 @@ def fake_is_vim_object(arg, module): def set_stubs(stubs):
"""Set the stubs."""
+ stubs.Set(vmops.VMWareVMOps, 'plug_vifs', fake.fake_plug_vifs)
+ stubs.Set(network_utils, 'get_network_with_the_name',
+ fake.fake_get_network)
stubs.Set(vmware_images, 'fetch_image', fake.fake_fetch_image)
stubs.Set(vmware_images, 'get_vmdk_size_and_properties',
fake.fake_get_vmdk_size_and_properties)
stubs.Set(vmware_images, 'upload_image', fake.fake_upload_image)
stubs.Set(vmwareapi_conn.VMWareAPISession, "_get_vim_object",
fake_get_vim_object)
+ stubs.Set(vmwareapi_conn.VMWareAPISession, "_get_vim_object",
+ fake_get_vim_object)
stubs.Set(vmwareapi_conn.VMWareAPISession, "_is_vim_object",
fake_is_vim_object)
|
