def test_execute_rollback(self, prep_resize_mock, sel_dest_mock, sig_mock, az_mock, gmv_mock, cm_mock, sm_mock, cn_mock, rc_mock, mock_ra, mock_gbf): sel_dest_mock.return_value = self.host_lists az_mock.return_value = 'myaz' task = self._generate_task() gmv_mock.return_value = 23 mock_gbf.return_value = objects.MigrationList() mock_get_resources = \ self.mock_network_api.get_requested_resource_for_instance mock_get_resources.return_value = [] # We just need this hook point to set a uuid on the # migration before we use it for teardown def set_migration_uuid(*a, **k): task._migration.uuid = uuids.migration return mock.MagicMock() # NOTE(danms): It's odd to do this on cn_mock, but it's just because # of when we need to have it set in the flow and where we have an easy # place to find it via self.migration. cn_mock.side_effect = set_migration_uuid prep_resize_mock.side_effect = test.TestingException task._held_allocations = mock.sentinel.allocs self.assertRaises(test.TestingException, task.execute) self.assertIsNotNone(task._migration) task._migration.create.assert_called_once_with() task._migration.save.assert_called_once_with() self.assertEqual('error', task._migration.status) mock_ra.assert_called_once_with(task.context, task._source_cn, task.instance, task._migration) mock_get_resources.assert_called_once_with(self.context, self.instance.uuid)
def test_get_migrations(self): filters = {'status': 'confirmed'} cell1_migrations = objects.MigrationList( objects=[objects.Migration(id=123)]) cell2_migrations = objects.MigrationList( objects=[objects.Migration(id=456)]) fake_responses = [ self._get_fake_response(cell1_migrations), self._get_fake_response(cell2_migrations) ] self.mox.StubOutWithMock(self.msg_runner, 'get_migrations') self.msg_runner.get_migrations(self.ctxt, None, False, filters).\ AndReturn(fake_responses) self.mox.ReplayAll() response = self.cells_manager.get_migrations(self.ctxt, filters) self.assertEqual(cell1_migrations.objects + cell2_migrations.objects, response.objects)
def test_get_migrations_for_a_given_cell(self): filters = {'status': 'confirmed', 'cell_name': 'ChildCell1'} target_cell = '%s%s%s' % (CONF.cells.name, '!', filters['cell_name']) migrations = objects.MigrationList(objects=[objects.Migration(id=123)]) fake_responses = [self._get_fake_response(migrations)] self.mox.StubOutWithMock(self.msg_runner, 'get_migrations') self.msg_runner.get_migrations(self.ctxt, target_cell, False, filters).AndReturn(fake_responses) self.mox.ReplayAll() response = self.cells_manager.get_migrations(self.ctxt, filters) self.assertEqual(migrations.objects, response.objects)
def get_migrations(self, ctxt, filters): """Fetch migrations applying the filters.""" target_cell = None if "cell_name" in filters: _path_cell_sep = cells_utils.PATH_CELL_SEP target_cell = '%s%s%s' % (CONF.cells.name, _path_cell_sep, filters['cell_name']) responses = self.msg_runner.get_migrations(ctxt, target_cell, False, filters) migrations = [] for response in responses: # response.value_or_raise returns MigrationList objects. # MigrationList.objects returns the list of Migration objects. migrations.extend(response.value_or_raise().objects) return objects.MigrationList(objects=migrations)
class MigrationTestCaseV266(MigrationsTestCaseV259): wsgi_api_version = '2.66' def test_index_with_invalid_changes_before(self): """Tests detail paging with an invalid changes-before value.""" req = fakes.HTTPRequest.blank( '/os-migrations?changes-before=wrong_time', version=self.wsgi_api_version, use_admin_context=True) self.assertRaises(exception.ValidationError, self.controller.index, req) def test_index_with_changes_before_old_microversion_failed(self): """Tests that the changes-before query parameter is an error before microversion 2.66. """ # Also use a valid filter (instance_uuid) to make sure # changes-before is an additional property. req = fakes.HTTPRequest.blank( '/os-migrations?changes-before=2018-01-10T16:59:24.138939&' 'instance_uuid=%s' % uuids.instance_uuid, version='2.65', use_admin_context=True) ex = self.assertRaises(exception.ValidationError, self.controller.index, req) self.assertIn('Additional properties are not allowed', six.text_type(ex)) @mock.patch('nova.compute.api.API.get_migrations', return_value=objects.MigrationList()) def test_index_with_changes_before_old_microversion(self, get_migrations): """Tests that the changes-before query parameter is ignored before microversion 2.59. """ # Also use a valid filter (instance_uuid) to make sure only # changes-before is removed. req = fakes.HTTPRequest.blank( '/os-migrations?changes-before=2018-01-10T16:59:24.138939&' 'instance_uuid=%s' % uuids.instance_uuid, version='2.58', use_admin_context=True) result = self.controller.index(req) self.assertEqual({'migrations': []}, result) get_migrations.assert_called_once_with( req.environ['nova.context'], {'instance_uuid': uuids.instance_uuid})
'memory_processed': 56789, 'memory_remaining': 400000, 'disk_total': 96789, 'disk_processed': 6789, 'disk_remaining': 90000, 'created_at': datetime.datetime(2013, 10, 22, 13, 42, 2), 'updated_at': datetime.datetime(2013, 10, 22, 13, 42, 2), 'deleted_at': None, 'deleted': False, 'uuid': uuids.migration2, 'cross_cell_move': False, 'user_id': None, 'project_id': None }] migrations_obj = base.obj_make_list('fake-context', objects.MigrationList(), objects.Migration, fake_migrations) class ServerMigrationsTestsV21(test.NoDBTestCase): wsgi_api_version = '2.22' def setUp(self): super(ServerMigrationsTestsV21, self).setUp() self.req = fakes.HTTPRequest.blank('', version=self.wsgi_api_version) self.context = self.req.environ['nova.context'] self.controller = server_migrations.ServerMigrationsController() self.compute_api = self.controller.compute_api def test_force_complete_succeeded(self): @mock.patch.object(self.compute_api, 'live_migrate_force_complete')
def _test_execute(self, prep_resize_mock, sel_dest_mock, sig_mock, az_mock, gmv_mock, cm_mock, sm_mock, cn_mock, rc_mock, gbf_mock, requested_destination=False): sel_dest_mock.return_value = self.host_lists az_mock.return_value = 'myaz' gbf_mock.return_value = objects.MigrationList() mock_get_resources = \ self.mock_network_api.get_requested_resource_for_instance mock_get_resources.return_value = [] if requested_destination: self.request_spec.requested_destination = objects.Destination( host='target_host', node=None) self.request_spec.retry = objects.SchedulerRetries.from_dict( self.context, self.filter_properties['retry']) self.filter_properties.pop('retry') self.filter_properties['requested_destination'] = ( self.request_spec.requested_destination) task = self._generate_task() gmv_mock.return_value = 23 # We just need this hook point to set a uuid on the # migration before we use it for teardown def set_migration_uuid(*a, **k): task._migration.uuid = uuids.migration return mock.MagicMock() # NOTE(danms): It's odd to do this on cn_mock, but it's just because # of when we need to have it set in the flow and where we have an easy # place to find it via self.migration. cn_mock.side_effect = set_migration_uuid selection = self.host_lists[0][0] with mock.patch.object(scheduler_utils, 'fill_provider_mapping') as fill_mock: task.execute() fill_mock.assert_called_once_with(task.context, task.reportclient, task.request_spec, selection) self.ensure_network_metadata_mock.assert_called_once_with( self.instance) self.heal_reqspec_is_bfv_mock.assert_called_once_with( self.context, self.request_spec, self.instance) sig_mock.assert_called_once_with(self.context, self.request_spec) task.query_client.select_destinations.assert_called_once_with( self.context, self.request_spec, [self.instance.uuid], return_objects=True, return_alternates=True) prep_resize_mock.assert_called_once_with( self.context, self.instance, self.request_spec.image, self.flavor, selection.service_host, task._migration, request_spec=self.request_spec, filter_properties=self.filter_properties, node=selection.nodename, clean_shutdown=self.clean_shutdown, host_list=[]) az_mock.assert_called_once_with(self.context, 'host1') self.assertIsNotNone(task._migration) old_flavor = self.instance.flavor new_flavor = self.flavor self.assertEqual(old_flavor.id, task._migration.old_instance_type_id) self.assertEqual(new_flavor.id, task._migration.new_instance_type_id) self.assertEqual('pre-migrating', task._migration.status) self.assertEqual(self.instance.uuid, task._migration.instance_uuid) self.assertEqual(self.instance.host, task._migration.source_compute) self.assertEqual(self.instance.node, task._migration.source_node) if old_flavor.id != new_flavor.id: self.assertEqual('resize', task._migration.migration_type) else: self.assertEqual('migration', task._migration.migration_type) task._migration.create.assert_called_once_with() if requested_destination: self.assertIsNone(self.request_spec.retry) self.assertIn('cell', self.request_spec.requested_destination) self.assertIsNotNone(self.request_spec.requested_destination.cell) mock_get_resources.assert_called_once_with(self.context, self.instance.uuid) self.assertEqual([], self.request_spec.requested_resources)
class MigrationTestCaseV266(MigrationsTestCaseV259): wsgi_api_version = '2.66' def test_index_with_invalid_changes_before(self): """Tests detail paging with an invalid changes-before value.""" req = fakes.HTTPRequest.blank( '/os-migrations?changes-before=wrong_time', version=self.wsgi_api_version, use_admin_context=True) self.assertRaises(exception.ValidationError, self.controller.index, req) @mock.patch('nova.compute.api.API.get_migrations_sorted', return_value=objects.MigrationList()) def test_index_with_changes_since_and_changes_before( self, get_migrations_sorted): changes_since = '2013-10-22T13:42:02Z' changes_before = '2013-10-22T13:42:03Z' req = fakes.HTTPRequest.blank( '/os-migrations?changes-since=%s&changes-before=%s&' 'instance_uuid=%s' % (changes_since, changes_before, uuids.instance_uuid), version=self.wsgi_api_version, use_admin_context=True) self.controller.index(req) search_opts = { 'instance_uuid': uuids.instance_uuid, 'changes-before': datetime.datetime(2013, 10, 22, 13, 42, 3, tzinfo=iso8601.iso8601.UTC), 'changes-since': datetime.datetime(2013, 10, 22, 13, 42, 2, tzinfo=iso8601.iso8601.UTC) } get_migrations_sorted.assert_called_once_with( req.environ['nova.context'], search_opts, sort_dirs=mock.ANY, sort_keys=mock.ANY, limit=1000, marker=None) def test_get_migrations_filters_with_distinct_changes_time_bad_request( self): changes_since = '2018-09-04T05:45:27Z' changes_before = '2018-09-03T05:45:27Z' req = fakes.HTTPRequest.blank('/os-migrations?' 'changes-since=%s&changes-before=%s' % (changes_since, changes_before), version=self.wsgi_api_version, use_admin_context=True) ex = self.assertRaises(exc.HTTPBadRequest, self.controller.index, req) self.assertIn( 'The value of changes-since must be less than ' 'or equal to changes-before', six.text_type(ex)) def test_index_with_changes_before_old_microversion_failed(self): """Tests that the changes-before query parameter is an error before microversion 2.66. """ # Also use a valid filter (instance_uuid) to make sure # changes-before is an additional property. req = fakes.HTTPRequest.blank( '/os-migrations?changes-before=2018-01-10T16:59:24.138939&' 'instance_uuid=%s' % uuids.instance_uuid, version='2.65', use_admin_context=True) ex = self.assertRaises(exception.ValidationError, self.controller.index, req) self.assertIn('Additional properties are not allowed', six.text_type(ex)) @mock.patch('nova.compute.api.API.get_migrations', return_value=objects.MigrationList()) def test_index_with_changes_before_old_microversion(self, get_migrations): """Tests that the changes-before query parameter is ignored before microversion 2.59. """ # Also use a valid filter (instance_uuid) to make sure only # changes-before is removed. req = fakes.HTTPRequest.blank( '/os-migrations?changes-before=2018-01-10T16:59:24.138939&' 'instance_uuid=%s' % uuids.instance_uuid, version='2.58', use_admin_context=True) result = self.controller.index(req) self.assertEqual({'migrations': []}, result) get_migrations.assert_called_once_with( req.environ['nova.context'], {'instance_uuid': uuids.instance_uuid})
class MigrationsTestCaseV259(MigrationsTestCaseV223): wsgi_api_version = '2.59' def test_index(self): migrations = { 'migrations': self.controller._output(self.req, migrations_obj, True, True) } for i, mig in enumerate(migrations['migrations']): # first item is in-progress live migration if i == 0: self.assertIn('links', mig) else: self.assertNotIn('links', mig) self.assertIn('migration_type', mig) self.assertIn('id', mig) self.assertIn('uuid', mig) self.assertNotIn('deleted', mig) self.assertNotIn('deleted_at', mig) with mock.patch.object(self.controller.compute_api, 'get_migrations_sorted') as m_get: m_get.return_value = migrations_obj response = self.controller.index(self.req) self.assertEqual(migrations, response) self.assertIn('links', response['migrations'][0]) self.assertIn('migration_type', response['migrations'][0]) @mock.patch('nova.compute.api.API.get_migrations_sorted') def test_index_with_invalid_marker(self, mock_migrations_get): """Tests detail paging with an invalid marker (not found).""" mock_migrations_get.side_effect = exception.MarkerNotFound( marker=uuids.invalid_marker) req = fakes.HTTPRequest.blank('/os-migrations?marker=%s' % uuids.invalid_marker, version=self.wsgi_api_version, use_admin_context=True) e = self.assertRaises(exc.HTTPBadRequest, self.controller.index, req) self.assertEqual( "Marker %s could not be found." % uuids.invalid_marker, six.text_type(e)) def test_index_with_invalid_limit(self): """Tests detail paging with an invalid limit.""" req = fakes.HTTPRequest.blank('/os-migrations?limit=x', version=self.wsgi_api_version, use_admin_context=True) self.assertRaises(exception.ValidationError, self.controller.index, req) req = fakes.HTTPRequest.blank('/os-migrations?limit=-1', version=self.wsgi_api_version, use_admin_context=True) self.assertRaises(exception.ValidationError, self.controller.index, req) def test_index_with_invalid_changes_since(self): """Tests detail paging with an invalid changes-since value.""" req = fakes.HTTPRequest.blank( '/os-migrations?changes-since=wrong_time', version=self.wsgi_api_version, use_admin_context=True) self.assertRaises(exception.ValidationError, self.controller.index, req) def test_index_with_unknown_query_param(self): """Tests detail paging with an unknown query parameter.""" req = fakes.HTTPRequest.blank('/os-migrations?foo=bar', version=self.wsgi_api_version, use_admin_context=True) ex = self.assertRaises(exception.ValidationError, self.controller.index, req) self.assertIn('Additional properties are not allowed', six.text_type(ex)) @mock.patch('nova.compute.api.API.get_migrations', return_value=objects.MigrationList()) def test_index_with_changes_since_old_microversion(self, get_migrations): """Tests that the changes-since query parameter is ignored before microversion 2.59. """ # Also use a valid filter (instance_uuid) to make sure only # changes-since is removed. req = fakes.HTTPRequest.blank( '/os-migrations?changes-since=2018-01-10T16:59:24.138939&' 'instance_uuid=%s' % uuids.instance_uuid, version='2.58', use_admin_context=True) result = self.controller.index(req) self.assertEqual({'migrations': []}, result) get_migrations.assert_called_once_with( req.environ['nova.context'], {'instance_uuid': uuids.instance_uuid})
'dest_compute': 'compute20', 'dest_host': '5.6.7.8', 'status': 'Done', 'instance_uuid': 'instance_id_456', 'old_instance_type_id': 5, 'new_instance_type_id': 6, 'created_at': datetime.datetime(2013, 10, 22, 13, 42, 2), 'updated_at': datetime.datetime(2013, 10, 22, 13, 42, 2), 'deleted_at': None, 'deleted': False } ] migrations_obj = base.obj_make_list( 'fake-context', objects.MigrationList(), objects.Migration, fake_migrations) class FakeRequest(object): environ = {"nova.context": context.RequestContext('fake_user', 'fake', is_admin=True)} GET = {} class MigrationsTestCaseV21(test.NoDBTestCase): migrations = migrations_v21 def setUp(self): """Run before each test."""
def get_migration_objects_sorted(ctx, filters, limit, marker, sort_keys, sort_dirs): mig_generator = MigrationLister(sort_keys, sort_dirs).get_records_sorted( ctx, filters, limit, marker) return base.obj_make_list(ctx, objects.MigrationList(), objects.Migration, mig_generator)
def test_find_destination_works_with_instance_group(self): self.instance.numa_topology = None self.fake_spec.instance_group = objects.InstanceGroup(members=["uuid"]) self.instance_uuid = self.instance.uuid = "uuid-2" updated_instance_group = objects.InstanceGroup( members=["uuid", "uuid-2"], hosts=['host1', 'host2'], policies=['anti-affinity'], metadetails={'wrs-sg:best_effort': 'false'}) expected_instance_group = copy.deepcopy(updated_instance_group) expected_instance_group.hosts = ['host1', 'host2', 'host3'] migration = objects.Migration(source_compute='host1', dest_compute='host3') migrations = objects.MigrationList(objects=[migration]) self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata') self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group') self.mox.StubOutWithMock(objects.RequestSpec, 'reset_forced_destinations') self.mox.StubOutWithMock(objects.InstanceGroup, 'get_by_instance_uuid') self.mox.StubOutWithMock(objects.MigrationList, 'get_by_filters') filters = { 'migration_type': 'live-migration', 'instance_uuid': 'uuid', 'status': ['queued', 'accepted', 'pre-migrating', 'preparing', 'running'] } self.mox.StubOutWithMock(self.task, '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') self.mox.StubOutWithMock(self.instance, 'is_volume_backed') def fake_select_destinations(context, request_spec, instance_uuids): self.assertEqual(expected_instance_group.members, request_spec.instance_group.members) self.assertEqual(expected_instance_group.hosts, request_spec.instance_group.hosts) return [{ 'host': 'host1', 'nodename': 'node1', 'limits': 'fake-limits' }] self.instance.is_volume_backed().AndReturn(False) self.task.scheduler_client.select_destinations = \ fake_select_destinations utils.get_image_from_system_metadata( self.instance.system_metadata).AndReturn("image") scheduler_utils.setup_instance_group(self.context, self.fake_spec) self.fake_spec.reset_forced_destinations() objects.InstanceGroup.get_by_instance_uuid( self.context, self.instance_uuid).AndReturn(updated_instance_group) objects.MigrationList.get_by_filters(self.context, filters).AndReturn(migrations) self.task._check_compatible_with_source_hypervisor("host1") self.task._call_livem_checks_on_host("host1", limits='fake-limits') self.mox.ReplayAll() self.assertEqual(("host1", 'fake-limits'), self.task._find_destination()) self.mox.VerifyAll()