summaryrefslogtreecommitdiffstats
path: root/nova/tests
diff options
context:
space:
mode:
Diffstat (limited to 'nova/tests')
-rw-r--r--nova/tests/api/ec2/test_cloud.py10
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_admin_actions.py4
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_availability_zone.py1
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_coverage_ext.py2
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_evacuate.py20
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_extended_availability_zone.py51
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_flavor_manage.py15
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_security_groups.py2
-rw-r--r--nova/tests/api/openstack/compute/extensions/test_plugin_api_extensions.py87
-rw-r--r--nova/tests/api/openstack/compute/plugins/v3/test_agents.py181
-rw-r--r--nova/tests/api/openstack/compute/plugins/v3/test_cells.py469
-rw-r--r--nova/tests/api/openstack/compute/plugins/v3/test_certificates.py77
-rw-r--r--nova/tests/api/openstack/compute/plugins/v3/test_evacuate.py198
-rw-r--r--nova/tests/api/openstack/compute/plugins/v3/test_extension_info.py108
-rw-r--r--nova/tests/api/openstack/compute/plugins/v3/test_flavor_access.py308
-rw-r--r--nova/tests/api/openstack/compute/plugins/v3/test_flavor_disabled.py101
-rw-r--r--nova/tests/api/openstack/compute/plugins/v3/test_flavors.py696
-rw-r--r--nova/tests/api/openstack/compute/plugins/v3/test_images.py1336
-rw-r--r--nova/tests/api/openstack/compute/plugins/v3/test_quota_classes.py188
-rw-r--r--nova/tests/api/openstack/compute/plugins/v3/test_quota_sets.py399
-rw-r--r--nova/tests/api/openstack/compute/plugins/v3/test_rescue.py126
-rw-r--r--nova/tests/api/openstack/compute/plugins/v3/test_server_diagnostics.py81
-rw-r--r--nova/tests/api/openstack/compute/plugins/v3/test_servers.py402
-rw-r--r--nova/tests/api/openstack/compute/test_flavors.py1
-rw-r--r--nova/tests/api/openstack/compute/test_limits.py24
-rw-r--r--nova/tests/api/openstack/compute/test_server_metadata.py3
-rw-r--r--nova/tests/api/openstack/compute/test_servers.py277
-rw-r--r--nova/tests/api/openstack/compute/test_v3_extensions.py37
-rw-r--r--nova/tests/api/openstack/fakes.py17
-rw-r--r--nova/tests/cells/test_cells_manager.py24
-rw-r--r--nova/tests/cells/test_cells_messaging.py225
-rw-r--r--nova/tests/cells/test_cells_rpcapi.py26
-rw-r--r--nova/tests/cells/test_cells_scheduler.py20
-rw-r--r--nova/tests/compute/test_compute.py389
-rw-r--r--nova/tests/conductor/tasks/__init__.py11
-rw-r--r--nova/tests/conductor/tasks/test_live_migrate.py311
-rw-r--r--nova/tests/conductor/test_conductor.py86
-rw-r--r--nova/tests/db/test_db_api.py827
-rw-r--r--nova/tests/db/test_migration_utils.py27
-rw-r--r--nova/tests/db/test_migrations.py10
-rw-r--r--nova/tests/fake_network.py24
-rw-r--r--nova/tests/fake_policy.py11
-rw-r--r--nova/tests/integrated/test_api_samples.py36
-rw-r--r--nova/tests/network/test_linux_net.py1
-rw-r--r--nova/tests/network/test_network_info.py2
-rw-r--r--nova/tests/network/test_quantumv2.py27
-rw-r--r--nova/tests/objects/test_instance.py93
-rw-r--r--nova/tests/objects/test_instance_fault.py86
-rw-r--r--nova/tests/objects/test_objects.py69
-rw-r--r--nova/tests/objects/test_security_group.py186
-rw-r--r--nova/tests/scheduler/test_chance_scheduler.py8
-rw-r--r--nova/tests/scheduler/test_filter_scheduler.py139
-rw-r--r--nova/tests/scheduler/test_host_filters.py126
-rw-r--r--nova/tests/scheduler/test_scheduler.py529
-rw-r--r--nova/tests/scheduler/test_scheduler_options.py1
-rw-r--r--nova/tests/servicegroup/test_mc_servicegroup.py16
-rw-r--r--nova/tests/servicegroup/test_zk_driver.py2
-rw-r--r--nova/tests/test_availability_zones.py4
-rw-r--r--nova/tests/test_cinder.py15
-rw-r--r--nova/tests/test_flavors.py16
-rw-r--r--nova/tests/test_metadata.py1
-rw-r--r--nova/tests/test_notifications.py10
-rw-r--r--nova/tests/test_quota.py2
-rw-r--r--nova/tests/test_utils.py121
-rw-r--r--nova/tests/test_wsgi.py15
-rw-r--r--nova/tests/utils.py4
-rw-r--r--nova/tests/virt/baremetal/db/test_bm_pxe_ip.py94
-rw-r--r--nova/tests/virt/baremetal/db/utils.py12
-rw-r--r--nova/tests/virt/baremetal/test_pxe.py26
-rwxr-xr-xnova/tests/virt/baremetal/test_tilera.py7
-rw-r--r--nova/tests/virt/hyperv/test_hypervapi.py21
-rw-r--r--nova/tests/virt/libvirt/test_libvirt.py293
-rw-r--r--nova/tests/virt/libvirt/test_libvirt_vif.py80
-rw-r--r--nova/tests/virt/test_virt_drivers.py29
-rw-r--r--nova/tests/virt/vmwareapi/db_fakes.py2
-rw-r--r--nova/tests/virt/vmwareapi/test_vmwareapi.py79
-rw-r--r--nova/tests/virt/vmwareapi/test_vmwareapi_vm_util.py96
-rw-r--r--nova/tests/virt/xenapi/test_vm_utils.py4
-rw-r--r--nova/tests/virt/xenapi/test_xenapi.py99
79 files changed, 7747 insertions, 1816 deletions
diff --git a/nova/tests/api/ec2/test_cloud.py b/nova/tests/api/ec2/test_cloud.py
index 543bf4a62..c9e8ff42f 100644
--- a/nova/tests/api/ec2/test_cloud.py
+++ b/nova/tests/api/ec2/test_cloud.py
@@ -46,6 +46,7 @@ from nova.network import api as network_api
from nova.network import quantumv2
from nova.openstack.common import log as logging
from nova.openstack.common import rpc
+from nova.openstack.common import timeutils
from nova import test
from nova.tests.api.openstack.compute.contrib import (
test_quantum_security_groups as test_quantum)
@@ -880,6 +881,7 @@ class CloudTestCase(test.TestCase):
'instance_type_id': 1,
'host': 'host1',
'vm_state': 'active',
+ 'launched_at': timeutils.utcnow(),
'hostname': 'server-1111',
'created_at': datetime.datetime(2012, 5, 1, 1, 1, 1),
'system_metadata': sys_meta
@@ -891,6 +893,7 @@ class CloudTestCase(test.TestCase):
'instance_type_id': 1,
'host': 'host2',
'vm_state': 'active',
+ 'launched_at': timeutils.utcnow(),
'hostname': 'server-1112',
'created_at': datetime.datetime(2012, 5, 1, 1, 1, 2),
'system_metadata': sys_meta
@@ -2121,6 +2124,7 @@ class CloudTestCase(test.TestCase):
return [dict(id=1,
source_type='snapshot',
destination_type='volume',
+ instance_uuid=inst_id,
snapshot_id=snapshots[0],
volume_id=volumes[0],
volume_size=1,
@@ -2134,7 +2138,8 @@ class CloudTestCase(test.TestCase):
virt_driver = {}
- def fake_power_on(self, instance):
+ def fake_power_on(self, context, instance, network_info,
+ block_device_info):
virt_driver['powered_on'] = True
self.stubs.Set(fake_virt.FakeDriver, 'power_on', fake_power_on)
@@ -2442,6 +2447,7 @@ class CloudTestCase(test.TestCase):
'image_ref': image_uuid,
'instance_type_id': 1,
'vm_state': 'active',
+ 'launched_at': timeutils.utcnow(),
'hostname': 'server-1111',
'created_at': datetime.datetime(2012, 5, 1, 1, 1, 1)
}
@@ -2492,6 +2498,7 @@ class CloudTestCase(test.TestCase):
'image_ref': image_uuid,
'instance_type_id': 1,
'vm_state': 'active',
+ 'launched_at': timeutils.utcnow(),
'hostname': 'server-1111',
'created_at': datetime.datetime(2012, 5, 1, 1, 1, 1)
}
@@ -2501,6 +2508,7 @@ class CloudTestCase(test.TestCase):
'image_ref': image_uuid,
'instance_type_id': 1,
'vm_state': 'active',
+ 'launched_at': timeutils.utcnow(),
'hostname': 'server-1112',
'created_at': datetime.datetime(2012, 5, 1, 1, 1, 2)
}
diff --git a/nova/tests/api/openstack/compute/contrib/test_admin_actions.py b/nova/tests/api/openstack/compute/contrib/test_admin_actions.py
index 5e64bdf94..39eebbcd1 100644
--- a/nova/tests/api/openstack/compute/contrib/test_admin_actions.py
+++ b/nova/tests/api/openstack/compute/contrib/test_admin_actions.py
@@ -26,6 +26,7 @@ from nova.conductor import api as conductor_api
from nova import context
from nova import exception
from nova.openstack.common import jsonutils
+from nova.openstack.common import timeutils
from nova import test
from nova.tests.api.openstack import fakes
@@ -41,6 +42,7 @@ INSTANCE = {
"tenant_id": 'fake_tenant_id',
"created_at": datetime.datetime(2010, 10, 10, 12, 0, 0),
"updated_at": datetime.datetime(2010, 11, 11, 11, 0, 0),
+ "launched_at": datetime.datetime(2010, 11, 11, 11, 0, 0),
"security_groups": [{"id": 1, "name": "test"}],
"progress": 0,
"image_ref": 'http://foo.com/123',
@@ -61,7 +63,7 @@ def fake_compute_api_raises_invalid_state(*args, **kwargs):
def fake_compute_api_get(self, context, instance_id):
return {'id': 1, 'uuid': instance_id, 'vm_state': vm_states.ACTIVE,
- 'task_state': None}
+ 'task_state': None, 'launched_at': timeutils.utcnow()}
class AdminActionsTest(test.TestCase):
diff --git a/nova/tests/api/openstack/compute/contrib/test_availability_zone.py b/nova/tests/api/openstack/compute/contrib/test_availability_zone.py
index 2ccb9fa31..0b63960ce 100644
--- a/nova/tests/api/openstack/compute/contrib/test_availability_zone.py
+++ b/nova/tests/api/openstack/compute/contrib/test_availability_zone.py
@@ -76,6 +76,7 @@ def fake_set_availability_zones(context, services):
class AvailabilityZoneApiTest(test.TestCase):
def setUp(self):
super(AvailabilityZoneApiTest, self).setUp()
+ availability_zones._reset_cache()
self.stubs.Set(db, 'service_get_all', fake_service_get_all)
self.stubs.Set(availability_zones, 'set_availability_zones',
fake_set_availability_zones)
diff --git a/nova/tests/api/openstack/compute/contrib/test_coverage_ext.py b/nova/tests/api/openstack/compute/contrib/test_coverage_ext.py
index 957625b34..93a623bf6 100644
--- a/nova/tests/api/openstack/compute/contrib/test_coverage_ext.py
+++ b/nova/tests/api/openstack/compute/contrib/test_coverage_ext.py
@@ -12,7 +12,7 @@
# 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
+# under the License.
import telnetlib
diff --git a/nova/tests/api/openstack/compute/contrib/test_evacuate.py b/nova/tests/api/openstack/compute/contrib/test_evacuate.py
index 816bac565..f2ebf9d78 100644
--- a/nova/tests/api/openstack/compute/contrib/test_evacuate.py
+++ b/nova/tests/api/openstack/compute/contrib/test_evacuate.py
@@ -76,8 +76,8 @@ class EvacuateTest(test.TestCase):
ctxt.project_id = 'fake'
ctxt.is_admin = True
app = fakes.wsgi_app(fake_auth_context=ctxt)
- uuid = self.UUID
- req = webob.Request.blank('/v2/fake/servers/%s/action' % uuid)
+ uuid1 = self.UUID
+ req = webob.Request.blank('/v2/fake/servers/%s/action' % uuid1)
req.method = 'POST'
req.body = jsonutils.dumps({
'evacuate': {
@@ -105,8 +105,8 @@ class EvacuateTest(test.TestCase):
ctxt.project_id = 'fake'
ctxt.is_admin = True
app = fakes.wsgi_app(fake_auth_context=ctxt)
- uuid = self.UUID
- req = webob.Request.blank('/v2/fake/servers/%s/action' % uuid)
+ uuid1 = self.UUID
+ req = webob.Request.blank('/v2/fake/servers/%s/action' % uuid1)
req.method = 'POST'
req.body = jsonutils.dumps({
'evacuate': {
@@ -132,8 +132,8 @@ class EvacuateTest(test.TestCase):
ctxt.project_id = 'fake'
ctxt.is_admin = True
app = fakes.wsgi_app(fake_auth_context=ctxt)
- uuid = self.UUID
- req = webob.Request.blank('/v2/fake/servers/%s/action' % uuid)
+ uuid1 = self.UUID
+ req = webob.Request.blank('/v2/fake/servers/%s/action' % uuid1)
req.method = 'POST'
req.body = jsonutils.dumps({
'evacuate': {
@@ -161,8 +161,8 @@ class EvacuateTest(test.TestCase):
ctxt.project_id = 'fake'
ctxt.is_admin = True
app = fakes.wsgi_app(fake_auth_context=ctxt)
- uuid = self.UUID
- req = webob.Request.blank('/v2/fake/servers/%s/action' % uuid)
+ uuid1 = self.UUID
+ req = webob.Request.blank('/v2/fake/servers/%s/action' % uuid1)
req.method = 'POST'
req.body = jsonutils.dumps({
'evacuate': {
@@ -184,8 +184,8 @@ class EvacuateTest(test.TestCase):
def test_not_admin(self):
ctxt = context.RequestContext('fake', 'fake', is_admin=False)
app = fakes.wsgi_app(fake_auth_context=ctxt)
- uuid = self.UUID
- req = webob.Request.blank('/v2/fake/servers/%s/action' % uuid)
+ uuid1 = self.UUID
+ req = webob.Request.blank('/v2/fake/servers/%s/action' % uuid1)
req.method = 'POST'
req.body = jsonutils.dumps({
'evacuate': {
diff --git a/nova/tests/api/openstack/compute/contrib/test_extended_availability_zone.py b/nova/tests/api/openstack/compute/contrib/test_extended_availability_zone.py
index 814c0fff4..59d60acf2 100644
--- a/nova/tests/api/openstack/compute/contrib/test_extended_availability_zone.py
+++ b/nova/tests/api/openstack/compute/contrib/test_extended_availability_zone.py
@@ -19,6 +19,7 @@ import webob
from nova.api.openstack.compute.contrib import extended_availability_zone
from nova import availability_zones
from nova import compute
+from nova.compute import vm_states
from nova import exception
from nova.openstack.common import jsonutils
from nova import test
@@ -29,14 +30,31 @@ UUID2 = '00000000-0000-0000-0000-000000000002'
UUID3 = '00000000-0000-0000-0000-000000000003'
+def fake_compute_get_az(*args, **kwargs):
+ inst = fakes.stub_instance(1, uuid=UUID3, host="get-host",
+ vm_state=vm_states.ACTIVE,
+ availability_zone='fakeaz')
+ return inst
+
+
+def fake_compute_get_empty(*args, **kwargs):
+ inst = fakes.stub_instance(1, uuid=UUID3, host="",
+ vm_state=vm_states.ACTIVE,
+ availability_zone='fakeaz')
+ return inst
+
+
def fake_compute_get(*args, **kwargs):
- inst = fakes.stub_instance(1, uuid=UUID3, host="get-host")
+ inst = fakes.stub_instance(1, uuid=UUID3, host="get-host",
+ vm_state=vm_states.ACTIVE)
return inst
def fake_compute_get_all(*args, **kwargs):
- inst1 = fakes.stub_instance(1, uuid=UUID1, host="all-host")
- inst2 = fakes.stub_instance(2, uuid=UUID2, host="all-host")
+ inst1 = fakes.stub_instance(1, uuid=UUID1, host="all-host",
+ vm_state=vm_states.ACTIVE)
+ inst2 = fakes.stub_instance(2, uuid=UUID2, host="all-host",
+ vm_state=vm_states.ACTIVE)
return [inst1, inst2]
@@ -44,12 +62,17 @@ def fake_get_host_availability_zone(context, host):
return host
+def fake_get_no_host_availability_zone(context, host):
+ return None
+
+
class ExtendedServerAttributesTest(test.TestCase):
content_type = 'application/json'
prefix = 'OS-EXT-AZ:'
def setUp(self):
super(ExtendedServerAttributesTest, self).setUp()
+ availability_zones._reset_cache()
fakes.stub_out_nw_api(self.stubs)
self.stubs.Set(compute.api.API, 'get', fake_compute_get)
self.stubs.Set(compute.api.API, 'get_all', fake_compute_get_all)
@@ -77,6 +100,28 @@ class ExtendedServerAttributesTest(test.TestCase):
self.assertEqual(server.get('%savailability_zone' % self.prefix),
az)
+ def test_show_no_host_az(self):
+ self.stubs.Set(compute.api.API, 'get', fake_compute_get_az)
+ self.stubs.Set(availability_zones, 'get_host_availability_zone',
+ fake_get_no_host_availability_zone)
+
+ url = '/v2/fake/servers/%s' % UUID3
+ res = self._make_request(url)
+
+ self.assertEqual(res.status_int, 200)
+ self.assertServerAttributes(self._get_server(res.body), 'fakeaz')
+
+ def test_show_empty_host_az(self):
+ self.stubs.Set(compute.api.API, 'get', fake_compute_get_empty)
+ self.stubs.Set(availability_zones, 'get_host_availability_zone',
+ fake_get_no_host_availability_zone)
+
+ url = '/v2/fake/servers/%s' % UUID3
+ res = self._make_request(url)
+
+ self.assertEqual(res.status_int, 200)
+ self.assertServerAttributes(self._get_server(res.body), 'fakeaz')
+
def test_show(self):
url = '/v2/fake/servers/%s' % UUID3
res = self._make_request(url)
diff --git a/nova/tests/api/openstack/compute/contrib/test_flavor_manage.py b/nova/tests/api/openstack/compute/contrib/test_flavor_manage.py
index df2c3d392..459dae932 100644
--- a/nova/tests/api/openstack/compute/contrib/test_flavor_manage.py
+++ b/nova/tests/api/openstack/compute/contrib/test_flavor_manage.py
@@ -218,3 +218,18 @@ class FlavorManageTest(test.TestCase):
req.body = jsonutils.dumps(expected)
res = req.get_response(self.app)
self.assertEqual(res.status_int, 409)
+
+ def test_invalid_memory_mb(self):
+ """Check negative and decimal number can't be accepted."""
+
+ self.stubs.UnsetAll()
+ self.assertRaises(exception.InvalidInput, flavors.create, "abc",
+ -512, 2, 1, 1, 1234, 512, 1, True)
+ self.assertRaises(exception.InvalidInput, flavors.create, "abcd",
+ 512.2, 2, 1, 1, 1234, 512, 1, True)
+ self.assertRaises(exception.InvalidInput, flavors.create, "abcde",
+ None, 2, 1, 1, 1234, 512, 1, True)
+ self.assertRaises(exception.InvalidInput, flavors.create, "abcdef",
+ 512, 2, None, 1, 1234, 512, 1, True)
+ self.assertRaises(exception.InvalidInput, flavors.create, "abcdef",
+ "test_memory_mb", 2, None, 1, 1234, 512, 1, True)
diff --git a/nova/tests/api/openstack/compute/contrib/test_security_groups.py b/nova/tests/api/openstack/compute/contrib/test_security_groups.py
index f1433bd0a..ac3e8885d 100644
--- a/nova/tests/api/openstack/compute/contrib/test_security_groups.py
+++ b/nova/tests/api/openstack/compute/contrib/test_security_groups.py
@@ -716,7 +716,7 @@ class TestSecurityGroupRules(test.TestCase):
db1 = security_group_db(self.sg1)
db2 = security_group_db(self.sg2)
- def return_security_group(context, group_id):
+ def return_security_group(context, group_id, columns_to_join=None):
if group_id == db1['id']:
return db1
if group_id == db2['id']:
diff --git a/nova/tests/api/openstack/compute/extensions/test_plugin_api_extensions.py b/nova/tests/api/openstack/compute/extensions/test_plugin_api_extensions.py
deleted file mode 100644
index 3aac638c6..000000000
--- a/nova/tests/api/openstack/compute/extensions/test_plugin_api_extensions.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# Copyright 2011 OpenStack Foundation
-# 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 pkg_resources
-
-from nova.api.openstack.compute import extensions as computeextensions
-from nova.api.openstack import extensions
-from nova.openstack.common.plugin import plugin
-from nova import test
-
-
-class StubController(object):
-
- def i_am_the_stub(self):
- pass
-
-
-class StubControllerExtension(extensions.ExtensionDescriptor):
- """This is a docstring. We need it."""
- name = 'stubextension'
- alias = 'stubby'
-
- def get_resources(self):
- resources = []
- res = extensions.ResourceExtension('testme',
- StubController())
- resources.append(res)
- return resources
-
-
-service_list = []
-
-
-class TestPluginClass(plugin.Plugin):
-
- def __init__(self, service_name):
- super(TestPluginClass, self).__init__(service_name)
- self._add_api_extension_descriptor(StubControllerExtension)
- service_list.append(service_name)
-
-
-class MockEntrypoint(pkg_resources.EntryPoint):
- def load(self):
- return TestPluginClass
-
-
-class APITestCase(test.TestCase):
- """Test case for the plugin api extension interface."""
- def test_add_extension(self):
- def mock_load(_s):
- return TestPluginClass()
-
- def mock_iter_entry_points(_t):
- return [MockEntrypoint("fake", "fake", ["fake"])]
-
- self.stubs.Set(pkg_resources, 'iter_entry_points',
- mock_iter_entry_points)
- global service_list
- service_list = []
-
- # Marking out the default extension paths makes this test MUCH faster.
- self.flags(osapi_compute_extension=[])
-
- found = False
- mgr = computeextensions.ExtensionManager()
- for res in mgr.get_resources():
- # We have to use this weird 'dir' check because
- # the plugin framework muddies up the classname
- # such that 'isinstance' doesn't work right.
- if 'i_am_the_stub' in dir(res.controller):
- found = True
-
- self.assertTrue(found)
- self.assertEqual(len(service_list), 1)
- self.assertEqual(service_list[0], 'compute-extensions')
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_agents.py b/nova/tests/api/openstack/compute/plugins/v3/test_agents.py
new file mode 100644
index 000000000..0154ada9e
--- /dev/null
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_agents.py
@@ -0,0 +1,181 @@
+# Copyright 2012 IBM Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+from nova.api.openstack.compute.contrib import agents
+from nova import context
+from nova import db
+from nova.db.sqlalchemy import models
+from nova import test
+
+fake_agents_list = [{'hypervisor': 'kvm', 'os': 'win',
+ 'architecture': 'x86',
+ 'version': '7.0',
+ 'url': 'xxx://xxxx/xxx/xxx',
+ 'md5hash': 'add6bb58e139be103324d04d82d8f545',
+ 'id': 1},
+ {'hypervisor': 'kvm', 'os': 'linux',
+ 'architecture': 'x86',
+ 'version': '16.0',
+ 'url': 'xxx://xxxx/xxx/xxx1',
+ 'md5hash': 'add6bb58e139be103324d04d82d8f546',
+ 'id': 2},
+ {'hypervisor': 'xen', 'os': 'linux',
+ 'architecture': 'x86',
+ 'version': '16.0',
+ 'url': 'xxx://xxxx/xxx/xxx2',
+ 'md5hash': 'add6bb58e139be103324d04d82d8f547',
+ 'id': 3},
+ {'hypervisor': 'xen', 'os': 'win',
+ 'architecture': 'power',
+ 'version': '7.0',
+ 'url': 'xxx://xxxx/xxx/xxx3',
+ 'md5hash': 'add6bb58e139be103324d04d82d8f548',
+ 'id': 4},
+ ]
+
+
+def fake_agent_build_get_all(context, hypervisor):
+ agent_build_all = []
+ for agent in fake_agents_list:
+ if hypervisor and hypervisor != agent['hypervisor']:
+ continue
+ agent_build_ref = models.AgentBuild()
+ agent_build_ref.update(agent)
+ agent_build_all.append(agent_build_ref)
+ return agent_build_all
+
+
+def fake_agent_build_update(context, agent_build_id, values):
+ pass
+
+
+def fake_agent_build_destroy(context, agent_update_id):
+ pass
+
+
+def fake_agent_build_create(context, values):
+ values['id'] = 1
+ agent_build_ref = models.AgentBuild()
+ agent_build_ref.update(values)
+ return agent_build_ref
+
+
+class FakeRequest(object):
+ environ = {"nova.context": context.get_admin_context()}
+ GET = {}
+
+
+class FakeRequestWithHypervisor(object):
+ environ = {"nova.context": context.get_admin_context()}
+ GET = {'hypervisor': 'kvm'}
+
+
+class AgentsTest(test.TestCase):
+
+ def setUp(self):
+ super(AgentsTest, self).setUp()
+
+ self.stubs.Set(db, "agent_build_get_all",
+ fake_agent_build_get_all)
+ self.stubs.Set(db, "agent_build_update",
+ fake_agent_build_update)
+ self.stubs.Set(db, "agent_build_destroy",
+ fake_agent_build_destroy)
+ self.stubs.Set(db, "agent_build_create",
+ fake_agent_build_create)
+ self.context = context.get_admin_context()
+ self.controller = agents.AgentController()
+
+ def test_agents_create(self):
+ req = FakeRequest()
+ body = {'agent': {'hypervisor': 'kvm',
+ 'os': 'win',
+ 'architecture': 'x86',
+ 'version': '7.0',
+ 'url': 'xxx://xxxx/xxx/xxx',
+ 'md5hash': 'add6bb58e139be103324d04d82d8f545'}}
+ response = {'agent': {'hypervisor': 'kvm',
+ 'os': 'win',
+ 'architecture': 'x86',
+ 'version': '7.0',
+ 'url': 'xxx://xxxx/xxx/xxx',
+ 'md5hash': 'add6bb58e139be103324d04d82d8f545',
+ 'agent_id': 1}}
+ res_dict = self.controller.create(req, body)
+ self.assertEqual(res_dict, response)
+
+ def test_agents_delete(self):
+ req = FakeRequest()
+ self.controller.delete(req, 1)
+
+ def test_agents_list(self):
+ req = FakeRequest()
+ res_dict = self.controller.index(req)
+ agents_list = [{'hypervisor': 'kvm', 'os': 'win',
+ 'architecture': 'x86',
+ 'version': '7.0',
+ 'url': 'xxx://xxxx/xxx/xxx',
+ 'md5hash': 'add6bb58e139be103324d04d82d8f545',
+ 'agent_id': 1},
+ {'hypervisor': 'kvm', 'os': 'linux',
+ 'architecture': 'x86',
+ 'version': '16.0',
+ 'url': 'xxx://xxxx/xxx/xxx1',
+ 'md5hash': 'add6bb58e139be103324d04d82d8f546',
+ 'agent_id': 2},
+ {'hypervisor': 'xen', 'os': 'linux',
+ 'architecture': 'x86',
+ 'version': '16.0',
+ 'url': 'xxx://xxxx/xxx/xxx2',
+ 'md5hash': 'add6bb58e139be103324d04d82d8f547',
+ 'agent_id': 3},
+ {'hypervisor': 'xen', 'os': 'win',
+ 'architecture': 'power',
+ 'version': '7.0',
+ 'url': 'xxx://xxxx/xxx/xxx3',
+ 'md5hash': 'add6bb58e139be103324d04d82d8f548',
+ 'agent_id': 4},
+ ]
+ self.assertEqual(res_dict, {'agents': agents_list})
+
+ def test_agents_list_with_hypervisor(self):
+ req = FakeRequestWithHypervisor()
+ res_dict = self.controller.index(req)
+ response = [{'hypervisor': 'kvm', 'os': 'win',
+ 'architecture': 'x86',
+ 'version': '7.0',
+ 'url': 'xxx://xxxx/xxx/xxx',
+ 'md5hash': 'add6bb58e139be103324d04d82d8f545',
+ 'agent_id': 1},
+ {'hypervisor': 'kvm', 'os': 'linux',
+ 'architecture': 'x86',
+ 'version': '16.0',
+ 'url': 'xxx://xxxx/xxx/xxx1',
+ 'md5hash': 'add6bb58e139be103324d04d82d8f546',
+ 'agent_id': 2},
+ ]
+ self.assertEqual(res_dict, {'agents': response})
+
+ def test_agents_update(self):
+ req = FakeRequest()
+ body = {'para': {'version': '7.0',
+ 'url': 'xxx://xxxx/xxx/xxx',
+ 'md5hash': 'add6bb58e139be103324d04d82d8f545'}}
+ response = {'agent': {'agent_id': 1,
+ 'version': '7.0',
+ 'url': 'xxx://xxxx/xxx/xxx',
+ 'md5hash': 'add6bb58e139be103324d04d82d8f545'}}
+ res_dict = self.controller.update(req, 1, body)
+ self.assertEqual(res_dict, response)
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_cells.py b/nova/tests/api/openstack/compute/plugins/v3/test_cells.py
new file mode 100644
index 000000000..f369c06e3
--- /dev/null
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_cells.py
@@ -0,0 +1,469 @@
+# Copyright 2011-2012 OpenStack Foundation
+# 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 copy
+
+from lxml import etree
+from webob import exc
+
+from nova.api.openstack.compute.plugins.v3 import cells as cells_ext
+from nova.api.openstack import extensions
+from nova.api.openstack import xmlutil
+from nova.cells import rpcapi as cells_rpcapi
+from nova import context
+from nova import db
+from nova import exception
+from nova.openstack.common import timeutils
+from nova import test
+from nova.tests.api.openstack import fakes
+from nova.tests import utils
+
+
+FAKE_CELLS = [
+ dict(id=1, name='cell1', username='bob', is_parent=True,
+ weight_scale=1.0, weight_offset=0.0,
+ rpc_host='r1.example.org', password='xxxx'),
+ dict(id=2, name='cell2', username='alice', is_parent=False,
+ weight_scale=1.0, weight_offset=0.0,
+ rpc_host='r2.example.org', password='qwerty')]
+
+
+FAKE_CAPABILITIES = [
+ {'cap1': '0,1', 'cap2': '2,3'},
+ {'cap3': '4,5', 'cap4': '5,6'}]
+
+
+def fake_db_cell_get(context, cell_name):
+ for cell in FAKE_CELLS:
+ if cell_name == cell['name']:
+ return cell
+ else:
+ raise exception.CellNotFound(cell_name=cell_name)
+
+
+def fake_db_cell_create(context, values):
+ cell = dict(id=1)
+ cell.update(values)
+ return cell
+
+
+def fake_db_cell_update(context, cell_id, values):
+ cell = fake_db_cell_get(context, cell_id)
+ cell.update(values)
+ return cell
+
+
+def fake_cells_api_get_all_cell_info(*args):
+ cells = copy.deepcopy(FAKE_CELLS)
+ del cells[0]['password']
+ del cells[1]['password']
+ for i, cell in enumerate(cells):
+ cell['capabilities'] = FAKE_CAPABILITIES[i]
+ return cells
+
+
+def fake_db_cell_get_all(context):
+ return FAKE_CELLS
+
+
+class CellsTest(test.TestCase):
+ def setUp(self):
+ super(CellsTest, self).setUp()
+ self.stubs.Set(db, 'cell_get', fake_db_cell_get)
+ self.stubs.Set(db, 'cell_get_all', fake_db_cell_get_all)
+ self.stubs.Set(db, 'cell_update', fake_db_cell_update)
+ self.stubs.Set(db, 'cell_create', fake_db_cell_create)
+ self.stubs.Set(cells_rpcapi.CellsAPI, 'get_cell_info_for_neighbors',
+ fake_cells_api_get_all_cell_info)
+
+ self.controller = cells_ext.CellsController()
+ self.context = context.get_admin_context()
+
+ def _get_request(self, resource):
+ return fakes.HTTPRequestV3.blank('/' + resource)
+
+ def test_index(self):
+ req = self._get_request("cells")
+ res_dict = self.controller.index(req)
+
+ self.assertEqual(len(res_dict['cells']), 2)
+ for i, cell in enumerate(res_dict['cells']):
+ self.assertEqual(cell['name'], FAKE_CELLS[i]['name'])
+ self.assertNotIn('capabilitiles', cell)
+ self.assertNotIn('password', cell)
+
+ def test_detail(self):
+ req = self._get_request("cells/detail")
+ res_dict = self.controller.detail(req)
+
+ self.assertEqual(len(res_dict['cells']), 2)
+ for i, cell in enumerate(res_dict['cells']):
+ self.assertEqual(cell['name'], FAKE_CELLS[i]['name'])
+ self.assertEqual(cell['capabilities'], FAKE_CAPABILITIES[i])
+ self.assertNotIn('password', cell)
+
+ def test_show_bogus_cell_raises(self):
+ req = self._get_request("cells/bogus")
+ self.assertRaises(exc.HTTPNotFound, self.controller.show, req, 'bogus')
+
+ def test_get_cell_by_name(self):
+ req = self._get_request("cells/cell1")
+ res_dict = self.controller.show(req, 'cell1')
+ cell = res_dict['cell']
+
+ self.assertEqual(cell['name'], 'cell1')
+ self.assertEqual(cell['rpc_host'], 'r1.example.org')
+ self.assertNotIn('password', cell)
+
+ def test_cell_delete(self):
+ call_info = {'delete_called': 0}
+
+ def fake_db_cell_delete(context, cell_name):
+ self.assertEqual(cell_name, 'cell999')
+ call_info['delete_called'] += 1
+
+ self.stubs.Set(db, 'cell_delete', fake_db_cell_delete)
+
+ req = self._get_request("cells/cell999")
+ self.controller.delete(req, 'cell999')
+ self.assertEqual(call_info['delete_called'], 1)
+
+ def test_delete_bogus_cell_raises(self):
+ req = self._get_request("cells/cell999")
+ req.environ['nova.context'] = self.context
+ self.assertRaises(exc.HTTPNotFound, self.controller.delete, req,
+ 'cell999')
+
+ def test_cell_create_parent(self):
+ body = {'cell': {'name': 'meow',
+ 'username': 'fred',
+ 'password': 'fubar',
+ 'rpc_host': 'r3.example.org',
+ 'type': 'parent',
+ # Also test this is ignored/stripped
+ 'is_parent': False}}
+
+ req = self._get_request("cells")
+ res_dict = self.controller.create(req, body)
+ cell = res_dict['cell']
+
+ self.assertEqual(cell['name'], 'meow')
+ self.assertEqual(cell['username'], 'fred')
+ self.assertEqual(cell['rpc_host'], 'r3.example.org')
+ self.assertEqual(cell['type'], 'parent')
+ self.assertNotIn('password', cell)
+ self.assertNotIn('is_parent', cell)
+
+ def test_cell_create_child(self):
+ body = {'cell': {'name': 'meow',
+ 'username': 'fred',
+ 'password': 'fubar',
+ 'rpc_host': 'r3.example.org',
+ 'type': 'child'}}
+
+ req = self._get_request("cells")
+ res_dict = self.controller.create(req, body)
+ cell = res_dict['cell']
+
+ self.assertEqual(cell['name'], 'meow')
+ self.assertEqual(cell['username'], 'fred')
+ self.assertEqual(cell['rpc_host'], 'r3.example.org')
+ self.assertEqual(cell['type'], 'child')
+ self.assertNotIn('password', cell)
+ self.assertNotIn('is_parent', cell)
+
+ def test_cell_create_no_name_raises(self):
+ body = {'cell': {'username': 'moocow',
+ 'password': 'secret',
+ 'rpc_host': 'r3.example.org',
+ 'type': 'parent'}}
+
+ req = self._get_request("cells")
+ self.assertRaises(exc.HTTPBadRequest,
+ self.controller.create, req, body)
+
+ def test_cell_create_name_empty_string_raises(self):
+ body = {'cell': {'name': '',
+ 'username': 'fred',
+ 'password': 'secret',
+ 'rpc_host': 'r3.example.org',
+ 'type': 'parent'}}
+
+ req = self._get_request("cells")
+ self.assertRaises(exc.HTTPBadRequest,
+ self.controller.create, req, body)
+
+ def test_cell_create_name_with_bang_raises(self):
+ body = {'cell': {'name': 'moo!cow',
+ 'username': 'fred',
+ 'password': 'secret',
+ 'rpc_host': 'r3.example.org',
+ 'type': 'parent'}}
+
+ req = self._get_request("cells")
+ self.assertRaises(exc.HTTPBadRequest,
+ self.controller.create, req, body)
+
+ def test_cell_create_name_with_dot_raises(self):
+ body = {'cell': {'name': 'moo.cow',
+ 'username': 'fred',
+ 'password': 'secret',
+ 'rpc_host': 'r3.example.org',
+ 'type': 'parent'}}
+
+ req = self._get_request("cells")
+ self.assertRaises(exc.HTTPBadRequest,
+ self.controller.create, req, body)
+
+ def test_cell_create_name_with_invalid_type_raises(self):
+ body = {'cell': {'name': 'moocow',
+ 'username': 'fred',
+ 'password': 'secret',
+ 'rpc_host': 'r3.example.org',
+ 'type': 'invalid'}}
+
+ req = self._get_request("cells")
+ self.assertRaises(exc.HTTPBadRequest,
+ self.controller.create, req, body)
+
+ def test_cell_update(self):
+ body = {'cell': {'username': 'zeb',
+ 'password': 'sneaky'}}
+
+ req = self._get_request("cells/cell1")
+ res_dict = self.controller.update(req, 'cell1', body)
+ cell = res_dict['cell']
+
+ self.assertEqual(cell['name'], 'cell1')
+ self.assertEqual(cell['rpc_host'], FAKE_CELLS[0]['rpc_host'])
+ self.assertEqual(cell['username'], 'zeb')
+ self.assertNotIn('password', cell)
+
+ def test_cell_update_empty_name_raises(self):
+ body = {'cell': {'name': '',
+ 'username': 'zeb',
+ 'password': 'sneaky'}}
+
+ req = self._get_request("cells/cell1")
+ self.assertRaises(exc.HTTPBadRequest,
+ self.controller.update, req, 'cell1', body)
+
+ def test_cell_update_invalid_type_raises(self):
+ body = {'cell': {'username': 'zeb',
+ 'type': 'invalid',
+ 'password': 'sneaky'}}
+
+ req = self._get_request("cells/cell1")
+ self.assertRaises(exc.HTTPBadRequest,
+ self.controller.update, req, 'cell1', body)
+
+ def test_cell_info(self):
+ caps = ['cap1=a;b', 'cap2=c;d']
+ self.flags(name='darksecret', capabilities=caps, group='cells')
+
+ req = self._get_request("cells/info")
+ res_dict = self.controller.info(req)
+ cell = res_dict['cell']
+ cell_caps = cell['capabilities']
+
+ self.assertEqual(cell['name'], 'darksecret')
+ self.assertEqual(cell_caps['cap1'], 'a;b')
+ self.assertEqual(cell_caps['cap2'], 'c;d')
+
+ def test_show_capacities(self):
+ self.mox.StubOutWithMock(self.controller.cells_rpcapi,
+ 'get_capacities')
+ response = {"ram_free":
+ {"units_by_mb": {"8192": 0, "512": 13,
+ "4096": 1, "2048": 3, "16384": 0},
+ "total_mb": 7680},
+ "disk_free":
+ {"units_by_mb": {"81920": 11, "20480": 46,
+ "40960": 23, "163840": 5, "0": 0},
+ "total_mb": 1052672}
+ }
+ self.controller.cells_rpcapi.\
+ get_capacities(self.context, cell_name=None).AndReturn(response)
+ self.mox.ReplayAll()
+ req = self._get_request("cells/capacities")
+ req.environ["nova.context"] = self.context
+ res_dict = self.controller.capacities(req)
+ self.assertEqual(response, res_dict['cell']['capacities'])
+
+ def test_show_capacity_fails_with_non_admin_context(self):
+ rules = {"compute_extension:cells": "is_admin:true"}
+ self.policy.set_rules(rules)
+
+ self.mox.ReplayAll()
+ req = self._get_request("cells/capacities")
+ req.environ["nova.context"] = self.context
+ req.environ["nova.context"].is_admin = False
+ self.assertRaises(exception.PolicyNotAuthorized,
+ self.controller.capacities, req)
+
+ def test_show_capacities_for_invalid_cell(self):
+ self.mox.StubOutWithMock(self.controller.cells_rpcapi,
+ 'get_capacities')
+ self.controller.cells_rpcapi. \
+ get_capacities(self.context, cell_name="invalid_cell").AndRaise(
+ exception.CellNotFound(cell_name="invalid_cell"))
+ self.mox.ReplayAll()
+ req = self._get_request("cells/invalid_cell/capacities")
+ req.environ["nova.context"] = self.context
+ self.assertRaises(exc.HTTPNotFound,
+ self.controller.capacities, req, "invalid_cell")
+
+ def test_show_capacities_for_cell(self):
+ self.mox.StubOutWithMock(self.controller.cells_rpcapi,
+ 'get_capacities')
+ response = {"ram_free":
+ {"units_by_mb": {"8192": 0, "512": 13,
+ "4096": 1, "2048": 3, "16384": 0},
+ "total_mb": 7680},
+ "disk_free":
+ {"units_by_mb": {"81920": 11, "20480": 46,
+ "40960": 23, "163840": 5, "0": 0},
+ "total_mb": 1052672}
+ }
+ self.controller.cells_rpcapi.\
+ get_capacities(self.context, cell_name='cell_name').\
+ AndReturn(response)
+ self.mox.ReplayAll()
+ req = self._get_request("cells/capacities")
+ req.environ["nova.context"] = self.context
+ res_dict = self.controller.capacities(req, 'cell_name')
+ self.assertEqual(response, res_dict['cell']['capacities'])
+
+ def test_sync_instances(self):
+ call_info = {}
+
+ def sync_instances(self, context, **kwargs):
+ call_info['project_id'] = kwargs.get('project_id')
+ call_info['updated_since'] = kwargs.get('updated_since')
+
+ self.stubs.Set(cells_rpcapi.CellsAPI, 'sync_instances', sync_instances)
+
+ req = self._get_request("cells/sync_instances")
+ body = {}
+ self.controller.sync_instances(req, body=body)
+ self.assertEqual(call_info['project_id'], None)
+ self.assertEqual(call_info['updated_since'], None)
+
+ body = {'project_id': 'test-project'}
+ self.controller.sync_instances(req, body=body)
+ self.assertEqual(call_info['project_id'], 'test-project')
+ self.assertEqual(call_info['updated_since'], None)
+
+ expected = timeutils.utcnow().isoformat()
+ if not expected.endswith("+00:00"):
+ expected += "+00:00"
+
+ body = {'updated_since': expected}
+ self.controller.sync_instances(req, body=body)
+ self.assertEqual(call_info['project_id'], None)
+ self.assertEqual(call_info['updated_since'], expected)
+
+ body = {'updated_since': 'skjdfkjsdkf'}
+ self.assertRaises(exc.HTTPBadRequest,
+ self.controller.sync_instances, req, body=body)
+
+ body = {'foo': 'meow'}
+ self.assertRaises(exc.HTTPBadRequest,
+ self.controller.sync_instances, req, body=body)
+
+
+class TestCellsXMLSerializer(test.TestCase):
+ def test_multiple_cells(self):
+ fixture = {'cells': fake_cells_api_get_all_cell_info()}
+
+ serializer = cells_ext.CellsTemplate()
+ output = serializer.serialize(fixture)
+ res_tree = etree.XML(output)
+
+ self.assertEqual(res_tree.tag, '{%s}cells' % xmlutil.XMLNS_V10)
+ self.assertEqual(len(res_tree), 2)
+ self.assertEqual(res_tree[0].tag, '{%s}cell' % xmlutil.XMLNS_V10)
+ self.assertEqual(res_tree[1].tag, '{%s}cell' % xmlutil.XMLNS_V10)
+
+ def test_single_cell_with_caps(self):
+ cell = {'id': 1,
+ 'name': 'darksecret',
+ 'username': 'meow',
+ 'capabilities': {'cap1': 'a;b',
+ 'cap2': 'c;d'}}
+ fixture = {'cell': cell}
+
+ serializer = cells_ext.CellTemplate()
+ output = serializer.serialize(fixture)
+ res_tree = etree.XML(output)
+
+ self.assertEqual(res_tree.tag, '{%s}cell' % xmlutil.XMLNS_V10)
+ self.assertEqual(res_tree.get('name'), 'darksecret')
+ self.assertEqual(res_tree.get('username'), 'meow')
+ self.assertEqual(res_tree.get('password'), None)
+ self.assertEqual(len(res_tree), 1)
+
+ child = res_tree[0]
+ self.assertEqual(child.tag,
+ '{%s}capabilities' % xmlutil.XMLNS_V10)
+ for elem in child:
+ self.assertIn(elem.tag, ('{%s}cap1' % xmlutil.XMLNS_V10,
+ '{%s}cap2' % xmlutil.XMLNS_V10))
+ if elem.tag == '{%s}cap1' % xmlutil.XMLNS_V10:
+ self.assertEqual(elem.text, 'a;b')
+ elif elem.tag == '{%s}cap2' % xmlutil.XMLNS_V10:
+ self.assertEqual(elem.text, 'c;d')
+
+ def test_single_cell_without_caps(self):
+ cell = {'id': 1,
+ 'username': 'woof',
+ 'name': 'darksecret'}
+ fixture = {'cell': cell}
+
+ serializer = cells_ext.CellTemplate()
+ output = serializer.serialize(fixture)
+ res_tree = etree.XML(output)
+
+ self.assertEqual(res_tree.tag, '{%s}cell' % xmlutil.XMLNS_V10)
+ self.assertEqual(res_tree.get('name'), 'darksecret')
+ self.assertEqual(res_tree.get('username'), 'woof')
+ self.assertEqual(res_tree.get('password'), None)
+ self.assertEqual(len(res_tree), 0)
+
+
+class TestCellsXMLDeserializer(test.TestCase):
+ def test_cell_deserializer(self):
+ caps_dict = {'cap1': 'a;b',
+ 'cap2': 'c;d'}
+ caps_xml = ("<capabilities><cap1>a;b</cap1>"
+ "<cap2>c;d</cap2></capabilities>")
+ expected = {'cell': {'name': 'testcell1',
+ 'type': 'child',
+ 'rpc_host': 'localhost',
+ 'capabilities': caps_dict}}
+ intext = ("<?xml version='1.0' encoding='UTF-8'?>\n"
+ "<cell><name>testcell1</name><type>child</type>"
+ "<rpc_host>localhost</rpc_host>"
+ "%s</cell>") % caps_xml
+ deserializer = cells_ext.CellDeserializer()
+ result = deserializer.deserialize(intext)
+ self.assertEqual(dict(body=expected), result)
+
+ def test_with_corrupt_xml(self):
+ deserializer = cells_ext.CellDeserializer()
+ self.assertRaises(
+ exception.MalformedRequestBody,
+ deserializer.deserialize,
+ utils.killer_xml_body())
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_certificates.py b/nova/tests/api/openstack/compute/plugins/v3/test_certificates.py
new file mode 100644
index 000000000..222087872
--- /dev/null
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_certificates.py
@@ -0,0 +1,77 @@
+# Copyright (c) 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from lxml import etree
+
+from nova.api.openstack.compute.plugins.v3 import certificates
+from nova import context
+from nova.openstack.common import rpc
+from nova import test
+from nova.tests.api.openstack import fakes
+
+
+def fake_get_root_cert(context, *args, **kwargs):
+ return 'fakeroot'
+
+
+def fake_create_cert(context, *args, **kwargs):
+ return 'fakepk', 'fakecert'
+
+
+class CertificatesTest(test.TestCase):
+ def setUp(self):
+ super(CertificatesTest, self).setUp()
+ self.context = context.RequestContext('fake', 'fake')
+ self.controller = certificates.CertificatesController()
+
+ def test_translate_certificate_view(self):
+ pk, cert = fake_create_cert(self.context)
+ view = certificates._translate_certificate_view(cert, pk)
+ self.assertEqual(view['data'], cert)
+ self.assertEqual(view['private_key'], pk)
+
+ def test_certificates_show_root(self):
+ self.stubs.Set(rpc, 'call', fake_get_root_cert)
+ req = fakes.HTTPRequestV3.blank('/os-certificates/root')
+ res_dict = self.controller.show(req, 'root')
+
+ cert = fake_get_root_cert(self.context)
+ response = {'certificate': {'data': cert, 'private_key': None}}
+ self.assertEqual(res_dict, response)
+
+ def test_certificates_create_certificate(self):
+ self.stubs.Set(rpc, 'call', fake_create_cert)
+ req = fakes.HTTPRequestV3.blank('/os-certificates/')
+ res_dict = self.controller.create(req)
+
+ pk, cert = fake_create_cert(self.context)
+ response = {'certificate': {'data': cert, 'private_key': pk}}
+ self.assertEqual(res_dict, response)
+
+
+class CertificatesSerializerTest(test.TestCase):
+ def test_index_serializer(self):
+ serializer = certificates.CertificateTemplate()
+ text = serializer.serialize(dict(
+ certificate=dict(
+ data='fakecert',
+ private_key='fakepk'),
+ ))
+
+ tree = etree.fromstring(text)
+
+ self.assertEqual('certificate', tree.tag)
+ self.assertEqual('fakepk', tree.get('private_key'))
+ self.assertEqual('fakecert', tree.get('data'))
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_evacuate.py b/nova/tests/api/openstack/compute/plugins/v3/test_evacuate.py
new file mode 100644
index 000000000..72a531277
--- /dev/null
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_evacuate.py
@@ -0,0 +1,198 @@
+# Copyright 2013 OpenStack Foundation
+#
+# 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 uuid
+
+from oslo.config import cfg
+import webob
+
+from nova.compute import api as compute_api
+from nova.compute import vm_states
+from nova import context
+from nova.openstack.common import jsonutils
+from nova import test
+from nova.tests.api.openstack import fakes
+
+CONF = cfg.CONF
+CONF.import_opt('password_length', 'nova.utils')
+
+
+def fake_compute_api(*args, **kwargs):
+ return True
+
+
+def fake_compute_api_get(self, context, instance_id):
+ return {
+ 'id': 1,
+ 'uuid': instance_id,
+ 'vm_state': vm_states.ACTIVE,
+ 'task_state': None, 'host': 'host1'
+ }
+
+
+class EvacuateTest(test.TestCase):
+
+ _methods = ('resize', 'evacuate')
+
+ def setUp(self):
+ super(EvacuateTest, self).setUp()
+ self.stubs.Set(compute_api.API, 'get', fake_compute_api_get)
+ self.UUID = uuid.uuid4()
+ for _method in self._methods:
+ self.stubs.Set(compute_api.API, _method, fake_compute_api)
+
+ def test_evacuate_instance_with_no_target(self):
+ ctxt = context.get_admin_context()
+ ctxt.user_id = 'fake'
+ ctxt.project_id = 'fake'
+ ctxt.is_admin = True
+ app = fakes.wsgi_app_v3(fake_auth_context=ctxt)
+ req = webob.Request.blank('/v3/servers/%s/action' % self.UUID)
+ req.method = 'POST'
+ req.body = jsonutils.dumps({
+ 'evacuate': {
+ 'onSharedStorage': 'False',
+ 'adminPass': 'MyNewPass'
+ }
+ })
+ req.content_type = 'application/json'
+ res = req.get_response(app)
+ self.assertEqual(res.status_int, 400)
+
+ def test_evacuate_instance_with_target(self):
+ ctxt = context.get_admin_context()
+ ctxt.user_id = 'fake'
+ ctxt.project_id = 'fake'
+ ctxt.is_admin = True
+ app = fakes.wsgi_app_v3(fake_auth_context=ctxt)
+ uuid1 = self.UUID
+ req = webob.Request.blank('/v3/servers/%s/action' % uuid1)
+ req.method = 'POST'
+ req.body = jsonutils.dumps({
+ 'evacuate': {
+ 'host': 'my_host',
+ 'onSharedStorage': 'false',
+ 'adminPass': 'MyNewPass'
+ }
+ })
+ req.content_type = 'application/json'
+
+ def fake_update(inst, context, instance,
+ task_state, expected_task_state):
+ return None
+
+ self.stubs.Set(compute_api.API, 'update', fake_update)
+
+ resp = req.get_response(app)
+ self.assertEqual(resp.status_int, 200)
+ resp_json = jsonutils.loads(resp.body)
+ self.assertEqual("MyNewPass", resp_json['adminPass'])
+
+ def test_evacuate_shared_and_pass(self):
+ ctxt = context.get_admin_context()
+ ctxt.user_id = 'fake'
+ ctxt.project_id = 'fake'
+ ctxt.is_admin = True
+ app = fakes.wsgi_app_v3(fake_auth_context=ctxt)
+ uuid1 = self.UUID
+ req = webob.Request.blank('/v3/servers/%s/action' % uuid1)
+ req.method = 'POST'
+ req.body = jsonutils.dumps({
+ 'evacuate': {
+ 'host': 'my_host',
+ 'onSharedStorage': 'True',
+ 'adminPass': 'MyNewPass'
+ }
+ })
+ req.content_type = 'application/json'
+
+ def fake_update(inst, context, instance,
+ task_state, expected_task_state):
+ return None
+
+ self.stubs.Set(compute_api.API, 'update', fake_update)
+
+ res = req.get_response(app)
+ self.assertEqual(res.status_int, 400)
+
+ def test_evacuate_not_shared_pass_generated(self):
+ ctxt = context.get_admin_context()
+ ctxt.user_id = 'fake'
+ ctxt.project_id = 'fake'
+ ctxt.is_admin = True
+ app = fakes.wsgi_app_v3(fake_auth_context=ctxt)
+ uuid1 = self.UUID
+ req = webob.Request.blank('/v3/servers/%s/action' % uuid1)
+ req.method = 'POST'
+ req.body = jsonutils.dumps({
+ 'evacuate': {
+ 'host': 'my_host',
+ 'onSharedStorage': 'False',
+ }
+ })
+
+ req.content_type = 'application/json'
+
+ def fake_update(inst, context, instance,
+ task_state, expected_task_state):
+ return None
+
+ self.stubs.Set(compute_api.API, 'update', fake_update)
+
+ resp = req.get_response(app)
+ self.assertEqual(resp.status_int, 200)
+ resp_json = jsonutils.loads(resp.body)
+ self.assertEqual(CONF.password_length, len(resp_json['adminPass']))
+
+ def test_evacuate_shared(self):
+ ctxt = context.get_admin_context()
+ ctxt.user_id = 'fake'
+ ctxt.project_id = 'fake'
+ ctxt.is_admin = True
+ app = fakes.wsgi_app_v3(fake_auth_context=ctxt)
+ uuid1 = self.UUID
+ req = webob.Request.blank('/v3/servers/%s/action' % uuid1)
+ req.method = 'POST'
+ req.body = jsonutils.dumps({
+ 'evacuate': {
+ 'host': 'my_host',
+ 'onSharedStorage': 'True',
+ }
+ })
+ req.content_type = 'application/json'
+
+ def fake_update(inst, context, instance,
+ task_state, expected_task_state):
+ return None
+
+ self.stubs.Set(compute_api.API, 'update', fake_update)
+
+ res = req.get_response(app)
+ self.assertEqual(res.status_int, 200)
+
+ def test_not_admin(self):
+ ctxt = context.RequestContext('fake', 'fake', is_admin=False)
+ app = fakes.wsgi_app_v3(fake_auth_context=ctxt)
+ uuid1 = self.UUID
+ req = webob.Request.blank('/v3/servers/%s/action' % uuid1)
+ req.method = 'POST'
+ req.body = jsonutils.dumps({
+ 'evacuate': {
+ 'host': 'my_host',
+ 'onSharedStorage': 'True',
+ }
+ })
+ req.content_type = 'application/json'
+ res = req.get_response(app)
+ self.assertEqual(res.status_int, 403)
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_extension_info.py b/nova/tests/api/openstack/compute/plugins/v3/test_extension_info.py
new file mode 100644
index 000000000..a19d28064
--- /dev/null
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_extension_info.py
@@ -0,0 +1,108 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from nova.api.openstack.compute import plugins
+from nova.api.openstack.compute.plugins.v3 import extension_info
+from nova import exception
+from nova import policy
+from nova import test
+from nova.tests.api.openstack import fakes
+
+
+class fake_extension(object):
+ def __init__(self, name, alias, description, namespace, version):
+ self.name = name
+ self.alias = alias
+ self.__doc__ = description
+ self.namespace = namespace
+ self.version = version
+
+
+fake_extensions = {
+ 'ext1-alias': fake_extension('ext1', 'ext1-alias', 'ext1 description',
+ 'ext1 namespace', 1),
+ 'ext2-alias': fake_extension('ext2', 'ext2-alias', 'ext2 description',
+ 'ext2 namespace', 2),
+ 'ext3-alias': fake_extension('ext3', 'ext3-alias', 'ext3 description',
+ 'ext3 namespace', 1)
+}
+
+def fake_policy_enforce(context, action, target, do_raise=True):
+ return True
+
+def fake_policy_enforce_selective(context, action, target, do_raise=True):
+ if action == 'compute_extension:v3:ext1-alias:discoverable':
+ raise exception.NotAuthorized
+ else:
+ return True
+
+
+class ExtensionInfoTest(test.TestCase):
+
+ def setUp(self):
+ super(ExtensionInfoTest, self).setUp()
+ ext_info = plugins.LoadedExtensionInfo()
+ ext_info.extensions = fake_extensions
+ self.controller = extension_info.ExtensionInfoController(ext_info)
+
+ def test_extension_info_list(self):
+ self.stubs.Set(policy, 'enforce', fake_policy_enforce)
+ req = fakes.HTTPRequestV3.blank('/extensions')
+ res_dict = self.controller.index(req)
+ self.assertEqual(3, len(res_dict['extensions']))
+ for e in res_dict['extensions']:
+ self.assertIn(e['alias'], fake_extensions)
+ self.assertEqual(e['name'], fake_extensions[e['alias']].name)
+ self.assertEqual(e['alias'], fake_extensions[e['alias']].alias)
+ self.assertEqual(e['description'],
+ fake_extensions[e['alias']].__doc__)
+ self.assertEqual(e['namespace'],
+ fake_extensions[e['alias']].namespace)
+ self.assertEqual(e['version'],
+ fake_extensions[e['alias']].version)
+
+ def test_extension_info_show(self):
+ self.stubs.Set(policy, 'enforce', fake_policy_enforce)
+ req = fakes.HTTPRequestV3.blank('/extensions/ext1-alias')
+ res_dict = self.controller.show(req, 'ext1-alias')
+ self.assertEqual(1, len(res_dict))
+ self.assertEqual(res_dict['extension']['name'],
+ fake_extensions['ext1-alias'].name)
+ self.assertEqual(res_dict['extension']['alias'],
+ fake_extensions['ext1-alias'].alias)
+ self.assertEqual(res_dict['extension']['description'],
+ fake_extensions['ext1-alias'].__doc__)
+ self.assertEqual(res_dict['extension']['namespace'],
+ fake_extensions['ext1-alias'].namespace)
+ self.assertEqual(res_dict['extension']['version'],
+ fake_extensions['ext1-alias'].version)
+
+ def test_extension_info_list_not_all_discoverable(self):
+ self.stubs.Set(policy, 'enforce', fake_policy_enforce_selective)
+ req = fakes.HTTPRequestV3.blank('/extensions')
+ res_dict = self.controller.index(req)
+ self.assertEqual(2, len(res_dict['extensions']))
+ for e in res_dict['extensions']:
+ self.assertNotEqual('ext1-alias', e['alias'])
+ self.assertIn(e['alias'], fake_extensions)
+ self.assertEqual(e['name'], fake_extensions[e['alias']].name)
+ self.assertEqual(e['alias'], fake_extensions[e['alias']].alias)
+ self.assertEqual(e['description'],
+ fake_extensions[e['alias']].__doc__)
+ self.assertEqual(e['namespace'],
+ fake_extensions[e['alias']].namespace)
+ self.assertEqual(e['version'],
+ fake_extensions[e['alias']].version)
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_flavor_access.py b/nova/tests/api/openstack/compute/plugins/v3/test_flavor_access.py
new file mode 100644
index 000000000..7d9ec93df
--- /dev/null
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_flavor_access.py
@@ -0,0 +1,308 @@
+# Copyright 2012 OpenStack Foundation
+# 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 datetime
+
+from lxml import etree
+from webob import exc
+
+from nova.api.openstack.compute.plugins.v3 import flavor_access
+from nova.api.openstack.compute import flavors as flavors_api
+from nova.compute import flavors
+from nova import context
+from nova import exception
+from nova import test
+from nova.tests.api.openstack import fakes
+
+
+def generate_flavor(flavorid, ispublic):
+ return {
+ 'id': flavorid,
+ 'flavorid': str(flavorid),
+ 'root_gb': 1,
+ 'ephemeral_gb': 1,
+ 'name': u'test',
+ 'deleted': False,
+ 'created_at': datetime.datetime(2012, 1, 1, 1, 1, 1, 1),
+ 'updated_at': None,
+ 'memory_mb': 512,
+ 'vcpus': 1,
+ 'swap': 512,
+ 'rxtx_factor': 1.0,
+ 'extra_specs': {},
+ 'deleted_at': None,
+ 'vcpu_weight': None,
+ 'is_public': bool(ispublic)
+ }
+
+
+INSTANCE_TYPES = {
+ '0': generate_flavor(0, True),
+ '1': generate_flavor(1, True),
+ '2': generate_flavor(2, False),
+ '3': generate_flavor(3, False)}
+
+
+ACCESS_LIST = [{'flavor_id': '2', 'project_id': 'proj2'},
+ {'flavor_id': '2', 'project_id': 'proj3'},
+ {'flavor_id': '3', 'project_id': 'proj3'}]
+
+
+def fake_get_flavor_access_by_flavor_id(flavorid):
+ res = []
+ for access in ACCESS_LIST:
+ if access['flavor_id'] == flavorid:
+ res.append(access)
+ return res
+
+
+def fake_get_flavor_by_flavor_id(flavorid):
+ return INSTANCE_TYPES[flavorid]
+
+
+def _has_flavor_access(flavorid, projectid):
+ for access in ACCESS_LIST:
+ if access['flavor_id'] == flavorid and \
+ access['project_id'] == projectid:
+ return True
+ return False
+
+
+def fake_get_all_flavors(context, inactive=0, filters=None):
+ if filters == None or filters['is_public'] == None:
+ return INSTANCE_TYPES
+
+ res = {}
+ for k, v in INSTANCE_TYPES.iteritems():
+ if filters['is_public'] and _has_flavor_access(k, context.project_id):
+ res.update({k: v})
+ continue
+ if v['is_public'] == filters['is_public']:
+ res.update({k: v})
+
+ return res
+
+
+class FakeRequest(object):
+ environ = {"nova.context": context.get_admin_context()}
+
+ def get_db_flavor(self, flavor_id):
+ return INSTANCE_TYPES[flavor_id]
+
+
+class FakeResponse(object):
+ obj = {'flavor': {'id': '0'},
+ 'flavors': [
+ {'id': '0'},
+ {'id': '2'}]
+ }
+
+ def attach(self, **kwargs):
+ pass
+
+
+class FlavorAccessTest(test.TestCase):
+ def setUp(self):
+ super(FlavorAccessTest, self).setUp()
+ self.flavor_controller = flavors_api.Controller()
+ self.flavor_access_controller = flavor_access.FlavorAccessController()
+ self.flavor_action_controller = flavor_access.FlavorActionController()
+ self.req = FakeRequest()
+ self.context = self.req.environ['nova.context']
+ self.stubs.Set(flavors, 'get_flavor_by_flavor_id',
+ fake_get_flavor_by_flavor_id)
+ self.stubs.Set(flavors, 'get_all_flavors', fake_get_all_flavors)
+ self.stubs.Set(flavors, 'get_flavor_access_by_flavor_id',
+ fake_get_flavor_access_by_flavor_id)
+
+ def _verify_flavor_list(self, result, expected):
+ # result already sorted by flavor_id
+ self.assertEqual(len(result), len(expected))
+
+ for d1, d2 in zip(result, expected):
+ self.assertEqual(d1['id'], d2['id'])
+
+ def test_list_flavor_access_public(self):
+ # query os-flavor-access on public flavor should return 404
+ req = fakes.HTTPRequest.blank('/v3/fake/flavors/os-flavor-access',
+ use_admin_context=True)
+ self.assertRaises(exc.HTTPNotFound,
+ self.flavor_access_controller.index,
+ self.req, '1')
+
+ def test_list_flavor_access_private(self):
+ expected = {'flavor_access': [
+ {'flavor_id': '2', 'tenant_id': 'proj2'},
+ {'flavor_id': '2', 'tenant_id': 'proj3'}]}
+ result = self.flavor_access_controller.index(self.req, '2')
+ self.assertEqual(result, expected)
+
+ def test_list_flavor_with_admin_default_proj1(self):
+ expected = {'flavors': [{'id': '0'}, {'id': '1'}]}
+ req = fakes.HTTPRequest.blank('/v3/fake/flavors',
+ use_admin_context=True)
+ req.environ['nova.context'].project_id = 'proj1'
+ result = self.flavor_controller.index(req)
+ self._verify_flavor_list(result['flavors'], expected['flavors'])
+
+ def test_list_flavor_with_admin_default_proj2(self):
+ expected = {'flavors': [{'id': '0'}, {'id': '1'}, {'id': '2'}]}
+ req = fakes.HTTPRequest.blank('/v3/fake/flavors',
+ use_admin_context=True)
+ req.environ['nova.context'].project_id = 'proj2'
+ result = self.flavor_controller.index(req)
+ self._verify_flavor_list(result['flavors'], expected['flavors'])
+
+ def test_list_flavor_with_admin_ispublic_true(self):
+ expected = {'flavors': [{'id': '0'}, {'id': '1'}]}
+ req = fakes.HTTPRequest.blank('/v3/fake/flavors?is_public=true',
+ use_admin_context=True)
+ result = self.flavor_controller.index(req)
+ self._verify_flavor_list(result['flavors'], expected['flavors'])
+
+ def test_list_flavor_with_admin_ispublic_false(self):
+ expected = {'flavors': [{'id': '2'}, {'id': '3'}]}
+ req = fakes.HTTPRequest.blank('/v3/fake/flavors?is_public=false',
+ use_admin_context=True)
+ result = self.flavor_controller.index(req)
+ self._verify_flavor_list(result['flavors'], expected['flavors'])
+
+ def test_list_flavor_with_admin_ispublic_false_proj2(self):
+ expected = {'flavors': [{'id': '2'}, {'id': '3'}]}
+ req = fakes.HTTPRequest.blank('/v3/fake/flavors?is_public=false',
+ use_admin_context=True)
+ req.environ['nova.context'].project_id = 'proj2'
+ result = self.flavor_controller.index(req)
+ self._verify_flavor_list(result['flavors'], expected['flavors'])
+
+ def test_list_flavor_with_admin_ispublic_none(self):
+ expected = {'flavors': [{'id': '0'}, {'id': '1'}, {'id': '2'},
+ {'id': '3'}]}
+ req = fakes.HTTPRequest.blank('/v3/fake/flavors?is_public=none',
+ use_admin_context=True)
+ result = self.flavor_controller.index(req)
+ self._verify_flavor_list(result['flavors'], expected['flavors'])
+
+ def test_list_flavor_with_no_admin_default(self):
+ expected = {'flavors': [{'id': '0'}, {'id': '1'}]}
+ req = fakes.HTTPRequest.blank('/v3/fake/flavors',
+ use_admin_context=False)
+ result = self.flavor_controller.index(req)
+ self._verify_flavor_list(result['flavors'], expected['flavors'])
+
+ def test_list_flavor_with_no_admin_ispublic_true(self):
+ expected = {'flavors': [{'id': '0'}, {'id': '1'}]}
+ req = fakes.HTTPRequest.blank('/v3/fake/flavors?is_public=true',
+ use_admin_context=False)
+ result = self.flavor_controller.index(req)
+ self._verify_flavor_list(result['flavors'], expected['flavors'])
+
+ def test_list_flavor_with_no_admin_ispublic_false(self):
+ expected = {'flavors': [{'id': '0'}, {'id': '1'}]}
+ req = fakes.HTTPRequest.blank('/v3/fake/flavors?is_public=false',
+ use_admin_context=False)
+ result = self.flavor_controller.index(req)
+ self._verify_flavor_list(result['flavors'], expected['flavors'])
+
+ def test_list_flavor_with_no_admin_ispublic_none(self):
+ expected = {'flavors': [{'id': '0'}, {'id': '1'}]}
+ req = fakes.HTTPRequest.blank('/v3/fake/flavors?is_public=none',
+ use_admin_context=False)
+ result = self.flavor_controller.index(req)
+ self._verify_flavor_list(result['flavors'], expected['flavors'])
+
+ def test_show(self):
+ resp = FakeResponse()
+ self.flavor_action_controller.show(self.req, resp, '0')
+ self.assertEqual({'id': '0', 'os-flavor-access:is_public': True},
+ resp.obj['flavor'])
+ self.flavor_action_controller.show(self.req, resp, '2')
+ self.assertEqual({'id': '0', 'os-flavor-access:is_public': False},
+ resp.obj['flavor'])
+
+ def test_detail(self):
+ resp = FakeResponse()
+ self.flavor_action_controller.detail(self.req, resp)
+ self.assertEqual([{'id': '0', 'os-flavor-access:is_public': True},
+ {'id': '2', 'os-flavor-access:is_public': False}],
+ resp.obj['flavors'])
+
+ def test_create(self):
+ resp = FakeResponse()
+ self.flavor_action_controller.create(self.req, {}, resp)
+ self.assertEqual({'id': '0', 'os-flavor-access:is_public': True},
+ resp.obj['flavor'])
+
+ def test_add_tenant_access(self):
+ def stub_add_flavor_access(flavorid, projectid, ctxt=None):
+ self.assertEqual('3', flavorid, "flavorid")
+ self.assertEqual("proj2", projectid, "projectid")
+ self.stubs.Set(flavors, 'add_flavor_access',
+ stub_add_flavor_access)
+ expected = {'flavor_access':
+ [{'flavor_id': '3', 'tenant_id': 'proj3'}]}
+ body = {'addTenantAccess': {'tenant': 'proj2'}}
+ req = fakes.HTTPRequest.blank('/v3/fake/flavors/2/action',
+ use_admin_context=True)
+ result = self.flavor_action_controller.\
+ _addTenantAccess(req, '3', body)
+ self.assertEqual(result, expected)
+
+ def test_add_tenant_access_with_already_added_access(self):
+ def stub_add_flavor_access(flavorid, projectid, ctxt=None):
+ raise exception.FlavorAccessExists(flavor_id=flavorid,
+ project_id=projectid)
+ self.stubs.Set(flavors, 'add_flavor_access',
+ stub_add_flavor_access)
+ body = {'addTenantAccess': {'tenant': 'proj2'}}
+ req = fakes.HTTPRequest.blank('/v3/fake/flavors/2/action',
+ use_admin_context=True)
+ self.assertRaises(exc.HTTPConflict,
+ self.flavor_action_controller._addTenantAccess,
+ self.req, '3', body)
+
+ def test_remove_tenant_access_with_bad_access(self):
+ def stub_remove_flavor_access(flavorid, projectid, ctxt=None):
+ raise exception.FlavorAccessNotFound(flavor_id=flavorid,
+ project_id=projectid)
+ self.stubs.Set(flavors, 'remove_flavor_access',
+ stub_remove_flavor_access)
+ body = {'removeTenantAccess': {'tenant': 'proj2'}}
+ req = fakes.HTTPRequest.blank('/v3/fake/flavors/2/action',
+ use_admin_context=True)
+ self.assertRaises(exc.HTTPNotFound,
+ self.flavor_action_controller._removeTenantAccess,
+ self.req, '3', body)
+
+
+class FlavorAccessSerializerTest(test.TestCase):
+ def test_serializer_empty(self):
+ serializer = flavor_access.FlavorAccessTemplate()
+ text = serializer.serialize(dict(flavor_access=[]))
+ tree = etree.fromstring(text)
+ self.assertEqual(len(tree), 0)
+
+ def test_serializer(self):
+ expected = ("<?xml version='1.0' encoding='UTF-8'?>\n"
+ '<flavor_access>'
+ '<access tenant_id="proj2" flavor_id="2"/>'
+ '<access tenant_id="proj3" flavor_id="2"/>'
+ '</flavor_access>')
+ access_list = [{'flavor_id': '2', 'tenant_id': 'proj2'},
+ {'flavor_id': '2', 'tenant_id': 'proj3'}]
+
+ serializer = flavor_access.FlavorAccessTemplate()
+ text = serializer.serialize(dict(flavor_access=access_list))
+ self.assertEqual(text, expected)
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_flavor_disabled.py b/nova/tests/api/openstack/compute/plugins/v3/test_flavor_disabled.py
new file mode 100644
index 000000000..5ff7f4035
--- /dev/null
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_flavor_disabled.py
@@ -0,0 +1,101 @@
+# Copyright 2012 Nebula, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from lxml import etree
+import webob
+
+from nova.api.openstack.compute.plugins.v3 import flavor_disabled
+from nova.compute import flavors
+from nova.openstack.common import jsonutils
+from nova import test
+from nova.tests.api.openstack import fakes
+
+FAKE_FLAVORS = {
+ 'flavor 1': {
+ "flavorid": '1',
+ "name": 'flavor 1',
+ "memory_mb": '256',
+ "root_gb": '10',
+ "disabled": False,
+ },
+ 'flavor 2': {
+ "flavorid": '2',
+ "name": 'flavor 2',
+ "memory_mb": '512',
+ "root_gb": '20',
+ "disabled": True,
+ },
+}
+
+
+def fake_flavor_get_by_flavor_id(flavorid):
+ return FAKE_FLAVORS['flavor %s' % flavorid]
+
+
+def fake_flavor_get_all(*args, **kwargs):
+ return FAKE_FLAVORS
+
+
+class FlavorDisabledTest(test.TestCase):
+ content_type = 'application/json'
+ prefix = '%s:' % flavor_disabled.FlavorDisabled.alias
+
+ def setUp(self):
+ super(FlavorDisabledTest, self).setUp()
+ fakes.stub_out_nw_api(self.stubs)
+ self.stubs.Set(flavors, "get_all_flavors",
+ fake_flavor_get_all)
+ self.stubs.Set(flavors,
+ "get_flavor_by_flavor_id",
+ fake_flavor_get_by_flavor_id)
+
+ def _make_request(self, url):
+ req = webob.Request.blank(url)
+ req.headers['Accept'] = self.content_type
+ app = fakes.wsgi_app_v3(init_only=('servers', 'flavors',
+ 'os-flavor-disabled'))
+ return req.get_response(app)
+
+ def _get_flavor(self, body):
+ return jsonutils.loads(body).get('flavor')
+
+ def _get_flavors(self, body):
+ return jsonutils.loads(body).get('flavors')
+
+ def assertFlavorDisabled(self, flavor, disabled):
+ self.assertEqual(str(flavor.get('%sdisabled' % self.prefix)), disabled)
+
+ def test_show(self):
+ res = self._make_request('/v3/flavors/1')
+ self.assertEqual(res.status_int, 200, res.body)
+ self.assertFlavorDisabled(self._get_flavor(res.body), 'False')
+
+ def test_detail(self):
+ res = self._make_request('/v3/flavors/detail')
+
+ self.assertEqual(res.status_int, 200, res.body)
+ flavors = self._get_flavors(res.body)
+ self.assertFlavorDisabled(flavors[0], 'False')
+ self.assertFlavorDisabled(flavors[1], 'True')
+
+
+class FlavorDisabledXmlTest(FlavorDisabledTest):
+ content_type = 'application/xml'
+ prefix = '{%s}' % flavor_disabled.FlavorDisabled.namespace
+
+ def _get_flavor(self, body):
+ return etree.XML(body)
+
+ def _get_flavors(self, body):
+ return etree.XML(body).getchildren()
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_flavors.py b/nova/tests/api/openstack/compute/plugins/v3/test_flavors.py
new file mode 100644
index 000000000..d204af11f
--- /dev/null
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_flavors.py
@@ -0,0 +1,696 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from lxml import etree
+import webob
+
+import urlparse
+
+from nova.api.openstack.compute.plugins.v3 import flavors
+from nova.api.openstack import xmlutil
+import nova.compute.flavors
+from nova import context
+from nova import db
+from nova import exception
+from nova import test
+from nova.tests.api.openstack import fakes
+from nova.tests import matchers
+
+NS = "{http://docs.openstack.org/compute/api/v1.1}"
+ATOMNS = "{http://www.w3.org/2005/Atom}"
+
+
+FAKE_FLAVORS = {
+ 'flavor 1': {
+ "flavorid": '1',
+ "name": 'flavor 1',
+ "memory_mb": '256',
+ "root_gb": '10',
+ },
+ 'flavor 2': {
+ "flavorid": '2',
+ "name": 'flavor 2',
+ "memory_mb": '512',
+ "root_gb": '20',
+ },
+}
+
+
+def fake_flavor_get_by_flavor_id(flavorid):
+ return FAKE_FLAVORS['flavor %s' % flavorid]
+
+
+def fake_flavor_get_all(inactive=False, filters=None):
+ def reject_min(db_attr, filter_attr):
+ return (filter_attr in filters and
+ int(flavor[db_attr]) < int(filters[filter_attr]))
+
+ filters = filters or {}
+ output = {}
+ for (flavor_name, flavor) in FAKE_FLAVORS.items():
+ if reject_min('memory_mb', 'min_memory_mb'):
+ continue
+ elif reject_min('root_gb', 'min_root_gb'):
+ continue
+
+ output[flavor_name] = flavor
+
+ return output
+
+
+def empty_flavor_get_all(inactive=False, filters=None):
+ return {}
+
+
+def return_flavor_not_found(flavor_id):
+ raise exception.InstanceTypeNotFound(instance_type_id=flavor_id)
+
+
+class FlavorsTest(test.TestCase):
+ def setUp(self):
+ super(FlavorsTest, self).setUp()
+ self.flags(osapi_compute_extension=[])
+ fakes.stub_out_networking(self.stubs)
+ fakes.stub_out_rate_limiting(self.stubs)
+ self.stubs.Set(nova.compute.flavors, "get_all_flavors",
+ fake_flavor_get_all)
+ self.stubs.Set(nova.compute.flavors,
+ "get_flavor_by_flavor_id",
+ fake_flavor_get_by_flavor_id)
+
+ self.controller = flavors.FlavorsController()
+
+ def test_get_flavor_by_invalid_id(self):
+ self.stubs.Set(nova.compute.flavors,
+ "get_flavor_by_flavor_id",
+ return_flavor_not_found)
+ req = fakes.HTTPRequestV3.blank('/flavors/asdf')
+ self.assertRaises(webob.exc.HTTPNotFound,
+ self.controller.show, req, 'asdf')
+
+ def test_get_flavor_by_id(self):
+ req = fakes.HTTPRequestV3.blank('/flavors/1')
+ flavor = self.controller.show(req, '1')
+ expected = {
+ "flavor": {
+ "id": "1",
+ "name": "flavor 1",
+ "ram": "256",
+ "disk": "10",
+ "vcpus": "",
+ "links": [
+ {
+ "rel": "self",
+ "href": "http://localhost/v3/flavors/1",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/flavors/1",
+ },
+ ],
+ },
+ }
+ self.assertEqual(flavor, expected)
+
+ def test_get_flavor_with_custom_link_prefix(self):
+ self.flags(osapi_compute_link_prefix='http://zoo.com:42',
+ osapi_glance_link_prefix='http://circus.com:34')
+ req = fakes.HTTPRequestV3.blank('/flavors/1')
+ flavor = self.controller.show(req, '1')
+ expected = {
+ "flavor": {
+ "id": "1",
+ "name": "flavor 1",
+ "ram": "256",
+ "disk": "10",
+ "vcpus": "",
+ "links": [
+ {
+ "rel": "self",
+ "href": "http://zoo.com:42/v3/flavors/1",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://zoo.com:42/flavors/1",
+ },
+ ],
+ },
+ }
+ self.assertEqual(flavor, expected)
+
+ def test_get_flavor_list(self):
+ req = fakes.HTTPRequestV3.blank('/flavors')
+ flavor = self.controller.index(req)
+ expected = {
+ "flavors": [
+ {
+ "id": "1",
+ "name": "flavor 1",
+ "links": [
+ {
+ "rel": "self",
+ "href": "http://localhost/v3/flavors/1",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/flavors/1",
+ },
+ ],
+ },
+ {
+ "id": "2",
+ "name": "flavor 2",
+ "links": [
+ {
+ "rel": "self",
+ "href": "http://localhost/v3/flavors/2",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/flavors/2",
+ },
+ ],
+ },
+ ],
+ }
+ self.assertEqual(flavor, expected)
+
+ def test_get_flavor_list_with_marker(self):
+ self.maxDiff = None
+ req = fakes.HTTPRequestV3.blank('/flavors?limit=1&marker=1')
+ flavor = self.controller.index(req)
+ expected = {
+ "flavors": [
+ {
+ "id": "2",
+ "name": "flavor 2",
+ "links": [
+ {
+ "rel": "self",
+ "href": "http://localhost/v3/flavors/2",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/flavors/2",
+ },
+ ],
+ },
+ ],
+ 'flavors_links': [
+ {'href': 'http://localhost/v3/flavors?limit=1&marker=2',
+ 'rel': 'next'}
+ ]
+ }
+ self.assertThat(flavor, matchers.DictMatches(expected))
+
+ def test_get_flavor_detail_with_limit(self):
+ req = fakes.HTTPRequestV3.blank('/flavors/detail?limit=1')
+ response = self.controller.index(req)
+ response_list = response["flavors"]
+ response_links = response["flavors_links"]
+
+ expected_flavors = [
+ {
+ "id": "1",
+ "name": "flavor 1",
+ "links": [
+ {
+ "rel": "self",
+ "href": "http://localhost/v3/flavors/1",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/flavors/1",
+ },
+ ],
+ },
+ ]
+ self.assertEqual(response_list, expected_flavors)
+ self.assertEqual(response_links[0]['rel'], 'next')
+
+ href_parts = urlparse.urlparse(response_links[0]['href'])
+ self.assertEqual('/v3/flavors', href_parts.path)
+ params = urlparse.parse_qs(href_parts.query)
+ self.assertThat({'limit': ['1'], 'marker': ['1']},
+ matchers.DictMatches(params))
+
+ def test_get_flavor_with_limit(self):
+ req = fakes.HTTPRequestV3.blank('/flavors?limit=2')
+ response = self.controller.index(req)
+ response_list = response["flavors"]
+ response_links = response["flavors_links"]
+
+ expected_flavors = [
+ {
+ "id": "1",
+ "name": "flavor 1",
+ "links": [
+ {
+ "rel": "self",
+ "href": "http://localhost/v3/flavors/1",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/flavors/1",
+ },
+ ],
+ },
+ {
+ "id": "2",
+ "name": "flavor 2",
+ "links": [
+ {
+ "rel": "self",
+ "href": "http://localhost/v3/flavors/2",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/flavors/2",
+ },
+ ],
+ }
+ ]
+ self.assertEqual(response_list, expected_flavors)
+ self.assertEqual(response_links[0]['rel'], 'next')
+
+ href_parts = urlparse.urlparse(response_links[0]['href'])
+ self.assertEqual('/v3/flavors', href_parts.path)
+ params = urlparse.parse_qs(href_parts.query)
+ self.assertThat({'limit': ['2'], 'marker': ['2']},
+ matchers.DictMatches(params))
+
+ def test_get_flavor_list_detail(self):
+ req = fakes.HTTPRequestV3.blank('/flavors/detail')
+ flavor = self.controller.detail(req)
+ expected = {
+ "flavors": [
+ {
+ "id": "1",
+ "name": "flavor 1",
+ "ram": "256",
+ "disk": "10",
+ "vcpus": "",
+ "links": [
+ {
+ "rel": "self",
+ "href": "http://localhost/v3/flavors/1",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/flavors/1",
+ },
+ ],
+ },
+ {
+ "id": "2",
+ "name": "flavor 2",
+ "ram": "512",
+ "disk": "20",
+ "vcpus": "",
+ "links": [
+ {
+ "rel": "self",
+ "href": "http://localhost/v3/flavors/2",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/flavors/2",
+ },
+ ],
+ },
+ ],
+ }
+ self.assertEqual(flavor, expected)
+
+ def test_get_empty_flavor_list(self):
+ self.stubs.Set(nova.compute.flavors, "get_all_flavors",
+ empty_flavor_get_all)
+
+ req = fakes.HTTPRequestV3.blank('/flavors')
+ flavors = self.controller.index(req)
+ expected = {'flavors': []}
+ self.assertEqual(flavors, expected)
+
+ def test_get_flavor_list_filter_min_ram(self):
+ # Flavor lists may be filtered by minRam.
+ req = fakes.HTTPRequestV3.blank('/flavors?minRam=512')
+ flavor = self.controller.index(req)
+ expected = {
+ "flavors": [
+ {
+ "id": "2",
+ "name": "flavor 2",
+ "links": [
+ {
+ "rel": "self",
+ "href": "http://localhost/v3/flavors/2",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/flavors/2",
+ },
+ ],
+ },
+ ],
+ }
+ self.assertEqual(flavor, expected)
+
+ def test_get_flavor_list_filter_invalid_min_ram(self):
+ # Ensure you cannot list flavors with invalid minRam param.
+ req = fakes.HTTPRequestV3.blank('/flavors?minRam=NaN')
+ self.assertRaises(webob.exc.HTTPBadRequest,
+ self.controller.index, req)
+
+ def test_get_flavor_list_filter_min_disk(self):
+ # Flavor lists may be filtered by minDisk.
+ req = fakes.HTTPRequestV3.blank('/flavors?minDisk=20')
+ flavor = self.controller.index(req)
+ expected = {
+ "flavors": [
+ {
+ "id": "2",
+ "name": "flavor 2",
+ "links": [
+ {
+ "rel": "self",
+ "href": "http://localhost/v3/flavors/2",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/flavors/2",
+ },
+ ],
+ },
+ ],
+ }
+ self.assertEqual(flavor, expected)
+
+ def test_get_flavor_list_filter_invalid_min_disk(self):
+ # Ensure you cannot list flavors with invalid minDisk param.
+ req = fakes.HTTPRequestV3.blank('/flavors?minDisk=NaN')
+ self.assertRaises(webob.exc.HTTPBadRequest,
+ self.controller.index, req)
+
+ def test_get_flavor_list_detail_min_ram_and_min_disk(self):
+ """Tests that filtering work on flavor details and that minRam and
+ minDisk filters can be combined
+ """
+ req = fakes.HTTPRequestV3.blank('/flavors/detail'
+ '?minRam=256&minDisk=20')
+ flavor = self.controller.detail(req)
+ expected = {
+ "flavors": [
+ {
+ "id": "2",
+ "name": "flavor 2",
+ "ram": "512",
+ "disk": "20",
+ "vcpus": "",
+ "links": [
+ {
+ "rel": "self",
+ "href": "http://localhost/v3/flavors/2",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/flavors/2",
+ },
+ ],
+ },
+ ],
+ }
+ self.assertEqual(flavor, expected)
+
+
+class FlavorsXMLSerializationTest(test.TestCase):
+ def _create_flavor(self):
+ id = 0
+ while True:
+ id += 1
+ yield {
+ "id": str(id),
+ "name": "asdf",
+ "ram": "256",
+ "disk": "10",
+ "vcpus": "",
+ "swap": "512",
+ "links": [
+ {
+ "rel": "self",
+ "href": "http://localhost/v3/flavors/%s" % id,
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/flavors/%s" % id,
+ },
+ ],
+ }
+
+ def setUp(self):
+ super(FlavorsXMLSerializationTest, self).setUp()
+ self.flavors = self._create_flavor()
+
+ def test_xml_declaration(self):
+ serializer = flavors.FlavorTemplate()
+ fixture = {'flavor': next(self.flavors)}
+ output = serializer.serialize(fixture)
+ has_dec = output.startswith("<?xml version='1.0' encoding='UTF-8'?>")
+ self.assertTrue(has_dec)
+
+ def test_show(self):
+ serializer = flavors.FlavorTemplate()
+
+ fixture = {'flavor': next(self.flavors)}
+ output = serializer.serialize(fixture)
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'flavor', version='v3')
+ flavor_dict = fixture['flavor']
+
+ for key in ['name', 'id', 'ram', 'disk']:
+ self.assertEqual(root.get(key), str(flavor_dict[key]))
+
+ link_nodes = root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(flavor_dict['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ def test_show_handles_integers(self):
+ serializer = flavors.FlavorTemplate()
+
+ fixture = {'flavor': next(self.flavors)}
+ output = serializer.serialize(fixture)
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'flavor', version='v3')
+ flavor_dict = fixture['flavor']
+
+ for key in ['name', 'id', 'ram', 'disk']:
+ self.assertEqual(root.get(key), str(flavor_dict[key]))
+
+ link_nodes = root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(flavor_dict['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ def test_detail(self):
+ serializer = flavors.FlavorsTemplate()
+
+ fixture = {
+ "flavors": [
+ next(self.flavors),
+ next(self.flavors),
+ ],
+ }
+
+ output = serializer.serialize(fixture)
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'flavors', version='v3')
+ flavor_elems = root.findall('{0}flavor'.format(NS))
+ self.assertEqual(len(flavor_elems), 2)
+ for i, flavor_elem in enumerate(flavor_elems):
+ flavor_dict = fixture['flavors'][i]
+
+ for key in ['name', 'id', 'ram', 'disk']:
+ self.assertEqual(flavor_elem.get(key), str(flavor_dict[key]))
+
+ link_nodes = flavor_elem.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(flavor_dict['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ def test_index(self):
+ serializer = flavors.MinimalFlavorsTemplate()
+
+ fixture = {
+ "flavors": [
+ next(self.flavors),
+ next(self.flavors),
+ ],
+ }
+
+ output = serializer.serialize(fixture)
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'flavors_index')
+ flavor_elems = root.findall('{0}flavor'.format(NS))
+ self.assertEqual(len(flavor_elems), 2)
+ for i, flavor_elem in enumerate(flavor_elems):
+ flavor_dict = fixture['flavors'][i]
+
+ for key in ['name', 'id']:
+ self.assertEqual(flavor_elem.get(key), str(flavor_dict[key]))
+
+ link_nodes = flavor_elem.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(flavor_dict['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ def test_index_empty(self):
+ serializer = flavors.MinimalFlavorsTemplate()
+
+ fixture = {
+ "flavors": [],
+ }
+
+ output = serializer.serialize(fixture)
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'flavors_index')
+ flavor_elems = root.findall('{0}flavor'.format(NS))
+ self.assertEqual(len(flavor_elems), 0)
+
+
+class DisabledFlavorsWithRealDBTest(test.TestCase):
+ """
+ Tests that disabled flavors should not be shown nor listed.
+ """
+ def setUp(self):
+ super(DisabledFlavorsWithRealDBTest, self).setUp()
+ self.controller = flavors.FlavorsController()
+
+ # Add a new disabled type to the list of flavors
+ self.req = fakes.HTTPRequestV3.blank('/flavors')
+ self.context = self.req.environ['nova.context']
+ self.admin_context = context.get_admin_context()
+
+ self.disabled_type = self._create_disabled_instance_type()
+ self.inst_types = db.api.instance_type_get_all(self.admin_context)
+
+ def tearDown(self):
+ db.api.instance_type_destroy(self.admin_context,
+ self.disabled_type['name'])
+
+ super(DisabledFlavorsWithRealDBTest, self).tearDown()
+
+ def _create_disabled_instance_type(self):
+ inst_types = db.api.instance_type_get_all(self.admin_context)
+
+ inst_type = inst_types[0]
+
+ del inst_type['id']
+ inst_type['name'] += '.disabled'
+ inst_type['flavorid'] = unicode(max(
+ [int(flavor['flavorid']) for flavor in inst_types]) + 1)
+ inst_type['disabled'] = True
+
+ disabled_type = db.api.instance_type_create(self.admin_context,
+ inst_type)
+
+ return disabled_type
+
+ def test_index_should_not_list_disabled_flavors_to_user(self):
+ self.context.is_admin = False
+
+ flavor_list = self.controller.index(self.req)['flavors']
+ api_flavorids = set(f['id'] for f in flavor_list)
+
+ db_flavorids = set(i['flavorid'] for i in self.inst_types)
+ disabled_flavorid = str(self.disabled_type['flavorid'])
+
+ self.assert_(disabled_flavorid in db_flavorids)
+ self.assertEqual(db_flavorids - set([disabled_flavorid]),
+ api_flavorids)
+
+ def test_index_should_list_disabled_flavors_to_admin(self):
+ self.context.is_admin = True
+
+ flavor_list = self.controller.index(self.req)['flavors']
+ api_flavorids = set(f['id'] for f in flavor_list)
+
+ db_flavorids = set(i['flavorid'] for i in self.inst_types)
+ disabled_flavorid = str(self.disabled_type['flavorid'])
+
+ self.assert_(disabled_flavorid in db_flavorids)
+ self.assertEqual(db_flavorids, api_flavorids)
+
+ def test_show_should_include_disabled_flavor_for_user(self):
+ """
+ Counterintuitively we should show disabled flavors to all users and not
+ just admins. The reason is that, when a user performs a server-show
+ request, we want to be able to display the pretty flavor name ('512 MB
+ Instance') and not just the flavor-id even if the flavor id has been
+ marked disabled.
+ """
+ self.context.is_admin = False
+
+ flavor = self.controller.show(
+ self.req, self.disabled_type['flavorid'])['flavor']
+
+ self.assertEqual(flavor['name'], self.disabled_type['name'])
+
+ def test_show_should_include_disabled_flavor_for_admin(self):
+ self.context.is_admin = True
+
+ flavor = self.controller.show(
+ self.req, self.disabled_type['flavorid'])['flavor']
+
+ self.assertEqual(flavor['name'], self.disabled_type['name'])
+
+
+class ParseIsPublicTest(test.TestCase):
+ def setUp(self):
+ super(ParseIsPublicTest, self).setUp()
+ self.controller = flavors.FlavorsController()
+
+ def assertPublic(self, expected, is_public):
+ self.assertIs(expected, self.controller._parse_is_public(is_public),
+ '%s did not return %s' % (is_public, expected))
+
+ def test_None(self):
+ self.assertPublic(True, None)
+
+ def test_truthy(self):
+ self.assertPublic(True, True)
+ self.assertPublic(True, 't')
+ self.assertPublic(True, 'true')
+ self.assertPublic(True, 'yes')
+ self.assertPublic(True, '1')
+
+ def test_falsey(self):
+ self.assertPublic(False, False)
+ self.assertPublic(False, 'f')
+ self.assertPublic(False, 'false')
+ self.assertPublic(False, 'no')
+ self.assertPublic(False, '0')
+
+ def test_string_none(self):
+ self.assertPublic(None, 'none')
+
+ def test_other(self):
+ self.assertRaises(
+ webob.exc.HTTPBadRequest, self.assertPublic, None, 'other')
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_images.py b/nova/tests/api/openstack/compute/plugins/v3/test_images.py
new file mode 100644
index 000000000..712e3c8a5
--- /dev/null
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_images.py
@@ -0,0 +1,1336 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2010 OpenStack Foundation
+# 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 of the new image services, both as a service layer,
+and as a WSGI layer
+"""
+
+import urlparse
+
+from lxml import etree
+import webob
+
+from nova.api.openstack.compute.plugins.v3 import images
+from nova.api.openstack.compute.views import images as images_view
+from nova.api.openstack import xmlutil
+from nova import exception
+from nova.image import glance
+from nova import test
+from nova.tests.api.openstack import fakes
+from nova.tests import matchers
+
+NS = "{http://docs.openstack.org/compute/api/v1.1}"
+ATOMNS = "{http://www.w3.org/2005/Atom}"
+NOW_API_FORMAT = "2010-10-11T10:30:22Z"
+
+
+class ImagesControllerTest(test.TestCase):
+ """
+ Test of the OpenStack API /images application controller w/Glance.
+ """
+
+ def setUp(self):
+ """Run before each test."""
+ super(ImagesControllerTest, self).setUp()
+ fakes.stub_out_networking(self.stubs)
+ fakes.stub_out_rate_limiting(self.stubs)
+ fakes.stub_out_key_pair_funcs(self.stubs)
+ fakes.stub_out_compute_api_snapshot(self.stubs)
+ fakes.stub_out_compute_api_backup(self.stubs)
+ fakes.stub_out_glance(self.stubs)
+
+ self.controller = images.ImagesController()
+
+ def test_get_image(self):
+ fake_req = fakes.HTTPRequestV3.blank('/os-images/123')
+ actual_image = self.controller.show(fake_req, '124')
+
+ href = "http://localhost/v3/images/124"
+ bookmark = "http://localhost/images/124"
+ alternate = "%s/fake/images/124" % glance.generate_glance_url()
+ server_uuid = "aa640691-d1a7-4a67-9d3c-d35ee6b3cc74"
+ server_href = "http://localhost/v3/servers/" + server_uuid
+ server_bookmark = "http://localhost/servers/" + server_uuid
+
+ expected_image = {
+ "image": {
+ "id": "124",
+ "name": "queued snapshot",
+ "updated": NOW_API_FORMAT,
+ "created": NOW_API_FORMAT,
+ "status": "SAVING",
+ "progress": 25,
+ "minDisk": 0,
+ "minRam": 0,
+ 'server': {
+ 'id': server_uuid,
+ "links": [{
+ "rel": "self",
+ "href": server_href,
+ },
+ {
+ "rel": "bookmark",
+ "href": server_bookmark,
+ }],
+ },
+ "metadata": {
+ "instance_uuid": server_uuid,
+ "user_id": "fake",
+ },
+ "links": [{
+ "rel": "self",
+ "href": href,
+ },
+ {
+ "rel": "bookmark",
+ "href": bookmark,
+ },
+ {
+ "rel": "alternate",
+ "type": "application/vnd.openstack.image",
+ "href": alternate
+ }],
+ },
+ }
+
+ self.assertThat(actual_image, matchers.DictMatches(expected_image))
+
+ def test_get_image_with_custom_prefix(self):
+ self.flags(osapi_compute_link_prefix='https://zoo.com:42',
+ osapi_glance_link_prefix='http://circus.com:34')
+ fake_req = fakes.HTTPRequestV3.blank('/v3/os-images/124')
+ actual_image = self.controller.show(fake_req, '124')
+ href = "https://zoo.com:42/v3/images/124"
+ bookmark = "https://zoo.com:42/images/124"
+ alternate = "http://circus.com:34/fake/images/124"
+ server_uuid = "aa640691-d1a7-4a67-9d3c-d35ee6b3cc74"
+ server_href = "https://zoo.com:42/v3/servers/" + server_uuid
+ server_bookmark = "https://zoo.com:42/servers/" + server_uuid
+
+ expected_image = {
+ "image": {
+ "id": "124",
+ "name": "queued snapshot",
+ "updated": NOW_API_FORMAT,
+ "created": NOW_API_FORMAT,
+ "status": "SAVING",
+ "progress": 25,
+ "minDisk": 0,
+ "minRam": 0,
+ 'server': {
+ 'id': server_uuid,
+ "links": [{
+ "rel": "self",
+ "href": server_href,
+ },
+ {
+ "rel": "bookmark",
+ "href": server_bookmark,
+ }],
+ },
+ "metadata": {
+ "instance_uuid": server_uuid,
+ "user_id": "fake",
+ },
+ "links": [{
+ "rel": "self",
+ "href": href,
+ },
+ {
+ "rel": "bookmark",
+ "href": bookmark,
+ },
+ {
+ "rel": "alternate",
+ "type": "application/vnd.openstack.image",
+ "href": alternate
+ }],
+ },
+ }
+ self.assertThat(actual_image, matchers.DictMatches(expected_image))
+
+ def test_get_image_404(self):
+ fake_req = fakes.HTTPRequestV3.blank('/os-images/unknown')
+ self.assertRaises(webob.exc.HTTPNotFound,
+ self.controller.show, fake_req, 'unknown')
+
+ def test_get_image_details(self):
+ request = fakes.HTTPRequestV3.blank('/os-images/detail')
+ response = self.controller.detail(request)
+ response_list = response["images"]
+
+ server_uuid = "aa640691-d1a7-4a67-9d3c-d35ee6b3cc74"
+ server_href = "http://localhost/v3/servers/" + server_uuid
+ server_bookmark = "http://localhost/servers/" + server_uuid
+ alternate = "%s/fake/images/%s"
+
+ expected = [{
+ 'id': '123',
+ 'name': 'public image',
+ 'metadata': {'key1': 'value1'},
+ 'updated': NOW_API_FORMAT,
+ 'created': NOW_API_FORMAT,
+ 'status': 'ACTIVE',
+ 'progress': 100,
+ 'minDisk': 10,
+ 'minRam': 128,
+ "links": [{
+ "rel": "self",
+ "href": "http://localhost/v3/images/123",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/images/123",
+ },
+ {
+ "rel": "alternate",
+ "type": "application/vnd.openstack.image",
+ "href": alternate % (glance.generate_glance_url(), 123),
+ }],
+ },
+ {
+ 'id': '124',
+ 'name': 'queued snapshot',
+ 'metadata': {
+ u'instance_uuid': server_uuid,
+ u'user_id': u'fake',
+ },
+ 'updated': NOW_API_FORMAT,
+ 'created': NOW_API_FORMAT,
+ 'status': 'SAVING',
+ 'progress': 25,
+ 'minDisk': 0,
+ 'minRam': 0,
+ 'server': {
+ 'id': server_uuid,
+ "links": [{
+ "rel": "self",
+ "href": server_href,
+ },
+ {
+ "rel": "bookmark",
+ "href": server_bookmark,
+ }],
+ },
+ "links": [{
+ "rel": "self",
+ "href": "http://localhost/v3/images/124",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/images/124",
+ },
+ {
+ "rel": "alternate",
+ "type": "application/vnd.openstack.image",
+ "href": alternate % (glance.generate_glance_url(), 124),
+ }],
+ },
+ {
+ 'id': '125',
+ 'name': 'saving snapshot',
+ 'metadata': {
+ u'instance_uuid': server_uuid,
+ u'user_id': u'fake',
+ },
+ 'updated': NOW_API_FORMAT,
+ 'created': NOW_API_FORMAT,
+ 'status': 'SAVING',
+ 'progress': 50,
+ 'minDisk': 0,
+ 'minRam': 0,
+ 'server': {
+ 'id': server_uuid,
+ "links": [{
+ "rel": "self",
+ "href": server_href,
+ },
+ {
+ "rel": "bookmark",
+ "href": server_bookmark,
+ }],
+ },
+ "links": [{
+ "rel": "self",
+ "href": "http://localhost/v3/images/125",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/images/125",
+ },
+ {
+ "rel": "alternate",
+ "type": "application/vnd.openstack.image",
+ "href": "%s/fake/images/125" % glance.generate_glance_url()
+ }],
+ },
+ {
+ 'id': '126',
+ 'name': 'active snapshot',
+ 'metadata': {
+ u'instance_uuid': server_uuid,
+ u'user_id': u'fake',
+ },
+ 'updated': NOW_API_FORMAT,
+ 'created': NOW_API_FORMAT,
+ 'status': 'ACTIVE',
+ 'progress': 100,
+ 'minDisk': 0,
+ 'minRam': 0,
+ 'server': {
+ 'id': server_uuid,
+ "links": [{
+ "rel": "self",
+ "href": server_href,
+ },
+ {
+ "rel": "bookmark",
+ "href": server_bookmark,
+ }],
+ },
+ "links": [{
+ "rel": "self",
+ "href": "http://localhost/v3/images/126",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/images/126",
+ },
+ {
+ "rel": "alternate",
+ "type": "application/vnd.openstack.image",
+ "href": "%s/fake/images/126" % glance.generate_glance_url()
+ }],
+ },
+ {
+ 'id': '127',
+ 'name': 'killed snapshot',
+ 'metadata': {
+ u'instance_uuid': server_uuid,
+ u'user_id': u'fake',
+ },
+ 'updated': NOW_API_FORMAT,
+ 'created': NOW_API_FORMAT,
+ 'status': 'ERROR',
+ 'progress': 0,
+ 'minDisk': 0,
+ 'minRam': 0,
+ 'server': {
+ 'id': server_uuid,
+ "links": [{
+ "rel": "self",
+ "href": server_href,
+ },
+ {
+ "rel": "bookmark",
+ "href": server_bookmark,
+ }],
+ },
+ "links": [{
+ "rel": "self",
+ "href": "http://localhost/v3/images/127",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/images/127",
+ },
+ {
+ "rel": "alternate",
+ "type": "application/vnd.openstack.image",
+ "href": "%s/fake/images/127" % glance.generate_glance_url()
+ }],
+ },
+ {
+ 'id': '128',
+ 'name': 'deleted snapshot',
+ 'metadata': {
+ u'instance_uuid': server_uuid,
+ u'user_id': u'fake',
+ },
+ 'updated': NOW_API_FORMAT,
+ 'created': NOW_API_FORMAT,
+ 'status': 'DELETED',
+ 'progress': 0,
+ 'minDisk': 0,
+ 'minRam': 0,
+ 'server': {
+ 'id': server_uuid,
+ "links": [{
+ "rel": "self",
+ "href": server_href,
+ },
+ {
+ "rel": "bookmark",
+ "href": server_bookmark,
+ }],
+ },
+ "links": [{
+ "rel": "self",
+ "href": "http://localhost/v3/images/128",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/images/128",
+ },
+ {
+ "rel": "alternate",
+ "type": "application/vnd.openstack.image",
+ "href": "%s/fake/images/128" % glance.generate_glance_url()
+ }],
+ },
+ {
+ 'id': '129',
+ 'name': 'pending_delete snapshot',
+ 'metadata': {
+ u'instance_uuid': server_uuid,
+ u'user_id': u'fake',
+ },
+ 'updated': NOW_API_FORMAT,
+ 'created': NOW_API_FORMAT,
+ 'status': 'DELETED',
+ 'progress': 0,
+ 'minDisk': 0,
+ 'minRam': 0,
+ 'server': {
+ 'id': server_uuid,
+ "links": [{
+ "rel": "self",
+ "href": server_href,
+ },
+ {
+ "rel": "bookmark",
+ "href": server_bookmark,
+ }],
+ },
+ "links": [{
+ "rel": "self",
+ "href": "http://localhost/v3/images/129",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/images/129",
+ },
+ {
+ "rel": "alternate",
+ "type": "application/vnd.openstack.image",
+ "href": "%s/fake/images/129" % glance.generate_glance_url()
+ }],
+ },
+ {
+ 'id': '130',
+ 'name': None,
+ 'metadata': {},
+ 'updated': NOW_API_FORMAT,
+ 'created': NOW_API_FORMAT,
+ 'status': 'ACTIVE',
+ 'progress': 100,
+ 'minDisk': 0,
+ 'minRam': 0,
+ "links": [{
+ "rel": "self",
+ "href": "http://localhost/v3/images/130",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/images/130",
+ },
+ {
+ "rel": "alternate",
+ "type": "application/vnd.openstack.image",
+ "href": "%s/fake/images/130" % glance.generate_glance_url()
+ }],
+ },
+ ]
+
+ self.assertThat(expected, matchers.DictListMatches(response_list))
+
+ def test_get_image_details_with_limit(self):
+ request = fakes.HTTPRequestV3.blank('/os-images/detail?limit=2')
+ response = self.controller.detail(request)
+ response_list = response["images"]
+ response_links = response["images_links"]
+
+ server_uuid = "aa640691-d1a7-4a67-9d3c-d35ee6b3cc74"
+ server_href = "http://localhost/v3/servers/" + server_uuid
+ server_bookmark = "http://localhost/servers/" + server_uuid
+ alternate = "%s/fake/images/%s"
+
+ expected = [{
+ 'id': '123',
+ 'name': 'public image',
+ 'metadata': {'key1': 'value1'},
+ 'updated': NOW_API_FORMAT,
+ 'created': NOW_API_FORMAT,
+ 'status': 'ACTIVE',
+ 'minDisk': 10,
+ 'progress': 100,
+ 'minRam': 128,
+ "links": [{
+ "rel": "self",
+ "href": "http://localhost/v3/images/123",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/images/123",
+ },
+ {
+ "rel": "alternate",
+ "type": "application/vnd.openstack.image",
+ "href": alternate % (glance.generate_glance_url(), 123),
+ }],
+ },
+ {
+ 'id': '124',
+ 'name': 'queued snapshot',
+ 'metadata': {
+ u'instance_uuid': server_uuid,
+ u'user_id': u'fake',
+ },
+ 'updated': NOW_API_FORMAT,
+ 'created': NOW_API_FORMAT,
+ 'status': 'SAVING',
+ 'minDisk': 0,
+ 'progress': 25,
+ 'minRam': 0,
+ 'server': {
+ 'id': server_uuid,
+ "links": [{
+ "rel": "self",
+ "href": server_href,
+ },
+ {
+ "rel": "bookmark",
+ "href": server_bookmark,
+ }],
+ },
+ "links": [{
+ "rel": "self",
+ "href": "http://localhost/v3/images/124",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://localhost/images/124",
+ },
+ {
+ "rel": "alternate",
+ "type": "application/vnd.openstack.image",
+ "href": alternate % (glance.generate_glance_url(), 124),
+ }],
+ }]
+
+ self.assertThat(expected, matchers.DictListMatches(response_list))
+
+ href_parts = urlparse.urlparse(response_links[0]['href'])
+ self.assertEqual('/v3/images', href_parts.path)
+ params = urlparse.parse_qs(href_parts.query)
+
+ self.assertThat({'limit': ['2'], 'marker': ['124']},
+ matchers.DictMatches(params))
+
+ def test_image_detail_filter_with_name(self):
+ image_service = self.mox.CreateMockAnything()
+ filters = {'name': 'testname'}
+ request = fakes.HTTPRequestV3.blank('/v3/os-images/detail'
+ '?name=testname')
+ context = request.environ['nova.context']
+ image_service.detail(context, filters=filters).AndReturn([])
+ self.mox.ReplayAll()
+ controller = images.ImagesController(image_service=image_service)
+ controller.detail(request)
+
+ def test_image_detail_filter_with_status(self):
+ image_service = self.mox.CreateMockAnything()
+ filters = {'status': 'active'}
+ request = fakes.HTTPRequestV3.blank('/v3/os-images/detail'
+ '?status=ACTIVE')
+ context = request.environ['nova.context']
+ image_service.detail(context, filters=filters).AndReturn([])
+ self.mox.ReplayAll()
+ controller = images.ImagesController(image_service=image_service)
+ controller.detail(request)
+
+ def test_image_detail_filter_with_property(self):
+ image_service = self.mox.CreateMockAnything()
+ filters = {'property-test': '3'}
+ request = fakes.HTTPRequestV3.blank('/v3/os-images/detail'
+ '?property-test=3')
+ context = request.environ['nova.context']
+ image_service.detail(context, filters=filters).AndReturn([])
+ self.mox.ReplayAll()
+ controller = images.ImagesController(image_service=image_service)
+ controller.detail(request)
+
+ def test_image_detail_filter_server_href(self):
+ image_service = self.mox.CreateMockAnything()
+ uuid = 'fa95aaf5-ab3b-4cd8-88c0-2be7dd051aaf'
+ ref = 'http://localhost:8774/servers/' + uuid
+ url = '/v3/os-images/detail?server=' + ref
+ filters = {'property-instance_uuid': uuid}
+ request = fakes.HTTPRequestV3.blank(url)
+ context = request.environ['nova.context']
+ image_service.detail(context, filters=filters).AndReturn([])
+ self.mox.ReplayAll()
+ controller = images.ImagesController(image_service=image_service)
+ controller.detail(request)
+
+ def test_image_detail_filter_server_uuid(self):
+ image_service = self.mox.CreateMockAnything()
+ uuid = 'fa95aaf5-ab3b-4cd8-88c0-2be7dd051aaf'
+ url = '/v2/fake/images/detail?server=' + uuid
+ filters = {'property-instance_uuid': uuid}
+ request = fakes.HTTPRequestV3.blank(url)
+ context = request.environ['nova.context']
+ image_service.detail(context, filters=filters).AndReturn([])
+ self.mox.ReplayAll()
+ controller = images.ImagesController(image_service=image_service)
+ controller.detail(request)
+
+ def test_image_detail_filter_changes_since(self):
+ image_service = self.mox.CreateMockAnything()
+ filters = {'changes-since': '2011-01-24T17:08Z'}
+ request = fakes.HTTPRequestV3.blank('/v3/os-images/detail'
+ '?changes-since=2011-01-24T17:08Z')
+ context = request.environ['nova.context']
+ image_service.detail(context, filters=filters).AndReturn([])
+ self.mox.ReplayAll()
+ controller = images.ImagesController(image_service=image_service)
+ controller.detail(request)
+
+ def test_image_detail_filter_with_type(self):
+ image_service = self.mox.CreateMockAnything()
+ filters = {'property-image_type': 'BASE'}
+ request = fakes.HTTPRequestV3.blank('/v3/os-images/detail?type=BASE')
+ context = request.environ['nova.context']
+ image_service.detail(context, filters=filters).AndReturn([])
+ self.mox.ReplayAll()
+ controller = images.ImagesController(image_service=image_service)
+ controller.detail(request)
+
+ def test_image_detail_filter_not_supported(self):
+ image_service = self.mox.CreateMockAnything()
+ filters = {'status': 'active'}
+ request = fakes.HTTPRequestV3.blank('/v3/os-images/detail?status='
+ 'ACTIVE&UNSUPPORTEDFILTER=testname')
+ context = request.environ['nova.context']
+ image_service.detail(context, filters=filters).AndReturn([])
+ self.mox.ReplayAll()
+ controller = images.ImagesController(image_service=image_service)
+ controller.detail(request)
+
+ def test_image_detail_no_filters(self):
+ image_service = self.mox.CreateMockAnything()
+ filters = {}
+ request = fakes.HTTPRequestV3.blank('/v3/os-images/detail')
+ context = request.environ['nova.context']
+ image_service.detail(context, filters=filters).AndReturn([])
+ self.mox.ReplayAll()
+ controller = images.ImagesController(image_service=image_service)
+ controller.detail(request)
+
+ def test_image_detail_invalid_marker(self):
+ class InvalidImageService(object):
+
+ def detail(self, *args, **kwargs):
+ raise exception.Invalid('meow')
+
+ request = fakes.HTTPRequestV3.blank('/v3/os-images?marker=invalid')
+ controller = images.ImagesController(image_service=InvalidImageService())
+ self.assertRaises(webob.exc.HTTPBadRequest, controller.detail, request)
+
+ def test_generate_alternate_link(self):
+ view = images_view.ViewBuilder()
+ request = fakes.HTTPRequestV3.blank('/v3/os-images/1')
+ generated_url = view._get_alternate_link(request, 1)
+ actual_url = "%s/fake/images/1" % glance.generate_glance_url()
+ self.assertEqual(generated_url, actual_url)
+
+ def test_delete_image(self):
+ request = fakes.HTTPRequestV3.blank('/v3/os-images/124')
+ request.method = 'DELETE'
+ response = self.controller.delete(request, '124')
+ self.assertEqual(response.status_int, 204)
+
+ def test_delete_deleted_image(self):
+ """If you try to delete a deleted image, you get back 403 Forbidden."""
+
+ deleted_image_id = 128
+ # see nova.tests.api.openstack.fakes:_make_image_fixtures
+
+ request = fakes.HTTPRequestV3.blank(
+ '/v3/os-images/%s' % deleted_image_id)
+ request.method = 'DELETE'
+ self.assertRaises(webob.exc.HTTPForbidden, self.controller.delete,
+ request, '%s' % deleted_image_id)
+
+ def test_delete_image_not_found(self):
+ request = fakes.HTTPRequestV3.blank('/v3/os-images/300')
+ request.method = 'DELETE'
+ self.assertRaises(webob.exc.HTTPNotFound,
+ self.controller.delete, request, '300')
+
+
+class ImageXMLSerializationTest(test.TestCase):
+
+ TIMESTAMP = "2010-10-11T10:30:22Z"
+ SERVER_UUID = 'aa640691-d1a7-4a67-9d3c-d35ee6b3cc74'
+ SERVER_HREF = 'http://localhost/v3/servers/' + SERVER_UUID
+ SERVER_BOOKMARK = 'http://localhost/servers/' + SERVER_UUID
+ IMAGE_HREF = 'http://localhost/v3/os-images/%s'
+ IMAGE_NEXT = 'http://localhost/v3/os-images?limit=%s&marker=%s'
+ IMAGE_BOOKMARK = 'http://localhost/os-images/%s'
+
+ def test_xml_declaration(self):
+ serializer = images.ImageTemplate()
+
+ fixture = {
+ 'image': {
+ 'id': 1,
+ 'name': 'Image1',
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ 'status': 'ACTIVE',
+ 'progress': 80,
+ 'server': {
+ 'id': self.SERVER_UUID,
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ 'metadata': {
+ 'key1': 'value1',
+ },
+ 'links': [
+ {
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ }
+
+ output = serializer.serialize(fixture)
+ has_dec = output.startswith("<?xml version='1.0' encoding='UTF-8'?>")
+ self.assertTrue(has_dec)
+
+ def test_show(self):
+ serializer = images.ImageTemplate()
+
+ fixture = {
+ 'image': {
+ 'id': 1,
+ 'name': 'Image1',
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ 'status': 'ACTIVE',
+ 'progress': 80,
+ 'minRam': 10,
+ 'minDisk': 100,
+ 'server': {
+ 'id': self.SERVER_UUID,
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ 'metadata': {
+ 'key1': 'value1',
+ },
+ 'links': [
+ {
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ }
+
+ output = serializer.serialize(fixture)
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'image')
+ image_dict = fixture['image']
+
+ for key in ['name', 'id', 'updated', 'created', 'status', 'progress']:
+ self.assertEqual(root.get(key), str(image_dict[key]))
+
+ link_nodes = root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(image_dict['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ metadata_root = root.find('{0}metadata'.format(NS))
+ metadata_elems = metadata_root.findall('{0}meta'.format(NS))
+ self.assertEqual(len(metadata_elems), 1)
+ for i, metadata_elem in enumerate(metadata_elems):
+ (meta_key, meta_value) = image_dict['metadata'].items()[i]
+ self.assertEqual(str(metadata_elem.get('key')), str(meta_key))
+ self.assertEqual(str(metadata_elem.text).strip(), str(meta_value))
+
+ server_root = root.find('{0}server'.format(NS))
+ self.assertEqual(server_root.get('id'), image_dict['server']['id'])
+ link_nodes = server_root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(image_dict['server']['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ def test_show_zero_metadata(self):
+ serializer = images.ImageTemplate()
+
+ fixture = {
+ 'image': {
+ 'id': 1,
+ 'name': 'Image1',
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ 'status': 'ACTIVE',
+ 'server': {
+ 'id': self.SERVER_UUID,
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ 'metadata': {},
+ 'links': [
+ {
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ }
+
+ output = serializer.serialize(fixture)
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'image')
+ image_dict = fixture['image']
+
+ for key in ['name', 'id', 'updated', 'created', 'status']:
+ self.assertEqual(root.get(key), str(image_dict[key]))
+
+ link_nodes = root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(image_dict['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ meta_nodes = root.findall('{0}meta'.format(ATOMNS))
+ self.assertEqual(len(meta_nodes), 0)
+
+ server_root = root.find('{0}server'.format(NS))
+ self.assertEqual(server_root.get('id'), image_dict['server']['id'])
+ link_nodes = server_root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(image_dict['server']['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ def test_show_image_no_metadata_key(self):
+ serializer = images.ImageTemplate()
+
+ fixture = {
+ 'image': {
+ 'id': 1,
+ 'name': 'Image1',
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ 'status': 'ACTIVE',
+ 'server': {
+ 'id': self.SERVER_UUID,
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ 'links': [
+ {
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ }
+
+ output = serializer.serialize(fixture)
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'image')
+ image_dict = fixture['image']
+
+ for key in ['name', 'id', 'updated', 'created', 'status']:
+ self.assertEqual(root.get(key), str(image_dict[key]))
+
+ link_nodes = root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(image_dict['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ meta_nodes = root.findall('{0}meta'.format(ATOMNS))
+ self.assertEqual(len(meta_nodes), 0)
+
+ server_root = root.find('{0}server'.format(NS))
+ self.assertEqual(server_root.get('id'), image_dict['server']['id'])
+ link_nodes = server_root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(image_dict['server']['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ def test_show_no_server(self):
+ serializer = images.ImageTemplate()
+
+ fixture = {
+ 'image': {
+ 'id': 1,
+ 'name': 'Image1',
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ 'status': 'ACTIVE',
+ 'metadata': {
+ 'key1': 'value1',
+ },
+ 'links': [
+ {
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ }
+
+ output = serializer.serialize(fixture)
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'image')
+ image_dict = fixture['image']
+
+ for key in ['name', 'id', 'updated', 'created', 'status']:
+ self.assertEqual(root.get(key), str(image_dict[key]))
+
+ link_nodes = root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(image_dict['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ metadata_root = root.find('{0}metadata'.format(NS))
+ metadata_elems = metadata_root.findall('{0}meta'.format(NS))
+ self.assertEqual(len(metadata_elems), 1)
+ for i, metadata_elem in enumerate(metadata_elems):
+ (meta_key, meta_value) = image_dict['metadata'].items()[i]
+ self.assertEqual(str(metadata_elem.get('key')), str(meta_key))
+ self.assertEqual(str(metadata_elem.text).strip(), str(meta_value))
+
+ server_root = root.find('{0}server'.format(NS))
+ self.assertEqual(server_root, None)
+
+ def test_show_with_min_ram(self):
+ serializer = images.ImageTemplate()
+
+ fixture = {
+ 'image': {
+ 'id': 1,
+ 'name': 'Image1',
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ 'status': 'ACTIVE',
+ 'progress': 80,
+ 'minRam': 256,
+ 'server': {
+ 'id': self.SERVER_UUID,
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ 'metadata': {
+ 'key1': 'value1',
+ },
+ 'links': [
+ {
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ }
+
+ output = serializer.serialize(fixture)
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'image')
+ image_dict = fixture['image']
+
+ for key in ['name', 'id', 'updated', 'created', 'status', 'progress',
+ 'minRam']:
+ self.assertEqual(root.get(key), str(image_dict[key]))
+
+ link_nodes = root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(image_dict['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ metadata_root = root.find('{0}metadata'.format(NS))
+ metadata_elems = metadata_root.findall('{0}meta'.format(NS))
+ self.assertEqual(len(metadata_elems), 1)
+ for i, metadata_elem in enumerate(metadata_elems):
+ (meta_key, meta_value) = image_dict['metadata'].items()[i]
+ self.assertEqual(str(metadata_elem.get('key')), str(meta_key))
+ self.assertEqual(str(metadata_elem.text).strip(), str(meta_value))
+
+ server_root = root.find('{0}server'.format(NS))
+ self.assertEqual(server_root.get('id'), image_dict['server']['id'])
+ link_nodes = server_root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(image_dict['server']['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ def test_show_with_min_disk(self):
+ serializer = images.ImageTemplate()
+
+ fixture = {
+ 'image': {
+ 'id': 1,
+ 'name': 'Image1',
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ 'status': 'ACTIVE',
+ 'progress': 80,
+ 'minDisk': 5,
+ 'server': {
+ 'id': self.SERVER_UUID,
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ 'metadata': {
+ 'key1': 'value1',
+ },
+ 'links': [
+ {
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ }
+
+ output = serializer.serialize(fixture)
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'image')
+ image_dict = fixture['image']
+
+ for key in ['name', 'id', 'updated', 'created', 'status', 'progress',
+ 'minDisk']:
+ self.assertEqual(root.get(key), str(image_dict[key]))
+
+ link_nodes = root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(image_dict['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ metadata_root = root.find('{0}metadata'.format(NS))
+ metadata_elems = metadata_root.findall('{0}meta'.format(NS))
+ self.assertEqual(len(metadata_elems), 1)
+ for i, metadata_elem in enumerate(metadata_elems):
+ (meta_key, meta_value) = image_dict['metadata'].items()[i]
+ self.assertEqual(str(metadata_elem.get('key')), str(meta_key))
+ self.assertEqual(str(metadata_elem.text).strip(), str(meta_value))
+
+ server_root = root.find('{0}server'.format(NS))
+ self.assertEqual(server_root.get('id'), image_dict['server']['id'])
+ link_nodes = server_root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(image_dict['server']['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ def test_index(self):
+ serializer = images.MinimalImagesTemplate()
+
+ fixture = {
+ 'images': [
+ {
+ 'id': 1,
+ 'name': 'Image1',
+ 'links': [
+ {
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ {
+ 'id': 2,
+ 'name': 'Image2',
+ 'links': [
+ {
+ 'href': self.IMAGE_HREF % 2,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 2,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ ]
+ }
+
+ output = serializer.serialize(fixture)
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'images_index')
+ image_elems = root.findall('{0}image'.format(NS))
+ self.assertEqual(len(image_elems), 2)
+ for i, image_elem in enumerate(image_elems):
+ image_dict = fixture['images'][i]
+
+ for key in ['name', 'id']:
+ self.assertEqual(image_elem.get(key), str(image_dict[key]))
+
+ link_nodes = image_elem.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(image_dict['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ def test_index_with_links(self):
+ serializer = images.MinimalImagesTemplate()
+
+ fixture = {
+ 'images': [
+ {
+ 'id': 1,
+ 'name': 'Image1',
+ 'links': [
+ {
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ {
+ 'id': 2,
+ 'name': 'Image2',
+ 'links': [
+ {
+ 'href': self.IMAGE_HREF % 2,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 2,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ ],
+ 'images_links': [
+ {
+ 'rel': 'next',
+ 'href': self.IMAGE_NEXT % (2, 2),
+ }
+ ],
+ }
+
+ output = serializer.serialize(fixture)
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'images_index')
+ image_elems = root.findall('{0}image'.format(NS))
+ self.assertEqual(len(image_elems), 2)
+ for i, image_elem in enumerate(image_elems):
+ image_dict = fixture['images'][i]
+
+ for key in ['name', 'id']:
+ self.assertEqual(image_elem.get(key), str(image_dict[key]))
+
+ link_nodes = image_elem.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(image_dict['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ # Check images_links
+ images_links = root.findall('{0}link'.format(ATOMNS))
+ for i, link in enumerate(fixture['images_links']):
+ for key, value in link.items():
+ self.assertEqual(images_links[i].get(key), value)
+
+ def test_index_zero_images(self):
+ serializer = images.MinimalImagesTemplate()
+
+ fixtures = {
+ 'images': [],
+ }
+
+ output = serializer.serialize(fixtures)
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'images_index')
+ image_elems = root.findall('{0}image'.format(NS))
+ self.assertEqual(len(image_elems), 0)
+
+ def test_detail(self):
+ serializer = images.ImagesTemplate()
+
+ fixture = {
+ 'images': [
+ {
+ 'id': 1,
+ 'name': 'Image1',
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ 'status': 'ACTIVE',
+ 'server': {
+ 'id': self.SERVER_UUID,
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ 'links': [
+ {
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ {
+ 'id': '2',
+ 'name': 'Image2',
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ 'status': 'SAVING',
+ 'progress': 80,
+ 'metadata': {
+ 'key1': 'value1',
+ },
+ 'links': [
+ {
+ 'href': self.IMAGE_HREF % 2,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 2,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ ]
+ }
+
+ output = serializer.serialize(fixture)
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'images')
+ image_elems = root.findall('{0}image'.format(NS))
+ self.assertEqual(len(image_elems), 2)
+ for i, image_elem in enumerate(image_elems):
+ image_dict = fixture['images'][i]
+
+ for key in ['name', 'id', 'updated', 'created', 'status']:
+ self.assertEqual(image_elem.get(key), str(image_dict[key]))
+
+ link_nodes = image_elem.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(image_dict['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_quota_classes.py b/nova/tests/api/openstack/compute/plugins/v3/test_quota_classes.py
new file mode 100644
index 000000000..c4f79118e
--- /dev/null
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_quota_classes.py
@@ -0,0 +1,188 @@
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from lxml import etree
+import webob
+
+from nova.api.openstack.compute.contrib import quota_classes
+from nova.api.openstack import wsgi
+from nova import test
+from nova.tests.api.openstack import fakes
+
+
+def quota_set(class_name):
+ return {'quota_class_set': {'id': class_name, 'metadata_items': 128,
+ 'ram': 51200, 'floating_ips': 10,
+ 'fixed_ips': -1, 'instances': 10,
+ 'injected_files': 5, 'cores': 20,
+ 'injected_file_content_bytes': 10240,
+ 'security_groups': 10,
+ 'security_group_rules': 20, 'key_pairs': 100,
+ 'injected_file_path_bytes': 255}}
+
+
+class QuotaClassSetsTest(test.TestCase):
+
+ def setUp(self):
+ super(QuotaClassSetsTest, self).setUp()
+ self.controller = quota_classes.QuotaClassSetsController()
+
+ def test_format_quota_set(self):
+ raw_quota_set = {
+ 'instances': 10,
+ 'cores': 20,
+ 'ram': 51200,
+ 'floating_ips': 10,
+ 'fixed_ips': -1,
+ 'metadata_items': 128,
+ 'injected_files': 5,
+ 'injected_file_path_bytes': 255,
+ 'injected_file_content_bytes': 10240,
+ 'security_groups': 10,
+ 'security_group_rules': 20,
+ 'key_pairs': 100,
+ }
+
+ quota_set = self.controller._format_quota_set('test_class',
+ raw_quota_set)
+ qs = quota_set['quota_class_set']
+
+ self.assertEqual(qs['id'], 'test_class')
+ self.assertEqual(qs['instances'], 10)
+ self.assertEqual(qs['cores'], 20)
+ self.assertEqual(qs['ram'], 51200)
+ self.assertEqual(qs['floating_ips'], 10)
+ self.assertEqual(qs['fixed_ips'], -1)
+ self.assertEqual(qs['metadata_items'], 128)
+ self.assertEqual(qs['injected_files'], 5)
+ self.assertEqual(qs['injected_file_path_bytes'], 255)
+ self.assertEqual(qs['injected_file_content_bytes'], 10240)
+ self.assertEqual(qs['security_groups'], 10)
+ self.assertEqual(qs['security_group_rules'], 20)
+ self.assertEqual(qs['key_pairs'], 100)
+
+ def test_quotas_show_as_admin(self):
+ req = fakes.HTTPRequest.blank(
+ '/v2/fake4/os-quota-class-sets/test_class',
+ use_admin_context=True)
+ res_dict = self.controller.show(req, 'test_class')
+
+ self.assertEqual(res_dict, quota_set('test_class'))
+
+ def test_quotas_show_as_unauthorized_user(self):
+ req = fakes.HTTPRequest.blank(
+ '/v2/fake4/os-quota-class-sets/test_class')
+ self.assertRaises(webob.exc.HTTPForbidden, self.controller.show,
+ req, 'test_class')
+
+ def test_quotas_update_as_admin(self):
+ body = {'quota_class_set': {'instances': 50, 'cores': 50,
+ 'ram': 51200, 'floating_ips': 10,
+ 'fixed_ips': -1, 'metadata_items': 128,
+ 'injected_files': 5,
+ 'injected_file_content_bytes': 10240,
+ 'injected_file_path_bytes': 255,
+ 'security_groups': 10,
+ 'security_group_rules': 20,
+ 'key_pairs': 100}}
+
+ req = fakes.HTTPRequest.blank(
+ '/v2/fake4/os-quota-class-sets/test_class',
+ use_admin_context=True)
+ res_dict = self.controller.update(req, 'test_class', body)
+
+ self.assertEqual(res_dict, body)
+
+ def test_quotas_update_as_user(self):
+ body = {'quota_class_set': {'instances': 50, 'cores': 50,
+ 'ram': 51200, 'floating_ips': 10,
+ 'fixed_ips': -1, 'metadata_items': 128,
+ 'injected_files': 5,
+ 'injected_file_content_bytes': 10240,
+ 'security_groups': 10,
+ 'security_group_rules': 20,
+ 'key_pairs': 100,
+ }}
+
+ req = fakes.HTTPRequest.blank(
+ '/v2/fake4/os-quota-class-sets/test_class')
+ self.assertRaises(webob.exc.HTTPForbidden, self.controller.update,
+ req, 'test_class', body)
+
+
+class QuotaTemplateXMLSerializerTest(test.TestCase):
+ def setUp(self):
+ super(QuotaTemplateXMLSerializerTest, self).setUp()
+ self.serializer = quota_classes.QuotaClassTemplate()
+ self.deserializer = wsgi.XMLDeserializer()
+
+ def test_serializer(self):
+ exemplar = dict(quota_class_set=dict(
+ id='test_class',
+ metadata_items=10,
+ injected_file_path_bytes=255,
+ injected_file_content_bytes=20,
+ ram=50,
+ floating_ips=60,
+ fixed_ips=-1,
+ instances=70,
+ injected_files=80,
+ security_groups=10,
+ security_group_rules=20,
+ key_pairs=100,
+ cores=90))
+ text = self.serializer.serialize(exemplar)
+
+ tree = etree.fromstring(text)
+
+ self.assertEqual('quota_class_set', tree.tag)
+ self.assertEqual('test_class', tree.get('id'))
+ self.assertEqual(len(exemplar['quota_class_set']) - 1, len(tree))
+ for child in tree:
+ self.assertTrue(child.tag in exemplar['quota_class_set'])
+ self.assertEqual(int(child.text),
+ exemplar['quota_class_set'][child.tag])
+
+ def test_deserializer(self):
+ exemplar = dict(quota_class_set=dict(
+ metadata_items='10',
+ injected_file_content_bytes='20',
+ ram='50',
+ floating_ips='60',
+ fixed_ips='-1',
+ instances='70',
+ injected_files='80',
+ security_groups='10',
+ security_group_rules='20',
+ key_pairs='100',
+ cores='90'))
+ intext = ("<?xml version='1.0' encoding='UTF-8'?>\n"
+ '<quota_class_set>'
+ '<metadata_items>10</metadata_items>'
+ '<injected_file_content_bytes>20'
+ '</injected_file_content_bytes>'
+ '<ram>50</ram>'
+ '<floating_ips>60</floating_ips>'
+ '<fixed_ips>-1</fixed_ips>'
+ '<instances>70</instances>'
+ '<injected_files>80</injected_files>'
+ '<cores>90</cores>'
+ '<security_groups>10</security_groups>'
+ '<security_group_rules>20</security_group_rules>'
+ '<key_pairs>100</key_pairs>'
+ '</quota_class_set>')
+
+ result = self.deserializer.deserialize(intext)['body']
+ self.assertEqual(result, exemplar)
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_quota_sets.py b/nova/tests/api/openstack/compute/plugins/v3/test_quota_sets.py
new file mode 100644
index 000000000..6eea01cff
--- /dev/null
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_quota_sets.py
@@ -0,0 +1,399 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 OpenStack Foundation
+# Copyright 2013 IBM Corp.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from lxml import etree
+import webob
+
+from nova.api.openstack.compute.plugins.v3 import quota_sets as quotas
+from nova.api.openstack import extensions
+from nova.api.openstack import wsgi
+from nova import context as context_maker
+from nova import quota
+from nova import test
+from nova.tests.api.openstack import fakes
+
+
+def quota_set(id):
+ return {'quota_set': {'id': id, 'metadata_items': 128,
+ 'ram': 51200, 'floating_ips': 10, 'fixed_ips': -1,
+ 'instances': 10, 'injected_files': 5, 'cores': 20,
+ 'injected_file_content_bytes': 10240,
+ 'security_groups': 10, 'security_group_rules': 20,
+ 'key_pairs': 100, 'injected_file_path_bytes': 255}}
+
+
+class QuotaSetsTest(test.TestCase):
+
+ def setUp(self):
+ super(QuotaSetsTest, self).setUp()
+ self.ext_mgr = self.mox.CreateMock(extensions.ExtensionManager)
+ self.controller = quotas.QuotaSetsController(self.ext_mgr)
+
+ def test_format_quota_set(self):
+ raw_quota_set = {
+ 'instances': 10,
+ 'cores': 20,
+ 'ram': 51200,
+ 'floating_ips': 10,
+ 'fixed_ips': -1,
+ 'metadata_items': 128,
+ 'injected_files': 5,
+ 'injected_file_path_bytes': 255,
+ 'injected_file_content_bytes': 10240,
+ 'security_groups': 10,
+ 'security_group_rules': 20,
+ 'key_pairs': 100}
+
+ quota_set = self.controller._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['floating_ips'], 10)
+ self.assertEqual(qs['fixed_ips'], -1)
+ self.assertEqual(qs['metadata_items'], 128)
+ self.assertEqual(qs['injected_files'], 5)
+ self.assertEqual(qs['injected_file_path_bytes'], 255)
+ self.assertEqual(qs['injected_file_content_bytes'], 10240)
+ self.assertEqual(qs['security_groups'], 10)
+ self.assertEqual(qs['security_group_rules'], 20)
+ self.assertEqual(qs['key_pairs'], 100)
+
+ def test_quotas_defaults(self):
+ uri = '/os-quota-sets/fake_tenant/defaults'
+
+ req = fakes.HTTPRequestV3.blank(uri)
+ res_dict = self.controller.defaults(req, 'fake_tenant')
+
+ expected = {'quota_set': {
+ 'id': 'fake_tenant',
+ 'instances': 10,
+ 'cores': 20,
+ 'ram': 51200,
+ 'floating_ips': 10,
+ 'fixed_ips': -1,
+ 'metadata_items': 128,
+ 'injected_files': 5,
+ 'injected_file_path_bytes': 255,
+ 'injected_file_content_bytes': 10240,
+ 'security_groups': 10,
+ 'security_group_rules': 20,
+ 'key_pairs': 100}}
+
+ self.assertEqual(res_dict, expected)
+
+ def test_quotas_show_as_admin(self):
+ req = fakes.HTTPRequestV3.blank('/os-quota-sets/1234',
+ use_admin_context=True)
+ res_dict = self.controller.show(req, 1234)
+
+ self.assertEqual(res_dict, quota_set('1234'))
+
+ def test_quotas_show_as_unauthorized_user(self):
+ req = fakes.HTTPRequestV3.blank('/os-quota-sets/1234')
+ self.assertRaises(webob.exc.HTTPForbidden, self.controller.show,
+ req, 1234)
+
+ def test_quotas_update_as_admin(self):
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
+ body = {'quota_set': {'instances': 50, 'cores': 50,
+ 'ram': 51200, 'floating_ips': 10,
+ 'fixed_ips': -1, 'metadata_items': 128,
+ 'injected_files': 5,
+ 'injected_file_content_bytes': 10240,
+ 'injected_file_path_bytes': 255,
+ 'security_groups': 10,
+ 'security_group_rules': 20,
+ 'key_pairs': 100, 'fixed_ips': -1}}
+
+ req = fakes.HTTPRequestV3.blank('/os-quota-sets/update_me',
+ use_admin_context=True)
+ res_dict = self.controller.update(req, 'update_me', body)
+
+ self.assertEqual(res_dict, body)
+
+ def test_quotas_update_as_user(self):
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
+ body = {'quota_set': {'instances': 50, 'cores': 50,
+ 'ram': 51200, 'floating_ips': 10,
+ 'fixed_ips': -1, 'metadata_items': 128,
+ 'injected_files': 5,
+ 'injected_file_content_bytes': 10240,
+ 'security_groups': 10,
+ 'security_group_rules': 20,
+ 'key_pairs': 100}}
+
+ req = fakes.HTTPRequestV3.blank('/os-quota-sets/update_me')
+ self.assertRaises(webob.exc.HTTPForbidden, self.controller.update,
+ req, 'update_me', body)
+
+ def test_quotas_update_invalid_key(self):
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
+ body = {'quota_set': {'instances2': -2, 'cores': -2,
+ 'ram': -2, 'floating_ips': -2,
+ 'metadata_items': -2, 'injected_files': -2,
+ 'injected_file_content_bytes': -2}}
+
+ req = fakes.HTTPRequestV3.blank('/os-quota-sets/update_me',
+ use_admin_context=True)
+ self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
+ req, 'update_me', body)
+
+ def test_quotas_update_invalid_limit(self):
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
+ body = {'quota_set': {'instances': -2, 'cores': -2,
+ 'ram': -2, 'floating_ips': -2, 'fixed_ips': -2,
+ 'metadata_items': -2, 'injected_files': -2,
+ 'injected_file_content_bytes': -2}}
+
+ req = fakes.HTTPRequestV3.blank('/os-quota-sets/update_me',
+ use_admin_context=True)
+ self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
+ req, 'update_me', body)
+
+ def test_quotas_update_invalid_value_json_fromat_empty_string(self):
+ expected_resp = {'quota_set': {
+ 'instances': 50, 'cores': 50,
+ 'ram': 51200, 'floating_ips': 10,
+ 'fixed_ips': -1, 'metadata_items': 128,
+ 'injected_files': 5,
+ 'injected_file_content_bytes': 10240,
+ 'injected_file_path_bytes': 255,
+ 'security_groups': 10,
+ 'security_group_rules': 20,
+ 'key_pairs': 100}}
+
+ # when PUT JSON format with empty string for quota
+ body = {'quota_set': {'instances': 50, 'cores': 50,
+ 'ram': '', 'floating_ips': 10,
+ 'fixed_ips': -1, 'metadata_items': 128,
+ 'injected_files': 5,
+ 'injected_file_content_bytes': 10240,
+ 'injected_file_path_bytes': 255,
+ 'security_groups': 10,
+ 'security_group_rules': 20,
+ 'key_pairs': 100}}
+ req = fakes.HTTPRequestV3.blank('/os-quota-sets/update_me',
+ use_admin_context=True)
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
+ res_dict = self.controller.update(req, 'update_me', body)
+ self.assertEqual(res_dict, expected_resp)
+
+ def test_quotas_update_invalid_value_xml_fromat_empty_string(self):
+ expected_resp = {'quota_set': {
+ 'instances': 50, 'cores': 50,
+ 'ram': 51200, 'floating_ips': 10,
+ 'fixed_ips': -1, 'metadata_items': 128,
+ 'injected_files': 5,
+ 'injected_file_content_bytes': 10240,
+ 'injected_file_path_bytes': 255,
+ 'security_groups': 10,
+ 'security_group_rules': 20,
+ 'key_pairs': 100}}
+ # when PUT XML format with empty string for quota
+ body = {'quota_set': {'instances': 50, 'cores': 50,
+ 'ram': {}, 'floating_ips': 10,
+ 'fixed_ips': -1, 'metadata_items': 128,
+ 'injected_files': 5,
+ 'injected_file_content_bytes': 10240,
+ 'injected_file_path_bytes': 255,
+ 'security_groups': 10,
+ 'security_group_rules': 20,
+ 'key_pairs': 100}}
+ req = fakes.HTTPRequestV3.blank('/os-quota-sets/update_me',
+ use_admin_context=True)
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
+ res_dict = self.controller.update(req, 'update_me', body)
+ self.assertEqual(res_dict, expected_resp)
+
+ def test_quotas_update_invalid_value_non_int(self):
+ # when PUT non integer value
+ body = {'quota_set': {'instances': test, 'cores': 50,
+ 'ram': {}, 'floating_ips': 10,
+ 'fixed_ips': -1, 'metadata_items': 128,
+ 'injected_files': 5,
+ 'injected_file_content_bytes': 10240,
+ 'injected_file_path_bytes': 255,
+ 'security_groups': 10,
+ 'security_group_rules': 20,
+ 'key_pairs': 100}}
+ req = fakes.HTTPRequestV3.blank('/os-quota-sets/update_me',
+ use_admin_context=True)
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
+ self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
+ req, 'update_me', body)
+
+ def test_delete_quotas_when_extension_not_loaded(self):
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(False)
+ self.mox.ReplayAll()
+ req = fakes.HTTPRequestV3.blank('/os-quota-sets/1234')
+ self.assertRaises(webob.exc.HTTPNotFound, self.controller.delete,
+ req, 1234)
+
+ def test_quotas_delete_as_unauthorized_user(self):
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
+ req = fakes.HTTPRequestV3.blank('/os-quota-sets/1234')
+ self.assertRaises(webob.exc.HTTPForbidden, self.controller.delete,
+ req, 1234)
+
+ def test_quotas_delete_as_admin(self):
+ context = context_maker.get_admin_context()
+ self.req = fakes.HTTPRequestV3.blank('/os-quota-sets/1234')
+ self.req.environ['nova.context'] = context
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.StubOutWithMock(quota.QUOTAS,
+ "destroy_all_by_project")
+ quota.QUOTAS.destroy_all_by_project(context, 1234)
+ self.mox.ReplayAll()
+ res = self.controller.delete(self.req, 1234)
+ self.mox.VerifyAll()
+ self.assertEqual(res.status_int, 202)
+
+
+class QuotaXMLSerializerTest(test.TestCase):
+ def setUp(self):
+ super(QuotaXMLSerializerTest, self).setUp()
+ self.serializer = quotas.QuotaTemplate()
+ self.deserializer = wsgi.XMLDeserializer()
+
+ def test_serializer(self):
+ exemplar = dict(quota_set=dict(
+ id='project_id',
+ metadata_items=10,
+ injected_file_path_bytes=255,
+ injected_file_content_bytes=20,
+ ram=50,
+ floating_ips=60,
+ fixed_ips=-1,
+ instances=70,
+ injected_files=80,
+ security_groups=10,
+ security_group_rules=20,
+ key_pairs=100,
+ cores=90))
+ text = self.serializer.serialize(exemplar)
+
+ tree = etree.fromstring(text)
+
+ self.assertEqual('quota_set', tree.tag)
+ self.assertEqual('project_id', tree.get('id'))
+ self.assertEqual(len(exemplar['quota_set']) - 1, len(tree))
+ for child in tree:
+ self.assertTrue(child.tag in exemplar['quota_set'])
+ self.assertEqual(int(child.text), exemplar['quota_set'][child.tag])
+
+ def test_deserializer(self):
+ exemplar = dict(quota_set=dict(
+ metadata_items='10',
+ injected_file_content_bytes='20',
+ ram='50',
+ floating_ips='60',
+ fixed_ips='-1',
+ instances='70',
+ injected_files='80',
+ security_groups='10',
+ security_group_rules='20',
+ key_pairs='100',
+ cores='90'))
+ intext = ("<?xml version='1.0' encoding='UTF-8'?>\n"
+ '<quota_set>'
+ '<metadata_items>10</metadata_items>'
+ '<injected_file_content_bytes>20'
+ '</injected_file_content_bytes>'
+ '<ram>50</ram>'
+ '<floating_ips>60</floating_ips>'
+ '<fixed_ips>-1</fixed_ips>'
+ '<instances>70</instances>'
+ '<injected_files>80</injected_files>'
+ '<security_groups>10</security_groups>'
+ '<security_group_rules>20</security_group_rules>'
+ '<key_pairs>100</key_pairs>'
+ '<cores>90</cores>'
+ '</quota_set>')
+
+ result = self.deserializer.deserialize(intext)['body']
+ self.assertEqual(result, exemplar)
+
+
+fake_quotas = {'ram': {'limit': 51200,
+ 'in_use': 12800,
+ 'reserved': 12800},
+ 'cores': {'limit': 20,
+ 'in_use': 10,
+ 'reserved': 5},
+ 'instances': {'limit': 100,
+ 'in_use': 0,
+ 'reserved': 0}}
+
+
+def fake_get_quotas(self, context, id, usages=False):
+ if usages:
+ return fake_quotas
+ else:
+ return dict((k, v['limit']) for k, v in fake_quotas.items())
+
+
+class ExtendedQuotasTest(test.TestCase):
+
+ def setUp(self):
+ super(ExtendedQuotasTest, self).setUp()
+ self.ext_mgr = self.mox.CreateMock(extensions.ExtensionManager)
+ self.controller = quotas.QuotaSetsController(self.ext_mgr)
+
+ def test_quotas_update_exceed_in_used(self):
+
+ body = {'quota_set': {'cores': 10}}
+
+ self.stubs.Set(quotas.QuotaSetsController, '_get_quotas',
+ fake_get_quotas)
+ req = fakes.HTTPRequestV3.blank('/os-quota-sets/update_me',
+ use_admin_context=True)
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
+
+ self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
+ req, 'update_me', body)
+
+ def test_quotas_force_update_exceed_in_used(self):
+ self.stubs.Set(quotas.QuotaSetsController, '_get_quotas',
+ fake_get_quotas)
+ req = fakes.HTTPRequestV3.blank('/os-quota-sets/update_me',
+ use_admin_context=True)
+ expected = {'quota_set': {'ram': 25600, 'instances': 200, 'cores': 10}}
+ body = {'quota_set': {'ram': 25600,
+ 'instances': 200,
+ 'cores': 10,
+ 'force': 'True'}}
+ fake_quotas.get('ram')['limit'] = 25600
+ fake_quotas.get('cores')['limit'] = 10
+ fake_quotas.get('instances')['limit'] = 200
+
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
+ res_dict = self.controller.update(req, 'update_me', body)
+ self.assertEqual(res_dict, expected)
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_rescue.py b/nova/tests/api/openstack/compute/plugins/v3/test_rescue.py
new file mode 100644
index 000000000..75733e50f
--- /dev/null
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_rescue.py
@@ -0,0 +1,126 @@
+# Copyright 2011 OpenStack Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from oslo.config import cfg
+import webob
+
+from nova import compute
+from nova import exception
+from nova.openstack.common import jsonutils
+from nova import test
+from nova.tests.api.openstack import fakes
+
+CONF = cfg.CONF
+CONF.import_opt('password_length', 'nova.utils')
+
+
+def rescue(self, context, instance, rescue_password=None):
+ pass
+
+
+def unrescue(self, context, instance):
+ pass
+
+
+class RescueTest(test.TestCase):
+ def setUp(self):
+ super(RescueTest, self).setUp()
+
+ def fake_compute_get(*args, **kwargs):
+ uuid = '70f6db34-de8d-4fbd-aafb-4065bdfa6114'
+ return {'id': 1, 'uuid': uuid}
+
+ self.stubs.Set(compute.api.API, "get", fake_compute_get)
+ self.stubs.Set(compute.api.API, "rescue", rescue)
+ self.stubs.Set(compute.api.API, "unrescue", unrescue)
+ self.app = fakes.wsgi_app_v3(init_only=('servers', 'os-rescue'))
+
+ def test_rescue_with_preset_password(self):
+ body = {"rescue": {"adminPass": "AABBCC112233"}}
+ req = webob.Request.blank('/v3/servers/test_inst/action')
+ req.method = "POST"
+ req.body = jsonutils.dumps(body)
+ req.headers["content-type"] = "application/json"
+
+ resp = req.get_response(self.app)
+ self.assertEqual(resp.status_int, 200)
+ resp_json = jsonutils.loads(resp.body)
+ self.assertEqual("AABBCC112233", resp_json['adminPass'])
+
+ def test_rescue_generates_password(self):
+ body = dict(rescue=None)
+ req = webob.Request.blank('/v3/servers/test_inst/action')
+ req.method = "POST"
+ req.body = jsonutils.dumps(body)
+ req.headers["content-type"] = "application/json"
+
+ resp = req.get_response(self.app)
+ self.assertEqual(resp.status_int, 200)
+ resp_json = jsonutils.loads(resp.body)
+ self.assertEqual(CONF.password_length, len(resp_json['adminPass']))
+
+ def test_rescue_of_rescued_instance(self):
+ body = dict(rescue=None)
+
+ def fake_rescue(*args, **kwargs):
+ raise exception.InstanceInvalidState('fake message')
+
+ self.stubs.Set(compute.api.API, "rescue", fake_rescue)
+ req = webob.Request.blank('/v3/servers/test_inst/action')
+ req.method = "POST"
+ req.body = jsonutils.dumps(body)
+ req.headers["content-type"] = "application/json"
+
+ resp = req.get_response(self.app)
+ self.assertEqual(resp.status_int, 409)
+
+ def test_unrescue(self):
+ body = dict(unrescue=None)
+ req = webob.Request.blank('/v3/servers/test_inst/action')
+ req.method = "POST"
+ req.body = jsonutils.dumps(body)
+ req.headers["content-type"] = "application/json"
+
+ resp = req.get_response(self.app)
+ self.assertEqual(resp.status_int, 202)
+
+ def test_unrescue_of_active_instance(self):
+ body = dict(unrescue=None)
+
+ def fake_unrescue(*args, **kwargs):
+ raise exception.InstanceInvalidState('fake message')
+
+ self.stubs.Set(compute.api.API, "unrescue", fake_unrescue)
+ req = webob.Request.blank('/v3/servers/test_inst/action')
+ req.method = "POST"
+ req.body = jsonutils.dumps(body)
+ req.headers["content-type"] = "application/json"
+
+ resp = req.get_response(self.app)
+ self.assertEqual(resp.status_int, 409)
+
+ def test_rescue_raises_unrescuable(self):
+ body = dict(rescue=None)
+
+ def fake_rescue(*args, **kwargs):
+ raise exception.InstanceNotRescuable('fake message')
+
+ self.stubs.Set(compute.api.API, "rescue", fake_rescue)
+ req = webob.Request.blank('/v3/servers/test_inst/action')
+ req.method = "POST"
+ req.body = jsonutils.dumps(body)
+ req.headers["content-type"] = "application/json"
+
+ resp = req.get_response(self.app)
+ self.assertEqual(resp.status_int, 400)
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_server_diagnostics.py b/nova/tests/api/openstack/compute/plugins/v3/test_server_diagnostics.py
new file mode 100644
index 000000000..61b78fea8
--- /dev/null
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_server_diagnostics.py
@@ -0,0 +1,81 @@
+# Copyright 2011 Eldar Nugaev
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from lxml import etree
+
+from nova.api.openstack import compute
+from nova.api.openstack.compute.plugins.v3 import server_diagnostics
+from nova.api.openstack import wsgi
+from nova.compute import api as compute_api
+from nova.openstack.common import jsonutils
+from nova import test
+from nova.tests.api.openstack import fakes
+
+
+UUID = 'abc'
+
+
+def fake_get_diagnostics(self, _context, instance_uuid):
+ return {'data': 'Some diagnostic info'}
+
+
+def fake_instance_get(self, _context, instance_uuid):
+ if instance_uuid != UUID:
+ raise Exception("Invalid UUID")
+ return {'uuid': instance_uuid}
+
+
+class ServerDiagnosticsTest(test.TestCase):
+
+ def setUp(self):
+ super(ServerDiagnosticsTest, self).setUp()
+ self.stubs.Set(compute_api.API, 'get_diagnostics',
+ fake_get_diagnostics)
+ self.stubs.Set(compute_api.API, 'get', fake_instance_get)
+
+ self.router = compute.APIRouterV3(init_only=('servers', 'os-server-diagnostics'))
+
+ def test_get_diagnostics(self):
+ req = fakes.HTTPRequestV3.blank(
+ '/servers/%s/os-server-diagnostics' % UUID)
+ res = req.get_response(self.router)
+ output = jsonutils.loads(res.body)
+ self.assertEqual(output, {'data': 'Some diagnostic info'})
+
+
+class TestServerDiagnosticsXMLSerializer(test.TestCase):
+ namespace = wsgi.XMLNS_V11
+
+ def _tag(self, elem):
+ tagname = elem.tag
+ self.assertEqual(tagname[0], '{')
+ tmp = tagname.partition('}')
+ namespace = tmp[0][1:]
+ self.assertEqual(namespace, self.namespace)
+ return tmp[2]
+
+ def test_index_serializer(self):
+ serializer = server_diagnostics.ServerDiagnosticsTemplate()
+ exemplar = dict(diag1='foo', diag2='bar')
+ text = serializer.serialize(exemplar)
+
+ tree = etree.fromstring(text)
+
+ self.assertEqual('diagnostics', self._tag(tree))
+ self.assertEqual(len(tree), len(exemplar))
+ for child in tree:
+ tag = self._tag(child)
+ self.assertTrue(tag in exemplar)
+ self.assertEqual(child.text, exemplar[tag])
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_servers.py b/nova/tests/api/openstack/compute/plugins/v3/test_servers.py
index da17d8fd5..4505a1750 100644
--- a/nova/tests/api/openstack/compute/plugins/v3/test_servers.py
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_servers.py
@@ -228,7 +228,7 @@ class ServersControllerTest(test.TestCase):
self.assertEquals(res, [(None, None, port)])
def test_get_server_by_uuid(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
res_dict = self.controller.show(req, FAKE_UUID)
self.assertEqual(res_dict['server']['id'], FAKE_UUID)
@@ -246,7 +246,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get',
return_instance_with_host)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
server1 = self.controller.show(req, FAKE_UUID)
server2 = self.controller.show(req, FAKE_UUID)
@@ -255,11 +255,11 @@ class ServersControllerTest(test.TestCase):
def test_get_server_by_id(self):
self.flags(use_ipv6=True)
- image_bookmark = "http://localhost/fake/images/10"
- flavor_bookmark = "http://localhost/fake/flavors/1"
+ image_bookmark = "http://localhost/images/10"
+ flavor_bookmark = "http://localhost/flavors/1"
uuid = FAKE_UUID
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % uuid)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % uuid)
res_dict = self.controller.show(req, uuid)
expected_server = {
@@ -305,11 +305,11 @@ class ServersControllerTest(test.TestCase):
"links": [
{
"rel": "self",
- "href": "http://localhost/v3/fake/servers/%s" % uuid,
+ "href": "http://localhost/v3/servers/%s" % uuid,
},
{
"rel": "bookmark",
- "href": "http://localhost/fake/servers/%s" % uuid,
+ "href": "http://localhost/servers/%s" % uuid,
},
],
}
@@ -318,15 +318,15 @@ class ServersControllerTest(test.TestCase):
self.assertThat(res_dict, matchers.DictMatches(expected_server))
def test_get_server_with_active_status_by_id(self):
- image_bookmark = "http://localhost/fake/images/10"
- flavor_bookmark = "http://localhost/fake/flavors/1"
+ image_bookmark = "http://localhost/images/10"
+ flavor_bookmark = "http://localhost/flavors/1"
new_return_server = fakes.fake_instance_get(
vm_state=vm_states.ACTIVE, progress=100)
self.stubs.Set(db, 'instance_get_by_uuid', new_return_server)
uuid = FAKE_UUID
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % uuid)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % uuid)
res_dict = self.controller.show(req, uuid)
expected_server = {
"server": {
@@ -371,11 +371,11 @@ class ServersControllerTest(test.TestCase):
"links": [
{
"rel": "self",
- "href": "http://localhost/v3/fake/servers/%s" % uuid,
+ "href": "http://localhost/v3/servers/%s" % uuid,
},
{
"rel": "bookmark",
- "href": "http://localhost/fake/servers/%s" % uuid,
+ "href": "http://localhost/servers/%s" % uuid,
},
],
}
@@ -385,9 +385,9 @@ class ServersControllerTest(test.TestCase):
def test_get_server_with_id_image_ref_by_id(self):
image_ref = "10"
- image_bookmark = "http://localhost/fake/images/10"
+ image_bookmark = "http://localhost/images/10"
flavor_id = "1"
- flavor_bookmark = "http://localhost/fake/flavors/1"
+ flavor_bookmark = "http://localhost/flavors/1"
new_return_server = fakes.fake_instance_get(
vm_state=vm_states.ACTIVE, image_ref=image_ref,
@@ -395,7 +395,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_by_uuid', new_return_server)
uuid = FAKE_UUID
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % uuid)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % uuid)
res_dict = self.controller.show(req, uuid)
expected_server = {
"server": {
@@ -440,11 +440,11 @@ class ServersControllerTest(test.TestCase):
"links": [
{
"rel": "self",
- "href": "http://localhost/v3/fake/servers/%s" % uuid,
+ "href": "http://localhost/v3/servers/%s" % uuid,
},
{
"rel": "bookmark",
- "href": "http://localhost/fake/servers/%s" % uuid,
+ "href": "http://localhost/servers/%s" % uuid,
},
],
}
@@ -484,7 +484,7 @@ class ServersControllerTest(test.TestCase):
return_server = fakes.fake_instance_get(nw_cache=nw_cache)
self.stubs.Set(db, 'instance_get_by_uuid', return_server)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s/ips' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s/ips' % FAKE_UUID)
res_dict = self.ips_controller.index(req, FAKE_UUID)
expected = {
@@ -504,7 +504,7 @@ class ServersControllerTest(test.TestCase):
self.assertThat(res_dict, matchers.DictMatches(expected))
def test_get_server_addresses_nonexistent_network(self):
- url = '/v3/fake/servers/%s/ips/network_0' % FAKE_UUID
+ url = '/v3/servers/%s/ips/network_0' % FAKE_UUID
req = fakes.HTTPRequestV3.blank(url)
self.assertRaises(webob.exc.HTTPNotFound, self.ips_controller.show,
req, FAKE_UUID, 'network_0')
@@ -516,7 +516,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_by_uuid', fake_instance_get)
server_id = str(uuid.uuid4())
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s/ips' % server_id)
+ req = fakes.HTTPRequestV3.blank('/servers/%s/ips' % server_id)
self.assertRaises(webob.exc.HTTPNotFound,
self.ips_controller.index, req, server_id)
@@ -524,14 +524,14 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_all_by_filters',
return_servers_empty)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
res_dict = self.controller.index(req)
num_servers = len(res_dict['servers'])
self.assertEqual(0, num_servers)
def test_get_server_list_with_reservation_id(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?reservation_id=foo')
+ req = fakes.HTTPRequestV3.blank('/servers?reservation_id=foo')
res_dict = self.controller.index(req)
i = 0
@@ -540,7 +540,7 @@ class ServersControllerTest(test.TestCase):
i += 1
def test_get_server_list_with_reservation_id_empty(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/detail?'
+ req = fakes.HTTPRequestV3.blank('/servers/detail?'
'reservation_id=foo')
res_dict = self.controller.detail(req)
@@ -550,7 +550,7 @@ class ServersControllerTest(test.TestCase):
i += 1
def test_get_server_list_with_reservation_id_details(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/detail?'
+ req = fakes.HTTPRequestV3.blank('/servers/detail?'
'reservation_id=foo')
res_dict = self.controller.detail(req)
@@ -560,7 +560,7 @@ class ServersControllerTest(test.TestCase):
i += 1
def test_get_server_list(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
res_dict = self.controller.index(req)
self.assertEqual(len(res_dict['servers']), 5)
@@ -572,18 +572,18 @@ class ServersControllerTest(test.TestCase):
expected_links = [
{
"rel": "self",
- "href": "http://localhost/v3/fake/servers/%s" % s['id'],
+ "href": "http://localhost/v3/servers/%s" % s['id'],
},
{
"rel": "bookmark",
- "href": "http://localhost/fake/servers/%s" % s['id'],
+ "href": "http://localhost/servers/%s" % s['id'],
},
]
self.assertEqual(s['links'], expected_links)
def test_get_servers_with_limit(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?limit=3')
+ req = fakes.HTTPRequestV3.blank('/servers?limit=3')
res_dict = self.controller.index(req)
servers = res_dict['servers']
@@ -593,14 +593,14 @@ class ServersControllerTest(test.TestCase):
servers_links = res_dict['servers_links']
self.assertEqual(servers_links[0]['rel'], 'next')
href_parts = urlparse.urlparse(servers_links[0]['href'])
- self.assertEqual('/v3/fake/servers', href_parts.path)
+ self.assertEqual('/v3/servers', href_parts.path)
params = urlparse.parse_qs(href_parts.query)
expected_params = {'limit': ['3'],
'marker': [fakes.get_fake_uuid(2)]}
self.assertThat(params, matchers.DictMatches(expected_params))
def test_get_servers_with_limit_bad_value(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?limit=aaa')
+ req = fakes.HTTPRequestV3.blank('/servers?limit=aaa')
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.index, req)
@@ -608,14 +608,14 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_all_by_filters',
return_servers_empty)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/detail')
+ req = fakes.HTTPRequestV3.blank('/servers/detail')
res_dict = self.controller.index(req)
num_servers = len(res_dict['servers'])
self.assertEqual(0, num_servers)
def test_get_server_details_with_limit(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/detail?limit=3')
+ req = fakes.HTTPRequestV3.blank('/servers/detail?limit=3')
res = self.controller.detail(req)
servers = res['servers']
@@ -626,18 +626,18 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(servers_links[0]['rel'], 'next')
href_parts = urlparse.urlparse(servers_links[0]['href'])
- self.assertEqual('/v3/fake/servers', href_parts.path)
+ self.assertEqual('/v3/servers', href_parts.path)
params = urlparse.parse_qs(href_parts.query)
expected = {'limit': ['3'], 'marker': [fakes.get_fake_uuid(2)]}
self.assertThat(params, matchers.DictMatches(expected))
def test_get_server_details_with_limit_bad_value(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/detail?limit=aaa')
+ req = fakes.HTTPRequestV3.blank('/servers/detail?limit=aaa')
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.detail, req)
def test_get_server_details_with_limit_and_other_params(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/detail'
+ req = fakes.HTTPRequestV3.blank('/servers/detail'
'?limit=3&blah=2:t')
res = self.controller.detail(req)
@@ -649,36 +649,36 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(servers_links[0]['rel'], 'next')
href_parts = urlparse.urlparse(servers_links[0]['href'])
- self.assertEqual('/v3/fake/servers', href_parts.path)
+ self.assertEqual('/v3/servers', href_parts.path)
params = urlparse.parse_qs(href_parts.query)
expected = {'limit': ['3'], 'blah': ['2:t'],
'marker': [fakes.get_fake_uuid(2)]}
self.assertThat(params, matchers.DictMatches(expected))
def test_get_servers_with_too_big_limit(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?limit=30')
+ req = fakes.HTTPRequestV3.blank('/servers?limit=30')
res_dict = self.controller.index(req)
self.assertTrue('servers_links' not in res_dict)
def test_get_servers_with_bad_limit(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?limit=asdf')
+ req = fakes.HTTPRequestV3.blank('/servers?limit=asdf')
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.index, req)
def test_get_servers_with_marker(self):
- url = '/v3/fake/servers?marker=%s' % fakes.get_fake_uuid(2)
+ url = '/v3/servers?marker=%s' % fakes.get_fake_uuid(2)
req = fakes.HTTPRequestV3.blank(url)
servers = self.controller.index(req)['servers']
self.assertEqual([s['name'] for s in servers], ["server4", "server5"])
def test_get_servers_with_limit_and_marker(self):
- url = '/v3/fake/servers?limit=2&marker=%s' % fakes.get_fake_uuid(1)
+ url = '/v3/servers?limit=2&marker=%s' % fakes.get_fake_uuid(1)
req = fakes.HTTPRequestV3.blank(url)
servers = self.controller.index(req)['servers']
self.assertEqual([s['name'] for s in servers], ['server3', 'server4'])
def test_get_servers_with_bad_marker(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?limit=2&marker=asdf')
+ req = fakes.HTTPRequestV3.blank('/servers?limit=2&marker=asdf')
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.index, req)
@@ -692,7 +692,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?unknownoption=whee')
+ req = fakes.HTTPRequestV3.blank('/servers?unknownoption=whee')
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 1)
@@ -711,7 +711,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?image=12345')
+ req = fakes.HTTPRequestV3.blank('/servers?image=12345')
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 1)
@@ -728,7 +728,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_all_by_filters',
fake_get_all)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?tenant_id=fake',
+ req = fakes.HTTPRequestV3.blank('/servers?tenant_id=fake',
use_admin_context=True)
res = self.controller.index(req)
@@ -744,7 +744,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_all_by_filters',
fake_get_all)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers',
+ req = fakes.HTTPRequestV3.blank('/servers',
use_admin_context=True)
res = self.controller.index(req)
@@ -769,7 +769,7 @@ class ServersControllerTest(test.TestCase):
common_policy.set_rules(common_policy.Rules(rules))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?all_tenants=1')
+ req = fakes.HTTPRequestV3.blank('/servers?all_tenants=1')
res = self.controller.index(req)
self.assertTrue('servers' in res)
@@ -791,7 +791,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_all_by_filters',
fake_get_all)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?all_tenants=1')
+ req = fakes.HTTPRequestV3.blank('/servers?all_tenants=1')
self.assertRaises(exception.PolicyNotAuthorized,
self.controller.index, req)
@@ -809,14 +809,14 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?flavor=12345')
+ req = fakes.HTTPRequestV3.blank('/servers?flavor=12345')
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0]['id'], server_uuid)
def test_get_servers_with_bad_flavor(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?flavor=abcde')
+ req = fakes.HTTPRequestV3.blank('/servers?flavor=abcde')
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 0)
@@ -834,7 +834,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?status=active')
+ req = fakes.HTTPRequestV3.blank('/servers?status=active')
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 1)
@@ -842,13 +842,13 @@ class ServersControllerTest(test.TestCase):
def test_get_servers_invalid_status(self):
# Test getting servers by invalid status.
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?status=baloney',
+ req = fakes.HTTPRequestV3.blank('/servers?status=baloney',
use_admin_context=False)
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 0)
def test_get_servers_deleted_status_as_user(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?status=deleted',
+ req = fakes.HTTPRequestV3.blank('/servers?status=deleted',
use_admin_context=False)
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.detail, req)
@@ -866,7 +866,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?status=deleted',
+ req = fakes.HTTPRequestV3.blank('/servers?status=deleted',
use_admin_context=True)
servers = self.controller.detail(req)['servers']
@@ -886,7 +886,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?name=whee.*')
+ req = fakes.HTTPRequestV3.blank('/servers?name=whee.*')
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 1)
@@ -909,7 +909,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
params = 'changes-since=2011-01-24T17:08:01Z'
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?%s' % params)
+ req = fakes.HTTPRequestV3.blank('/servers?%s' % params)
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 1)
@@ -917,7 +917,7 @@ class ServersControllerTest(test.TestCase):
def test_get_servers_allows_changes_since_bad_value(self):
params = 'changes-since=asdf'
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?%s' % params)
+ req = fakes.HTTPRequestV3.blank('/servers?%s' % params)
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.index, req)
def test_get_servers_admin_filters_as_user(self):
@@ -943,7 +943,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
query_str = "name=foo&ip=10.*&status=active&unknown_option=meow"
- req = fakes.HTTPRequest.blank('/v3/fake/servers?%s' % query_str)
+ req = fakes.HTTPRequest.blank('/servers?%s' % query_str)
res = self.controller.index(req)
servers = res['servers']
@@ -972,7 +972,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
query_str = "name=foo&ip=10.*&status=active&unknown_option=meow"
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?%s' % query_str,
+ req = fakes.HTTPRequestV3.blank('/servers?%s' % query_str,
use_admin_context=True)
servers = self.controller.index(req)['servers']
@@ -994,7 +994,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?ip=10\..*')
+ req = fakes.HTTPRequestV3.blank('/servers?ip=10\..*')
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 1)
@@ -1016,7 +1016,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers?ip6=ffff.*',
+ req = fakes.HTTPRequestV3.blank('/servers?ip6=ffff.*',
use_admin_context=True)
servers = self.controller.index(req)['servers']
@@ -1028,7 +1028,7 @@ class ServersControllerTest(test.TestCase):
fakes.fake_instance_get(name='server_test',
access_ipv4='0.0.0.0',
access_ipv6='beef::0123'))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {
@@ -1045,7 +1045,7 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(res_dict['server']['accessIPv6'], 'beef::0123')
def test_update_server_invalid_xml_raises_lookup(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/xml'
#xml request which raises LookupError
@@ -1057,7 +1057,7 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(res.status_int, 400)
def test_update_server_invalid_xml_raises_expat(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/xml'
#xml request which raises ExpatError
@@ -1071,7 +1071,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_name(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(name='server_test'))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'name': 'server_test'}}
@@ -1084,7 +1084,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_name_too_long(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(name='server_test'))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'name': 'x' * 256}}
@@ -1095,7 +1095,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv4(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv4='0.0.0.0'))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv4': '0.0.0.0'}}
@@ -1108,7 +1108,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv4_bad_format(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv4='0.0.0.0'))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv4': 'bad_format'}}
@@ -1119,7 +1119,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv4_none(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv4='0.0.0.0'))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv4': None}}
@@ -1132,7 +1132,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv4_blank(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv4='0.0.0.0'))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv4': ''}}
@@ -1145,7 +1145,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv6(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv6='beef::0123'))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv6': 'beef::0123'}}
@@ -1158,7 +1158,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv6_bad_format(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv6='beef::0123'))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv6': 'bad_format'}}
@@ -1169,7 +1169,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv6_none(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv6='beef::0123'))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv6': None}}
@@ -1182,7 +1182,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv6_blank(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv6='beef::0123'))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv6': ''}}
@@ -1193,7 +1193,7 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(res_dict['server']['accessIPv6'], '')
def test_update_server_personality(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {
@@ -1223,7 +1223,7 @@ class ServersControllerTest(test.TestCase):
# self.stubs.Set(db, 'instance_get',
# return_server_with_attributes(name='server_test'))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = "application/json"
req.body = jsonutils.dumps(body)
@@ -1237,7 +1237,7 @@ class ServersControllerTest(test.TestCase):
raise exception.InstanceNotFound(instance_id='fake')
self.stubs.Set(compute_api.API, 'get', fake_get)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'name': 'server_test'}}
@@ -1250,7 +1250,7 @@ class ServersControllerTest(test.TestCase):
raise exception.InstanceNotFound(instance_id='fake')
self.stubs.Set(compute_api.API, 'update', fake_update)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'name': 'server_test'}}
@@ -1263,7 +1263,7 @@ class ServersControllerTest(test.TestCase):
fakes.fake_instance_get(vm_state=vm_states.ACTIVE))
# proper local hrefs must start with 'http://localhost/v3/'
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
- image_href = 'http://localhost/v3/fake/images/%s' % image_uuid
+ image_href = 'http://localhost/v3/images/%s' % image_uuid
access_ipv4 = 'bad_format'
access_ipv6 = 'fead::1234'
body = {
@@ -1285,7 +1285,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/a/action')
+ req = fakes.HTTPRequestV3.blank('/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1297,7 +1297,7 @@ class ServersControllerTest(test.TestCase):
fakes.fake_instance_get(vm_state=vm_states.ACTIVE))
# proper local hrefs must start with 'http://localhost/v3/'
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
- image_href = 'http://localhost/v3/fake/images/%s' % image_uuid
+ image_href = 'http://localhost/v3/images/%s' % image_uuid
access_ipv4 = '0.0.0.0'
access_ipv6 = 'fead::1234'
body = {
@@ -1319,7 +1319,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/a/action')
+ req = fakes.HTTPRequestV3.blank('/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1331,7 +1331,7 @@ class ServersControllerTest(test.TestCase):
fakes.fake_instance_get(vm_state=vm_states.ACTIVE))
# proper local hrefs must start with 'http://localhost/v3/'
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
- image_href = 'http://localhost/v3/fake/images/%s' % image_uuid
+ image_href = 'http://localhost/v3/images/%s' % image_uuid
access_ipv4 = '0.0.0.0'
access_ipv6 = 'fead::1234'
body = {
@@ -1353,7 +1353,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/a/action')
+ req = fakes.HTTPRequestV3.blank('/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1365,7 +1365,7 @@ class ServersControllerTest(test.TestCase):
fakes.fake_instance_get(vm_state=vm_states.ACTIVE))
# proper local hrefs must start with 'http://localhost/v3/'
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
- image_href = 'http://localhost/v3/fake/images/%s' % image_uuid
+ image_href = 'http://localhost/v3/images/%s' % image_uuid
access_ipv4 = '0.0.0.0'
access_ipv6 = 'fead::1234'
body = {
@@ -1387,7 +1387,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/a/action')
+ req = fakes.HTTPRequestV3.blank('/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1407,7 +1407,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_by_uuid',
fakes.fake_instance_get(vm_state=vm_states.ACTIVE))
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
- image_href = 'http://localhost/v3/fake/images/%s' % image_uuid
+ image_href = 'http://localhost/v3/images/%s' % image_uuid
body = {
'rebuild': {
'name': 'new_name',
@@ -1415,7 +1415,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/a/action')
+ req = fakes.HTTPRequestV3.blank('/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1435,7 +1435,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_by_uuid',
fakes.fake_instance_get(vm_state=vm_states.ACTIVE))
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
- image_href = 'http://localhost/v3/fake/images/%s' % image_uuid
+ image_href = 'http://localhost/v3/images/%s' % image_uuid
body = {
'rebuild': {
'name': 'new_name',
@@ -1443,7 +1443,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/a/action')
+ req = fakes.HTTPRequestV3.blank('/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1464,7 +1464,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_by_uuid',
fakes.fake_instance_get(vm_state=vm_states.ACTIVE))
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
- image_href = 'http://localhost/v3/fake/images/%s' % image_uuid
+ image_href = 'http://localhost/v3/images/%s' % image_uuid
body = {
'rebuild': {
'name': 'new_name',
@@ -1472,7 +1472,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/a/action')
+ req = fakes.HTTPRequestV3.blank('/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1490,7 +1490,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_by_uuid',
fakes.fake_instance_get(vm_state=vm_states.ACTIVE))
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
- image_href = 'http://localhost/v3/fake/images/%s' % image_uuid
+ image_href = 'http://localhost/v3/images/%s' % image_uuid
body = {
'rebuild': {
'name': 'new_name',
@@ -1498,7 +1498,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/a/action')
+ req = fakes.HTTPRequestV3.blank('/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1510,7 +1510,7 @@ class ServersControllerTest(test.TestCase):
fakes.fake_instance_get(vm_state=vm_states.ACTIVE))
# proper local hrefs must start with 'http://localhost/v3/'
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
- image_href = 'http://localhost/v3/fake/images/%s' % image_uuid
+ image_href = 'http://localhost/v3/images/%s' % image_uuid
access_ipv4 = '1.2.3.4'
access_ipv6 = 'bad_format'
body = {
@@ -1532,7 +1532,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/a/action')
+ req = fakes.HTTPRequestV3.blank('/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1545,7 +1545,7 @@ class ServersControllerTest(test.TestCase):
"links": [
{
"rel": "bookmark",
- "href": 'http://localhost/fake/flavors/1',
+ "href": 'http://localhost/flavors/1',
},
],
}
@@ -1554,11 +1554,11 @@ class ServersControllerTest(test.TestCase):
"links": [
{
"rel": "bookmark",
- "href": 'http://localhost/fake/images/10',
+ "href": 'http://localhost/images/10',
},
],
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/detail')
+ req = fakes.HTTPRequestV3.blank('/servers/detail')
res_dict = self.controller.detail(req)
for i, s in enumerate(res_dict['servers']):
@@ -1586,7 +1586,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_all_by_filters',
return_servers_with_host)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/detail')
+ req = fakes.HTTPRequestV3.blank('/servers/detail')
res_dict = self.controller.detail(req)
server_list = res_dict['servers']
@@ -1601,7 +1601,7 @@ class ServersControllerTest(test.TestCase):
def _delete_server_instance(self, uuid=FAKE_UUID):
fakes.stub_out_instance_quota(self.stubs, 0, 10)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % uuid)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % uuid)
req.method = 'DELETE'
self.server_delete_called = False
@@ -1626,7 +1626,7 @@ class ServersControllerTest(test.TestCase):
def test_delete_server_instance_while_building(self):
fakes.stub_out_instance_quota(self.stubs, 0, 10)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'DELETE'
self.server_delete_called = False
@@ -1640,7 +1640,7 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(self.server_delete_called, True)
def test_delete_server_instance_while_resize(self):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'DELETE'
self.server_delete_called = False
@@ -1673,7 +1673,7 @@ class ServerStatusTest(test.TestCase):
fakes.fake_instance_get(vm_state=vm_state,
task_state=task_state))
- request = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ request = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
return self.controller.show(request, FAKE_UUID)
def test_active(self):
@@ -1699,7 +1699,7 @@ class ServerStatusTest(test.TestCase):
rule = {'compute:reboot':
common_policy.parse_rule('role:admin')}
common_policy.set_rules(common_policy.Rules(rule))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/1234/action')
+ req = fakes.HTTPRequestV3.blank('/servers/1234/action')
self.assertRaises(exception.PolicyNotAuthorized,
self.controller._action_reboot, req, '1234',
{'reboot': {'type': 'HARD'}})
@@ -1727,7 +1727,7 @@ class ServerStatusTest(test.TestCase):
rule = {'compute:confirm_resize':
common_policy.parse_rule('role:admin')}
common_policy.set_rules(common_policy.Rules(rule))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/1234/action')
+ req = fakes.HTTPRequestV3.blank('/servers/1234/action')
self.assertRaises(exception.PolicyNotAuthorized,
self.controller._action_confirm_resize, req, '1234', {})
@@ -1749,7 +1749,7 @@ class ServerStatusTest(test.TestCase):
rule = {'compute:revert_resize':
common_policy.parse_rule('role:admin')}
common_policy.set_rules(common_policy.Rules(rule))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/1234/action')
+ req = fakes.HTTPRequestV3.blank('/servers/1234/action')
self.assertRaises(exception.PolicyNotAuthorized,
self.controller._action_revert_resize, req, '1234', {})
@@ -1881,7 +1881,7 @@ class ServersControllerCreateTest(test.TestCase):
name='server_test', imageRef=image_uuid, flavorRef=2,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1902,7 +1902,7 @@ class ServersControllerCreateTest(test.TestCase):
'flavorRef': flavor_ref,
}
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1943,7 +1943,7 @@ class ServersControllerCreateTest(test.TestCase):
self.addCleanup(image_service.update, context, image_uuid,
{'status': 'active'})
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
body = dict(server=dict(
name='server_test', imageRef=image_uuid, flavorRef=2,
@@ -1973,7 +1973,7 @@ class ServersControllerCreateTest(test.TestCase):
self.addCleanup(image_service.update, context, image_uuid,
{'size': orig_size})
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
body = dict(server=dict(name='server_test',
imageRef=image_uuid,
@@ -2001,7 +2001,7 @@ class ServersControllerCreateTest(test.TestCase):
# 'flavorRef': flavor_ref,
# }
# }
- # req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ # req = fakes.HTTPRequestV3.blank('/servers')
# req.method = 'POST'
# req.body = jsonutils.dumps(body)
# req.headers["content-type"] = "application/json"
@@ -2025,7 +2025,7 @@ class ServersControllerCreateTest(test.TestCase):
# 'flavorRef': flavor_ref,
# }
# }
- # req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ # req = fakes.HTTPRequestV3.blank('/servers')
# req.method = 'POST'
# req.body = jsonutils.dumps(body)
# req.headers["content-type"] = "application/json"
@@ -2049,7 +2049,7 @@ class ServersControllerCreateTest(test.TestCase):
# 'flavorRef': flavor_ref,
# }
# }
- # req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ # req = fakes.HTTPRequestV3.blank('/servers')
# req.method = 'POST'
# req.body = jsonutils.dumps(body)
# req.headers["content-type"] = "application/json"
@@ -2073,7 +2073,7 @@ class ServersControllerCreateTest(test.TestCase):
# 'flavorRef': flavor_ref,
# }
# }
- # req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ # req = fakes.HTTPRequestV3.blank('/servers')
# req.method = 'POST'
# req.body = jsonutils.dumps(body)
# req.headers["content-type"] = "application/json"
@@ -2103,7 +2103,7 @@ class ServersControllerCreateTest(test.TestCase):
# }
# }
- # req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ # req = fakes.HTTPRequestV3.blank('/servers')
# req.method = 'POST'
# req.body = jsonutils.dumps(body)
# req.headers["content-type"] = "application/json"
@@ -2134,7 +2134,7 @@ class ServersControllerCreateTest(test.TestCase):
# }
# }
- # req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ # req = fakes.HTTPRequestV3.blank('/servers')
# req.method = 'POST'
# req.body = jsonutils.dumps(body)
# req.headers["content-type"] = "application/json"
@@ -2165,7 +2165,7 @@ class ServersControllerCreateTest(test.TestCase):
# }
# }
- # req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ # req = fakes.HTTPRequestV3.blank('/servers')
# req.method = 'POST'
# req.body = jsonutils.dumps(body)
# req.headers["content-type"] = "application/json"
@@ -2247,7 +2247,7 @@ class ServersControllerCreateTest(test.TestCase):
# }
# }
- # req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ # req = fakes.HTTPRequestV3.blank('/servers')
# req.method = 'POST'
# req.body = jsonutils.dumps(body)
# req.headers["content-type"] = "application/json"
@@ -2272,7 +2272,7 @@ class ServersControllerCreateTest(test.TestCase):
# }
# }
- # req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ # req = fakes.HTTPRequestV3.blank('/servers')
# req.method = 'POST'
# req.body = jsonutils.dumps(body)
# req.headers["content-type"] = "application/json"
@@ -2281,8 +2281,8 @@ class ServersControllerCreateTest(test.TestCase):
def test_create_instance_image_ref_is_bookmark(self):
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
- image_href = 'http://localhost/fake/images/%s' % image_uuid
- flavor_ref = 'http://localhost/fake/flavors/3'
+ image_href = 'http://localhost/images/%s' % image_uuid
+ flavor_ref = 'http://localhost/flavors/3'
body = {
'server': {
'name': 'server_test',
@@ -2291,7 +2291,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2302,8 +2302,8 @@ class ServersControllerCreateTest(test.TestCase):
def test_create_instance_image_ref_is_invalid(self):
image_uuid = 'this_is_not_a_valid_uuid'
- image_href = 'http://localhost/fake/images/%s' % image_uuid
- flavor_ref = 'http://localhost/fake/flavors/3'
+ image_href = 'http://localhost/images/%s' % image_uuid
+ flavor_ref = 'http://localhost/flavors/3'
body = {
'server': {
'name': 'server_test',
@@ -2312,7 +2312,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2330,7 +2330,7 @@ class ServersControllerCreateTest(test.TestCase):
server.pop('imageRef', None)
server.update(params)
body = dict(server=server)
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2764,8 +2764,8 @@ class ServersControllerCreateTest(test.TestCase):
def test_create_instance_with_access_ip(self):
# proper local hrefs must start with 'http://localhost/v3/'
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
- image_href = 'http://localhost/v3/fake/images/%s' % image_uuid
- flavor_ref = 'http://localhost/fake/flavors/3'
+ image_href = 'http://localhost/v3/images/%s' % image_uuid
+ flavor_ref = 'http://localhost/flavors/3'
access_ipv4 = '1.2.3.4'
access_ipv6 = 'fead::1234'
body = {
@@ -2788,7 +2788,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2804,8 +2804,8 @@ class ServersControllerCreateTest(test.TestCase):
# proper local hrefs must start with 'http://localhost/v3/'
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
- image_href = 'http://localhost/v3/fake/images/%s' % image_uuid
- flavor_ref = 'http://localhost/fake/flavors/3'
+ image_href = 'http://localhost/v3/images/%s' % image_uuid
+ flavor_ref = 'http://localhost/flavors/3'
access_ipv4 = '1.2.3.4'
access_ipv6 = 'fead::1234'
body = {
@@ -2828,7 +2828,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2841,8 +2841,8 @@ class ServersControllerCreateTest(test.TestCase):
def test_create_instance_bad_format_access_ip_v4(self):
# proper local hrefs must start with 'http://localhost/v3/'
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
- image_href = 'http://localhost/v3/fake/images/%s' % image_uuid
- flavor_ref = 'http://localhost/fake/flavors/3'
+ image_href = 'http://localhost/v3/images/%s' % image_uuid
+ flavor_ref = 'http://localhost/flavors/3'
access_ipv4 = 'bad_format'
access_ipv6 = 'fead::1234'
body = {
@@ -2865,7 +2865,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2875,8 +2875,8 @@ class ServersControllerCreateTest(test.TestCase):
def test_create_instance_bad_format_access_ip_v6(self):
# proper local hrefs must start with 'http://localhost/v3/'
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
- image_href = 'http://localhost/v3/fake/images/%s' % image_uuid
- flavor_ref = 'http://localhost/fake/flavors/3'
+ image_href = 'http://localhost/v3/images/%s' % image_uuid
+ flavor_ref = 'http://localhost/flavors/3'
access_ipv4 = '1.2.3.4'
access_ipv6 = 'bad_format'
body = {
@@ -2899,7 +2899,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2930,7 +2930,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2961,7 +2961,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2996,7 +2996,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3024,7 +3024,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3048,7 +3048,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3072,7 +3072,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3096,7 +3096,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3110,7 +3110,7 @@ class ServersControllerCreateTest(test.TestCase):
body = dict(server=dict(
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
key_name='nonexistentkey'))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3124,7 +3124,7 @@ class ServersControllerCreateTest(test.TestCase):
body = dict(server=dict(
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
key_name='key'))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3140,7 +3140,7 @@ class ServersControllerCreateTest(test.TestCase):
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3149,13 +3149,13 @@ class ServersControllerCreateTest(test.TestCase):
self.controller.create, req, body)
def test_create_instance_invalid_flavor_id_int(self):
- image_href = 'http://localhost/v3/fake/images/2'
+ image_href = 'http://localhost/v3/images/2'
flavor_ref = -1
body = dict(server=dict(
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3170,7 +3170,7 @@ class ServersControllerCreateTest(test.TestCase):
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3198,7 +3198,7 @@ class ServersControllerCreateTest(test.TestCase):
# },
# }
- # req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ # req = fakes.HTTPRequestV3.blank('/servers')
# req.method = 'POST'
# req.body = jsonutils.dumps(body)
# req.headers["content-type"] = "application/json"
@@ -3227,7 +3227,7 @@ class ServersControllerCreateTest(test.TestCase):
# },
# }
- # req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ # req = fakes.HTTPRequestV3.blank('/servers')
# req.method = 'POST'
# req.body = jsonutils.dumps(body)
# req.headers["content-type"] = "application/json"
@@ -3256,7 +3256,7 @@ class ServersControllerCreateTest(test.TestCase):
# },
# }
- # req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ # req = fakes.HTTPRequestV3.blank('/servers')
# req.method = 'POST'
# req.body = jsonutils.dumps(body)
# req.headers["content-type"] = "application/json"
@@ -3283,7 +3283,7 @@ class ServersControllerCreateTest(test.TestCase):
# },
# }
- # req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ # req = fakes.HTTPRequestV3.blank('/servers')
# req.method = 'POST'
# req.body = jsonutils.dumps(body)
# req.headers["content-type"] = "application/json"
@@ -3311,7 +3311,7 @@ class ServersControllerCreateTest(test.TestCase):
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3330,7 +3330,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3350,7 +3350,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = "application/json"
@@ -3371,7 +3371,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = "application/json"
@@ -3392,7 +3392,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = "application/json"
@@ -3430,7 +3430,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3438,8 +3438,8 @@ class ServersControllerCreateTest(test.TestCase):
self.controller.create, req, body)
def test_create_location(self):
- selfhref = 'http://localhost/v3/fake/servers/%s' % FAKE_UUID
- bookhref = 'http://localhost/fake/servers/%s' % FAKE_UUID
+ selfhref = 'http://localhost/v3/servers/%s' % FAKE_UUID
+ bookhref = 'http://localhost/servers/%s' % FAKE_UUID
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
image_href = 'http://localhost/v3/images/%s' % image_uuid
flavor_ref = 'http://localhost/123/flavors/3'
@@ -3461,7 +3461,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
@@ -3477,7 +3477,7 @@ class ServersControllerCreateTest(test.TestCase):
name='server_test', imageRef=image_uuid, flavorRef=3,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -4255,10 +4255,10 @@ class ServersViewBuilderTest(test.TestCase):
self.uuid = self.instance['uuid']
self.view_builder = views.servers.ViewBuilder()
- self.request = fakes.HTTPRequestV3.blank("/v2")
+ self.request = fakes.HTTPRequestV3.blank("")
def test_get_flavor_valid_instance_type(self):
- flavor_bookmark = "http://localhost/fake/flavors/1"
+ flavor_bookmark = "http://localhost/flavors/1"
expected = {"id": "1",
"links": [{"rel": "bookmark",
"href": flavor_bookmark}]}
@@ -4266,8 +4266,8 @@ class ServersViewBuilderTest(test.TestCase):
self.assertEqual(result, expected)
def test_build_server(self):
- self_link = "http://localhost/v3/fake/servers/%s" % self.uuid
- bookmark_link = "http://localhost/fake/servers/%s" % self.uuid
+ self_link = "http://localhost/v3/servers/%s" % self.uuid
+ bookmark_link = "http://localhost/servers/%s" % self.uuid
expected_server = {
"server": {
"id": self.uuid,
@@ -4296,12 +4296,12 @@ class ServersViewBuilderTest(test.TestCase):
"links": [
{
"rel": "self",
- "href": "http://localhost/v3/fake/servers/%s" %
+ "href": "http://localhost/v3/servers/%s" %
self.uuid,
},
{
"rel": "bookmark",
- "href": "http://localhost/fake/servers/%s" % self.uuid,
+ "href": "http://localhost/servers/%s" % self.uuid,
},
],
}
@@ -4311,10 +4311,10 @@ class ServersViewBuilderTest(test.TestCase):
self.assertThat(output, matchers.DictMatches(expected_server))
def test_build_server_detail(self):
- image_bookmark = "http://localhost/fake/images/5"
- flavor_bookmark = "http://localhost/fake/flavors/1"
- self_link = "http://localhost/v3/fake/servers/%s" % self.uuid
- bookmark_link = "http://localhost/fake/servers/%s" % self.uuid
+ image_bookmark = "http://localhost/images/5"
+ flavor_bookmark = "http://localhost/flavors/1"
+ self_link = "http://localhost/v3/servers/%s" % self.uuid
+ bookmark_link = "http://localhost/servers/%s" % self.uuid
expected_server = {
"server": {
"id": self.uuid,
@@ -4384,10 +4384,10 @@ class ServersViewBuilderTest(test.TestCase):
'created_at': datetime.datetime(2010, 10, 10, 12, 0, 0),
}
- image_bookmark = "http://localhost/fake/images/5"
- flavor_bookmark = "http://localhost/fake/flavors/1"
- self_link = "http://localhost/v3/fake/servers/%s" % self.uuid
- bookmark_link = "http://localhost/fake/servers/%s" % self.uuid
+ image_bookmark = "http://localhost/images/5"
+ flavor_bookmark = "http://localhost/flavors/1"
+ self_link = "http://localhost/v3/servers/%s" % self.uuid
+ bookmark_link = "http://localhost/servers/%s" % self.uuid
expected_server = {
"server": {
"id": self.uuid,
@@ -4517,10 +4517,10 @@ class ServersViewBuilderTest(test.TestCase):
'created_at': datetime.datetime(2010, 10, 10, 12, 0, 0),
}
- image_bookmark = "http://localhost/fake/images/5"
- flavor_bookmark = "http://localhost/fake/flavors/1"
- self_link = "http://localhost/v3/fake/servers/%s" % self.uuid
- bookmark_link = "http://localhost/fake/servers/%s" % self.uuid
+ image_bookmark = "http://localhost/images/5"
+ flavor_bookmark = "http://localhost/flavors/1"
+ self_link = "http://localhost/v3/servers/%s" % self.uuid
+ bookmark_link = "http://localhost/servers/%s" % self.uuid
output = self.view_builder.show(self.request, self.instance)
self.assertFalse('fault' in output['server'])
@@ -4529,10 +4529,10 @@ class ServersViewBuilderTest(test.TestCase):
#set the power state of the instance to running
self.instance['vm_state'] = vm_states.ACTIVE
self.instance['progress'] = 100
- image_bookmark = "http://localhost/fake/images/5"
- flavor_bookmark = "http://localhost/fake/flavors/1"
- self_link = "http://localhost/v3/fake/servers/%s" % self.uuid
- bookmark_link = "http://localhost/fake/servers/%s" % self.uuid
+ image_bookmark = "http://localhost/images/5"
+ flavor_bookmark = "http://localhost/flavors/1"
+ self_link = "http://localhost/v3/servers/%s" % self.uuid
+ bookmark_link = "http://localhost/servers/%s" % self.uuid
expected_server = {
"server": {
"id": self.uuid,
@@ -4591,10 +4591,10 @@ class ServersViewBuilderTest(test.TestCase):
self.instance['access_ip_v4'] = '1.2.3.4'
- image_bookmark = "http://localhost/fake/images/5"
- flavor_bookmark = "http://localhost/fake/flavors/1"
- self_link = "http://localhost/v3/fake/servers/%s" % self.uuid
- bookmark_link = "http://localhost/fake/servers/%s" % self.uuid
+ image_bookmark = "http://localhost/images/5"
+ flavor_bookmark = "http://localhost/flavors/1"
+ self_link = "http://localhost/v3/servers/%s" % self.uuid
+ bookmark_link = "http://localhost/servers/%s" % self.uuid
expected_server = {
"server": {
"id": self.uuid,
@@ -4653,10 +4653,10 @@ class ServersViewBuilderTest(test.TestCase):
self.instance['access_ip_v6'] = 'fead::1234'
- image_bookmark = "http://localhost/fake/images/5"
- flavor_bookmark = "http://localhost/fake/flavors/1"
- self_link = "http://localhost/v3/fake/servers/%s" % self.uuid
- bookmark_link = "http://localhost/fake/servers/%s" % self.uuid
+ image_bookmark = "http://localhost/images/5"
+ flavor_bookmark = "http://localhost/flavors/1"
+ self_link = "http://localhost/v3/servers/%s" % self.uuid
+ bookmark_link = "http://localhost/servers/%s" % self.uuid
expected_server = {
"server": {
"id": self.uuid,
@@ -4717,10 +4717,10 @@ class ServersViewBuilderTest(test.TestCase):
metadata.append(models.InstanceMetadata(key="Open", value="Stack"))
self.instance['metadata'] = metadata
- image_bookmark = "http://localhost/fake/images/5"
- flavor_bookmark = "http://localhost/fake/flavors/1"
- self_link = "http://localhost/v3/fake/servers/%s" % self.uuid
- bookmark_link = "http://localhost/fake/servers/%s" % self.uuid
+ image_bookmark = "http://localhost/images/5"
+ flavor_bookmark = "http://localhost/flavors/1"
+ self_link = "http://localhost/v3/servers/%s" % self.uuid
+ bookmark_link = "http://localhost/servers/%s" % self.uuid
expected_server = {
"server": {
"id": self.uuid,
@@ -5777,7 +5777,7 @@ class ServersUnprocessableEntityTestCase(test.TestCase):
self.controller = servers.ServersController(extension_info=ext_info)
def _unprocessable_server_create(self, body):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers')
+ req = fakes.HTTPRequestV3.blank('/servers')
req.method = 'POST'
self.assertRaises(webob.exc.HTTPUnprocessableEntity,
@@ -5795,7 +5795,7 @@ class ServersUnprocessableEntityTestCase(test.TestCase):
self._unprocessable_server_create(body=body)
def _unprocessable_server_update(self, body):
- req = fakes.HTTPRequestV3.blank('/v3/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequestV3.blank('/servers/%s' % FAKE_UUID)
req.method = 'PUT'
self.assertRaises(webob.exc.HTTPUnprocessableEntity,
diff --git a/nova/tests/api/openstack/compute/test_flavors.py b/nova/tests/api/openstack/compute/test_flavors.py
index 77e637044..3741fcd33 100644
--- a/nova/tests/api/openstack/compute/test_flavors.py
+++ b/nova/tests/api/openstack/compute/test_flavors.py
@@ -792,6 +792,7 @@ class ParseIsPublicTest(test.TestCase):
def test_string_none(self):
self.assertPublic(None, 'none')
+ self.assertPublic(None, 'None')
def test_other(self):
self.assertRaises(
diff --git a/nova/tests/api/openstack/compute/test_limits.py b/nova/tests/api/openstack/compute/test_limits.py
index b9dc72b1f..3dbc7bfea 100644
--- a/nova/tests/api/openstack/compute/test_limits.py
+++ b/nova/tests/api/openstack/compute/test_limits.py
@@ -32,14 +32,18 @@ from nova.openstack.common import jsonutils
from nova import test
from nova.tests.api.openstack import fakes
from nova.tests import matchers
+from nova import utils
TEST_LIMITS = [
- limits.Limit("GET", "/delayed", "^/delayed", 1, limits.PER_MINUTE),
- limits.Limit("POST", "*", ".*", 7, limits.PER_MINUTE),
- limits.Limit("POST", "/servers", "^/servers", 3, limits.PER_MINUTE),
- limits.Limit("PUT", "*", "", 10, limits.PER_MINUTE),
- limits.Limit("PUT", "/servers", "^/servers", 5, limits.PER_MINUTE),
+ limits.Limit("GET", "/delayed", "^/delayed", 1,
+ utils.TIME_UNITS['MINUTE']),
+ limits.Limit("POST", "*", ".*", 7, utils.TIME_UNITS['MINUTE']),
+ limits.Limit("POST", "/servers", "^/servers", 3,
+ utils.TIME_UNITS['MINUTE']),
+ limits.Limit("PUT", "*", "", 10, utils.TIME_UNITS['MINUTE']),
+ limits.Limit("PUT", "/servers", "^/servers", 5,
+ utils.TIME_UNITS['MINUTE']),
]
NS = {
'atom': 'http://www.w3.org/2005/Atom',
@@ -312,7 +316,7 @@ class LimitsControllerTest(BaseLimitTestSuite):
req, 1, {})
-class TestLimiter(limits.Limiter):
+class MockLimiter(limits.Limiter):
pass
@@ -331,12 +335,12 @@ class LimitMiddlewareTest(BaseLimitTestSuite):
super(LimitMiddlewareTest, self).setUp()
_limits = '(GET, *, .*, 1, MINUTE)'
self.app = limits.RateLimitingMiddleware(self._empty_app, _limits,
- "%s.TestLimiter" %
+ "%s.MockLimiter" %
self.__class__.__module__)
def test_limit_class(self):
# Test that middleware selected correct limiter class.
- assert isinstance(self.app._limiter, TestLimiter)
+ assert isinstance(self.app._limiter, MockLimiter)
def test_good_request(self):
# Test successful GET request through middleware.
@@ -485,8 +489,8 @@ class ParseLimitsTest(BaseLimitTestSuite):
self.assertEqual([t.value for t in l], expected)
# ...and the units...
- expected = [limits.PER_MINUTE, limits.PER_HOUR,
- limits.PER_SECOND, limits.PER_DAY]
+ expected = [utils.TIME_UNITS['MINUTE'], utils.TIME_UNITS['HOUR'],
+ utils.TIME_UNITS['SECOND'], utils.TIME_UNITS['DAY']]
self.assertEqual([t.unit for t in l], expected)
diff --git a/nova/tests/api/openstack/compute/test_server_metadata.py b/nova/tests/api/openstack/compute/test_server_metadata.py
index fa25ad4a3..f0548ffa0 100644
--- a/nova/tests/api/openstack/compute/test_server_metadata.py
+++ b/nova/tests/api/openstack/compute/test_server_metadata.py
@@ -26,6 +26,7 @@ from nova.compute import vm_states
import nova.db
from nova import exception
from nova.openstack.common import jsonutils
+from nova.openstack.common import timeutils
from nova import test
from nova.tests.api.openstack import fakes
@@ -77,6 +78,7 @@ def return_server(context, server_id):
'uuid': '0cc3346e-9fef-4445-abe6-5d2b2690ec64',
'name': 'fake',
'locked': False,
+ 'launched_at': timeutils.utcnow(),
'vm_state': vm_states.ACTIVE}
@@ -85,6 +87,7 @@ def return_server_by_uuid(context, server_uuid):
'uuid': '0cc3346e-9fef-4445-abe6-5d2b2690ec64',
'name': 'fake',
'locked': False,
+ 'launched_at': timeutils.utcnow(),
'vm_state': vm_states.ACTIVE}
diff --git a/nova/tests/api/openstack/compute/test_servers.py b/nova/tests/api/openstack/compute/test_servers.py
index af8a4a276..82bb6b868 100644
--- a/nova/tests/api/openstack/compute/test_servers.py
+++ b/nova/tests/api/openstack/compute/test_servers.py
@@ -231,7 +231,7 @@ class ServersControllerTest(test.TestCase):
self.assertEquals(res, [(None, None, port)])
def test_get_server_by_uuid(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
res_dict = self.controller.show(req, FAKE_UUID)
self.assertEqual(res_dict['server']['id'], FAKE_UUID)
@@ -250,7 +250,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get',
return_instance_with_host)
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
server1 = self.controller.show(req, FAKE_UUID)
server2 = self.controller.show(req, FAKE_UUID)
@@ -263,7 +263,7 @@ class ServersControllerTest(test.TestCase):
flavor_bookmark = "http://localhost/fake/flavors/1"
uuid = FAKE_UUID
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % uuid)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % uuid)
res_dict = self.controller.show(req, uuid)
expected_server = {
@@ -330,7 +330,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_by_uuid', new_return_server)
uuid = FAKE_UUID
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % uuid)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % uuid)
res_dict = self.controller.show(req, uuid)
expected_server = {
"server": {
@@ -399,7 +399,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_by_uuid', new_return_server)
uuid = FAKE_UUID
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % uuid)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % uuid)
res_dict = self.controller.show(req, uuid)
expected_server = {
"server": {
@@ -488,7 +488,7 @@ class ServersControllerTest(test.TestCase):
return_server = fakes.fake_instance_get(nw_cache=nw_cache)
self.stubs.Set(db, 'instance_get_by_uuid', return_server)
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s/ips' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s/ips' % FAKE_UUID)
res_dict = self.ips_controller.index(req, FAKE_UUID)
expected = {
@@ -508,7 +508,7 @@ class ServersControllerTest(test.TestCase):
self.assertThat(res_dict, matchers.DictMatches(expected))
def test_get_server_addresses_nonexistent_network(self):
- url = '/v2/fake/servers/%s/ips/network_0' % FAKE_UUID
+ url = '/fake/servers/%s/ips/network_0' % FAKE_UUID
req = fakes.HTTPRequest.blank(url)
self.assertRaises(webob.exc.HTTPNotFound, self.ips_controller.show,
req, FAKE_UUID, 'network_0')
@@ -520,7 +520,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_by_uuid', fake_instance_get)
server_id = str(uuid.uuid4())
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s/ips' % server_id)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s/ips' % server_id)
self.assertRaises(webob.exc.HTTPNotFound,
self.ips_controller.index, req, server_id)
@@ -528,14 +528,14 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_all_by_filters',
return_servers_empty)
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
res_dict = self.controller.index(req)
num_servers = len(res_dict['servers'])
self.assertEqual(0, num_servers)
def test_get_server_list_with_reservation_id(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers?reservation_id=foo')
+ req = fakes.HTTPRequest.blank('/fake/servers?reservation_id=foo')
res_dict = self.controller.index(req)
i = 0
@@ -544,7 +544,7 @@ class ServersControllerTest(test.TestCase):
i += 1
def test_get_server_list_with_reservation_id_empty(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers/detail?'
+ req = fakes.HTTPRequest.blank('/fake/servers/detail?'
'reservation_id=foo')
res_dict = self.controller.detail(req)
@@ -554,7 +554,7 @@ class ServersControllerTest(test.TestCase):
i += 1
def test_get_server_list_with_reservation_id_details(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers/detail?'
+ req = fakes.HTTPRequest.blank('/fake/servers/detail?'
'reservation_id=foo')
res_dict = self.controller.detail(req)
@@ -564,7 +564,7 @@ class ServersControllerTest(test.TestCase):
i += 1
def test_get_server_list(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
res_dict = self.controller.index(req)
self.assertEqual(len(res_dict['servers']), 5)
@@ -587,7 +587,7 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(s['links'], expected_links)
def test_get_servers_with_limit(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers?limit=3')
+ req = fakes.HTTPRequest.blank('/fake/servers?limit=3')
res_dict = self.controller.index(req)
servers = res_dict['servers']
@@ -604,7 +604,7 @@ class ServersControllerTest(test.TestCase):
self.assertThat(params, matchers.DictMatches(expected_params))
def test_get_servers_with_limit_bad_value(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers?limit=aaa')
+ req = fakes.HTTPRequest.blank('/fake/servers?limit=aaa')
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.index, req)
@@ -612,14 +612,14 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_all_by_filters',
return_servers_empty)
- req = fakes.HTTPRequest.blank('/v2/fake/servers/detail')
+ req = fakes.HTTPRequest.blank('/fake/servers/detail')
res_dict = self.controller.index(req)
num_servers = len(res_dict['servers'])
self.assertEqual(0, num_servers)
def test_get_server_details_with_limit(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers/detail?limit=3')
+ req = fakes.HTTPRequest.blank('/fake/servers/detail?limit=3')
res = self.controller.detail(req)
servers = res['servers']
@@ -636,12 +636,12 @@ class ServersControllerTest(test.TestCase):
self.assertThat(params, matchers.DictMatches(expected))
def test_get_server_details_with_limit_bad_value(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers/detail?limit=aaa')
+ req = fakes.HTTPRequest.blank('/fake/servers/detail?limit=aaa')
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.detail, req)
def test_get_server_details_with_limit_and_other_params(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers/detail'
+ req = fakes.HTTPRequest.blank('/fake/servers/detail'
'?limit=3&blah=2:t')
res = self.controller.detail(req)
@@ -660,12 +660,12 @@ class ServersControllerTest(test.TestCase):
self.assertThat(params, matchers.DictMatches(expected))
def test_get_servers_with_too_big_limit(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers?limit=30')
+ req = fakes.HTTPRequest.blank('/fake/servers?limit=30')
res_dict = self.controller.index(req)
self.assertTrue('servers_links' not in res_dict)
def test_get_servers_with_bad_limit(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers?limit=asdf')
+ req = fakes.HTTPRequest.blank('/fake/servers?limit=asdf')
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.index, req)
@@ -682,7 +682,7 @@ class ServersControllerTest(test.TestCase):
self.assertEqual([s['name'] for s in servers], ['server3', 'server4'])
def test_get_servers_with_bad_marker(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers?limit=2&marker=asdf')
+ req = fakes.HTTPRequest.blank('/fake/servers?limit=2&marker=asdf')
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.index, req)
@@ -696,7 +696,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequest.blank('/v2/fake/servers?unknownoption=whee')
+ req = fakes.HTTPRequest.blank('/fake/servers?unknownoption=whee')
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 1)
@@ -715,7 +715,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequest.blank('/v2/fake/servers?image=12345')
+ req = fakes.HTTPRequest.blank('/fake/servers?image=12345')
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 1)
@@ -732,7 +732,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_all_by_filters',
fake_get_all)
- req = fakes.HTTPRequest.blank('/v2/fake/servers?tenant_id=fake',
+ req = fakes.HTTPRequest.blank('/fake/servers?tenant_id=fake',
use_admin_context=True)
res = self.controller.index(req)
@@ -748,7 +748,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_all_by_filters',
fake_get_all)
- req = fakes.HTTPRequest.blank('/v2/fake/servers',
+ req = fakes.HTTPRequest.blank('/fake/servers',
use_admin_context=True)
res = self.controller.index(req)
@@ -773,7 +773,7 @@ class ServersControllerTest(test.TestCase):
common_policy.set_rules(common_policy.Rules(rules))
- req = fakes.HTTPRequest.blank('/v2/fake/servers?all_tenants=1')
+ req = fakes.HTTPRequest.blank('/fake/servers?all_tenants=1')
res = self.controller.index(req)
self.assertTrue('servers' in res)
@@ -795,7 +795,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_all_by_filters',
fake_get_all)
- req = fakes.HTTPRequest.blank('/v2/fake/servers?all_tenants=1')
+ req = fakes.HTTPRequest.blank('/fake/servers?all_tenants=1')
self.assertRaises(exception.PolicyNotAuthorized,
self.controller.index, req)
@@ -813,14 +813,14 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequest.blank('/v2/fake/servers?flavor=12345')
+ req = fakes.HTTPRequest.blank('/fake/servers?flavor=12345')
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0]['id'], server_uuid)
def test_get_servers_with_bad_flavor(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers?flavor=abcde')
+ req = fakes.HTTPRequest.blank('/fake/servers?flavor=abcde')
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 0)
@@ -838,7 +838,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequest.blank('/v2/fake/servers?status=active')
+ req = fakes.HTTPRequest.blank('/fake/servers?status=active')
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 1)
@@ -846,13 +846,13 @@ class ServersControllerTest(test.TestCase):
def test_get_servers_invalid_status(self):
# Test getting servers by invalid status.
- req = fakes.HTTPRequest.blank('/v2/fake/servers?status=baloney',
+ req = fakes.HTTPRequest.blank('/fake/servers?status=baloney',
use_admin_context=False)
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 0)
def test_get_servers_deleted_status_as_user(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers?status=deleted',
+ req = fakes.HTTPRequest.blank('/fake/servers?status=deleted',
use_admin_context=False)
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.detail, req)
@@ -870,7 +870,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequest.blank('/v2/fake/servers?status=deleted',
+ req = fakes.HTTPRequest.blank('/fake/servers?status=deleted',
use_admin_context=True)
servers = self.controller.detail(req)['servers']
@@ -890,7 +890,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequest.blank('/v2/fake/servers?name=whee.*')
+ req = fakes.HTTPRequest.blank('/fake/servers?name=whee.*')
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 1)
@@ -913,7 +913,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
params = 'changes-since=2011-01-24T17:08:01Z'
- req = fakes.HTTPRequest.blank('/v2/fake/servers?%s' % params)
+ req = fakes.HTTPRequest.blank('/fake/servers?%s' % params)
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 1)
@@ -921,7 +921,7 @@ class ServersControllerTest(test.TestCase):
def test_get_servers_allows_changes_since_bad_value(self):
params = 'changes-since=asdf'
- req = fakes.HTTPRequest.blank('/v2/fake/servers?%s' % params)
+ req = fakes.HTTPRequest.blank('/fake/servers?%s' % params)
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.index, req)
def test_get_servers_admin_filters_as_user(self):
@@ -947,7 +947,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
query_str = "name=foo&ip=10.*&status=active&unknown_option=meow"
- req = fakes.HTTPRequest.blank('/v2/fake/servers?%s' % query_str)
+ req = fakes.HTTPRequest.blank('/fake/servers?%s' % query_str)
res = self.controller.index(req)
servers = res['servers']
@@ -976,7 +976,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
query_str = "name=foo&ip=10.*&status=active&unknown_option=meow"
- req = fakes.HTTPRequest.blank('/v2/fake/servers?%s' % query_str,
+ req = fakes.HTTPRequest.blank('/fake/servers?%s' % query_str,
use_admin_context=True)
servers = self.controller.index(req)['servers']
@@ -997,7 +997,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequest.blank('/v2/fake/servers?ip=10\..*')
+ req = fakes.HTTPRequest.blank('/fake/servers?ip=10\..*')
servers = self.controller.index(req)['servers']
self.assertEqual(len(servers), 1)
@@ -1019,7 +1019,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
- req = fakes.HTTPRequest.blank('/v2/fake/servers?ip6=ffff.*',
+ req = fakes.HTTPRequest.blank('/fake/servers?ip6=ffff.*',
use_admin_context=True)
servers = self.controller.index(req)['servers']
@@ -1031,7 +1031,7 @@ class ServersControllerTest(test.TestCase):
fakes.fake_instance_get(name='server_test',
access_ipv4='0.0.0.0',
access_ipv6='beef::0123'))
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {
@@ -1048,7 +1048,7 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(res_dict['server']['accessIPv6'], 'beef::0123')
def test_update_server_invalid_xml_raises_lookup(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/xml'
#xml request which raises LookupError
@@ -1060,7 +1060,7 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(res.status_int, 400)
def test_update_server_invalid_xml_raises_expat(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/xml'
#xml request which raises ExpatError
@@ -1074,7 +1074,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_name(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(name='server_test'))
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'name': 'server_test'}}
@@ -1087,7 +1087,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_name_too_long(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(name='server_test'))
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'name': 'x' * 256}}
@@ -1109,7 +1109,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv4(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv4='0.0.0.0'))
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv4': '0.0.0.0'}}
@@ -1122,7 +1122,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv4_bad_format(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv4='0.0.0.0'))
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv4': 'bad_format'}}
@@ -1133,7 +1133,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv4_none(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv4='0.0.0.0'))
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv4': None}}
@@ -1146,7 +1146,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv4_blank(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv4='0.0.0.0'))
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv4': ''}}
@@ -1159,7 +1159,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv6(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv6='beef::0123'))
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv6': 'beef::0123'}}
@@ -1172,7 +1172,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv6_bad_format(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv6='beef::0123'))
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv6': 'bad_format'}}
@@ -1183,7 +1183,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv6_none(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv6='beef::0123'))
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv6': None}}
@@ -1196,7 +1196,7 @@ class ServersControllerTest(test.TestCase):
def test_update_server_access_ipv6_blank(self):
self.stubs.Set(db, 'instance_get',
fakes.fake_instance_get(access_ipv6='beef::0123'))
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'accessIPv6': ''}}
@@ -1207,7 +1207,7 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(res_dict['server']['accessIPv6'], '')
def test_update_server_personality(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {
@@ -1237,7 +1237,7 @@ class ServersControllerTest(test.TestCase):
# self.stubs.Set(db, 'instance_get',
# return_server_with_attributes(name='server_test'))
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = "application/json"
req.body = jsonutils.dumps(body)
@@ -1251,7 +1251,7 @@ class ServersControllerTest(test.TestCase):
raise exception.InstanceNotFound(instance_id='fake')
self.stubs.Set(compute_api.API, 'get', fake_get)
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'name': 'server_test'}}
@@ -1264,7 +1264,7 @@ class ServersControllerTest(test.TestCase):
raise exception.InstanceNotFound(instance_id='fake')
self.stubs.Set(compute_api.API, 'update', fake_update)
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
req.content_type = 'application/json'
body = {'server': {'name': 'server_test'}}
@@ -1299,7 +1299,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers/a/action')
+ req = fakes.HTTPRequest.blank('/fake/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1333,7 +1333,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers/a/action')
+ req = fakes.HTTPRequest.blank('/fake/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1367,7 +1367,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers/a/action')
+ req = fakes.HTTPRequest.blank('/fake/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1401,7 +1401,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers/a/action')
+ req = fakes.HTTPRequest.blank('/fake/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1429,7 +1429,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers/a/action')
+ req = fakes.HTTPRequest.blank('/fake/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1457,7 +1457,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers/a/action')
+ req = fakes.HTTPRequest.blank('/fake/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1486,7 +1486,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers/a/action')
+ req = fakes.HTTPRequest.blank('/fake/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1512,7 +1512,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers/a/action')
+ req = fakes.HTTPRequest.blank('/fake/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1546,7 +1546,7 @@ class ServersControllerTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers/a/action')
+ req = fakes.HTTPRequest.blank('/fake/servers/a/action')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1572,7 +1572,7 @@ class ServersControllerTest(test.TestCase):
},
],
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers/detail')
+ req = fakes.HTTPRequest.blank('/fake/servers/detail')
res_dict = self.controller.detail(req)
for i, s in enumerate(res_dict['servers']):
@@ -1600,7 +1600,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(db, 'instance_get_all_by_filters',
return_servers_with_host)
- req = fakes.HTTPRequest.blank('/v2/fake/servers/detail')
+ req = fakes.HTTPRequest.blank('/fake/servers/detail')
res_dict = self.controller.detail(req)
server_list = res_dict['servers']
@@ -1615,7 +1615,7 @@ class ServersControllerTest(test.TestCase):
def _delete_server_instance(self, uuid=FAKE_UUID):
fakes.stub_out_instance_quota(self.stubs, 0, 10)
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % uuid)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % uuid)
req.method = 'DELETE'
self.server_delete_called = False
@@ -1640,7 +1640,7 @@ class ServersControllerTest(test.TestCase):
def test_delete_server_instance_while_building(self):
fakes.stub_out_instance_quota(self.stubs, 0, 10)
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'DELETE'
self.server_delete_called = False
@@ -1654,7 +1654,7 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(self.server_delete_called, True)
def test_delete_server_instance_while_resize(self):
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'DELETE'
self.server_delete_called = False
@@ -1688,7 +1688,7 @@ class ServerStatusTest(test.TestCase):
fakes.fake_instance_get(vm_state=vm_state,
task_state=task_state))
- request = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ request = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
return self.controller.show(request, FAKE_UUID)
def test_active(self):
@@ -1714,7 +1714,7 @@ class ServerStatusTest(test.TestCase):
rule = {'compute:reboot':
common_policy.parse_rule('role:admin')}
common_policy.set_rules(common_policy.Rules(rule))
- req = fakes.HTTPRequest.blank('/v2/fake/servers/1234/action')
+ req = fakes.HTTPRequest.blank('/fake/servers/1234/action')
self.assertRaises(exception.PolicyNotAuthorized,
self.controller._action_reboot, req, '1234',
{'reboot': {'type': 'HARD'}})
@@ -1742,7 +1742,7 @@ class ServerStatusTest(test.TestCase):
rule = {'compute:confirm_resize':
common_policy.parse_rule('role:admin')}
common_policy.set_rules(common_policy.Rules(rule))
- req = fakes.HTTPRequest.blank('/v2/fake/servers/1234/action')
+ req = fakes.HTTPRequest.blank('/fake/servers/1234/action')
self.assertRaises(exception.PolicyNotAuthorized,
self.controller._action_confirm_resize, req, '1234', {})
@@ -1764,7 +1764,7 @@ class ServerStatusTest(test.TestCase):
rule = {'compute:revert_resize':
common_policy.parse_rule('role:admin')}
common_policy.set_rules(common_policy.Rules(rule))
- req = fakes.HTTPRequest.blank('/v2/fake/servers/1234/action')
+ req = fakes.HTTPRequest.blank('/fake/servers/1234/action')
self.assertRaises(exception.PolicyNotAuthorized,
self.controller._action_revert_resize, req, '1234', {})
@@ -1900,7 +1900,7 @@ class ServersControllerCreateTest(test.TestCase):
name='server_test', imageRef=image_uuid, flavorRef=2,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1921,7 +1921,7 @@ class ServersControllerCreateTest(test.TestCase):
'flavorRef': flavor_ref,
}
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1942,7 +1942,7 @@ class ServersControllerCreateTest(test.TestCase):
'networks': {'uuid': '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'},
}
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -1960,7 +1960,7 @@ class ServersControllerCreateTest(test.TestCase):
self.addCleanup(image_service.update, context, image_uuid,
{'status': 'active'})
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
body = dict(server=dict(
name='server_test', imageRef=image_uuid, flavorRef=2,
@@ -1990,7 +1990,7 @@ class ServersControllerCreateTest(test.TestCase):
self.addCleanup(image_service.update, context, image_uuid,
{'size': orig_size})
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
body = dict(server=dict(name='server_test',
imageRef=image_uuid,
@@ -2016,7 +2016,7 @@ class ServersControllerCreateTest(test.TestCase):
'flavorRef': flavor_ref,
}
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2038,7 +2038,7 @@ class ServersControllerCreateTest(test.TestCase):
'flavorRef': flavor_ref,
}
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2060,7 +2060,7 @@ class ServersControllerCreateTest(test.TestCase):
'flavorRef': flavor_ref,
}
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2082,7 +2082,7 @@ class ServersControllerCreateTest(test.TestCase):
'flavorRef': flavor_ref,
}
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2110,7 +2110,7 @@ class ServersControllerCreateTest(test.TestCase):
}
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2139,7 +2139,7 @@ class ServersControllerCreateTest(test.TestCase):
}
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2168,7 +2168,7 @@ class ServersControllerCreateTest(test.TestCase):
}
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2244,7 +2244,7 @@ class ServersControllerCreateTest(test.TestCase):
}
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2267,7 +2267,7 @@ class ServersControllerCreateTest(test.TestCase):
}
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2286,7 +2286,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2307,7 +2307,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2325,7 +2325,7 @@ class ServersControllerCreateTest(test.TestCase):
server.pop('imageRef', None)
server.update(params)
body = dict(server=server)
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2805,7 +2805,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2845,7 +2845,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2882,7 +2882,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2916,7 +2916,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -2947,7 +2947,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3009,7 +3009,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3044,7 +3044,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3072,7 +3072,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3096,7 +3096,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3120,7 +3120,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3144,7 +3144,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3158,7 +3158,7 @@ class ServersControllerCreateTest(test.TestCase):
body = dict(server=dict(
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
key_name='nonexistentkey'))
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3172,7 +3172,7 @@ class ServersControllerCreateTest(test.TestCase):
body = dict(server=dict(
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
key_name='key'))
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3188,7 +3188,7 @@ class ServersControllerCreateTest(test.TestCase):
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3203,7 +3203,7 @@ class ServersControllerCreateTest(test.TestCase):
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3218,7 +3218,7 @@ class ServersControllerCreateTest(test.TestCase):
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3244,34 +3244,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
- req.method = 'POST'
- req.body = jsonutils.dumps(body)
- req.headers["content-type"] = "application/json"
- res = self.controller.create(req, body).obj
-
- server = res['server']
- self.assertEqual(FAKE_UUID, server['id'])
-
- def test_create_instance_with_config_drive_as_id(self):
- self.ext_mgr.extensions = {'os-config-drive': 'fake'}
- image_href = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
- flavor_ref = 'http://localhost/v2/fake/flavors/3'
- body = {
- 'server': {
- 'name': 'config_drive_test',
- 'imageRef': image_href,
- 'flavorRef': flavor_ref,
- 'metadata': {
- 'hello': 'world',
- 'open': 'stack',
- },
- 'personality': {},
- 'config_drive': image_href,
- },
- }
-
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3281,6 +3254,7 @@ class ServersControllerCreateTest(test.TestCase):
self.assertEqual(FAKE_UUID, server['id'])
def test_create_instance_with_bad_config_drive(self):
+ # Test with an image href as config drive value.
self.ext_mgr.extensions = {'os-config-drive': 'fake'}
image_href = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
flavor_ref = 'http://localhost/v2/fake/flavors/3'
@@ -3294,15 +3268,14 @@ class ServersControllerCreateTest(test.TestCase):
'open': 'stack',
},
'personality': {},
- 'config_drive': 'asdf',
+ 'config_drive': image_href,
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
-
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, req, body)
@@ -3323,7 +3296,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3351,7 +3324,7 @@ class ServersControllerCreateTest(test.TestCase):
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3370,7 +3343,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3390,7 +3363,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = "application/json"
@@ -3411,7 +3384,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = "application/json"
@@ -3432,7 +3405,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = "application/json"
@@ -3470,7 +3443,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -3501,7 +3474,7 @@ class ServersControllerCreateTest(test.TestCase):
},
}
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
@@ -3517,7 +3490,7 @@ class ServersControllerCreateTest(test.TestCase):
name='server_test', imageRef=image_uuid, flavorRef=3,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
@@ -4285,7 +4258,7 @@ class ServersViewBuilderTest(test.TestCase):
self.uuid = self.instance['uuid']
self.view_builder = views.servers.ViewBuilder()
- self.request = fakes.HTTPRequest.blank("/v2")
+ self.request = fakes.HTTPRequest.blank("/v2/fake")
def test_get_flavor_valid_flavor(self):
flavor_bookmark = "http://localhost/fake/flavors/1"
@@ -5808,7 +5781,7 @@ class ServersUnprocessableEntityTestCase(test.TestCase):
self.controller = servers.Controller(self.ext_mgr)
def _unprocessable_server_create(self, body):
- req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req = fakes.HTTPRequest.blank('/fake/servers')
req.method = 'POST'
self.assertRaises(webob.exc.HTTPUnprocessableEntity,
@@ -5826,7 +5799,7 @@ class ServersUnprocessableEntityTestCase(test.TestCase):
self._unprocessable_server_create(body=body)
def _unprocessable_server_update(self, body):
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
req.method = 'PUT'
self.assertRaises(webob.exc.HTTPUnprocessableEntity,
diff --git a/nova/tests/api/openstack/compute/test_v3_extensions.py b/nova/tests/api/openstack/compute/test_v3_extensions.py
index 97429ca45..ec472f38a 100644
--- a/nova/tests/api/openstack/compute/test_v3_extensions.py
+++ b/nova/tests/api/openstack/compute/test_v3_extensions.py
@@ -16,10 +16,12 @@
from oslo.config import cfg
import stevedore
+import webob.exc
from nova.api import openstack
from nova.api.openstack import compute
from nova.api.openstack.compute import plugins
+from nova.api.openstack import extensions
from nova import exception
from nova import test
@@ -139,3 +141,38 @@ class ExtensionLoadingTestCase(test.TestCase):
self.stubs.Set(plugins, 'LoadedExtensionInfo',
fake_loaded_extension_info)
self.assertRaises(exception.CoreAPIMissing, compute.APIRouterV3)
+
+ def test_extensions_expected_error(self):
+ @extensions.expected_errors(404)
+ def fake_func():
+ raise webob.exc.HTTPNotFound()
+
+ self.assertRaises(webob.exc.HTTPNotFound, fake_func)
+
+ def test_extensions_expected_error_from_list(self):
+ @extensions.expected_errors((404, 403))
+ def fake_func():
+ raise webob.exc.HTTPNotFound()
+
+ self.assertRaises(webob.exc.HTTPNotFound, fake_func)
+
+ def test_extensions_unexpected_error(self):
+ @extensions.expected_errors(404)
+ def fake_func():
+ raise webob.exc.HTTPConflict()
+
+ self.assertRaises(webob.exc.HTTPInternalServerError, fake_func)
+
+ def test_extensions_unexpected_error_from_list(self):
+ @extensions.expected_errors((404, 413))
+ def fake_func():
+ raise webob.exc.HTTPConflict()
+
+ self.assertRaises(webob.exc.HTTPInternalServerError, fake_func)
+
+ def test_extensions_unexpected_policy_not_authorized_error(self):
+ @extensions.expected_errors(404)
+ def fake_func():
+ raise exception.PolicyNotAuthorized(action="foo")
+
+ self.assertRaises(exception.PolicyNotAuthorized, fake_func)
diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py
index f05561ff2..d0239885d 100644
--- a/nova/tests/api/openstack/fakes.py
+++ b/nova/tests/api/openstack/fakes.py
@@ -419,7 +419,7 @@ def get_fake_uuid(token=0):
def fake_instance_get(**kwargs):
- def _return_server(context, uuid):
+ def _return_server(context, uuid, columns_to_join=None):
return stub_instance(1, **kwargs)
return _return_server
@@ -435,6 +435,8 @@ def fake_instance_get_all_by_filters(num_servers=5, **kwargs):
if "limit" in kwargs:
limit = kwargs["limit"]
+ if 'columns_to_join' in kwargs:
+ kwargs.pop('columns_to_join')
for i in xrange(num_servers):
uuid = get_fake_uuid(i)
server = stub_instance(id=i + 1, uuid=uuid,
@@ -462,7 +464,8 @@ def stub_instance(id, user_id=None, project_id=None, host=None,
security_groups=None, root_device_name=None,
limit=None, marker=None,
launched_at=datetime.datetime.utcnow(),
- terminated_at=datetime.datetime.utcnow()):
+ terminated_at=datetime.datetime.utcnow(),
+ availability_zone=''):
if user_id is None:
user_id = 'fake_user'
@@ -488,7 +491,10 @@ def stub_instance(id, user_id=None, project_id=None, host=None,
key_data = ''
if security_groups is None:
- security_groups = [{"id": 1, "name": "test"}]
+ security_groups = [{"id": 1, "name": "test", "description": "Foo:",
+ "project_id": "project", "user_id": "user",
+ "created_at": None, "updated_at": None,
+ "deleted_at": None, "deleted": False}]
# ReservationID isn't sent back, hack it in there.
server_name = name or "server%s" % id
@@ -501,6 +507,8 @@ def stub_instance(id, user_id=None, project_id=None, host=None,
"id": int(id),
"created_at": datetime.datetime(2010, 10, 10, 12, 0, 0),
"updated_at": datetime.datetime(2010, 11, 11, 11, 0, 0),
+ "deleted_at": datetime.datetime(2010, 12, 12, 10, 0, 0),
+ "deleted": None,
"user_id": user_id,
"project_id": project_id,
"image_ref": image_ref,
@@ -528,7 +536,7 @@ def stub_instance(id, user_id=None, project_id=None, host=None,
"scheduled_at": timeutils.utcnow(),
"launched_at": launched_at,
"terminated_at": terminated_at,
- "availability_zone": "",
+ "availability_zone": availability_zone,
"display_name": display_name or server_name,
"display_description": "",
"locked": False,
@@ -553,6 +561,7 @@ def stub_instance(id, user_id=None, project_id=None, host=None,
"os_type": ""}
instance.update(info_cache)
+ instance['info_cache']['instance_uuid'] = instance['uuid']
return instance
diff --git a/nova/tests/cells/test_cells_manager.py b/nova/tests/cells/test_cells_manager.py
index 4e35cd818..89a60cb35 100644
--- a/nova/tests/cells/test_cells_manager.py
+++ b/nova/tests/cells/test_cells_manager.py
@@ -548,3 +548,27 @@ class CellsManagerClassTestCase(test.TestCase):
instance_uuid=instance_uuid, console_port=console_port,
console_type=console_type)
self.assertEqual('fake-response', response)
+
+ def test_bdm_update_or_create_at_top(self):
+ self.mox.StubOutWithMock(self.msg_runner,
+ 'bdm_update_or_create_at_top')
+ self.msg_runner.bdm_update_or_create_at_top(self.ctxt,
+ 'fake-bdm',
+ create='foo')
+ self.mox.ReplayAll()
+ self.cells_manager.bdm_update_or_create_at_top(self.ctxt,
+ 'fake-bdm',
+ create='foo')
+
+ def test_bdm_destroy_at_top(self):
+ self.mox.StubOutWithMock(self.msg_runner, 'bdm_destroy_at_top')
+ self.msg_runner.bdm_destroy_at_top(self.ctxt,
+ 'fake_instance_uuid',
+ device_name='fake_device_name',
+ volume_id='fake_volume_id')
+
+ self.mox.ReplayAll()
+ self.cells_manager.bdm_destroy_at_top(self.ctxt,
+ 'fake_instance_uuid',
+ device_name='fake_device_name',
+ volume_id='fake_volume_id')
diff --git a/nova/tests/cells/test_cells_messaging.py b/nova/tests/cells/test_cells_messaging.py
index d4d9b052e..734fecf0e 100644
--- a/nova/tests/cells/test_cells_messaging.py
+++ b/nova/tests/cells/test_cells_messaging.py
@@ -23,6 +23,7 @@ from nova.compute import vm_states
from nova import context
from nova import db
from nova import exception
+from nova.objects import instance as instance_obj
from nova.openstack.common import rpc
from nova.openstack.common import timeutils
from nova import test
@@ -641,6 +642,60 @@ class CellsTargetedMethodsTestCase(test.TestCase):
result = response.value_or_raise()
self.assertEqual('fake_result', result)
+ def test_run_compute_api_method_expects_obj(self):
+ instance_uuid = 'fake_instance_uuid'
+ method_info = {'method': 'start',
+ 'method_args': (instance_uuid, 2, 3),
+ 'method_kwargs': {'arg1': 'val1', 'arg2': 'val2'}}
+ self.mox.StubOutWithMock(self.tgt_compute_api, 'start')
+ self.mox.StubOutWithMock(self.tgt_db_inst, 'instance_get_by_uuid')
+
+ self.tgt_db_inst.instance_get_by_uuid(self.ctxt,
+ instance_uuid).AndReturn('fake_instance')
+
+ def get_instance_mock():
+ # NOTE(comstud): This block of code simulates the following
+ # mox code:
+ #
+ # self.mox.StubOutWithMock(instance_obj, 'Instance',
+ # use_mock_anything=True)
+ # self.mox.StubOutWithMock(instance_obj.Instance,
+ # '_from_db_object')
+ # instance_mock = self.mox.CreateMock(instance_obj.Instance)
+ # instance_obj.Instance().AndReturn(instance_mock)
+ #
+ # Unfortunately, the above code fails on py27 do to some
+ # issue with the Mock object do to similar issue as this:
+ # https://code.google.com/p/pymox/issues/detail?id=35
+ #
+ class FakeInstance(object):
+ def _from_db_object(obj, db_obj):
+ pass
+
+ instance_mock = FakeInstance()
+
+ def fake_instance():
+ return instance_mock
+
+ self.stubs.Set(instance_obj, 'Instance', fake_instance)
+ self.mox.StubOutWithMock(instance_mock, '_from_db_object')
+ return instance_mock
+
+ instance = get_instance_mock()
+ instance._from_db_object(
+ instance, 'fake_instance').AndReturn(instance)
+ self.tgt_compute_api.start(self.ctxt, instance, 2, 3,
+ arg1='val1', arg2='val2').AndReturn('fake_result')
+ self.mox.ReplayAll()
+
+ response = self.src_msg_runner.run_compute_api_method(
+ self.ctxt,
+ self.tgt_cell_name,
+ method_info,
+ True)
+ result = response.value_or_raise()
+ self.assertEqual('fake_result', result)
+
def test_run_compute_api_method_unknown_instance(self):
# Unknown instance should send a broadcast up that instance
# is gone.
@@ -1426,3 +1481,173 @@ class CellsBroadcastMethodsTestCase(test.TestCase):
self.mox.ReplayAll()
self.src_msg_runner.consoleauth_delete_tokens(self.ctxt, fake_uuid)
+
+ def test_bdm_update_or_create_with_none_create(self):
+ fake_bdm = {'id': 'fake_id',
+ 'volume_id': 'fake_volume_id'}
+ expected_bdm = fake_bdm.copy()
+ expected_bdm.pop('id')
+
+ # Shouldn't be called for these 2 cells
+ self.mox.StubOutWithMock(self.src_db_inst,
+ 'block_device_mapping_update_or_create')
+ self.mox.StubOutWithMock(self.mid_db_inst,
+ 'block_device_mapping_update_or_create')
+
+ self.mox.StubOutWithMock(self.tgt_db_inst,
+ 'block_device_mapping_update_or_create')
+ self.tgt_db_inst.block_device_mapping_update_or_create(
+ self.ctxt, expected_bdm, legacy=False)
+
+ self.mox.ReplayAll()
+
+ self.src_msg_runner.bdm_update_or_create_at_top(self.ctxt,
+ fake_bdm,
+ create=None)
+
+ def test_bdm_update_or_create_with_true_create(self):
+ fake_bdm = {'id': 'fake_id',
+ 'volume_id': 'fake_volume_id'}
+ expected_bdm = fake_bdm.copy()
+ expected_bdm.pop('id')
+
+ # Shouldn't be called for these 2 cells
+ self.mox.StubOutWithMock(self.src_db_inst,
+ 'block_device_mapping_create')
+ self.mox.StubOutWithMock(self.mid_db_inst,
+ 'block_device_mapping_create')
+
+ self.mox.StubOutWithMock(self.tgt_db_inst,
+ 'block_device_mapping_create')
+ self.tgt_db_inst.block_device_mapping_create(
+ self.ctxt, fake_bdm, legacy=False)
+
+ self.mox.ReplayAll()
+
+ self.src_msg_runner.bdm_update_or_create_at_top(self.ctxt,
+ fake_bdm,
+ create=True)
+
+ def test_bdm_update_or_create_with_false_create_vol_id(self):
+ fake_bdm = {'id': 'fake_id',
+ 'instance_uuid': 'fake_instance_uuid',
+ 'device_name': 'fake_device_name',
+ 'volume_id': 'fake_volume_id'}
+ expected_bdm = fake_bdm.copy()
+ expected_bdm.pop('id')
+
+ fake_inst_bdms = [{'id': 1,
+ 'volume_id': 'not-a-match',
+ 'device_name': 'not-a-match'},
+ {'id': 2,
+ 'volume_id': 'fake_volume_id',
+ 'device_name': 'not-a-match'},
+ {'id': 3,
+ 'volume_id': 'not-a-match',
+ 'device_name': 'not-a-match'}]
+
+ # Shouldn't be called for these 2 cells
+ self.mox.StubOutWithMock(self.src_db_inst,
+ 'block_device_mapping_update')
+ self.mox.StubOutWithMock(self.mid_db_inst,
+ 'block_device_mapping_update')
+
+ self.mox.StubOutWithMock(self.tgt_db_inst,
+ 'block_device_mapping_get_all_by_instance')
+ self.mox.StubOutWithMock(self.tgt_db_inst,
+ 'block_device_mapping_update')
+
+ self.tgt_db_inst.block_device_mapping_get_all_by_instance(
+ self.ctxt, 'fake_instance_uuid').AndReturn(
+ fake_inst_bdms)
+ # Should try to update ID 2.
+ self.tgt_db_inst.block_device_mapping_update(
+ self.ctxt, 2, expected_bdm, legacy=False)
+
+ self.mox.ReplayAll()
+
+ self.src_msg_runner.bdm_update_or_create_at_top(self.ctxt,
+ fake_bdm,
+ create=False)
+
+ def test_bdm_update_or_create_with_false_create_dev_name(self):
+ fake_bdm = {'id': 'fake_id',
+ 'instance_uuid': 'fake_instance_uuid',
+ 'device_name': 'fake_device_name',
+ 'volume_id': 'fake_volume_id'}
+ expected_bdm = fake_bdm.copy()
+ expected_bdm.pop('id')
+
+ fake_inst_bdms = [{'id': 1,
+ 'volume_id': 'not-a-match',
+ 'device_name': 'not-a-match'},
+ {'id': 2,
+ 'volume_id': 'not-a-match',
+ 'device_name': 'fake_device_name'},
+ {'id': 3,
+ 'volume_id': 'not-a-match',
+ 'device_name': 'not-a-match'}]
+
+ # Shouldn't be called for these 2 cells
+ self.mox.StubOutWithMock(self.src_db_inst,
+ 'block_device_mapping_update')
+ self.mox.StubOutWithMock(self.mid_db_inst,
+ 'block_device_mapping_update')
+
+ self.mox.StubOutWithMock(self.tgt_db_inst,
+ 'block_device_mapping_get_all_by_instance')
+ self.mox.StubOutWithMock(self.tgt_db_inst,
+ 'block_device_mapping_update')
+
+ self.tgt_db_inst.block_device_mapping_get_all_by_instance(
+ self.ctxt, 'fake_instance_uuid').AndReturn(
+ fake_inst_bdms)
+ # Should try to update ID 2.
+ self.tgt_db_inst.block_device_mapping_update(
+ self.ctxt, 2, expected_bdm, legacy=False)
+
+ self.mox.ReplayAll()
+
+ self.src_msg_runner.bdm_update_or_create_at_top(self.ctxt,
+ fake_bdm,
+ create=False)
+
+ def test_bdm_destroy_by_volume(self):
+ fake_instance_uuid = 'fake-instance-uuid'
+ fake_volume_id = 'fake-volume-name'
+
+ # Shouldn't be called for these 2 cells
+ self.mox.StubOutWithMock(self.src_db_inst,
+ 'block_device_mapping_destroy_by_instance_and_volume')
+ self.mox.StubOutWithMock(self.mid_db_inst,
+ 'block_device_mapping_destroy_by_instance_and_volume')
+
+ self.mox.StubOutWithMock(self.tgt_db_inst,
+ 'block_device_mapping_destroy_by_instance_and_volume')
+ self.tgt_db_inst.block_device_mapping_destroy_by_instance_and_volume(
+ self.ctxt, fake_instance_uuid, fake_volume_id)
+
+ self.mox.ReplayAll()
+
+ self.src_msg_runner.bdm_destroy_at_top(self.ctxt, fake_instance_uuid,
+ volume_id=fake_volume_id)
+
+ def test_bdm_destroy_by_device(self):
+ fake_instance_uuid = 'fake-instance-uuid'
+ fake_device_name = 'fake-device-name'
+
+ # Shouldn't be called for these 2 cells
+ self.mox.StubOutWithMock(self.src_db_inst,
+ 'block_device_mapping_destroy_by_instance_and_device')
+ self.mox.StubOutWithMock(self.mid_db_inst,
+ 'block_device_mapping_destroy_by_instance_and_device')
+
+ self.mox.StubOutWithMock(self.tgt_db_inst,
+ 'block_device_mapping_destroy_by_instance_and_device')
+ self.tgt_db_inst.block_device_mapping_destroy_by_instance_and_device(
+ self.ctxt, fake_instance_uuid, fake_device_name)
+
+ self.mox.ReplayAll()
+
+ self.src_msg_runner.bdm_destroy_at_top(self.ctxt, fake_instance_uuid,
+ device_name=fake_device_name)
diff --git a/nova/tests/cells/test_cells_rpcapi.py b/nova/tests/cells/test_cells_rpcapi.py
index 4d58bdb9e..6eeff1730 100644
--- a/nova/tests/cells/test_cells_rpcapi.py
+++ b/nova/tests/cells/test_cells_rpcapi.py
@@ -425,3 +425,29 @@ class CellsAPITestCase(test.TestCase):
self._check_result(call_info, 'validate_console_port',
expected_args, version='1.6')
self.assertEqual(result, 'fake_response')
+
+ def test_bdm_update_or_create_at_top(self):
+ fake_bdm = {'id': 2, 'other': 'meow'}
+
+ call_info = self._stub_rpc_method('cast', None)
+
+ self.cells_rpcapi.bdm_update_or_create_at_top(
+ self.fake_context, fake_bdm, create='fake-create')
+
+ expected_args = {'bdm': fake_bdm, 'create': 'fake-create'}
+ self._check_result(call_info, 'bdm_update_or_create_at_top',
+ expected_args, version='1.10')
+
+ def test_bdm_destroy_at_top(self):
+ call_info = self._stub_rpc_method('cast', None)
+
+ self.cells_rpcapi.bdm_destroy_at_top(self.fake_context,
+ 'fake-uuid',
+ device_name='fake-device',
+ volume_id='fake-vol')
+
+ expected_args = {'instance_uuid': 'fake-uuid',
+ 'device_name': 'fake-device',
+ 'volume_id': 'fake-vol'}
+ self._check_result(call_info, 'bdm_destroy_at_top',
+ expected_args, version='1.10')
diff --git a/nova/tests/cells/test_cells_scheduler.py b/nova/tests/cells/test_cells_scheduler.py
index 9cd637cdf..46be492cc 100644
--- a/nova/tests/cells/test_cells_scheduler.py
+++ b/nova/tests/cells/test_cells_scheduler.py
@@ -84,10 +84,9 @@ class CellsSchedulerTestCase(test.TestCase):
'block_device_mapping': 'fake_bdm'}
self.build_inst_kwargs = {
'instances': self.instances,
- 'instance_type': 'fake_type',
'image': 'fake_image',
- 'filter_properties': {},
- 'security_group': 'fake_sec_groups',
+ 'filter_properties': {'instance_type': 'fake_type'},
+ 'security_groups': 'fake_sec_groups',
'block_device_mapping': 'fake_bdm'}
def test_create_instances_here(self):
@@ -178,7 +177,7 @@ class CellsSchedulerTestCase(test.TestCase):
call_info['target_cell'] = target_cell
call_info['build_inst_kwargs'] = build_inst_kwargs
- def fake_build_request_spec(image, instances):
+ def fake_build_request_spec(ctxt, image, instances):
request_spec = {
'instance_uuids': [inst['uuid'] for inst in instances],
'image': image}
@@ -264,7 +263,7 @@ class CellsSchedulerTestCase(test.TestCase):
def fake_rpc_build_instances(ctxt, **build_inst_kwargs):
call_info['build_inst_kwargs'] = build_inst_kwargs
- def fake_build_request_spec(image, instances):
+ def fake_build_request_spec(ctxt, image, instances):
request_spec = {
'instance_uuids': [inst['uuid'] for inst in instances],
'image': image}
@@ -284,10 +283,11 @@ class CellsSchedulerTestCase(test.TestCase):
self.assertEqual(self.instance_uuids, call_info['instance_uuids'])
self.assertEqual(self.build_inst_kwargs['instances'][0],
call_info['instance_properties'])
- self.assertEqual(self.build_inst_kwargs['instance_type'],
- call_info['instance_type'])
+ self.assertEqual(
+ self.build_inst_kwargs['filter_properties']['instance_type'],
+ call_info['instance_type'])
self.assertEqual(self.build_inst_kwargs['image'], call_info['image'])
- self.assertEqual(self.build_inst_kwargs['security_group'],
+ self.assertEqual(self.build_inst_kwargs['security_groups'],
call_info['security_groups'])
self.assertEqual(self.build_inst_kwargs['block_device_mapping'],
call_info['block_device_mapping'])
@@ -341,7 +341,7 @@ class CellsSchedulerTestCase(test.TestCase):
self.assertEqual(vm_states.ERROR, values['vm_state'])
call_info['errored_uuids'].append(instance_uuid)
- def fake_build_request_spec(image, instances):
+ def fake_build_request_spec(ctxt, image, instances):
request_spec = {
'instance_uuids': [inst['uuid'] for inst in instances],
'image': image}
@@ -385,7 +385,7 @@ class CellsSchedulerTestCase(test.TestCase):
self.assertEqual(vm_states.ERROR, instance['vm_state'])
call_info['errored_uuids2'].append(instance['uuid'])
- def fake_build_request_spec(image, instances):
+ def fake_build_request_spec(ctxt, image, instances):
request_spec = {
'instance_uuids': [inst['uuid'] for inst in instances],
'image': image}
diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py
index 8c6fce3a5..4fbf805f1 100644
--- a/nova/tests/compute/test_compute.py
+++ b/nova/tests/compute/test_compute.py
@@ -73,6 +73,11 @@ from nova.tests import fake_network_cache_model
from nova.tests.image import fake as fake_image
from nova.tests import matchers
from nova import utils
+from nova.virt.event import EVENT_LIFECYCLE_PAUSED
+from nova.virt.event import EVENT_LIFECYCLE_RESUMED
+from nova.virt.event import EVENT_LIFECYCLE_STARTED
+from nova.virt.event import EVENT_LIFECYCLE_STOPPED
+from nova.virt.event import LifecycleEvent
from nova.virt import fake
from nova.volume import cinder
@@ -259,6 +264,10 @@ class BaseTestCase(test.TestCase):
inst['os_type'] = 'Linux'
inst['system_metadata'] = make_fake_sys_meta()
inst['locked'] = False
+ inst['created_at'] = timeutils.utcnow()
+ inst['updated_at'] = timeutils.utcnow()
+ inst['launched_at'] = timeutils.utcnow()
+ inst['security_groups'] = []
inst.update(params)
_create_service_entries(self.context.elevated(),
{'fake_zone': [inst['host']]})
@@ -272,7 +281,10 @@ class BaseTestCase(test.TestCase):
def _fake_db_create(_ctxt, inst):
for k, v in inst.items():
- setattr(instance, k, v)
+ if k == 'security_groups':
+ setattr(instance, k, v or None)
+ else:
+ setattr(instance, k, v)
return instance
self.stubs.Set(db, 'instance_create', _fake_db_create)
@@ -1076,6 +1088,103 @@ class ComputeTestCase(BaseTestCase):
self._assert_state({'vm_state': vm_states.ERROR,
'task_state': None})
+ def test_allocate_network_succeeds_after_retries(self):
+ # Undo setUp() stubs as this is a true unit test
+ self.stubs.UnsetAll()
+ self.flags(network_allocate_retries=8)
+
+ nwapi = self.compute.network_api
+ self.mox.StubOutWithMock(nwapi, 'allocate_for_instance')
+ self.mox.StubOutWithMock(time, 'sleep')
+
+ instance = {}
+ is_vpn = 'fake-is-vpn'
+ req_networks = 'fake-req-networks'
+ macs = 'fake-macs'
+ sec_groups = 'fake-sec-groups'
+ final_result = 'meow'
+
+ expected_sleep_times = [1, 2, 4, 8, 16, 30, 30, 30]
+
+ for sleep_time in expected_sleep_times:
+ nwapi.allocate_for_instance(
+ self.context, instance, vpn=is_vpn,
+ requested_networks=req_networks, macs=macs,
+ conductor_api=self.compute.conductor_api,
+ security_groups=sec_groups).AndRaise(
+ test.TestingException())
+ time.sleep(sleep_time)
+
+ nwapi.allocate_for_instance(
+ self.context, instance, vpn=is_vpn,
+ requested_networks=req_networks, macs=macs,
+ conductor_api=self.compute.conductor_api,
+ security_groups=sec_groups).AndReturn(final_result)
+
+ self.mox.ReplayAll()
+
+ res = self.compute._allocate_network_async(self.context, instance,
+ req_networks,
+ macs,
+ sec_groups,
+ is_vpn)
+ self.assertEqual(final_result, res)
+
+ def test_allocate_network_fails(self):
+ # Undo setUp() stubs as this is a true unit test
+ self.stubs.UnsetAll()
+ self.flags(network_allocate_retries=0)
+
+ nwapi = self.compute.network_api
+ self.mox.StubOutWithMock(nwapi, 'allocate_for_instance')
+
+ instance = {}
+ is_vpn = 'fake-is-vpn'
+ req_networks = 'fake-req-networks'
+ macs = 'fake-macs'
+ sec_groups = 'fake-sec-groups'
+
+ nwapi.allocate_for_instance(
+ self.context, instance, vpn=is_vpn,
+ requested_networks=req_networks, macs=macs,
+ conductor_api=self.compute.conductor_api,
+ security_groups=sec_groups).AndRaise(test.TestingException())
+
+ self.mox.ReplayAll()
+
+ self.assertRaises(test.TestingException,
+ self.compute._allocate_network_async,
+ self.context, instance, req_networks, macs,
+ sec_groups, is_vpn)
+
+ def test_allocate_network_neg_conf_value_treated_as_zero(self):
+ # Undo setUp() stubs as this is a true unit test
+ self.stubs.UnsetAll()
+ self.flags(network_allocate_retries=-1)
+
+ nwapi = self.compute.network_api
+ self.mox.StubOutWithMock(nwapi, 'allocate_for_instance')
+
+ instance = {}
+ is_vpn = 'fake-is-vpn'
+ req_networks = 'fake-req-networks'
+ macs = 'fake-macs'
+ sec_groups = 'fake-sec-groups'
+
+ # Only attempted once.
+ nwapi.allocate_for_instance(
+ self.context, instance, vpn=is_vpn,
+ requested_networks=req_networks, macs=macs,
+ conductor_api=self.compute.conductor_api,
+ security_groups=sec_groups).AndRaise(test.TestingException())
+
+ self.mox.ReplayAll()
+
+ self.assertRaises(test.TestingException,
+ self.compute._allocate_network_async,
+ self.context, instance, req_networks, macs,
+ sec_groups, is_vpn)
+
def test_run_instance_dealloc_network_instance_not_found(self):
"""spawn network deallocate test.
@@ -1214,6 +1323,30 @@ class ComputeTestCase(BaseTestCase):
LOG.info(_("After terminating instances: %s"), instances)
self.assertEqual(len(instances), 0)
+ def test_terminate_no_fixed_ips(self):
+ # This is as reported in LP bug 1192893
+ instance = jsonutils.to_primitive(self._create_fake_instance())
+
+ self.compute.run_instance(self.context, instance=instance)
+
+ instances = db.instance_get_all(self.context)
+ LOG.info(_("Running instances: %s"), instances)
+ self.assertEqual(len(instances), 1)
+
+ self.mox.StubOutWithMock(self.compute, '_get_instance_nw_info')
+ self.compute._get_instance_nw_info(
+ mox.IgnoreArg(),
+ mox.IgnoreArg()).AndRaise(
+ exception.NoMoreFixedIps()
+ )
+ self.mox.ReplayAll()
+
+ self.compute.terminate_instance(self.context, instance=instance)
+
+ instances = db.instance_get_all(self.context)
+ LOG.info(_("After terminating instances: %s"), instances)
+ self.assertEqual(len(instances), 0)
+
def test_terminate_failure_leaves_task_state(self):
"""Ensure that a failure in terminate_instance does not result
in the task state being reverted from DELETING (see LP 1046236).
@@ -1248,6 +1381,7 @@ class ComputeTestCase(BaseTestCase):
def test_run_terminate_timestamps(self):
# Make sure timestamps are set for launched and destroyed.
instance = jsonutils.to_primitive(self._create_fake_instance())
+ instance['launched_at'] = None
self.assertEqual(instance['launched_at'], None)
self.assertEqual(instance['deleted_at'], None)
launch = timeutils.utcnow()
@@ -1399,7 +1533,8 @@ class ComputeTestCase(BaseTestCase):
called = {'power_on': False}
- def fake_driver_power_on(self, instance):
+ def fake_driver_power_on(self, context, instance, network_info,
+ block_device_info):
called['power_on'] = True
self.stubs.Set(nova.virt.fake.FakeDriver, 'power_on',
@@ -2257,6 +2392,7 @@ class ComputeTestCase(BaseTestCase):
self.assertTrue('display_name' in payload)
self.assertTrue('created_at' in payload)
self.assertTrue('launched_at' in payload)
+ self.assertTrue('fixed_ips' in payload)
self.assertTrue(payload['launched_at'])
image_ref_url = glance.generate_image_url(FAKE_IMAGE_REF)
self.assertEquals(payload['image_ref_url'], image_ref_url)
@@ -4333,9 +4469,11 @@ class ComputeTestCase(BaseTestCase):
instance_map = {}
instances = []
for x in xrange(5):
- uuid = 'fake-uuid-%s' % x
- instance_map[uuid] = {'uuid': uuid, 'host': CONF.host}
- instances.append(instance_map[uuid])
+ inst_uuid = 'fake-uuid-%s' % x
+ instance_map[inst_uuid] = fake_instance.fake_db_instance(
+ uuid=inst_uuid, host=CONF.host, created_at=None)
+ # These won't be in our instance since they're not requested
+ instances.append(instance_map[inst_uuid])
call_info = {'get_all_by_host': 0, 'get_by_uuid': 0,
'get_nw_info': 0, 'expected_instance': None}
@@ -4345,7 +4483,7 @@ class ComputeTestCase(BaseTestCase):
self.assertEqual(columns_to_join, [])
return instances[:]
- def fake_instance_get_by_uuid(context, instance_uuid):
+ def fake_instance_get_by_uuid(context, instance_uuid, columns_to_join):
if instance_uuid not in instance_map:
raise exception.InstanceNotFound(instance_id=instance_uuid)
call_info['get_by_uuid'] += 1
@@ -4357,12 +4495,13 @@ class ComputeTestCase(BaseTestCase):
# and is ignored. However, the below increment of
# 'get_nw_info' won't happen, and you'll get an assert
# failure checking it below.
- self.assertEqual(call_info['expected_instance'], instance)
+ self.assertEqual(call_info['expected_instance']['uuid'],
+ instance['uuid'])
call_info['get_nw_info'] += 1
- self.stubs.Set(self.compute.conductor_api, 'instance_get_all_by_host',
+ self.stubs.Set(db, 'instance_get_all_by_host',
fake_instance_get_all_by_host)
- self.stubs.Set(self.compute.conductor_api, 'instance_get_by_uuid',
+ self.stubs.Set(db, 'instance_get_by_uuid',
fake_instance_get_by_uuid)
self.stubs.Set(self.compute, '_get_instance_nw_info',
fake_get_instance_nw_info)
@@ -4437,19 +4576,27 @@ class ComputeTestCase(BaseTestCase):
self.assertTrue(instance)
def test_poll_unconfirmed_resizes(self):
- instances = [{'uuid': 'fake_uuid1', 'vm_state': vm_states.RESIZED,
- 'task_state': None},
- {'uuid': 'noexist'},
- {'uuid': 'fake_uuid2', 'vm_state': vm_states.ERROR,
- 'task_state': None},
- {'uuid': 'fake_uuid3', 'vm_state': vm_states.ACTIVE,
- 'task_state': task_states.REBOOTING},
- {'uuid': 'fake_uuid4', 'vm_state': vm_states.RESIZED,
- 'task_state': None},
- {'uuid': 'fake_uuid5', 'vm_state': vm_states.ACTIVE,
- 'task_state': None},
- {'uuid': 'fake_uuid6', 'vm_state': vm_states.RESIZED,
- 'task_state': 'deleting'}]
+ instances = [
+ fake_instance.fake_db_instance(uuid='fake_uuid1',
+ vm_state=vm_states.RESIZED,
+ task_state=None),
+ fake_instance.fake_db_instance(uuid='noexist'),
+ fake_instance.fake_db_instance(uuid='fake_uuid2',
+ vm_state=vm_states.ERROR,
+ task_state=None),
+ fake_instance.fake_db_instance(uuid='fake_uuid3',
+ vm_state=vm_states.ACTIVE,
+ task_state=
+ task_states.REBOOTING),
+ fake_instance.fake_db_instance(uuid='fake_uuid4',
+ vm_state=vm_states.RESIZED,
+ task_state=None),
+ fake_instance.fake_db_instance(uuid='fake_uuid5',
+ vm_state=vm_states.ACTIVE,
+ task_state=None),
+ fake_instance.fake_db_instance(uuid='fake_uuid6',
+ vm_state=vm_states.RESIZED,
+ task_state='deleting')]
expected_migration_status = {'fake_uuid1': 'confirmed',
'noexist': 'error',
'fake_uuid2': 'error',
@@ -4811,7 +4958,8 @@ class ComputeTestCase(BaseTestCase):
inst = dict(fakes.stub_instance(1),
deleted_at=None, created_at=None, updated_at=None,
deleted=0, info_cache={'instance_uuid': 'fake-uuid',
- 'network_info': None})
+ 'network_info': None},
+ security_groups=None)
startup_instances = [inst, inst, inst]
def _do_mock_calls(defer_iptables_apply):
@@ -5269,6 +5417,38 @@ class ComputeTestCase(BaseTestCase):
self._test_sync_to_stop(power_state.RUNNING, vs, ps,
stop=False)
+ def _test_lifecycle_event(self, lifecycle_event, power_state):
+ instance = self._create_fake_instance()
+ uuid = instance['uuid']
+
+ self.mox.StubOutWithMock(self.compute, '_sync_instance_power_state')
+ if power_state != None:
+ self.compute._sync_instance_power_state(
+ mox.IgnoreArg(),
+ mox.ContainsKeyValue('uuid', uuid),
+ power_state)
+ self.mox.ReplayAll()
+ self.compute.handle_events(LifecycleEvent(uuid, lifecycle_event))
+ self.mox.VerifyAll()
+ self.mox.UnsetStubs()
+
+ def test_lifecycle_events(self):
+ self._test_lifecycle_event(EVENT_LIFECYCLE_STOPPED,
+ power_state.SHUTDOWN)
+ self._test_lifecycle_event(EVENT_LIFECYCLE_STARTED,
+ power_state.RUNNING)
+ self._test_lifecycle_event(EVENT_LIFECYCLE_PAUSED,
+ power_state.PAUSED)
+ self._test_lifecycle_event(EVENT_LIFECYCLE_RESUMED,
+ power_state.RUNNING)
+ self._test_lifecycle_event(-1, None)
+
+ def test_lifecycle_event_non_existent_instance(self):
+ # No error raised for non-existent instance because of inherent race
+ # between database updates and hypervisor events. See bug #1180501.
+ event = LifecycleEvent('does-not-exist', EVENT_LIFECYCLE_STOPPED)
+ self.compute.handle_events(event)
+
class ComputeAPITestCase(BaseTestCase):
@@ -5710,6 +5890,21 @@ class ComputeAPITestCase(BaseTestCase):
db.instance_destroy(self.context, instance['uuid'])
+ def test_delete_if_not_launched(self):
+ instance, instance_uuid = self._run_instance(params={
+ 'host': CONF.host})
+
+ db.instance_update(self.context, instance['uuid'],
+ {"vm_state": vm_states.ERROR,
+ "launched_at": None})
+
+ self.compute_api.delete(self.context, instance)
+
+ instance = db.instance_get_by_uuid(self.context, instance_uuid)
+ self.assertEqual(instance['task_state'], task_states.DELETING)
+
+ db.instance_destroy(self.context, instance['uuid'])
+
def test_delete_in_resizing(self):
def fake_quotas_reserve(context, expire=None, project_id=None,
**deltas):
@@ -5984,7 +6179,7 @@ class ComputeAPITestCase(BaseTestCase):
db.instance_destroy(self.context, instance['uuid'])
- def test_rebuild(self):
+ def _test_rebuild(self, vm_state):
instance = jsonutils.to_primitive(self._create_fake_instance())
instance_uuid = instance['uuid']
self.compute.run_instance(self.context, instance=instance)
@@ -6015,6 +6210,10 @@ class ComputeAPITestCase(BaseTestCase):
image_ref = instance["image_ref"] + '-new_image_ref'
password = "new_password"
+
+ db.instance_update(self.context, instance['uuid'],
+ {"vm_state": vm_state})
+
self.compute_api.rebuild(self.context, instance, image_ref, password)
self.assertEqual(info['image_ref'], image_ref)
@@ -6029,6 +6228,34 @@ class ComputeAPITestCase(BaseTestCase):
'preserved': 'preserve this!'})
db.instance_destroy(self.context, instance['uuid'])
+ def test_rebuild(self):
+ # Test we can rebuild an instance in the Error State
+ self._test_rebuild(vm_state=vm_states.ACTIVE)
+
+ def test_rebuild_in_error_state(self):
+ # Test we can rebuild an instance in the Error State
+ self._test_rebuild(vm_state=vm_states.ERROR)
+
+ def test_rebuild_in_error_not_launched(self):
+ instance = jsonutils.to_primitive(
+ self._create_fake_instance(params={'image_ref': ''}))
+ instance_uuid = instance['uuid']
+ self.stubs.Set(fake_image._FakeImageService, 'show', self.fake_show)
+ self.compute.run_instance(self.context, instance=instance)
+
+ db.instance_update(self.context, instance['uuid'],
+ {"vm_state": vm_states.ERROR,
+ "launched_at": None})
+
+ instance = db.instance_get_by_uuid(self.context, instance['uuid'])
+
+ self.assertRaises(exception.InstanceInvalidState,
+ self.compute_api.rebuild,
+ self.context,
+ instance,
+ instance['image_ref'],
+ "new password")
+
def test_rebuild_no_image(self):
instance = jsonutils.to_primitive(
self._create_fake_instance(params={'image_ref': ''}))
@@ -6175,7 +6402,7 @@ class ComputeAPITestCase(BaseTestCase):
self.stubs.Set(nova.virt.fake.FakeDriver, 'legacy_nwinfo',
lambda x: False)
- def test_reboot_soft(self):
+ def _test_reboot_soft(self, vm_state):
# Ensure instance can be soft rebooted.
instance = jsonutils.to_primitive(self._create_fake_instance())
self.compute.run_instance(self.context, instance=instance)
@@ -6192,6 +6419,9 @@ class ComputeAPITestCase(BaseTestCase):
inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
self.assertEqual(inst_ref['task_state'], None)
+ db.instance_update(self.context, instance['uuid'],
+ {"vm_state": vm_state})
+
reboot_type = "SOFT"
self._stub_out_reboot(device_name)
self.compute_api.reboot(self.context, inst_ref, reboot_type)
@@ -6201,7 +6431,15 @@ class ComputeAPITestCase(BaseTestCase):
db.instance_destroy(self.context, inst_ref['uuid'])
- def test_reboot_hard(self):
+ def test_soft_reboot(self):
+ # Ensure instance can be rebooted while in error state.
+ self._test_reboot_soft(vm_state=vm_states.ACTIVE)
+
+ def test_soft_reboot_of_instance_in_error(self):
+ # Ensure instance can be rebooted while in error state.
+ self._test_reboot_soft(vm_state=vm_states.ERROR)
+
+ def test_reboot_hard(self, vm_state=vm_states.ACTIVE):
# Ensure instance can be hard rebooted.
instance = jsonutils.to_primitive(self._create_fake_instance())
self.compute.run_instance(self.context, instance=instance)
@@ -6218,6 +6456,9 @@ class ComputeAPITestCase(BaseTestCase):
inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
self.assertEqual(inst_ref['task_state'], None)
+ db.instance_update(self.context, instance['uuid'],
+ {"vm_state": vm_state})
+
reboot_type = "HARD"
self._stub_out_reboot(device_name)
self.compute_api.reboot(self.context, inst_ref, reboot_type)
@@ -6227,6 +6468,10 @@ class ComputeAPITestCase(BaseTestCase):
db.instance_destroy(self.context, inst_ref['uuid'])
+ def test_hard_reboot_of_instance_in_error(self):
+ # Ensure instance can be rebooted while in error state.
+ self.test_reboot_hard(vm_state=vm_states.ERROR)
+
def test_hard_reboot_of_soft_rebooting_instance(self):
# Ensure instance can be hard rebooted while soft rebooting.
instance = jsonutils.to_primitive(self._create_fake_instance())
@@ -6263,7 +6508,7 @@ class ComputeAPITestCase(BaseTestCase):
inst_ref,
reboot_type)
- def test_soft_reboot_of_rescued_instance(self):
+ def test_reboot_of_rescued_instance(self):
# Ensure instance can't be rebooted while in rescued state.
instance = jsonutils.to_primitive(self._create_fake_instance())
self.compute.run_instance(self.context, instance=instance)
@@ -6287,6 +6532,33 @@ class ComputeAPITestCase(BaseTestCase):
inst_ref,
'HARD')
+ def test_reboot_of_instance_in_error_not_launched(self):
+ # Ensure instance can be not rebooted while in error states
+ # if they have never been booted at least once.
+ instance = jsonutils.to_primitive(self._create_fake_instance())
+ self.compute.run_instance(self.context, instance=instance)
+
+ inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
+ self.assertEqual(inst_ref['task_state'], None)
+
+ db.instance_update(self.context, instance['uuid'],
+ {"vm_state": vm_states.ERROR,
+ "launched_at": None})
+
+ inst_ref = db.instance_get_by_uuid(self.context, inst_ref['uuid'])
+
+ self.assertRaises(exception.InstanceInvalidState,
+ self.compute_api.reboot,
+ self.context,
+ inst_ref,
+ 'SOFT')
+
+ self.assertRaises(exception.InstanceInvalidState,
+ self.compute_api.reboot,
+ self.context,
+ inst_ref,
+ 'HARD')
+
def test_hostname_create(self):
# Ensure instance hostname is set during creation.
inst_type = flavors.get_flavor_by_name('m1.tiny')
@@ -7726,7 +7998,8 @@ class ComputeAPITestCase(BaseTestCase):
self.assertRaises(exception.InvalidDevicePath,
self.compute_api.attach_volume,
self.context,
- {'locked': False, 'vm_state': vm_states.ACTIVE},
+ {'locked': False, 'vm_state': vm_states.ACTIVE,
+ 'launched_at': timeutils.utcnow()},
None,
'/invalid')
@@ -8033,6 +8306,7 @@ class ComputeAPITestCase(BaseTestCase):
# Ensure exception is raised while detaching an un-attached volume
instance = {'uuid': 'uuid1',
'locked': False,
+ 'launched_at': timeutils.utcnow(),
'vm_state': vm_states.ACTIVE}
volume = {'id': 1, 'attach_status': 'detached'}
@@ -8045,6 +8319,7 @@ class ComputeAPITestCase(BaseTestCase):
# instance doesn't match.
instance = {'uuid': 'uuid1',
'locked': False,
+ 'launched_at': timeutils.utcnow(),
'vm_state': vm_states.ACTIVE}
volume = {'id': 1, 'attach_status': 'in-use',
'instance_uuid': 'uuid2'}
@@ -8359,6 +8634,7 @@ class ComputeAPITestCase(BaseTestCase):
def test_fail_evacuate_from_non_existing_host(self):
inst = {}
inst['vm_state'] = vm_states.ACTIVE
+ inst['launched_at'] = timeutils.utcnow()
inst['image_ref'] = FAKE_IMAGE_REF
inst['reservation_id'] = 'r-fakeres'
inst['user_id'] = self.user_id
@@ -9450,42 +9726,31 @@ class CheckConfigDriveTestCase(test.TestCase):
def setUp(self):
super(CheckConfigDriveTestCase, self).setUp()
self.compute_api = compute.API()
- self.context = context.RequestContext(
- 'fake_user_id', 'fake_project_id')
-
- self.called = called = {'show': False}
-
- def fake_get_remote_image_service(context, image_id):
- class FakeGlance(object):
- def show(self, context, image_id):
- called['show'] = True
- return FakeGlance(), image_id
-
- self.stubs.Set(glance, 'get_remote_image_service',
- fake_get_remote_image_service)
-
- def tearDown(self):
- self.stubs.UnsetAll()
- super(CheckConfigDriveTestCase, self).tearDown()
-
- def assertCheck(self, expected, config_drive):
+ def _assertCheck(self, expected, config_drive):
self.assertEqual(expected,
- self.compute_api._check_config_drive(
- self.context, config_drive))
-
- def test_value_is_none(self):
- self.assertFalse(self.called['show'])
- self.assertCheck((None, None), None)
- self.assertFalse(self.called['show'])
-
- def test_bool_string_or_id(self):
- self.assertCheck((None, True), "true")
- self.assertCheck((None, True), 1)
- self.assertCheck((None, True), 't')
-
- def test_value_is_image_id(self):
- self.assertCheck(("fake-uuid", None), "fake-uuid")
+ self.compute_api._check_config_drive(config_drive))
+
+ def _assertInvalid(self, config_drive):
+ self.assertRaises(exception.ConfigDriveInvalidValue,
+ self.compute_api._check_config_drive,
+ config_drive)
+
+ def test_config_drive_false_values(self):
+ self._assertCheck('', None)
+ self._assertCheck('', '')
+ self._assertCheck('', 'False')
+ self._assertCheck('', 'f')
+ self._assertCheck('', '0')
+
+ def test_config_drive_true_values(self):
+ self._assertCheck(True, 'True')
+ self._assertCheck(True, 't')
+ self._assertCheck(True, '1')
+
+ def test_config_drive_bogus_values_raise(self):
+ self._assertInvalid('asd')
+ self._assertInvalid(uuidutils.generate_uuid())
class CheckRequestedImageTestCase(test.TestCase):
diff --git a/nova/tests/conductor/tasks/__init__.py b/nova/tests/conductor/tasks/__init__.py
new file mode 100644
index 000000000..94e731d20
--- /dev/null
+++ b/nova/tests/conductor/tasks/__init__.py
@@ -0,0 +1,11 @@
+# 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.
diff --git a/nova/tests/conductor/tasks/test_live_migrate.py b/nova/tests/conductor/tasks/test_live_migrate.py
new file mode 100644
index 000000000..c54e53b1a
--- /dev/null
+++ b/nova/tests/conductor/tasks/test_live_migrate.py
@@ -0,0 +1,311 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from nova.compute import flavors
+from nova.compute import power_state
+from nova.conductor.tasks import live_migrate
+from nova import db
+from nova import exception
+from nova import test
+
+
+class LiveMigrationTaskTestCase(test.TestCase):
+ def setUp(self):
+ super(LiveMigrationTaskTestCase, self).setUp()
+ self.context = "context"
+ self.instance_host = "host"
+ self.instance_uuid = "uuid"
+ self.instance_image = "image_ref"
+ self.instance = {
+ "host": self.instance_host,
+ "uuid": self.instance_uuid,
+ "power_state": power_state.RUNNING,
+ "memory_mb": 512,
+ "image_ref": self.instance_image}
+ self.destination = "destination"
+ self.block_migration = "bm"
+ self.disk_over_commit = "doc"
+ self.select_hosts_callback = self._select_hosts_callback
+ self._generate_task()
+
+ def _generate_task(self):
+ self.task = live_migrate.LiveMigrationTask(self.context,
+ self.instance, self.destination, self.block_migration,
+ self.disk_over_commit, self.select_hosts_callback)
+
+ def _select_hosts_callback(self, *args):
+ return ["host1"]
+
+ def test_execute_with_destination(self):
+ self.mox.StubOutWithMock(self.task, '_check_host_is_up')
+ self.mox.StubOutWithMock(self.task, '_check_requested_destination')
+ self.mox.StubOutWithMock(self.task.compute_rpcapi, 'live_migration')
+
+ self.task._check_host_is_up(self.instance_host)
+ self.task._check_requested_destination()
+ self.task.compute_rpcapi.live_migration(self.context,
+ host=self.instance_host,
+ instance=self.instance,
+ dest=self.destination,
+ block_migration=self.block_migration,
+ migrate_data=None).AndReturn("bob")
+
+ self.mox.ReplayAll()
+ self.assertEqual("bob", self.task.execute())
+
+ def test_execute_without_destination(self):
+ self.destination = None
+ self._generate_task()
+ self.assertEqual(None, self.task.destination)
+
+ self.mox.StubOutWithMock(self.task, '_check_host_is_up')
+ self.mox.StubOutWithMock(self.task, '_find_destination')
+ self.mox.StubOutWithMock(self.task.compute_rpcapi, 'live_migration')
+
+ self.task._check_host_is_up(self.instance_host)
+ self.task._find_destination().AndReturn("found_host")
+ self.task.compute_rpcapi.live_migration(self.context,
+ host=self.instance_host,
+ instance=self.instance,
+ dest="found_host",
+ block_migration=self.block_migration,
+ migrate_data=None).AndReturn("bob")
+
+ self.mox.ReplayAll()
+ self.assertEqual("bob", self.task.execute())
+
+ def test_check_instance_is_running_passes(self):
+ self.task._check_instance_is_running()
+
+ def test_check_instance_is_running_fails_when_shutdown(self):
+ self.task.instance['power_state'] = power_state.SHUTDOWN
+ self.assertRaises(exception.InstanceNotRunning,
+ self.task._check_instance_is_running)
+
+ def test_check_instance_host_is_up(self):
+ self.mox.StubOutWithMock(db, 'service_get_by_compute_host')
+ self.mox.StubOutWithMock(self.task.servicegroup_api, 'service_is_up')
+
+ db.service_get_by_compute_host(self.context,
+ "host").AndReturn("service")
+ self.task.servicegroup_api.service_is_up("service").AndReturn(True)
+
+ self.mox.ReplayAll()
+ self.task._check_host_is_up("host")
+
+ def test_check_instance_host_is_up_fails_if_not_up(self):
+ self.mox.StubOutWithMock(db, 'service_get_by_compute_host')
+ self.mox.StubOutWithMock(self.task.servicegroup_api, 'service_is_up')
+
+ db.service_get_by_compute_host(self.context,
+ "host").AndReturn("service")
+ self.task.servicegroup_api.service_is_up("service").AndReturn(False)
+
+ self.mox.ReplayAll()
+ self.assertRaises(exception.ComputeServiceUnavailable,
+ self.task._check_host_is_up, "host")
+
+ def test_check_instance_host_is_up_fails_if_not_found(self):
+ self.mox.StubOutWithMock(db, 'service_get_by_compute_host')
+
+ db.service_get_by_compute_host(self.context,
+ "host").AndRaise(exception.NotFound)
+
+ self.mox.ReplayAll()
+ self.assertRaises(exception.ComputeServiceUnavailable,
+ self.task._check_host_is_up, "host")
+
+ def test_check_requested_destination(self):
+ self.mox.StubOutWithMock(db, 'service_get_by_compute_host')
+ self.mox.StubOutWithMock(self.task, '_get_compute_info')
+ self.mox.StubOutWithMock(self.task.servicegroup_api, 'service_is_up')
+ self.mox.StubOutWithMock(self.task.compute_rpcapi,
+ 'check_can_live_migrate_destination')
+
+ db.service_get_by_compute_host(self.context,
+ self.destination).AndReturn("service")
+ self.task.servicegroup_api.service_is_up("service").AndReturn(True)
+ hypervisor_details = {
+ "hypervisor_type": "a",
+ "hypervisor_version": 6.1,
+ "free_ram_mb": 513
+ }
+ self.task._get_compute_info(self.destination)\
+ .AndReturn(hypervisor_details)
+ self.task._get_compute_info(self.instance_host)\
+ .AndReturn(hypervisor_details)
+ self.task._get_compute_info(self.destination)\
+ .AndReturn(hypervisor_details)
+
+ self.task.compute_rpcapi.check_can_live_migrate_destination(
+ self.context, self.instance, self.destination,
+ self.block_migration, self.disk_over_commit).AndReturn(
+ "migrate_data")
+
+ self.mox.ReplayAll()
+ self.task._check_requested_destination()
+ self.assertEqual("migrate_data", self.task.migrate_data)
+
+ def test_check_requested_destination_fails_with_same_dest(self):
+ self.task.destination = "same"
+ self.task.source = "same"
+ self.assertRaises(exception.UnableToMigrateToSelf,
+ self.task._check_requested_destination)
+
+ def test_check_requested_destination_fails_when_destination_is_up(self):
+ self.mox.StubOutWithMock(db, 'service_get_by_compute_host')
+
+ db.service_get_by_compute_host(self.context,
+ self.destination).AndRaise(exception.NotFound)
+
+ self.mox.ReplayAll()
+ self.assertRaises(exception.ComputeServiceUnavailable,
+ self.task._check_requested_destination)
+
+ def test_check_requested_destination_fails_with_not_enough_memory(self):
+ self.mox.StubOutWithMock(self.task, '_check_host_is_up')
+ self.mox.StubOutWithMock(db, 'service_get_by_compute_host')
+
+ self.task._check_host_is_up(self.destination)
+ db.service_get_by_compute_host(self.context,
+ self.destination).AndReturn({
+ "compute_node": [{"free_ram_mb": 511}]
+ })
+
+ self.mox.ReplayAll()
+ self.assertRaises(exception.MigrationPreCheckError,
+ self.task._check_requested_destination)
+
+ def test_check_requested_destination_fails_with_hypervisor_diff(self):
+ self.mox.StubOutWithMock(self.task, '_check_host_is_up')
+ self.mox.StubOutWithMock(self.task,
+ '_check_destination_has_enough_memory')
+ self.mox.StubOutWithMock(self.task, '_get_compute_info')
+
+ self.task._check_host_is_up(self.destination)
+ self.task._check_destination_has_enough_memory()
+ self.task._get_compute_info(self.instance_host).AndReturn({
+ "hypervisor_type": "b"
+ })
+ self.task._get_compute_info(self.destination).AndReturn({
+ "hypervisor_type": "a"
+ })
+
+ self.mox.ReplayAll()
+ self.assertRaises(exception.InvalidHypervisorType,
+ self.task._check_requested_destination)
+
+ def test_check_requested_destination_fails_with_hypervisor_too_old(self):
+ self.mox.StubOutWithMock(self.task, '_check_host_is_up')
+ self.mox.StubOutWithMock(self.task,
+ '_check_destination_has_enough_memory')
+ self.mox.StubOutWithMock(self.task, '_get_compute_info')
+
+ self.task._check_host_is_up(self.destination)
+ self.task._check_destination_has_enough_memory()
+ self.task._get_compute_info(self.instance_host).AndReturn({
+ "hypervisor_type": "a",
+ "hypervisor_version": 7
+ })
+ self.task._get_compute_info(self.destination).AndReturn({
+ "hypervisor_type": "a",
+ "hypervisor_version": 6
+ })
+
+ self.mox.ReplayAll()
+ self.assertRaises(exception.DestinationHypervisorTooOld,
+ self.task._check_requested_destination)
+
+ def test_find_destination_works(self):
+ self.mox.StubOutWithMock(self.task.image_service, 'show')
+ self.mox.StubOutWithMock(flavors, 'extract_flavor')
+ self.mox.StubOutWithMock(self.task,
+ '_check_compatible_with_source_hypervisor')
+ self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host')
+
+ self.task.image_service.show(self.context,
+ self.instance_image).AndReturn("image")
+ flavors.extract_flavor(self.instance).AndReturn("inst_type")
+ self.task._check_compatible_with_source_hypervisor("host1")
+ self.task._call_livem_checks_on_host("host1")
+
+ self.mox.ReplayAll()
+ self.assertEqual("host1", self.task._find_destination())
+
+ def _test_find_destination_retry_hypervisor_raises(self, error):
+ self.mox.StubOutWithMock(self.task.image_service, 'show')
+ self.mox.StubOutWithMock(flavors, 'extract_flavor')
+ self.mox.StubOutWithMock(self.task,
+ '_check_compatible_with_source_hypervisor')
+ self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host')
+
+ self.task.image_service.show(self.context,
+ self.instance_image).AndReturn("image")
+ flavors.extract_flavor(self.instance).AndReturn("inst_type")
+ self.task._check_compatible_with_source_hypervisor("host1")\
+ .AndRaise(error)
+
+ self.task._check_compatible_with_source_hypervisor("host1")
+ self.task._call_livem_checks_on_host("host1")
+
+ self.mox.ReplayAll()
+ self.assertEqual("host1", self.task._find_destination())
+
+ def test_find_destination_retry_with_old_hypervisor(self):
+ self._test_find_destination_retry_hypervisor_raises(
+ exception.DestinationHypervisorTooOld)
+
+ def test_find_destination_retry_with_invalid_hypervisor_type(self):
+ self._test_find_destination_retry_hypervisor_raises(
+ exception.InvalidHypervisorType)
+
+ def test_find_destination_retry_with_invalid_livem_checks(self):
+ self.mox.StubOutWithMock(self.task.image_service, 'show')
+ self.mox.StubOutWithMock(flavors, 'extract_flavor')
+ self.mox.StubOutWithMock(self.task,
+ '_check_compatible_with_source_hypervisor')
+ self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host')
+
+ self.task.image_service.show(self.context,
+ self.instance_image).AndReturn("image")
+ flavors.extract_flavor(self.instance).AndReturn("inst_type")
+ self.task._check_compatible_with_source_hypervisor("host1")
+ self.task._call_livem_checks_on_host("host1")\
+ .AndRaise(exception.Invalid)
+
+ self.task._check_compatible_with_source_hypervisor("host1")
+ self.task._call_livem_checks_on_host("host1")
+
+ self.mox.ReplayAll()
+ self.assertEqual("host1", self.task._find_destination())
+
+ def test_find_destination_retry_exceeds_max(self):
+ self.flags(scheduler_max_attempts=1)
+ self.mox.StubOutWithMock(self.task.image_service, 'show')
+ self.mox.StubOutWithMock(flavors, 'extract_flavor')
+ self.mox.StubOutWithMock(self.task,
+ '_check_compatible_with_source_hypervisor')
+ self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host')
+
+ self.task.image_service.show(self.context,
+ self.instance_image).AndReturn("image")
+ flavors.extract_flavor(self.instance).AndReturn("inst_type")
+ self.task._check_compatible_with_source_hypervisor("host1")\
+ .AndRaise(exception.DestinationHypervisorTooOld)
+
+ self.mox.ReplayAll()
+ self.assertRaises(exception.NoValidHost, self.task._find_destination)
+
+ def test_not_implemented_rollback(self):
+ self.assertRaises(NotImplementedError, self.task.rollback)
diff --git a/nova/tests/conductor/test_conductor.py b/nova/tests/conductor/test_conductor.py
index 7a33cfbb9..609c2164c 100644
--- a/nova/tests/conductor/test_conductor.py
+++ b/nova/tests/conductor/test_conductor.py
@@ -246,9 +246,8 @@ class _BaseTestCase(object):
self.mox.StubOutWithMock(db, 'aggregate_metadata_delete')
db.aggregate_metadata_delete(mox.IgnoreArg(), aggregate['id'], 'fake')
self.mox.ReplayAll()
- result = self.conductor.aggregate_metadata_delete(self.context,
- aggregate,
- 'fake')
+ self.conductor.aggregate_metadata_delete(self.context, aggregate,
+ 'fake')
def test_aggregate_metadata_get_by_host(self):
self.mox.StubOutWithMock(db, 'aggregate_metadata_get_by_host')
@@ -389,7 +388,7 @@ class _BaseTestCase(object):
fake_inst['project_id'],
fake_inst['user_id'],
fake_inst['availability_zone'],
- False, mox.IgnoreArg()).AndReturn('fake-usage')
+ False).AndReturn('fake-usage')
compute_utils.usage_volume_info('fake-usage').AndReturn('fake-info')
notifier_api.notify(self.context,
'conductor.%s' % self.conductor_manager.host,
@@ -616,13 +615,28 @@ class ConductorTestCase(_BaseTestCase, test.TestCase):
self.conductor_manager = self.conductor
def test_block_device_mapping_update_or_create(self):
- fake_bdm = {'id': 'fake-id'}
+ fake_bdm = {'id': 'fake-id', 'device_name': 'foo'}
+ fake_bdm2 = {'id': 'fake-id', 'device_name': 'foo2'}
+ cells_rpcapi = self.conductor.cells_rpcapi
self.mox.StubOutWithMock(db, 'block_device_mapping_create')
self.mox.StubOutWithMock(db, 'block_device_mapping_update')
self.mox.StubOutWithMock(db, 'block_device_mapping_update_or_create')
- db.block_device_mapping_create(self.context, fake_bdm)
- db.block_device_mapping_update(self.context, fake_bdm['id'], fake_bdm)
- db.block_device_mapping_update_or_create(self.context, fake_bdm)
+ self.mox.StubOutWithMock(cells_rpcapi,
+ 'bdm_update_or_create_at_top')
+ db.block_device_mapping_create(self.context,
+ fake_bdm).AndReturn(fake_bdm2)
+ cells_rpcapi.bdm_update_or_create_at_top(self.context, fake_bdm2,
+ create=True)
+ db.block_device_mapping_update(self.context, fake_bdm['id'],
+ fake_bdm).AndReturn(fake_bdm2)
+ cells_rpcapi.bdm_update_or_create_at_top(self.context,
+ fake_bdm2,
+ create=False)
+ db.block_device_mapping_update_or_create(
+ self.context, fake_bdm).AndReturn(fake_bdm2)
+ cells_rpcapi.bdm_update_or_create_at_top(self.context,
+ fake_bdm2,
+ create=None)
self.mox.ReplayAll()
self.conductor.block_device_mapping_update_or_create(self.context,
fake_bdm,
@@ -634,22 +648,44 @@ class ConductorTestCase(_BaseTestCase, test.TestCase):
fake_bdm)
def test_block_device_mapping_destroy(self):
- fake_bdm = {'id': 'fake-bdm'}
- fake_bdm2 = {'id': 'fake-bdm-2'}
+ fake_bdm = {'id': 'fake-bdm',
+ 'instance_uuid': 'fake-uuid',
+ 'device_name': 'fake-device1',
+ 'volume_id': 'fake-vol-id1'}
+ fake_bdm2 = {'id': 'fake-bdm-2',
+ 'instance_uuid': 'fake-uuid2',
+ 'device_name': '',
+ 'volume_id': 'fake-vol-id2'}
fake_inst = {'uuid': 'fake-uuid'}
+
+ cells_rpcapi = self.conductor.cells_rpcapi
+
self.mox.StubOutWithMock(db, 'block_device_mapping_destroy')
self.mox.StubOutWithMock(
db, 'block_device_mapping_destroy_by_instance_and_device')
self.mox.StubOutWithMock(
db, 'block_device_mapping_destroy_by_instance_and_volume')
+ self.mox.StubOutWithMock(cells_rpcapi, 'bdm_destroy_at_top')
+
db.block_device_mapping_destroy(self.context, 'fake-bdm')
+ cells_rpcapi.bdm_destroy_at_top(self.context,
+ fake_bdm['instance_uuid'],
+ device_name=fake_bdm['device_name'])
db.block_device_mapping_destroy(self.context, 'fake-bdm-2')
+ cells_rpcapi.bdm_destroy_at_top(self.context,
+ fake_bdm2['instance_uuid'],
+ volume_id=fake_bdm2['volume_id'])
db.block_device_mapping_destroy_by_instance_and_device(self.context,
'fake-uuid',
'fake-device')
+ cells_rpcapi.bdm_destroy_at_top(self.context, fake_inst['uuid'],
+ device_name='fake-device')
db.block_device_mapping_destroy_by_instance_and_volume(self.context,
'fake-uuid',
'fake-volume')
+ cells_rpcapi.bdm_destroy_at_top(self.context, fake_inst['uuid'],
+ volume_id='fake-volume')
+
self.mox.ReplayAll()
self.conductor.block_device_mapping_destroy(self.context,
[fake_bdm,
@@ -794,8 +830,12 @@ class ConductorRPCAPITestCase(_BaseTestCase, test.TestCase):
fake_bdm)
def test_block_device_mapping_destroy(self):
- fake_bdm = {'id': 'fake-bdm'}
+ fake_bdm = {'id': 'fake-bdm',
+ 'instance_uuid': 'fake-uuid',
+ 'device_name': 'fake-device1',
+ 'volume_id': 'fake-vol-id1'}
fake_inst = {'uuid': 'fake-uuid'}
+
self.mox.StubOutWithMock(db, 'block_device_mapping_destroy')
self.mox.StubOutWithMock(
db, 'block_device_mapping_destroy_by_instance_and_device')
@@ -945,8 +985,12 @@ class ConductorAPITestCase(_BaseTestCase, test.TestCase):
'fake-bdm')
def test_block_device_mapping_destroy(self):
- fake_bdm = {'id': 'fake-bdm'}
+ fake_bdm = {'id': 'fake-bdm',
+ 'instance_uuid': 'fake-uuid',
+ 'device_name': 'fake-device1',
+ 'volume_id': 'fake-vol-id1'}
fake_inst = {'uuid': 'fake-uuid'}
+
self.mox.StubOutWithMock(db, 'block_device_mapping_destroy')
self.mox.StubOutWithMock(
db, 'block_device_mapping_destroy_by_instance_and_device')
@@ -1183,18 +1227,28 @@ class _BaseTaskTestCase(object):
def test_build_instances(self):
instance_type = flavors.get_default_flavor()
system_metadata = flavors.save_flavor_info({}, instance_type)
- # NOTE(alaski): instance_type -> system_metadata -> instance_type loses
- # some data (extra_specs) so we need both for testing.
- instance_type_extract = flavors.extract_flavor(
+ # NOTE(alaski): instance_type -> system_metadata -> instance_type
+ # loses some data (extra_specs). This build process is using
+ # scheduler/utils:build_request_spec() which extracts flavor from
+ # system_metadata and will re-query the DB for extra_specs.. so
+ # we need to test this properly
+ expected_instance_type = flavors.extract_flavor(
{'system_metadata': system_metadata})
+ expected_instance_type['extra_specs'] = 'fake-specs'
+
+ self.mox.StubOutWithMock(db, 'instance_type_extra_specs_get')
self.mox.StubOutWithMock(self.conductor_manager.scheduler_rpcapi,
'run_instance')
+
+ db.instance_type_extra_specs_get(
+ self.context,
+ instance_type['flavorid']).AndReturn('fake-specs')
self.conductor_manager.scheduler_rpcapi.run_instance(self.context,
request_spec={
'image': {'fake_data': 'should_pass_silently'},
'instance_properties': {'system_metadata': system_metadata,
'uuid': 'fakeuuid'},
- 'instance_type': instance_type_extract,
+ 'instance_type': expected_instance_type,
'instance_uuids': ['fakeuuid', 'fakeuuid2'],
'block_device_mapping': 'block_device_mapping',
'security_group': 'security_groups'},
diff --git a/nova/tests/db/test_db_api.py b/nova/tests/db/test_db_api.py
index 0a5b75bf4..e7ae1b76d 100644
--- a/nova/tests/db/test_db_api.py
+++ b/nova/tests/db/test_db_api.py
@@ -30,6 +30,7 @@ from sqlalchemy.dialects import sqlite
from sqlalchemy import exc
from sqlalchemy.exc import IntegrityError
from sqlalchemy import MetaData
+from sqlalchemy.orm import exc as sqlalchemy_orm_exc
from sqlalchemy.orm import query
from sqlalchemy.sql.expression import select
@@ -152,18 +153,18 @@ class DbApiTestCase(DbTestCase):
self.flags(osapi_compute_unique_server_name_scope=None)
def test_ec2_ids_not_found_are_printable(self):
- def check_exc_format(method):
+ def check_exc_format(method, value):
try:
- method(self.context, 'fake')
+ method(self.context, value)
except exception.NotFound as exc:
- self.assertTrue('fake' in unicode(exc))
+ self.assertTrue(unicode(value) in unicode(exc))
- check_exc_format(db.get_ec2_volume_id_by_uuid)
- check_exc_format(db.get_volume_uuid_by_ec2_id)
- check_exc_format(db.get_ec2_snapshot_id_by_uuid)
- check_exc_format(db.get_snapshot_uuid_by_ec2_id)
- check_exc_format(db.get_ec2_instance_id_by_uuid)
- check_exc_format(db.get_instance_uuid_by_ec2_id)
+ check_exc_format(db.get_ec2_volume_id_by_uuid, 'fake')
+ check_exc_format(db.get_volume_uuid_by_ec2_id, 123456)
+ check_exc_format(db.get_ec2_snapshot_id_by_uuid, 'fake')
+ check_exc_format(db.get_snapshot_uuid_by_ec2_id, 123456)
+ check_exc_format(db.get_ec2_instance_id_by_uuid, 'fake')
+ check_exc_format(db.get_instance_uuid_by_ec2_id, 123456)
def test_instance_get_all_with_meta(self):
inst = self.create_instance_with_args()
@@ -285,7 +286,7 @@ class DbApiTestCase(DbTestCase):
def test_instance_get_all_by_filters_deleted_and_soft_deleted(self):
inst1 = self.create_instance_with_args()
inst2 = self.create_instance_with_args(vm_state=vm_states.SOFT_DELETED)
- inst3 = self.create_instance_with_args()
+ self.create_instance_with_args()
db.instance_destroy(self.context, inst1['uuid'])
result = db.instance_get_all_by_filters(self.context,
{'deleted': True})
@@ -295,8 +296,8 @@ class DbApiTestCase(DbTestCase):
def test_instance_get_all_by_filters_deleted_no_soft_deleted(self):
inst1 = self.create_instance_with_args()
- inst2 = self.create_instance_with_args(vm_state=vm_states.SOFT_DELETED)
- inst3 = self.create_instance_with_args()
+ self.create_instance_with_args(vm_state=vm_states.SOFT_DELETED)
+ self.create_instance_with_args()
db.instance_destroy(self.context, inst1['uuid'])
result = db.instance_get_all_by_filters(self.context,
{'deleted': True,
@@ -947,8 +948,8 @@ class AggregateDBApiTestCase(test.TestCase):
values2 = {'name': 'fake_aggregate4'}
a1 = _create_aggregate_with_hosts(context=ctxt,
metadata={'goodkey': 'good'})
- a2 = _create_aggregate_with_hosts(context=ctxt, values=values)
- a3 = _create_aggregate(context=ctxt, values=values2)
+ _create_aggregate_with_hosts(context=ctxt, values=values)
+ _create_aggregate(context=ctxt, values=values2)
# filter result by key
r1 = db.aggregate_get_by_host(ctxt, 'foo.openstack.org', key='goodkey')
self.assertEqual([a1['id']], [x['id'] for x in r1])
@@ -957,9 +958,9 @@ class AggregateDBApiTestCase(test.TestCase):
ctxt = context.get_admin_context()
values = {'name': 'fake_aggregate2'}
values2 = {'name': 'fake_aggregate3'}
- a1 = _create_aggregate_with_hosts(context=ctxt)
- a2 = _create_aggregate_with_hosts(context=ctxt, values=values)
- a3 = _create_aggregate_with_hosts(context=ctxt, values=values2,
+ _create_aggregate_with_hosts(context=ctxt)
+ _create_aggregate_with_hosts(context=ctxt, values=values)
+ _create_aggregate_with_hosts(context=ctxt, values=values2,
hosts=['bar.openstack.org'], metadata={'badkey': 'bad'})
r1 = db.aggregate_metadata_get_by_host(ctxt, 'foo.openstack.org')
self.assertEqual(r1['fake_key1'], set(['fake_value1']))
@@ -969,8 +970,8 @@ class AggregateDBApiTestCase(test.TestCase):
ctxt = context.get_admin_context()
values = {'name': 'fake_aggregate2'}
values2 = {'name': 'fake_aggregate3'}
- a1 = _create_aggregate_with_hosts(context=ctxt)
- a2 = _create_aggregate_with_hosts(context=ctxt, values=values)
+ _create_aggregate_with_hosts(context=ctxt)
+ _create_aggregate_with_hosts(context=ctxt, values=values)
a3 = _create_aggregate_with_hosts(context=ctxt, values=values2,
hosts=['foo.openstack.org'], metadata={'good': 'value'})
r1 = db.aggregate_metadata_get_by_host(ctxt, 'foo.openstack.org',
@@ -987,9 +988,9 @@ class AggregateDBApiTestCase(test.TestCase):
ctxt = context.get_admin_context()
values = {'name': 'fake_aggregate2'}
values2 = {'name': 'fake_aggregate3'}
- a1 = _create_aggregate_with_hosts(context=ctxt)
- a2 = _create_aggregate_with_hosts(context=ctxt, values=values)
- a3 = _create_aggregate_with_hosts(context=ctxt, values=values2,
+ _create_aggregate_with_hosts(context=ctxt)
+ _create_aggregate_with_hosts(context=ctxt, values=values)
+ _create_aggregate_with_hosts(context=ctxt, values=values2,
hosts=['foo.openstack.org'], metadata={'good': 'value'})
r1 = db.aggregate_host_get_by_metadata_key(ctxt, key='good')
self.assertEqual(r1, {'foo.openstack.org': set(['value'])})
@@ -1299,10 +1300,11 @@ class ModelsObjectComparatorMixin(object):
self.assertEqual(value, obj2[key])
def _assertEqualListsOfObjects(self, objs1, objs2, ignored_keys=None):
- self.assertEqual(len(objs1), len(objs2))
- objs2 = dict([(o['id'], o) for o in objs2])
- for o1 in objs1:
- self._assertEqualObjects(o1, objs2[o1['id']], ignored_keys)
+ obj_to_dict = lambda o: self._dict_from_object(o, ignored_keys)
+ sort_key = lambda d: [d[k] for k in sorted(d)]
+ conv_and_sort = lambda obj: sorted(map(obj_to_dict, obj), key=sort_key)
+
+ self.assertEqual(conv_and_sort(objs1), conv_and_sort(objs2))
def _assertEqualListsOfPrimitivesAsSets(self, primitives1, primitives2):
self.assertEqual(len(primitives1), len(primitives2))
@@ -1313,6 +1315,54 @@ class ModelsObjectComparatorMixin(object):
self.assertIn(primitive, primitives1)
+class InstanceSystemMetadataTestCase(test.TestCase):
+
+ """Tests for db.api.instance_system_metadata_* methods."""
+
+ def setUp(self):
+ super(InstanceSystemMetadataTestCase, self).setUp()
+ values = {'host': 'h1', 'project_id': 'p1',
+ 'system_metadata': {'key': 'value'}}
+ self.ctxt = context.get_admin_context()
+ self.instance = db.instance_create(self.ctxt, values)
+
+ def test_instance_system_metadata_get(self):
+ metadata = db.instance_system_metadata_get(self.ctxt,
+ self.instance['uuid'])
+ self.assertEqual(metadata, {'key': 'value'})
+
+ def test_instance_system_metadata_update_new_pair(self):
+ db.instance_system_metadata_update(
+ self.ctxt, self.instance['uuid'],
+ {'new_key': 'new_value'}, False)
+ metadata = db.instance_system_metadata_get(self.ctxt,
+ self.instance['uuid'])
+ self.assertEqual(metadata, {'key': 'value', 'new_key': 'new_value'})
+
+ def test_instance_system_metadata_update_existent_pair(self):
+ db.instance_system_metadata_update(
+ self.ctxt, self.instance['uuid'],
+ {'key': 'new_value'}, True)
+ metadata = db.instance_system_metadata_get(self.ctxt,
+ self.instance['uuid'])
+ self.assertEqual(metadata, {'key': 'new_value'})
+
+ def test_instance_system_metadata_update_delete_true(self):
+ db.instance_system_metadata_update(
+ self.ctxt, self.instance['uuid'],
+ {'new_key': 'new_value'}, True)
+ metadata = db.instance_system_metadata_get(self.ctxt,
+ self.instance['uuid'])
+ self.assertEqual(metadata, {'new_key': 'new_value'})
+
+ @test.testtools.skip("bug 1189462")
+ def test_instance_system_metadata_update_nonexistent(self):
+ self.assertRaises(exception.InstanceNotFound,
+ db.instance_system_metadata_update,
+ self.ctxt, 'nonexistent-uuid',
+ {'key': 'value'}, True)
+
+
class ReservationTestCase(test.TestCase, ModelsObjectComparatorMixin):
"""Tests for db.api.reservation_* methods."""
@@ -1414,7 +1464,7 @@ class ReservationTestCase(test.TestCase, ModelsObjectComparatorMixin):
def test_reservation_expire(self):
self.values['expire'] = datetime.datetime.utcnow() + datetime.\
timedelta(days=1)
- reservations = self._quota_reserve()
+ self._quota_reserve()
db.reservation_expire(self.ctxt)
expected = {'project_id': 'project1',
@@ -1425,6 +1475,119 @@ class ReservationTestCase(test.TestCase, ModelsObjectComparatorMixin):
self.ctxt, 'project1'))
+class SecurityGroupRuleTestCase(test.TestCase, ModelsObjectComparatorMixin):
+ def setUp(self):
+ super(SecurityGroupRuleTestCase, self).setUp()
+ self.ctxt = context.get_admin_context()
+
+ def _get_base_values(self):
+ return {
+ 'name': 'fake_sec_group',
+ 'description': 'fake_sec_group_descr',
+ 'user_id': 'fake',
+ 'project_id': 'fake',
+ 'instances': []
+ }
+
+ def _get_base_rule_values(self):
+ return {
+ 'protocol': "tcp",
+ 'from_port': 80,
+ 'to_port': 8080,
+ 'cidr': None,
+ 'deleted': 0,
+ 'deleted_at': None,
+ 'grantee_group': None,
+ 'updated_at': None
+ }
+
+ def _create_security_group(self, values):
+ v = self._get_base_values()
+ v.update(values)
+ return db.security_group_create(self.ctxt, v)
+
+ def _create_security_group_rule(self, values):
+ v = self._get_base_rule_values()
+ v.update(values)
+ return db.security_group_rule_create(self.ctxt, v)
+
+ def test_security_group_rule_create(self):
+ security_group_rule = self._create_security_group_rule({})
+ self.assertIsNotNone(security_group_rule['id'])
+ for key, value in self._get_base_rule_values().items():
+ self.assertEqual(value, security_group_rule[key])
+
+ def test_security_group_rule_get_by_security_group(self):
+ security_group = self._create_security_group({})
+ security_group_rule = self._create_security_group_rule(
+ {'parent_group': security_group})
+ security_group_rule1 = self._create_security_group_rule(
+ {'parent_group': security_group})
+ found_rules = db.security_group_rule_get_by_security_group(self.ctxt,
+ security_group['id'])
+ self.assertEqual(len(found_rules), 2)
+ rules_ids = [security_group_rule['id'], security_group_rule1['id']]
+ for rule in found_rules:
+ self.assertIn(rule['id'], rules_ids)
+
+ def test_security_group_rule_get_by_security_group_grantee(self):
+ security_group = self._create_security_group({})
+ security_group_rule = self._create_security_group_rule(
+ {'grantee_group': security_group})
+ rules = db.security_group_rule_get_by_security_group_grantee(self.ctxt,
+ security_group['id'])
+ self.assertEqual(len(rules), 1)
+ self.assertEqual(rules[0]['id'], security_group_rule['id'])
+
+ def test_security_group_rule_destroy(self):
+ security_group1 = self._create_security_group({})
+ security_group2 = self._create_security_group({})
+ security_group_rule1 = self._create_security_group_rule({})
+ security_group_rule2 = self._create_security_group_rule({})
+ db.security_group_rule_destroy(self.ctxt, security_group_rule1['id'])
+ self.assertRaises(exception.SecurityGroupNotFound,
+ db.security_group_rule_get,
+ self.ctxt, security_group_rule1['id'])
+ self._assertEqualObjects(db.security_group_rule_get(self.ctxt,
+ security_group_rule2['id']),
+ security_group_rule2, ['grantee_group'])
+
+ def test_security_group_rule_destroy_not_found_exception(self):
+ self.assertRaises(exception.SecurityGroupNotFound,
+ db.security_group_rule_destroy, self.ctxt, 100500)
+
+ def test_security_group_rule_get(self):
+ security_group_rule1 = (
+ self._create_security_group_rule({}))
+ security_group_rule2 = self._create_security_group_rule({})
+ real_security_group_rule = db.security_group_rule_get(self.ctxt,
+ security_group_rule1['id'])
+ self._assertEqualObjects(security_group_rule1,
+ real_security_group_rule, ['grantee_group'])
+
+ def test_security_group_rule_get_not_found_exception(self):
+ self.assertRaises(exception.SecurityGroupNotFound,
+ db.security_group_rule_get, self.ctxt, 100500)
+
+ def test_security_group_rule_count_by_group(self):
+ sg1 = self._create_security_group({})
+ sg2 = self._create_security_group({})
+ rules_by_group = {sg1: [], sg2: []}
+ for group in rules_by_group:
+ rules = rules_by_group[group]
+ for i in range(0, 10):
+ rules.append(
+ self._create_security_group_rule({'parent_group_id':
+ group['id']}))
+ db.security_group_rule_destroy(self.ctxt,
+ rules_by_group[sg1][0]['id'])
+ counted_groups = [db.security_group_rule_count_by_group(self.ctxt,
+ group['id'])
+ for group in [sg1, sg2]]
+ expected = [9, 10]
+ self.assertEqual(counted_groups, expected)
+
+
class SecurityGroupTestCase(test.TestCase, ModelsObjectComparatorMixin):
def setUp(self):
super(SecurityGroupTestCase, self).setUp()
@@ -1459,19 +1622,39 @@ class SecurityGroupTestCase(test.TestCase, ModelsObjectComparatorMixin):
self.assertRaises(exception.SecurityGroupNotFound,
db.security_group_get,
self.ctxt, security_group1['id'])
- self._assertEqualObjects(db.security_group_get(self.ctxt,
- security_group2['id']),
- security_group2)
+ self._assertEqualObjects(db.security_group_get(
+ self.ctxt, security_group2['id'],
+ columns_to_join=['instances']), security_group2)
def test_security_group_get(self):
security_group1 = self._create_security_group({})
- security_group2 = self._create_security_group(
- {'name': 'fake_sec_group2'})
+ self._create_security_group({'name': 'fake_sec_group2'})
real_security_group = db.security_group_get(self.ctxt,
- security_group1['id'])
+ security_group1['id'],
+ columns_to_join=['instances'])
self._assertEqualObjects(security_group1,
real_security_group)
+ def test_security_group_get_no_instances(self):
+ instance = db.instance_create(self.ctxt, {})
+ sid = self._create_security_group({'instances': [instance]})['id']
+
+ session = get_session()
+ self.mox.StubOutWithMock(sqlalchemy_api, 'get_session')
+ sqlalchemy_api.get_session().AndReturn(session)
+ sqlalchemy_api.get_session().AndReturn(session)
+ self.mox.ReplayAll()
+
+ security_group = db.security_group_get(self.ctxt, sid,
+ columns_to_join=['instances'])
+ session.expunge(security_group)
+ self.assertEqual(1, len(security_group['instances']))
+
+ security_group = db.security_group_get(self.ctxt, sid)
+ session.expunge(security_group)
+ self.assertRaises(sqlalchemy_orm_exc.DetachedInstanceError,
+ getattr, security_group, 'instances')
+
def test_security_group_get_not_found_exception(self):
self.assertRaises(exception.SecurityGroupNotFound,
db.security_group_get, self.ctxt, 100500)
@@ -1558,8 +1741,8 @@ class SecurityGroupTestCase(test.TestCase, ModelsObjectComparatorMixin):
{'name': 'fake2', 'project_id': 'fake_proj1'},
{'name': 'fake3', 'project_id': 'fake_proj2'},
]
- security_groups = [self._create_security_group(vals)
- for vals in values]
+ for vals in values:
+ self._create_security_group(vals)
real = []
for project in ('fake_proj1', 'fake_proj2'):
@@ -1592,7 +1775,7 @@ class SecurityGroupTestCase(test.TestCase, ModelsObjectComparatorMixin):
self.ctxt.project_id,
'default'))
- default_group = db.security_group_ensure_default(self.ctxt)
+ db.security_group_ensure_default(self.ctxt)
self.assertTrue(db.security_group_exists(self.ctxt,
self.ctxt.project_id,
@@ -1712,7 +1895,7 @@ class ServiceTestCase(test.TestCase, ModelsObjectComparatorMixin):
def test_service_get(self):
service1 = self._create_service({})
- service2 = self._create_service({'host': 'some_other_fake_host'})
+ self._create_service({'host': 'some_other_fake_host'})
real_service1 = db.service_get(self.ctxt, service1['id'])
self._assertEqualObjects(service1, real_service1,
ignored_keys=['compute_node'])
@@ -1737,7 +1920,7 @@ class ServiceTestCase(test.TestCase, ModelsObjectComparatorMixin):
def test_service_get_by_host_and_topic(self):
service1 = self._create_service({'host': 'host1', 'topic': 'topic1'})
- service2 = self._create_service({'host': 'host2', 'topic': 'topic2'})
+ self._create_service({'host': 'host2', 'topic': 'topic2'})
real_service1 = db.service_get_by_host_and_topic(self.ctxt,
host='host1',
@@ -1854,292 +2037,264 @@ class BaseInstanceTypeTestCase(test.TestCase, ModelsObjectComparatorMixin):
class InstanceActionTestCase(test.TestCase, ModelsObjectComparatorMixin):
+ IGNORED_FIELDS = [
+ 'id',
+ 'created_at',
+ 'updated_at',
+ 'deleted_at',
+ 'deleted'
+ ]
+
+ def setUp(self):
+ super(InstanceActionTestCase, self).setUp()
+ self.ctxt = context.get_admin_context()
+
+ def _create_action_values(self, uuid, action='run_instance', ctxt=None):
+ if ctxt is None:
+ ctxt = self.ctxt
+ return {
+ 'action': action,
+ 'instance_uuid': uuid,
+ 'request_id': ctxt.request_id,
+ 'user_id': ctxt.user_id,
+ 'project_id': ctxt.project_id,
+ 'start_time': timeutils.utcnow(),
+ 'message': 'action-message'
+ }
+
+ def _create_event_values(self, uuid, event='schedule',
+ ctxt=None, extra=None):
+ if ctxt is None:
+ ctxt = self.ctxt
+ values = {
+ 'event': event,
+ 'instance_uuid': uuid,
+ 'request_id': ctxt.request_id,
+ 'start_time': timeutils.utcnow()
+ }
+ if extra is not None:
+ values.update(extra)
+ return values
+
+ def _assertActionSaved(self, action, uuid):
+ """Retrieve the action to ensure it was successfully added."""
+ actions = db.actions_get(self.ctxt, uuid)
+ self.assertEqual(1, len(actions))
+ self._assertEqualObjects(action, actions[0])
+
+ def _assertActionEventSaved(self, event, action_id):
+ # Retrieve the event to ensure it was successfully added
+ events = db.action_events_get(self.ctxt, action_id)
+ self.assertEqual(1, len(events))
+ self._assertEqualObjects(event, events[0],
+ ['instance_uuid', 'request_id'])
+
def test_instance_action_start(self):
"""Create an instance action."""
- ctxt = context.get_admin_context()
uuid = str(stdlib_uuid.uuid4())
- start_time = timeutils.utcnow()
- action_values = {'action': 'run_instance',
- 'instance_uuid': uuid,
- 'request_id': ctxt.request_id,
- 'user_id': ctxt.user_id,
- 'project_id': ctxt.project_id,
- 'start_time': start_time}
- db.action_start(ctxt, action_values)
+ action_values = self._create_action_values(uuid)
+ action = db.action_start(self.ctxt, action_values)
- # Retrieve the action to ensure it was successfully added
- actions = db.actions_get(ctxt, uuid)
- self.assertEqual(1, len(actions))
- self.assertEqual('run_instance', actions[0]['action'])
- self.assertEqual(start_time, actions[0]['start_time'])
- self.assertEqual(ctxt.request_id, actions[0]['request_id'])
- self.assertEqual(ctxt.user_id, actions[0]['user_id'])
- self.assertEqual(ctxt.project_id, actions[0]['project_id'])
+ ignored_keys = self.IGNORED_FIELDS + ['finish_time']
+ self._assertEqualObjects(action_values, action, ignored_keys)
+
+ self._assertActionSaved(action, uuid)
def test_instance_action_finish(self):
"""Create an instance action."""
- ctxt = context.get_admin_context()
uuid = str(stdlib_uuid.uuid4())
- start_time = timeutils.utcnow()
- action_start_values = {'action': 'run_instance',
- 'instance_uuid': uuid,
- 'request_id': ctxt.request_id,
- 'user_id': ctxt.user_id,
- 'project_id': ctxt.project_id,
- 'start_time': start_time}
- db.action_start(ctxt, action_start_values)
-
- finish_time = timeutils.utcnow() + datetime.timedelta(seconds=5)
- action_finish_values = {'instance_uuid': uuid,
- 'request_id': ctxt.request_id,
- 'finish_time': finish_time}
- db.action_finish(ctxt, action_finish_values)
+ action_values = self._create_action_values(uuid)
+ db.action_start(self.ctxt, action_values)
- # Retrieve the action to ensure it was successfully added
- actions = db.actions_get(ctxt, uuid)
- self.assertEqual(1, len(actions))
- self.assertEqual('run_instance', actions[0]['action'])
- self.assertEqual(start_time, actions[0]['start_time'])
- self.assertEqual(finish_time, actions[0]['finish_time'])
- self.assertEqual(ctxt.request_id, actions[0]['request_id'])
- self.assertEqual(ctxt.user_id, actions[0]['user_id'])
- self.assertEqual(ctxt.project_id, actions[0]['project_id'])
+ action_values['finish_time'] = timeutils.utcnow()
+ action = db.action_finish(self.ctxt, action_values)
+ self._assertEqualObjects(action_values, action, self.IGNORED_FIELDS)
+
+ self._assertActionSaved(action, uuid)
+
+ def test_instance_action_finish_without_started_event(self):
+ """Create an instance finish action."""
+ uuid = str(stdlib_uuid.uuid4())
+
+ action_values = self._create_action_values(uuid)
+ action_values['finish_time'] = timeutils.utcnow()
+ self.assertRaises(exception.InstanceActionNotFound, db.action_finish,
+ self.ctxt, action_values)
def test_instance_actions_get_by_instance(self):
"""Ensure we can get actions by UUID."""
- ctxt1 = context.get_admin_context()
- ctxt2 = context.get_admin_context()
uuid1 = str(stdlib_uuid.uuid4())
- uuid2 = str(stdlib_uuid.uuid4())
- action_values = {'action': 'run_instance',
- 'instance_uuid': uuid1,
- 'request_id': ctxt1.request_id,
- 'user_id': ctxt1.user_id,
- 'project_id': ctxt1.project_id,
- 'start_time': timeutils.utcnow()}
- db.action_start(ctxt1, action_values)
+ expected = []
+
+ action_values = self._create_action_values(uuid1)
+ action = db.action_start(self.ctxt, action_values)
+ expected.append(action)
+
action_values['action'] = 'resize'
- db.action_start(ctxt1, action_values)
-
- action_values = {'action': 'reboot',
- 'instance_uuid': uuid2,
- 'request_id': ctxt2.request_id,
- 'user_id': ctxt2.user_id,
- 'project_id': ctxt2.project_id,
- 'start_time': timeutils.utcnow()}
+ action = db.action_start(self.ctxt, action_values)
+ expected.append(action)
+
+ # Create some extra actions
+ uuid2 = str(stdlib_uuid.uuid4())
+ ctxt2 = context.get_admin_context()
+ action_values = self._create_action_values(uuid2, 'reboot', ctxt2)
db.action_start(ctxt2, action_values)
db.action_start(ctxt2, action_values)
# Retrieve the action to ensure it was successfully added
- actions = db.actions_get(ctxt1, uuid1)
- self.assertEqual(2, len(actions))
- self.assertEqual('resize', actions[0]['action'])
- self.assertEqual('run_instance', actions[1]['action'])
+ actions = db.actions_get(self.ctxt, uuid1)
+ self._assertEqualListsOfObjects(expected, actions)
def test_instance_action_get_by_instance_and_action(self):
"""Ensure we can get an action by instance UUID and action id."""
- ctxt1 = context.get_admin_context()
ctxt2 = context.get_admin_context()
uuid1 = str(stdlib_uuid.uuid4())
uuid2 = str(stdlib_uuid.uuid4())
- action_values = {'action': 'run_instance',
- 'instance_uuid': uuid1,
- 'request_id': ctxt1.request_id,
- 'user_id': ctxt1.user_id,
- 'project_id': ctxt1.project_id,
- 'start_time': timeutils.utcnow()}
- db.action_start(ctxt1, action_values)
+ action_values = self._create_action_values(uuid1)
+ db.action_start(self.ctxt, action_values)
action_values['action'] = 'resize'
- db.action_start(ctxt1, action_values)
-
- action_values = {'action': 'reboot',
- 'instance_uuid': uuid2,
- 'request_id': ctxt2.request_id,
- 'user_id': ctxt2.user_id,
- 'project_id': ctxt2.project_id,
- 'start_time': timeutils.utcnow()}
+ db.action_start(self.ctxt, action_values)
+
+ action_values = self._create_action_values(uuid2, 'reboot', ctxt2)
db.action_start(ctxt2, action_values)
db.action_start(ctxt2, action_values)
- actions = db.actions_get(ctxt1, uuid1)
+ actions = db.actions_get(self.ctxt, uuid1)
request_id = actions[0]['request_id']
- action = db.action_get_by_request_id(ctxt1, uuid1, request_id)
+ action = db.action_get_by_request_id(self.ctxt, uuid1, request_id)
self.assertEqual('run_instance', action['action'])
- self.assertEqual(ctxt1.request_id, action['request_id'])
+ self.assertEqual(self.ctxt.request_id, action['request_id'])
def test_instance_action_event_start(self):
"""Create an instance action event."""
- ctxt = context.get_admin_context()
uuid = str(stdlib_uuid.uuid4())
- start_time = timeutils.utcnow()
- action_values = {'action': 'run_instance',
- 'instance_uuid': uuid,
- 'request_id': ctxt.request_id,
- 'user_id': ctxt.user_id,
- 'project_id': ctxt.project_id,
- 'start_time': start_time}
- action = db.action_start(ctxt, action_values)
-
- event_values = {'event': 'schedule',
- 'instance_uuid': uuid,
- 'request_id': ctxt.request_id,
- 'start_time': start_time}
- db.action_event_start(ctxt, event_values)
+ action_values = self._create_action_values(uuid)
+ action = db.action_start(self.ctxt, action_values)
- # Retrieve the event to ensure it was successfully added
- events = db.action_events_get(ctxt, action['id'])
- self.assertEqual(1, len(events))
- self.assertEqual('schedule', events[0]['event'])
- self.assertEqual(start_time, events[0]['start_time'])
+ event_values = self._create_event_values(uuid)
+ event = db.action_event_start(self.ctxt, event_values)
+ # self.fail(self._dict_from_object(event, None))
+ event_values['action_id'] = action['id']
+ ignored = self.IGNORED_FIELDS + ['finish_time', 'traceback', 'result']
+ self._assertEqualObjects(event_values, event, ignored)
+
+ self._assertActionEventSaved(event, action['id'])
+
+ def test_instance_action_event_start_without_action(self):
+ """Create an instance action event."""
+ uuid = str(stdlib_uuid.uuid4())
+
+ event_values = self._create_event_values(uuid)
+ self.assertRaises(exception.InstanceActionNotFound,
+ db.action_event_start, self.ctxt, event_values)
+
+ def test_instance_action_event_finish_without_started_event(self):
+ """Finish an instance action event."""
+ uuid = str(stdlib_uuid.uuid4())
+
+ db.action_start(self.ctxt, self._create_action_values(uuid))
+
+ event_values = {
+ 'finish_time': timeutils.utcnow() + datetime.timedelta(seconds=5),
+ 'result': 'Success'
+ }
+ event_values = self._create_event_values(uuid, extra=event_values)
+ self.assertRaises(exception.InstanceActionEventNotFound,
+ db.action_event_finish, self.ctxt, event_values)
+
+ def test_instance_action_event_finish_without_action(self):
+ """Finish an instance action event."""
+ uuid = str(stdlib_uuid.uuid4())
+
+ event_values = {
+ 'finish_time': timeutils.utcnow() + datetime.timedelta(seconds=5),
+ 'result': 'Success'
+ }
+ event_values = self._create_event_values(uuid, extra=event_values)
+ self.assertRaises(exception.InstanceActionNotFound,
+ db.action_event_finish, self.ctxt, event_values)
def test_instance_action_event_finish_success(self):
"""Finish an instance action event."""
- ctxt = context.get_admin_context()
uuid = str(stdlib_uuid.uuid4())
- start_time = timeutils.utcnow()
- action_values = {'action': 'run_instance',
- 'instance_uuid': uuid,
- 'request_id': ctxt.request_id,
- 'user_id': ctxt.user_id,
- 'project_id': ctxt.project_id,
- 'start_time': start_time}
- action = db.action_start(ctxt, action_values)
-
- event_values = {'event': 'schedule',
- 'request_id': ctxt.request_id,
- 'instance_uuid': uuid,
- 'start_time': start_time}
- db.action_event_start(ctxt, event_values)
-
- finish_time = timeutils.utcnow() + datetime.timedelta(seconds=5)
- event_finish_values = {'event': 'schedule',
- 'request_id': ctxt.request_id,
- 'instance_uuid': uuid,
- 'finish_time': finish_time,
- 'result': 'Success'}
- db.action_event_finish(ctxt, event_finish_values)
+ action = db.action_start(self.ctxt, self._create_action_values(uuid))
- # Retrieve the event to ensure it was successfully added
- events = db.action_events_get(ctxt, action['id'])
- action = db.action_get_by_request_id(ctxt, uuid, ctxt.request_id)
- self.assertEqual(1, len(events))
- self.assertEqual('schedule', events[0]['event'])
- self.assertEqual(start_time, events[0]['start_time'])
- self.assertEqual(finish_time, events[0]['finish_time'])
- self.assertNotEqual(action['message'], 'Error')
+ db.action_event_start(self.ctxt, self._create_event_values(uuid))
+
+ event_values = {
+ 'finish_time': timeutils.utcnow() + datetime.timedelta(seconds=5),
+ 'result': 'Success'
+ }
+ event_values = self._create_event_values(uuid, extra=event_values)
+ event = db.action_event_finish(self.ctxt, event_values)
+
+ self._assertActionEventSaved(event, action['id'])
+ action = db.action_get_by_request_id(self.ctxt, uuid,
+ self.ctxt.request_id)
+ self.assertNotEqual('Error', action['message'])
def test_instance_action_event_finish_error(self):
"""Finish an instance action event with an error."""
- ctxt = context.get_admin_context()
uuid = str(stdlib_uuid.uuid4())
- start_time = timeutils.utcnow()
- action_values = {'action': 'run_instance',
- 'instance_uuid': uuid,
- 'request_id': ctxt.request_id,
- 'user_id': ctxt.user_id,
- 'project_id': ctxt.project_id,
- 'start_time': start_time}
- action = db.action_start(ctxt, action_values)
-
- event_values = {'event': 'schedule',
- 'request_id': ctxt.request_id,
- 'instance_uuid': uuid,
- 'start_time': start_time}
- db.action_event_start(ctxt, event_values)
-
- finish_time = timeutils.utcnow() + datetime.timedelta(seconds=5)
- event_finish_values = {'event': 'schedule',
- 'request_id': ctxt.request_id,
- 'instance_uuid': uuid,
- 'finish_time': finish_time,
- 'result': 'Error'}
- db.action_event_finish(ctxt, event_finish_values)
+ action = db.action_start(self.ctxt, self._create_action_values(uuid))
- # Retrieve the event to ensure it was successfully added
- events = db.action_events_get(ctxt, action['id'])
- action = db.action_get_by_request_id(ctxt, uuid, ctxt.request_id)
- self.assertEqual(1, len(events))
- self.assertEqual('schedule', events[0]['event'])
- self.assertEqual(start_time, events[0]['start_time'])
- self.assertEqual(finish_time, events[0]['finish_time'])
- self.assertEqual(action['message'], 'Error')
+ db.action_event_start(self.ctxt, self._create_event_values(uuid))
+
+ event_values = {
+ 'finish_time': timeutils.utcnow() + datetime.timedelta(seconds=5),
+ 'result': 'Error'
+ }
+ event_values = self._create_event_values(uuid, extra=event_values)
+ event = db.action_event_finish(self.ctxt, event_values)
+
+ self._assertActionEventSaved(event, action['id'])
+ action = db.action_get_by_request_id(self.ctxt, uuid,
+ self.ctxt.request_id)
+ self.assertEqual('Error', action['message'])
def test_instance_action_and_event_start_string_time(self):
"""Create an instance action and event with a string start_time."""
- ctxt = context.get_admin_context()
uuid = str(stdlib_uuid.uuid4())
- start_time = timeutils.utcnow()
- start_time_str = timeutils.strtime(start_time)
- action_values = {'action': 'run_instance',
- 'instance_uuid': uuid,
- 'request_id': ctxt.request_id,
- 'user_id': ctxt.user_id,
- 'project_id': ctxt.project_id,
- 'start_time': start_time_str}
- action = db.action_start(ctxt, action_values)
-
- event_values = {'event': 'schedule',
- 'instance_uuid': uuid,
- 'request_id': ctxt.request_id,
- 'start_time': start_time_str}
- db.action_event_start(ctxt, event_values)
+ action = db.action_start(self.ctxt, self._create_action_values(uuid))
- # Retrieve the event to ensure it was successfully added
- events = db.action_events_get(ctxt, action['id'])
- self.assertEqual(1, len(events))
- self.assertEqual('schedule', events[0]['event'])
- # db api still returns models with datetime, not str, values
- self.assertEqual(start_time, events[0]['start_time'])
+ event_values = {'start_time': timeutils.strtime(timeutils.utcnow())}
+ event_values = self._create_event_values(uuid, extra=event_values)
+ event = db.action_event_start(self.ctxt, event_values)
+
+ self._assertActionEventSaved(event, action['id'])
def test_instance_action_event_get_by_id(self):
"""Get a specific instance action event."""
- ctxt1 = context.get_admin_context()
ctxt2 = context.get_admin_context()
uuid1 = str(stdlib_uuid.uuid4())
uuid2 = str(stdlib_uuid.uuid4())
- action_values = {'action': 'run_instance',
- 'instance_uuid': uuid1,
- 'request_id': ctxt1.request_id,
- 'user_id': ctxt1.user_id,
- 'project_id': ctxt1.project_id,
- 'start_time': timeutils.utcnow()}
- added_action = db.action_start(ctxt1, action_values)
-
- action_values = {'action': 'reboot',
- 'instance_uuid': uuid2,
- 'request_id': ctxt2.request_id,
- 'user_id': ctxt2.user_id,
- 'project_id': ctxt2.project_id,
- 'start_time': timeutils.utcnow()}
- db.action_start(ctxt2, action_values)
+ action = db.action_start(self.ctxt,
+ self._create_action_values(uuid1))
- start_time = timeutils.utcnow()
- event_values = {'event': 'schedule',
- 'instance_uuid': uuid1,
- 'request_id': ctxt1.request_id,
- 'start_time': start_time}
- added_event = db.action_event_start(ctxt1, event_values)
-
- event_values = {'event': 'reboot',
- 'instance_uuid': uuid2,
- 'request_id': ctxt2.request_id,
- 'start_time': timeutils.utcnow()}
+ db.action_start(ctxt2,
+ self._create_action_values(uuid2, 'reboot', ctxt2))
+
+ event = db.action_event_start(self.ctxt,
+ self._create_event_values(uuid1))
+
+ event_values = self._create_event_values(uuid2, 'reboot', ctxt2)
db.action_event_start(ctxt2, event_values)
# Retrieve the event to ensure it was successfully added
- event = db.action_event_get_by_id(ctxt1, added_action['id'],
- added_event['id'])
- self.assertEqual('schedule', event['event'])
- self.assertEqual(start_time, event['start_time'])
+ saved_event = db.action_event_get_by_id(self.ctxt,
+ action['id'],
+ event['id'])
+ self._assertEqualObjects(event, saved_event,
+ ['instance_uuid', 'request_id'])
class InstanceFaultTestCase(test.TestCase, ModelsObjectComparatorMixin):
@@ -3537,24 +3692,24 @@ class VolumeUsageDBApiTestCase(test.TestCase):
vol_usages = db.vol_get_usage_by_time(ctxt, start_time)
self.assertEqual(len(vol_usages), 0)
- vol_usage = db.vol_usage_update(ctxt, 1, rd_req=10, rd_bytes=20,
- wr_req=30, wr_bytes=40,
- instance_id='fake-instance-uuid1',
- project_id='fake-project-uuid1',
- user_id='fake-user-uuid1',
- availability_zone='fake-az')
- vol_usage = db.vol_usage_update(ctxt, 2, rd_req=100, rd_bytes=200,
- wr_req=300, wr_bytes=400,
- instance_id='fake-instance-uuid2',
- project_id='fake-project-uuid2',
- user_id='fake-user-uuid2',
- availability_zone='fake-az')
- vol_usage = db.vol_usage_update(ctxt, 1, rd_req=1000, rd_bytes=2000,
- wr_req=3000, wr_bytes=4000,
- instance_id='fake-instance-uuid1',
- project_id='fake-project-uuid1',
- user_id='fake-user-uuid1',
- availability_zone='fake-az')
+ db.vol_usage_update(ctxt, 1, rd_req=10, rd_bytes=20,
+ wr_req=30, wr_bytes=40,
+ instance_id='fake-instance-uuid1',
+ project_id='fake-project-uuid1',
+ user_id='fake-user-uuid1',
+ availability_zone='fake-az')
+ db.vol_usage_update(ctxt, 2, rd_req=100, rd_bytes=200,
+ wr_req=300, wr_bytes=400,
+ instance_id='fake-instance-uuid2',
+ project_id='fake-project-uuid2',
+ user_id='fake-user-uuid2',
+ availability_zone='fake-az')
+ db.vol_usage_update(ctxt, 1, rd_req=1000, rd_bytes=2000,
+ wr_req=3000, wr_bytes=4000,
+ instance_id='fake-instance-uuid1',
+ project_id='fake-project-uuid1',
+ user_id='fake-user-uuid1',
+ availability_zone='fake-az')
vol_usages = db.vol_get_usage_by_time(ctxt, start_time)
self.assertEqual(len(vol_usages), 2)
@@ -3576,44 +3731,44 @@ class VolumeUsageDBApiTestCase(test.TestCase):
timeutils.utcnow().AndReturn(now3)
self.mox.ReplayAll()
- vol_usage = db.vol_usage_update(ctxt, 1, rd_req=100, rd_bytes=200,
- wr_req=300, wr_bytes=400,
- instance_id='fake-instance-uuid',
- project_id='fake-project-uuid',
- user_id='fake-user-uuid',
- availability_zone='fake-az')
+ db.vol_usage_update(ctxt, 1, rd_req=100, rd_bytes=200,
+ wr_req=300, wr_bytes=400,
+ instance_id='fake-instance-uuid',
+ project_id='fake-project-uuid',
+ user_id='fake-user-uuid',
+ availability_zone='fake-az')
current_usage = db.vol_get_usage_by_time(ctxt, start_time)[0]
self.assertEqual(current_usage['tot_reads'], 0)
self.assertEqual(current_usage['curr_reads'], 100)
- vol_usage = db.vol_usage_update(ctxt, 1, rd_req=200, rd_bytes=300,
- wr_req=400, wr_bytes=500,
- instance_id='fake-instance-uuid',
- project_id='fake-project-uuid',
- user_id='fake-user-uuid',
- availability_zone='fake-az',
- update_totals=True)
+ db.vol_usage_update(ctxt, 1, rd_req=200, rd_bytes=300,
+ wr_req=400, wr_bytes=500,
+ instance_id='fake-instance-uuid',
+ project_id='fake-project-uuid',
+ user_id='fake-user-uuid',
+ availability_zone='fake-az',
+ update_totals=True)
current_usage = db.vol_get_usage_by_time(ctxt, start_time)[0]
self.assertEqual(current_usage['tot_reads'], 200)
self.assertEqual(current_usage['curr_reads'], 0)
- vol_usage = db.vol_usage_update(ctxt, 1, rd_req=300, rd_bytes=400,
- wr_req=500, wr_bytes=600,
- instance_id='fake-instance-uuid',
- project_id='fake-project-uuid',
- availability_zone='fake-az',
- user_id='fake-user-uuid')
+ db.vol_usage_update(ctxt, 1, rd_req=300, rd_bytes=400,
+ wr_req=500, wr_bytes=600,
+ instance_id='fake-instance-uuid',
+ project_id='fake-project-uuid',
+ availability_zone='fake-az',
+ user_id='fake-user-uuid')
current_usage = db.vol_get_usage_by_time(ctxt, start_time)[0]
self.assertEqual(current_usage['tot_reads'], 200)
self.assertEqual(current_usage['curr_reads'], 300)
- vol_usage = db.vol_usage_update(ctxt, 1, rd_req=400, rd_bytes=500,
- wr_req=600, wr_bytes=700,
- instance_id='fake-instance-uuid',
- project_id='fake-project-uuid',
- user_id='fake-user-uuid',
- availability_zone='fake-az',
- update_totals=True)
+ db.vol_usage_update(ctxt, 1, rd_req=400, rd_bytes=500,
+ wr_req=600, wr_bytes=700,
+ instance_id='fake-instance-uuid',
+ project_id='fake-project-uuid',
+ user_id='fake-user-uuid',
+ availability_zone='fake-az',
+ update_totals=True)
vol_usages = db.vol_get_usage_by_time(ctxt, start_time)
@@ -3830,12 +3985,15 @@ class BlockDeviceMappingTestCase(test.TestCase):
def test_block_device_mapping_update(self):
bdm = self._create_bdm({})
- db.block_device_mapping_update(self.ctxt, bdm['id'],
- {'destination_type': 'moon'},
- legacy=False)
+ result = db.block_device_mapping_update(
+ self.ctxt, bdm['id'], {'destination_type': 'moon'},
+ legacy=False)
uuid = bdm['instance_uuid']
bdm_real = db.block_device_mapping_get_all_by_instance(self.ctxt, uuid)
self.assertEqual(bdm_real[0]['destination_type'], 'moon')
+ # Also make sure the update call returned correct data
+ self.assertEqual(dict(bdm_real[0].iteritems()),
+ dict(result.iteritems()))
def test_block_device_mapping_update_or_create(self):
values = {
@@ -4555,7 +4713,7 @@ class QuotaTestCase(test.TestCase, ModelsObjectComparatorMixin):
self.ctxt, 'p1', 'nonexitent_resource')
def test_quota_usage_get(self):
- reservations = _quota_reserve(self.ctxt, 'p1')
+ _quota_reserve(self.ctxt, 'p1')
quota_usage = db.quota_usage_get(self.ctxt, 'p1', 'res0')
expected = {'resource': 'res0', 'project_id': 'p1',
'in_use': 0, 'reserved': 0, 'total': 0}
@@ -4563,7 +4721,7 @@ class QuotaTestCase(test.TestCase, ModelsObjectComparatorMixin):
self.assertEqual(value, quota_usage[key])
def test_quota_usage_get_all_by_project(self):
- reservations = _quota_reserve(self.ctxt, 'p1')
+ _quota_reserve(self.ctxt, 'p1')
expected = {'project_id': 'p1',
'res0': {'in_use': 0, 'reserved': 0},
'res1': {'in_use': 1, 'reserved': 1},
@@ -4576,8 +4734,7 @@ class QuotaTestCase(test.TestCase, ModelsObjectComparatorMixin):
self.ctxt, 'p1', 'resource', in_use=42)
def test_quota_usage_update(self):
- reservations = _quota_reserve(self.ctxt, 'p1')
- until_refresh = datetime.datetime.now() + datetime.timedelta(days=1)
+ _quota_reserve(self.ctxt, 'p1')
db.quota_usage_update(self.ctxt, 'p1', 'res0', in_use=42, reserved=43)
quota_usage = db.quota_usage_get(self.ctxt, 'p1', 'res0')
expected = {'resource': 'res0', 'project_id': 'p1',
@@ -4633,7 +4790,7 @@ class QuotaClassTestCase(test.TestCase, ModelsObjectComparatorMixin):
'resource0': 0, 'resource1': 1, 'resource2': 2})
def test_quota_class_update(self):
- qc = db.quota_class_create(self.ctxt, 'class name', 'resource', 42)
+ db.quota_class_create(self.ctxt, 'class name', 'resource', 42)
db.quota_class_update(self.ctxt, 'class name', 'resource', 43)
self.assertEqual(db.quota_class_get(self.ctxt, 'class name',
'resource').hard_limit, 43)
@@ -4792,6 +4949,19 @@ class ComputeNodeTestCase(test.TestCase, ModelsObjectComparatorMixin):
self.assertNotEqual(self.item['updated_at'],
item_updated['updated_at'])
+ def test_compute_node_update_override_updated_at(self):
+ # Update the record once so updated_at is set.
+ first = db.compute_node_update(self.ctxt, self.item['id'],
+ {'free_ram_mb': '12'})
+ self.assertIsNotNone(first['updated_at'])
+
+ # Update a second time. Make sure that the updated_at value we send
+ # is overridden.
+ second = db.compute_node_update(self.ctxt, self.item['id'],
+ {'updated_at': first.updated_at,
+ 'free_ram_mb': '13'})
+ self.assertNotEqual(first['updated_at'], second['updated_at'])
+
def test_compute_node_stat_unchanged(self):
# don't update unchanged stat values:
stats = self.item['stats']
@@ -4866,6 +5036,49 @@ class ProviderFwRuleTestCase(test.TestCase, ModelsObjectComparatorMixin):
self.assertEqual([], db.provider_fw_rule_get_all(self.ctxt))
+class CertificateTestCase(test.TestCase, ModelsObjectComparatorMixin):
+
+ def setUp(self):
+ super(CertificateTestCase, self).setUp()
+ self.ctxt = context.get_admin_context()
+ self.created = self._certificates_create()
+
+ def _get_certs_values(self):
+ base_values = {
+ 'user_id': 'user',
+ 'project_id': 'project',
+ 'file_name': 'filename'
+ }
+ return [dict((k, v + str(x)) for k, v in base_values.iteritems())
+ for x in xrange(1, 4)]
+
+ def _certificates_create(self):
+ return [db.certificate_create(self.ctxt, cert)
+ for cert in self._get_certs_values()]
+
+ def test_certificate_create(self):
+ ignored_keys = ['id', 'deleted', 'deleted_at', 'created_at',
+ 'updated_at']
+ for i, cert in enumerate(self._get_certs_values()):
+ self._assertEqualObjects(self.created[i], cert,
+ ignored_keys=ignored_keys)
+
+ def test_certificate_get_all_by_project(self):
+ cert = db.certificate_get_all_by_project(self.ctxt,
+ self.created[1].project_id)
+ self._assertEqualObjects(self.created[1], cert[0])
+
+ def test_certificate_get_all_by_user(self):
+ cert = db.certificate_get_all_by_user(self.ctxt,
+ self.created[1].user_id)
+ self._assertEqualObjects(self.created[1], cert[0])
+
+ def test_certificate_get_all_by_user_and_project(self):
+ cert = db.certificate_get_all_by_user_and_project(self.ctxt,
+ self.created[1].user_id, self.created[1].project_id)
+ self._assertEqualObjects(self.created[1], cert[0])
+
+
class CellTestCase(test.TestCase, ModelsObjectComparatorMixin):
_ignored_keys = ['id', 'deleted', 'deleted_at', 'created_at', 'updated_at']
diff --git a/nova/tests/db/test_migration_utils.py b/nova/tests/db/test_migration_utils.py
index 3674a7c45..af206632d 100644
--- a/nova/tests/db/test_migration_utils.py
+++ b/nova/tests/db/test_migration_utils.py
@@ -19,7 +19,7 @@ import warnings
from migrate.changeset import UniqueConstraint
from sqlalchemy.dialects import mysql
from sqlalchemy import Boolean, Index, Integer, DateTime, String
-from sqlalchemy import MetaData, Table, Column
+from sqlalchemy import MetaData, Table, Column, ForeignKey
from sqlalchemy.engine import reflection
from sqlalchemy.exc import NoSuchTableError
from sqlalchemy.exc import SAWarning
@@ -514,3 +514,28 @@ class TestMigrationUtils(test_migrations.BaseMigrationTestCase):
# but sqlalchemy will set it to NullType.
self.assertTrue(isinstance(table.c.foo.type, NullType))
self.assertTrue(isinstance(table.c.deleted.type, Boolean))
+
+ def test_drop_unique_constraint_in_sqlite_fk_recreate(self):
+ engine = self.engines['sqlite']
+ meta = MetaData()
+ meta.bind = engine
+ parent_table = Table('table0', meta,
+ Column('id', Integer, primary_key=True),
+ Column('foo', Integer))
+ parent_table.create()
+ table_name = 'table1'
+ table = Table(table_name, meta,
+ Column('id', Integer, primary_key=True),
+ Column('baz', Integer),
+ Column('bar', Integer, ForeignKey("table0.id")),
+ UniqueConstraint('baz', name='constr1'))
+ table.create()
+ utils.drop_unique_constraint(engine, table_name, 'constr1', 'baz')
+
+ insp = reflection.Inspector.from_engine(engine)
+ f_keys = insp.get_foreign_keys(table_name)
+ self.assertEqual(len(f_keys), 1)
+ f_key = f_keys[0]
+ self.assertEqual(f_key['referred_table'], 'table0')
+ self.assertEqual(f_key['referred_columns'], ['id'])
+ self.assertEqual(f_key['constrained_columns'], ['bar'])
diff --git a/nova/tests/db/test_migrations.py b/nova/tests/db/test_migrations.py
index 812f0d8ae..7e28fb1d5 100644
--- a/nova/tests/db/test_migrations.py
+++ b/nova/tests/db/test_migrations.py
@@ -806,8 +806,6 @@ class TestNovaMigrations(BaseMigrationTestCase, CommonTestsMixIn):
def _check_153(self, engine, data):
fake_types, fake_instances = data
# NOTE(danms): Fetch all the tables and data from scratch after change
- instances = db_utils.get_table(engine, 'instances')
- instance_types = db_utils.get_table(engine, 'instance_types')
sys_meta = db_utils.get_table(engine, 'instance_system_metadata')
# Collect all system metadata, indexed by instance_uuid
@@ -1073,7 +1071,6 @@ class TestNovaMigrations(BaseMigrationTestCase, CommonTestsMixIn):
for result in results:
the_id = result['id']
key = result['key']
- value = result['value']
original = data[the_id]
if key == 'instance_type_baz':
@@ -1775,6 +1772,13 @@ class TestBaremetalMigrations(BaseMigrationTestCase, CommonTestsMixIn):
columns = [c.name for c in bm_nodes.columns]
self.assertNotIn(u'prov_mac_address', columns)
+ def _check_008(self, engine, data):
+ self.assertRaises(sqlalchemy.exc.NoSuchTableError,
+ db_utils.get_table, engine, 'bm_pxe_ips')
+
+ def _post_downgrade_008(self, engine):
+ db_utils.get_table(engine, 'bm_pxe_ips')
+
class ProjectTestCase(test.TestCase):
diff --git a/nova/tests/fake_network.py b/nova/tests/fake_network.py
index 79af362bb..f4e8d3841 100644
--- a/nova/tests/fake_network.py
+++ b/nova/tests/fake_network.py
@@ -27,6 +27,9 @@ from nova.network import manager as network_manager
from nova.network import model as network_model
from nova.network import nova_ipam_lib
from nova.network import rpcapi as network_rpcapi
+from nova.objects import base as obj_base
+from nova.objects import instance_info_cache
+from nova.openstack.common import jsonutils
from nova.virt.libvirt import config as libvirt_config
@@ -456,7 +459,7 @@ def _get_fake_cache():
ipv6_addr = 'fe80:b33f::a8bb:ccff:fedd:eeff'
info[0]['network']['subnets'].append({'cidr': 'fe80:b33f::/64',
'ips': [_ip(ipv6_addr)]})
- return info
+ return jsonutils.dumps(info)
def _get_instances_with_cached_ips(orig_func, *args, **kwargs):
@@ -464,9 +467,22 @@ def _get_instances_with_cached_ips(orig_func, *args, **kwargs):
entries
"""
instances = orig_func(*args, **kwargs)
- if isinstance(instances, list):
+ context = args[0]
+
+ def _info_cache_for(instance):
+ info_cache = {'network_info': _get_fake_cache(),
+ 'instance_uuid': instance['uuid']}
+ if isinstance(instance, obj_base.NovaObject):
+ _info_cache = instance_info_cache.InstanceInfoCache()
+ instance_info_cache.InstanceInfoCache._from_db_object(context,
+ _info_cache,
+ info_cache)
+ info_cache = _info_cache
+ instance['info_cache'] = info_cache
+
+ if isinstance(instances, (list, obj_base.ObjectListBase)):
for instance in instances:
- instance['info_cache'] = {'network_info': _get_fake_cache()}
+ _info_cache_for(instance)
else:
- instances['info_cache'] = {'network_info': _get_fake_cache()}
+ _info_cache_for(instances)
return instances
diff --git a/nova/tests/fake_policy.py b/nova/tests/fake_policy.py
index ed8cc7424..cbd856f4b 100644
--- a/nova/tests/fake_policy.py
+++ b/nova/tests/fake_policy.py
@@ -111,7 +111,9 @@ policy_data = """
"compute_extension:attach_interfaces": "",
"compute_extension:baremetal_nodes": "",
"compute_extension:cells": "",
+ "compute_extension:v3:os-cells": "",
"compute_extension:certificates": "",
+ "compute_extension:v3:os-certificates": "",
"compute_extension:cloudpipe": "",
"compute_extension:cloudpipe_update": "",
"compute_extension:config_drive": "",
@@ -122,6 +124,7 @@ policy_data = """
"compute_extension:deferred_delete": "",
"compute_extension:disk_config": "",
"compute_extension:evacuate": "is_admin:True",
+ "compute_extension:v3:os-evacuate": "is_admin:True",
"compute_extension:extended_server_attributes": "",
"compute_extension:extended_status": "",
"compute_extension:extended_availability_zone": "",
@@ -131,7 +134,9 @@ policy_data = """
"compute_extension:fixed_ips": "",
"compute_extension:v3:os-fixed-ips": "",
"compute_extension:flavor_access": "",
+ "compute_extension:v3:os-flavor-access": "",
"compute_extension:flavor_disabled": "",
+ "compute_extension:v3:os-flavor-disabled": "",
"compute_extension:flavor_rxtx": "",
"compute_extension:flavor_swap": "",
"compute_extension:flavorextradata": "",
@@ -151,6 +156,7 @@ policy_data = """
"compute_extension:hosts": "",
"compute_extension:hypervisors": "",
"compute_extension:image_size": "",
+ "compute_extension:v3:os-images": "",
"compute_extension:instance_actions": "",
"compute_extension:instance_actions:events": "is_admin:True",
"compute_extension:instance_usage_audit_log": "",
@@ -164,11 +170,16 @@ policy_data = """
"compute_extension:quotas:show": "",
"compute_extension:quotas:update": "",
"compute_extension:quotas:delete": "",
+ "compute_extension:v3:os-quota-sets:show": "",
+ "compute_extension:v3:os-quota-sets:update": "",
+ "compute_extension:v3:os-quota-sets:delete": "",
"compute_extension:quota_classes": "",
"compute_extension:rescue": "",
+ "compute_extension:v3:os-rescue": "",
"compute_extension:security_group_default_rules": "",
"compute_extension:security_groups": "",
"compute_extension:server_diagnostics": "",
+ "compute_extension:v3:os-server-diagnostics": "",
"compute_extension:server_password": "",
"compute_extension:server_usage": "",
"compute_extension:services": "",
diff --git a/nova/tests/integrated/test_api_samples.py b/nova/tests/integrated/test_api_samples.py
index 87ed6c6ce..00a989a70 100644
--- a/nova/tests/integrated/test_api_samples.py
+++ b/nova/tests/integrated/test_api_samples.py
@@ -47,7 +47,7 @@ from nova.openstack.common import jsonutils
from nova.openstack.common import log as logging
from nova.openstack.common import timeutils
import nova.quota
-from nova.scheduler import driver
+from nova.scheduler import manager as scheduler_manager
from nova.servicegroup import api as service_group_api
from nova import test
from nova.tests.api.openstack.compute.contrib import test_coverage_ext
@@ -2213,23 +2213,13 @@ class AdminActionsSamplesJsonTest(ServersSampleBase):
def test_post_live_migrate_server(self):
# Get api samples to server live migrate request.
- def fake_live_migration_src_check(self, context, instance_ref):
- """Skip live migration scheduler checks."""
+ def fake_live_migration(self, context, instance, dest,
+ block_migration, disk_over_commit):
return
- def fake_live_migration_dest_check(self, context, instance_ref, dest):
- """Skip live migration scheduler checks."""
- return dest
-
- def fake_live_migration_common(self, context, instance_ref, dest):
- """Skip live migration scheduler checks."""
- return
- self.stubs.Set(driver.Scheduler, '_live_migration_src_check',
- fake_live_migration_src_check)
- self.stubs.Set(driver.Scheduler, '_live_migration_dest_check',
- fake_live_migration_dest_check)
- self.stubs.Set(driver.Scheduler, '_live_migration_common_check',
- fake_live_migration_common)
+ self.stubs.Set(scheduler_manager.SchedulerManager,
+ 'live_migration',
+ fake_live_migration)
def fake_get_compute(context, host):
service = dict(host=host,
@@ -3194,7 +3184,7 @@ class ExtendedAvailabilityZoneJsonTests(ServersSampleBase):
self._verify_response('server-get-resp', subs, response, 200)
def test_detail(self):
- uuid = self._post_server()
+ self._post_server()
response = self._do_get('servers/detail')
subs = self._get_regexes()
subs['hostid'] = '[a-f0-9]+'
@@ -3422,18 +3412,18 @@ class ConfigDriveSampleJsonTest(ServersSampleBase):
response = self._do_get('servers/%s' % uuid)
subs = self._get_regexes()
subs['hostid'] = '[a-f0-9]+'
- # config drive can be an uuid or empty value
- subs['cdrive'] = '(%s)?' % subs['uuid']
+ # config drive can be a string for True or empty value for False
+ subs['cdrive'] = '.*'
self._verify_response('server-config-drive-get-resp', subs,
response, 200)
def test_config_drive_detail(self):
- uuid = self._post_server()
+ self._post_server()
response = self._do_get('servers/detail')
subs = self._get_regexes()
subs['hostid'] = '[a-f0-9]+'
- # config drive can be an uuid or empty value
- subs['cdrive'] = '(%s)?' % subs['uuid']
+ # config drive can be a string for True or empty value for False
+ subs['cdrive'] = '.*'
self._verify_response('servers-config-drive-details-resp',
subs, response, 200)
@@ -3506,7 +3496,7 @@ class FlavorAccessSampleJsonTests(ApiSampleTestBase):
def test_flavor_access_add_tenant(self):
self._create_flavor()
- response = self._add_tenant()
+ self._add_tenant()
def test_flavor_access_remove_tenant(self):
self._create_flavor()
diff --git a/nova/tests/network/test_linux_net.py b/nova/tests/network/test_linux_net.py
index 5c7f3828d..e8368d06a 100644
--- a/nova/tests/network/test_linux_net.py
+++ b/nova/tests/network/test_linux_net.py
@@ -861,7 +861,6 @@ class LinuxNetworkTestCase(test.TestCase):
self.stubs.Set(ln, 'ensure_ebtables_rules', lambda *a, **kw: None)
net = {'bridge': 'br100', 'cidr': '10.0.0.0/24'}
ln.ensure_floating_forward('10.10.10.10', '10.0.0.1', 'eth0', net)
- one_forward_rules = len(linux_net.iptables_manager.ipv4['nat'].rules)
ln.ensure_floating_forward('10.10.10.11', '10.0.0.10', 'eth0', net)
two_forward_rules = len(linux_net.iptables_manager.ipv4['nat'].rules)
ln.ensure_floating_forward('10.10.10.10', '10.0.0.3', 'eth0', net)
diff --git a/nova/tests/network/test_network_info.py b/nova/tests/network/test_network_info.py
index bb3d91f55..38a27b51c 100644
--- a/nova/tests/network/test_network_info.py
+++ b/nova/tests/network/test_network_info.py
@@ -372,7 +372,7 @@ class NetworkInfoTests(test.TestCase):
ninfo = model.NetworkInfo([fake_network_cache_model.new_vif(),
fake_network_cache_model.new_vif(
{'address': 'bb:bb:bb:bb:bb:bb'})])
- deserialized = model.NetworkInfo.hydrate(ninfo)
+ model.NetworkInfo.hydrate(ninfo)
self.assertEqual(ninfo.fixed_ips(),
[fake_network_cache_model.new_ip({'address': '10.10.0.2'}),
fake_network_cache_model.new_ip(
diff --git a/nova/tests/network/test_quantumv2.py b/nova/tests/network/test_quantumv2.py
index 0b6f184ae..2ddeb72bf 100644
--- a/nova/tests/network/test_quantumv2.py
+++ b/nova/tests/network/test_quantumv2.py
@@ -19,8 +19,6 @@ import uuid
import mox
from oslo.config import cfg
-from quantumclient import client as quantum_client
-from quantumclient.common import exceptions as quantum_exceptions
from quantumclient.v2_0 import client
from nova.compute import flavors
@@ -104,17 +102,6 @@ class TestQuantumClient(test.TestCase):
self.mox.ReplayAll()
quantumv2.get_client(my_context)
- def test_cached_admin_client(self):
- self.mox.StubOutWithMock(quantum_client.HTTPClient, "authenticate")
-
- # should be called one time only
- quantum_client.HTTPClient.authenticate()
- self.mox.ReplayAll()
-
- admin1 = quantumv2.get_client(None, admin=True)
- admin2 = quantumv2.get_client(None, admin=True)
- self.assertIs(admin1, admin2)
-
def test_withouttoken_keystone_connection_error(self):
self.flags(quantum_auth_strategy='keystone')
self.flags(quantum_url='http://anyhost/')
@@ -727,7 +714,6 @@ class TestQuantumv2(test.TestCase):
port_data = number == 1 and self.port_data1 or self.port_data2
self.moxed_client.delete_port(port_data[0]['id'])
- nets = [port_data[0]['network_id']]
quantumv2.get_client(mox.IgnoreArg(), admin=True).AndReturn(
self.moxed_client)
self.moxed_client.list_ports(
@@ -1069,7 +1055,6 @@ class TestQuantumv2(test.TestCase):
def test_allocate_floating_ip_with_pool_id(self):
api = quantumapi.API()
- pool_name = self.fip_pool['name']
pool_id = self.fip_pool['id']
search_opts = {'router:external': True,
'fields': 'id',
@@ -1113,7 +1098,6 @@ class TestQuantumv2(test.TestCase):
def test_release_floating_ip_associated(self):
api = quantumapi.API()
address = self.fip_associated['floating_ip_address']
- fip_id = self.fip_associated['id']
self.moxed_client.list_floatingips(floating_ip_address=address).\
AndReturn({'floatingips': [self.fip_associated]})
@@ -1157,7 +1141,6 @@ class TestQuantumv2(test.TestCase):
api = quantumapi.API()
address = self.fip_associated['floating_ip_address']
fixed_address = self.fip_associated['fixed_ip_address']
- fip_id = self.fip_associated['id']
search_opts = {'device_owner': 'compute:nova',
'device_id': self.instance['uuid']}
@@ -1191,7 +1174,6 @@ class TestQuantumv2(test.TestCase):
self.moxed_client.list_subnets(
**search_opts).AndReturn({'subnets': self.subnet_data_n})
- zone = 'compute:%s' % self.instance['availability_zone']
search_opts = {'device_id': self.instance['uuid'],
'device_owner': 'compute:nova',
'network_id': network_id}
@@ -1236,7 +1218,7 @@ class TestQuantumv2(test.TestCase):
def test_list_floating_ips_without_l3_support(self):
api = quantumapi.API()
- QuantumNotFound = quantum_exceptions.QuantumClientException(
+ QuantumNotFound = quantumv2.exceptions.QuantumClientException(
status_code=404)
self.moxed_client.list_floatingips(
fixed_ip_address='1.1.1.1', port_id=1).AndRaise(QuantumNotFound)
@@ -1370,6 +1352,13 @@ class TestQuantumv2(test.TestCase):
self.assertEqual(nw_info[0]['type'], model.VIF_TYPE_BRIDGE)
self.assertEqual(nw_info[0]['network']['bridge'], 'brqnet-id')
+ def test_get_all_empty_list_networks(self):
+ api = quantumapi.API()
+ self.moxed_client.list_networks().AndReturn({'networks': []})
+ self.mox.ReplayAll()
+ networks = api.get_all(self.context)
+ self.assertEqual(networks, [])
+
class TestQuantumv2ModuleMethods(test.TestCase):
def test_ensure_requested_network_ordering_no_preference_ids(self):
diff --git a/nova/tests/objects/test_instance.py b/nova/tests/objects/test_instance.py
index fa0a536fd..9f222951a 100644
--- a/nova/tests/objects/test_instance.py
+++ b/nova/tests/objects/test_instance.py
@@ -20,8 +20,12 @@ from nova import context
from nova import db
from nova.objects import base
from nova.objects import instance
+from nova.objects import security_group
from nova.openstack.common import timeutils
+from nova import test
from nova.tests.api.openstack import fakes
+from nova.tests import fake_instance
+from nova.tests.objects import test_instance_fault
from nova.tests.objects import test_objects
@@ -41,6 +45,7 @@ class _TestInstanceObject(object):
tzinfo=iso8601.iso8601.Utc(), microsecond=0))
fake_instance['deleted'] = False
fake_instance['info_cache']['instance_uuid'] = fake_instance['uuid']
+ fake_instance['security_groups'] = None
return fake_instance
def test_datetime_deserialization(self):
@@ -90,7 +95,7 @@ class _TestInstanceObject(object):
self.mox.StubOutWithMock(db, 'instance_get_by_uuid')
db.instance_get_by_uuid(ctxt, 'uuid', []).AndReturn(self.fake_instance)
self.mox.ReplayAll()
- inst = instance.Instance.get_by_uuid(ctxt, uuid='uuid')
+ inst = instance.Instance.get_by_uuid(ctxt, 'uuid')
# Make sure these weren't loaded
for attr in instance.INSTANCE_OPTIONAL_FIELDS:
attrname = base.get_attrname(attr)
@@ -102,7 +107,7 @@ class _TestInstanceObject(object):
self.mox.StubOutWithMock(db, 'instance_get_by_uuid')
db.instance_get_by_uuid(
ctxt, 'uuid',
- instance.INSTANCE_OPTIONAL_FIELDS).AndReturn(self.fake_instance)
+ ['metadata', 'system_metadata']).AndReturn(self.fake_instance)
self.mox.ReplayAll()
inst = instance.Instance.get_by_uuid(
ctxt, 'uuid', expected_attrs=instance.INSTANCE_OPTIONAL_FIELDS)
@@ -213,6 +218,58 @@ class _TestInstanceObject(object):
inst.info_cache.network_info = 'bar'
inst.save()
+ def test_with_security_groups(self):
+ ctxt = context.get_admin_context()
+ fake_inst = dict(self.fake_instance)
+ fake_uuid = fake_inst['uuid']
+ fake_inst['security_groups'] = [
+ {'id': 1, 'name': 'secgroup1', 'description': 'fake-desc',
+ 'user_id': 'fake-user', 'project_id': 'fake_project',
+ 'created_at': None, 'updated_at': None, 'deleted_at': None,
+ 'deleted': False},
+ {'id': 2, 'name': 'secgroup2', 'description': 'fake-desc',
+ 'user_id': 'fake-user', 'project_id': 'fake_project',
+ 'created_at': None, 'updated_at': None, 'deleted_at': None,
+ 'deleted': False},
+ ]
+ self.mox.StubOutWithMock(db, 'instance_get_by_uuid')
+ self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
+ self.mox.StubOutWithMock(db, 'security_group_update')
+ db.instance_get_by_uuid(ctxt, fake_uuid, []).AndReturn(fake_inst)
+ db.security_group_update(ctxt, 1, {'description': 'changed'}
+ ).AndReturn(fake_inst['security_groups'][0])
+ self.mox.ReplayAll()
+ inst = instance.Instance.get_by_uuid(ctxt, fake_uuid)
+ self.assertEqual(len(inst.security_groups), 2)
+ for index, group in enumerate(fake_inst['security_groups']):
+ for key in group:
+ self.assertEqual(group[key],
+ inst.security_groups[index][key])
+ self.assertTrue(isinstance(inst.security_groups[index],
+ security_group.SecurityGroup))
+ self.assertEqual(inst.security_groups.obj_what_changed(), set())
+ inst.security_groups[0].description = 'changed'
+ inst.save()
+ self.assertEqual(inst.security_groups.obj_what_changed(), set())
+
+ def test_with_fault(self):
+ ctxt = context.get_admin_context()
+ fake_inst = dict(self.fake_instance)
+ fake_uuid = fake_inst['uuid']
+ fake_faults = [dict(x, instance_uuid=fake_uuid)
+ for x in test_instance_fault.fake_faults['fake-uuid']]
+ self.mox.StubOutWithMock(db, 'instance_get_by_uuid')
+ self.mox.StubOutWithMock(db, 'instance_fault_get_by_instance_uuids')
+ db.instance_get_by_uuid(ctxt, fake_uuid, []).AndReturn(
+ self.fake_instance)
+ db.instance_fault_get_by_instance_uuids(ctxt, [fake_uuid]).AndReturn(
+ {fake_uuid: fake_faults})
+ self.mox.ReplayAll()
+ inst = instance.Instance.get_by_uuid(ctxt, fake_uuid,
+ expected_attrs=['fault'])
+ self.assertEqual(fake_faults[0], dict(inst.fault.items()))
+ self.assertRemotes()
+
def test_iteritems_with_extra_attrs(self):
self.stubs.Set(instance.Instance, 'name', 'foo')
inst = instance.Instance()
@@ -248,6 +305,7 @@ class _TestInstanceListObject(object):
tzinfo=iso8601.iso8601.Utc(), microsecond=0))
fake_instance['info_cache'] = {'network_info': 'foo',
'instance_uuid': fake_instance['uuid']}
+ fake_instance['security_groups'] = []
fake_instance['deleted'] = 0
if updates:
fake_instance.update(updates)
@@ -258,7 +316,7 @@ class _TestInstanceListObject(object):
ctxt = context.get_admin_context()
self.mox.StubOutWithMock(db, 'instance_get_all_by_filters')
db.instance_get_all_by_filters(ctxt, {'foo': 'bar'}, 'uuid', 'asc',
- None, None,
+ limit=None, marker=None,
columns_to_join=['metadata']).AndReturn(
fakes)
self.mox.ReplayAll()
@@ -284,6 +342,7 @@ class _TestInstanceListObject(object):
self.assertTrue(isinstance(inst_list.objects[i],
instance.Instance))
self.assertEqual(inst_list.objects[i].uuid, fakes[i]['uuid'])
+ self.assertEqual(inst_list.objects[i]._context, ctxt)
self.assertEqual(inst_list.obj_what_changed(), set())
self.assertRemotes()
@@ -336,6 +395,27 @@ class _TestInstanceListObject(object):
self.assertEqual(inst_list.objects[i].uuid, fakes[i]['uuid'])
self.assertRemotes()
+ def test_with_fault(self):
+ ctxt = context.get_admin_context()
+ fake_insts = [
+ fake_instance.fake_db_instance(uuid='fake-uuid', host='host'),
+ fake_instance.fake_db_instance(uuid='fake-inst2', host='host'),
+ ]
+ fake_faults = test_instance_fault.fake_faults
+ self.mox.StubOutWithMock(db, 'instance_get_all_by_host')
+ self.mox.StubOutWithMock(db, 'instance_fault_get_by_instance_uuids')
+ db.instance_get_all_by_host(ctxt, 'host', columns_to_join=[]
+ ).AndReturn(fake_insts)
+ db.instance_fault_get_by_instance_uuids(
+ ctxt, [x['uuid'] for x in fake_insts]).AndReturn(fake_faults)
+ self.mox.ReplayAll()
+ instances = instance.InstanceList.get_by_host(ctxt, 'host',
+ expected_attrs=['fault'])
+ self.assertEqual(2, len(instances))
+ self.assertEqual(fake_faults['fake-uuid'][0],
+ dict(instances[0].fault.iteritems()))
+ self.assertEqual(None, instances[1].fault)
+
class TestInstanceListObject(test_objects._LocalTest,
_TestInstanceListObject):
@@ -345,3 +425,10 @@ class TestInstanceListObject(test_objects._LocalTest,
class TestRemoteInstanceListObject(test_objects._RemoteTest,
_TestInstanceListObject):
pass
+
+
+class TestInstanceObjectMisc(test.TestCase):
+ def test_expected_cols(self):
+ self.stubs.Set(instance, 'INSTANCE_OPTIONAL_NON_COLUMNS', ['bar'])
+ self.assertEqual(['foo'], instance.expected_cols(['foo', 'bar']))
+ self.assertEqual(None, instance.expected_cols(None))
diff --git a/nova/tests/objects/test_instance_fault.py b/nova/tests/objects/test_instance_fault.py
new file mode 100644
index 000000000..2f9840df1
--- /dev/null
+++ b/nova/tests/objects/test_instance_fault.py
@@ -0,0 +1,86 @@
+# Copyright 2013 IBM Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from nova import context
+from nova import db
+from nova.objects import instance_fault
+from nova.tests.objects import test_objects
+
+
+fake_faults = {
+ 'fake-uuid': [
+ {'id': 1, 'instance_uuid': 'fake-uuid', 'code': 123, 'message': 'msg1',
+ 'details': 'details', 'host': 'host', 'deleted': False,
+ 'created_at': None, 'updated_at': None, 'deleted_at': None},
+ {'id': 2, 'instance_uuid': 'fake-uuid', 'code': 456, 'message': 'msg2',
+ 'details': 'details', 'host': 'host', 'deleted': False,
+ 'created_at': None, 'updated_at': None, 'deleted_at': None},
+ ]
+ }
+
+
+class _TestInstanceFault(object):
+ def test_get_latest_for_instance(self):
+ ctxt = context.get_admin_context()
+ self.mox.StubOutWithMock(db, 'instance_fault_get_by_instance_uuids')
+ db.instance_fault_get_by_instance_uuids(ctxt, ['fake-uuid']).AndReturn(
+ fake_faults)
+ self.mox.ReplayAll()
+ fault = instance_fault.InstanceFault.get_latest_for_instance(
+ ctxt, 'fake-uuid')
+ for key in fake_faults['fake-uuid'][0]:
+ self.assertEqual(fake_faults['fake-uuid'][0][key], fault[key])
+
+ def test_get_latest_for_instance_with_none(self):
+ ctxt = context.get_admin_context()
+ self.mox.StubOutWithMock(db, 'instance_fault_get_by_instance_uuids')
+ db.instance_fault_get_by_instance_uuids(ctxt, ['fake-uuid']).AndReturn(
+ {})
+ self.mox.ReplayAll()
+ fault = instance_fault.InstanceFault.get_latest_for_instance(
+ ctxt, 'fake-uuid')
+ self.assertEqual(None, fault)
+
+ def test_get_by_instance(self):
+ ctxt = context.get_admin_context()
+ self.mox.StubOutWithMock(db, 'instance_fault_get_by_instance_uuids')
+ db.instance_fault_get_by_instance_uuids(ctxt, ['fake-uuid']).AndReturn(
+ fake_faults)
+ self.mox.ReplayAll()
+ faults = instance_fault.InstanceFaultList.get_by_instance_uuids(
+ ctxt, ['fake-uuid'])
+ for index, db_fault in enumerate(fake_faults['fake-uuid']):
+ for key in db_fault:
+ self.assertEqual(fake_faults['fake-uuid'][index][key],
+ faults[index][key])
+
+ def test_get_by_instance_with_none(self):
+ ctxt = context.get_admin_context()
+ self.mox.StubOutWithMock(db, 'instance_fault_get_by_instance_uuids')
+ db.instance_fault_get_by_instance_uuids(ctxt, ['fake-uuid']).AndReturn(
+ {})
+ self.mox.ReplayAll()
+ faults = instance_fault.InstanceFaultList.get_by_instance_uuids(
+ ctxt, ['fake-uuid'])
+ self.assertEqual(0, len(faults))
+
+
+class TestInstanceFault(test_objects._LocalTest,
+ _TestInstanceFault):
+ pass
+
+
+class TestInstanceFaultRemote(test_objects._RemoteTest,
+ _TestInstanceFault):
+ pass
diff --git a/nova/tests/objects/test_objects.py b/nova/tests/objects/test_objects.py
index 332833cb0..03a270386 100644
--- a/nova/tests/objects/test_objects.py
+++ b/nova/tests/objects/test_objects.py
@@ -178,6 +178,31 @@ class TestUtils(test.TestCase):
self.assertEqual(utils.dt_deserializer(None, None), None)
self.assertRaises(ValueError, utils.dt_deserializer, None, 'foo')
+ def test_obj_to_primitive_list(self):
+ class MyList(base.ObjectListBase, base.NovaObject):
+ pass
+ mylist = MyList()
+ mylist.objects = [1, 2, 3]
+ self.assertEqual([1, 2, 3], base.obj_to_primitive(mylist))
+
+ def test_obj_to_primitive_dict(self):
+ myobj = MyObj()
+ myobj.foo = 1
+ myobj.bar = 'foo'
+ self.assertEqual({'foo': 1, 'bar': 'foo'},
+ base.obj_to_primitive(myobj))
+
+ def test_obj_to_primitive_recursive(self):
+ class MyList(base.ObjectListBase, base.NovaObject):
+ pass
+
+ mylist = MyList()
+ mylist.objects = [MyObj(), MyObj()]
+ for i, value in enumerate(mylist):
+ value.foo = i
+ self.assertEqual([{'foo': 0}, {'foo': 1}],
+ base.obj_to_primitive(mylist))
+
class _BaseTestCase(test.TestCase):
def setUp(self):
@@ -441,6 +466,13 @@ class _TestObject(object):
}
self.assertEqual(obj.obj_to_primitive(), expected)
+ def test_contains(self):
+ obj = MyObj()
+ self.assertFalse('foo' in obj)
+ obj.foo = 1
+ self.assertTrue('foo' in obj)
+ self.assertFalse('does_not_exist' in obj)
+
class TestObject(_LocalTest, _TestObject):
pass
@@ -502,3 +534,40 @@ class TestObjectListBase(test.TestCase):
self.assertFalse(obj is obj2)
self.assertEqual([x.foo for x in obj],
[y.foo for y in obj2])
+
+
+class TestObjectSerializer(test.TestCase):
+ def test_serialize_entity_primitive(self):
+ ser = base.NovaObjectSerializer()
+ for thing in (1, 'foo', [1, 2], {'foo': 'bar'}):
+ self.assertEqual(thing, ser.serialize_entity(None, thing))
+
+ def test_deserialize_entity_primitive(self):
+ ser = base.NovaObjectSerializer()
+ for thing in (1, 'foo', [1, 2], {'foo': 'bar'}):
+ self.assertEqual(thing, ser.deserialize_entity(None, thing))
+
+ def test_object_serialization(self):
+ ser = base.NovaObjectSerializer()
+ ctxt = context.get_admin_context()
+ obj = MyObj()
+ primitive = ser.serialize_entity(ctxt, obj)
+ self.assertTrue('nova_object.name' in primitive)
+ obj2 = ser.deserialize_entity(ctxt, primitive)
+ self.assertTrue(isinstance(obj2, MyObj))
+ self.assertEqual(ctxt, obj2._context)
+
+ def test_object_serialization_iterables(self):
+ ser = base.NovaObjectSerializer()
+ ctxt = context.get_admin_context()
+ obj = MyObj()
+ for iterable in (list, tuple, set):
+ thing = iterable([obj])
+ primitive = ser.serialize_entity(ctxt, thing)
+ self.assertEqual(1, len(primitive))
+ for item in primitive:
+ self.assertFalse(isinstance(item, base.NovaObject))
+ thing2 = ser.deserialize_entity(ctxt, primitive)
+ self.assertEqual(1, len(thing2))
+ for item in thing2:
+ self.assertTrue(isinstance(item, MyObj))
diff --git a/nova/tests/objects/test_security_group.py b/nova/tests/objects/test_security_group.py
new file mode 100644
index 000000000..ee2f79ad7
--- /dev/null
+++ b/nova/tests/objects/test_security_group.py
@@ -0,0 +1,186 @@
+# Copyright 2013 IBM Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from nova import context
+from nova import db
+from nova.objects import instance
+from nova.objects import security_group
+from nova.tests.objects import test_objects
+
+
+fake_secgroup = {
+ 'created_at': None,
+ 'updated_at': None,
+ 'deleted_at': None,
+ 'deleted': None,
+ 'id': 1,
+ 'name': 'fake-name',
+ 'description': 'fake-desc',
+ 'user_id': 'fake-user',
+ 'project_id': 'fake-project',
+ }
+
+
+class _TestSecurityGroupObject(object):
+ def _fix_deleted(self, db_secgroup):
+ # NOTE(danms): Account for the difference in 'deleted'
+ return dict(db_secgroup.items(), deleted=False)
+
+ def test_get(self):
+ ctxt = context.get_admin_context()
+ self.mox.StubOutWithMock(db, 'security_group_get')
+ db.security_group_get(ctxt, 1).AndReturn(fake_secgroup)
+ self.mox.ReplayAll()
+ secgroup = security_group.SecurityGroup.get(ctxt, 1)
+ self.assertEqual(self._fix_deleted(fake_secgroup),
+ dict(secgroup.items()))
+ self.assertEqual(secgroup.obj_what_changed(), set())
+ self.assertRemotes()
+
+ def test_get_by_name(self):
+ ctxt = context.get_admin_context()
+ self.mox.StubOutWithMock(db, 'security_group_get_by_name')
+ db.security_group_get_by_name(ctxt, 'fake-project',
+ 'fake-name').AndReturn(fake_secgroup)
+ self.mox.ReplayAll()
+ secgroup = security_group.SecurityGroup.get_by_name(ctxt,
+ 'fake-project',
+ 'fake-name')
+ self.assertEqual(self._fix_deleted(fake_secgroup),
+ dict(secgroup.items()))
+ self.assertEqual(secgroup.obj_what_changed(), set())
+ self.assertRemotes()
+
+ def test_in_use(self):
+ ctxt = context.get_admin_context()
+ self.mox.StubOutWithMock(db, 'security_group_in_use')
+ db.security_group_in_use(ctxt, 123).AndReturn(True)
+ self.mox.ReplayAll()
+ secgroup = security_group.SecurityGroup()
+ secgroup.id = 123
+ self.assertTrue(secgroup.in_use(ctxt))
+ self.assertRemotes()
+
+ def test_save(self):
+ ctxt = context.get_admin_context()
+ self.mox.StubOutWithMock(db, 'security_group_update')
+ updated_secgroup = dict(fake_secgroup, project_id='changed')
+ db.security_group_update(ctxt, 1,
+ {'description': 'foobar'}).AndReturn(
+ updated_secgroup)
+ self.mox.ReplayAll()
+ secgroup = security_group.SecurityGroup._from_db_object(
+ security_group.SecurityGroup(), fake_secgroup)
+ secgroup.description = 'foobar'
+ secgroup.save(ctxt)
+ self.assertEqual(self._fix_deleted(updated_secgroup),
+ dict(secgroup.items()))
+ self.assertEqual(secgroup.obj_what_changed(), set())
+ self.assertRemotes()
+
+ def test_save_no_changes(self):
+ ctxt = context.get_admin_context()
+ self.mox.StubOutWithMock(db, 'security_group_update')
+ self.mox.ReplayAll()
+ secgroup = security_group.SecurityGroup._from_db_object(
+ security_group.SecurityGroup(), fake_secgroup)
+ secgroup.save(ctxt)
+
+ def test_refresh(self):
+ ctxt = context.get_admin_context()
+ updated_secgroup = dict(fake_secgroup, description='changed')
+ self.mox.StubOutWithMock(db, 'security_group_get')
+ db.security_group_get(ctxt, 1).AndReturn(updated_secgroup)
+ self.mox.ReplayAll()
+ secgroup = security_group.SecurityGroup._from_db_object(
+ security_group.SecurityGroup(), fake_secgroup)
+ secgroup.refresh(ctxt)
+ self.assertEqual(self._fix_deleted(updated_secgroup),
+ dict(secgroup.items()))
+ self.assertEqual(secgroup.obj_what_changed(), set())
+ self.assertRemotes()
+
+
+class TestSecurityGroupObject(test_objects._LocalTest,
+ _TestSecurityGroupObject):
+ pass
+
+
+class TestSecurityGroupObjectRemote(test_objects._RemoteTest,
+ _TestSecurityGroupObject):
+ pass
+
+
+fake_secgroups = [
+ dict(fake_secgroup, id=1, name='secgroup1'),
+ dict(fake_secgroup, id=2, name='secgroup2'),
+ ]
+
+
+class _TestSecurityGroupListObject(object):
+ def test_get_all(self):
+ ctxt = context.get_admin_context()
+ self.mox.StubOutWithMock(db, 'security_group_get_all')
+ db.security_group_get_all(ctxt).AndReturn(fake_secgroups)
+ self.mox.ReplayAll()
+ secgroup_list = security_group.SecurityGroupList.get_all(ctxt)
+ for i in range(len(fake_secgroups)):
+ self.assertTrue(isinstance(secgroup_list[i],
+ security_group.SecurityGroup))
+ self.assertEqual(fake_secgroups[i]['id'],
+ secgroup_list[i]['id'])
+ self.assertEqual(secgroup_list[i]._context, ctxt)
+
+ def test_get_by_project(self):
+ ctxt = context.get_admin_context()
+ self.mox.StubOutWithMock(db, 'security_group_get_by_project')
+ db.security_group_get_by_project(ctxt,
+ 'fake-project').AndReturn(
+ fake_secgroups)
+ self.mox.ReplayAll()
+ secgroup_list = security_group.SecurityGroupList.get_by_project(
+ ctxt, 'fake-project')
+ for i in range(len(fake_secgroups)):
+ self.assertTrue(isinstance(secgroup_list[i],
+ security_group.SecurityGroup))
+ self.assertEqual(fake_secgroups[i]['id'],
+ secgroup_list[i]['id'])
+
+ def test_get_by_instance(self):
+ ctxt = context.get_admin_context()
+
+ inst = instance.Instance()
+ inst.uuid = 'fake-inst-uuid'
+ self.mox.StubOutWithMock(db, 'security_group_get_by_instance')
+ db.security_group_get_by_instance(ctxt,
+ 'fake-inst-uuid').AndReturn(
+ fake_secgroups)
+ self.mox.ReplayAll()
+ secgroup_list = security_group.SecurityGroupList.get_by_instance(
+ ctxt, inst)
+ for i in range(len(fake_secgroups)):
+ self.assertTrue(isinstance(secgroup_list[i],
+ security_group.SecurityGroup))
+ self.assertEqual(fake_secgroups[i]['id'],
+ secgroup_list[i]['id'])
+
+
+class TestSecurityGroupListObject(test_objects._LocalTest,
+ _TestSecurityGroupListObject):
+ pass
+
+
+class TestSecurityGroupListObjectRemote(test_objects._RemoteTest,
+ _TestSecurityGroupListObject):
+ pass
diff --git a/nova/tests/scheduler/test_chance_scheduler.py b/nova/tests/scheduler/test_chance_scheduler.py
index cfe7f5d63..ba1701e93 100644
--- a/nova/tests/scheduler/test_chance_scheduler.py
+++ b/nova/tests/scheduler/test_chance_scheduler.py
@@ -68,15 +68,11 @@ class ChanceSchedulerTestCase(test_scheduler.SchedulerTestCase):
def test_basic_schedule_run_instance(self):
ctxt = context.RequestContext('fake', 'fake', False)
ctxt_elevated = 'fake-context-elevated'
- fake_args = (1, 2, 3)
instance_opts = {'fake_opt1': 'meow', 'launch_index': -1}
instance1 = {'uuid': 'fake-uuid1'}
instance2 = {'uuid': 'fake-uuid2'}
request_spec = {'instance_uuids': ['fake-uuid1', 'fake-uuid2'],
'instance_properties': instance_opts}
- instance1_encoded = {'uuid': 'fake-uuid1', '_is_precooked': False}
- instance2_encoded = {'uuid': 'fake-uuid2', '_is_precooked': False}
- reservations = ['resv1', 'resv2']
def inc_launch_index(*args):
request_spec['instance_properties']['launch_index'] = (
@@ -118,7 +114,6 @@ class ChanceSchedulerTestCase(test_scheduler.SchedulerTestCase):
def test_basic_schedule_run_instance_no_hosts(self):
ctxt = context.RequestContext('fake', 'fake', False)
ctxt_elevated = 'fake-context-elevated'
- fake_args = (1, 2, 3)
uuid = 'fake-uuid1'
instance_opts = {'fake_opt1': 'meow', 'launch_index': -1}
request_spec = {'instance_uuids': [uuid],
@@ -170,10 +165,7 @@ class ChanceSchedulerTestCase(test_scheduler.SchedulerTestCase):
def test_select_hosts(self):
ctxt = context.RequestContext('fake', 'fake', False)
ctxt_elevated = 'fake-context-elevated'
- fake_args = (1, 2, 3)
instance_opts = {'fake_opt1': 'meow', 'launch_index': -1}
- instance1 = {'uuid': 'fake-uuid1'}
- instance2 = {'uuid': 'fake-uuid2'}
request_spec = {'instance_uuids': ['fake-uuid1', 'fake-uuid2'],
'instance_properties': instance_opts}
diff --git a/nova/tests/scheduler/test_filter_scheduler.py b/nova/tests/scheduler/test_filter_scheduler.py
index d6cc7808e..ac2e73ec7 100644
--- a/nova/tests/scheduler/test_filter_scheduler.py
+++ b/nova/tests/scheduler/test_filter_scheduler.py
@@ -25,12 +25,10 @@ from nova.conductor import api as conductor_api
from nova import context
from nova import db
from nova import exception
-from nova.openstack.common import rpc
from nova.scheduler import driver
from nova.scheduler import filter_scheduler
from nova.scheduler import host_manager
from nova.scheduler import weights
-from nova import servicegroup
from nova.tests.scheduler import fakes
from nova.tests.scheduler import test_scheduler
@@ -393,143 +391,6 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
self.assertEqual([['host', 'node']],
filter_properties['retry']['hosts'])
- def test_live_migration_dest_check_service_memory_overcommit(self):
- instance = self._live_migration_instance()
-
- # Live-migration should work since default is to overcommit memory.
- self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
- self.mox.StubOutWithMock(db, 'service_get_by_compute_host')
- self.mox.StubOutWithMock(servicegroup.API, 'service_is_up')
- self.mox.StubOutWithMock(self.driver, '_get_compute_info')
- self.mox.StubOutWithMock(self.driver, '_live_migration_common_check')
- self.mox.StubOutWithMock(rpc, 'call')
- self.mox.StubOutWithMock(self.driver.compute_rpcapi, 'live_migration')
-
- dest = 'fake_host2'
- block_migration = False
- disk_over_commit = False
-
- self.driver._live_migration_src_check(self.context, instance)
- db.service_get_by_compute_host(self.context,
- dest).AndReturn('fake_service3')
- self.servicegroup_api.service_is_up('fake_service3').AndReturn(True)
-
- self.driver._get_compute_info(self.context, dest).AndReturn(
- {'memory_mb': 2048,
- 'free_disk_gb': 512,
- 'local_gb_used': 512,
- 'free_ram_mb': 512,
- 'local_gb': 1024,
- 'vcpus': 4,
- 'vcpus_used': 2,
- 'updated_at': None})
-
- self.driver._live_migration_common_check(self.context, instance, dest)
-
- rpc.call(self.context, "compute.fake_host2",
- {"method": 'check_can_live_migrate_destination',
- "namespace": None,
- "args": {'instance': instance,
- 'block_migration': block_migration,
- 'disk_over_commit': disk_over_commit},
- "version": compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION},
- None).AndReturn({})
-
- self.driver.compute_rpcapi.live_migration(self.context,
- host=instance['host'], instance=instance, dest=dest,
- block_migration=block_migration, migrate_data={})
-
- self.mox.ReplayAll()
- result = self.driver.schedule_live_migration(self.context,
- instance=instance, dest=dest,
- block_migration=block_migration,
- disk_over_commit=disk_over_commit)
- self.assertEqual(result, None)
-
- def test_live_migration_assert_memory_no_overcommit(self):
- # Test that memory check passes with no memory overcommit.
- def fake_get(context, host):
- return {'memory_mb': 2048,
- 'free_disk_gb': 512,
- 'local_gb_used': 512,
- 'free_ram_mb': 1024,
- 'local_gb': 1024,
- 'vcpus': 4,
- 'vcpus_used': 2,
- 'updated_at': None}
-
- self.stubs.Set(self.driver, '_get_compute_info', fake_get)
-
- self.flags(ram_allocation_ratio=1.0)
- instance = self._live_migration_instance()
- dest = 'fake_host2'
- result = self.driver._assert_compute_node_has_enough_memory(
- self.context, instance, dest)
- self.assertEqual(result, None)
-
- def test_live_migration_assert_memory_no_overcommit_lack_memory(self):
- # Test that memory check fails with no memory overcommit.
- def fake_get(context, host):
- return {'memory_mb': 2048,
- 'free_disk_gb': 512,
- 'local_gb_used': 512,
- 'free_ram_mb': 1023,
- 'local_gb': 1024,
- 'vcpus': 4,
- 'vcpus_used': 2,
- 'updated_at': None}
-
- self.stubs.Set(self.driver, '_get_compute_info', fake_get)
-
- self.flags(ram_allocation_ratio=1.0)
- instance = self._live_migration_instance()
- dest = 'fake_host2'
- self.assertRaises(exception.MigrationError,
- self.driver._assert_compute_node_has_enough_memory,
- context, instance, dest)
-
- def test_live_migration_assert_memory_overcommit(self):
- # Test that memory check passes with memory overcommit.
- def fake_get(context, host):
- return {'memory_mb': 2048,
- 'free_disk_gb': 512,
- 'local_gb_used': 512,
- 'free_ram_mb': -1024,
- 'local_gb': 1024,
- 'vcpus': 4,
- 'vcpus_used': 2,
- 'updated_at': None}
-
- self.stubs.Set(self.driver, '_get_compute_info', fake_get)
-
- self.flags(ram_allocation_ratio=2.0)
- instance = self._live_migration_instance()
- dest = 'fake_host2'
- result = self.driver._assert_compute_node_has_enough_memory(
- self.context, instance, dest)
- self.assertEqual(result, None)
-
- def test_live_migration_assert_memory_overcommit_lack_memory(self):
- # Test that memory check fails with memory overcommit.
- def fake_get(context, host):
- return {'memory_mb': 2048,
- 'free_disk_gb': 512,
- 'local_gb_used': 512,
- 'free_ram_mb': -1025,
- 'local_gb': 1024,
- 'vcpus': 4,
- 'vcpus_used': 2,
- 'updated_at': None}
-
- self.stubs.Set(self.driver, '_get_compute_info', fake_get)
-
- self.flags(ram_allocation_ratio=2.0)
- instance = self._live_migration_instance()
- dest = 'fake_host2'
- self.assertRaises(exception.MigrationError,
- self.driver._assert_compute_node_has_enough_memory,
- self.context, instance, dest)
-
def test_basic_schedule_run_instances_anti_affinity(self):
filter_properties = {'scheduler_hints':
{'group': 'cats'}}
diff --git a/nova/tests/scheduler/test_host_filters.py b/nova/tests/scheduler/test_host_filters.py
index b09e23f1d..8832f5c2b 100644
--- a/nova/tests/scheduler/test_host_filters.py
+++ b/nova/tests/scheduler/test_host_filters.py
@@ -316,9 +316,6 @@ class HostFiltersTestCase(test.NoDBTestCase):
def test_affinity_different_filter_handles_none(self):
filt_cls = self.class_map['DifferentHostFilter']()
host = fakes.FakeHostState('host1', 'node1', {})
- instance = fakes.FakeInstance(context=self.context,
- params={'host': 'host2'})
- instance_uuid = instance.uuid
filter_properties = {'context': self.context.elevated(),
'scheduler_hints': None}
@@ -381,9 +378,6 @@ class HostFiltersTestCase(test.NoDBTestCase):
def test_affinity_same_filter_handles_none(self):
filt_cls = self.class_map['SameHostFilter']()
host = fakes.FakeHostState('host1', 'node1', {})
- instance = fakes.FakeInstance(context=self.context,
- params={'host': 'host2'})
- instance_uuid = instance.uuid
filter_properties = {'context': self.context.elevated(),
'scheduler_hints': None}
@@ -542,6 +536,64 @@ class HostFiltersTestCase(test.NoDBTestCase):
self.assertTrue(filt_cls.host_passes(host, filter_properties))
self.assertEqual(2048 * 2.0, host.limits['memory_mb'])
+ def test_aggregate_ram_filter_value_error(self):
+ self._stub_service_is_up(True)
+ filt_cls = self.class_map['AggregateRamFilter']()
+ self.flags(ram_allocation_ratio=1.0)
+ filter_properties = {'context': self.context,
+ 'instance_type': {'memory_mb': 1024}}
+ capabilities = {'enabled': True}
+ service = {'disabled': False}
+ host = fakes.FakeHostState('host1', 'node1',
+ {'free_ram_mb': 1024, 'total_usable_ram_mb': 1024,
+ 'capabilities': capabilities, 'service': service})
+ self._create_aggregate_with_host(name='fake_aggregate',
+ hosts=['host1'],
+ metadata={'ram_allocation_ratio': 'XXX'})
+ self.assertTrue(filt_cls.host_passes(host, filter_properties))
+ self.assertEqual(1024 * 1.0, host.limits['memory_mb'])
+
+ def test_aggregate_ram_filter_default_value(self):
+ self._stub_service_is_up(True)
+ filt_cls = self.class_map['AggregateRamFilter']()
+ self.flags(ram_allocation_ratio=1.0)
+ filter_properties = {'context': self.context,
+ 'instance_type': {'memory_mb': 1024}}
+ capabilities = {'enabled': True}
+ service = {'disabled': False}
+ host = fakes.FakeHostState('host1', 'node1',
+ {'free_ram_mb': 1023, 'total_usable_ram_mb': 1024,
+ 'capabilities': capabilities, 'service': service})
+ # False: fallback to default flag w/o aggregates
+ self.assertFalse(filt_cls.host_passes(host, filter_properties))
+ self._create_aggregate_with_host(name='fake_aggregate',
+ hosts=['host1'],
+ metadata={'ram_allocation_ratio': '2.0'})
+ # True: use ratio from aggregates
+ self.assertTrue(filt_cls.host_passes(host, filter_properties))
+ self.assertEqual(1024 * 2.0, host.limits['memory_mb'])
+
+ def test_aggregate_ram_filter_conflict_values(self):
+ self._stub_service_is_up(True)
+ filt_cls = self.class_map['AggregateRamFilter']()
+ self.flags(ram_allocation_ratio=1.0)
+ filter_properties = {'context': self.context,
+ 'instance_type': {'memory_mb': 1024}}
+ capabilities = {'enabled': True}
+ service = {'disabled': False}
+ host = fakes.FakeHostState('host1', 'node1',
+ {'free_ram_mb': 1023, 'total_usable_ram_mb': 1024,
+ 'capabilities': capabilities, 'service': service})
+ self._create_aggregate_with_host(name='fake_aggregate1',
+ hosts=['host1'],
+ metadata={'ram_allocation_ratio': '1.5'})
+ self._create_aggregate_with_host(name='fake_aggregate2',
+ hosts=['host1'],
+ metadata={'ram_allocation_ratio': '2.0'})
+ # use the minimum ratio from aggregates
+ self.assertTrue(filt_cls.host_passes(host, filter_properties))
+ self.assertEqual(1024 * 1.5, host.limits['memory_mb'])
+
def test_disk_filter_passes(self):
self._stub_service_is_up(True)
filt_cls = self.class_map['DiskFilter']()
@@ -708,6 +760,9 @@ class HostFiltersTestCase(test.NoDBTestCase):
self.assertFalse(filt_cls.host_passes(host, filter_properties))
def _do_test_compute_filter_extra_specs(self, ecaps, especs, passes):
+ """In real Openstack runtime environment,compute capabilities
+ value may be number, so we should use number to do unit test.
+ """
self._stub_service_is_up(True)
filt_cls = self.class_map['ComputeCapabilitiesFilter']()
capabilities = {'enabled': True}
@@ -723,33 +778,33 @@ class HostFiltersTestCase(test.NoDBTestCase):
def test_compute_filter_passes_extra_specs_simple(self):
self._do_test_compute_filter_extra_specs(
- ecaps={'opt1': '1', 'opt2': '2'},
+ ecaps={'opt1': 1, 'opt2': 2},
especs={'opt1': '1', 'opt2': '2', 'trust:trusted_host': 'true'},
passes=True)
def test_compute_filter_fails_extra_specs_simple(self):
self._do_test_compute_filter_extra_specs(
- ecaps={'opt1': '1', 'opt2': '2'},
+ ecaps={'opt1': 1, 'opt2': 2},
especs={'opt1': '1', 'opt2': '222', 'trust:trusted_host': 'true'},
passes=False)
def test_compute_filter_pass_extra_specs_simple_with_scope(self):
self._do_test_compute_filter_extra_specs(
- ecaps={'opt1': '1', 'opt2': '2'},
+ ecaps={'opt1': 1, 'opt2': 2},
especs={'capabilities:opt1': '1',
'trust:trusted_host': 'true'},
passes=True)
def test_compute_filter_extra_specs_simple_with_wrong_scope(self):
self._do_test_compute_filter_extra_specs(
- ecaps={'opt1': '1', 'opt2': '2'},
+ ecaps={'opt1': 1, 'opt2': 2},
especs={'wrong_scope:opt1': '1',
'trust:trusted_host': 'true'},
passes=True)
def test_compute_filter_extra_specs_pass_multi_level_with_scope(self):
self._do_test_compute_filter_extra_specs(
- ecaps={'opt1': {'a': '1', 'b': {'aa': '2'}}, 'opt2': '2'},
+ ecaps={'opt1': {'a': 1, 'b': {'aa': 2}}, 'opt2': 2},
especs={'opt1:a': '1', 'capabilities:opt1:b:aa': '2',
'trust:trusted_host': 'true'},
passes=True)
@@ -950,7 +1005,6 @@ class HostFiltersTestCase(test.NoDBTestCase):
'local_gb': 200},
'scheduler_hints': {'query': json_query}}
capabilities = {'enabled': True}
- service = {'disabled': True}
host = fakes.FakeHostState('host1', 'node1',
{'free_ram_mb': 1024,
'free_disk_mb': 200 * 1024,
@@ -1314,6 +1368,52 @@ class HostFiltersTestCase(test.NoDBTestCase):
{'vcpus_total': 4, 'vcpus_used': 8})
self.assertFalse(filt_cls.host_passes(host, filter_properties))
+ def test_aggregate_core_filter_value_error(self):
+ filt_cls = self.class_map['AggregateCoreFilter']()
+ filter_properties = {'context': self.context,
+ 'instance_type': {'vcpus': 1}}
+ self.flags(cpu_allocation_ratio=2)
+ host = fakes.FakeHostState('host1', 'node1',
+ {'vcpus_total': 4, 'vcpus_used': 7})
+ self._create_aggregate_with_host(name='fake_aggregate',
+ hosts=['host1'],
+ metadata={'cpu_allocation_ratio': 'XXX'})
+ self.assertTrue(filt_cls.host_passes(host, filter_properties))
+ self.assertEqual(4 * 2, host.limits['vcpu'])
+
+ def test_aggregate_core_filter_default_value(self):
+ filt_cls = self.class_map['AggregateCoreFilter']()
+ filter_properties = {'context': self.context,
+ 'instance_type': {'vcpus': 1}}
+ self.flags(cpu_allocation_ratio=2)
+ host = fakes.FakeHostState('host1', 'node1',
+ {'vcpus_total': 4, 'vcpus_used': 8})
+ # False: fallback to default flag w/o aggregates
+ self.assertFalse(filt_cls.host_passes(host, filter_properties))
+ self._create_aggregate_with_host(name='fake_aggregate',
+ hosts=['host1'],
+ metadata={'cpu_allocation_ratio': '3'})
+ # True: use ratio from aggregates
+ self.assertTrue(filt_cls.host_passes(host, filter_properties))
+ self.assertEqual(4 * 3, host.limits['vcpu'])
+
+ def test_aggregate_core_filter_conflict_values(self):
+ filt_cls = self.class_map['AggregateCoreFilter']()
+ filter_properties = {'context': self.context,
+ 'instance_type': {'vcpus': 1}}
+ self.flags(cpu_allocation_ratio=1)
+ host = fakes.FakeHostState('host1', 'node1',
+ {'vcpus_total': 4, 'vcpus_used': 8})
+ self._create_aggregate_with_host(name='fake_aggregate1',
+ hosts=['host1'],
+ metadata={'cpu_allocation_ratio': '2'})
+ self._create_aggregate_with_host(name='fake_aggregate2',
+ hosts=['host1'],
+ metadata={'cpu_allocation_ratio': '3'})
+ # use the minimum ratio from aggregates
+ self.assertFalse(filt_cls.host_passes(host, filter_properties))
+ self.assertEqual(4 * 2, host.limits['vcpu'])
+
@staticmethod
def _make_zone_request(zone, is_admin=False):
ctxt = context.RequestContext('fake', 'fake', is_admin=is_admin)
@@ -1382,6 +1482,8 @@ class HostFiltersTestCase(test.NoDBTestCase):
filt_cls = self.class_map['IoOpsFilter']()
host = fakes.FakeHostState('host1', 'node1',
{'num_io_ops': 8})
+ filter_properties = {}
+ self.assertFalse(filt_cls.host_passes(host, filter_properties))
def test_filter_num_instances_passes(self):
self.flags(max_instances_per_host=5)
diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py
index 0574f6d2e..149c6d3c8 100644
--- a/nova/tests/scheduler/test_scheduler.py
+++ b/nova/tests/scheduler/test_scheduler.py
@@ -22,20 +22,16 @@ Tests For Scheduler
import mox
from nova.compute import api as compute_api
-from nova.compute import flavors
-from nova.compute import power_state
-from nova.compute import rpcapi as compute_rpcapi
from nova.compute import task_states
from nova.compute import utils as compute_utils
from nova.compute import vm_states
from nova.conductor import api as conductor_api
+from nova.conductor.tasks import live_migrate
from nova import context
from nova import db
from nova import exception
from nova.image import glance
-from nova.openstack.common import jsonutils
from nova.openstack.common.notifier import api as notifier
-from nova.openstack.common import rpc
from nova.openstack.common.rpc import common as rpc_common
from nova.scheduler import driver
from nova.scheduler import manager
@@ -45,7 +41,6 @@ from nova.tests import fake_instance_actions
from nova.tests.image import fake as fake_image
from nova.tests import matchers
from nova.tests.scheduler import fakes
-from nova import utils
class SchedulerManagerTestCase(test.NoDBTestCase):
@@ -88,7 +83,7 @@ class SchedulerManagerTestCase(test.NoDBTestCase):
self.manager.driver.update_service_capabilities(service_name,
host, {})
self.mox.ReplayAll()
- result = self.manager.update_service_capabilities(self.context,
+ self.manager.update_service_capabilities(self.context,
service_name=service_name, host=host, capabilities={})
self.mox.VerifyAll()
@@ -98,7 +93,7 @@ class SchedulerManagerTestCase(test.NoDBTestCase):
self.manager.driver.update_service_capabilities(
service_name, host, capabilities)
self.mox.ReplayAll()
- result = self.manager.update_service_capabilities(self.context,
+ self.manager.update_service_capabilities(self.context,
service_name=service_name, host=host,
capabilities=capabilities)
@@ -220,11 +215,11 @@ class SchedulerManagerTestCase(test.NoDBTestCase):
block_migration = False
disk_over_commit = False
- self._mox_schedule_method_helper('schedule_live_migration')
+ self.mox.StubOutWithMock(self.manager, '_schedule_live_migration')
self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc')
self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
- self.manager.driver.schedule_live_migration(self.context,
+ self.manager._schedule_live_migration(self.context,
inst, dest, block_migration, disk_over_commit).AndRaise(
exception.NoValidHost(reason=""))
db.instance_update_and_get_original(self.context, inst["uuid"],
@@ -253,11 +248,11 @@ class SchedulerManagerTestCase(test.NoDBTestCase):
block_migration = False
disk_over_commit = False
- self._mox_schedule_method_helper('schedule_live_migration')
+ self.mox.StubOutWithMock(self.manager, '_schedule_live_migration')
self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc')
self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
- self.manager.driver.schedule_live_migration(self.context,
+ self.manager._schedule_live_migration(self.context,
inst, dest, block_migration, disk_over_commit).AndRaise(
exception.ComputeServiceUnavailable(host="src"))
db.instance_update_and_get_original(self.context, inst["uuid"],
@@ -277,6 +272,17 @@ class SchedulerManagerTestCase(test.NoDBTestCase):
self.context, inst, dest, block_migration,
disk_over_commit)
+ def test_live_migrate(self):
+ instance = {'host': 'h'}
+ self.mox.StubOutClassWithMocks(live_migrate, "LiveMigrationTask")
+ task = live_migrate.LiveMigrationTask(self.context, instance,
+ "dest", "bm", "doc", self.manager.driver.select_hosts)
+ task.execute()
+
+ self.mox.ReplayAll()
+ self.manager.live_migration(self.context, instance, "dest",
+ "bm", "doc")
+
def test_live_migration_set_vmstate_error(self):
inst = {"uuid": "fake-instance-id",
"vm_state": vm_states.ACTIVE, }
@@ -285,11 +291,11 @@ class SchedulerManagerTestCase(test.NoDBTestCase):
block_migration = False
disk_over_commit = False
- self._mox_schedule_method_helper('schedule_live_migration')
+ self.mox.StubOutWithMock(self.manager, '_schedule_live_migration')
self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc')
self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
- self.manager.driver.schedule_live_migration(self.context,
+ self.manager._schedule_live_migration(self.context,
inst, dest, block_migration, disk_over_commit).AndRaise(
ValueError)
db.instance_update_and_get_original(self.context, inst["uuid"],
@@ -402,6 +408,17 @@ class SchedulerManagerTestCase(test.NoDBTestCase):
self.manager._set_vm_state_and_notify('foo', {'vm_state': 'foo'},
self.context, None, request)
+ def test_select_hosts_throws_rpc_clientexception(self):
+ self.mox.StubOutWithMock(self.manager.driver, 'select_hosts')
+
+ self.manager.driver.select_hosts(self.context, {}, {}).AndRaise(
+ exception.NoValidHost(reason=""))
+
+ self.mox.ReplayAll()
+ self.assertRaises(rpc_common.ClientException,
+ self.manager.select_hosts,
+ self.context, {}, {})
+
class SchedulerTestCase(test.NoDBTestCase):
"""Test case for base scheduler driver class."""
@@ -444,7 +461,7 @@ class SchedulerTestCase(test.NoDBTestCase):
self.driver.host_manager.update_service_capabilities(
service_name, host, capabilities)
self.mox.ReplayAll()
- result = self.driver.update_service_capabilities(service_name,
+ self.driver.update_service_capabilities(service_name,
host, capabilities)
def test_hosts_up(self):
@@ -464,482 +481,6 @@ class SchedulerTestCase(test.NoDBTestCase):
result = self.driver.hosts_up(self.context, self.topic)
self.assertEqual(result, ['host2'])
- def _live_migration_instance(self):
- inst_type = {'memory_mb': 1024, 'root_gb': 40, 'deleted_at': None,
- 'name': u'm1.medium', 'deleted': 0, 'created_at': None,
- 'ephemeral_gb': 0, 'updated_at': None, 'disabled': False,
- 'vcpus': 2, 'extra_specs': {}, 'swap': 0,
- 'rxtx_factor': 1.0, 'is_public': True, 'flavorid': u'3',
- 'vcpu_weight': None, 'id': 1}
-
- sys_meta = utils.dict_to_metadata(
- flavors.save_flavor_info({}, inst_type))
- return {'id': 31337,
- 'uuid': 'fake_uuid',
- 'name': 'fake-instance',
- 'host': 'fake_host1',
- 'power_state': power_state.RUNNING,
- 'memory_mb': 1024,
- 'root_gb': 1024,
- 'ephemeral_gb': 0,
- 'vm_state': '',
- 'task_state': '',
- 'instance_type_id': inst_type['id'],
- 'image_ref': 'fake-image-ref',
- 'system_metadata': sys_meta}
-
- def test_live_migration_basic(self):
- # Test basic schedule_live_migration functionality.
- self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
- self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check')
- self.mox.StubOutWithMock(self.driver, '_live_migration_common_check')
- self.mox.StubOutWithMock(self.driver.compute_rpcapi,
- 'check_can_live_migrate_destination')
- self.mox.StubOutWithMock(self.driver.compute_rpcapi,
- 'live_migration')
-
- dest = 'fake_host2'
- block_migration = False
- disk_over_commit = False
- instance = jsonutils.to_primitive(self._live_migration_instance())
-
- self.driver._live_migration_src_check(self.context, instance)
- self.driver._live_migration_dest_check(self.context, instance,
- dest).AndReturn(dest)
- self.driver._live_migration_common_check(self.context, instance,
- dest)
- self.driver.compute_rpcapi.check_can_live_migrate_destination(
- self.context, instance, dest, block_migration,
- disk_over_commit).AndReturn({})
- self.driver.compute_rpcapi.live_migration(self.context,
- host=instance['host'], instance=instance, dest=dest,
- block_migration=block_migration, migrate_data={})
-
- self.mox.ReplayAll()
- self.driver.schedule_live_migration(self.context,
- instance=instance, dest=dest,
- block_migration=block_migration,
- disk_over_commit=disk_over_commit)
-
- def test_live_migration_all_checks_pass(self):
- # Test live migration when all checks pass.
-
- self.mox.StubOutWithMock(servicegroup.API, 'service_is_up')
- self.mox.StubOutWithMock(db, 'service_get_by_compute_host')
- self.mox.StubOutWithMock(rpc, 'call')
- self.mox.StubOutWithMock(self.driver.compute_rpcapi,
- 'live_migration')
-
- dest = 'fake_host2'
- block_migration = True
- disk_over_commit = True
- instance = jsonutils.to_primitive(self._live_migration_instance())
-
- # Source checks
- db.service_get_by_compute_host(self.context,
- instance['host']).AndReturn('fake_service2')
- self.servicegroup_api.service_is_up('fake_service2').AndReturn(True)
-
- # Destination checks (compute is up, enough memory, disk)
- db.service_get_by_compute_host(self.context,
- dest).AndReturn('fake_service3')
- self.servicegroup_api.service_is_up('fake_service3').AndReturn(True)
- # assert_compute_node_has_enough_memory()
- db.service_get_by_compute_host(self.context, dest).AndReturn(
- {'compute_node': [{'memory_mb': 2048,
- 'free_disk_gb': 512,
- 'local_gb_used': 512,
- 'free_ram_mb': 1280,
- 'local_gb': 1024,
- 'vcpus': 4,
- 'vcpus_used': 2,
- 'updated_at': None,
- 'hypervisor_version': 1}]})
-
- # Common checks (same hypervisor, etc)
- db.service_get_by_compute_host(self.context, dest).AndReturn(
- {'compute_node': [{'hypervisor_type': 'xen',
- 'hypervisor_version': 1}]})
- db.service_get_by_compute_host(self.context,
- instance['host']).AndReturn(
- {'compute_node': [{'hypervisor_type': 'xen',
- 'hypervisor_version': 1,
- 'cpu_info': 'fake_cpu_info'}]})
-
- rpc.call(self.context, "compute.fake_host2",
- {"method": 'check_can_live_migrate_destination',
- "namespace": None,
- "args": {'instance': instance,
- 'block_migration': block_migration,
- 'disk_over_commit': disk_over_commit},
- "version": compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION},
- None).AndReturn({})
-
- self.driver.compute_rpcapi.live_migration(self.context,
- host=instance['host'], instance=instance, dest=dest,
- block_migration=block_migration, migrate_data={})
-
- self.mox.ReplayAll()
- result = self.driver.schedule_live_migration(self.context,
- instance=instance, dest=dest,
- block_migration=block_migration,
- disk_over_commit=disk_over_commit)
- self.assertEqual(result, None)
-
- def test_live_migration_instance_not_running(self):
- # The instance given by instance_id is not running.
-
- dest = 'fake_host2'
- block_migration = False
- disk_over_commit = False
- instance = self._live_migration_instance()
- instance['power_state'] = power_state.NOSTATE
-
- self.assertRaises(exception.InstanceNotRunning,
- self.driver.schedule_live_migration, self.context,
- instance=instance, dest=dest,
- block_migration=block_migration,
- disk_over_commit=disk_over_commit)
-
- def test_live_migration_compute_src_not_exist(self):
- # Raise exception when src compute node is does not exist.
-
- self.mox.StubOutWithMock(servicegroup.API, 'service_is_up')
- self.mox.StubOutWithMock(db, 'service_get_by_compute_host')
-
- dest = 'fake_host2'
- block_migration = False
- disk_over_commit = False
- instance = self._live_migration_instance()
-
- # Compute down
- db.service_get_by_compute_host(self.context,
- instance['host']).AndRaise(
- exception.ComputeHostNotFound(host='fake'))
-
- self.mox.ReplayAll()
- self.assertRaises(exception.ComputeServiceUnavailable,
- self.driver.schedule_live_migration, self.context,
- instance=instance, dest=dest,
- block_migration=block_migration,
- disk_over_commit=disk_over_commit)
-
- def test_live_migration_compute_src_not_alive(self):
- # Raise exception when src compute node is not alive.
-
- self.mox.StubOutWithMock(servicegroup.API, 'service_is_up')
- self.mox.StubOutWithMock(db, 'service_get_by_compute_host')
-
- dest = 'fake_host2'
- block_migration = False
- disk_over_commit = False
- instance = self._live_migration_instance()
-
- # Compute down
- db.service_get_by_compute_host(self.context,
- instance['host']).AndReturn('fake_service2')
- self.servicegroup_api.service_is_up('fake_service2').AndReturn(False)
-
- self.mox.ReplayAll()
- self.assertRaises(exception.ComputeServiceUnavailable,
- self.driver.schedule_live_migration, self.context,
- instance=instance, dest=dest,
- block_migration=block_migration,
- disk_over_commit=disk_over_commit)
-
- def test_live_migration_compute_dest_not_exist(self):
- # Raise exception when dest compute node does not exist.
-
- self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
- self.mox.StubOutWithMock(db, 'service_get_by_compute_host')
-
- dest = 'fake_host2'
- block_migration = False
- disk_over_commit = False
- instance = self._live_migration_instance()
-
- self.driver._live_migration_src_check(self.context, instance)
- # Compute down
- db.service_get_by_compute_host(self.context,
- dest).AndRaise(exception.NotFound())
-
- self.mox.ReplayAll()
- self.assertRaises(exception.ComputeServiceUnavailable,
- self.driver.schedule_live_migration, self.context,
- instance=instance, dest=dest,
- block_migration=block_migration,
- disk_over_commit=disk_over_commit)
-
- def test_live_migration_compute_dest_not_alive(self):
- # Raise exception when dest compute node is not alive.
-
- self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
- self.mox.StubOutWithMock(db, 'service_get_by_compute_host')
- self.mox.StubOutWithMock(servicegroup.API, 'service_is_up')
-
- dest = 'fake_host2'
- block_migration = False
- disk_over_commit = False
- instance = self._live_migration_instance()
-
- self.driver._live_migration_src_check(self.context, instance)
- db.service_get_by_compute_host(self.context,
- dest).AndReturn('fake_service3')
- # Compute is down
- self.servicegroup_api.service_is_up('fake_service3').AndReturn(False)
-
- self.mox.ReplayAll()
- self.assertRaises(exception.ComputeServiceUnavailable,
- self.driver.schedule_live_migration, self.context,
- instance=instance, dest=dest,
- block_migration=block_migration,
- disk_over_commit=disk_over_commit)
-
- def test_live_migration_dest_check_service_same_host(self):
- # Confirms exception raises in case dest and src is same host.
-
- self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
- block_migration = False
- instance = self._live_migration_instance()
- # make dest same as src
- dest = instance['host']
-
- self.driver._live_migration_src_check(self.context, instance)
-
- self.mox.ReplayAll()
- self.assertRaises(exception.UnableToMigrateToSelf,
- self.driver.schedule_live_migration, self.context,
- instance=instance, dest=dest,
- block_migration=block_migration,
- disk_over_commit=False)
-
- def test_live_migration_dest_check_service_lack_memory(self):
- # Confirms exception raises when dest doesn't have enough memory.
-
- # Flag needed to make FilterScheduler test hit memory limit since the
- # default for it is to allow memory overcommit by a factor of 1.5.
- self.flags(ram_allocation_ratio=1.0)
-
- self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
- self.mox.StubOutWithMock(db, 'service_get_by_compute_host')
- self.mox.StubOutWithMock(servicegroup.API, 'service_is_up')
- self.mox.StubOutWithMock(self.driver, '_get_compute_info')
-
- dest = 'fake_host2'
- block_migration = False
- disk_over_commit = False
- instance = self._live_migration_instance()
-
- self.driver._live_migration_src_check(self.context, instance)
- db.service_get_by_compute_host(self.context,
- dest).AndReturn('fake_service3')
- self.servicegroup_api.service_is_up('fake_service3').AndReturn(True)
-
- self.driver._get_compute_info(self.context, dest).AndReturn(
- {'memory_mb': 2048,
- 'free_disk_gb': 512,
- 'local_gb_used': 512,
- 'free_ram_mb': 512,
- 'local_gb': 1024,
- 'vcpus': 4,
- 'vcpus_used': 2,
- 'updated_at': None})
-
- self.mox.ReplayAll()
- self.assertRaises(exception.MigrationError,
- self.driver.schedule_live_migration, self.context,
- instance=instance, dest=dest,
- block_migration=block_migration,
- disk_over_commit=disk_over_commit)
-
- def test_live_migration_different_hypervisor_type_raises(self):
- # Confirm live_migration to hypervisor of different type raises.
- self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
- self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check')
- self.mox.StubOutWithMock(rpc, 'queue_get_for')
- self.mox.StubOutWithMock(rpc, 'call')
- self.mox.StubOutWithMock(rpc, 'cast')
- self.mox.StubOutWithMock(db, 'service_get_by_compute_host')
-
- dest = 'fake_host2'
- block_migration = False
- disk_over_commit = False
- instance = self._live_migration_instance()
-
- self.driver._live_migration_src_check(self.context, instance)
- self.driver._live_migration_dest_check(self.context, instance,
- dest).AndReturn(dest)
-
- db.service_get_by_compute_host(self.context, dest).AndReturn(
- {'compute_node': [{'hypervisor_type': 'xen',
- 'hypervisor_version': 1}]})
- db.service_get_by_compute_host(self.context,
- instance['host']).AndReturn(
- {'compute_node': [{'hypervisor_type': 'not-xen',
- 'hypervisor_version': 1}]})
-
- self.mox.ReplayAll()
- self.assertRaises(exception.InvalidHypervisorType,
- self.driver.schedule_live_migration, self.context,
- instance=instance, dest=dest,
- block_migration=block_migration,
- disk_over_commit=disk_over_commit)
-
- def test_live_migration_dest_hypervisor_version_older_raises(self):
- # Confirm live migration to older hypervisor raises.
- self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
- self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check')
- self.mox.StubOutWithMock(rpc, 'queue_get_for')
- self.mox.StubOutWithMock(rpc, 'call')
- self.mox.StubOutWithMock(rpc, 'cast')
- self.mox.StubOutWithMock(db, 'service_get_by_compute_host')
-
- dest = 'fake_host2'
- block_migration = False
- disk_over_commit = False
- instance = self._live_migration_instance()
-
- self.driver._live_migration_src_check(self.context, instance)
- self.driver._live_migration_dest_check(self.context, instance,
- dest).AndReturn(dest)
-
- db.service_get_by_compute_host(self.context, dest).AndReturn(
- {'compute_node': [{'hypervisor_type': 'xen',
- 'hypervisor_version': 1}]})
- db.service_get_by_compute_host(self.context,
- instance['host']).AndReturn(
- {'compute_node': [{'hypervisor_type': 'xen',
- 'hypervisor_version': 2}]})
- self.mox.ReplayAll()
- self.assertRaises(exception.DestinationHypervisorTooOld,
- self.driver.schedule_live_migration, self.context,
- instance=instance, dest=dest,
- block_migration=block_migration,
- disk_over_commit=disk_over_commit)
-
- def test_live_migration_dest_check_auto_set_host(self):
- instance = self._live_migration_instance()
-
- # Confirm dest is picked by scheduler if not set.
- self.mox.StubOutWithMock(self.driver, 'select_hosts')
- self.mox.StubOutWithMock(flavors, 'extract_flavor')
-
- request_spec = {'instance_properties': instance,
- 'instance_type': {},
- 'instance_uuids': [instance['uuid']],
- 'image': self.image_service.show(self.context,
- instance['image_ref'])
- }
- ignore_hosts = [instance['host']]
- filter_properties = {'ignore_hosts': ignore_hosts}
-
- flavors.extract_flavor(instance).AndReturn({})
- self.driver.select_hosts(self.context, request_spec,
- filter_properties).AndReturn(['fake_host2'])
-
- self.mox.ReplayAll()
- result = self.driver._live_migration_dest_check(self.context, instance,
- None, ignore_hosts)
- self.assertEqual('fake_host2', result)
-
- def test_live_migration_dest_check_no_image(self):
- instance = self._live_migration_instance()
- instance['image_ref'] = ''
-
- # Confirm dest is picked by scheduler if not set.
- self.mox.StubOutWithMock(self.driver, 'select_hosts')
- self.mox.StubOutWithMock(flavors, 'extract_flavor')
-
- request_spec = {'instance_properties': instance,
- 'instance_type': {},
- 'instance_uuids': [instance['uuid']],
- 'image': None
- }
- ignore_hosts = [instance['host']]
- filter_properties = {'ignore_hosts': ignore_hosts}
-
- flavors.extract_flavor(instance).AndReturn({})
- self.driver.select_hosts(self.context, request_spec,
- filter_properties).AndReturn(['fake_host2'])
-
- self.mox.ReplayAll()
- result = self.driver._live_migration_dest_check(self.context, instance,
- None, ignore_hosts)
- self.assertEqual('fake_host2', result)
-
- def test_live_migration_auto_set_dest(self):
- instance = self._live_migration_instance()
-
- # Confirm scheduler picks target host if none given.
- self.mox.StubOutWithMock(flavors, 'extract_flavor')
- self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
- self.mox.StubOutWithMock(self.driver, 'select_hosts')
- self.mox.StubOutWithMock(self.driver, '_live_migration_common_check')
- self.mox.StubOutWithMock(rpc, 'call')
- self.mox.StubOutWithMock(self.driver.compute_rpcapi, 'live_migration')
-
- dest = None
- block_migration = False
- disk_over_commit = False
- request_spec = {'instance_properties': instance,
- 'instance_type': {},
- 'instance_uuids': [instance['uuid']],
- 'image': self.image_service.show(self.context,
- instance['image_ref'])
- }
-
- self.driver._live_migration_src_check(self.context, instance)
-
- flavors.extract_flavor(
- instance).MultipleTimes().AndReturn({})
-
- # First selected host raises exception.InvalidHypervisorType
- self.driver.select_hosts(self.context, request_spec,
- {'ignore_hosts': [instance['host']]}).AndReturn(['fake_host2'])
- self.driver._live_migration_common_check(self.context, instance,
- 'fake_host2').AndRaise(exception.InvalidHypervisorType())
-
- # Second selected host raises exception.InvalidCPUInfo
- self.driver.select_hosts(self.context, request_spec,
- {'ignore_hosts': [instance['host'],
- 'fake_host2']}).AndReturn(['fake_host3'])
- self.driver._live_migration_common_check(self.context, instance,
- 'fake_host3')
- rpc.call(self.context, "compute.fake_host3",
- {"method": 'check_can_live_migrate_destination',
- "namespace": None,
- "args": {'instance': instance,
- 'block_migration': block_migration,
- 'disk_over_commit': disk_over_commit},
- "version": compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION},
- None).AndRaise(exception.InvalidCPUInfo(reason=""))
-
- # Third selected host pass all checks
- self.driver.select_hosts(self.context, request_spec,
- {'ignore_hosts': [instance['host'],
- 'fake_host2',
- 'fake_host3']}).AndReturn(['fake_host4'])
- self.driver._live_migration_common_check(self.context, instance,
- 'fake_host4')
- rpc.call(self.context, "compute.fake_host4",
- {"method": 'check_can_live_migrate_destination',
- "namespace": None,
- "args": {'instance': instance,
- 'block_migration': block_migration,
- 'disk_over_commit': disk_over_commit},
- "version": compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION},
- None).AndReturn({})
- self.driver.compute_rpcapi.live_migration(self.context,
- host=instance['host'], instance=instance, dest='fake_host4',
- block_migration=block_migration, migrate_data={})
-
- self.mox.ReplayAll()
- result = self.driver.schedule_live_migration(self.context,
- instance=instance, dest=dest,
- block_migration=block_migration,
- disk_over_commit=disk_over_commit)
- self.assertEqual(result, None)
-
def test_handle_schedule_error_adds_instance_fault(self):
instance = {'uuid': 'fake-uuid'}
self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
@@ -961,12 +502,10 @@ class SchedulerTestCase(test.NoDBTestCase):
class SchedulerDriverBaseTestCase(SchedulerTestCase):
"""Test cases for base scheduler driver class methods
- that can't will fail if the driver is changed.
+ that will fail if the driver is changed.
"""
def test_unimplemented_schedule_run_instance(self):
- fake_args = (1, 2, 3)
- fake_kwargs = {'cat': 'meow'}
fake_request_spec = {'instance_properties':
{'uuid': 'uuid'}}
@@ -976,8 +515,6 @@ class SchedulerDriverBaseTestCase(SchedulerTestCase):
None, None)
def test_unimplemented_schedule_prep_resize(self):
- fake_args = (1, 2, 3)
- fake_kwargs = {'cat': 'meow'}
fake_request_spec = {'instance_properties':
{'uuid': 'uuid'}}
diff --git a/nova/tests/scheduler/test_scheduler_options.py b/nova/tests/scheduler/test_scheduler_options.py
index 6ab245ef9..eb7ccfeec 100644
--- a/nova/tests/scheduler/test_scheduler_options.py
+++ b/nova/tests/scheduler/test_scheduler_options.py
@@ -71,7 +71,6 @@ class SchedulerOptionsTestCase(test.NoDBTestCase):
file_old = None
file_now = datetime.datetime(2012, 1, 1, 1, 1, 1)
- data = dict(a=1, b=2, c=3)
jdata = ""
fake = FakeSchedulerOptions(last_checked, now, file_old, file_now,
diff --git a/nova/tests/servicegroup/test_mc_servicegroup.py b/nova/tests/servicegroup/test_mc_servicegroup.py
index 9d5601ff8..9f27ecc31 100644
--- a/nova/tests/servicegroup/test_mc_servicegroup.py
+++ b/nova/tests/servicegroup/test_mc_servicegroup.py
@@ -103,15 +103,9 @@ class MemcachedServiceGroupTestCase(test.TestCase):
ServiceFixture(host3, self._binary, self._topic)).serv
serv3.start()
- service_ref1 = db.service_get_by_args(self._ctx,
- host1,
- self._binary)
- service_ref2 = db.service_get_by_args(self._ctx,
- host2,
- self._binary)
- service_ref3 = db.service_get_by_args(self._ctx,
- host3,
- self._binary)
+ db.service_get_by_args(self._ctx, host1, self._binary)
+ db.service_get_by_args(self._ctx, host2, self._binary)
+ db.service_get_by_args(self._ctx, host3, self._binary)
host1key = str("%s:%s" % (self._topic, host1))
host2key = str("%s:%s" % (self._topic, host2))
@@ -198,9 +192,7 @@ class MemcachedServiceGroupTestCase(test.TestCase):
serv = self.useFixture(
ServiceFixture(self._host, self._binary, self._topic)).serv
serv.start()
- service_ref = db.service_get_by_args(self._ctx,
- self._host,
- self._binary)
+ db.service_get_by_args(self._ctx, self._host, self._binary)
self.servicegroup_api = servicegroup.API()
# updating model_disconnected
diff --git a/nova/tests/servicegroup/test_zk_driver.py b/nova/tests/servicegroup/test_zk_driver.py
index eb6ddd4bf..716f62e4e 100644
--- a/nova/tests/servicegroup/test_zk_driver.py
+++ b/nova/tests/servicegroup/test_zk_driver.py
@@ -40,7 +40,7 @@ class ZKServiceGroupTestCase(test.TestCase):
self.flags(servicegroup_driver='zk')
self.flags(address='localhost:2181', group="zookeeper")
try:
- _unused = zk.ZooKeeperDriver()
+ zk.ZooKeeperDriver()
except ImportError:
self.skipTest("Unable to test due to lack of ZooKeeper")
diff --git a/nova/tests/test_availability_zones.py b/nova/tests/test_availability_zones.py
index 3923dd9a1..0c58cd08a 100644
--- a/nova/tests/test_availability_zones.py
+++ b/nova/tests/test_availability_zones.py
@@ -179,8 +179,8 @@ class AvailabilityZoneTestCases(test.TestCase):
disabled=False)
service4 = self._create_service_with_topic('compute', 'host4',
disabled=True)
- service5 = self._create_service_with_topic('compute', 'host5',
- disabled=True)
+ self._create_service_with_topic('compute', 'host5',
+ disabled=True)
self._add_to_aggregate(service1, self.agg)
self._add_to_aggregate(service2, self.agg)
diff --git a/nova/tests/test_cinder.py b/nova/tests/test_cinder.py
index e8dff9a4a..eefc1bab6 100644
--- a/nova/tests/test_cinder.py
+++ b/nova/tests/test_cinder.py
@@ -14,7 +14,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import httplib2
import urlparse
from cinderclient import exceptions as cinder_exception
@@ -76,9 +75,9 @@ class FakeHTTPClient(cinder.cinder_client.client.HTTPClient):
status, body = getattr(self, callback)(**kwargs)
if hasattr(status, 'items'):
- return httplib2.Response(status), body
+ return status, body
else:
- return httplib2.Response({"status": status}), body
+ return {"status": status}, body
def get_volumes_1234(self, **kw):
volume = {'volume': _stub_volume(id='1234')}
@@ -154,7 +153,7 @@ class CinderTestCase(test.TestCase):
self.fake_client_factory.assert_called(*args, **kwargs)
def test_context_with_catalog(self):
- volume = self.api.get(self.context, '1234')
+ self.api.get(self.context, '1234')
self.assert_called('GET', '/volumes/1234')
self.assertEquals(
self.fake_client_factory.client.client.management_url,
@@ -164,7 +163,7 @@ class CinderTestCase(test.TestCase):
self.flags(
cinder_endpoint_template='http://other_host:8776/v1/%(project_id)s'
)
- volume = self.api.get(self.context, '1234')
+ self.api.get(self.context, '1234')
self.assert_called('GET', '/volumes/1234')
self.assertEquals(
self.fake_client_factory.client.client.management_url,
@@ -184,7 +183,7 @@ class CinderTestCase(test.TestCase):
# The True/False negation is awkward, but better for the client
# to pass us insecure=True and we check verify_cert == False
self.flags(cinder_api_insecure=True)
- volume = self.api.get(self.context, '1234')
+ self.api.get(self.context, '1234')
self.assert_called('GET', '/volumes/1234')
self.assertEquals(
self.fake_client_factory.client.client.verify_cert, False)
@@ -192,7 +191,7 @@ class CinderTestCase(test.TestCase):
def test_cinder_api_cacert_file(self):
cacert = "/etc/ssl/certs/ca-certificates.crt"
self.flags(cinder_ca_certificates_file=cacert)
- volume = self.api.get(self.context, '1234')
+ self.api.get(self.context, '1234')
self.assert_called('GET', '/volumes/1234')
self.assertEquals(
self.fake_client_factory.client.client.verify_cert, cacert)
@@ -200,7 +199,7 @@ class CinderTestCase(test.TestCase):
def test_cinder_http_retries(self):
retries = 42
self.flags(cinder_http_retries=retries)
- volume = self.api.get(self.context, '1234')
+ self.api.get(self.context, '1234')
self.assert_called('GET', '/volumes/1234')
self.assertEquals(
self.fake_client_factory.client.client.retries, retries)
diff --git a/nova/tests/test_flavors.py b/nova/tests/test_flavors.py
index bd3f805cd..6edbddb21 100644
--- a/nova/tests/test_flavors.py
+++ b/nova/tests/test_flavors.py
@@ -69,11 +69,8 @@ class InstanceTypeTestCase(test.TestCase):
project_id = 'fake'
ctxt = context.RequestContext(user_id, project_id, is_admin=True)
flavor_id = 'flavor1'
- type_ref = flavors.create('some flavor', 256, 1, 120, 100,
- flavorid=flavor_id)
- access_ref = flavors.add_flavor_access(flavor_id,
- project_id,
- ctxt=ctxt)
+ flavors.create('some flavor', 256, 1, 120, 100, flavorid=flavor_id)
+ flavors.add_flavor_access(flavor_id, project_id, ctxt=ctxt)
self.assertRaises(exception.FlavorAccessExists,
flavors.add_flavor_access,
flavor_id, project_id, ctxt)
@@ -92,10 +89,8 @@ class InstanceTypeTestCase(test.TestCase):
project_id = 'fake'
ctxt = context.RequestContext(user_id, project_id, is_admin=True)
flavor_id = 'flavor1'
- type_ref = flavors.create('some flavor', 256, 1, 120, 100,
- flavorid=flavor_id)
- access_ref = flavors.add_flavor_access(flavor_id, project_id,
- ctxt)
+ flavors.create('some flavor', 256, 1, 120, 100, flavorid=flavor_id)
+ flavors.add_flavor_access(flavor_id, project_id, ctxt)
flavors.remove_flavor_access(flavor_id, project_id, ctxt)
projects = flavors.get_flavor_access_by_flavor_id(flavor_id,
@@ -107,8 +102,7 @@ class InstanceTypeTestCase(test.TestCase):
project_id = 'fake'
ctxt = context.RequestContext(user_id, project_id, is_admin=True)
flavor_id = 'flavor1'
- type_ref = flavors.create('some flavor', 256, 1, 120, 100,
- flavorid=flavor_id)
+ flavors.create('some flavor', 256, 1, 120, 100, flavorid=flavor_id)
self.assertRaises(exception.FlavorAccessNotFound,
flavors.remove_flavor_access,
flavor_id, project_id, ctxt=ctxt)
diff --git a/nova/tests/test_metadata.py b/nova/tests/test_metadata.py
index 8cdc3e7af..2aece7ac8 100644
--- a/nova/tests/test_metadata.py
+++ b/nova/tests/test_metadata.py
@@ -71,6 +71,7 @@ INSTANCES = (
'info_cache': {'network_info': []},
'hostname': 'test.novadomain',
'display_name': 'my_displayname',
+ 'metadata': {}
},
)
diff --git a/nova/tests/test_notifications.py b/nova/tests/test_notifications.py
index 23fe4c82b..0d7c0e7a8 100644
--- a/nova/tests/test_notifications.py
+++ b/nova/tests/test_notifications.py
@@ -295,13 +295,17 @@ class NotificationsTestCase(test.TestCase):
self.assertEquals(payload["access_ip_v6"], access_ip_v6)
def test_send_name_update(self):
- notifications.send_update(self.context, self.instance, self.instance)
+ param = {"display_name": "new_display_name"}
+ new_name_inst = self._wrapped_create(params=param)
+ notifications.send_update(self.context, self.instance, new_name_inst)
self.assertEquals(1, len(test_notifier.NOTIFICATIONS))
notif = test_notifier.NOTIFICATIONS[0]
payload = notif["payload"]
- display_name = self.instance["display_name"]
+ old_display_name = self.instance["display_name"]
+ new_display_name = new_name_inst["display_name"]
- self.assertEquals(payload["display_name"], display_name)
+ self.assertEquals(payload["old_display_name"], old_display_name)
+ self.assertEquals(payload["display_name"], new_display_name)
def test_send_no_state_change(self):
called = [False]
diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py
index be3669958..37009f3df 100644
--- a/nova/tests/test_quota.py
+++ b/nova/tests/test_quota.py
@@ -227,7 +227,7 @@ class QuotaIntegrationTestCase(test.TestCase):
timeutils.advance_time_seconds(80)
- result = quota.QUOTAS.expire(self.context)
+ quota.QUOTAS.expire(self.context)
assertInstancesReserved(0)
diff --git a/nova/tests/test_utils.py b/nova/tests/test_utils.py
index f400bb899..ada649549 100644
--- a/nova/tests/test_utils.py
+++ b/nova/tests/test_utils.py
@@ -38,41 +38,6 @@ from nova import utils
CONF = cfg.CONF
-class ByteConversionTest(test.TestCase):
- def test_string_conversions(self):
- working_examples = {
- '1024KB': 1048576,
- '1024TB': 1125899906842624,
- '1024K': 1048576,
- '1024T': 1125899906842624,
- '1TB': 1099511627776,
- '1T': 1099511627776,
- '1KB': 1024,
- '1K': 1024,
- '1B': 1,
- '1B': 1,
- '1': 1,
- '1MB': 1048576,
- '7MB': 7340032,
- '0MB': 0,
- '0KB': 0,
- '0TB': 0,
- '': 0,
- }
- for (in_value, expected_value) in working_examples.items():
- b_value = utils.to_bytes(in_value)
- self.assertEquals(expected_value, b_value)
- if len(in_value):
- in_value = "-" + in_value
- b_value = utils.to_bytes(in_value)
- self.assertEquals(expected_value * -1, b_value)
- breaking_examples = [
- 'junk1KB', '1023BBBB',
- ]
- for v in breaking_examples:
- self.assertRaises(TypeError, utils.to_bytes, v)
-
-
class GetFromPathTestCase(test.TestCase):
def test_tolerates_nones(self):
f = utils.get_from_path
@@ -228,6 +193,92 @@ class GetFromPathTestCase(test.TestCase):
self.assertEquals(['b_1'], f(input, "a/b"))
+class GetMyIP4AddressTestCase(test.TestCase):
+ def test_get_my_ipv4_address_with_no_ipv4(self):
+ response = """172.16.0.0/16 via 172.16.251.13 dev tun1
+172.16.251.1 via 172.16.251.13 dev tun1
+172.16.251.13 dev tun1 proto kernel scope link src 172.16.251.14
+172.24.0.0/16 via 172.16.251.13 dev tun1
+192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1"""
+
+ def fake_execute(*args, **kwargs):
+ return response, None
+
+ self.stubs.Set(utils, 'execute', fake_execute)
+ address = utils.get_my_ipv4_address()
+ self.assertEqual(address, '127.0.0.1')
+
+ def test_get_my_ipv4_address_bad_process(self):
+ def fake_execute(*args, **kwargs):
+ raise processutils.ProcessExecutionError()
+
+ self.stubs.Set(utils, 'execute', fake_execute)
+ address = utils.get_my_ipv4_address()
+ self.assertEqual(address, '127.0.0.1')
+
+ def test_get_my_ipv4_address_with_single_interface(self):
+ response_route = """default via 192.168.1.1 dev wlan0 proto static
+192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.137 metric 9
+"""
+ response_addr = """
+1: lo inet 127.0.0.1/8 scope host lo
+3: wlan0 inet 192.168.1.137/24 brd 192.168.1.255 scope global wlan0
+"""
+
+ def fake_execute(*args, **kwargs):
+ if 'route' in args:
+ return response_route, None
+ return response_addr, None
+
+ self.stubs.Set(utils, 'execute', fake_execute)
+ address = utils.get_my_ipv4_address()
+ self.assertEqual(address, '192.168.1.137')
+
+ def test_get_my_ipv4_address_with_multi_ipv4_on_single_interface(self):
+ response_route = """
+172.18.56.0/24 dev customer proto kernel scope link src 172.18.56.22
+169.254.0.0/16 dev customer scope link metric 1031
+default via 172.18.56.1 dev customer
+"""
+ response_addr = (""
+"31: customer inet 172.18.56.22/24 brd 172.18.56.255 scope global"
+" customer\n"
+"31: customer inet 172.18.56.32/24 brd 172.18.56.255 scope global "
+"secondary customer")
+
+ def fake_execute(*args, **kwargs):
+ if 'route' in args:
+ return response_route, None
+ return response_addr, None
+
+ self.stubs.Set(utils, 'execute', fake_execute)
+ address = utils.get_my_ipv4_address()
+ self.assertEqual(address, '172.18.56.22')
+
+ def test_get_my_ipv4_address_with_multiple_interfaces(self):
+ response_route = """
+169.1.9.0/24 dev eth1 proto kernel scope link src 169.1.9.10
+172.17.248.0/21 dev eth0 proto kernel scope link src 172.17.255.9
+169.254.0.0/16 dev eth0 scope link metric 1002
+169.254.0.0/16 dev eth1 scope link metric 1003
+default via 172.17.248.1 dev eth0 proto static
+"""
+ response_addr = """
+1: lo inet 127.0.0.1/8 scope host lo
+2: eth0 inet 172.17.255.9/21 brd 172.17.255.255 scope global eth0
+3: eth1 inet 169.1.9.10/24 scope global eth1
+"""
+
+ def fake_execute(*args, **kwargs):
+ if 'route' in args:
+ return response_route, None
+ return response_addr, None
+
+ self.stubs.Set(utils, 'execute', fake_execute)
+ address = utils.get_my_ipv4_address()
+ self.assertEqual(address, '172.17.255.9')
+
+
class GenericUtilsTestCase(test.TestCase):
def test_parse_server_string(self):
result = utils.parse_server_string('::1')
diff --git a/nova/tests/test_wsgi.py b/nova/tests/test_wsgi.py
index d1d659fe3..7118aa938 100644
--- a/nova/tests/test_wsgi.py
+++ b/nova/tests/test_wsgi.py
@@ -23,8 +23,7 @@ import tempfile
import testtools
import eventlet
-import httplib2
-import paste
+import requests
import nova.exception
from nova import test
@@ -119,16 +118,16 @@ class TestWSGIServer(test.TestCase):
server.start()
uri = "http://127.0.0.1:%d/%s" % (server.port, 10000 * 'x')
- resp, _ = httplib2.Http().request(uri)
+ resp = requests.get(uri)
eventlet.sleep(0)
- self.assertNotEqual(resp.status,
- paste.httpexceptions.HTTPRequestURITooLong.code)
+ self.assertNotEqual(resp.status_code,
+ requests.codes.REQUEST_URI_TOO_LARGE)
uri = "http://127.0.0.1:%d/%s" % (server.port, 20000 * 'x')
- resp, _ = httplib2.Http().request(uri)
+ resp = requests.get(uri)
eventlet.sleep(0)
- self.assertEqual(resp.status,
- paste.httpexceptions.HTTPRequestURITooLong.code)
+ self.assertEqual(resp.status_code,
+ requests.codes.REQUEST_URI_TOO_LARGE)
server.stop()
server.wait()
diff --git a/nova/tests/utils.py b/nova/tests/utils.py
index 994e4f220..d39d14950 100644
--- a/nova/tests/utils.py
+++ b/nova/tests/utils.py
@@ -12,7 +12,7 @@
# 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 errno
import platform
@@ -212,5 +212,5 @@ def is_ipv6_supported():
if e.errno == errno.EAFNOSUPPORT:
has_ipv6_support = False
else:
- raise e
+ raise
return has_ipv6_support
diff --git a/nova/tests/virt/baremetal/db/test_bm_pxe_ip.py b/nova/tests/virt/baremetal/db/test_bm_pxe_ip.py
deleted file mode 100644
index 85f3e2f4b..000000000
--- a/nova/tests/virt/baremetal/db/test_bm_pxe_ip.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# Copyright (c) 2012 NTT DOCOMO, INC.
-# 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.
-
-"""
-Bare-metal DB testcase for BareMetalPxeIp
-"""
-
-from nova import exception
-from nova.openstack.common.db import exception as db_exc
-from nova.tests.virt.baremetal.db import base
-from nova.tests.virt.baremetal.db import utils
-from nova.virt.baremetal import db
-
-
-class BareMetalPxeIpTestCase(base.BMDBTestCase):
-
- def _create_pxe_ip(self):
- i1 = utils.new_bm_pxe_ip(address='10.1.1.1',
- server_address='10.1.1.101')
- i2 = utils.new_bm_pxe_ip(address='10.1.1.2',
- server_address='10.1.1.102')
-
- i1_ref = db.bm_pxe_ip_create_direct(self.context, i1)
- self.assertTrue(i1_ref['id'] is not None)
- self.assertEqual(i1_ref['address'], '10.1.1.1')
- self.assertEqual(i1_ref['server_address'], '10.1.1.101')
-
- i2_ref = db.bm_pxe_ip_create_direct(self.context, i2)
- self.assertTrue(i2_ref['id'] is not None)
- self.assertEqual(i2_ref['address'], '10.1.1.2')
- self.assertEqual(i2_ref['server_address'], '10.1.1.102')
-
- self.i1 = i1_ref
- self.i2 = i2_ref
-
- def test_unuque_address(self):
- self._create_pxe_ip()
-
- # address duplicates
- i = utils.new_bm_pxe_ip(address='10.1.1.1',
- server_address='10.1.1.201')
- self.assertRaises(db_exc.DBError,
- db.bm_pxe_ip_create_direct,
- self.context, i)
-
- # server_address duplicates
- i = utils.new_bm_pxe_ip(address='10.1.1.3',
- server_address='10.1.1.101')
- self.assertRaises(db_exc.DBError,
- db.bm_pxe_ip_create_direct,
- self.context, i)
-
- db.bm_pxe_ip_destroy(self.context, self.i1['id'])
- i = utils.new_bm_pxe_ip(address='10.1.1.1',
- server_address='10.1.1.101')
- ref = db.bm_pxe_ip_create_direct(self.context, i)
- self.assertTrue(ref is not None)
-
- def test_bm_pxe_ip_associate(self):
- self._create_pxe_ip()
- node = db.bm_node_create(self.context, utils.new_bm_node())
- ip_id = db.bm_pxe_ip_associate(self.context, node['id'])
- ref = db.bm_pxe_ip_get(self.context, ip_id)
- self.assertEqual(ref['bm_node_id'], node['id'])
-
- def test_bm_pxe_ip_associate_raise(self):
- self._create_pxe_ip()
- node_id = 123
- self.assertRaises(exception.NovaException,
- db.bm_pxe_ip_associate,
- self.context, node_id)
-
- def test_delete_by_address(self):
- self._create_pxe_ip()
- db.bm_pxe_ip_destroy_by_address(self.context, '10.1.1.1')
- del_ref = db.bm_pxe_ip_get(self.context, self.i1['id'])
- self.assertTrue(del_ref is None)
-
- def test_delete_by_address_not_exist(self):
- self._create_pxe_ip()
- del_ref = db.bm_pxe_ip_destroy_by_address(self.context, '10.11.12.13')
- self.assertTrue(del_ref is None)
diff --git a/nova/tests/virt/baremetal/db/utils.py b/nova/tests/virt/baremetal/db/utils.py
index c3b3cff5f..6faeb13d8 100644
--- a/nova/tests/virt/baremetal/db/utils.py
+++ b/nova/tests/virt/baremetal/db/utils.py
@@ -39,18 +39,6 @@ def new_bm_node(**kwargs):
return h
-def new_bm_pxe_ip(**kwargs):
- x = bm_models.BareMetalPxeIp()
- x.id = kwargs.pop('id', None)
- x.address = kwargs.pop('address', None)
- x.server_address = kwargs.pop('server_address', None)
- x.bm_node_id = kwargs.pop('bm_node_id', None)
- if len(kwargs) > 0:
- raise test.TestingException("unknown field: %s"
- % ','.join(kwargs.keys()))
- return x
-
-
def new_bm_interface(**kwargs):
x = bm_models.BareMetalInterface()
x.id = kwargs.pop('id', None)
diff --git a/nova/tests/virt/baremetal/test_pxe.py b/nova/tests/virt/baremetal/test_pxe.py
index 022f9c692..cd4e5c143 100644
--- a/nova/tests/virt/baremetal/test_pxe.py
+++ b/nova/tests/virt/baremetal/test_pxe.py
@@ -116,6 +116,7 @@ class PXEClassMethodsTestCase(BareMetalPXETestCase):
'deployment_ari_path': 'eee',
'aki_path': 'fff',
'ari_path': 'ggg',
+ 'network_info': self.test_network_info,
}
config = pxe.build_pxe_config(**args)
self.assertThat(config, matchers.StartsWith('default deploy'))
@@ -140,6 +141,21 @@ class PXEClassMethodsTestCase(BareMetalPXETestCase):
matchers.Not(matchers.Contains('kernel ddd')),
))
+ def test_build_pxe_network_config(self):
+ self.flags(
+ pxe_network_config=True,
+ group='baremetal',
+ )
+ net = utils.get_test_network_info(1)
+ config = pxe.build_pxe_network_config(net)
+ self.assertIn('eth0:off', config)
+ self.assertNotIn('eth1', config)
+
+ net = utils.get_test_network_info(2)
+ config = pxe.build_pxe_network_config(net)
+ self.assertIn('eth0:off', config)
+ self.assertIn('eth1:off', config)
+
def test_build_network_config(self):
net = utils.get_test_network_info(1)
config = pxe.build_network_config(net)
@@ -458,7 +474,8 @@ class PXEPublicMethodsTestCase(BareMetalPXETestCase):
bm_utils.random_alnum(32).AndReturn('alnum')
pxe.build_pxe_config(
self.node['id'], 'alnum', iqn,
- 'aaaa', 'bbbb', 'cccc', 'dddd').AndReturn(pxe_config)
+ 'aaaa', 'bbbb', 'cccc', 'dddd',
+ self.test_network_info).AndReturn(pxe_config)
bm_utils.write_to_file(pxe_path, pxe_config)
for mac in macs:
bm_utils.create_link_without_raise(
@@ -466,7 +483,8 @@ class PXEPublicMethodsTestCase(BareMetalPXETestCase):
self.mox.ReplayAll()
- self.driver.activate_bootloader(self.context, self.node, self.instance)
+ self.driver.activate_bootloader(self.context, self.node, self.instance,
+ network_info=self.test_network_info)
self.mox.VerifyAll()
@@ -515,8 +533,8 @@ class PXEPublicMethodsTestCase(BareMetalPXETestCase):
row = db.bm_node_get(self.context, 1)
self.assertTrue(row['deploy_key'] is None)
- self.driver.activate_bootloader(self.context, self.node,
- self.instance)
+ self.driver.activate_bootloader(self.context, self.node, self.instance,
+ network_info=self.test_network_info)
row = db.bm_node_get(self.context, 1)
self.assertTrue(row['deploy_key'] is not None)
diff --git a/nova/tests/virt/baremetal/test_tilera.py b/nova/tests/virt/baremetal/test_tilera.py
index 488cba4df..7ad5c4b6a 100755
--- a/nova/tests/virt/baremetal/test_tilera.py
+++ b/nova/tests/virt/baremetal/test_tilera.py
@@ -317,7 +317,8 @@ class TileraPublicMethodsTestCase(BareMetalTileraTestCase):
self.mox.ReplayAll()
- self.driver.activate_bootloader(self.context, self.node, self.instance)
+ self.driver.activate_bootloader(self.context, self.node, self.instance,
+ network_info=self.test_network_info)
self.mox.VerifyAll()
@@ -334,8 +335,8 @@ class TileraPublicMethodsTestCase(BareMetalTileraTestCase):
row = db.bm_node_get(self.context, 1)
self.assertTrue(row['deploy_key'] is None)
- self.driver.activate_bootloader(self.context, self.node,
- self.instance)
+ self.driver.activate_bootloader(self.context, self.node, self.instance,
+ network_info=self.test_network_info)
row = db.bm_node_get(self.context, 1)
self.assertTrue(row['deploy_key'] is not None)
diff --git a/nova/tests/virt/hyperv/test_hypervapi.py b/nova/tests/virt/hyperv/test_hypervapi.py
index cfc79c388..9f2d745ff 100644
--- a/nova/tests/virt/hyperv/test_hypervapi.py
+++ b/nova/tests/virt/hyperv/test_hypervapi.py
@@ -495,13 +495,24 @@ class HyperVAPITestCase(test.TestCase):
constants.HYPERV_VM_STATE_DISABLED)
def test_power_on(self):
- self._test_vm_state_change(self._conn.power_on,
- constants.HYPERV_VM_STATE_DISABLED,
- constants.HYPERV_VM_STATE_ENABLED)
+ self._instance_data = self._get_instance_data()
+ network_info = fake_network.fake_get_instance_nw_info(self.stubs,
+ spectacular=True)
+ vmutils.VMUtils.set_vm_state(mox.Func(self._check_instance_name),
+ constants.HYPERV_VM_STATE_ENABLED)
+ self._mox.ReplayAll()
+ self._conn.power_on(self._context, self._instance_data, network_info)
+ self._mox.VerifyAll()
def test_power_on_already_running(self):
- self._test_vm_state_change(self._conn.power_on, None,
- constants.HYPERV_VM_STATE_ENABLED)
+ self._instance_data = self._get_instance_data()
+ network_info = fake_network.fake_get_instance_nw_info(self.stubs,
+ spectacular=True)
+ vmutils.VMUtils.set_vm_state(mox.Func(self._check_instance_name),
+ constants.HYPERV_VM_STATE_ENABLED)
+ self._mox.ReplayAll()
+ self._conn.power_on(self._context, self._instance_data, network_info)
+ self._mox.VerifyAll()
def test_reboot(self):
diff --git a/nova/tests/virt/libvirt/test_libvirt.py b/nova/tests/virt/libvirt/test_libvirt.py
index 3c658a7f5..5636e1706 100644
--- a/nova/tests/virt/libvirt/test_libvirt.py
+++ b/nova/tests/virt/libvirt/test_libvirt.py
@@ -26,6 +26,7 @@ import re
import shutil
import tempfile
+from eventlet import greenthread
from lxml import etree
from oslo.config import cfg
from xml.dom import minidom
@@ -43,6 +44,7 @@ from nova.openstack.common import fileutils
from nova.openstack.common import importutils
from nova.openstack.common import jsonutils
from nova.openstack.common import loopingcall
+from nova.openstack.common import processutils
from nova.openstack.common import uuidutils
from nova import test
from nova.tests import fake_network
@@ -77,6 +79,7 @@ CONF.import_opt('compute_manager', 'nova.service')
CONF.import_opt('host', 'nova.netconf')
CONF.import_opt('my_ip', 'nova.netconf')
CONF.import_opt('base_dir_name', 'nova.virt.libvirt.imagecache')
+CONF.import_opt('instances_path', 'nova.compute.manager')
_fake_network_info = fake_network.fake_get_instance_nw_info
_fake_stub_out_get_nw_info = fake_network.stub_out_nw_api_get_instance_nw_info
@@ -286,8 +289,9 @@ class LibvirtConnTestCase(test.TestCase):
self.user_id = 'fake'
self.project_id = 'fake'
self.context = context.get_admin_context()
- self.flags(instances_path='')
- self.flags(libvirt_snapshots_directory='')
+ temp_dir = self.useFixture(fixtures.TempDir()).path
+ self.flags(instances_path=temp_dir)
+ self.flags(libvirt_snapshots_directory=temp_dir)
self.useFixture(fixtures.MonkeyPatch(
'nova.virt.libvirt.driver.libvirt_utils',
fake_libvirt_utils))
@@ -343,6 +347,9 @@ class LibvirtConnTestCase(test.TestCase):
'extra_specs': {},
'system_metadata': sys_meta}
+ def relpath(self, path):
+ return os.path.relpath(path, CONF.instances_path)
+
def tearDown(self):
nova.tests.image.fake.FakeImageService_reset()
super(LibvirtConnTestCase, self).tearDown()
@@ -589,8 +596,8 @@ class LibvirtConnTestCase(test.TestCase):
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = db.instance_create(self.context, self.test_instance)
- # make configdrive.enabled_for() return True
- instance_ref['config_drive'] = 'ANY_ID'
+ # make configdrive.required_by() return True
+ instance_ref['config_drive'] = True
disk_info = blockinfo.get_disk_info(CONF.libvirt_type,
instance_ref)
@@ -2078,8 +2085,8 @@ class LibvirtConnTestCase(test.TestCase):
else:
suffix = ''
if expect_kernel:
- check = (lambda t: t.find('./os/kernel').text.split(
- '/')[1], 'kernel' + suffix)
+ check = (lambda t: self.relpath(t.find('./os/kernel').text).
+ split('/')[1], 'kernel' + suffix)
else:
check = (lambda t: t.find('./os/kernel'), None)
check_list.append(check)
@@ -2094,8 +2101,8 @@ class LibvirtConnTestCase(test.TestCase):
check_list.append(check)
if expect_ramdisk:
- check = (lambda t: t.find('./os/initrd').text.split(
- '/')[1], 'ramdisk' + suffix)
+ check = (lambda t: self.relpath(t.find('./os/initrd').text).
+ split('/')[1], 'ramdisk' + suffix)
else:
check = (lambda t: t.find('./os/initrd'), None)
check_list.append(check)
@@ -2146,8 +2153,9 @@ class LibvirtConnTestCase(test.TestCase):
check = (lambda t: t.findall('./devices/serial')[1].get(
'type'), 'pty')
check_list.append(check)
- check = (lambda t: t.findall('./devices/serial/source')[0].get(
- 'path').split('/')[1], 'console.log')
+ check = (lambda t: self.relpath(t.findall(
+ './devices/serial/source')[0].get('path')).
+ split('/')[1], 'console.log')
check_list.append(check)
else:
check = (lambda t: t.find('./devices/console').get(
@@ -2159,16 +2167,16 @@ class LibvirtConnTestCase(test.TestCase):
(lambda t: t.find('./memory').text, '2097152')]
if rescue:
common_checks += [
- (lambda t: t.findall('./devices/disk/source')[0].get(
- 'file').split('/')[1], 'disk.rescue'),
- (lambda t: t.findall('./devices/disk/source')[1].get(
- 'file').split('/')[1], 'disk')]
+ (lambda t: self.relpath(t.findall('./devices/disk/source')[0].
+ get('file')).split('/')[1], 'disk.rescue'),
+ (lambda t: self.relpath(t.findall('./devices/disk/source')[1].
+ get('file')).split('/')[1], 'disk')]
else:
- common_checks += [(lambda t: t.findall(
- './devices/disk/source')[0].get('file').split('/')[1],
+ common_checks += [(lambda t: self.relpath(t.findall(
+ './devices/disk/source')[0].get('file')).split('/')[1],
'disk')]
- common_checks += [(lambda t: t.findall(
- './devices/disk/source')[1].get('file').split('/')[1],
+ common_checks += [(lambda t: self.relpath(t.findall(
+ './devices/disk/source')[1].get('file')).split('/')[1],
'disk.local')]
for (libvirt_type, (expected_uri, checks)) in type_uri_map.iteritems():
@@ -2683,6 +2691,80 @@ class LibvirtConnTestCase(test.TestCase):
db.instance_destroy(self.context, instance_ref['uuid'])
+ def test_get_instance_disk_info_excludes_volumes(self):
+ # 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>"
+ "<disk type='file'><driver name='qemu' type='qcow2'/>"
+ "<source file='/fake/path/to/volume1'/>"
+ "<target dev='vdc' bus='virtio'/></disk>"
+ "<disk type='file'><driver name='qemu' type='qcow2'/>"
+ "<source file='/fake/path/to/volume2'/>"
+ "<target dev='vdd' bus='virtio'/></disk>"
+ "</devices></domain>")
+
+ # 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)
+
+ GB = 1024 * 1024 * 1024
+ fake_libvirt_utils.disk_sizes['/test/disk'] = 10 * GB
+ fake_libvirt_utils.disk_sizes['/test/disk.local'] = 20 * GB
+ fake_libvirt_utils.disk_backing_files['/test/disk.local'] = 'file'
+
+ self.mox.StubOutWithMock(os.path, "getsize")
+ os.path.getsize('/test/disk').AndReturn((10737418240))
+ os.path.getsize('/test/disk.local').AndReturn((3328599655))
+
+ ret = ("image: /test/disk\n"
+ "file format: raw\n"
+ "virtual size: 20G (21474836480 bytes)\n"
+ "disk size: 3.1G\n"
+ "cluster_size: 2097152\n"
+ "backing file: /test/dummy (actual path: /backing/file)\n")
+
+ self.mox.StubOutWithMock(os.path, "exists")
+ os.path.exists('/test/disk.local').AndReturn(True)
+
+ self.mox.StubOutWithMock(utils, "execute")
+ utils.execute('env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info',
+ '/test/disk.local').AndReturn((ret, ''))
+
+ self.mox.ReplayAll()
+ conn_info = {'driver_volume_type': 'fake'}
+ info = {'block_device_mapping': [
+ {'connection_info': conn_info, 'mount_device': '/dev/vdc'},
+ {'connection_info': conn_info, 'mount_device': '/dev/vdd'}]}
+ conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
+ info = conn.get_instance_disk_info(instance_ref['name'],
+ block_device_info=info)
+ info = jsonutils.loads(info)
+ self.assertEquals(info[0]['type'], 'raw')
+ self.assertEquals(info[0]['path'], '/test/disk')
+ self.assertEquals(info[0]['disk_size'], 10737418240)
+ self.assertEquals(info[0]['backing_file'], "")
+ self.assertEquals(info[0]['over_committed_disk_size'], 0)
+ self.assertEquals(info[1]['type'], 'qcow2')
+ self.assertEquals(info[1]['path'], '/test/disk.local')
+ self.assertEquals(info[1]['virt_disk_size'], 21474836480)
+ self.assertEquals(info[1]['backing_file'], "file")
+ self.assertEquals(info[1]['over_committed_disk_size'], 18146236825)
+
+ db.instance_destroy(self.context, instance_ref['uuid'])
+
def test_spawn_with_network_info(self):
# Preparing mocks
def fake_none(*args, **kwargs):
@@ -3165,6 +3247,90 @@ class LibvirtConnTestCase(test.TestCase):
self.stubs.Set(os.path, 'exists', fake_os_path_exists)
conn.destroy(instance, [], None, False)
+ def test_reboot_different_ids(self):
+ class FakeLoopingCall:
+ def start(self, *a, **k):
+ return self
+
+ def wait(self):
+ return None
+
+ self.flags(libvirt_wait_soft_reboot_seconds=1)
+ info_tuple = ('fake', 'fake', 'fake', 'also_fake')
+ self.reboot_create_called = False
+
+ # Mock domain
+ mock_domain = self.mox.CreateMock(libvirt.virDomain)
+ mock_domain.info().AndReturn(
+ (libvirt_driver.VIR_DOMAIN_RUNNING,) + info_tuple)
+ mock_domain.ID().AndReturn('some_fake_id')
+ mock_domain.shutdown()
+ mock_domain.info().AndReturn(
+ (libvirt_driver.VIR_DOMAIN_CRASHED,) + info_tuple)
+ mock_domain.ID().AndReturn('some_other_fake_id')
+
+ self.mox.ReplayAll()
+
+ def fake_lookup_by_name(instance_name):
+ return mock_domain
+
+ def fake_create_domain(**kwargs):
+ self.reboot_create_called = True
+
+ conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
+ instance = {"name": "instancename", "id": "instanceid",
+ "uuid": "875a8070-d0b9-4949-8b31-104d125c9a64"}
+ self.stubs.Set(conn, '_lookup_by_name', fake_lookup_by_name)
+ self.stubs.Set(conn, '_create_domain', fake_create_domain)
+ self.stubs.Set(loopingcall, 'FixedIntervalLoopingCall',
+ lambda *a, **k: FakeLoopingCall())
+ conn.reboot(None, instance, [])
+ self.assertTrue(self.reboot_create_called)
+
+ def test_reboot_same_ids(self):
+ class FakeLoopingCall:
+ def start(self, *a, **k):
+ return self
+
+ def wait(self):
+ return None
+
+ self.flags(libvirt_wait_soft_reboot_seconds=1)
+ info_tuple = ('fake', 'fake', 'fake', 'also_fake')
+ self.reboot_hard_reboot_called = False
+
+ # Mock domain
+ mock_domain = self.mox.CreateMock(libvirt.virDomain)
+ mock_domain.info().AndReturn(
+ (libvirt_driver.VIR_DOMAIN_RUNNING,) + info_tuple)
+ mock_domain.ID().AndReturn('some_fake_id')
+ mock_domain.shutdown()
+ mock_domain.info().AndReturn(
+ (libvirt_driver.VIR_DOMAIN_CRASHED,) + info_tuple)
+ mock_domain.ID().AndReturn('some_fake_id')
+
+ self.mox.ReplayAll()
+
+ def fake_lookup_by_name(instance_name):
+ return mock_domain
+
+ def fake_hard_reboot(*args, **kwargs):
+ self.reboot_hard_reboot_called = True
+
+ def fake_sleep(interval):
+ pass
+
+ conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
+ instance = {"name": "instancename", "id": "instanceid",
+ "uuid": "875a8070-d0b9-4949-8b31-104d125c9a64"}
+ self.stubs.Set(conn, '_lookup_by_name', fake_lookup_by_name)
+ self.stubs.Set(greenthread, 'sleep', fake_sleep)
+ self.stubs.Set(conn, '_hard_reboot', fake_hard_reboot)
+ self.stubs.Set(loopingcall, 'FixedIntervalLoopingCall',
+ lambda *a, **k: FakeLoopingCall())
+ conn.reboot(None, instance, [])
+ self.assertTrue(self.reboot_hard_reboot_called)
+
def test_destroy_undefines(self):
mock = self.mox.CreateMock(libvirt.virDomain)
mock.ID()
@@ -3931,6 +4097,88 @@ class LibvirtConnTestCase(test.TestCase):
self.mox.ReplayAll()
self.assertTrue(conn._is_storage_shared_with('foo', '/path'))
+ def test_create_domain_define_xml_fails(self):
+ """
+ Tests that the xml is logged when defining the domain fails.
+ """
+ fake_xml = "<test>this is a test</test>"
+
+ def fake_defineXML(xml):
+ self.assertEquals(fake_xml, xml)
+ raise libvirt.libvirtError('virDomainDefineXML() failed')
+
+ self.log_error_called = False
+
+ def fake_error(msg):
+ self.log_error_called = True
+ self.assertTrue(fake_xml in msg)
+
+ self.stubs.Set(nova.virt.libvirt.driver.LOG, 'error', fake_error)
+
+ self.create_fake_libvirt_mock(defineXML=fake_defineXML)
+ self.mox.ReplayAll()
+ conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
+
+ self.assertRaises(libvirt.libvirtError, conn._create_domain, fake_xml)
+ self.assertTrue(self.log_error_called)
+
+ def test_create_domain_with_flags_fails(self):
+ """
+ Tests that the xml is logged when creating the domain with flags fails.
+ """
+ fake_xml = "<test>this is a test</test>"
+ fake_domain = FakeVirtDomain(fake_xml)
+
+ def fake_createWithFlags(launch_flags):
+ raise libvirt.libvirtError('virDomainCreateWithFlags() failed')
+
+ self.log_error_called = False
+
+ def fake_error(msg):
+ self.log_error_called = True
+ self.assertTrue(fake_xml in msg)
+
+ self.stubs.Set(fake_domain, 'createWithFlags', fake_createWithFlags)
+ self.stubs.Set(nova.virt.libvirt.driver.LOG, 'error', fake_error)
+
+ self.create_fake_libvirt_mock()
+ self.mox.ReplayAll()
+ conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
+
+ self.assertRaises(libvirt.libvirtError, conn._create_domain,
+ domain=fake_domain)
+ self.assertTrue(self.log_error_called)
+
+ def test_create_domain_enable_hairpin_fails(self):
+ """
+ Tests that the xml is logged when enabling hairpin mode for the domain
+ fails.
+ """
+ fake_xml = "<test>this is a test</test>"
+ fake_domain = FakeVirtDomain(fake_xml)
+
+ def fake_enable_hairpin(launch_flags):
+ raise processutils.ProcessExecutionError('error')
+
+ self.log_error_called = False
+
+ def fake_error(msg):
+ self.log_error_called = True
+ self.assertTrue(fake_xml in msg)
+
+ self.stubs.Set(nova.virt.libvirt.driver.LOG, 'error', fake_error)
+
+ self.create_fake_libvirt_mock()
+ self.mox.ReplayAll()
+ conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
+ self.stubs.Set(conn, '_enable_hairpin', fake_enable_hairpin)
+
+ self.assertRaises(processutils.ProcessExecutionError,
+ conn._create_domain,
+ domain=fake_domain,
+ power_on=False)
+ self.assertTrue(self.log_error_called)
+
class HostStateTestCase(test.TestCase):
@@ -4945,10 +5193,9 @@ class LibvirtDriverTestCase(test.TestCase):
inst['host'] = 'host1'
inst['root_gb'] = 10
inst['ephemeral_gb'] = 20
- inst['config_drive'] = 1
+ inst['config_drive'] = True
inst['kernel_id'] = 2
inst['ramdisk_id'] = 3
- inst['config_drive_id'] = 1
inst['key_data'] = 'ABCDEFG'
inst['system_metadata'] = sys_meta
@@ -4963,7 +5210,8 @@ class LibvirtDriverTestCase(test.TestCase):
self.counter = 0
self.checked_shared_storage = False
- def fake_get_instance_disk_info(instance, xml=None):
+ def fake_get_instance_disk_info(instance, xml=None,
+ block_device_info=None):
return '[]'
def fake_destroy(instance):
@@ -5015,7 +5263,8 @@ class LibvirtDriverTestCase(test.TestCase):
'disk_size': '83886080'}]
disk_info_text = jsonutils.dumps(disk_info)
- def fake_get_instance_disk_info(instance, xml=None):
+ def fake_get_instance_disk_info(instance, xml=None,
+ block_device_info=None):
return disk_info_text
def fake_destroy(instance):
diff --git a/nova/tests/virt/libvirt/test_libvirt_vif.py b/nova/tests/virt/libvirt/test_libvirt_vif.py
index c9c6aef12..7cbf67b07 100644
--- a/nova/tests/virt/libvirt/test_libvirt_vif.py
+++ b/nova/tests/virt/libvirt/test_libvirt_vif.py
@@ -103,6 +103,17 @@ class LibvirtVifTestCase(test.TestCase):
'ovs_interfaceid': 'aaa-bbb-ccc',
}
+ mapping_ivs = {
+ 'mac': 'ca:fe:de:ad:be:ef',
+ 'gateway_v6': net_ovs['gateway_v6'],
+ 'ips': [{'ip': '101.168.1.9'}],
+ 'dhcp_server': '191.168.1.1',
+ 'vif_uuid': 'vif-xxx-yyy-zzz',
+ 'vif_devname': 'tap-xxx-yyy-zzz',
+ 'vif_type': network_model.VIF_TYPE_IVS,
+ 'ivs_interfaceid': 'aaa-bbb-ccc',
+ }
+
mapping_ovs_legacy = {
'mac': 'ca:fe:de:ad:be:ef',
'gateway_v6': net_ovs['gateway_v6'],
@@ -411,6 +422,24 @@ class LibvirtVifTestCase(test.TestCase):
self.mapping_bridge_quantum,
br_want)
+ def _check_ivs_ethernet_driver(self, d, net, mapping, dev_prefix):
+ self.flags(firewall_driver="nova.virt.firewall.NoopFirewallDriver")
+ xml = self._get_instance_xml(d, net, mapping)
+
+ doc = etree.fromstring(xml)
+ ret = doc.findall('./devices/interface')
+ self.assertEqual(len(ret), 1)
+ node = ret[0]
+ ret = node.findall("filterref")
+ self.assertEqual(len(ret), 0)
+ self.assertEqual(node.get("type"), "ethernet")
+ dev_name = node.find("target").get("dev")
+ self.assertTrue(dev_name.startswith(dev_prefix))
+ mac = node.find("mac").get("address")
+ self.assertEqual(mac, self.mapping_ivs['mac'])
+ script = node.find("script").get("path")
+ self.assertEquals(script, "")
+
def _check_ovs_ethernet_driver(self, d, net, mapping, dev_prefix):
self.flags(firewall_driver="nova.virt.firewall.NoopFirewallDriver")
xml = self._get_instance_xml(d, net, mapping)
@@ -451,6 +480,33 @@ class LibvirtVifTestCase(test.TestCase):
self.mapping_ovs,
"tap")
+ def test_ivs_ethernet_driver(self):
+ def get_connection():
+ return fakelibvirt.Connection("qemu:///session",
+ False,
+ 9010)
+ d = vif.LibvirtGenericVIFDriver(get_connection)
+ self._check_ivs_ethernet_driver(d,
+ self.net_ovs,
+ self.mapping_ivs,
+ "tap")
+
+ def _check_ivs_virtualport_driver(self, d, net, mapping, want_iface_id):
+ self.flags(firewall_driver="nova.virt.firewall.NoopFirewallDriver")
+ xml = self._get_instance_xml(d, net, mapping)
+ doc = etree.fromstring(xml)
+ ret = doc.findall('./devices/interface')
+ self.assertEqual(len(ret), 1)
+ node = ret[0]
+ ret = node.findall("filterref")
+ self.assertEqual(len(ret), 0)
+ self.assertEqual(node.get("type"), "ethernet")
+
+ tap_name = node.find("target").get("dev")
+ self.assertEqual(tap_name, mapping['vif_devname'])
+ mac = node.find("mac").get("address")
+ self.assertEqual(mac, mapping['mac'])
+
def _check_ovs_virtualport_driver(self, d, net, mapping, want_iface_id):
self.flags(firewall_driver="nova.virt.firewall.NoopFirewallDriver")
xml = self._get_instance_xml(d, net, mapping)
@@ -502,6 +558,18 @@ class LibvirtVifTestCase(test.TestCase):
self.mapping_ovs,
want_iface_id)
+ def test_generic_ivs_virtualport_driver(self):
+ def get_connection():
+ return fakelibvirt.Connection("qemu:///session",
+ False,
+ 9011)
+ d = vif.LibvirtGenericVIFDriver(get_connection)
+ want_iface_id = self.mapping_ivs['ivs_interfaceid']
+ self._check_ivs_virtualport_driver(d,
+ self.net_ovs,
+ self.mapping_ivs,
+ want_iface_id)
+
def _check_quantum_hybrid_driver(self, d, net, mapping, br_want):
self.flags(firewall_driver="nova.virt.firewall.IptablesFirewallDriver")
xml = self._get_instance_xml(d, net, mapping)
@@ -542,6 +610,18 @@ class LibvirtVifTestCase(test.TestCase):
self.mapping_ovs,
br_want)
+ def test_ivs_hybrid_driver(self):
+ def get_connection():
+ return fakelibvirt.Connection("qemu:///session",
+ False)
+ d = vif.LibvirtGenericVIFDriver(get_connection)
+ br_want = "qbr" + self.mapping_ivs['vif_uuid']
+ br_want = br_want[:network_model.NIC_NAME_LEN]
+ self._check_quantum_hybrid_driver(d,
+ self.net_ovs,
+ self.mapping_ivs,
+ br_want)
+
def test_generic_8021qbh_driver(self):
def get_connection():
return fakelibvirt.Connection("qemu:///session",
diff --git a/nova/tests/virt/test_virt_drivers.py b/nova/tests/virt/test_virt_drivers.py
index 47f983258..6cc9bef43 100644
--- a/nova/tests/virt/test_virt_drivers.py
+++ b/nova/tests/virt/test_virt_drivers.py
@@ -60,7 +60,7 @@ class _FakeDriverBackendTestCase(object):
# So that the _supports_direct_io does the test based
# on the current working directory, instead of the
# default instances_path which doesn't exist
- self.flags(instances_path='')
+ self.flags(instances_path=self.useFixture(fixtures.TempDir()).path)
# Put fakelibvirt in place
if 'libvirt' in sys.modules:
@@ -106,7 +106,8 @@ class _FakeDriverBackendTestCase(object):
def fake_make_drive(_self, _path):
pass
- def fake_get_instance_disk_info(_self, instance, xml=None):
+ def fake_get_instance_disk_info(_self, instance, xml=None,
+ block_device_info=None):
return '[]'
self.stubs.Set(nova.virt.libvirt.driver.LibvirtDriver,
@@ -311,13 +312,14 @@ class _VirtDriverTestCase(_FakeDriverBackendTestCase):
@catch_notimplementederror
def test_power_on_running(self):
instance_ref, network_info = self._get_running_instance()
- self.connection.power_on(instance_ref)
+ self.connection.power_on(self.ctxt, instance_ref,
+ network_info, None)
@catch_notimplementederror
def test_power_on_powered_off(self):
instance_ref, network_info = self._get_running_instance()
self.connection.power_off(instance_ref)
- self.connection.power_on(instance_ref)
+ self.connection.power_on(self.ctxt, instance_ref, network_info, None)
@catch_notimplementederror
def test_soft_delete(self):
@@ -407,7 +409,24 @@ class _VirtDriverTestCase(_FakeDriverBackendTestCase):
self.connection.attach_volume({'driver_volume_type': 'fake'},
instance_ref,
'/dev/sda')
- self.connection.power_on(instance_ref)
+
+ bdm = {
+ 'root_device_name': None,
+ 'swap': None,
+ 'ephemerals': [],
+ 'block_device_mapping': [{
+ 'instance_uuid': instance_ref['uuid'],
+ 'connection_info': {'driver_volume_type': 'fake'},
+ 'mount_device': '/dev/sda',
+ 'delete_on_termination': False,
+ 'virtual_name': None,
+ 'snapshot_id': None,
+ 'volume_id': 'abcdedf',
+ 'volume_size': None,
+ 'no_device': None
+ }]
+ }
+ self.connection.power_on(self.ctxt, instance_ref, network_info, bdm)
self.connection.detach_volume({'driver_volume_type': 'fake'},
instance_ref,
'/dev/sda')
diff --git a/nova/tests/virt/vmwareapi/db_fakes.py b/nova/tests/virt/vmwareapi/db_fakes.py
index 93fcf6e13..87c3dde67 100644
--- a/nova/tests/virt/vmwareapi/db_fakes.py
+++ b/nova/tests/virt/vmwareapi/db_fakes.py
@@ -1,5 +1,6 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
+# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack Foundation
#
@@ -74,6 +75,7 @@ def stub_out_db_instance_api(stubs):
'vcpus': type_data['vcpus'],
'mac_addresses': [{'address': values['mac_address']}],
'root_gb': type_data['root_gb'],
+ 'node': values['node'],
}
return FakeModel(base_options)
diff --git a/nova/tests/virt/vmwareapi/test_vmwareapi.py b/nova/tests/virt/vmwareapi/test_vmwareapi.py
index 69a9ffab8..afda26b0d 100644
--- a/nova/tests/virt/vmwareapi/test_vmwareapi.py
+++ b/nova/tests/virt/vmwareapi/test_vmwareapi.py
@@ -1,5 +1,6 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
+# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
# Copyright (c) 2012 VMware, Inc.
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack Foundation
@@ -111,6 +112,7 @@ class VMwareAPIVMTestCase(test.TestCase):
use_linked_clone=False)
self.user_id = 'fake'
self.project_id = 'fake'
+ self.node_name = 'test_url'
self.context = context.RequestContext(self.user_id, self.project_id)
vmwareapi_fake.reset()
db_fakes.stub_out_db_instance_api(self.stubs)
@@ -143,6 +145,7 @@ class VMwareAPIVMTestCase(test.TestCase):
'ramdisk_id': "1",
'mac_address': "de:ad:be:ef:be:ef",
'instance_type': 'm1.large',
+ 'node': self.node_name,
}
self.instance = db.instance_create(None, values)
@@ -332,14 +335,14 @@ class VMwareAPIVMTestCase(test.TestCase):
self.conn.power_off(self.instance)
info = self.conn.get_info({'uuid': 'fake-uuid'})
self._check_vm_info(info, power_state.SHUTDOWN)
- self.conn.power_on(self.instance)
+ self.conn.power_on(self.context, self.instance, self.network_info)
info = self.conn.get_info({'uuid': 'fake-uuid'})
self._check_vm_info(info, power_state.RUNNING)
def test_power_on_non_existent(self):
self._create_instance_in_the_db()
self.assertRaises(exception.InstanceNotFound, self.conn.power_on,
- self.instance)
+ self.context, self.instance, self.network_info)
def test_power_off(self):
self._create_vm()
@@ -424,7 +427,7 @@ class VMwareAPIVMTestCase(test.TestCase):
self.assertEquals(4, step)
self.assertEqual(vmops.RESIZE_TOTAL_STEPS, total_steps)
- self.stubs.Set(self.conn._vmops, "power_on", fake_power_on)
+ self.stubs.Set(self.conn._vmops, "_power_on", fake_power_on)
self.stubs.Set(self.conn._vmops, "_update_instance_progress",
fake_vmops_update_instance_progress)
@@ -436,6 +439,7 @@ class VMwareAPIVMTestCase(test.TestCase):
instance=self.instance,
disk_info=None,
network_info=None,
+ block_device_info=None,
image_meta=None,
power_on=power_on)
# verify the results
@@ -472,15 +476,20 @@ class VMwareAPIVMTestCase(test.TestCase):
self.assertEquals(self.vm_name, vm_name)
return vmwareapi_fake._get_objects("VirtualMachine")[0]
+ def fake_get_vm_ref_from_uuid(session, vm_uuid):
+ return vmwareapi_fake._get_objects("VirtualMachine")[0]
+
def fake_call_method(*args, **kwargs):
pass
def fake_wait_for_task(*args, **kwargs):
pass
- self.stubs.Set(self.conn._vmops, "power_on", fake_power_on)
+ self.stubs.Set(self.conn._vmops, "_power_on", fake_power_on)
self.stubs.Set(self.conn._vmops, "_get_orig_vm_name_label",
fake_get_orig_vm_name_label)
+ self.stubs.Set(vm_util, "get_vm_ref_from_uuid",
+ fake_get_vm_ref_from_uuid)
self.stubs.Set(vm_util, "get_vm_ref_from_name",
fake_get_vm_ref_from_name)
self.stubs.Set(self.conn._session, "_call_method", fake_call_method)
@@ -500,6 +509,41 @@ class VMwareAPIVMTestCase(test.TestCase):
def test_finish_revert_migration_power_off(self):
self._test_finish_revert_migration(power_on=False)
+ def test_diagnostics_non_existent_vm(self):
+ self._create_instance_in_the_db()
+ self.assertRaises(exception.InstanceNotFound,
+ self.conn.get_diagnostics,
+ self.instance)
+
+ def test_get_console_pool_info(self):
+ info = self.conn.get_console_pool_info("console_type")
+ self.assertEquals(info['address'], 'test_url')
+ self.assertEquals(info['username'], 'test_username')
+ self.assertEquals(info['password'], 'test_pass')
+
+ def test_get_vnc_console_non_existent(self):
+ self._create_instance_in_the_db()
+ self.assertRaises(exception.InstanceNotFound,
+ self.conn.get_vnc_console,
+ self.instance)
+
+ def test_get_vnc_console(self):
+ self._create_instance_in_the_db()
+ self._create_vm()
+ vnc_dict = self.conn.get_vnc_console(self.instance)
+ self.assertEquals(vnc_dict['host'], "ha-host")
+ self.assertEquals(vnc_dict['port'], 5910)
+
+ def test_host_ip_addr(self):
+ self.assertEquals(self.conn.get_host_ip_addr(), "test_url")
+
+ def test_get_volume_connector(self):
+ self._create_instance_in_the_db()
+ connector_dict = self.conn.get_volume_connector(self.instance)
+ self.assertEquals(connector_dict['ip'], "test_url")
+ self.assertEquals(connector_dict['initiator'], "iscsi-name")
+ self.assertEquals(connector_dict['host'], "test_url")
+
class VMwareAPIHostTestCase(test.TestCase):
"""Unit tests for Vmware API host calls."""
@@ -547,3 +591,30 @@ class VMwareAPIHostTestCase(test.TestCase):
def test_host_maintenance_off(self):
self._test_host_action(self.conn.host_maintenance_mode, False)
+
+
+class VMwareAPIVCDriverTestCase(VMwareAPIVMTestCase):
+
+ def setUp(self):
+ super(VMwareAPIVCDriverTestCase, self).setUp()
+ self.flags(
+ vmwareapi_cluster_name='test_cluster',
+ vmwareapi_task_poll_interval=10,
+ vnc_enabled=False
+ )
+ self.conn = driver.VMwareVCDriver(None, False)
+
+ def tearDown(self):
+ super(VMwareAPIVCDriverTestCase, self).tearDown()
+ vmwareapi_fake.cleanup()
+
+ def test_get_available_resource(self):
+ stats = self.conn.get_available_resource(self.node_name)
+ self.assertEquals(stats['vcpus'], 16)
+ self.assertEquals(stats['local_gb'], 1024)
+ self.assertEquals(stats['local_gb_used'], 1024 - 500)
+ self.assertEquals(stats['memory_mb'], 1024)
+ self.assertEquals(stats['memory_mb_used'], 1024 - 524)
+ self.assertEquals(stats['hypervisor_type'], 'VMware ESXi')
+ self.assertEquals(stats['hypervisor_version'], '5.0.0')
+ self.assertEquals(stats['hypervisor_hostname'], 'test_url')
diff --git a/nova/tests/virt/vmwareapi/test_vmwareapi_vm_util.py b/nova/tests/virt/vmwareapi/test_vmwareapi_vm_util.py
index 123a314c1..0456dfece 100644
--- a/nova/tests/virt/vmwareapi/test_vmwareapi_vm_util.py
+++ b/nova/tests/virt/vmwareapi/test_vmwareapi_vm_util.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from collections import namedtuple
+
from nova import exception
from nova import test
from nova.virt.vmwareapi import fake
@@ -33,9 +35,11 @@ class fake_session(object):
class VMwareVMUtilTestCase(test.TestCase):
def setUp(self):
super(VMwareVMUtilTestCase, self).setUp()
+ fake.reset()
def tearDown(self):
super(VMwareVMUtilTestCase, self).tearDown()
+ fake.reset()
def test_get_datastore_ref_and_name(self):
result = vm_util.get_datastore_ref_and_name(
@@ -54,3 +58,95 @@ class VMwareVMUtilTestCase(test.TestCase):
self.assertRaises(exception.DatastoreNotFound,
vm_util.get_datastore_ref_and_name,
fake_session(), cluster="fake-cluster")
+
+ def test_get_host_ref_from_id(self):
+
+ fake_host_sys = fake.HostSystem(
+ fake.ManagedObjectReference("HostSystem", "host-123"))
+
+ fake_host_id = fake_host_sys.obj.value
+ fake_host_name = "ha-host"
+
+ ref = vm_util.get_host_ref_from_id(
+ fake_session([fake_host_sys]), fake_host_id, ['name'])
+
+ self.assertIsInstance(ref, fake.HostSystem)
+ self.assertEqual(fake_host_id, ref.obj.value)
+
+ host_name = vm_util.get_host_name_from_host_ref(ref)
+
+ self.assertEquals(fake_host_name, host_name)
+
+ def test_get_host_name_for_vm(self):
+
+ fake_vm = fake.ManagedObject(
+ "VirtualMachine", fake.ManagedObjectReference(
+ "vm-123", "VirtualMachine"))
+ fake_vm.propSet.append(
+ fake.Property('name', 'vm-123'))
+
+ vm_ref = vm_util.get_vm_ref_from_name(
+ fake_session([fake_vm]), 'vm-123')
+
+ self.assertIsNotNone(vm_ref)
+
+ fake_results = [
+ fake.ObjectContent(
+ None, [
+ fake.Property('runtime.host',
+ fake.ManagedObjectReference(
+ 'host-123', 'HostSystem'))
+ ])]
+
+ host_id = vm_util.get_host_id_from_vm_ref(
+ fake_session(fake_results), vm_ref)
+
+ self.assertEqual('host-123', host_id)
+
+ def test_property_from_property_set(self):
+
+ ObjectContent = namedtuple('ObjectContent', ['propSet'])
+ DynamicProperty = namedtuple('Property', ['name', 'val'])
+ MoRef = namedtuple('Val', ['value'])
+
+ results_good = [
+ ObjectContent(propSet=[
+ DynamicProperty(name='name', val=MoRef(value='vm-123'))]),
+ ObjectContent(propSet=[
+ DynamicProperty(name='foo', val=MoRef(value='bar1')),
+ DynamicProperty(
+ name='runtime.host', val=MoRef(value='host-123')),
+ DynamicProperty(name='foo', val=MoRef(value='bar2')),
+ ]),
+ ObjectContent(propSet=[
+ DynamicProperty(
+ name='something', val=MoRef(value='thing'))]), ]
+
+ results_bad = [
+ ObjectContent(propSet=[
+ DynamicProperty(name='name', val=MoRef(value='vm-123'))]),
+ ObjectContent(propSet=[
+ DynamicProperty(name='foo', val='bar1'),
+ DynamicProperty(name='foo', val='bar2'), ]),
+ ObjectContent(propSet=[
+ DynamicProperty(
+ name='something', val=MoRef(value='thing'))]), ]
+
+ prop = vm_util.property_from_property_set(
+ 'runtime.host', results_good)
+ self.assertIsNotNone(prop)
+ value = prop.val.value
+ self.assertEqual('host-123', value)
+
+ prop2 = vm_util.property_from_property_set(
+ 'runtime.host', results_bad)
+ self.assertIsNone(prop2)
+
+ prop3 = vm_util.property_from_property_set('foo', results_good)
+ self.assertIsNotNone(prop3)
+ val3 = prop3.val.value
+ self.assertEqual('bar1', val3)
+
+ prop4 = vm_util.property_from_property_set('foo', results_bad)
+ self.assertIsNotNone(prop4)
+ self.assertEqual('bar1', prop4.val)
diff --git a/nova/tests/virt/xenapi/test_vm_utils.py b/nova/tests/virt/xenapi/test_vm_utils.py
index 68caab651..6884ab5a8 100644
--- a/nova/tests/virt/xenapi/test_vm_utils.py
+++ b/nova/tests/virt/xenapi/test_vm_utils.py
@@ -266,7 +266,7 @@ class FetchVhdImageTestCase(test.TestCase):
self._apply_stubouts()
self._common_params_setup(True)
- vm_utils._add_bittorrent_params(self.params)
+ vm_utils._add_bittorrent_params(self.image_id, self.params)
vm_utils._fetch_using_dom0_plugin_with_retry(self.context,
self.session, self.image_id, "bittorrent", self.params,
@@ -289,7 +289,7 @@ class FetchVhdImageTestCase(test.TestCase):
self._common_params_setup(True)
self.mox.StubOutWithMock(self.session, 'call_xenapi')
- vm_utils._add_bittorrent_params(self.params)
+ vm_utils._add_bittorrent_params(self.image_id, self.params)
vm_utils._fetch_using_dom0_plugin_with_retry(self.context,
self.session, self.image_id, "bittorrent", self.params,
diff --git a/nova/tests/virt/xenapi/test_xenapi.py b/nova/tests/virt/xenapi/test_xenapi.py
index 91d4f0770..f6ff23aba 100644
--- a/nova/tests/virt/xenapi/test_xenapi.py
+++ b/nova/tests/virt/xenapi/test_xenapi.py
@@ -31,6 +31,7 @@ from nova.compute import power_state
from nova.compute import task_states
from nova.compute import vm_states
from nova import context
+from nova import crypto
from nova import db
from nova import exception
from nova.openstack.common import importutils
@@ -983,13 +984,14 @@ class XenAPIVMTestCase(stubs.XenAPITestBase):
actual_injected_files.append((path, contents))
return jsonutils.dumps({'returncode': '0', 'message': 'success'})
- def noop(*args, **kwargs):
- pass
-
self.stubs.Set(stubs.FakeSessionForVMTests,
'_plugin_agent_inject_file', fake_inject_file)
- self.stubs.Set(agent.XenAPIBasedAgent,
- 'set_admin_password', noop)
+
+ def fake_encrypt_text(sshkey, new_pass):
+ self.assertEqual("fake_keydata", sshkey)
+ return "fake"
+
+ self.stubs.Set(crypto, 'ssh_encrypt_text', fake_encrypt_text)
expected_data = ('\n# The following ssh key was injected by '
'Nova\nfake_keydata\n')
@@ -1020,6 +1022,93 @@ class XenAPIVMTestCase(stubs.XenAPITestBase):
self.check_vm_params_for_linux()
self.assertEquals(actual_injected_files, injected_files)
+ def test_spawn_agent_upgrade(self):
+ self.flags(xenapi_use_agent_default=True)
+ actual_injected_files = []
+
+ def fake_agent_build(_self, *args):
+ return {"version": "1.1.0", "architecture": "x86-64",
+ "hypervisor": "xen", "os": "windows",
+ "url": "url", "md5hash": "asdf"}
+
+ self.stubs.Set(self.conn.virtapi, 'agent_build_get_by_triple',
+ fake_agent_build)
+
+ self._test_spawn(IMAGE_VHD, None, None,
+ os_type="linux", architecture="x86-64")
+
+ def test_spawn_agent_upgrade_fails_silently(self):
+ self.flags(xenapi_use_agent_default=True)
+ actual_injected_files = []
+
+ def fake_agent_build(_self, *args):
+ return {"version": "1.1.0", "architecture": "x86-64",
+ "hypervisor": "xen", "os": "windows",
+ "url": "url", "md5hash": "asdf"}
+
+ self.stubs.Set(self.conn.virtapi, 'agent_build_get_by_triple',
+ fake_agent_build)
+
+ def fake_agent_update(self, method, args):
+ raise xenapi_fake.Failure(["fake_error"])
+
+ self.stubs.Set(stubs.FakeSessionForVMTests,
+ '_plugin_agent_agentupdate', fake_agent_update)
+
+ self._test_spawn(IMAGE_VHD, None, None,
+ os_type="linux", architecture="x86-64")
+
+ def _test_spawn_fails_with(self, trigger, expected_exception):
+ self.flags(xenapi_use_agent_default=True)
+ self.flags(agent_version_timeout=0)
+ actual_injected_files = []
+
+ def fake_agent_version(self, method, args):
+ raise xenapi_fake.Failure([trigger])
+
+ self.stubs.Set(stubs.FakeSessionForVMTests,
+ '_plugin_agent_version', fake_agent_version)
+
+ self.assertRaises(expected_exception, self._test_spawn,
+ IMAGE_VHD, None, None, os_type="linux", architecture="x86-64")
+
+ def test_spawn_fails_with_agent_timeout(self):
+ self._test_spawn_fails_with("TIMEOUT:fake", exception.AgentTimeout)
+
+ def test_spawn_fails_with_agent_not_implemented(self):
+ self._test_spawn_fails_with("NOT IMPLEMENTED:fake",
+ exception.AgentNotImplemented)
+
+ def test_spawn_fails_with_agent_error(self):
+ self._test_spawn_fails_with("fake_error", exception.AgentError)
+
+ def test_spawn_fails_with_agent_bad_return(self):
+ self.flags(xenapi_use_agent_default=True)
+ self.flags(agent_version_timeout=0)
+ actual_injected_files = []
+
+ def fake_agent_version(self, method, args):
+ return xenapi_fake.as_json(returncode='-1', message='fake')
+ self.stubs.Set(stubs.FakeSessionForVMTests,
+ '_plugin_agent_version', fake_agent_version)
+
+ self.assertRaises(exception.AgentError, self._test_spawn,
+ IMAGE_VHD, None, None, os_type="linux", architecture="x86-64")
+
+ def test_spawn_fails_agent_not_implemented(self):
+ # Test spawning with injected_files.
+ self.flags(xenapi_use_agent_default=True)
+ self.flags(agent_version_timeout=0)
+ actual_injected_files = []
+
+ def fake_agent_version(self, method, args):
+ raise xenapi_fake.Failure(["NOT IMPLEMENTED:fake"])
+ self.stubs.Set(stubs.FakeSessionForVMTests,
+ '_plugin_agent_version', fake_agent_version)
+
+ self.assertRaises(exception.AgentNotImplemented, self._test_spawn,
+ IMAGE_VHD, None, None, os_type="linux", architecture="x86-64")
+
def test_rescue(self):
instance = self._create_instance()
session = xenapi_conn.XenAPISession('test_url', 'root', 'test_pass',