summaryrefslogtreecommitdiffstats
path: root/nova/tests
diff options
context:
space:
mode:
authorTushar Patil <tushar.vitthal.patil@gmail.com>2011-08-17 17:17:47 -0700
committerTushar Patil <tushar.vitthal.patil@gmail.com>2011-08-17 17:17:47 -0700
commitc3ef50fd4b866ec6dc90ad114e36b16c857ca206 (patch)
tree68d6b7c352d7b0a6ab0fc2096486ba983af46ed8 /nova/tests
parent19a4ddaf157ebb388cce37ddc142dfad304b8cf0 (diff)
parentaca07a42fabb7f506cf132b995b4ad0139987b02 (diff)
Merged with trunk and fixed broken testcases
Diffstat (limited to 'nova/tests')
-rw-r--r--nova/tests/api/openstack/contrib/test_floating_ips.py18
-rw-r--r--nova/tests/api/openstack/contrib/test_quotas.py152
-rw-r--r--nova/tests/api/openstack/test_extensions.py122
-rw-r--r--nova/tests/api/openstack/test_limits.py178
-rw-r--r--nova/tests/api/openstack/test_server_actions.py20
-rw-r--r--nova/tests/api/openstack/test_servers.py32
-rw-r--r--nova/tests/glance/stubs.py6
-rw-r--r--nova/tests/integrated/test_servers.py5
-rw-r--r--nova/tests/scheduler/test_abstract_scheduler.py (renamed from nova/tests/scheduler/test_zone_aware_scheduler.py)40
-rw-r--r--nova/tests/scheduler/test_least_cost_scheduler.py4
-rw-r--r--nova/tests/scheduler/test_scheduler.py83
-rw-r--r--nova/tests/test_compute.py97
-rw-r--r--nova/tests/test_libvirt.py236
-rw-r--r--nova/tests/test_metadata.py2
-rw-r--r--nova/tests/test_network.py198
-rw-r--r--nova/tests/test_xenapi.py5
-rw-r--r--nova/tests/xenapi/stubs.py4
17 files changed, 891 insertions, 311 deletions
diff --git a/nova/tests/api/openstack/contrib/test_floating_ips.py b/nova/tests/api/openstack/contrib/test_floating_ips.py
index ab7ae2e54..704d06582 100644
--- a/nova/tests/api/openstack/contrib/test_floating_ips.py
+++ b/nova/tests/api/openstack/contrib/test_floating_ips.py
@@ -116,14 +116,14 @@ class FloatingIpTest(test.TestCase):
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
res_dict = json.loads(res.body)
- response = {'floating_ips': [{'floating_ip': {'instance_id': 11,
- 'ip': '10.10.10.10',
- 'fixed_ip': '10.0.0.1',
- 'id': 1}},
- {'floating_ip': {'instance_id': None,
- 'ip': '10.10.10.11',
- 'fixed_ip': None,
- 'id': 2}}]}
+ response = {'floating_ips': [{'instance_id': 11,
+ 'ip': '10.10.10.10',
+ 'fixed_ip': '10.0.0.1',
+ 'id': 1},
+ {'instance_id': None,
+ 'ip': '10.10.10.11',
+ 'fixed_ip': None,
+ 'id': 2}]}
self.assertEqual(res_dict, response)
def test_floating_ip_show(self):
@@ -177,8 +177,10 @@ class FloatingIpTest(test.TestCase):
self.assertEqual(actual, expected)
def test_floating_ip_disassociate(self):
+ body = dict()
req = webob.Request.blank('/v1.1/os-floating-ips/1/disassociate')
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, 200)
diff --git a/nova/tests/api/openstack/contrib/test_quotas.py b/nova/tests/api/openstack/contrib/test_quotas.py
new file mode 100644
index 000000000..f6a25385f
--- /dev/null
+++ b/nova/tests/api/openstack/contrib/test_quotas.py
@@ -0,0 +1,152 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.
+
+import json
+import webob
+
+from nova import context
+from nova import test
+from nova.tests.api.openstack import fakes
+
+from nova.api.openstack.contrib.quotas import QuotaSetsController
+
+
+def quota_set(id):
+ return {'quota_set': {'id': id, 'metadata_items': 128, 'volumes': 10,
+ 'gigabytes': 1000, 'ram': 51200, 'floating_ips': 10,
+ 'instances': 10, 'injected_files': 5, 'cores': 20,
+ 'injected_file_content_bytes': 10240}}
+
+
+def quota_set_list():
+ return {'quota_set_list': [quota_set('1234'), quota_set('5678'),
+ quota_set('update_me')]}
+
+
+class QuotaSetsTest(test.TestCase):
+
+ def setUp(self):
+ super(QuotaSetsTest, self).setUp()
+ self.controller = QuotaSetsController()
+ self.user_id = 'fake'
+ self.project_id = 'fake'
+ self.user_context = context.RequestContext(self.user_id,
+ self.project_id)
+ self.admin_context = context.RequestContext(self.user_id,
+ self.project_id,
+ is_admin=True)
+
+ def test_format_quota_set(self):
+ raw_quota_set = {
+ 'instances': 10,
+ 'cores': 20,
+ 'ram': 51200,
+ 'volumes': 10,
+ 'floating_ips': 10,
+ 'metadata_items': 128,
+ 'gigabytes': 1000,
+ 'injected_files': 5,
+ 'injected_file_content_bytes': 10240}
+
+ quota_set = QuotaSetsController()._format_quota_set('1234',
+ raw_quota_set)
+ qs = quota_set['quota_set']
+
+ self.assertEqual(qs['id'], '1234')
+ self.assertEqual(qs['instances'], 10)
+ self.assertEqual(qs['cores'], 20)
+ self.assertEqual(qs['ram'], 51200)
+ self.assertEqual(qs['volumes'], 10)
+ self.assertEqual(qs['gigabytes'], 1000)
+ self.assertEqual(qs['floating_ips'], 10)
+ self.assertEqual(qs['metadata_items'], 128)
+ self.assertEqual(qs['injected_files'], 5)
+ self.assertEqual(qs['injected_file_content_bytes'], 10240)
+
+ def test_quotas_defaults(self):
+ req = webob.Request.blank('/v1.1/os-quota-sets/fake_tenant/defaults')
+ req.method = 'GET'
+ req.headers['Content-Type'] = 'application/json'
+ res = req.get_response(fakes.wsgi_app())
+
+ self.assertEqual(res.status_int, 200)
+ expected = {'quota_set': {
+ 'id': 'fake_tenant',
+ 'instances': 10,
+ 'cores': 20,
+ 'ram': 51200,
+ 'volumes': 10,
+ 'gigabytes': 1000,
+ 'floating_ips': 10,
+ 'metadata_items': 128,
+ 'injected_files': 5,
+ 'injected_file_content_bytes': 10240}}
+
+ self.assertEqual(json.loads(res.body), expected)
+
+ def test_quotas_show_as_admin(self):
+ req = webob.Request.blank('/v1.1/os-quota-sets/1234')
+ req.method = 'GET'
+ req.headers['Content-Type'] = 'application/json'
+ res = req.get_response(fakes.wsgi_app(
+ fake_auth_context=self.admin_context))
+
+ self.assertEqual(res.status_int, 200)
+ self.assertEqual(json.loads(res.body), quota_set('1234'))
+
+ def test_quotas_show_as_unauthorized_user(self):
+ req = webob.Request.blank('/v1.1/os-quota-sets/1234')
+ req.method = 'GET'
+ req.headers['Content-Type'] = 'application/json'
+ res = req.get_response(fakes.wsgi_app(
+ fake_auth_context=self.user_context))
+
+ self.assertEqual(res.status_int, 403)
+
+ def test_quotas_update_as_admin(self):
+ updated_quota_set = {'quota_set': {'instances': 50,
+ 'cores': 50, 'ram': 51200, 'volumes': 10,
+ 'gigabytes': 1000, 'floating_ips': 10,
+ 'metadata_items': 128, 'injected_files': 5,
+ 'injected_file_content_bytes': 10240}}
+
+ req = webob.Request.blank('/v1.1/os-quota-sets/update_me')
+ req.method = 'PUT'
+ req.body = json.dumps(updated_quota_set)
+ req.headers['Content-Type'] = 'application/json'
+
+ res = req.get_response(fakes.wsgi_app(
+ fake_auth_context=self.admin_context))
+
+ self.assertEqual(json.loads(res.body), updated_quota_set)
+
+ def test_quotas_update_as_user(self):
+ updated_quota_set = {'quota_set': {'instances': 50,
+ 'cores': 50, 'ram': 51200, 'volumes': 10,
+ 'gigabytes': 1000, 'floating_ips': 10,
+ 'metadata_items': 128, 'injected_files': 5,
+ 'injected_file_content_bytes': 10240}}
+
+ req = webob.Request.blank('/v1.1/os-quota-sets/update_me')
+ req.method = 'PUT'
+ req.body = json.dumps(updated_quota_set)
+ req.headers['Content-Type'] = 'application/json'
+
+ res = req.get_response(fakes.wsgi_app(
+ fake_auth_context=self.user_context))
+
+ self.assertEqual(res.status_int, 403)
diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py
index ea8fe68a7..5d3208e10 100644
--- a/nova/tests/api/openstack/test_extensions.py
+++ b/nova/tests/api/openstack/test_extensions.py
@@ -84,6 +84,18 @@ class ExtensionControllerTest(test.TestCase):
super(ExtensionControllerTest, self).setUp()
ext_path = os.path.join(os.path.dirname(__file__), "extensions")
self.flags(osapi_extensions_path=ext_path)
+ self.ext_list = [
+ "FlavorExtraSpecs",
+ "Floating_ips",
+ "Fox In Socks",
+ "Hosts",
+ "Keypairs",
+ "Multinic",
+ "Quotas",
+ "SecurityGroups",
+ "Volumes",
+ ]
+ self.ext_list.sort()
def test_list_extensions_json(self):
app = openstack.APIRouterV11()
@@ -96,12 +108,10 @@ class ExtensionControllerTest(test.TestCase):
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", "Keypairs", "Multinic", "SecurityGroups",
- "Volumes"])
+ self.assertEqual(names, self.ext_list)
# Make sure that at least Fox in Sox is correct.
- (fox_ext,) = [
+ (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',
@@ -127,9 +137,7 @@ class ExtensionControllerTest(test.TestCase):
"updated": "2011-01-22T13:25:27-06:00",
"description": "The Fox In Socks Extension",
"alias": "FOXNSOX",
- "links": [],
- },
- )
+ "links": []})
def test_list_extensions_xml(self):
app = openstack.APIRouterV11()
@@ -145,10 +153,10 @@ class ExtensionControllerTest(test.TestCase):
# Make sure we have all the extensions.
exts = root.findall('{0}extension'.format(NS))
- self.assertEqual(len(exts), 8)
+ self.assertEqual(len(exts), len(self.ext_list))
# Make sure that at least Fox in Sox is correct.
- (fox_ext,) = [x for x in exts if x.get('alias') == 'FOXNSOX']
+ (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')
@@ -220,6 +228,7 @@ class ResourceExtensionTest(test.TestCase):
class InvalidExtension(object):
+
def get_alias(self):
return "THIRD"
@@ -281,7 +290,7 @@ class ActionExtensionTest(test.TestCase):
def test_invalid_action_body(self):
body = dict(blah=dict(name="test")) # Doesn't exist
response = self._send_server_action_request("/servers/1/action", body)
- self.assertEqual(501, response.status_int)
+ self.assertEqual(400, response.status_int)
def test_invalid_action(self):
body = dict(blah=dict(name="test"))
@@ -336,27 +345,18 @@ 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',
- },
- ],
- },
- }
+ 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')
print xml
@@ -378,48 +378,30 @@ class ExtensionsXMLSerializerTest(test.TestCase):
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",
+ 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",
+ "href": "http://foo.com/api/ext/cs-pie.pdf"},
+ {"rel": "describedby",
"type": "application/vnd.sun.wadl+xml",
- "href": "http://foo.com/api/ext/cs-cbs.wadl",
- },
- ],
- },
- ],
- }
+ "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
diff --git a/nova/tests/api/openstack/test_limits.py b/nova/tests/api/openstack/test_limits.py
index 1dc3c3a17..801b06230 100644
--- a/nova/tests/api/openstack/test_limits.py
+++ b/nova/tests/api/openstack/test_limits.py
@@ -915,86 +915,56 @@ class LimitsViewBuilderV11Test(test.TestCase):
def setUp(self):
self.view_builder = views.limits.ViewBuilderV11()
- self.rate_limits = [
- {
- "URI": "*",
- "regex": ".*",
- "value": 10,
- "verb": "POST",
- "remaining": 2,
- "unit": "MINUTE",
- "resetTime": 1311272226,
- },
- {
- "URI": "*/servers",
- "regex": "^/servers",
- "value": 50,
- "verb": "POST",
- "remaining": 10,
- "unit": "DAY",
- "resetTime": 1311272226,
- },
- ]
- self.absolute_limits = {
- "metadata_items": 1,
- "injected_files": 5,
- "injected_file_content_bytes": 5,
- }
+ self.rate_limits = [{"URI": "*",
+ "regex": ".*",
+ "value": 10,
+ "verb": "POST",
+ "remaining": 2,
+ "unit": "MINUTE",
+ "resetTime": 1311272226},
+ {"URI": "*/servers",
+ "regex": "^/servers",
+ "value": 50,
+ "verb": "POST",
+ "remaining": 10,
+ "unit": "DAY",
+ "resetTime": 1311272226}]
+ self.absolute_limits = {"metadata_items": 1,
+ "injected_files": 5,
+ "injected_file_content_bytes": 5}
def tearDown(self):
pass
def test_build_limits(self):
- expected_limits = {
- "limits": {
- "rate": [
- {
- "uri": "*",
- "regex": ".*",
- "limit": [
- {
- "value": 10,
- "verb": "POST",
- "remaining": 2,
- "unit": "MINUTE",
- "next-available": "2011-07-21T18:17:06Z",
- },
- ]
- },
- {
- "uri": "*/servers",
- "regex": "^/servers",
- "limit": [
- {
- "value": 50,
- "verb": "POST",
- "remaining": 10,
- "unit": "DAY",
- "next-available": "2011-07-21T18:17:06Z",
- },
- ]
- },
- ],
- "absolute": {
- "maxServerMeta": 1,
- "maxImageMeta": 1,
- "maxPersonality": 5,
- "maxPersonalitySize": 5
- }
- }
- }
+ expected_limits = {"limits": {
+ "rate": [{
+ "uri": "*",
+ "regex": ".*",
+ "limit": [{"value": 10,
+ "verb": "POST",
+ "remaining": 2,
+ "unit": "MINUTE",
+ "next-available": "2011-07-21T18:17:06Z"}]},
+ {"uri": "*/servers",
+ "regex": "^/servers",
+ "limit": [{"value": 50,
+ "verb": "POST",
+ "remaining": 10,
+ "unit": "DAY",
+ "next-available": "2011-07-21T18:17:06Z"}]}],
+ "absolute": {"maxServerMeta": 1,
+ "maxImageMeta": 1,
+ "maxPersonality": 5,
+ "maxPersonalitySize": 5}}}
output = self.view_builder.build(self.rate_limits,
self.absolute_limits)
self.assertDictMatch(output, expected_limits)
def test_build_limits_empty_limits(self):
- expected_limits = {
- "limits": {
- "rate": [],
- "absolute": {},
- }
- }
+ expected_limits = {"limits": {"rate": [],
+ "absolute": {}}}
abs_limits = {}
rate_limits = []
@@ -1012,45 +982,28 @@ class LimitsXMLSerializationTest(test.TestCase):
def test_index(self):
serializer = limits.LimitsXMLSerializer()
-
- fixture = {
- "limits": {
- "rate": [
- {
- "uri": "*",
- "regex": ".*",
- "limit": [
- {
- "value": 10,
- "verb": "POST",
- "remaining": 2,
- "unit": "MINUTE",
- "next-available": "2011-12-15T22:42:45Z",
- },
- ]
- },
- {
- "uri": "*/servers",
- "regex": "^/servers",
- "limit": [
- {
- "value": 50,
- "verb": "POST",
- "remaining": 10,
- "unit": "DAY",
- "next-available": "2011-12-15T22:42:45Z"
- },
- ]
- },
- ],
- "absolute": {
- "maxServerMeta": 1,
- "maxImageMeta": 1,
- "maxPersonality": 5,
- "maxPersonalitySize": 10240
- }
- }
- }
+ fixture = {"limits": {
+ "rate": [{
+ "uri": "*",
+ "regex": ".*",
+ "limit": [{
+ "value": 10,
+ "verb": "POST",
+ "remaining": 2,
+ "unit": "MINUTE",
+ "next-available": "2011-12-15T22:42:45Z"}]},
+ {"uri": "*/servers",
+ "regex": "^/servers",
+ "limit": [{
+ "value": 50,
+ "verb": "POST",
+ "remaining": 10,
+ "unit": "DAY",
+ "next-available": "2011-12-15T22:42:45Z"}]}],
+ "absolute": {"maxServerMeta": 1,
+ "maxImageMeta": 1,
+ "maxPersonality": 5,
+ "maxPersonalitySize": 10240}}}
output = serializer.serialize(fixture, 'index')
actual = minidom.parseString(output.replace(" ", ""))
@@ -1083,12 +1036,9 @@ class LimitsXMLSerializationTest(test.TestCase):
def test_index_no_limits(self):
serializer = limits.LimitsXMLSerializer()
- fixture = {
- "limits": {
- "rate": [],
- "absolute": {},
- }
- }
+ fixture = {"limits": {
+ "rate": [],
+ "absolute": {}}}
output = serializer.serialize(fixture, 'index')
actual = minidom.parseString(output.replace(" ", ""))
diff --git a/nova/tests/api/openstack/test_server_actions.py b/nova/tests/api/openstack/test_server_actions.py
index 717e11c00..687a19390 100644
--- a/nova/tests/api/openstack/test_server_actions.py
+++ b/nova/tests/api/openstack/test_server_actions.py
@@ -352,7 +352,7 @@ class ServerActionsTest(test.TestCase):
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
response = req.get_response(fakes.wsgi_app())
- self.assertEqual(501, response.status_int)
+ self.assertEqual(400, response.status_int)
def test_create_backup_with_metadata(self):
self.flags(allow_admin_api=True)
@@ -487,6 +487,24 @@ class ServerActionsTestV11(test.TestCase):
def tearDown(self):
self.stubs.UnsetAll()
+ def test_server_bad_body(self):
+ body = {}
+ req = webob.Request.blank('/v1.1/servers/1/action')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ req.body = json.dumps(body)
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 400)
+
+ def test_server_unknown_action(self):
+ body = {'sockTheFox': {'fakekey': '1234'}}
+ req = webob.Request.blank('/v1.1/servers/1/action')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ req.body = json.dumps(body)
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 400)
+
def test_server_change_password(self):
mock_method = MockSetAdminPassword()
self.stubs.Set(nova.compute.api.API, 'set_admin_password', mock_method)
diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py
index 290f6e990..a510d7d97 100644
--- a/nova/tests/api/openstack/test_servers.py
+++ b/nova/tests/api/openstack/test_servers.py
@@ -134,8 +134,8 @@ def return_security_group(context, instance_id, security_group_id):
pass
-def instance_update(context, instance_id, kwargs):
- return stub_instance(instance_id)
+def instance_update(context, instance_id, values):
+ return stub_instance(instance_id, name=values.get('display_name'))
def instance_addresses(context, instance_id):
@@ -145,7 +145,7 @@ def instance_addresses(context, instance_id):
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):
+ flavor_id="1", interfaces=None, name=None):
metadata = []
metadata.append(InstanceMetadata(key='seq', value=id))
@@ -161,7 +161,7 @@ def stub_instance(id, user_id='fake', project_id='fake', private_address=None,
host = str(host)
# ReservationID isn't sent back, hack it in there.
- server_name = "server%s" % id
+ server_name = name or "server%s" % id
if reservation_id != "":
server_name = "reservation_%s" % (reservation_id, )
@@ -1880,13 +1880,17 @@ class ServersTest(test.TestCase):
self.assertEqual(res.status_int, 400)
def test_update_server_name_v1_1(self):
+ self.stubs.Set(nova.db.api, 'instance_get',
+ return_server_with_attributes(name='server_test'))
req = webob.Request.blank('/v1.1/servers/1')
req.method = 'PUT'
req.content_type = 'application/json'
- req.body = json.dumps({'server': {'name': 'new-name'}})
+ req.body = json.dumps({'server': {'name': 'server_test'}})
res = req.get_response(fakes.wsgi_app())
- self.assertEqual(res.status_int, 204)
- self.assertEqual(res.body, '')
+ self.assertEqual(res.status_int, 200)
+ res_dict = json.loads(res.body)
+ self.assertEqual(res_dict['server']['id'], 1)
+ self.assertEqual(res_dict['server']['name'], 'server_test')
def test_update_server_adminPass_ignored_v1_1(self):
inst_dict = dict(name='server_test', adminPass='bacon')
@@ -1897,16 +1901,19 @@ class ServersTest(test.TestCase):
self.assertEqual(params, filtered_dict)
return filtered_dict
- self.stubs.Set(nova.db.api, 'instance_update',
- server_update)
+ self.stubs.Set(nova.db.api, 'instance_update', server_update)
+ self.stubs.Set(nova.db.api, 'instance_get',
+ return_server_with_attributes(name='server_test'))
req = webob.Request.blank('/v1.1/servers/1')
req.method = 'PUT'
req.content_type = "application/json"
req.body = self.body
res = req.get_response(fakes.wsgi_app())
- self.assertEqual(res.status_int, 204)
- self.assertEqual(res.body, '')
+ self.assertEqual(res.status_int, 200)
+ res_dict = json.loads(res.body)
+ self.assertEqual(res_dict['server']['id'], 1)
+ self.assertEqual(res_dict['server']['name'], 'server_test')
def test_create_backup_schedules(self):
req = webob.Request.blank('/v1.0/servers/1/backup_schedule')
@@ -3049,8 +3056,7 @@ class ServersViewBuilderV11Test(test.TestCase):
address_builder,
flavor_builder,
image_builder,
- base_url,
- )
+ base_url)
return view_builder
def test_build_server(self):
diff --git a/nova/tests/glance/stubs.py b/nova/tests/glance/stubs.py
index d51b19ccd..f2a19f22d 100644
--- a/nova/tests/glance/stubs.py
+++ b/nova/tests/glance/stubs.py
@@ -32,6 +32,7 @@ class FakeGlance(object):
IMAGE_RAMDISK = 3
IMAGE_RAW = 4
IMAGE_VHD = 5
+ IMAGE_ISO = 6
IMAGE_FIXTURES = {
IMAGE_MACHINE: {
@@ -58,6 +59,11 @@ class FakeGlance(object):
'image_meta': {'name': 'fakevhd', 'size': 0,
'disk_format': 'vhd',
'container_format': 'ovf'},
+ 'image_data': StringIO.StringIO('')},
+ IMAGE_ISO: {
+ 'image_meta': {'name': 'fakeiso', 'size': 0,
+ 'disk_format': 'iso',
+ 'container_format': 'bare'},
'image_data': StringIO.StringIO('')}}
def __init__(self, host, port=None, use_ssl=False, auth_tok=None):
diff --git a/nova/tests/integrated/test_servers.py b/nova/tests/integrated/test_servers.py
index 150279a95..725f6d529 100644
--- a/nova/tests/integrated/test_servers.py
+++ b/nova/tests/integrated/test_servers.py
@@ -27,6 +27,7 @@ LOG = logging.getLogger('nova.tests.integrated')
class ServersTest(integrated_helpers._IntegratedTestBase):
+
def test_get_servers(self):
"""Simple check that listing servers works."""
servers = self.api.get_servers()
@@ -103,6 +104,10 @@ class ServersTest(integrated_helpers._IntegratedTestBase):
# It should be available...
# TODO(justinsb): Mock doesn't yet do this...
#self.assertEqual('available', found_server['status'])
+ servers = self.api.get_servers(detail=True)
+ for server in servers:
+ self.assertTrue("image" in server)
+ self.assertTrue("flavor" in server)
self._delete_server(created_server_id)
diff --git a/nova/tests/scheduler/test_zone_aware_scheduler.py b/nova/tests/scheduler/test_abstract_scheduler.py
index 788efca52..f4f5cc233 100644
--- a/nova/tests/scheduler/test_zone_aware_scheduler.py
+++ b/nova/tests/scheduler/test_abstract_scheduler.py
@@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
"""
-Tests For Zone Aware Scheduler.
+Tests For Abstract Scheduler.
"""
import json
@@ -25,7 +25,7 @@ from nova import rpc
from nova import test
from nova.compute import api as compute_api
from nova.scheduler import driver
-from nova.scheduler import zone_aware_scheduler
+from nova.scheduler import abstract_scheduler
from nova.scheduler import zone_manager
@@ -60,7 +60,7 @@ def fake_zone_manager_service_states(num_hosts):
return states
-class FakeZoneAwareScheduler(zone_aware_scheduler.ZoneAwareScheduler):
+class FakeAbstractScheduler(abstract_scheduler.AbstractScheduler):
# No need to stub anything at the moment
pass
@@ -161,15 +161,15 @@ def fake_zone_get_all(context):
]
-class ZoneAwareSchedulerTestCase(test.TestCase):
- """Test case for Zone Aware Scheduler."""
+class AbstractSchedulerTestCase(test.TestCase):
+ """Test case for Abstract Scheduler."""
- def test_zone_aware_scheduler(self):
+ def test_abstract_scheduler(self):
"""
Create a nested set of FakeZones, try to build multiple instances
and ensure that a select call returns the appropriate build plan.
"""
- sched = FakeZoneAwareScheduler()
+ sched = FakeAbstractScheduler()
self.stubs.Set(sched, '_call_zone_method', fake_call_zone_method)
self.stubs.Set(nova.db, 'zone_get_all', fake_zone_get_all)
@@ -194,7 +194,7 @@ class ZoneAwareSchedulerTestCase(test.TestCase):
properly adjusted based on the scale/offset in the zone
db entries.
"""
- sched = FakeZoneAwareScheduler()
+ sched = FakeAbstractScheduler()
child_results = fake_call_zone_method(None, None, None, None)
zones = fake_zone_get_all(None)
sched._adjust_child_weights(child_results, zones)
@@ -209,11 +209,11 @@ class ZoneAwareSchedulerTestCase(test.TestCase):
if zone == 'zone3': # Scale x1000
self.assertEqual(scaled.pop(0), w)
- def test_empty_zone_aware_scheduler(self):
+ def test_empty_abstract_scheduler(self):
"""
Ensure empty hosts & child_zones result in NoValidHosts exception.
"""
- sched = FakeZoneAwareScheduler()
+ sched = FakeAbstractScheduler()
self.stubs.Set(sched, '_call_zone_method', fake_empty_call_zone_method)
self.stubs.Set(nova.db, 'zone_get_all', fake_zone_get_all)
@@ -231,7 +231,7 @@ class ZoneAwareSchedulerTestCase(test.TestCase):
If the zone_blob hint was passed in, don't re-schedule.
"""
global was_called
- sched = FakeZoneAwareScheduler()
+ sched = FakeAbstractScheduler()
was_called = False
self.stubs.Set(sched, '_provision_resource', fake_provision_resource)
request_spec = {
@@ -248,7 +248,7 @@ class ZoneAwareSchedulerTestCase(test.TestCase):
def test_provision_resource_local(self):
"""Provision a resource locally or remotely."""
global was_called
- sched = FakeZoneAwareScheduler()
+ sched = FakeAbstractScheduler()
was_called = False
self.stubs.Set(sched, '_provision_resource_locally',
fake_provision_resource_locally)
@@ -260,7 +260,7 @@ class ZoneAwareSchedulerTestCase(test.TestCase):
def test_provision_resource_remote(self):
"""Provision a resource locally or remotely."""
global was_called
- sched = FakeZoneAwareScheduler()
+ sched = FakeAbstractScheduler()
was_called = False
self.stubs.Set(sched, '_provision_resource_from_blob',
fake_provision_resource_from_blob)
@@ -272,9 +272,9 @@ class ZoneAwareSchedulerTestCase(test.TestCase):
def test_provision_resource_from_blob_empty(self):
"""Provision a resource locally or remotely given no hints."""
global was_called
- sched = FakeZoneAwareScheduler()
+ sched = FakeAbstractScheduler()
request_spec = {}
- self.assertRaises(zone_aware_scheduler.InvalidBlob,
+ self.assertRaises(abstract_scheduler.InvalidBlob,
sched._provision_resource_from_blob,
None, {}, 1, {}, {})
@@ -283,7 +283,7 @@ class ZoneAwareSchedulerTestCase(test.TestCase):
Provision a resource locally or remotely when blob hint passed in.
"""
global was_called
- sched = FakeZoneAwareScheduler()
+ sched = FakeAbstractScheduler()
was_called = False
def fake_create_db_entry_for_new_instance(self, context,
@@ -317,7 +317,7 @@ class ZoneAwareSchedulerTestCase(test.TestCase):
passed in.
"""
global was_called
- sched = FakeZoneAwareScheduler()
+ sched = FakeAbstractScheduler()
self.stubs.Set(sched, '_decrypt_blob',
fake_decrypt_blob_returns_child_info)
was_called = False
@@ -336,7 +336,7 @@ class ZoneAwareSchedulerTestCase(test.TestCase):
from an immediate child.
"""
global was_called
- sched = FakeZoneAwareScheduler()
+ sched = FakeAbstractScheduler()
was_called = False
self.stubs.Set(sched, '_ask_child_zone_to_create_instance',
fake_ask_child_zone_to_create_instance)
@@ -350,14 +350,14 @@ class ZoneAwareSchedulerTestCase(test.TestCase):
def test_decrypt_blob(self):
"""Test that the decrypt method works."""
- fixture = FakeZoneAwareScheduler()
+ fixture = FakeAbstractScheduler()
test_data = {"foo": "bar"}
class StubDecryptor(object):
def decryptor(self, key):
return lambda blob: blob
- self.stubs.Set(zone_aware_scheduler, 'crypto',
+ self.stubs.Set(abstract_scheduler, 'crypto',
StubDecryptor())
self.assertEqual(fixture._decrypt_blob(test_data),
diff --git a/nova/tests/scheduler/test_least_cost_scheduler.py b/nova/tests/scheduler/test_least_cost_scheduler.py
index fbe6b2f77..de7581d0a 100644
--- a/nova/tests/scheduler/test_least_cost_scheduler.py
+++ b/nova/tests/scheduler/test_least_cost_scheduler.py
@@ -18,7 +18,7 @@ Tests For Least Cost Scheduler
from nova import test
from nova.scheduler import least_cost
-from nova.tests.scheduler import test_zone_aware_scheduler
+from nova.tests.scheduler import test_abstract_scheduler
MB = 1024 * 1024
@@ -70,7 +70,7 @@ class LeastCostSchedulerTestCase(test.TestCase):
zone_manager = FakeZoneManager()
- states = test_zone_aware_scheduler.fake_zone_manager_service_states(
+ states = test_abstract_scheduler.fake_zone_manager_service_states(
num_hosts=10)
zone_manager.service_states = states
diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py
index 7a26fd1bb..158df2a27 100644
--- a/nova/tests/scheduler/test_scheduler.py
+++ b/nova/tests/scheduler/test_scheduler.py
@@ -36,8 +36,9 @@ from nova import test
from nova import rpc
from nova import utils
from nova.scheduler import api
-from nova.scheduler import manager
from nova.scheduler import driver
+from nova.scheduler import manager
+from nova.scheduler import multi
from nova.compute import power_state
@@ -256,7 +257,9 @@ class SimpleDriverTestCase(test.TestCase):
def _create_instance(self, **kwargs):
"""Create a test instance"""
inst = {}
- inst['image_id'] = 1
+ # NOTE(jk0): If an integer is passed as the image_ref, the image
+ # service will use the default image service (in this case, the fake).
+ inst['image_ref'] = '1'
inst['reservation_id'] = 'r-fakeres'
inst['user_id'] = self.user_id
inst['project_id'] = self.project_id
@@ -391,7 +394,7 @@ class SimpleDriverTestCase(test.TestCase):
compute1.kill()
compute2.kill()
- def test_wont_sechedule_if_specified_host_is_down_no_queue(self):
+ def test_wont_schedule_if_specified_host_is_down_no_queue(self):
compute1 = service.Service('host1',
'nova-compute',
'compute',
@@ -643,10 +646,13 @@ class SimpleDriverTestCase(test.TestCase):
self.mox.StubOutWithMock(driver_i, '_live_migration_dest_check')
self.mox.StubOutWithMock(driver_i, '_live_migration_common_check')
driver_i._live_migration_src_check(nocare, nocare)
- driver_i._live_migration_dest_check(nocare, nocare, i_ref['host'])
- driver_i._live_migration_common_check(nocare, nocare, i_ref['host'])
+ driver_i._live_migration_dest_check(nocare, nocare,
+ i_ref['host'], False)
+ driver_i._live_migration_common_check(nocare, nocare,
+ i_ref['host'], False)
self.mox.StubOutWithMock(rpc, 'cast', use_mock_anything=True)
- kwargs = {'instance_id': instance_id, 'dest': i_ref['host']}
+ kwargs = {'instance_id': instance_id, 'dest': i_ref['host'],
+ 'block_migration': False}
rpc.cast(self.context,
db.queue_get_for(nocare, FLAGS.compute_topic, i_ref['host']),
{"method": 'live_migration', "args": kwargs})
@@ -654,7 +660,8 @@ class SimpleDriverTestCase(test.TestCase):
self.mox.ReplayAll()
self.scheduler.live_migration(self.context, FLAGS.compute_topic,
instance_id=instance_id,
- dest=i_ref['host'])
+ dest=i_ref['host'],
+ block_migration=False)
i_ref = db.instance_get(self.context, instance_id)
self.assertTrue(i_ref['state_description'] == 'migrating')
@@ -735,7 +742,7 @@ class SimpleDriverTestCase(test.TestCase):
self.assertRaises(exception.ComputeServiceUnavailable,
self.scheduler.driver._live_migration_dest_check,
- self.context, i_ref, i_ref['host'])
+ self.context, i_ref, i_ref['host'], False)
db.instance_destroy(self.context, instance_id)
db.service_destroy(self.context, s_ref['id'])
@@ -748,7 +755,7 @@ class SimpleDriverTestCase(test.TestCase):
self.assertRaises(exception.UnableToMigrateToSelf,
self.scheduler.driver._live_migration_dest_check,
- self.context, i_ref, i_ref['host'])
+ self.context, i_ref, i_ref['host'], False)
db.instance_destroy(self.context, instance_id)
db.service_destroy(self.context, s_ref['id'])
@@ -756,15 +763,33 @@ class SimpleDriverTestCase(test.TestCase):
def test_live_migration_dest_check_service_lack_memory(self):
"""Confirms exception raises when dest doesn't have enough memory."""
instance_id = self._create_instance()
+ instance_id2 = self._create_instance(host='somewhere',
+ memory_mb=12)
i_ref = db.instance_get(self.context, instance_id)
- s_ref = self._create_compute_service(host='somewhere',
- memory_mb_used=12)
+ s_ref = self._create_compute_service(host='somewhere')
self.assertRaises(exception.MigrationError,
self.scheduler.driver._live_migration_dest_check,
- self.context, i_ref, 'somewhere')
+ self.context, i_ref, 'somewhere', False)
db.instance_destroy(self.context, instance_id)
+ db.instance_destroy(self.context, instance_id2)
+ db.service_destroy(self.context, s_ref['id'])
+
+ def test_block_migration_dest_check_service_lack_disk(self):
+ """Confirms exception raises when dest doesn't have enough disk."""
+ instance_id = self._create_instance()
+ instance_id2 = self._create_instance(host='somewhere',
+ local_gb=70)
+ i_ref = db.instance_get(self.context, instance_id)
+ s_ref = self._create_compute_service(host='somewhere')
+
+ self.assertRaises(exception.MigrationError,
+ self.scheduler.driver._live_migration_dest_check,
+ self.context, i_ref, 'somewhere', True)
+
+ db.instance_destroy(self.context, instance_id)
+ db.instance_destroy(self.context, instance_id2)
db.service_destroy(self.context, s_ref['id'])
def test_live_migration_dest_check_service_works_correctly(self):
@@ -776,7 +801,8 @@ class SimpleDriverTestCase(test.TestCase):
ret = self.scheduler.driver._live_migration_dest_check(self.context,
i_ref,
- 'somewhere')
+ 'somewhere',
+ False)
self.assertTrue(ret is None)
db.instance_destroy(self.context, instance_id)
db.service_destroy(self.context, s_ref['id'])
@@ -809,9 +835,10 @@ class SimpleDriverTestCase(test.TestCase):
"args": {'filename': fpath}})
self.mox.ReplayAll()
- self.assertRaises(exception.SourceHostUnavailable,
+ #self.assertRaises(exception.SourceHostUnavailable,
+ self.assertRaises(exception.FileNotFound,
self.scheduler.driver._live_migration_common_check,
- self.context, i_ref, dest)
+ self.context, i_ref, dest, False)
db.instance_destroy(self.context, instance_id)
db.service_destroy(self.context, s_ref['id'])
@@ -835,7 +862,7 @@ class SimpleDriverTestCase(test.TestCase):
self.mox.ReplayAll()
self.assertRaises(exception.InvalidHypervisorType,
self.scheduler.driver._live_migration_common_check,
- self.context, i_ref, dest)
+ self.context, i_ref, dest, False)
db.instance_destroy(self.context, instance_id)
db.service_destroy(self.context, s_ref['id'])
@@ -861,7 +888,7 @@ class SimpleDriverTestCase(test.TestCase):
self.mox.ReplayAll()
self.assertRaises(exception.DestinationHypervisorTooOld,
self.scheduler.driver._live_migration_common_check,
- self.context, i_ref, dest)
+ self.context, i_ref, dest, False)
db.instance_destroy(self.context, instance_id)
db.service_destroy(self.context, s_ref['id'])
@@ -893,7 +920,8 @@ class SimpleDriverTestCase(test.TestCase):
try:
self.scheduler.driver._live_migration_common_check(self.context,
i_ref,
- dest)
+ dest,
+ False)
except rpc.RemoteError, e:
c = (e.message.find(_("doesn't have compatibility to")) >= 0)
@@ -903,6 +931,25 @@ class SimpleDriverTestCase(test.TestCase):
db.service_destroy(self.context, s_ref2['id'])
+class MultiDriverTestCase(SimpleDriverTestCase):
+ """Test case for multi driver."""
+
+ def setUp(self):
+ super(MultiDriverTestCase, self).setUp()
+ self.flags(connection_type='fake',
+ stub_network=True,
+ max_cores=4,
+ max_gigabytes=4,
+ network_manager='nova.network.manager.FlatManager',
+ volume_driver='nova.volume.driver.FakeISCSIDriver',
+ compute_scheduler_driver=('nova.scheduler.simple'
+ '.SimpleScheduler'),
+ volume_scheduler_driver=('nova.scheduler.simple'
+ '.SimpleScheduler'),
+ scheduler_driver='nova.scheduler.multi.MultiScheduler')
+ self.scheduler = manager.SchedulerManager()
+
+
class FakeZone(object):
def __init__(self, id, api_url, username, password):
self.id = id
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index 73c9bd78d..4f5d36f14 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -632,7 +632,7 @@ class ComputeTestCase(test.TestCase):
vid = i_ref['volumes'][i]['id']
volmock.setup_compute_volume(c, vid).InAnyOrder('g1')
drivermock.plug_vifs(i_ref, [])
- drivermock.ensure_filtering_rules_for_instance(i_ref)
+ drivermock.ensure_filtering_rules_for_instance(i_ref, [])
self.compute.db = dbmock
self.compute.volume_manager = volmock
@@ -657,7 +657,7 @@ class ComputeTestCase(test.TestCase):
self.mox.StubOutWithMock(compute_manager.LOG, 'info')
compute_manager.LOG.info(_("%s has no volume."), i_ref['hostname'])
drivermock.plug_vifs(i_ref, [])
- drivermock.ensure_filtering_rules_for_instance(i_ref)
+ drivermock.ensure_filtering_rules_for_instance(i_ref, [])
self.compute.db = dbmock
self.compute.driver = drivermock
@@ -714,11 +714,15 @@ class ComputeTestCase(test.TestCase):
dbmock.queue_get_for(c, FLAGS.compute_topic, i_ref['host']).\
AndReturn(topic)
rpc.call(c, topic, {"method": "pre_live_migration",
- "args": {'instance_id': i_ref['id']}})
+ "args": {'instance_id': i_ref['id'],
+ 'block_migration': False,
+ 'disk': None}})
+
self.mox.StubOutWithMock(self.compute.driver, 'live_migration')
self.compute.driver.live_migration(c, i_ref, i_ref['host'],
self.compute.post_live_migration,
- self.compute.recover_live_migration)
+ self.compute.rollback_live_migration,
+ False)
self.compute.db = dbmock
self.mox.ReplayAll()
@@ -739,13 +743,18 @@ class ComputeTestCase(test.TestCase):
dbmock.queue_get_for(c, FLAGS.compute_topic, i_ref['host']).\
AndReturn(topic)
rpc.call(c, topic, {"method": "pre_live_migration",
- "args": {'instance_id': i_ref['id']}}).\
+ "args": {'instance_id': i_ref['id'],
+ 'block_migration': False,
+ 'disk': None}}).\
AndRaise(rpc.RemoteError('', '', ''))
dbmock.instance_update(c, i_ref['id'], {'state_description': 'running',
'state': power_state.RUNNING,
'host': i_ref['host']})
for v in i_ref['volumes']:
dbmock.volume_update(c, v['id'], {'status': 'in-use'})
+ # mock for volume_api.remove_from_compute
+ rpc.call(c, topic, {"method": "remove_volume",
+ "args": {'volume_id': v['id']}})
self.compute.db = dbmock
self.mox.ReplayAll()
@@ -766,7 +775,9 @@ class ComputeTestCase(test.TestCase):
AndReturn(topic)
self.mox.StubOutWithMock(rpc, 'call')
rpc.call(c, topic, {"method": "pre_live_migration",
- "args": {'instance_id': i_ref['id']}}).\
+ "args": {'instance_id': i_ref['id'],
+ 'block_migration': False,
+ 'disk': None}}).\
AndRaise(rpc.RemoteError('', '', ''))
dbmock.instance_update(c, i_ref['id'], {'state_description': 'running',
'state': power_state.RUNNING,
@@ -791,11 +802,14 @@ class ComputeTestCase(test.TestCase):
dbmock.queue_get_for(c, FLAGS.compute_topic, i_ref['host']).\
AndReturn(topic)
rpc.call(c, topic, {"method": "pre_live_migration",
- "args": {'instance_id': i_ref['id']}})
+ "args": {'instance_id': i_ref['id'],
+ 'block_migration': False,
+ 'disk': None}})
self.mox.StubOutWithMock(self.compute.driver, 'live_migration')
self.compute.driver.live_migration(c, i_ref, i_ref['host'],
self.compute.post_live_migration,
- self.compute.recover_live_migration)
+ self.compute.rollback_live_migration,
+ False)
self.compute.db = dbmock
self.mox.ReplayAll()
@@ -829,6 +843,10 @@ class ComputeTestCase(test.TestCase):
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.mox.StubOutWithMock(rpc, 'call')
+ rpc.call(c, db.queue_get_for(c, FLAGS.compute_topic, dest),
+ {"method": "post_live_migration_at_destination",
+ "args": {'instance_id': i_ref['id'], 'block_migration': False}})
# executing
self.mox.ReplayAll()
@@ -1323,6 +1341,69 @@ class ComputeTestCase(test.TestCase):
db.instance_destroy(c, instance_id2)
db.instance_destroy(c, instance_id3)
+ def test_get_all_by_metadata(self):
+ """Test searching instances by metadata"""
+
+ c = context.get_admin_context()
+ instance_id0 = self._create_instance()
+ instance_id1 = self._create_instance({
+ 'metadata': {'key1': 'value1'}})
+ instance_id2 = self._create_instance({
+ 'metadata': {'key2': 'value2'}})
+ instance_id3 = self._create_instance({
+ 'metadata': {'key3': 'value3'}})
+ instance_id4 = self._create_instance({
+ 'metadata': {'key3': 'value3',
+ 'key4': 'value4'}})
+
+ # get all instances
+ instances = self.compute_api.get_all(c,
+ search_opts={'metadata': {}})
+ self.assertEqual(len(instances), 5)
+
+ # wrong key/value combination
+ instances = self.compute_api.get_all(c,
+ search_opts={'metadata': {'key1': 'value3'}})
+ self.assertEqual(len(instances), 0)
+
+ # non-existing keys
+ instances = self.compute_api.get_all(c,
+ search_opts={'metadata': {'key5': 'value1'}})
+ self.assertEqual(len(instances), 0)
+
+ # find existing instance
+ instances = self.compute_api.get_all(c,
+ search_opts={'metadata': {'key2': 'value2'}})
+ self.assertEqual(len(instances), 1)
+ self.assertEqual(instances[0].id, instance_id2)
+
+ instances = self.compute_api.get_all(c,
+ search_opts={'metadata': {'key3': 'value3'}})
+ self.assertEqual(len(instances), 2)
+ instance_ids = [instance.id for instance in instances]
+ self.assertTrue(instance_id3 in instance_ids)
+ self.assertTrue(instance_id4 in instance_ids)
+
+ # multiple criterias as a dict
+ instances = self.compute_api.get_all(c,
+ search_opts={'metadata': {'key3': 'value3',
+ 'key4': 'value4'}})
+ self.assertEqual(len(instances), 1)
+ self.assertEqual(instances[0].id, instance_id4)
+
+ # multiple criterias as a list
+ instances = self.compute_api.get_all(c,
+ search_opts={'metadata': [{'key4': 'value4'},
+ {'key3': 'value3'}]})
+ self.assertEqual(len(instances), 1)
+ self.assertEqual(instances[0].id, instance_id4)
+
+ db.instance_destroy(c, instance_id0)
+ db.instance_destroy(c, instance_id1)
+ db.instance_destroy(c, instance_id2)
+ db.instance_destroy(c, instance_id3)
+ db.instance_destroy(c, instance_id4)
+
@staticmethod
def _parse_db_block_device_mapping(bdm_ref):
attr_list = ('delete_on_termination', 'device_name', 'no_device',
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index 2180cf4f0..688518bb8 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -21,6 +21,7 @@ import os
import re
import shutil
import sys
+import tempfile
from xml.etree.ElementTree import fromstring as xml_to_tree
from xml.dom.minidom import parseString as xml_to_dom
@@ -49,18 +50,19 @@ def _create_network_info(count=1, ipv6=None):
if ipv6 is None:
ipv6 = FLAGS.use_ipv6
fake = 'fake'
- fake_ip = '0.0.0.0/0'
- fake_ip_2 = '0.0.0.1/0'
- fake_ip_3 = '0.0.0.1/0'
+ fake_ip = '10.11.12.13'
+ fake_ip_2 = '0.0.0.1'
+ fake_ip_3 = '0.0.0.1'
fake_vlan = 100
fake_bridge_interface = 'eth0'
network = {'bridge': fake,
'cidr': fake_ip,
'cidr_v6': fake_ip,
+ 'gateway_v6': fake,
'vlan': fake_vlan,
'bridge_interface': fake_bridge_interface}
mapping = {'mac': fake,
- 'dhcp_server': fake,
+ 'dhcp_server': '10.0.0.1',
'gateway': fake,
'gateway6': fake,
'ips': [{'ip': fake_ip}, {'ip': fake_ip}]}
@@ -71,12 +73,12 @@ def _create_network_info(count=1, ipv6=None):
return [(network, mapping) for x in xrange(0, count)]
-def _setup_networking(instance_id, ip='1.2.3.4'):
+def _setup_networking(instance_id, ip='1.2.3.4', mac='56:12:12:12:12:12'):
ctxt = context.get_admin_context()
network_ref = db.project_get_networks(ctxt,
'fake',
associate=True)[0]
- vif = {'address': '56:12:12:12:12:12',
+ vif = {'address': mac,
'network_id': network_ref['id'],
'instance_id': instance_id}
vif_ref = db.virtual_interface_create(ctxt, vif)
@@ -273,15 +275,14 @@ class LibvirtConnTestCase(test.TestCase):
conn = connection.LibvirtConnection(True)
instance_ref = db.instance_create(self.context, self.test_instance)
- result = conn._prepare_xml_info(instance_ref, False)
- self.assertFalse(result['nics'])
-
- result = conn._prepare_xml_info(instance_ref, False,
- _create_network_info())
+ result = conn._prepare_xml_info(instance_ref,
+ _create_network_info(),
+ False)
self.assertTrue(len(result['nics']) == 1)
- result = conn._prepare_xml_info(instance_ref, False,
- _create_network_info(2))
+ result = conn._prepare_xml_info(instance_ref,
+ _create_network_info(2),
+ False)
self.assertTrue(len(result['nics']) == 2)
def test_xml_and_uri_no_ramdisk_no_kernel(self):
@@ -408,16 +409,16 @@ class LibvirtConnTestCase(test.TestCase):
network_info = _create_network_info(2)
conn = connection.LibvirtConnection(True)
instance_ref = db.instance_create(self.context, instance_data)
- xml = conn.to_xml(instance_ref, False, network_info)
+ xml = conn.to_xml(instance_ref, network_info, False)
tree = xml_to_tree(xml)
interfaces = tree.findall("./devices/interface")
self.assertEquals(len(interfaces), 2)
parameters = interfaces[0].findall('./filterref/parameter')
self.assertEquals(interfaces[0].get('type'), 'bridge')
self.assertEquals(parameters[0].get('name'), 'IP')
- self.assertEquals(parameters[0].get('value'), '0.0.0.0/0')
+ self.assertEquals(parameters[0].get('value'), '10.11.12.13')
self.assertEquals(parameters[1].get('name'), 'DHCPSERVER')
- self.assertEquals(parameters[1].get('value'), 'fake')
+ self.assertEquals(parameters[1].get('value'), '10.0.0.1')
def _check_xml_and_container(self, instance):
user_context = context.RequestContext(self.user_id,
@@ -431,7 +432,8 @@ class LibvirtConnTestCase(test.TestCase):
uri = conn.get_uri()
self.assertEquals(uri, 'lxc:///')
- xml = conn.to_xml(instance_ref)
+ network_info = _create_network_info()
+ xml = conn.to_xml(instance_ref, network_info)
tree = xml_to_tree(xml)
check = [
@@ -528,17 +530,20 @@ class LibvirtConnTestCase(test.TestCase):
uri = conn.get_uri()
self.assertEquals(uri, expected_uri)
- xml = conn.to_xml(instance_ref, rescue)
+ network_info = _create_network_info()
+ xml = conn.to_xml(instance_ref, network_info, rescue)
tree = xml_to_tree(xml)
for i, (check, expected_result) in enumerate(checks):
self.assertEqual(check(tree),
expected_result,
- '%s failed check %d' % (xml, i))
+ '%s != %s failed check %d' %
+ (check(tree), expected_result, i))
for i, (check, expected_result) in enumerate(common_checks):
self.assertEqual(check(tree),
expected_result,
- '%s failed common check %d' % (xml, i))
+ '%s != %s failed common check %d' %
+ (check(tree), expected_result, i))
# This test is supposed to make sure we don't
# override a specifically set uri
@@ -623,7 +628,7 @@ class LibvirtConnTestCase(test.TestCase):
return
# Preparing mocks
- def fake_none(self):
+ def fake_none(self, *args):
return
def fake_raise(self):
@@ -640,6 +645,7 @@ class LibvirtConnTestCase(test.TestCase):
self.create_fake_libvirt_mock()
instance_ref = db.instance_create(self.context, self.test_instance)
+ network_info = _create_network_info()
# Start test
self.mox.ReplayAll()
@@ -649,6 +655,7 @@ class LibvirtConnTestCase(test.TestCase):
conn.firewall_driver.setattr('prepare_instance_filter', fake_none)
conn.firewall_driver.setattr('instance_filter_exists', fake_none)
conn.ensure_filtering_rules_for_instance(instance_ref,
+ network_info,
time=fake_timer)
except exception.Error, e:
c1 = (0 <= e.message.find('Timeout migrating for'))
@@ -690,17 +697,20 @@ 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.StubOutWithMock(self.compute, "recover_live_migration")
+ self.mox.StubOutWithMock(self.compute, "rollback_live_migration")
+# self.compute.recover_live_migration(self.context, instance_ref,
+# dest='dest')
+ self.compute.rollback_live_migration(self.context, instance_ref,
+ 'dest', False)
+
+ #start test
self.mox.ReplayAll()
conn = connection.LibvirtConnection(False)
self.assertRaises(libvirt.libvirtError,
conn._live_migration,
- self.context, instance_ref, 'dest', '',
- self.compute.recover_live_migration)
+ self.context, instance_ref, 'dest', False,
+ self.compute.rollback_live_migration)
instance_ref = db.instance_get(self.context, instance_ref['id'])
self.assertTrue(instance_ref['state_description'] == 'running')
@@ -711,6 +721,95 @@ class LibvirtConnTestCase(test.TestCase):
db.volume_destroy(self.context, volume_ref['id'])
db.instance_destroy(self.context, instance_ref['id'])
+ def test_pre_block_migration_works_correctly(self):
+ """Confirms pre_block_migration works correctly."""
+
+ # Skip if non-libvirt environment
+ if not self.lazy_load_library_exists():
+ return
+
+ # Replace instances_path since this testcase creates tmpfile
+ tmpdir = tempfile.mkdtemp()
+ store = FLAGS.instances_path
+ FLAGS.instances_path = tmpdir
+
+ # Test data
+ instance_ref = db.instance_create(self.context, self.test_instance)
+ dummyjson = '[{"path": "%s/disk", "local_gb": "10G", "type": "raw"}]'
+
+ # Preparing mocks
+ # qemu-img should be mockd since test environment might not have
+ # large disk space.
+ self.mox.StubOutWithMock(utils, "execute")
+ utils.execute('sudo', 'qemu-img', 'create', '-f', 'raw',
+ '%s/%s/disk' % (tmpdir, instance_ref.name), '10G')
+
+ self.mox.ReplayAll()
+ conn = connection.LibvirtConnection(False)
+ conn.pre_block_migration(self.context, instance_ref,
+ dummyjson % tmpdir)
+
+ self.assertTrue(os.path.exists('%s/%s/' %
+ (tmpdir, instance_ref.name)))
+
+ shutil.rmtree(tmpdir)
+ db.instance_destroy(self.context, instance_ref['id'])
+ # Restore FLAGS.instances_path
+ FLAGS.instances_path = store
+
+ def test_get_instance_disk_info_works_correctly(self):
+ """Confirms pre_block_migration works correctly."""
+ # Skip if non-libvirt environment
+ if not self.lazy_load_library_exists():
+ return
+
+ # Test data
+ instance_ref = db.instance_create(self.context, self.test_instance)
+ dummyxml = ("<domain type='kvm'><name>instance-0000000a</name>"
+ "<devices>"
+ "<disk type='file'><driver name='qemu' type='raw'/>"
+ "<source file='/test/disk'/>"
+ "<target dev='vda' bus='virtio'/></disk>"
+ "<disk type='file'><driver name='qemu' type='qcow2'/>"
+ "<source file='/test/disk.local'/>"
+ "<target dev='vdb' bus='virtio'/></disk>"
+ "</devices></domain>")
+
+ ret = ("image: /test/disk\nfile format: raw\n"
+ "virtual size: 20G (21474836480 bytes)\ndisk size: 3.1G\n")
+
+ # Preparing mocks
+ vdmock = self.mox.CreateMock(libvirt.virDomain)
+ self.mox.StubOutWithMock(vdmock, "XMLDesc")
+ vdmock.XMLDesc(0).AndReturn(dummyxml)
+
+ def fake_lookup(instance_name):
+ if instance_name == instance_ref.name:
+ return vdmock
+ self.create_fake_libvirt_mock(lookupByName=fake_lookup)
+
+ self.mox.StubOutWithMock(os.path, "getsize")
+ # based on above testdata, one is raw image, so getsize is mocked.
+ os.path.getsize("/test/disk").AndReturn(10 * 1024 * 1024 * 1024)
+ # another is qcow image, so qemu-img should be mocked.
+ self.mox.StubOutWithMock(utils, "execute")
+ utils.execute('sudo', 'qemu-img', 'info', '/test/disk.local').\
+ AndReturn((ret, ''))
+
+ self.mox.ReplayAll()
+ conn = connection.LibvirtConnection(False)
+ info = conn.get_instance_disk_info(self.context, instance_ref)
+ info = utils.loads(info)
+
+ self.assertTrue(info[0]['type'] == 'raw' and
+ info[1]['type'] == 'qcow2' and
+ info[0]['path'] == '/test/disk' and
+ info[1]['path'] == '/test/disk.local' and
+ info[0]['local_gb'] == '10G' and
+ info[1]['local_gb'] == '20G')
+
+ db.instance_destroy(self.context, instance_ref['id'])
+
def test_spawn_with_network_info(self):
# Skip if non-libvirt environment
if not self.lazy_load_library_exists():
@@ -884,7 +983,11 @@ class IptablesFirewallTestCase(test.TestCase):
def test_static_filters(self):
instance_ref = self._create_instance_ref()
- _setup_networking(instance_ref['id'], self.test_ip)
+ src_instance_ref = self._create_instance_ref()
+ src_ip = '10.11.12.14'
+ src_mac = '56:12:12:12:12:13'
+ _setup_networking(instance_ref['id'], self.test_ip, src_mac)
+ _setup_networking(src_instance_ref['id'], src_ip)
admin_ctxt = context.get_admin_context()
secgroup = db.security_group_create(admin_ctxt,
@@ -893,6 +996,12 @@ class IptablesFirewallTestCase(test.TestCase):
'name': 'testgroup',
'description': 'test group'})
+ src_secgroup = db.security_group_create(admin_ctxt,
+ {'user_id': 'fake',
+ 'project_id': 'fake',
+ 'name': 'testsourcegroup',
+ 'description': 'src group'})
+
db.security_group_rule_create(admin_ctxt,
{'parent_group_id': secgroup['id'],
'protocol': 'icmp',
@@ -914,9 +1023,19 @@ class IptablesFirewallTestCase(test.TestCase):
'to_port': 81,
'cidr': '192.168.10.0/24'})
+ db.security_group_rule_create(admin_ctxt,
+ {'parent_group_id': secgroup['id'],
+ 'protocol': 'tcp',
+ 'from_port': 80,
+ 'to_port': 81,
+ 'group_id': src_secgroup['id']})
+
db.instance_add_security_group(admin_ctxt, instance_ref['id'],
secgroup['id'])
+ db.instance_add_security_group(admin_ctxt, src_instance_ref['id'],
+ src_secgroup['id'])
instance_ref = db.instance_get(admin_ctxt, instance_ref['id'])
+ src_instance_ref = db.instance_get(admin_ctxt, src_instance_ref['id'])
# self.fw.add_instance(instance_ref)
def fake_iptables_execute(*cmd, **kwargs):
@@ -942,8 +1061,9 @@ class IptablesFirewallTestCase(test.TestCase):
from nova.network import linux_net
linux_net.iptables_manager.execute = fake_iptables_execute
- self.fw.prepare_instance_filter(instance_ref)
- self.fw.apply_instance_filter(instance_ref)
+ network_info = _create_network_info()
+ self.fw.prepare_instance_filter(instance_ref, network_info)
+ self.fw.apply_instance_filter(instance_ref, network_info)
in_rules = filter(lambda l: not l.startswith('#'),
self.in_filter_rules)
@@ -969,17 +1089,22 @@ class IptablesFirewallTestCase(test.TestCase):
self.assertTrue(security_group_chain,
"The security group chain wasn't added")
- regex = re.compile('-A .* -p icmp -s 192.168.11.0/24 -j ACCEPT')
+ regex = re.compile('-A .* -j ACCEPT -p icmp -s 192.168.11.0/24')
self.assertTrue(len(filter(regex.match, self.out_rules)) > 0,
"ICMP acceptance rule wasn't added")
- regex = re.compile('-A .* -p icmp -s 192.168.11.0/24 -m icmp '
- '--icmp-type 8 -j ACCEPT')
+ regex = re.compile('-A .* -j ACCEPT -p icmp -m icmp --icmp-type 8'
+ ' -s 192.168.11.0/24')
self.assertTrue(len(filter(regex.match, self.out_rules)) > 0,
"ICMP Echo Request acceptance rule wasn't added")
- regex = re.compile('-A .* -p tcp -s 192.168.10.0/24 -m multiport '
- '--dports 80:81 -j ACCEPT')
+ regex = re.compile('-A .* -j ACCEPT -p tcp -m multiport '
+ '--dports 80:81 -s %s' % (src_ip,))
+ self.assertTrue(len(filter(regex.match, self.out_rules)) > 0,
+ "TCP port 80/81 acceptance rule wasn't added")
+
+ regex = re.compile('-A .* -j ACCEPT -p tcp '
+ '-m multiport --dports 80:81 -s 192.168.10.0/24')
self.assertTrue(len(filter(regex.match, self.out_rules)) > 0,
"TCP port 80/81 acceptance rule wasn't added")
db.instance_destroy(admin_ctxt, instance_ref['id'])
@@ -1008,7 +1133,7 @@ class IptablesFirewallTestCase(test.TestCase):
ipv6_len = len(self.fw.iptables.ipv6['filter'].rules)
inst_ipv4, inst_ipv6 = self.fw.instance_rules(instance_ref,
network_info)
- self.fw.add_filters_for_instance(instance_ref, network_info)
+ self.fw.prepare_instance_filter(instance_ref, network_info)
ipv4 = self.fw.iptables.ipv4['filter'].rules
ipv6 = self.fw.iptables.ipv6['filter'].rules
ipv4_network_rules = len(ipv4) - len(inst_ipv4) - ipv4_len
@@ -1023,7 +1148,7 @@ class IptablesFirewallTestCase(test.TestCase):
self.mox.StubOutWithMock(self.fw,
'add_filters_for_instance',
use_mock_anything=True)
- self.fw.add_filters_for_instance(instance_ref, mox.IgnoreArg())
+ self.fw.prepare_instance_filter(instance_ref, mox.IgnoreArg())
self.fw.instances[instance_ref['id']] = instance_ref
self.mox.ReplayAll()
self.fw.do_refresh_security_group_rules("fake")
@@ -1043,11 +1168,12 @@ class IptablesFirewallTestCase(test.TestCase):
instance_ref = self._create_instance_ref()
_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)
+ network_info = _create_network_info()
+ self.fw.setup_basic_filtering(instance_ref, network_info)
+ self.fw.prepare_instance_filter(instance_ref, network_info)
+ self.fw.apply_instance_filter(instance_ref, network_info)
original_filter_count = len(fakefilter.filters)
- self.fw.unfilter_instance(instance_ref)
+ self.fw.unfilter_instance(instance_ref, network_info)
# should undefine just the instance filter
self.assertEqual(original_filter_count - len(fakefilter.filters), 1)
@@ -1057,14 +1183,14 @@ class IptablesFirewallTestCase(test.TestCase):
def test_provider_firewall_rules(self):
# setup basic instance data
instance_ref = self._create_instance_ref()
- nw_info = _create_network_info(1)
_setup_networking(instance_ref['id'], self.test_ip)
# FRAGILE: peeks at how the firewall names chains
chain_name = 'inst-%s' % instance_ref['id']
# create a firewall via setup_basic_filtering like libvirt_conn.spawn
# should have a chain with 0 rules
- self.fw.setup_basic_filtering(instance_ref, network_info=nw_info)
+ network_info = _create_network_info(1)
+ self.fw.setup_basic_filtering(instance_ref, network_info)
self.assertTrue('provider' in self.fw.iptables.ipv4['filter'].chains)
rules = [rule for rule in self.fw.iptables.ipv4['filter'].rules
if rule.chain == 'provider']
@@ -1094,8 +1220,8 @@ class IptablesFirewallTestCase(test.TestCase):
self.assertEqual(2, len(rules))
# create the instance filter and make sure it has a jump rule
- self.fw.prepare_instance_filter(instance_ref, network_info=nw_info)
- self.fw.apply_instance_filter(instance_ref)
+ self.fw.prepare_instance_filter(instance_ref, network_info)
+ self.fw.apply_instance_filter(instance_ref, network_info)
inst_rules = [rule for rule in self.fw.iptables.ipv4['filter'].rules
if rule.chain == chain_name]
jump_rules = [rule for rule in inst_rules if '-j' in rule.rule]
@@ -1247,7 +1373,7 @@ class NWFilterTestCase(test.TestCase):
def _ensure_all_called():
instance_filter = 'nova-instance-%s-%s' % (instance_ref['name'],
- '561212121212')
+ 'fake')
secgroup_filter = 'nova-secgroup-%s' % self.security_group['id']
for required in [secgroup_filter, 'allow-dhcp-server',
'no-arp-spoofing', 'no-ip-spoofing',
@@ -1263,9 +1389,10 @@ class NWFilterTestCase(test.TestCase):
self.security_group.id)
instance = db.instance_get(self.context, inst_id)
- self.fw.setup_basic_filtering(instance)
- self.fw.prepare_instance_filter(instance)
- self.fw.apply_instance_filter(instance)
+ network_info = _create_network_info()
+ self.fw.setup_basic_filtering(instance, network_info)
+ self.fw.prepare_instance_filter(instance, network_info)
+ self.fw.apply_instance_filter(instance, network_info)
_ensure_all_called()
self.teardown_security_group()
db.instance_destroy(context.get_admin_context(), instance_ref['id'])
@@ -1296,11 +1423,12 @@ class NWFilterTestCase(test.TestCase):
instance = db.instance_get(self.context, 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)
+ network_info = _create_network_info()
+ self.fw.setup_basic_filtering(instance, network_info)
+ self.fw.prepare_instance_filter(instance, network_info)
+ self.fw.apply_instance_filter(instance, network_info)
original_filter_count = len(fakefilter.filters)
- self.fw.unfilter_instance(instance)
+ self.fw.unfilter_instance(instance, network_info)
# should undefine 2 filters: instance and instance-secgroup
self.assertEqual(original_filter_count - len(fakefilter.filters), 2)
diff --git a/nova/tests/test_metadata.py b/nova/tests/test_metadata.py
index ad678714e..bfc7a6d44 100644
--- a/nova/tests/test_metadata.py
+++ b/nova/tests/test_metadata.py
@@ -39,7 +39,7 @@ class MetadataTestCase(test.TestCase):
'key_name': None,
'host': 'test',
'launch_index': 1,
- 'instance_type': 'm1.tiny',
+ 'instance_type': {'name': 'm1.tiny'},
'reservation_id': 'r-xxxxxxxx',
'user_data': '',
'image_ref': 7,
diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py
index 2ca8b64f4..0ead680ee 100644
--- a/nova/tests/test_network.py
+++ b/nova/tests/test_network.py
@@ -210,7 +210,11 @@ class VlanNetworkTestCase(test.TestCase):
self.mox.StubOutWithMock(db, 'fixed_ip_update')
self.mox.StubOutWithMock(db,
'virtual_interface_get_by_instance_and_network')
+ self.mox.StubOutWithMock(db, 'instance_get')
+ db.instance_get(mox.IgnoreArg(),
+ mox.IgnoreArg()).AndReturn({'security_groups':
+ [{'id': 0}]})
db.fixed_ip_associate_pool(mox.IgnoreArg(),
mox.IgnoreArg(),
mox.IgnoreArg()).AndReturn('192.168.0.1')
@@ -247,6 +251,17 @@ class CommonNetworkTestCase(test.TestCase):
return [dict(address='10.0.0.0'), dict(address='10.0.0.1'),
dict(address='10.0.0.2')]
+ def network_get_by_cidr(self, context, cidr):
+ raise exception.NetworkNotFoundForCidr()
+
+ def network_create_safe(self, context, net):
+ fakenet = dict(net)
+ fakenet['id'] = 999
+ return fakenet
+
+ def network_get_all(self, context):
+ raise exception.NoNetworksFound()
+
def __init__(self):
self.db = self.FakeDB()
self.deallocate_called = None
@@ -254,6 +269,12 @@ class CommonNetworkTestCase(test.TestCase):
def deallocate_fixed_ip(self, context, address):
self.deallocate_called = address
+ def _create_fixed_ips(self, context, network_id):
+ pass
+
+ def fake_create_fixed_ips(self, context, network_id):
+ return None
+
def test_remove_fixed_ip_from_instance(self):
manager = self.FakeNetworkManager()
manager.remove_fixed_ip_from_instance(None, 99, '10.0.0.1')
@@ -265,3 +286,180 @@ class CommonNetworkTestCase(test.TestCase):
self.assertRaises(exception.FixedIpNotFoundForSpecificInstance,
manager.remove_fixed_ip_from_instance,
None, 99, 'bad input')
+
+ def test_validate_cidrs(self):
+ manager = self.FakeNetworkManager()
+ nets = manager.create_networks(None, 'fake', '192.168.0.0/24',
+ False, 1, 256, None, None, None,
+ None)
+ self.assertEqual(1, len(nets))
+ cidrs = [str(net['cidr']) for net in nets]
+ self.assertTrue('192.168.0.0/24' in cidrs)
+
+ def test_validate_cidrs_split_exact_in_half(self):
+ manager = self.FakeNetworkManager()
+ nets = manager.create_networks(None, 'fake', '192.168.0.0/24',
+ False, 2, 128, None, None, None,
+ None)
+ self.assertEqual(2, len(nets))
+ cidrs = [str(net['cidr']) for net in nets]
+ self.assertTrue('192.168.0.0/25' in cidrs)
+ self.assertTrue('192.168.0.128/25' in cidrs)
+
+ def test_validate_cidrs_split_cidr_in_use_middle_of_range(self):
+ manager = self.FakeNetworkManager()
+ self.mox.StubOutWithMock(manager.db, 'network_get_all')
+ ctxt = mox.IgnoreArg()
+ manager.db.network_get_all(ctxt).AndReturn([{'id': 1,
+ 'cidr': '192.168.2.0/24'}])
+ self.mox.ReplayAll()
+ nets = manager.create_networks(None, 'fake', '192.168.0.0/16',
+ False, 4, 256, None, None, None,
+ None)
+ self.assertEqual(4, len(nets))
+ cidrs = [str(net['cidr']) for net in nets]
+ exp_cidrs = ['192.168.0.0/24', '192.168.1.0/24', '192.168.3.0/24',
+ '192.168.4.0/24']
+ for exp_cidr in exp_cidrs:
+ self.assertTrue(exp_cidr in cidrs)
+ self.assertFalse('192.168.2.0/24' in cidrs)
+
+ def test_validate_cidrs_smaller_subnet_in_use(self):
+ manager = self.FakeNetworkManager()
+ self.mox.StubOutWithMock(manager.db, 'network_get_all')
+ ctxt = mox.IgnoreArg()
+ manager.db.network_get_all(ctxt).AndReturn([{'id': 1,
+ 'cidr': '192.168.2.9/25'}])
+ self.mox.ReplayAll()
+ # ValueError: requested cidr (192.168.2.0/24) conflicts with
+ # existing smaller cidr
+ args = (None, 'fake', '192.168.2.0/24', False, 1, 256, None, None,
+ None, None)
+ self.assertRaises(ValueError, manager.create_networks, *args)
+
+ def test_validate_cidrs_split_smaller_cidr_in_use(self):
+ manager = self.FakeNetworkManager()
+ self.mox.StubOutWithMock(manager.db, 'network_get_all')
+ ctxt = mox.IgnoreArg()
+ manager.db.network_get_all(ctxt).AndReturn([{'id': 1,
+ 'cidr': '192.168.2.0/25'}])
+ self.mox.ReplayAll()
+ nets = manager.create_networks(None, 'fake', '192.168.0.0/16',
+ False, 4, 256, None, None, None, None)
+ self.assertEqual(4, len(nets))
+ cidrs = [str(net['cidr']) for net in nets]
+ exp_cidrs = ['192.168.0.0/24', '192.168.1.0/24', '192.168.3.0/24',
+ '192.168.4.0/24']
+ for exp_cidr in exp_cidrs:
+ self.assertTrue(exp_cidr in cidrs)
+ self.assertFalse('192.168.2.0/24' in cidrs)
+
+ def test_validate_cidrs_split_smaller_cidr_in_use2(self):
+ manager = self.FakeNetworkManager()
+ self.mox.StubOutWithMock(manager.db, 'network_get_all')
+ ctxt = mox.IgnoreArg()
+ manager.db.network_get_all(ctxt).AndReturn([{'id': 1,
+ 'cidr': '192.168.2.9/29'}])
+ self.mox.ReplayAll()
+ nets = manager.create_networks(None, 'fake', '192.168.2.0/24',
+ False, 3, 32, None, None, None, None)
+ self.assertEqual(3, len(nets))
+ cidrs = [str(net['cidr']) for net in nets]
+ exp_cidrs = ['192.168.2.32/27', '192.168.2.64/27', '192.168.2.96/27']
+ for exp_cidr in exp_cidrs:
+ self.assertTrue(exp_cidr in cidrs)
+ self.assertFalse('192.168.2.0/27' in cidrs)
+
+ def test_validate_cidrs_split_all_in_use(self):
+ manager = self.FakeNetworkManager()
+ self.mox.StubOutWithMock(manager.db, 'network_get_all')
+ ctxt = mox.IgnoreArg()
+ in_use = [{'id': 1, 'cidr': '192.168.2.9/29'},
+ {'id': 2, 'cidr': '192.168.2.64/26'},
+ {'id': 3, 'cidr': '192.168.2.128/26'}]
+ manager.db.network_get_all(ctxt).AndReturn(in_use)
+ self.mox.ReplayAll()
+ args = (None, 'fake', '192.168.2.0/24', False, 3, 64, None, None,
+ None, None)
+ # ValueError: Not enough subnets avail to satisfy requested num_
+ # networks - some subnets in requested range already
+ # in use
+ self.assertRaises(ValueError, manager.create_networks, *args)
+
+ def test_validate_cidrs_one_in_use(self):
+ manager = self.FakeNetworkManager()
+ args = (None, 'fake', '192.168.0.0/24', False, 2, 256, None, None,
+ None, None)
+ # ValueError: network_size * num_networks exceeds cidr size
+ self.assertRaises(ValueError, manager.create_networks, *args)
+
+ def test_validate_cidrs_already_used(self):
+ manager = self.FakeNetworkManager()
+ self.mox.StubOutWithMock(manager.db, 'network_get_all')
+ ctxt = mox.IgnoreArg()
+ manager.db.network_get_all(ctxt).AndReturn([{'id': 1,
+ 'cidr': '192.168.0.0/24'}])
+ self.mox.ReplayAll()
+ # ValueError: cidr already in use
+ args = (None, 'fake', '192.168.0.0/24', False, 1, 256, None, None,
+ None, None)
+ self.assertRaises(ValueError, manager.create_networks, *args)
+
+ def test_validate_cidrs_too_many(self):
+ manager = self.FakeNetworkManager()
+ args = (None, 'fake', '192.168.0.0/24', False, 200, 256, None, None,
+ None, None)
+ # ValueError: Not enough subnets avail to satisfy requested
+ # num_networks
+ self.assertRaises(ValueError, manager.create_networks, *args)
+
+ def test_validate_cidrs_split_partial(self):
+ manager = self.FakeNetworkManager()
+ nets = manager.create_networks(None, 'fake', '192.168.0.0/16',
+ False, 2, 256, None, None, None, None)
+ returned_cidrs = [str(net['cidr']) for net in nets]
+ self.assertTrue('192.168.0.0/24' in returned_cidrs)
+ self.assertTrue('192.168.1.0/24' in returned_cidrs)
+
+ def test_validate_cidrs_conflict_existing_supernet(self):
+ manager = self.FakeNetworkManager()
+ self.mox.StubOutWithMock(manager.db, 'network_get_all')
+ ctxt = mox.IgnoreArg()
+ fakecidr = [{'id': 1, 'cidr': '192.168.0.0/8'}]
+ manager.db.network_get_all(ctxt).AndReturn(fakecidr)
+ self.mox.ReplayAll()
+ args = (None, 'fake', '192.168.0.0/24', False, 1, 256, None, None,
+ None, None)
+ # ValueError: requested cidr (192.168.0.0/24) conflicts
+ # with existing supernet
+ self.assertRaises(ValueError, manager.create_networks, *args)
+
+ def test_create_networks(self):
+ cidr = '192.168.0.0/24'
+ manager = self.FakeNetworkManager()
+ self.stubs.Set(manager, '_create_fixed_ips',
+ self.fake_create_fixed_ips)
+ args = [None, 'foo', cidr, None, 1, 256, 'fd00::/48', None, None,
+ None]
+ result = manager.create_networks(*args)
+ self.assertTrue(manager.create_networks(*args))
+
+ def test_create_networks_cidr_already_used(self):
+ manager = self.FakeNetworkManager()
+ self.mox.StubOutWithMock(manager.db, 'network_get_all')
+ ctxt = mox.IgnoreArg()
+ fakecidr = [{'id': 1, 'cidr': '192.168.0.0/24'}]
+ manager.db.network_get_all(ctxt).AndReturn(fakecidr)
+ self.mox.ReplayAll()
+ args = [None, 'foo', '192.168.0.0/24', None, 1, 256,
+ 'fd00::/48', None, None, None]
+ self.assertRaises(ValueError, manager.create_networks, *args)
+
+ def test_create_networks_many(self):
+ cidr = '192.168.0.0/16'
+ manager = self.FakeNetworkManager()
+ self.stubs.Set(manager, '_create_fixed_ips',
+ self.fake_create_fixed_ips)
+ args = [None, 'foo', cidr, None, 10, 256, 'fd00::/48', None, None,
+ None]
+ self.assertTrue(manager.create_networks(*args))
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py
index 1deb5a780..2f0559366 100644
--- a/nova/tests/test_xenapi.py
+++ b/nova/tests/test_xenapi.py
@@ -519,6 +519,11 @@ class XenAPIVMTestCase(test.TestCase):
os_type="windows", architecture="i386")
self.check_vm_params_for_windows()
+ def test_spawn_iso_glance(self):
+ self._test_spawn(glance_stubs.FakeGlance.IMAGE_ISO, None, None,
+ os_type="windows", architecture="i386")
+ self.check_vm_params_for_windows()
+
def test_spawn_glance(self):
self._test_spawn(glance_stubs.FakeGlance.IMAGE_MACHINE,
glance_stubs.FakeGlance.IMAGE_KERNEL,
diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py
index 0d0f84e32..a6a1febd6 100644
--- a/nova/tests/xenapi/stubs.py
+++ b/nova/tests/xenapi/stubs.py
@@ -28,10 +28,10 @@ from nova import utils
def stubout_instance_snapshot(stubs):
@classmethod
- def fake_fetch_image(cls, context, session, instance_id, image, user,
+ def fake_fetch_image(cls, context, session, instance, image, user,
project, type):
from nova.virt.xenapi.fake import create_vdi
- name_label = "instance-%s" % instance_id
+ name_label = "instance-%s" % instance.id
#TODO: create fake SR record
sr_ref = "fakesr"
vdi_ref = create_vdi(name_label=name_label, read_only=False,