def _test_resources_from_request_spec(self, expected, flavor, image=objects.ImageMeta()): fake_spec = objects.RequestSpec(flavor=flavor, image=image) resources = utils.resources_from_request_spec(fake_spec) self.assertResourceRequestsEqual(expected, resources) return resources
def test_from_flavor_as_object(self): flavor = objects.Flavor() spec = objects.RequestSpec() spec._from_flavor(flavor) self.assertEqual(flavor, spec.flavor)
def test_from_retry_missing_values(self): retry_dict = {} ctxt = context.RequestContext('fake', 'fake') spec = objects.RequestSpec(ctxt) spec._from_retry(retry_dict) self.assertIsNone(spec.retry)
def test_security_groups_load(self): req_obj = objects.RequestSpec() self.assertNotIn('security_groups', req_obj) self.assertIsInstance(req_obj.security_groups, objects.SecurityGroupList) self.assertIn('security_groups', req_obj)
def test_map_az(self, getmd): getmd.return_value = [objects.Aggregate(uuid=uuids.agg1)] reqspec = objects.RequestSpec(availability_zone='fooaz') request_filter.map_az_to_placement_aggregate(self.context, reqspec) self.assertEqual([uuids.agg1], reqspec.requested_destination.aggregates)
def test_to_legacy_filter_properties_dict_with_unset_values(self): spec = objects.RequestSpec() self.assertEqual({}, spec.to_legacy_filter_properties_dict())
def test_compat_requested_destination(self): req_obj = objects.RequestSpec() versions = ovo_base.obj_tree_get_versions('RequestSpec') primitive = req_obj.obj_to_primitive(target_version='1.5', version_manifest=versions) self.assertNotIn('requested_destination', primitive)
def test_unshelve(self, mock_setup_network, mock_get_power_state, mock_spawn, mock_prep_block_device, mock_notify_instance_usage, mock_notify_instance_action, mock_get_bdms): mock_bdms = mock.Mock() mock_get_bdms.return_value = mock_bdms instance = self._create_fake_instance_obj() instance.task_state = task_states.UNSHELVING instance.save() image = {'id': uuids.image_id} node = test_compute.NODENAME limits = {} filter_properties = {'limits': limits} host = 'fake-mini' cur_time = timeutils.utcnow() # Adding shelved_* keys in system metadata to verify # whether those are deleted after unshelve call. sys_meta = dict(instance.system_metadata) sys_meta['shelved_at'] = cur_time.isoformat() sys_meta['shelved_image_id'] = image['id'] sys_meta['shelved_host'] = host instance.system_metadata = sys_meta self.deleted_image_id = None def fake_delete(self2, ctxt, image_id): self.deleted_image_id = image_id def fake_claim(context, instance, node, allocations, limits): instance.host = self.compute.host requests = objects.InstancePCIRequests(requests=[]) return claims.Claim(context, instance, test_compute.NODENAME, self.rt, _fake_resources(), requests) tracking = { 'last_state': instance.task_state, 'spawned': False, } def check_save(expected_task_state=None): if tracking['last_state'] == task_states.UNSHELVING: if tracking['spawned']: self.assertIsNone(instance.task_state) else: self.assertEqual(task_states.SPAWNING, instance.task_state) tracking['spawned'] = True tracking['last_state'] == instance.task_state elif tracking['last_state'] == task_states.SPAWNING: self.assertEqual(vm_states.ACTIVE, instance.vm_state) tracking['last_state'] == instance.task_state else: self.fail('Unexpected save!') self.useFixture(fixtures.GlanceFixture(self)) self.stub_out('nova.tests.fixtures.GlanceFixture.delete', fake_delete) with mock.patch.object(self.rt, 'instance_claim', side_effect=fake_claim), \ mock.patch.object(instance, 'save') as mock_save: mock_save.side_effect = check_save self.compute.unshelve_instance( self.context, instance, image=image, filter_properties=filter_properties, node=node, request_spec=objects.RequestSpec()) mock_notify_instance_action.assert_has_calls([ mock.call(self.context, instance, 'fake-mini', action='unshelve', phase='start', bdms=mock_bdms), mock.call(self.context, instance, 'fake-mini', action='unshelve', phase='end', bdms=mock_bdms)]) # prepare expect call lists mock_notify_instance_usage_call_list = [ mock.call(self.context, instance, 'unshelve.start'), mock.call(self.context, instance, 'unshelve.end')] mock_notify_instance_usage.assert_has_calls( mock_notify_instance_usage_call_list) mock_prep_block_device.assert_called_once_with(self.context, instance, mock.ANY) mock_setup_network.assert_called_once_with( self.context, instance, self.compute.host, provider_mappings=None) mock_spawn.assert_called_once_with(self.context, instance, test.MatchType(objects.ImageMeta), injected_files=[], admin_password=None, allocations={}, network_info=[], block_device_info='fake_bdm') self.mock_get_allocations.assert_called_once_with(self.context, instance.uuid) mock_get_power_state.assert_called_once_with(instance) self.assertNotIn('shelved_at', instance.system_metadata) self.assertNotIn('shelved_image_id', instance.system_metadata) self.assertNotIn('shelved_host', instance.system_metadata) self.assertEqual(image['id'], self.deleted_image_id) self.assertEqual(instance.host, self.compute.host) self.assertEqual(123, instance.power_state) self.assertEqual(vm_states.ACTIVE, instance.vm_state) self.assertIsNone(instance.task_state) self.assertIsNone(instance.key_data) self.assertEqual(self.compute.host, instance.host) self.assertFalse(instance.auto_disk_config)
def test_unshelve_volume_backed(self, mock_image_meta, mock_notify_instance_usage, mock_prep_block_device, mock_spawn, mock_get_power_state, mock_setup_network, mock_instance_claim, mock_notify_instance_action, mock_get_bdms): mock_bdms = mock.Mock() mock_get_bdms.return_value = mock_bdms instance = self._create_fake_instance_obj() node = test_compute.NODENAME limits = {} filter_properties = {'limits': limits} instance.task_state = task_states.UNSHELVING instance.save() image_meta = {'properties': {'base_image_ref': uuids.image_id}} mock_image_meta.return_value = image_meta tracking = {'last_state': instance.task_state} def fake_claim(context, instance, node, allocations, limits): instance.host = self.compute.host requests = objects.InstancePCIRequests(requests=[]) return claims.Claim(context, instance, test_compute.NODENAME, self.rt, _fake_resources(), requests) mock_instance_claim.side_effect = fake_claim def check_save(expected_task_state=None): if tracking['last_state'] == task_states.UNSHELVING: self.assertEqual(task_states.SPAWNING, instance.task_state) tracking['last_state'] = instance.task_state elif tracking['last_state'] == task_states.SPAWNING: self.assertEqual(123, instance.power_state) self.assertEqual(vm_states.ACTIVE, instance.vm_state) self.assertIsNone(instance.task_state) self.assertIsNone(instance.key_data) self.assertFalse(instance.auto_disk_config) self.assertIsNone(instance.task_state) tracking['last_state'] = instance.task_state else: self.fail('Unexpected save!') with mock.patch.object(instance, 'save') as mock_save: mock_save.side_effect = check_save self.compute.unshelve_instance(self.context, instance, image=None, filter_properties=filter_properties, node=node, request_spec=objects.RequestSpec()) mock_notify_instance_action.assert_has_calls([ mock.call(self.context, instance, 'fake-mini', action='unshelve', phase='start', bdms=mock_bdms), mock.call(self.context, instance, 'fake-mini', action='unshelve', phase='end', bdms=mock_bdms)]) # prepare expect call lists mock_notify_instance_usage_call_list = [ mock.call(self.context, instance, 'unshelve.start'), mock.call(self.context, instance, 'unshelve.end')] mock_notify_instance_usage.assert_has_calls( mock_notify_instance_usage_call_list) mock_prep_block_device.assert_called_once_with(self.context, instance, mock.ANY) mock_setup_network.assert_called_once_with( self.context, instance, self.compute.host, provider_mappings=None) mock_instance_claim.assert_called_once_with(self.context, instance, test_compute.NODENAME, {}, limits) mock_spawn.assert_called_once_with(self.context, instance, test.MatchType(objects.ImageMeta), injected_files=[], admin_password=None, allocations={}, network_info=[], block_device_info='fake_bdm') self.mock_get_allocations.assert_called_once_with(self.context, instance.uuid) mock_get_power_state.assert_called_once_with(instance)
def test_select_destination(self): fake_spec = objects.RequestSpec() with mock.patch.object(self.manager.driver, 'select_destinations') as select_destinations: self.manager.select_destinations(None, spec_obj=fake_spec) select_destinations.assert_called_once_with(None, fake_spec)
def test_schedule_instance_group(self, mock_get_hosts, mock_get_all_states, mock_claim): """Test that since the request spec object contains an instance group object, that upon choosing a host in the primary schedule loop, that we update the request spec's instance group information """ num_instances = 2 ig = objects.InstanceGroup(hosts=[]) spec_obj = objects.RequestSpec(num_instances=num_instances, flavor=objects.Flavor(memory_mb=512, root_gb=512, ephemeral_gb=0, swap=0, vcpus=1), project_id=uuids.project_id, instance_group=ig) hs1 = mock.Mock(spec=host_manager.HostState, host='host1', uuid=uuids.cn1, cell_uuid=uuids.cell1) hs2 = mock.Mock(spec=host_manager.HostState, host='host2', uuid=uuids.cn2, cell_uuid=uuids.cell2) all_host_states = [hs1, hs2] mock_get_all_states.return_value = all_host_states mock_claim.return_value = True alloc_reqs_by_rp_uuid = { uuids.cn1: [mock.sentinel.alloc_req_cn1], uuids.cn2: [mock.sentinel.alloc_req_cn2], } # Simulate host 1 and host 2 being randomly returned first by # _get_sorted_hosts() in the two iterations for each instance in # num_instances mock_get_hosts.side_effect = ([hs2, hs1], [hs1, hs2], [hs2, hs1], [hs1, hs2]) instance_uuids = [ getattr(uuids, 'instance%d' % x) for x in range(num_instances) ] ctx = mock.Mock() self.driver._schedule(ctx, spec_obj, instance_uuids, alloc_reqs_by_rp_uuid, mock.sentinel.provider_summaries) # Check that we called _claim_resources() for both the first and second # host state claim_calls = [ mock.call(ctx.elevated.return_value, spec_obj, uuids.instance0, [mock.sentinel.alloc_req_cn2]), mock.call(ctx.elevated.return_value, spec_obj, uuids.instance1, [mock.sentinel.alloc_req_cn1]), ] mock_claim.assert_has_calls(claim_calls) # Check that _get_sorted_hosts() is called twice and that the # second time, we pass it the hosts that were returned from # _get_sorted_hosts() the first time sorted_host_calls = [ mock.call(spec_obj, all_host_states, 0), mock.call(spec_obj, [hs2, hs1], 1), ] mock_get_hosts.assert_has_calls(sorted_host_calls) # The instance group object should have both host1 and host2 in its # instance group hosts list and there should not be any "changes" to # save in the instance group object self.assertEqual(['host2', 'host1'], ig.hosts) self.assertEqual({}, ig.obj_get_changes())
def _load_request_spec(self, db_spec): self.request_spec = objects.RequestSpec._from_db_object( self._context, objects.RequestSpec(), db_spec)
def _test_resources_from_request_spec(self, flavor, expected): fake_spec = objects.RequestSpec(flavor=flavor) resources = utils.resources_from_request_spec(fake_spec) self.assertResourceRequestsEqual(expected, resources)
def test_network_requests_load(self): req_obj = objects.RequestSpec() self.assertNotIn('network_metadata', req_obj) self.assertIsInstance(req_obj.network_metadata, objects.NetworkMetadata) self.assertIn('network_metadata', req_obj)
def test_get_scheduler_hint_with_no_hints(self): spec_obj = objects.RequestSpec() self.assertEqual('bar', spec_obj.get_scheduler_hint('oops', default='bar'))
def test_unshelve_spawn_fails_cleanup_volume_connections( self, mock_terminate_volume_connections, mock_image_meta, mock_notify_instance_usage, mock_prep_block_device, mock_spawn, mock_setup_network, mock_instance_claim, mock_notify_instance_action, mock_get_bdms): """Tests error handling when a instance fails to unshelve and makes sure that volume connections are cleaned up from the host and that the host/node values are unset on the instance. """ mock_bdms = mock.Mock() mock_get_bdms.return_value = mock_bdms instance = self._create_fake_instance_obj() node = test_compute.NODENAME limits = {} filter_properties = {'limits': limits} instance.task_state = task_states.UNSHELVING instance.save() image_meta = {'properties': {'base_image_ref': uuids.image_id}} mock_image_meta.return_value = image_meta tracking = {'last_state': instance.task_state} def fake_claim(context, instance, node, allocations, limits): instance.host = self.compute.host instance.node = node requests = objects.InstancePCIRequests(requests=[]) return claims.Claim(context, instance, node, self.rt, _fake_resources(), requests, limits=limits) mock_instance_claim.side_effect = fake_claim def check_save(expected_task_state=None): if tracking['last_state'] == task_states.UNSHELVING: # This is before we've failed. self.assertEqual(task_states.SPAWNING, instance.task_state) tracking['last_state'] = instance.task_state elif tracking['last_state'] == task_states.SPAWNING: # This is after we've failed. self.assertIsNone(instance.host) self.assertIsNone(instance.node) self.assertIsNone(instance.task_state) tracking['last_state'] = instance.task_state else: self.fail('Unexpected save!') with mock.patch.object(instance, 'save') as mock_save: mock_save.side_effect = check_save self.assertRaises(test.TestingException, self.compute.unshelve_instance, self.context, instance, image=None, filter_properties=filter_properties, node=node, request_spec=objects.RequestSpec()) mock_notify_instance_action.assert_called_once_with( self.context, instance, 'fake-mini', action='unshelve', phase='start', bdms=mock_bdms) mock_notify_instance_usage.assert_called_once_with( self.context, instance, 'unshelve.start') mock_prep_block_device.assert_called_once_with( self.context, instance, mock_bdms) mock_setup_network.assert_called_once_with( self.context, instance, self.compute.host, provider_mappings=None) mock_instance_claim.assert_called_once_with(self.context, instance, test_compute.NODENAME, {}, limits) mock_spawn.assert_called_once_with( self.context, instance, test.MatchType(objects.ImageMeta), injected_files=[], admin_password=None, allocations={}, network_info=[], block_device_info='fake_bdm') mock_terminate_volume_connections.assert_called_once_with( self.context, instance, mock_bdms)
def test_image_meta_from_image_as_none(self): # just add a dumb check to have a full coverage spec = objects.RequestSpec() spec._image_meta_from_image(None) self.assertIsNone(spec.image)
def _test_group_affinity_filter_fails(self, filt_cls, policy): host = fakes.FakeHostState('host1', 'node1', {}) spec_obj = objects.RequestSpec(instance_group=objects.InstanceGroup( policies=[policy], hosts=['host2'])) self.assertFalse(filt_cls.host_passes(host, spec_obj))
def test_to_legacy_image_with_none(self, obj_to_primitive): spec = objects.RequestSpec(image=None) self.assertEqual({}, spec._to_legacy_image()) self.assertFalse(obj_to_primitive.called)
def test_with_tenant_and_az_and_traits(self, mock_getmd, mock_getnotmd): mock_getmd.side_effect = [ # Tenant filter [objects.Aggregate( uuid=uuids.agg1, metadata={'filter_tenant_id': 'owner'}), objects.Aggregate( uuid=uuids.agg2, metadata={'filter_tenant_id:12': 'owner'}), objects.Aggregate( uuid=uuids.agg3, metadata={'other_key': 'owner'})], # AZ filter [objects.Aggregate( uuid=uuids.agg4, metadata={'availability_zone': 'myaz'})], ] mock_getnotmd.side_effect = [ # isolate_aggregates filter [objects.Aggregate( uuid=uuids.agg1, metadata={'trait:CUSTOM_WINDOWS_LICENSED_TRAIT': 'required'}), objects.Aggregate( uuid=uuids.agg2, metadata={'trait:CUSTOM_WINDOWS_LICENSED_TRAIT': 'required', 'trait:CUSTOM_XYZ_TRAIT': 'required'}), objects.Aggregate( uuid=uuids.agg3, metadata={'trait:CUSTOM_XYZ_TRAIT': 'required'}), ], ] traits = set(['HW_GPU_API_DXVA', 'HW_NIC_DCB_ETS']) fake_flavor = objects.Flavor( vcpus=1, memory_mb=1024, root_gb=10, ephemeral_gb=5, swap=0, extra_specs={'trait:' + trait: 'required' for trait in traits}) fake_image = objects.ImageMeta( properties=objects.ImageMetaProps( traits_required=[])) reqspec = objects.RequestSpec(project_id='owner', availability_zone='myaz', flavor=fake_flavor, image=fake_image) request_filter.process_reqspec(self.context, reqspec) self.assertEqual( ','.join(sorted([uuids.agg1, uuids.agg2])), ','.join(sorted( reqspec.requested_destination.aggregates[0].split(',')))) self.assertEqual( ','.join(sorted([uuids.agg4])), ','.join(sorted( reqspec.requested_destination.aggregates[1].split(',')))) self.assertItemsEqual( set([uuids.agg1, uuids.agg2, uuids.agg3]), reqspec.requested_destination.forbidden_aggregates) mock_getmd.assert_has_calls([ mock.call(self.context, value='owner'), mock.call(self.context, key='availability_zone', value='myaz')]) keys = ['trait:%s' % trait for trait in traits] mock_getnotmd.assert_called_once_with( self.context, utils.ItemsMatcher(keys), 'trait:', value='required')
def test_default_requested_destination(self): req_obj = objects.RequestSpec() self.assertIsNone(req_obj.requested_destination)
def test_select_destinations_timeout_once(self, mock_select_destinations): # scenario: the scheduler service times out & recovers after failure fake_spec = objects.RequestSpec() fake_args = ['ctxt', fake_spec] self.client.select_destinations(*fake_args) mock_select_destinations.assert_has_calls([mock.call(*fake_args)] * 2)
def test_map_az_disabled(self, getmd): self.flags(query_placement_for_availability_zone=False, group='scheduler') reqspec = objects.RequestSpec(availability_zone='fooaz') request_filter.map_az_to_placement_aggregate(self.context, reqspec) getmd.assert_not_called()
def test_select_destinations(self, mock_select_destinations): fake_spec = objects.RequestSpec() self.client.select_destinations(context=self.context, spec_obj=fake_spec) mock_select_destinations.assert_called_once_with( self.context, fake_spec)
def test_map_az_no_hint(self, getmd): reqspec = objects.RequestSpec(availability_zone=None) request_filter.map_az_to_placement_aggregate(self.context, reqspec) self.assertNotIn('requested_destination', reqspec) self.assertFalse(getmd.called)
def test_from_hints(self): hints_dict = {'foo_str': '1', 'bar_list': ['2']} spec = objects.RequestSpec() spec._from_hints(hints_dict) expected = {'foo_str': ['1'], 'bar_list': ['2']} self.assertEqual(expected, spec.scheduler_hints)
def test_to_legacy_instance_with_unset_values(self): spec = objects.RequestSpec() self.assertEqual({}, spec._to_legacy_instance())
def test_from_hints_with_no_hints(self): spec = objects.RequestSpec() spec._from_hints(None) self.assertIsNone(spec.scheduler_hints)
def test_populate_group_info_missing_values(self): filt_props = {} spec = objects.RequestSpec() spec._populate_group_info(filt_props) self.assertIsNone(spec.instance_group)
def test_select_destinations_no_valid_host(self, mock_schedule): mock_schedule.return_value = [] self.assertRaises(exception.NoValidHost, self.driver.select_destinations, self.context, objects.RequestSpec(num_instances=1))