summaryrefslogtreecommitdiff
path: root/nova/tests/conductor/test_conductor.py
diff options
context:
space:
mode:
Diffstat (limited to 'nova/tests/conductor/test_conductor.py')
-rw-r--r--nova/tests/conductor/test_conductor.py2151
1 files changed, 0 insertions, 2151 deletions
diff --git a/nova/tests/conductor/test_conductor.py b/nova/tests/conductor/test_conductor.py
deleted file mode 100644
index 8f2d6bbe5f..0000000000
--- a/nova/tests/conductor/test_conductor.py
+++ /dev/null
@@ -1,2151 +0,0 @@
-# Copyright 2012 IBM Corp.
-# Copyright 2013 Red Hat, 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.
-
-"""Tests for the conductor service."""
-
-import contextlib
-
-import mock
-import mox
-from oslo.config import cfg
-from oslo import messaging
-from oslo.serialization import jsonutils
-from oslo.utils import timeutils
-
-from nova.api.ec2 import ec2utils
-from nova.compute import arch
-from nova.compute import flavors
-from nova.compute import task_states
-from nova.compute import utils as compute_utils
-from nova.compute import vm_states
-from nova import conductor
-from nova.conductor import api as conductor_api
-from nova.conductor import manager as conductor_manager
-from nova.conductor import rpcapi as conductor_rpcapi
-from nova.conductor.tasks import live_migrate
-from nova import context
-from nova import db
-from nova.db.sqlalchemy import models
-from nova import exception as exc
-from nova import notifications
-from nova import objects
-from nova.objects import base as obj_base
-from nova.objects import block_device as block_device_obj
-from nova.objects import fields
-from nova.objects import quotas as quotas_obj
-from nova import quota
-from nova import rpc
-from nova.scheduler import driver as scheduler_driver
-from nova.scheduler import utils as scheduler_utils
-from nova import test
-from nova.tests import cast_as_call
-from nova.tests.compute import test_compute
-from nova.tests import fake_block_device
-from nova.tests import fake_instance
-from nova.tests import fake_notifier
-from nova.tests import fake_server_actions
-from nova.tests import fake_utils
-from nova import utils
-
-
-CONF = cfg.CONF
-CONF.import_opt('report_interval', 'nova.service')
-
-
-FAKE_IMAGE_REF = 'fake-image-ref'
-
-
-class FakeContext(context.RequestContext):
- def elevated(self):
- """Return a consistent elevated context so we can detect it."""
- if not hasattr(self, '_elevated'):
- self._elevated = super(FakeContext, self).elevated()
- return self._elevated
-
-
-class _BaseTestCase(object):
- def setUp(self):
- super(_BaseTestCase, self).setUp()
- self.db = None
- self.user_id = 'fake'
- self.project_id = 'fake'
- self.context = FakeContext(self.user_id, self.project_id)
-
- fake_notifier.stub_notifier(self.stubs)
- self.addCleanup(fake_notifier.reset)
-
- def fake_deserialize_context(serializer, ctxt_dict):
- self.assertEqual(self.context.user_id, ctxt_dict['user_id'])
- self.assertEqual(self.context.project_id, ctxt_dict['project_id'])
- return self.context
-
- self.stubs.Set(rpc.RequestContextSerializer, 'deserialize_context',
- fake_deserialize_context)
-
- fake_utils.stub_out_utils_spawn_n(self.stubs)
-
- def _create_fake_instance(self, params=None, type_name='m1.tiny'):
- if not params:
- params = {}
-
- inst = {}
- inst['vm_state'] = vm_states.ACTIVE
- inst['image_ref'] = FAKE_IMAGE_REF
- inst['reservation_id'] = 'r-fakeres'
- inst['user_id'] = self.user_id
- inst['project_id'] = self.project_id
- inst['host'] = 'fake_host'
- type_id = flavors.get_flavor_by_name(type_name)['id']
- inst['instance_type_id'] = type_id
- inst['ami_launch_index'] = 0
- inst['memory_mb'] = 0
- inst['vcpus'] = 0
- inst['root_gb'] = 0
- inst['ephemeral_gb'] = 0
- inst['architecture'] = arch.X86_64
- inst['os_type'] = 'Linux'
- inst['availability_zone'] = 'fake-az'
- inst.update(params)
- return db.instance_create(self.context, inst)
-
- def _do_update(self, instance_uuid, **updates):
- return self.conductor.instance_update(self.context, instance_uuid,
- updates, None)
-
- def test_instance_update(self):
- instance = self._create_fake_instance()
- new_inst = self._do_update(instance['uuid'],
- vm_state=vm_states.STOPPED)
- instance = db.instance_get_by_uuid(self.context, instance['uuid'])
- self.assertEqual(instance['vm_state'], vm_states.STOPPED)
- self.assertEqual(new_inst['vm_state'], instance['vm_state'])
-
- def test_instance_update_invalid_key(self):
- # NOTE(danms): the real DB API call ignores invalid keys
- if self.db is None:
- self.conductor = utils.ExceptionHelper(self.conductor)
- self.assertRaises(KeyError,
- self._do_update, 'any-uuid', foobar=1)
-
- def test_migration_get_in_progress_by_host_and_node(self):
- self.mox.StubOutWithMock(db,
- 'migration_get_in_progress_by_host_and_node')
- db.migration_get_in_progress_by_host_and_node(
- self.context, 'fake-host', 'fake-node').AndReturn('fake-result')
- self.mox.ReplayAll()
- result = self.conductor.migration_get_in_progress_by_host_and_node(
- self.context, 'fake-host', 'fake-node')
- self.assertEqual(result, 'fake-result')
-
- def test_aggregate_metadata_get_by_host(self):
- self.mox.StubOutWithMock(db, 'aggregate_metadata_get_by_host')
- db.aggregate_metadata_get_by_host(self.context, 'host',
- 'key').AndReturn('result')
- self.mox.ReplayAll()
- result = self.conductor.aggregate_metadata_get_by_host(self.context,
- 'host', 'key')
- self.assertEqual(result, 'result')
-
- def test_bw_usage_update(self):
- self.mox.StubOutWithMock(db, 'bw_usage_update')
- self.mox.StubOutWithMock(db, 'bw_usage_get')
-
- update_args = (self.context, 'uuid', 'mac', 0, 10, 20, 5, 10, 20)
- get_args = (self.context, 'uuid', 0, 'mac')
-
- db.bw_usage_update(*update_args, update_cells=True)
- db.bw_usage_get(*get_args).AndReturn('foo')
-
- self.mox.ReplayAll()
- result = self.conductor.bw_usage_update(*update_args,
- update_cells=True)
- self.assertEqual(result, 'foo')
-
- def test_provider_fw_rule_get_all(self):
- fake_rules = ['a', 'b', 'c']
- self.mox.StubOutWithMock(db, 'provider_fw_rule_get_all')
- db.provider_fw_rule_get_all(self.context).AndReturn(fake_rules)
- self.mox.ReplayAll()
- result = self.conductor.provider_fw_rule_get_all(self.context)
- self.assertEqual(result, fake_rules)
-
- def test_block_device_mapping_get_all_by_instance(self):
- fake_inst = {'uuid': 'fake-uuid'}
- self.mox.StubOutWithMock(db,
- 'block_device_mapping_get_all_by_instance')
- db.block_device_mapping_get_all_by_instance(
- self.context, fake_inst['uuid']).AndReturn('fake-result')
- self.mox.ReplayAll()
- result = self.conductor.block_device_mapping_get_all_by_instance(
- self.context, fake_inst, legacy=False)
- self.assertEqual(result, 'fake-result')
-
- def test_vol_usage_update(self):
- self.mox.StubOutWithMock(db, 'vol_usage_update')
- self.mox.StubOutWithMock(compute_utils, 'usage_volume_info')
-
- fake_inst = {'uuid': 'fake-uuid',
- 'project_id': 'fake-project',
- 'user_id': 'fake-user',
- 'availability_zone': 'fake-az',
- }
-
- db.vol_usage_update(self.context, 'fake-vol', 22, 33, 44, 55,
- fake_inst['uuid'],
- fake_inst['project_id'],
- fake_inst['user_id'],
- fake_inst['availability_zone'],
- False).AndReturn('fake-usage')
- compute_utils.usage_volume_info('fake-usage').AndReturn('fake-info')
-
- self.mox.ReplayAll()
-
- self.conductor.vol_usage_update(self.context, 'fake-vol',
- 22, 33, 44, 55, fake_inst, None, False)
-
- self.assertEqual(1, len(fake_notifier.NOTIFICATIONS))
- msg = fake_notifier.NOTIFICATIONS[0]
- self.assertEqual('conductor.%s' % self.conductor_manager.host,
- msg.publisher_id)
- self.assertEqual('volume.usage', msg.event_type)
- self.assertEqual('INFO', msg.priority)
- self.assertEqual('fake-info', msg.payload)
-
- def test_compute_node_create(self):
- self.mox.StubOutWithMock(db, 'compute_node_create')
- db.compute_node_create(self.context, 'fake-values').AndReturn(
- 'fake-result')
- self.mox.ReplayAll()
- result = self.conductor.compute_node_create(self.context,
- 'fake-values')
- self.assertEqual(result, 'fake-result')
-
- def test_compute_node_update(self):
- node = {'id': 'fake-id'}
- self.mox.StubOutWithMock(db, 'compute_node_update')
- db.compute_node_update(self.context, node['id'], {'fake': 'values'}).\
- AndReturn('fake-result')
- self.mox.ReplayAll()
- result = self.conductor.compute_node_update(self.context, node,
- {'fake': 'values'})
- self.assertEqual(result, 'fake-result')
-
- def test_compute_node_delete(self):
- node = {'id': 'fake-id'}
- self.mox.StubOutWithMock(db, 'compute_node_delete')
- db.compute_node_delete(self.context, node['id']).AndReturn(None)
- self.mox.ReplayAll()
- result = self.conductor.compute_node_delete(self.context, node)
- self.assertIsNone(result)
-
- def test_task_log_get(self):
- self.mox.StubOutWithMock(db, 'task_log_get')
- db.task_log_get(self.context, 'task', 'begin', 'end', 'host',
- 'state').AndReturn('result')
- self.mox.ReplayAll()
- result = self.conductor.task_log_get(self.context, 'task', 'begin',
- 'end', 'host', 'state')
- self.assertEqual(result, 'result')
-
- def test_task_log_get_with_no_state(self):
- self.mox.StubOutWithMock(db, 'task_log_get')
- db.task_log_get(self.context, 'task', 'begin', 'end',
- 'host', None).AndReturn('result')
- self.mox.ReplayAll()
- result = self.conductor.task_log_get(self.context, 'task', 'begin',
- 'end', 'host', None)
- self.assertEqual(result, 'result')
-
- def test_task_log_begin_task(self):
- self.mox.StubOutWithMock(db, 'task_log_begin_task')
- db.task_log_begin_task(self.context.elevated(), 'task', 'begin',
- 'end', 'host', 'items',
- 'message').AndReturn('result')
- self.mox.ReplayAll()
- result = self.conductor.task_log_begin_task(
- self.context, 'task', 'begin', 'end', 'host', 'items', 'message')
- self.assertEqual(result, 'result')
-
- def test_task_log_end_task(self):
- self.mox.StubOutWithMock(db, 'task_log_end_task')
- db.task_log_end_task(self.context.elevated(), 'task', 'begin', 'end',
- 'host', 'errors', 'message').AndReturn('result')
- self.mox.ReplayAll()
- result = self.conductor.task_log_end_task(
- self.context, 'task', 'begin', 'end', 'host', 'errors', 'message')
- self.assertEqual(result, 'result')
-
- def test_notify_usage_exists(self):
- info = {
- 'audit_period_beginning': 'start',
- 'audit_period_ending': 'end',
- 'bandwidth': 'bw_usage',
- 'image_meta': {},
- 'extra': 'info',
- }
- instance = {
- 'system_metadata': [],
- }
-
- self.mox.StubOutWithMock(notifications, 'audit_period_bounds')
- self.mox.StubOutWithMock(notifications, 'bandwidth_usage')
- self.mox.StubOutWithMock(compute_utils, 'notify_about_instance_usage')
-
- notifications.audit_period_bounds(False).AndReturn(('start', 'end'))
- notifications.bandwidth_usage(instance, 'start', True).AndReturn(
- 'bw_usage')
- notifier = self.conductor_manager.notifier
- compute_utils.notify_about_instance_usage(notifier,
- self.context, instance,
- 'exists',
- system_metadata={},
- extra_usage_info=info)
-
- self.mox.ReplayAll()
-
- self.conductor.notify_usage_exists(self.context, instance, False, True,
- system_metadata={},
- extra_usage_info=dict(extra='info'))
-
- def test_security_groups_trigger_members_refresh(self):
- self.mox.StubOutWithMock(self.conductor_manager.security_group_api,
- 'trigger_members_refresh')
- self.conductor_manager.security_group_api.trigger_members_refresh(
- self.context, [1, 2, 3])
- self.mox.ReplayAll()
- self.conductor.security_groups_trigger_members_refresh(self.context,
- [1, 2, 3])
-
- def test_get_ec2_ids(self):
- expected = {
- 'instance-id': 'ec2-inst-id',
- 'ami-id': 'ec2-ami-id',
- 'kernel-id': 'ami-kernel-ec2-kernelid',
- 'ramdisk-id': 'ami-ramdisk-ec2-ramdiskid',
- }
- inst = {
- 'uuid': 'fake-uuid',
- 'kernel_id': 'ec2-kernelid',
- 'ramdisk_id': 'ec2-ramdiskid',
- 'image_ref': 'fake-image',
- }
- self.mox.StubOutWithMock(ec2utils, 'id_to_ec2_inst_id')
- self.mox.StubOutWithMock(ec2utils, 'glance_id_to_ec2_id')
- self.mox.StubOutWithMock(ec2utils, 'image_type')
-
- ec2utils.id_to_ec2_inst_id(inst['uuid']).AndReturn(
- expected['instance-id'])
- ec2utils.glance_id_to_ec2_id(self.context,
- inst['image_ref']).AndReturn(
- expected['ami-id'])
- for image_type in ['kernel', 'ramdisk']:
- image_id = inst['%s_id' % image_type]
- ec2utils.image_type(image_type).AndReturn('ami-' + image_type)
- ec2utils.glance_id_to_ec2_id(self.context, image_id,
- 'ami-' + image_type).AndReturn(
- 'ami-%s-ec2-%sid' % (image_type, image_type))
-
- self.mox.ReplayAll()
- result = self.conductor.get_ec2_ids(self.context, inst)
- self.assertEqual(result, expected)
-
-
-class ConductorTestCase(_BaseTestCase, test.TestCase):
- """Conductor Manager Tests."""
- def setUp(self):
- super(ConductorTestCase, self).setUp()
- self.conductor = conductor_manager.ConductorManager()
- self.conductor_manager = self.conductor
-
- def test_instance_get_by_uuid(self):
- orig_instance = self._create_fake_instance()
- copy_instance = self.conductor.instance_get_by_uuid(
- self.context, orig_instance['uuid'], None)
- self.assertEqual(orig_instance['name'],
- copy_instance['name'])
-
- def test_block_device_mapping_update_or_create(self):
- fake_bdm = {'id': 1, 'device_name': 'foo',
- 'source_type': 'volume', 'volume_id': 'fake-vol-id',
- 'destination_type': 'volume'}
- fake_bdm = fake_block_device.FakeDbBlockDeviceDict(fake_bdm)
- fake_bdm2 = {'id': 1, 'device_name': 'foo2',
- 'source_type': 'volume', 'volume_id': 'fake-vol-id',
- 'destination_type': 'volume'}
- fake_bdm2 = fake_block_device.FakeDbBlockDeviceDict(fake_bdm2)
- 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')
- 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, mox.IsA(block_device_obj.BlockDeviceMapping),
- 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, mox.IsA(block_device_obj.BlockDeviceMapping),
- create=False)
- self.mox.ReplayAll()
- self.conductor.block_device_mapping_update_or_create(self.context,
- fake_bdm,
- create=True)
- self.conductor.block_device_mapping_update_or_create(self.context,
- fake_bdm,
- create=False)
-
- def test_instance_get_all_by_filters(self):
- filters = {'foo': 'bar'}
- self.mox.StubOutWithMock(db, 'instance_get_all_by_filters')
- db.instance_get_all_by_filters(self.context, filters,
- 'fake-key', 'fake-sort',
- columns_to_join=None, use_slave=False)
- self.mox.ReplayAll()
- self.conductor.instance_get_all_by_filters(self.context, filters,
- 'fake-key', 'fake-sort',
- None, False)
-
- def test_instance_get_all_by_filters_use_slave(self):
- filters = {'foo': 'bar'}
- self.mox.StubOutWithMock(db, 'instance_get_all_by_filters')
- db.instance_get_all_by_filters(self.context, filters,
- 'fake-key', 'fake-sort',
- columns_to_join=None, use_slave=True)
- self.mox.ReplayAll()
- self.conductor.instance_get_all_by_filters(self.context, filters,
- 'fake-key', 'fake-sort',
- columns_to_join=None,
- use_slave=True)
-
- def test_instance_get_all_by_host(self):
- self.mox.StubOutWithMock(db, 'instance_get_all_by_host')
- self.mox.StubOutWithMock(db, 'instance_get_all_by_host_and_node')
- db.instance_get_all_by_host(self.context.elevated(),
- 'host', None).AndReturn('result')
- db.instance_get_all_by_host_and_node(self.context.elevated(), 'host',
- 'node').AndReturn('result')
- self.mox.ReplayAll()
- result = self.conductor.instance_get_all_by_host(self.context, 'host',
- None, None)
- self.assertEqual(result, 'result')
- result = self.conductor.instance_get_all_by_host(self.context, 'host',
- 'node', None)
- self.assertEqual(result, 'result')
-
- def _test_stubbed(self, name, dbargs, condargs,
- db_result_listified=False, db_exception=None):
-
- self.mox.StubOutWithMock(db, name)
- if db_exception:
- getattr(db, name)(self.context, *dbargs).AndRaise(db_exception)
- getattr(db, name)(self.context, *dbargs).AndRaise(db_exception)
- else:
- getattr(db, name)(self.context, *dbargs).AndReturn('fake-result')
- self.mox.ReplayAll()
- if db_exception:
- self.assertRaises(messaging.ExpectedException,
- self.conductor.service_get_all_by,
- self.context, **condargs)
-
- self.conductor = utils.ExceptionHelper(self.conductor)
-
- self.assertRaises(db_exception.__class__,
- self.conductor.service_get_all_by,
- self.context, **condargs)
- else:
- result = self.conductor.service_get_all_by(self.context,
- **condargs)
- if db_result_listified:
- self.assertEqual(['fake-result'], result)
- else:
- self.assertEqual('fake-result', result)
-
- def test_service_get_all(self):
- self._test_stubbed('service_get_all', (),
- dict(host=None, topic=None, binary=None))
-
- def test_service_get_by_host_and_topic(self):
- self._test_stubbed('service_get_by_host_and_topic',
- ('host', 'topic'),
- dict(topic='topic', host='host', binary=None))
-
- def test_service_get_all_by_topic(self):
- self._test_stubbed('service_get_all_by_topic',
- ('topic',),
- dict(topic='topic', host=None, binary=None))
-
- def test_service_get_all_by_host(self):
- self._test_stubbed('service_get_all_by_host',
- ('host',),
- dict(host='host', topic=None, binary=None))
-
- def test_service_get_by_compute_host(self):
- self._test_stubbed('service_get_by_compute_host',
- ('host',),
- dict(topic='compute', host='host', binary=None),
- db_result_listified=True)
-
- def test_service_get_by_args(self):
- self._test_stubbed('service_get_by_args',
- ('host', 'binary'),
- dict(host='host', binary='binary', topic=None))
-
- def test_service_get_by_compute_host_not_found(self):
- self._test_stubbed('service_get_by_compute_host',
- ('host',),
- dict(topic='compute', host='host', binary=None),
- db_exception=exc.ComputeHostNotFound(host='host'))
-
- def test_service_get_by_args_not_found(self):
- self._test_stubbed('service_get_by_args',
- ('host', 'binary'),
- dict(host='host', binary='binary', topic=None),
- db_exception=exc.HostBinaryNotFound(binary='binary',
- host='host'))
-
- def test_security_groups_trigger_handler(self):
- self.mox.StubOutWithMock(self.conductor_manager.security_group_api,
- 'trigger_handler')
- self.conductor_manager.security_group_api.trigger_handler('event',
- self.context,
- 'args')
- self.mox.ReplayAll()
- self.conductor.security_groups_trigger_handler(self.context,
- 'event', ['args'])
-
- def _test_object_action(self, is_classmethod, raise_exception):
- class TestObject(obj_base.NovaObject):
- def foo(self, context, raise_exception=False):
- if raise_exception:
- raise Exception('test')
- else:
- return 'test'
-
- @classmethod
- def bar(cls, context, raise_exception=False):
- if raise_exception:
- raise Exception('test')
- else:
- return 'test'
-
- obj = TestObject()
- if is_classmethod:
- result = self.conductor.object_class_action(
- self.context, TestObject.obj_name(), 'bar', '1.0',
- tuple(), {'raise_exception': raise_exception})
- else:
- updates, result = self.conductor.object_action(
- self.context, obj, 'foo', tuple(),
- {'raise_exception': raise_exception})
- self.assertEqual('test', result)
-
- def test_object_action(self):
- self._test_object_action(False, False)
-
- def test_object_action_on_raise(self):
- self.assertRaises(messaging.ExpectedException,
- self._test_object_action, False, True)
-
- def test_object_class_action(self):
- self._test_object_action(True, False)
-
- def test_object_class_action_on_raise(self):
- self.assertRaises(messaging.ExpectedException,
- self._test_object_action, True, True)
-
- def test_object_action_copies_object(self):
- class TestObject(obj_base.NovaObject):
- fields = {'dict': fields.DictOfStringsField()}
-
- def touch_dict(self, context):
- self.dict['foo'] = 'bar'
- self.obj_reset_changes()
-
- obj = TestObject()
- obj.dict = {}
- obj.obj_reset_changes()
- updates, result = self.conductor.object_action(
- self.context, obj, 'touch_dict', tuple(), {})
- # NOTE(danms): If conductor did not properly copy the object, then
- # the new and reference copies of the nested dict object will be
- # the same, and thus 'dict' will not be reported as changed
- self.assertIn('dict', updates)
- self.assertEqual({'foo': 'bar'}, updates['dict'])
-
- def _test_expected_exceptions(self, db_method, conductor_method, errors,
- *args, **kwargs):
- # Tests that expected exceptions are handled properly.
- for error in errors:
- with mock.patch.object(db, db_method, side_effect=error):
- self.assertRaises(messaging.ExpectedException,
- conductor_method,
- self.context, *args, **kwargs)
-
- def test_action_event_start_expected_exceptions(self):
- error = exc.InstanceActionNotFound(request_id='1', instance_uuid='2')
- self._test_expected_exceptions(
- 'action_event_start', self.conductor.action_event_start, [error],
- {'foo': 'bar'})
-
- def test_action_event_finish_expected_exceptions(self):
- errors = (exc.InstanceActionNotFound(request_id='1',
- instance_uuid='2'),
- exc.InstanceActionEventNotFound(event='1', action_id='2'))
- self._test_expected_exceptions(
- 'action_event_finish', self.conductor.action_event_finish,
- errors, {'foo': 'bar'})
-
- def test_instance_update_expected_exceptions(self):
- errors = (exc.InvalidUUID(uuid='foo'),
- exc.InstanceNotFound(instance_id=1),
- exc.UnexpectedTaskStateError(expected='foo',
- actual='bar'))
- self._test_expected_exceptions(
- 'instance_update', self.conductor.instance_update,
- errors, None, {'foo': 'bar'}, None)
-
- def test_instance_get_by_uuid_expected_exceptions(self):
- error = exc.InstanceNotFound(instance_id=1)
- self._test_expected_exceptions(
- 'instance_get_by_uuid', self.conductor.instance_get_by_uuid,
- [error], None, [])
-
- def test_aggregate_host_add_expected_exceptions(self):
- error = exc.AggregateHostExists(aggregate_id=1, host='foo')
- self._test_expected_exceptions(
- 'aggregate_host_add', self.conductor.aggregate_host_add,
- [error], {'id': 1}, None)
-
- def test_aggregate_host_delete_expected_exceptions(self):
- error = exc.AggregateHostNotFound(aggregate_id=1, host='foo')
- self._test_expected_exceptions(
- 'aggregate_host_delete', self.conductor.aggregate_host_delete,
- [error], {'id': 1}, None)
-
- def test_service_update_expected_exceptions(self):
- error = exc.ServiceNotFound(service_id=1)
- self._test_expected_exceptions(
- 'service_update',
- self.conductor.service_update,
- [error], {'id': 1}, None)
-
- def test_service_destroy_expected_exceptions(self):
- error = exc.ServiceNotFound(service_id=1)
- self._test_expected_exceptions(
- 'service_destroy',
- self.conductor.service_destroy,
- [error], 1)
-
- def _setup_aggregate_with_host(self):
- aggregate_ref = db.aggregate_create(self.context.elevated(),
- {'name': 'foo'}, metadata={'availability_zone': 'foo'})
-
- self.conductor.aggregate_host_add(self.context, aggregate_ref, 'bar')
-
- aggregate_ref = db.aggregate_get(self.context.elevated(),
- aggregate_ref['id'])
-
- return aggregate_ref
-
- def test_aggregate_host_add(self):
- aggregate_ref = self._setup_aggregate_with_host()
-
- self.assertIn('bar', aggregate_ref['hosts'])
-
- db.aggregate_delete(self.context.elevated(), aggregate_ref['id'])
-
- def test_aggregate_host_delete(self):
- aggregate_ref = self._setup_aggregate_with_host()
-
- self.conductor.aggregate_host_delete(self.context, aggregate_ref,
- 'bar')
-
- aggregate_ref = db.aggregate_get(self.context.elevated(),
- aggregate_ref['id'])
-
- self.assertNotIn('bar', aggregate_ref['hosts'])
-
- db.aggregate_delete(self.context.elevated(), aggregate_ref['id'])
-
- def test_network_migrate_instance_start(self):
- self.mox.StubOutWithMock(self.conductor_manager.network_api,
- 'migrate_instance_start')
- self.conductor_manager.network_api.migrate_instance_start(self.context,
- 'instance',
- 'migration')
- self.mox.ReplayAll()
- self.conductor.network_migrate_instance_start(self.context,
- 'instance',
- 'migration')
-
- def test_network_migrate_instance_finish(self):
- self.mox.StubOutWithMock(self.conductor_manager.network_api,
- 'migrate_instance_finish')
- self.conductor_manager.network_api.migrate_instance_finish(
- self.context, 'instance', 'migration')
- self.mox.ReplayAll()
- self.conductor.network_migrate_instance_finish(self.context,
- 'instance',
- 'migration')
-
- def test_instance_destroy(self):
- self.mox.StubOutWithMock(db, 'instance_destroy')
- db.instance_destroy(self.context, 'fake-uuid').AndReturn('fake-result')
- self.mox.ReplayAll()
- result = self.conductor.instance_destroy(self.context,
- {'uuid': 'fake-uuid'})
- self.assertEqual(result, 'fake-result')
-
- def test_compute_unrescue(self):
- self.mox.StubOutWithMock(self.conductor_manager.compute_api,
- 'unrescue')
- self.conductor_manager.compute_api.unrescue(self.context, 'instance')
- self.mox.ReplayAll()
- self.conductor.compute_unrescue(self.context, 'instance')
-
- def test_instance_get_active_by_window_joined(self):
- self.mox.StubOutWithMock(db, 'instance_get_active_by_window_joined')
- db.instance_get_active_by_window_joined(self.context, 'fake-begin',
- 'fake-end', 'fake-proj',
- 'fake-host')
- self.mox.ReplayAll()
- self.conductor.instance_get_active_by_window_joined(
- self.context, 'fake-begin', 'fake-end', 'fake-proj', 'fake-host')
-
- def test_instance_fault_create(self):
- self.mox.StubOutWithMock(db, 'instance_fault_create')
- db.instance_fault_create(self.context, 'fake-values').AndReturn(
- 'fake-result')
- self.mox.ReplayAll()
- result = self.conductor.instance_fault_create(self.context,
- 'fake-values')
- self.assertEqual(result, 'fake-result')
-
- def test_action_event_start(self):
- self.mox.StubOutWithMock(db, 'action_event_start')
- db.action_event_start(self.context, mox.IgnoreArg())
- self.mox.ReplayAll()
- self.conductor.action_event_start(self.context, {})
-
- def test_action_event_finish(self):
- self.mox.StubOutWithMock(db, 'action_event_finish')
- db.action_event_finish(self.context, mox.IgnoreArg())
- self.mox.ReplayAll()
- self.conductor.action_event_finish(self.context, {})
-
- def test_agent_build_get_by_triple(self):
- self.mox.StubOutWithMock(db, 'agent_build_get_by_triple')
- db.agent_build_get_by_triple(self.context, 'fake-hv', 'fake-os',
- 'fake-arch').AndReturn('it worked')
- self.mox.ReplayAll()
- result = self.conductor.agent_build_get_by_triple(self.context,
- 'fake-hv',
- 'fake-os',
- 'fake-arch')
- self.assertEqual(result, 'it worked')
-
-
-class ConductorRPCAPITestCase(_BaseTestCase, test.TestCase):
- """Conductor RPC API Tests."""
- def setUp(self):
- super(ConductorRPCAPITestCase, self).setUp()
- self.conductor_service = self.start_service(
- 'conductor', manager='nova.conductor.manager.ConductorManager')
- self.conductor_manager = self.conductor_service.manager
- self.conductor = conductor_rpcapi.ConductorAPI()
-
- def test_block_device_mapping_update_or_create(self):
- fake_bdm = {'id': 'fake-id'}
- 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')
- self.mox.StubOutWithMock(block_device_obj.BlockDeviceMapping,
- '_from_db_object')
- db.block_device_mapping_create(self.context, fake_bdm)
- block_device_obj.BlockDeviceMapping._from_db_object(
- self.context, mox.IgnoreArg(), mox.IgnoreArg())
- db.block_device_mapping_update(self.context, fake_bdm['id'], fake_bdm)
- block_device_obj.BlockDeviceMapping._from_db_object(
- self.context, mox.IgnoreArg(), mox.IgnoreArg())
- db.block_device_mapping_update_or_create(self.context, fake_bdm)
- block_device_obj.BlockDeviceMapping._from_db_object(
- self.context, mox.IgnoreArg(), mox.IgnoreArg())
- self.mox.ReplayAll()
- self.conductor.block_device_mapping_update_or_create(self.context,
- fake_bdm,
- create=True)
- self.conductor.block_device_mapping_update_or_create(self.context,
- fake_bdm,
- create=False)
- self.conductor.block_device_mapping_update_or_create(self.context,
- fake_bdm)
-
- def _test_stubbed(self, name, dbargs, condargs,
- db_result_listified=False, db_exception=None):
- self.mox.StubOutWithMock(db, name)
- if db_exception:
- getattr(db, name)(self.context, *dbargs).AndRaise(db_exception)
- else:
- getattr(db, name)(self.context, *dbargs).AndReturn('fake-result')
- self.mox.ReplayAll()
- if db_exception:
- self.assertRaises(db_exception.__class__,
- self.conductor.service_get_all_by,
- self.context, **condargs)
- else:
- result = self.conductor.service_get_all_by(self.context,
- **condargs)
- if db_result_listified:
- self.assertEqual(['fake-result'], result)
- else:
- self.assertEqual('fake-result', result)
-
- def test_service_get_all(self):
- self._test_stubbed('service_get_all', (),
- dict(topic=None, host=None, binary=None))
-
- def test_service_get_by_host_and_topic(self):
- self._test_stubbed('service_get_by_host_and_topic',
- ('host', 'topic'),
- dict(topic='topic', host='host', binary=None))
-
- def test_service_get_all_by_topic(self):
- self._test_stubbed('service_get_all_by_topic',
- ('topic',),
- dict(topic='topic', host=None, binary=None))
-
- def test_service_get_all_by_host(self):
- self._test_stubbed('service_get_all_by_host',
- ('host',),
- dict(host='host', topic=None, binary=None))
-
- def test_service_get_by_compute_host(self):
- self._test_stubbed('service_get_by_compute_host',
- ('host',),
- dict(topic='compute', host='host', binary=None),
- db_result_listified=True)
-
- def test_service_get_by_args(self):
- self._test_stubbed('service_get_by_args',
- ('host', 'binary'),
- dict(host='host', binary='binary', topic=None))
-
- def test_service_get_by_compute_host_not_found(self):
- self._test_stubbed('service_get_by_compute_host',
- ('host',),
- dict(topic='compute', host='host', binary=None),
- db_exception=exc.ComputeHostNotFound(host='host'))
-
- def test_service_get_by_args_not_found(self):
- self._test_stubbed('service_get_by_args',
- ('host', 'binary'),
- dict(host='host', binary='binary', topic=None),
- db_exception=exc.HostBinaryNotFound(binary='binary',
- host='host'))
-
- def test_security_groups_trigger_handler(self):
- self.mox.StubOutWithMock(self.conductor_manager.security_group_api,
- 'trigger_handler')
- self.conductor_manager.security_group_api.trigger_handler('event',
- self.context,
- 'arg')
- self.mox.ReplayAll()
- self.conductor.security_groups_trigger_handler(self.context,
- 'event', ['arg'])
-
- @mock.patch.object(db, 'service_update')
- @mock.patch('oslo.messaging.RPCClient.prepare')
- def test_service_update_time_big(self, mock_prepare, mock_update):
- CONF.set_override('report_interval', 10)
- services = {'id': 1}
- self.conductor.service_update(self.context, services, {})
- mock_prepare.assert_called_once_with(timeout=9)
-
- @mock.patch.object(db, 'service_update')
- @mock.patch('oslo.messaging.RPCClient.prepare')
- def test_service_update_time_small(self, mock_prepare, mock_update):
- CONF.set_override('report_interval', 3)
- services = {'id': 1}
- self.conductor.service_update(self.context, services, {})
- mock_prepare.assert_called_once_with(timeout=3)
-
- @mock.patch.object(db, 'service_update')
- @mock.patch('oslo.messaging.RPCClient.prepare')
- def test_service_update_no_time(self, mock_prepare, mock_update):
- CONF.set_override('report_interval', None)
- services = {'id': 1}
- self.conductor.service_update(self.context, services, {})
- mock_prepare.assert_called_once_with()
-
-
-class ConductorAPITestCase(_BaseTestCase, test.TestCase):
- """Conductor API Tests."""
- def setUp(self):
- super(ConductorAPITestCase, self).setUp()
- self.conductor_service = self.start_service(
- 'conductor', manager='nova.conductor.manager.ConductorManager')
- self.conductor = conductor_api.API()
- self.conductor_manager = self.conductor_service.manager
- self.db = None
-
- def _do_update(self, instance_uuid, **updates):
- # NOTE(danms): the public API takes actual keyword arguments,
- # so override the base class here to make the call correctly
- return self.conductor.instance_update(self.context, instance_uuid,
- **updates)
-
- def test_bw_usage_get(self):
- self.mox.StubOutWithMock(db, 'bw_usage_update')
- self.mox.StubOutWithMock(db, 'bw_usage_get')
-
- get_args = (self.context, 'uuid', 0, 'mac')
-
- db.bw_usage_get(*get_args).AndReturn('foo')
-
- self.mox.ReplayAll()
- result = self.conductor.bw_usage_get(*get_args)
- self.assertEqual(result, 'foo')
-
- def test_block_device_mapping_update_or_create(self):
- 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')
- self.mox.StubOutWithMock(block_device_obj.BlockDeviceMapping,
- '_from_db_object')
- db.block_device_mapping_create(self.context, 'fake-bdm')
- block_device_obj.BlockDeviceMapping._from_db_object(
- self.context, mox.IgnoreArg(), mox.IgnoreArg())
- db.block_device_mapping_update(self.context,
- 'fake-id', {'id': 'fake-id'})
- block_device_obj.BlockDeviceMapping._from_db_object(
- self.context, mox.IgnoreArg(), mox.IgnoreArg())
- db.block_device_mapping_update_or_create(self.context, 'fake-bdm')
- block_device_obj.BlockDeviceMapping._from_db_object(
- self.context, mox.IgnoreArg(), mox.IgnoreArg())
-
- self.mox.ReplayAll()
- self.conductor.block_device_mapping_create(self.context, 'fake-bdm')
- self.conductor.block_device_mapping_update(self.context, 'fake-id', {})
- self.conductor.block_device_mapping_update_or_create(self.context,
- 'fake-bdm')
-
- def _test_stubbed(self, name, *args, **kwargs):
- if args and isinstance(args[0], FakeContext):
- ctxt = args[0]
- args = args[1:]
- else:
- ctxt = self.context
- db_exception = kwargs.get('db_exception')
- self.mox.StubOutWithMock(db, name)
- if db_exception:
- getattr(db, name)(ctxt, *args).AndRaise(db_exception)
- else:
- getattr(db, name)(ctxt, *args).AndReturn('fake-result')
- if name == 'service_destroy':
- # TODO(russellb) This is a hack ... SetUp() starts the conductor()
- # service. There is a cleanup step that runs after this test which
- # also deletes the associated service record. This involves a call
- # to db.service_destroy(), which we have stubbed out.
- db.service_destroy(mox.IgnoreArg(), mox.IgnoreArg())
- self.mox.ReplayAll()
- if db_exception:
- self.assertRaises(db_exception.__class__,
- getattr(self.conductor, name),
- self.context, *args)
- else:
- result = getattr(self.conductor, name)(self.context, *args)
- self.assertEqual(
- result, 'fake-result' if kwargs.get('returns', True) else None)
-
- def test_service_get_all(self):
- self._test_stubbed('service_get_all')
-
- def test_service_get_by_host_and_topic(self):
- self._test_stubbed('service_get_by_host_and_topic', 'host', 'topic')
-
- def test_service_get_all_by_topic(self):
- self._test_stubbed('service_get_all_by_topic', 'topic')
-
- def test_service_get_all_by_host(self):
- self._test_stubbed('service_get_all_by_host', 'host')
-
- def test_service_get_by_compute_host(self):
- self._test_stubbed('service_get_by_compute_host', 'host')
-
- def test_service_get_by_args(self):
- self._test_stubbed('service_get_by_args', 'host', 'binary')
-
- def test_service_get_by_compute_host_not_found(self):
- self._test_stubbed('service_get_by_compute_host', 'host',
- db_exception=exc.ComputeHostNotFound(host='host'))
-
- def test_service_get_by_args_not_found(self):
- self._test_stubbed('service_get_by_args', 'host', 'binary',
- db_exception=exc.HostBinaryNotFound(binary='binary',
- host='host'))
-
- def test_service_create(self):
- self._test_stubbed('service_create', {})
-
- def test_service_destroy(self):
- self._test_stubbed('service_destroy', '', returns=False)
-
- def test_service_update(self):
- ctxt = self.context
- self.mox.StubOutWithMock(db, 'service_update')
- db.service_update(ctxt, '', {}).AndReturn('fake-result')
- self.mox.ReplayAll()
- result = self.conductor.service_update(self.context, {'id': ''}, {})
- self.assertEqual(result, 'fake-result')
-
- def test_instance_get_all_by_host_and_node(self):
- self._test_stubbed('instance_get_all_by_host_and_node',
- self.context.elevated(), 'host', 'node')
-
- def test_instance_get_all_by_host(self):
- self.mox.StubOutWithMock(db, 'instance_get_all_by_host')
- self.mox.StubOutWithMock(db, 'instance_get_all_by_host_and_node')
- db.instance_get_all_by_host(self.context.elevated(), 'host',
- None).AndReturn('fake-result')
- self.mox.ReplayAll()
- result = self.conductor.instance_get_all_by_host(self.context,
- 'host', None)
- self.assertEqual(result, 'fake-result')
-
- def test_wait_until_ready(self):
- timeouts = []
- calls = dict(count=0)
-
- def fake_ping(context, message, timeout):
- timeouts.append(timeout)
- calls['count'] += 1
- if calls['count'] < 15:
- raise messaging.MessagingTimeout("fake")
-
- self.stubs.Set(self.conductor.base_rpcapi, 'ping', fake_ping)
-
- self.conductor.wait_until_ready(self.context)
-
- self.assertEqual(timeouts.count(10), 10)
- self.assertIn(None, timeouts)
-
- def test_security_groups_trigger_handler(self):
- self.mox.StubOutWithMock(self.conductor_manager.security_group_api,
- 'trigger_handler')
- self.conductor_manager.security_group_api.trigger_handler('event',
- self.context,
- 'arg')
- self.mox.ReplayAll()
- self.conductor.security_groups_trigger_handler(self.context,
- 'event', 'arg')
-
-
-class ConductorLocalAPITestCase(ConductorAPITestCase):
- """Conductor LocalAPI Tests."""
- def setUp(self):
- super(ConductorLocalAPITestCase, self).setUp()
- self.conductor = conductor_api.LocalAPI()
- self.conductor_manager = self.conductor._manager._target
- self.db = db
-
- def test_client_exceptions(self):
- instance = self._create_fake_instance()
- # NOTE(danms): The LocalAPI should not raise exceptions wrapped
- # in ClientException. KeyError should be raised if an invalid
- # update key is passed, so use that to validate.
- self.assertRaises(KeyError,
- self._do_update, instance['uuid'], foo='bar')
-
- def test_wait_until_ready(self):
- # Override test in ConductorAPITestCase
- pass
-
-
-class ConductorImportTest(test.TestCase):
- def test_import_conductor_local(self):
- self.flags(use_local=True, group='conductor')
- self.assertIsInstance(conductor.API(), conductor_api.LocalAPI)
- self.assertIsInstance(conductor.ComputeTaskAPI(),
- conductor_api.LocalComputeTaskAPI)
-
- def test_import_conductor_rpc(self):
- self.flags(use_local=False, group='conductor')
- self.assertIsInstance(conductor.API(), conductor_api.API)
- self.assertIsInstance(conductor.ComputeTaskAPI(),
- conductor_api.ComputeTaskAPI)
-
- def test_import_conductor_override_to_local(self):
- self.flags(use_local=False, group='conductor')
- self.assertIsInstance(conductor.API(use_local=True),
- conductor_api.LocalAPI)
- self.assertIsInstance(conductor.ComputeTaskAPI(use_local=True),
- conductor_api.LocalComputeTaskAPI)
-
-
-class ConductorPolicyTest(test.TestCase):
- def test_all_allowed_keys(self):
-
- def fake_db_instance_update(self, *args, **kwargs):
- return None, None
- self.stubs.Set(db, 'instance_update_and_get_original',
- fake_db_instance_update)
-
- ctxt = context.RequestContext('fake-user', 'fake-project')
- conductor = conductor_api.LocalAPI()
- updates = {}
- for key in conductor_manager.allowed_updates:
- if key in conductor_manager.datetime_fields:
- updates[key] = timeutils.utcnow()
- else:
- updates[key] = 'foo'
- conductor.instance_update(ctxt, 'fake-instance', **updates)
-
- def test_allowed_keys_are_real(self):
- instance = models.Instance()
- keys = list(conductor_manager.allowed_updates)
-
- # NOTE(danms): expected_task_state is a parameter that gets
- # passed to the db layer, but is not actually an instance attribute
- del keys[keys.index('expected_task_state')]
-
- for key in keys:
- self.assertTrue(hasattr(instance, key))
-
-
-class _BaseTaskTestCase(object):
- def setUp(self):
- super(_BaseTaskTestCase, self).setUp()
- self.user_id = 'fake'
- self.project_id = 'fake'
- self.context = FakeContext(self.user_id, self.project_id)
- fake_server_actions.stub_out_action_events(self.stubs)
-
- def fake_deserialize_context(serializer, ctxt_dict):
- self.assertEqual(self.context.user_id, ctxt_dict['user_id'])
- self.assertEqual(self.context.project_id, ctxt_dict['project_id'])
- return self.context
-
- self.stubs.Set(rpc.RequestContextSerializer, 'deserialize_context',
- fake_deserialize_context)
-
- def _prepare_rebuild_args(self, update_args=None):
- rebuild_args = {'new_pass': 'admin_password',
- 'injected_files': 'files_to_inject',
- 'image_ref': 'image_ref',
- 'orig_image_ref': 'orig_image_ref',
- 'orig_sys_metadata': 'orig_sys_meta',
- 'bdms': {},
- 'recreate': False,
- 'on_shared_storage': False,
- 'preserve_ephemeral': False,
- 'host': 'compute-host'}
- if update_args:
- rebuild_args.update(update_args)
- return rebuild_args
-
- def test_live_migrate(self):
- inst = fake_instance.fake_db_instance()
- inst_obj = objects.Instance._from_db_object(
- self.context, objects.Instance(), inst, [])
-
- self.mox.StubOutWithMock(live_migrate, 'execute')
- live_migrate.execute(self.context,
- mox.IsA(objects.Instance),
- 'destination',
- 'block_migration',
- 'disk_over_commit')
- self.mox.ReplayAll()
-
- if isinstance(self.conductor, (conductor_api.ComputeTaskAPI,
- conductor_api.LocalComputeTaskAPI)):
- # The API method is actually 'live_migrate_instance'. It gets
- # converted into 'migrate_server' when doing RPC.
- self.conductor.live_migrate_instance(self.context, inst_obj,
- 'destination', 'block_migration', 'disk_over_commit')
- else:
- self.conductor.migrate_server(self.context, inst_obj,
- {'host': 'destination'}, True, False, None,
- 'block_migration', 'disk_over_commit')
-
- def test_cold_migrate(self):
- self.mox.StubOutWithMock(compute_utils, 'get_image_metadata')
- self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec')
- self.mox.StubOutWithMock(
- self.conductor_manager.compute_rpcapi, 'prep_resize')
- self.mox.StubOutWithMock(self.conductor_manager.scheduler_client,
- 'select_destinations')
- inst = fake_instance.fake_db_instance(image_ref='image_ref')
- inst_obj = objects.Instance._from_db_object(
- self.context, objects.Instance(), inst, [])
- flavor = flavors.get_default_flavor()
- flavor['extra_specs'] = 'extra_specs'
- request_spec = {'instance_type': flavor,
- 'instance_properties': {}}
- compute_utils.get_image_metadata(
- self.context, self.conductor_manager.image_api,
- 'image_ref', mox.IsA(objects.Instance)).AndReturn('image')
-
- scheduler_utils.build_request_spec(
- self.context, 'image',
- [mox.IsA(objects.Instance)],
- instance_type=flavor).AndReturn(request_spec)
-
- hosts = [dict(host='host1', nodename=None, limits={})]
- self.conductor_manager.scheduler_client.select_destinations(
- self.context, request_spec,
- {'retry': {'num_attempts': 1, 'hosts': []}}).AndReturn(hosts)
-
- filter_properties = {'limits': {},
- 'retry': {'num_attempts': 1,
- 'hosts': [['host1', None]]}}
-
- self.conductor_manager.compute_rpcapi.prep_resize(
- self.context, 'image', mox.IsA(objects.Instance),
- mox.IsA(dict), 'host1', [], request_spec=request_spec,
- filter_properties=filter_properties, node=None)
-
- self.mox.ReplayAll()
-
- scheduler_hint = {'filter_properties': {}}
-
- if isinstance(self.conductor, (conductor_api.ComputeTaskAPI,
- conductor_api.LocalComputeTaskAPI)):
- # The API method is actually 'resize_instance'. It gets
- # converted into 'migrate_server' when doing RPC.
- self.conductor.resize_instance(
- self.context, inst_obj, {}, scheduler_hint, flavor, [])
- else:
- self.conductor.migrate_server(
- self.context, inst_obj, scheduler_hint,
- False, False, flavor, None, None, [])
-
- def test_build_instances(self):
- system_metadata = flavors.save_flavor_info({},
- flavors.get_default_flavor())
- instances = [fake_instance.fake_instance_obj(
- self.context,
- system_metadata=system_metadata,
- expected_attrs=['system_metadata']) for i in xrange(2)]
- instance_type = flavors.extract_flavor(instances[0])
- instance_type['extra_specs'] = 'fake-specs'
- instance_properties = jsonutils.to_primitive(instances[0])
-
- self.mox.StubOutWithMock(db, 'flavor_extra_specs_get')
- self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group')
- self.mox.StubOutWithMock(self.conductor_manager.scheduler_client,
- 'select_destinations')
- self.mox.StubOutWithMock(db, 'instance_get_by_uuid')
- self.mox.StubOutWithMock(db,
- 'block_device_mapping_get_all_by_instance')
- self.mox.StubOutWithMock(self.conductor_manager.compute_rpcapi,
- 'build_and_run_instance')
-
- db.flavor_extra_specs_get(
- self.context,
- instance_type['flavorid']).AndReturn('fake-specs')
- scheduler_utils.setup_instance_group(self.context, None, None)
- self.conductor_manager.scheduler_client.select_destinations(
- self.context, {'image': {'fake_data': 'should_pass_silently'},
- 'instance_properties': jsonutils.to_primitive(
- instances[0]),
- 'instance_type': instance_type,
- 'instance_uuids': [inst.uuid for inst in instances],
- 'num_instances': 2},
- {'retry': {'num_attempts': 1, 'hosts': []}}).AndReturn(
- [{'host': 'host1', 'nodename': 'node1', 'limits': []},
- {'host': 'host2', 'nodename': 'node2', 'limits': []}])
- db.instance_get_by_uuid(self.context, instances[0].uuid,
- columns_to_join=['system_metadata'],
- use_slave=False).AndReturn(
- jsonutils.to_primitive(instances[0]))
- db.block_device_mapping_get_all_by_instance(self.context,
- instances[0].uuid, use_slave=False).AndReturn([])
- self.conductor_manager.compute_rpcapi.build_and_run_instance(
- self.context,
- instance=mox.IgnoreArg(),
- host='host1',
- image={'fake_data': 'should_pass_silently'},
- request_spec={
- 'image': {'fake_data': 'should_pass_silently'},
- 'instance_properties': instance_properties,
- 'instance_type': instance_type,
- 'instance_uuids': [inst.uuid for inst in instances],
- 'num_instances': 2},
- filter_properties={'retry': {'num_attempts': 1,
- 'hosts': [['host1', 'node1']]},
- 'limits': []},
- admin_password='admin_password',
- injected_files='injected_files',
- requested_networks=None,
- security_groups='security_groups',
- block_device_mapping=mox.IgnoreArg(),
- node='node1', limits=[])
- db.instance_get_by_uuid(self.context, instances[1].uuid,
- columns_to_join=['system_metadata'],
- use_slave=False).AndReturn(
- jsonutils.to_primitive(instances[1]))
- db.block_device_mapping_get_all_by_instance(self.context,
- instances[1].uuid, use_slave=False).AndReturn([])
- self.conductor_manager.compute_rpcapi.build_and_run_instance(
- self.context,
- instance=mox.IgnoreArg(),
- host='host2',
- image={'fake_data': 'should_pass_silently'},
- request_spec={
- 'image': {'fake_data': 'should_pass_silently'},
- 'instance_properties': instance_properties,
- 'instance_type': instance_type,
- 'instance_uuids': [inst.uuid for inst in instances],
- 'num_instances': 2},
- filter_properties={'limits': [],
- 'retry': {'num_attempts': 1,
- 'hosts': [['host2', 'node2']]}},
- admin_password='admin_password',
- injected_files='injected_files',
- requested_networks=None,
- security_groups='security_groups',
- block_device_mapping=mox.IgnoreArg(),
- node='node2', limits=[])
- self.mox.ReplayAll()
-
- # build_instances() is a cast, we need to wait for it to complete
- self.useFixture(cast_as_call.CastAsCall(self.stubs))
-
- self.conductor.build_instances(self.context,
- instances=instances,
- image={'fake_data': 'should_pass_silently'},
- filter_properties={},
- admin_password='admin_password',
- injected_files='injected_files',
- requested_networks=None,
- security_groups='security_groups',
- block_device_mapping='block_device_mapping',
- legacy_bdm=False)
-
- def test_build_instances_scheduler_failure(self):
- instances = [fake_instance.fake_instance_obj(self.context)
- for i in xrange(2)]
- image = {'fake-data': 'should_pass_silently'}
- spec = {'fake': 'specs',
- 'instance_properties': instances[0]}
- exception = exc.NoValidHost(reason='fake-reason')
- self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec')
- self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group')
- self.mox.StubOutWithMock(scheduler_driver, 'handle_schedule_error')
- self.mox.StubOutWithMock(self.conductor_manager.scheduler_client,
- 'select_destinations')
-
- scheduler_utils.build_request_spec(self.context, image,
- mox.IgnoreArg()).AndReturn(spec)
- scheduler_utils.setup_instance_group(self.context, None, None)
- self.conductor_manager.scheduler_client.select_destinations(
- self.context, spec,
- {'retry': {'num_attempts': 1,
- 'hosts': []}}).AndRaise(exception)
- for instance in instances:
- scheduler_driver.handle_schedule_error(self.context, exception,
- instance.uuid, spec)
- self.mox.ReplayAll()
-
- # build_instances() is a cast, we need to wait for it to complete
- self.useFixture(cast_as_call.CastAsCall(self.stubs))
-
- self.conductor.build_instances(self.context,
- instances=instances,
- image=image,
- filter_properties={},
- admin_password='admin_password',
- injected_files='injected_files',
- requested_networks=None,
- security_groups='security_groups',
- block_device_mapping='block_device_mapping',
- legacy_bdm=False)
-
- def test_unshelve_instance_on_host(self):
- db_instance = self._create_fake_instance()
- instance = objects.Instance.get_by_uuid(self.context,
- db_instance['uuid'], expected_attrs=['system_metadata'])
- instance.vm_state = vm_states.SHELVED
- instance.task_state = task_states.UNSHELVING
- instance.save()
- system_metadata = instance.system_metadata
-
- self.mox.StubOutWithMock(self.conductor_manager.compute_rpcapi,
- 'start_instance')
- self.mox.StubOutWithMock(self.conductor_manager, '_delete_image')
- self.mox.StubOutWithMock(self.conductor_manager.compute_rpcapi,
- 'unshelve_instance')
-
- self.conductor_manager.compute_rpcapi.start_instance(self.context,
- instance)
- self.conductor_manager._delete_image(self.context,
- 'fake_image_id')
- self.mox.ReplayAll()
-
- system_metadata['shelved_at'] = timeutils.utcnow()
- system_metadata['shelved_image_id'] = 'fake_image_id'
- system_metadata['shelved_host'] = 'fake-mini'
- self.conductor_manager.unshelve_instance(self.context, instance)
-
- def test_unshelve_offloaded_instance_glance_image_not_found(self):
- shelved_image_id = "image_not_found"
-
- db_instance = self._create_fake_instance()
- instance = objects.Instance.get_by_uuid(
- self.context,
- db_instance['uuid'],
- expected_attrs=['system_metadata'])
- instance.vm_state = vm_states.SHELVED_OFFLOADED
- instance.task_state = task_states.UNSHELVING
- instance.save()
- system_metadata = instance.system_metadata
-
- self.mox.StubOutWithMock(self.conductor_manager.image_api, 'get')
-
- e = exc.ImageNotFound(image_id=shelved_image_id)
- self.conductor_manager.image_api.get(
- self.context, shelved_image_id, show_deleted=False).AndRaise(e)
- self.mox.ReplayAll()
-
- system_metadata['shelved_at'] = timeutils.utcnow()
- system_metadata['shelved_host'] = 'fake-mini'
- system_metadata['shelved_image_id'] = shelved_image_id
-
- self.assertRaises(
- exc.UnshelveException,
- self.conductor_manager.unshelve_instance,
- self.context, instance)
- self.assertEqual(instance.vm_state, vm_states.ERROR)
-
- def test_unshelve_offloaded_instance_image_id_is_none(self):
- db_instance = jsonutils.to_primitive(self._create_fake_instance())
- instance = objects.Instance.get_by_uuid(
- self.context,
- db_instance['uuid'],
- expected_attrs=['system_metadata'])
- instance.vm_state = vm_states.SHELVED_OFFLOADED
- instance.task_state = task_states.UNSHELVING
- system_metadata = instance.system_metadata
- system_metadata['shelved_image_id'] = None
- instance.save()
-
- self.assertRaises(
- exc.UnshelveException,
- self.conductor_manager.unshelve_instance,
- self.context, instance)
- self.assertEqual(instance.vm_state, vm_states.ERROR)
-
- def test_unshelve_instance_schedule_and_rebuild(self):
- db_instance = self._create_fake_instance()
- instance = objects.Instance.get_by_uuid(self.context,
- db_instance['uuid'], expected_attrs=['system_metadata'])
- instance.vm_state = vm_states.SHELVED_OFFLOADED
- instance.save()
- filter_properties = {}
- system_metadata = instance.system_metadata
-
- self.mox.StubOutWithMock(self.conductor_manager.image_api, 'get')
- self.mox.StubOutWithMock(self.conductor_manager, '_schedule_instances')
- self.mox.StubOutWithMock(self.conductor_manager.compute_rpcapi,
- 'unshelve_instance')
-
- self.conductor_manager.image_api.get(self.context,
- 'fake_image_id', show_deleted=False).AndReturn('fake_image')
- self.conductor_manager._schedule_instances(self.context,
- 'fake_image', filter_properties, instance).AndReturn(
- [{'host': 'fake_host',
- 'nodename': 'fake_node',
- 'limits': {}}])
- self.conductor_manager.compute_rpcapi.unshelve_instance(self.context,
- instance, 'fake_host', image='fake_image',
- filter_properties={'limits': {}}, node='fake_node')
- self.mox.ReplayAll()
-
- system_metadata['shelved_at'] = timeutils.utcnow()
- system_metadata['shelved_image_id'] = 'fake_image_id'
- system_metadata['shelved_host'] = 'fake-mini'
- self.conductor_manager.unshelve_instance(self.context, instance)
-
- def test_unshelve_instance_schedule_and_rebuild_novalid_host(self):
- db_instance = self._create_fake_instance()
- instance = objects.Instance.get_by_uuid(self.context,
- db_instance['uuid'], expected_attrs=['system_metadata'])
- instance.vm_state = vm_states.SHELVED_OFFLOADED
- instance.save()
- system_metadata = instance.system_metadata
-
- def fake_schedule_instances(context, image, filter_properties,
- *instances):
- raise exc.NoValidHost(reason='')
-
- with contextlib.nested(
- mock.patch.object(self.conductor_manager.image_api, 'get',
- return_value='fake_image'),
- mock.patch.object(self.conductor_manager, '_schedule_instances',
- fake_schedule_instances)
- ) as (_get_image, _schedule_instances):
- system_metadata['shelved_at'] = timeutils.utcnow()
- system_metadata['shelved_image_id'] = 'fake_image_id'
- system_metadata['shelved_host'] = 'fake-mini'
- self.conductor_manager.unshelve_instance(self.context, instance)
- _get_image.assert_has_calls([mock.call(self.context,
- system_metadata['shelved_image_id'],
- show_deleted=False)])
- self.assertEqual(vm_states.SHELVED_OFFLOADED, instance.vm_state)
-
- def test_unshelve_instance_schedule_and_rebuild_volume_backed(self):
- db_instance = self._create_fake_instance()
- instance = objects.Instance.get_by_uuid(self.context,
- db_instance['uuid'], expected_attrs=['system_metadata'])
- instance.vm_state = vm_states.SHELVED_OFFLOADED
- instance.save()
- filter_properties = {}
- system_metadata = instance.system_metadata
-
- self.mox.StubOutWithMock(self.conductor_manager.image_api, 'get')
- self.mox.StubOutWithMock(self.conductor_manager, '_schedule_instances')
- self.mox.StubOutWithMock(self.conductor_manager.compute_rpcapi,
- 'unshelve_instance')
-
- self.conductor_manager.image_api.get(self.context,
- 'fake_image_id', show_deleted=False).AndReturn(None)
- self.conductor_manager._schedule_instances(self.context,
- None, filter_properties, instance).AndReturn(
- [{'host': 'fake_host',
- 'nodename': 'fake_node',
- 'limits': {}}])
- self.conductor_manager.compute_rpcapi.unshelve_instance(self.context,
- instance, 'fake_host', image=None,
- filter_properties={'limits': {}}, node='fake_node')
- self.mox.ReplayAll()
-
- system_metadata['shelved_at'] = timeutils.utcnow()
- system_metadata['shelved_image_id'] = 'fake_image_id'
- system_metadata['shelved_host'] = 'fake-mini'
- self.conductor_manager.unshelve_instance(self.context, instance)
-
- def test_rebuild_instance(self):
- db_instance = self._create_fake_instance()
- inst_obj = objects.Instance.get_by_uuid(self.context,
- db_instance['uuid'])
- rebuild_args = self._prepare_rebuild_args({'host': inst_obj.host})
-
- with contextlib.nested(
- mock.patch.object(self.conductor_manager.compute_rpcapi,
- 'rebuild_instance'),
- mock.patch.object(self.conductor_manager.scheduler_client,
- 'select_destinations')
- ) as (rebuild_mock, select_dest_mock):
- self.conductor_manager.rebuild_instance(context=self.context,
- instance=inst_obj,
- **rebuild_args)
- self.assertFalse(select_dest_mock.called)
- rebuild_mock.assert_called_once_with(self.context,
- instance=inst_obj,
- **rebuild_args)
-
- def test_rebuild_instance_with_scheduler(self):
- db_instance = self._create_fake_instance()
- inst_obj = objects.Instance.get_by_uuid(self.context,
- db_instance['uuid'])
- inst_obj.host = 'noselect'
- rebuild_args = self._prepare_rebuild_args({'host': None})
- expected_host = 'thebesthost'
- request_spec = {}
- filter_properties = {'ignore_hosts': [(inst_obj.host)]}
-
- with contextlib.nested(
- mock.patch.object(self.conductor_manager.compute_rpcapi,
- 'rebuild_instance'),
- mock.patch.object(self.conductor_manager.scheduler_client,
- 'select_destinations',
- return_value=[{'host': expected_host}]),
- mock.patch('nova.scheduler.utils.build_request_spec',
- return_value=request_spec)
- ) as (rebuild_mock, select_dest_mock, bs_mock):
- self.conductor_manager.rebuild_instance(context=self.context,
- instance=inst_obj,
- **rebuild_args)
- select_dest_mock.assert_called_once_with(self.context,
- request_spec,
- filter_properties)
- rebuild_args['host'] = expected_host
- rebuild_mock.assert_called_once_with(self.context,
- instance=inst_obj,
- **rebuild_args)
-
- def test_rebuild_instance_with_scheduler_no_host(self):
- db_instance = self._create_fake_instance()
- inst_obj = objects.Instance.get_by_uuid(self.context,
- db_instance['uuid'])
- inst_obj.host = 'noselect'
- rebuild_args = self._prepare_rebuild_args({'host': None})
- request_spec = {}
- filter_properties = {'ignore_hosts': [(inst_obj.host)]}
-
- with contextlib.nested(
- mock.patch.object(self.conductor_manager.compute_rpcapi,
- 'rebuild_instance'),
- mock.patch.object(self.conductor_manager.scheduler_client,
- 'select_destinations',
- side_effect=exc.NoValidHost(reason='')),
- mock.patch('nova.scheduler.utils.build_request_spec',
- return_value=request_spec)
- ) as (rebuild_mock, select_dest_mock, bs_mock):
- self.assertRaises(exc.NoValidHost,
- self.conductor_manager.rebuild_instance,
- context=self.context, instance=inst_obj,
- **rebuild_args)
- select_dest_mock.assert_called_once_with(self.context,
- request_spec,
- filter_properties)
- self.assertFalse(rebuild_mock.called)
-
-
-class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase):
- """ComputeTaskManager Tests."""
- def setUp(self):
- super(ConductorTaskTestCase, self).setUp()
- self.conductor = conductor_manager.ComputeTaskManager()
- self.conductor_manager = self.conductor
-
- def test_migrate_server_fails_with_rebuild(self):
- self.assertRaises(NotImplementedError, self.conductor.migrate_server,
- self.context, None, None, True, True, None, None, None)
-
- def test_migrate_server_fails_with_flavor(self):
- self.assertRaises(NotImplementedError, self.conductor.migrate_server,
- self.context, None, None, True, False, "dummy", None, None)
-
- def _build_request_spec(self, instance):
- return {
- 'instance_properties': {
- 'uuid': instance['uuid'], },
- }
-
- def _test_migrate_server_deals_with_expected_exceptions(self, ex):
- instance = fake_instance.fake_db_instance(uuid='uuid',
- vm_state=vm_states.ACTIVE)
- inst_obj = objects.Instance._from_db_object(
- self.context, objects.Instance(), instance, [])
- self.mox.StubOutWithMock(live_migrate, 'execute')
- self.mox.StubOutWithMock(scheduler_utils,
- 'set_vm_state_and_notify')
-
- live_migrate.execute(self.context, mox.IsA(objects.Instance),
- 'destination', 'block_migration',
- 'disk_over_commit').AndRaise(ex)
-
- scheduler_utils.set_vm_state_and_notify(self.context,
- 'compute_task', 'migrate_server',
- {'vm_state': vm_states.ACTIVE,
- 'task_state': None,
- 'expected_task_state': task_states.MIGRATING},
- ex, self._build_request_spec(inst_obj),
- self.conductor_manager.db)
- self.mox.ReplayAll()
-
- self.conductor = utils.ExceptionHelper(self.conductor)
-
- self.assertRaises(type(ex),
- self.conductor.migrate_server, self.context, inst_obj,
- {'host': 'destination'}, True, False, None, 'block_migration',
- 'disk_over_commit')
-
- def test_migrate_server_deals_with_invalidcpuinfo_exception(self):
- instance = fake_instance.fake_db_instance(uuid='uuid',
- vm_state=vm_states.ACTIVE)
- inst_obj = objects.Instance._from_db_object(
- self.context, objects.Instance(), instance, [])
- self.mox.StubOutWithMock(live_migrate, 'execute')
- self.mox.StubOutWithMock(scheduler_utils,
- 'set_vm_state_and_notify')
-
- ex = exc.InvalidCPUInfo(reason="invalid cpu info.")
- live_migrate.execute(self.context, mox.IsA(objects.Instance),
- 'destination', 'block_migration',
- 'disk_over_commit').AndRaise(ex)
-
- scheduler_utils.set_vm_state_and_notify(self.context,
- 'compute_task', 'migrate_server',
- {'vm_state': vm_states.ACTIVE,
- 'task_state': None,
- 'expected_task_state': task_states.MIGRATING},
- ex, self._build_request_spec(inst_obj),
- self.conductor_manager.db)
- self.mox.ReplayAll()
-
- self.conductor = utils.ExceptionHelper(self.conductor)
-
- self.assertRaises(exc.InvalidCPUInfo,
- self.conductor.migrate_server, self.context, inst_obj,
- {'host': 'destination'}, True, False, None, 'block_migration',
- 'disk_over_commit')
-
- @mock.patch.object(scheduler_utils, 'set_vm_state_and_notify')
- @mock.patch.object(live_migrate, 'execute')
- def test_migrate_server_deals_with_instancenotrunning_exception(self,
- mock_live_migrate, mock_set_state):
- inst = fake_instance.fake_db_instance()
- inst_obj = objects.Instance._from_db_object(
- self.context, objects.Instance(), inst, [])
-
- error = exc.InstanceNotRunning(instance_id="fake")
- mock_live_migrate.side_effect = error
-
- self.conductor = utils.ExceptionHelper(self.conductor)
-
- self.assertRaises(exc.InstanceNotRunning,
- self.conductor.migrate_server, self.context, inst_obj,
- {'host': 'destination'}, True, False, None,
- 'block_migration', 'disk_over_commit')
-
- request_spec = self._build_request_spec(inst_obj)
- mock_set_state.assert_called_once_with(self.context, 'compute_task',
- 'migrate_server',
- dict(vm_state=inst_obj.vm_state,
- task_state=None,
- expected_task_state=task_states.MIGRATING),
- error, request_spec, self.conductor_manager.db)
-
- def test_migrate_server_deals_with_DestinationHypervisorTooOld(self):
- ex = exc.DestinationHypervisorTooOld()
- self._test_migrate_server_deals_with_expected_exceptions(ex)
-
- def test_migrate_server_deals_with_HypervisorUnavailable(self):
- ex = exc.HypervisorUnavailable(host='dummy')
- self._test_migrate_server_deals_with_expected_exceptions(ex)
-
- def test_migrate_server_deals_with_unexpected_exceptions(self):
- instance = fake_instance.fake_db_instance()
- inst_obj = objects.Instance._from_db_object(
- self.context, objects.Instance(), instance, [])
- self.mox.StubOutWithMock(live_migrate, 'execute')
- self.mox.StubOutWithMock(scheduler_utils,
- 'set_vm_state_and_notify')
-
- ex = IOError()
- live_migrate.execute(self.context, mox.IsA(objects.Instance),
- 'destination', 'block_migration',
- 'disk_over_commit').AndRaise(ex)
- self.mox.ReplayAll()
-
- self.conductor = utils.ExceptionHelper(self.conductor)
-
- self.assertRaises(exc.MigrationError,
- self.conductor.migrate_server, self.context, inst_obj,
- {'host': 'destination'}, True, False, None, 'block_migration',
- 'disk_over_commit')
-
- def test_set_vm_state_and_notify(self):
- self.mox.StubOutWithMock(scheduler_utils,
- 'set_vm_state_and_notify')
- scheduler_utils.set_vm_state_and_notify(
- self.context, 'compute_task', 'method', 'updates',
- 'ex', 'request_spec', self.conductor.db)
-
- self.mox.ReplayAll()
-
- self.conductor._set_vm_state_and_notify(
- self.context, 'method', 'updates', 'ex', 'request_spec')
-
- def test_cold_migrate_no_valid_host_back_in_active_state(self):
- flavor = flavors.get_flavor_by_name('m1.tiny')
- inst = fake_instance.fake_db_instance(image_ref='fake-image_ref',
- instance_type_id=flavor['id'])
- inst_obj = objects.Instance._from_db_object(
- self.context, objects.Instance(), inst,
- expected_attrs=[])
- request_spec = dict(instance_type=dict(extra_specs=dict()),
- instance_properties=dict())
- filter_props = dict(context=None)
- resvs = 'fake-resvs'
- image = 'fake-image'
-
- self.mox.StubOutWithMock(compute_utils, 'get_image_metadata')
- self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec')
- self.mox.StubOutWithMock(self.conductor.scheduler_client,
- 'select_destinations')
- self.mox.StubOutWithMock(self.conductor,
- '_set_vm_state_and_notify')
- self.mox.StubOutWithMock(quota.QUOTAS, 'rollback')
-
- compute_utils.get_image_metadata(
- self.context, self.conductor_manager.image_api,
- 'fake-image_ref', mox.IsA(objects.Instance)).AndReturn(image)
-
- scheduler_utils.build_request_spec(
- self.context, image, [inst_obj],
- instance_type=flavor).AndReturn(request_spec)
-
- exc_info = exc.NoValidHost(reason="")
-
- self.conductor.scheduler_client.select_destinations(
- self.context, request_spec,
- filter_props).AndRaise(exc_info)
-
- updates = {'vm_state': vm_states.ACTIVE,
- 'task_state': None}
-
- self.conductor._set_vm_state_and_notify(self.context,
- 'migrate_server',
- updates, exc_info,
- request_spec)
- # NOTE(mriedem): Validate that the quota rollback is using
- # the correct project_id and user_id.
- project_id, user_id = quotas_obj.ids_from_instance(self.context,
- inst_obj)
- quota.QUOTAS.rollback(self.context, [resvs], project_id=project_id,
- user_id=user_id)
-
- self.mox.ReplayAll()
-
- self.assertRaises(exc.NoValidHost,
- self.conductor._cold_migrate,
- self.context, inst_obj,
- flavor, filter_props, [resvs])
-
- def test_cold_migrate_no_valid_host_back_in_stopped_state(self):
- flavor = flavors.get_flavor_by_name('m1.tiny')
- inst = fake_instance.fake_db_instance(image_ref='fake-image_ref',
- vm_state=vm_states.STOPPED,
- instance_type_id=flavor['id'])
- inst_obj = objects.Instance._from_db_object(
- self.context, objects.Instance(), inst,
- expected_attrs=[])
- request_spec = dict(instance_type=dict(extra_specs=dict()),
- instance_properties=dict())
- filter_props = dict(context=None)
- resvs = 'fake-resvs'
- image = 'fake-image'
-
- self.mox.StubOutWithMock(compute_utils, 'get_image_metadata')
- self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec')
- self.mox.StubOutWithMock(self.conductor.scheduler_client,
- 'select_destinations')
- self.mox.StubOutWithMock(self.conductor,
- '_set_vm_state_and_notify')
- self.mox.StubOutWithMock(quota.QUOTAS, 'rollback')
-
- compute_utils.get_image_metadata(
- self.context, self.conductor_manager.image_api,
- 'fake-image_ref', mox.IsA(objects.Instance)).AndReturn(image)
-
- scheduler_utils.build_request_spec(
- self.context, image, [inst_obj],
- instance_type=flavor).AndReturn(request_spec)
-
- exc_info = exc.NoValidHost(reason="")
-
- self.conductor.scheduler_client.select_destinations(
- self.context, request_spec,
- filter_props).AndRaise(exc_info)
-
- updates = {'vm_state': vm_states.STOPPED,
- 'task_state': None}
-
- self.conductor._set_vm_state_and_notify(self.context,
- 'migrate_server',
- updates, exc_info,
- request_spec)
- # NOTE(mriedem): Validate that the quota rollback is using
- # the correct project_id and user_id.
- project_id, user_id = quotas_obj.ids_from_instance(self.context,
- inst_obj)
- quota.QUOTAS.rollback(self.context, [resvs], project_id=project_id,
- user_id=user_id)
-
- self.mox.ReplayAll()
-
- self.assertRaises(exc.NoValidHost,
- self.conductor._cold_migrate, self.context,
- inst_obj, flavor, filter_props, [resvs])
-
- def test_cold_migrate_no_valid_host_error_msg(self):
- flavor = flavors.get_flavor_by_name('m1.tiny')
- inst = fake_instance.fake_db_instance(image_ref='fake-image_ref',
- vm_state=vm_states.STOPPED,
- instance_type_id=flavor['id'])
- inst_obj = objects.Instance._from_db_object(
- self.context, objects.Instance(), inst,
- expected_attrs=[])
- request_spec = dict(instance_type=dict(extra_specs=dict()),
- instance_properties=dict())
- filter_props = dict(context=None)
- resvs = 'fake-resvs'
- image = 'fake-image'
-
- with contextlib.nested(
- mock.patch.object(compute_utils, 'get_image_metadata',
- return_value=image),
- mock.patch.object(scheduler_utils, 'build_request_spec',
- return_value=request_spec),
- mock.patch.object(self.conductor.scheduler_client,
- 'select_destinations',
- side_effect=exc.NoValidHost(reason=""))
- ) as (image_mock, brs_mock, select_dest_mock):
- nvh = self.assertRaises(exc.NoValidHost,
- self.conductor._cold_migrate, self.context,
- inst_obj, flavor, filter_props, [resvs])
- self.assertIn('cold migrate', nvh.message)
-
- def test_cold_migrate_exception_host_in_error_state_and_raise(self):
- inst = fake_instance.fake_db_instance(image_ref='fake-image_ref',
- vm_state=vm_states.STOPPED)
- inst_obj = objects.Instance._from_db_object(
- self.context, objects.Instance(), inst,
- expected_attrs=[])
- request_spec = dict(instance_type=dict(extra_specs=dict()),
- instance_properties=dict())
- filter_props = dict(context=None)
- resvs = 'fake-resvs'
- image = 'fake-image'
- hosts = [dict(host='host1', nodename=None, limits={})]
-
- self.mox.StubOutWithMock(compute_utils, 'get_image_metadata')
- self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec')
- self.mox.StubOutWithMock(self.conductor.scheduler_client,
- 'select_destinations')
- self.mox.StubOutWithMock(scheduler_utils,
- 'populate_filter_properties')
- self.mox.StubOutWithMock(self.conductor.compute_rpcapi,
- 'prep_resize')
- self.mox.StubOutWithMock(self.conductor,
- '_set_vm_state_and_notify')
- self.mox.StubOutWithMock(quota.QUOTAS, 'rollback')
-
- compute_utils.get_image_metadata(
- self.context, self.conductor_manager.image_api,
- 'fake-image_ref', mox.IsA(objects.Instance)).AndReturn(image)
-
- scheduler_utils.build_request_spec(
- self.context, image, [inst_obj],
- instance_type='flavor').AndReturn(request_spec)
-
- expected_filter_props = {'retry': {'num_attempts': 1,
- 'hosts': []},
- 'context': None}
- self.conductor.scheduler_client.select_destinations(
- self.context, request_spec,
- expected_filter_props).AndReturn(hosts)
-
- scheduler_utils.populate_filter_properties(filter_props,
- hosts[0])
- exc_info = test.TestingException('something happened')
-
- expected_filter_props = {'retry': {'num_attempts': 1,
- 'hosts': []}}
-
- self.conductor.compute_rpcapi.prep_resize(
- self.context, image, inst_obj,
- 'flavor', hosts[0]['host'], [resvs],
- request_spec=request_spec,
- filter_properties=expected_filter_props,
- node=hosts[0]['nodename']).AndRaise(exc_info)
-
- updates = {'vm_state': vm_states.STOPPED,
- 'task_state': None}
-
- self.conductor._set_vm_state_and_notify(self.context,
- 'migrate_server',
- updates, exc_info,
- request_spec)
- # NOTE(mriedem): Validate that the quota rollback is using
- # the correct project_id and user_id.
- project_id, user_id = quotas_obj.ids_from_instance(self.context,
- inst_obj)
- quota.QUOTAS.rollback(self.context, [resvs], project_id=project_id,
- user_id=user_id)
-
- self.mox.ReplayAll()
-
- self.assertRaises(test.TestingException,
- self.conductor._cold_migrate,
- self.context, inst_obj, 'flavor',
- filter_props, [resvs])
-
- def test_resize_no_valid_host_error_msg(self):
- flavor = flavors.get_flavor_by_name('m1.tiny')
- flavor_new = flavors.get_flavor_by_name('m1.small')
- inst = fake_instance.fake_db_instance(image_ref='fake-image_ref',
- vm_state=vm_states.STOPPED,
- instance_type_id=flavor['id'])
- inst_obj = objects.Instance._from_db_object(
- self.context, objects.Instance(), inst,
- expected_attrs=[])
- request_spec = dict(instance_type=dict(extra_specs=dict()),
- instance_properties=dict())
- filter_props = dict(context=None)
- resvs = 'fake-resvs'
- image = 'fake-image'
-
- with contextlib.nested(
- mock.patch.object(compute_utils, 'get_image_metadata',
- return_value=image),
- mock.patch.object(scheduler_utils, 'build_request_spec',
- return_value=request_spec),
- mock.patch.object(self.conductor.scheduler_client,
- 'select_destinations',
- side_effect=exc.NoValidHost(reason=""))
- ) as (image_mock, brs_mock, select_dest_mock):
- nvh = self.assertRaises(exc.NoValidHost,
- self.conductor._cold_migrate, self.context,
- inst_obj, flavor_new, filter_props,
- [resvs])
- self.assertIn('resize', nvh.message)
-
- def test_build_instances_instance_not_found(self):
- instances = [fake_instance.fake_instance_obj(self.context)
- for i in xrange(2)]
- self.mox.StubOutWithMock(instances[0], 'refresh')
- self.mox.StubOutWithMock(instances[1], 'refresh')
- image = {'fake-data': 'should_pass_silently'}
- spec = {'fake': 'specs',
- 'instance_properties': instances[0]}
- self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec')
- self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group')
- self.mox.StubOutWithMock(scheduler_driver, 'handle_schedule_error')
- self.mox.StubOutWithMock(self.conductor_manager.scheduler_client,
- 'select_destinations')
- self.mox.StubOutWithMock(self.conductor_manager.compute_rpcapi,
- 'build_and_run_instance')
-
- scheduler_utils.build_request_spec(self.context, image,
- mox.IgnoreArg()).AndReturn(spec)
- scheduler_utils.setup_instance_group(self.context, None, None)
- self.conductor_manager.scheduler_client.select_destinations(
- self.context, spec,
- {'retry': {'num_attempts': 1, 'hosts': []}}).AndReturn(
- [{'host': 'host1', 'nodename': 'node1', 'limits': []},
- {'host': 'host2', 'nodename': 'node2', 'limits': []}])
- instances[0].refresh().AndRaise(
- exc.InstanceNotFound(instance_id=instances[0].uuid))
- instances[1].refresh()
- self.conductor_manager.compute_rpcapi.build_and_run_instance(
- self.context, instance=instances[1], host='host2',
- image={'fake-data': 'should_pass_silently'}, request_spec=spec,
- filter_properties={'limits': [],
- 'retry': {'num_attempts': 1,
- 'hosts': [['host2',
- 'node2']]}},
- admin_password='admin_password',
- injected_files='injected_files',
- requested_networks=None,
- security_groups='security_groups',
- block_device_mapping=mox.IsA(objects.BlockDeviceMappingList),
- node='node2', limits=[])
- self.mox.ReplayAll()
-
- # build_instances() is a cast, we need to wait for it to complete
- self.useFixture(cast_as_call.CastAsCall(self.stubs))
-
- self.conductor.build_instances(self.context,
- instances=instances,
- image=image,
- filter_properties={},
- admin_password='admin_password',
- injected_files='injected_files',
- requested_networks=None,
- security_groups='security_groups',
- block_device_mapping='block_device_mapping',
- legacy_bdm=False)
-
- @mock.patch.object(scheduler_utils, 'setup_instance_group')
- @mock.patch.object(scheduler_utils, 'build_request_spec')
- def test_build_instances_info_cache_not_found(self, build_request_spec,
- setup_instance_group):
- instances = [fake_instance.fake_instance_obj(self.context)
- for i in xrange(2)]
- image = {'fake-data': 'should_pass_silently'}
- destinations = [{'host': 'host1', 'nodename': 'node1', 'limits': []},
- {'host': 'host2', 'nodename': 'node2', 'limits': []}]
- spec = {'fake': 'specs',
- 'instance_properties': instances[0]}
- build_request_spec.return_value = spec
- with contextlib.nested(
- mock.patch.object(instances[0], 'refresh',
- side_effect=exc.InstanceInfoCacheNotFound(
- instance_uuid=instances[0].uuid)),
- mock.patch.object(instances[1], 'refresh'),
- mock.patch.object(self.conductor_manager.scheduler_client,
- 'select_destinations', return_value=destinations),
- mock.patch.object(self.conductor_manager.compute_rpcapi,
- 'build_and_run_instance')
- ) as (inst1_refresh, inst2_refresh, select_destinations,
- build_and_run_instance):
-
- # build_instances() is a cast, we need to wait for it to complete
- self.useFixture(cast_as_call.CastAsCall(self.stubs))
-
- self.conductor.build_instances(self.context,
- instances=instances,
- image=image,
- filter_properties={},
- admin_password='admin_password',
- injected_files='injected_files',
- requested_networks=None,
- security_groups='security_groups',
- block_device_mapping='block_device_mapping',
- legacy_bdm=False)
-
- setup_instance_group.assert_called_once_with(
- self.context, None, None)
- build_and_run_instance.assert_called_once_with(self.context,
- instance=instances[1], host='host2', image={'fake-data':
- 'should_pass_silently'}, request_spec=spec,
- filter_properties={'limits': [],
- 'retry': {'num_attempts': 1,
- 'hosts': [['host2',
- 'node2']]}},
- admin_password='admin_password',
- injected_files='injected_files',
- requested_networks=None,
- security_groups='security_groups',
- block_device_mapping=mock.ANY,
- node='node2', limits=[])
-
-
-class ConductorTaskRPCAPITestCase(_BaseTaskTestCase,
- test_compute.BaseTestCase):
- """Conductor compute_task RPC namespace Tests."""
- def setUp(self):
- super(ConductorTaskRPCAPITestCase, self).setUp()
- self.conductor_service = self.start_service(
- 'conductor', manager='nova.conductor.manager.ConductorManager')
- self.conductor = conductor_rpcapi.ComputeTaskAPI()
- service_manager = self.conductor_service.manager
- self.conductor_manager = service_manager.compute_task_mgr
-
-
-class ConductorTaskAPITestCase(_BaseTaskTestCase, test_compute.BaseTestCase):
- """Compute task API Tests."""
- def setUp(self):
- super(ConductorTaskAPITestCase, self).setUp()
- self.conductor_service = self.start_service(
- 'conductor', manager='nova.conductor.manager.ConductorManager')
- self.conductor = conductor_api.ComputeTaskAPI()
- service_manager = self.conductor_service.manager
- self.conductor_manager = service_manager.compute_task_mgr
-
-
-class ConductorLocalComputeTaskAPITestCase(ConductorTaskAPITestCase):
- """Conductor LocalComputeTaskAPI Tests."""
- def setUp(self):
- super(ConductorLocalComputeTaskAPITestCase, self).setUp()
- self.conductor = conductor_api.LocalComputeTaskAPI()
- self.conductor_manager = self.conductor._manager._target