summaryrefslogtreecommitdiffstats
path: root/nova/tests
diff options
context:
space:
mode:
authorWilliam Wolf <throughnothing@gmail.com>2011-05-20 12:43:02 -0400
committerWilliam Wolf <throughnothing@gmail.com>2011-05-20 12:43:02 -0400
commit355ef9c0a65cfb4bac1f21f39e149d77a27bd6a4 (patch)
tree14476d535ea8780433d4a33a93f5b502e33c8d94 /nova/tests
parentf1da26ec9af6f6adffb7b6bfdc64f9702db93b56 (diff)
parentf4d4d3a160416ebb4021837d300b299bb6ff75a6 (diff)
merge from trunk
Diffstat (limited to 'nova/tests')
-rw-r--r--nova/tests/api/openstack/extensions/foxinsocks.py26
-rw-r--r--nova/tests/api/openstack/test_extensions.py45
-rw-r--r--nova/tests/api/openstack/test_zones.py42
-rw-r--r--nova/tests/public_key/dummy.fingerprint1
-rw-r--r--nova/tests/public_key/dummy.pub1
-rw-r--r--nova/tests/test_cloud.py30
-rw-r--r--nova/tests/test_crypto.py48
-rw-r--r--nova/tests/test_scheduler.py61
-rw-r--r--nova/tests/test_zone_aware_scheduler.py119
9 files changed, 333 insertions, 40 deletions
diff --git a/nova/tests/api/openstack/extensions/foxinsocks.py b/nova/tests/api/openstack/extensions/foxinsocks.py
index 0860b51ac..dbdd0928a 100644
--- a/nova/tests/api/openstack/extensions/foxinsocks.py
+++ b/nova/tests/api/openstack/extensions/foxinsocks.py
@@ -63,31 +63,33 @@ class Foxinsocks(object):
self._delete_tweedle))
return actions
- def get_response_extensions(self):
- response_exts = []
+ def get_request_extensions(self):
+ request_exts = []
- def _goose_handler(res):
+ def _goose_handler(req, res):
#NOTE: This only handles JSON responses.
# You can use content type header to test for XML.
data = json.loads(res.body)
- data['flavor']['googoose'] = "Gooey goo for chewy chewing!"
- return data
+ data['flavor']['googoose'] = req.GET.get('chewing')
+ res.body = json.dumps(data)
+ return res
- resp_ext = extensions.ResponseExtension('GET', '/v1.1/flavors/:(id)',
+ req_ext1 = extensions.RequestExtension('GET', '/v1.1/flavors/:(id)',
_goose_handler)
- response_exts.append(resp_ext)
+ request_exts.append(req_ext1)
- def _bands_handler(res):
+ def _bands_handler(req, res):
#NOTE: This only handles JSON responses.
# You can use content type header to test for XML.
data = json.loads(res.body)
data['big_bands'] = 'Pig Bands!'
- return data
+ res.body = json.dumps(data)
+ return res
- resp_ext2 = extensions.ResponseExtension('GET', '/v1.1/flavors/:(id)',
+ req_ext2 = extensions.RequestExtension('GET', '/v1.1/flavors/:(id)',
_bands_handler)
- response_exts.append(resp_ext2)
- return response_exts
+ request_exts.append(req_ext2)
+ return request_exts
def _add_tweedle(self, input_dict, req, id):
diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py
index 481d34ed1..544298602 100644
--- a/nova/tests/api/openstack/test_extensions.py
+++ b/nova/tests/api/openstack/test_extensions.py
@@ -45,10 +45,10 @@ class StubController(nova.wsgi.Controller):
class StubExtensionManager(object):
- def __init__(self, resource_ext=None, action_ext=None, response_ext=None):
+ def __init__(self, resource_ext=None, action_ext=None, request_ext=None):
self.resource_ext = resource_ext
self.action_ext = action_ext
- self.response_ext = response_ext
+ self.request_ext = request_ext
def get_name(self):
return "Tweedle Beetle Extension"
@@ -71,11 +71,11 @@ class StubExtensionManager(object):
action_exts.append(self.action_ext)
return action_exts
- def get_response_extensions(self):
- response_exts = []
- if self.response_ext:
- response_exts.append(self.response_ext)
- return response_exts
+ def get_request_extensions(self):
+ request_extensions = []
+ if self.request_ext:
+ request_extensions.append(self.request_ext)
+ return request_extensions
class ExtensionControllerTest(unittest.TestCase):
@@ -183,10 +183,10 @@ class ActionExtensionTest(unittest.TestCase):
self.assertEqual(404, response.status_int)
-class ResponseExtensionTest(unittest.TestCase):
+class RequestExtensionTest(unittest.TestCase):
def setUp(self):
- super(ResponseExtensionTest, self).setUp()
+ super(RequestExtensionTest, self).setUp()
self.stubs = stubout.StubOutForTesting()
fakes.FakeAuthManager.reset_fake_data()
fakes.FakeAuthDatabase.data = {}
@@ -195,42 +195,39 @@ class ResponseExtensionTest(unittest.TestCase):
def tearDown(self):
self.stubs.UnsetAll()
- super(ResponseExtensionTest, self).tearDown()
+ super(RequestExtensionTest, self).tearDown()
def test_get_resources_with_stub_mgr(self):
- test_resp = "Gooey goo for chewy chewing!"
-
- def _resp_handler(res):
+ def _req_handler(req, res):
# only handle JSON responses
data = json.loads(res.body)
- data['flavor']['googoose'] = test_resp
- return data
+ data['flavor']['googoose'] = req.GET.get('chewing')
+ res.body = json.dumps(data)
+ return res
- resp_ext = extensions.ResponseExtension('GET',
+ req_ext = extensions.RequestExtension('GET',
'/v1.1/flavors/:(id)',
- _resp_handler)
+ _req_handler)
- manager = StubExtensionManager(None, None, resp_ext)
+ manager = StubExtensionManager(None, None, req_ext)
app = fakes.wsgi_app()
ext_midware = extensions.ExtensionMiddleware(app, manager)
- request = webob.Request.blank("/v1.1/flavors/1")
+ request = webob.Request.blank("/v1.1/flavors/1?chewing=bluegoo")
request.environ['api.version'] = '1.1'
response = request.get_response(ext_midware)
self.assertEqual(200, response.status_int)
response_data = json.loads(response.body)
- self.assertEqual(test_resp, response_data['flavor']['googoose'])
+ self.assertEqual('bluegoo', response_data['flavor']['googoose'])
def test_get_resources_with_mgr(self):
- test_resp = "Gooey goo for chewy chewing!"
-
app = fakes.wsgi_app()
ext_midware = extensions.ExtensionMiddleware(app)
- request = webob.Request.blank("/v1.1/flavors/1")
+ request = webob.Request.blank("/v1.1/flavors/1?chewing=newblue")
request.environ['api.version'] = '1.1'
response = request.get_response(ext_midware)
self.assertEqual(200, response.status_int)
response_data = json.loads(response.body)
- self.assertEqual(test_resp, response_data['flavor']['googoose'])
+ self.assertEqual('newblue', response_data['flavor']['googoose'])
self.assertEqual("Pig Bands!", response_data['big_bands'])
diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py
index 5d5799b59..fa2e05033 100644
--- a/nova/tests/api/openstack/test_zones.py
+++ b/nova/tests/api/openstack/test_zones.py
@@ -20,6 +20,8 @@ import json
import nova.db
from nova import context
+from nova import crypto
+from nova import exception
from nova import flags
from nova import test
from nova.api.openstack import zones
@@ -79,6 +81,18 @@ def zone_capabilities(method, context):
return dict()
+GLOBAL_BUILD_PLAN = [
+ dict(name='host1', weight=10, ip='10.0.0.1', zone='zone1'),
+ dict(name='host2', weight=9, ip='10.0.0.2', zone='zone2'),
+ dict(name='host3', weight=8, ip='10.0.0.3', zone='zone3'),
+ dict(name='host4', weight=7, ip='10.0.0.4', zone='zone4'),
+ ]
+
+
+def zone_select(context, specs):
+ return GLOBAL_BUILD_PLAN
+
+
class ZonesTest(test.TestCase):
def setUp(self):
super(ZonesTest, self).setUp()
@@ -190,3 +204,31 @@ class ZonesTest(test.TestCase):
self.assertEqual(res_dict['zone']['name'], 'darksecret')
self.assertEqual(res_dict['zone']['cap1'], 'a;b')
self.assertEqual(res_dict['zone']['cap2'], 'c;d')
+
+ def test_zone_select(self):
+ FLAGS.build_plan_encryption_key = 'c286696d887c9aa0611bbb3e2025a45a'
+ self.stubs.Set(api, 'select', zone_select)
+
+ req = webob.Request.blank('/v1.0/zones/select')
+
+ res = req.get_response(fakes.wsgi_app())
+ res_dict = json.loads(res.body)
+ self.assertEqual(res.status_int, 200)
+
+ self.assertTrue('weights' in res_dict)
+
+ for item in res_dict['weights']:
+ blob = item['blob']
+ decrypt = crypto.decryptor(FLAGS.build_plan_encryption_key)
+ secret_item = json.loads(decrypt(blob))
+ found = False
+ for original_item in GLOBAL_BUILD_PLAN:
+ if original_item['name'] != secret_item['name']:
+ continue
+ found = True
+ for key in ('weight', 'ip', 'zone'):
+ self.assertEqual(secret_item[key], original_item[key])
+
+ self.assertTrue(found)
+ self.assertEqual(len(item), 2)
+ self.assertTrue('weight' in item)
diff --git a/nova/tests/public_key/dummy.fingerprint b/nova/tests/public_key/dummy.fingerprint
new file mode 100644
index 000000000..715bca27a
--- /dev/null
+++ b/nova/tests/public_key/dummy.fingerprint
@@ -0,0 +1 @@
+1c:87:d1:d9:32:fd:62:3c:78:2b:c0:ad:c0:15:88:df
diff --git a/nova/tests/public_key/dummy.pub b/nova/tests/public_key/dummy.pub
new file mode 100644
index 000000000..d4cf2bc0d
--- /dev/null
+++ b/nova/tests/public_key/dummy.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAMGJlY9XEIm2X234pdO5yFWMp2JuOQx8U0E815IVXhmKxYCBK9ZakgZOIQmPbXoGYyV+mziDPp6HJ0wKYLQxkwLEFr51fAZjWQvRss0SinURRuLkockDfGFtD4pYJthekr/rlqMKlBSDUSpGq8jUWW60UJ18FGooFpxR7ESqQRx/AAAAFQC96LRglaUeeP+E8U/yblEJocuiWwAAAIA3XiMR8Skiz/0aBm5K50SeQznQuMJTyzt9S9uaz5QZWiFu69hOyGSFGw8fqgxEkXFJIuHobQQpGYQubLW0NdaYRqyE/Vud3JUJUb8Texld6dz8vGemyB5d1YvtSeHIo8/BGv2msOqR3u5AZTaGCBD9DhpSGOKHEdNjTtvpPd8S8gAAAIBociGZ5jf09iHLVENhyXujJbxfGRPsyNTyARJfCOGl0oFV6hEzcQyw8U/ePwjgvjc2UizMWLl8tsb2FXKHRdc2v+ND3Us+XqKQ33X3ADP4FZ/+Oj213gMyhCmvFTP0u5FmHog9My4CB7YcIWRuUR42WlhQ2IfPvKwUoTk3R+T6Og== www-data@mk
diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py
index c8559615a..54c0454de 100644
--- a/nova/tests/test_cloud.py
+++ b/nova/tests/test_cloud.py
@@ -354,6 +354,36 @@ class CloudTestCase(test.TestCase):
self.assertTrue(filter(lambda k: k['keyName'] == 'test1', keys))
self.assertTrue(filter(lambda k: k['keyName'] == 'test2', keys))
+ def test_import_public_key(self):
+ # test when user provides all values
+ result1 = self.cloud.import_public_key(self.context,
+ 'testimportkey1',
+ 'mytestpubkey',
+ 'mytestfprint')
+ self.assertTrue(result1)
+ keydata = db.key_pair_get(self.context,
+ self.context.user.id,
+ 'testimportkey1')
+ self.assertEqual('mytestpubkey', keydata['public_key'])
+ self.assertEqual('mytestfprint', keydata['fingerprint'])
+ # test when user omits fingerprint
+ pubkey_path = os.path.join(os.path.dirname(__file__), 'public_key')
+ f = open(pubkey_path + '/dummy.pub', 'r')
+ dummypub = f.readline().rstrip()
+ f.close
+ f = open(pubkey_path + '/dummy.fingerprint', 'r')
+ dummyfprint = f.readline().rstrip()
+ f.close
+ result2 = self.cloud.import_public_key(self.context,
+ 'testimportkey2',
+ dummypub)
+ self.assertTrue(result2)
+ keydata = db.key_pair_get(self.context,
+ self.context.user.id,
+ 'testimportkey2')
+ self.assertEqual(dummypub, keydata['public_key'])
+ self.assertEqual(dummyfprint, keydata['fingerprint'])
+
def test_delete_key_pair(self):
self._create_key('test')
self.cloud.delete_key_pair(self.context, 'test')
diff --git a/nova/tests/test_crypto.py b/nova/tests/test_crypto.py
new file mode 100644
index 000000000..945d78794
--- /dev/null
+++ b/nova/tests/test_crypto.py
@@ -0,0 +1,48 @@
+# Copyright 2011 OpenStack LLC.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+"""
+Tests for Crypto module.
+"""
+
+from nova import crypto
+from nova import test
+
+
+class SymmetricKeyTestCase(test.TestCase):
+ """Test case for Encrypt/Decrypt"""
+ def test_encrypt_decrypt(self):
+ key = 'c286696d887c9aa0611bbb3e2025a45a'
+ plain_text = "The quick brown fox jumped over the lazy dog."
+
+ # No IV supplied (all 0's)
+ encrypt = crypto.encryptor(key)
+ cipher_text = encrypt(plain_text)
+ self.assertNotEquals(plain_text, cipher_text)
+
+ decrypt = crypto.decryptor(key)
+ plain = decrypt(cipher_text)
+
+ self.assertEquals(plain_text, plain)
+
+ # IV supplied ...
+ iv = '562e17996d093d28ddb3ba695a2e6f58'
+ encrypt = crypto.encryptor(key, iv)
+ cipher_text = encrypt(plain_text)
+ self.assertNotEquals(plain_text, cipher_text)
+
+ decrypt = crypto.decryptor(key, iv)
+ plain = decrypt(cipher_text)
+
+ self.assertEquals(plain_text, plain)
diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py
index 968ef9d6c..54b3f80fb 100644
--- a/nova/tests/test_scheduler.py
+++ b/nova/tests/test_scheduler.py
@@ -912,7 +912,8 @@ class SimpleDriverTestCase(test.TestCase):
class FakeZone(object):
- def __init__(self, api_url, username, password):
+ def __init__(self, id, api_url, username, password):
+ self.id = id
self.api_url = api_url
self.username = username
self.password = password
@@ -920,7 +921,7 @@ class FakeZone(object):
def zone_get_all(context):
return [
- FakeZone('http://example.com', 'bob', 'xxx'),
+ FakeZone(1, 'http://example.com', 'bob', 'xxx'),
]
@@ -1037,7 +1038,7 @@ class FakeNovaClient(object):
class DynamicNovaClientTest(test.TestCase):
def test_issue_novaclient_command_found(self):
- zone = FakeZone('http://example.com', 'bob', 'xxx')
+ zone = FakeZone(1, 'http://example.com', 'bob', 'xxx')
self.assertEquals(api._issue_novaclient_command(
FakeNovaClient(FakeServerCollection()),
zone, "servers", "get", 100).a, 10)
@@ -1051,7 +1052,7 @@ class DynamicNovaClientTest(test.TestCase):
zone, "servers", "pause", 100), None)
def test_issue_novaclient_command_not_found(self):
- zone = FakeZone('http://example.com', 'bob', 'xxx')
+ zone = FakeZone(1, 'http://example.com', 'bob', 'xxx')
self.assertEquals(api._issue_novaclient_command(
FakeNovaClient(FakeEmptyServerCollection()),
zone, "servers", "get", 100), None)
@@ -1063,3 +1064,55 @@ class DynamicNovaClientTest(test.TestCase):
self.assertEquals(api._issue_novaclient_command(
FakeNovaClient(FakeEmptyServerCollection()),
zone, "servers", "any", "name"), None)
+
+
+class FakeZonesProxy(object):
+ def do_something(*args, **kwargs):
+ return 42
+
+ def raises_exception(*args, **kwargs):
+ raise Exception('testing')
+
+
+class FakeNovaClientOpenStack(object):
+ def __init__(self, *args, **kwargs):
+ self.zones = FakeZonesProxy()
+
+ def authenticate(self):
+ pass
+
+
+class CallZoneMethodTest(test.TestCase):
+ def setUp(self):
+ super(CallZoneMethodTest, self).setUp()
+ self.stubs = stubout.StubOutForTesting()
+ self.stubs.Set(db, 'zone_get_all', zone_get_all)
+ self.stubs.Set(novaclient, 'OpenStack', FakeNovaClientOpenStack)
+
+ def tearDown(self):
+ self.stubs.UnsetAll()
+ super(CallZoneMethodTest, self).tearDown()
+
+ def test_call_zone_method(self):
+ context = {}
+ method = 'do_something'
+ results = api.call_zone_method(context, method)
+ expected = [(1, 42)]
+ self.assertEqual(expected, results)
+
+ def test_call_zone_method_not_present(self):
+ context = {}
+ method = 'not_present'
+ self.assertRaises(AttributeError, api.call_zone_method,
+ context, method)
+
+ def test_call_zone_method_generates_exception(self):
+ context = {}
+ method = 'raises_exception'
+ results = api.call_zone_method(context, method)
+
+ # FIXME(sirp): for now the _error_trap code is catching errors and
+ # converting them to a ("ERROR", "string") tuples. The code (and this
+ # test) should eventually handle real exceptions.
+ expected = [(1, ('ERROR', 'testing'))]
+ self.assertEqual(expected, results)
diff --git a/nova/tests/test_zone_aware_scheduler.py b/nova/tests/test_zone_aware_scheduler.py
new file mode 100644
index 000000000..fdcde34c9
--- /dev/null
+++ b/nova/tests/test_zone_aware_scheduler.py
@@ -0,0 +1,119 @@
+# Copyright 2011 OpenStack LLC.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+"""
+Tests For Zone Aware Scheduler.
+"""
+
+from nova import test
+from nova.scheduler import driver
+from nova.scheduler import zone_aware_scheduler
+from nova.scheduler import zone_manager
+
+
+class FakeZoneAwareScheduler(zone_aware_scheduler.ZoneAwareScheduler):
+ def filter_hosts(self, num, specs):
+ # NOTE(sirp): this is returning [(hostname, services)]
+ return self.zone_manager.service_states.items()
+
+ def weigh_hosts(self, num, specs, hosts):
+ fake_weight = 99
+ weighted = []
+ for hostname, caps in hosts:
+ weighted.append(dict(weight=fake_weight, name=hostname))
+ return weighted
+
+
+class FakeZoneManager(zone_manager.ZoneManager):
+ def __init__(self):
+ self.service_states = {
+ 'host1': {
+ 'compute': {'ram': 1000}
+ },
+ 'host2': {
+ 'compute': {'ram': 2000}
+ },
+ 'host3': {
+ 'compute': {'ram': 3000}
+ }
+ }
+
+
+class FakeEmptyZoneManager(zone_manager.ZoneManager):
+ def __init__(self):
+ self.service_states = {}
+
+
+def fake_empty_call_zone_method(context, method, specs):
+ return []
+
+
+def fake_call_zone_method(context, method, specs):
+ return [
+ ('zone1', [
+ dict(weight=1, blob='AAAAAAA'),
+ dict(weight=111, blob='BBBBBBB'),
+ dict(weight=112, blob='CCCCCCC'),
+ dict(weight=113, blob='DDDDDDD'),
+ ]),
+ ('zone2', [
+ dict(weight=120, blob='EEEEEEE'),
+ dict(weight=2, blob='FFFFFFF'),
+ dict(weight=122, blob='GGGGGGG'),
+ dict(weight=123, blob='HHHHHHH'),
+ ]),
+ ('zone3', [
+ dict(weight=130, blob='IIIIIII'),
+ dict(weight=131, blob='JJJJJJJ'),
+ dict(weight=132, blob='KKKKKKK'),
+ dict(weight=3, blob='LLLLLLL'),
+ ]),
+ ]
+
+
+class ZoneAwareSchedulerTestCase(test.TestCase):
+ """Test case for Zone Aware Scheduler."""
+
+ def test_zone_aware_scheduler(self):
+ """
+ Create a nested set of FakeZones, ensure that a select call returns the
+ appropriate build plan.
+ """
+ sched = FakeZoneAwareScheduler()
+ self.stubs.Set(sched, '_call_zone_method', fake_call_zone_method)
+
+ zm = FakeZoneManager()
+ sched.set_zone_manager(zm)
+
+ fake_context = {}
+ build_plan = sched.select(fake_context, {})
+
+ self.assertEqual(15, len(build_plan))
+
+ hostnames = [plan_item['name']
+ for plan_item in build_plan if 'name' in plan_item]
+ self.assertEqual(3, len(hostnames))
+
+ def test_empty_zone_aware_scheduler(self):
+ """
+ Ensure empty hosts & child_zones result in NoValidHosts exception.
+ """
+ sched = FakeZoneAwareScheduler()
+ self.stubs.Set(sched, '_call_zone_method', fake_empty_call_zone_method)
+
+ zm = FakeEmptyZoneManager()
+ sched.set_zone_manager(zm)
+
+ fake_context = {}
+ self.assertRaises(driver.NoValidHost, sched.schedule, fake_context, {})