def test_find_destination_works(self): self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group') self.mox.StubOutWithMock(self.task.scheduler_client, 'select_destinations') self.mox.StubOutWithMock(self.task, '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') compute_utils.get_image_metadata(self.context, self.task.image_api, self.instance_image, self.instance).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) scheduler_utils.setup_instance_group( self.context, {}, {'ignore_hosts': [self.instance_host]}) self.task.scheduler_client.select_destinations( self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn([{ 'host': 'host1' }]) self.task._check_compatible_with_source_hypervisor("host1") self.task._call_livem_checks_on_host("host1") self.mox.ReplayAll() self.assertEqual("host1", self.task._find_destination())
def test_find_destination_retry_with_invalid_livem_checks(self): self.flags(migrate_max_retries=1) self.mox.StubOutWithMock(compute_utils, "get_image_metadata") self.mox.StubOutWithMock(scheduler_utils, "build_request_spec") self.mox.StubOutWithMock(self.task.scheduler_client, "select_destinations") self.mox.StubOutWithMock(self.task, "_check_compatible_with_source_hypervisor") self.mox.StubOutWithMock(self.task, "_call_livem_checks_on_host") compute_utils.get_image_metadata( self.context, self.task.image_api, self.instance_image, self.instance ).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) self.task.scheduler_client.select_destinations(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn( [{"host": "host1"}] ) self.task._check_compatible_with_source_hypervisor("host1") self.task._call_livem_checks_on_host("host1").AndRaise(exception.Invalid) self.task.scheduler_client.select_destinations(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn( [{"host": "host2"}] ) self.task._check_compatible_with_source_hypervisor("host2") self.task._call_livem_checks_on_host("host2") self.mox.ReplayAll() self.assertEqual("host2", self.task._find_destination())
def test_get_image_meta_with_image_id_none(self, mock_flavor_get): mock_flavor_get.return_value = objects.Flavor(extra_specs={}) self.image['properties'] = {'fake_property': 'fake_value'} inst = self.instance_obj with mock.patch.object(flavors, "extract_flavor") as mock_extract_flavor: with mock.patch.object(utils, "get_system_metadata_from_image" ) as mock_get_sys_metadata: image_meta = compute_utils.get_image_metadata( self.ctx, self.mock_image_api, None, inst) self.assertEqual(0, self.mock_image_api.get.call_count) self.assertEqual(0, mock_extract_flavor.call_count) self.assertEqual(0, mock_get_sys_metadata.call_count) self.assertNotIn('fake_property', image_meta['properties']) # Checking mock_image_api_get is called with 0 image_id # as 0 is a valid image ID image_meta = compute_utils.get_image_metadata(self.ctx, self.mock_image_api, 0, self.instance_obj) self.assertEqual(1, self.mock_image_api.get.call_count) self.assertIn('fake_property', image_meta['properties'])
def test_find_destination_retry_exceeds_max(self): self.flags(migrate_max_retries=0) self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group') self.mox.StubOutWithMock(self.task.scheduler_client, 'select_destinations') self.mox.StubOutWithMock(self.task, '_check_compatible_with_source_hypervisor') compute_utils.get_image_metadata(self.context, self.task.image_api, self.instance_image, self.instance).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) scheduler_utils.setup_instance_group( self.context, {}, {'ignore_hosts': [self.instance_host]}) self.task.scheduler_client.select_destinations(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn( [{'host': 'host1'}]) self.task._check_compatible_with_source_hypervisor("host1")\ .AndRaise(exception.DestinationHypervisorTooOld) self.mox.ReplayAll() self.assertRaises(exception.NoValidHost, self.task._find_destination)
def test_find_destination_retry_with_invalid_livem_checks(self): self.flags(migrate_max_retries=1) self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(self.task.scheduler_client, 'select_destinations') self.mox.StubOutWithMock(self.task, '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') compute_utils.get_image_metadata(self.context, self.task.image_api, self.instance_image, self.instance).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) self.task.scheduler_client.select_destinations( self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn([{ 'host': 'host1' }]) self.task._check_compatible_with_source_hypervisor("host1") self.task._call_livem_checks_on_host("host1")\ .AndRaise(exception.Invalid) self.task.scheduler_client.select_destinations( self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn([{ 'host': 'host2' }]) self.task._check_compatible_with_source_hypervisor("host2") self.task._call_livem_checks_on_host("host2") self.mox.ReplayAll() self.assertEqual("host2", self.task._find_destination())
def test_find_destination_works(self): self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group') self.mox.StubOutWithMock(self.task.scheduler_client, 'select_destinations') self.mox.StubOutWithMock(self.task, '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') compute_utils.get_image_metadata(self.context, self.task.image_api, self.instance_image, self.instance).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) scheduler_utils.setup_instance_group( self.context, {}, {'ignore_hosts': [self.instance_host]}) self.task.scheduler_client.select_destinations(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn( [{'host': 'host1'}]) self.task._check_compatible_with_source_hypervisor("host1") self.task._call_livem_checks_on_host("host1") self.mox.ReplayAll() self.assertEqual("host1", self.task._find_destination())
def _test_find_destination_retry_hypervisor_raises(self, error): self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(self.task.scheduler_client, 'select_destinations') self.mox.StubOutWithMock(self.task, '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') compute_utils.get_image_metadata(self.context, self.task.image_api, self.instance_image, self.instance).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) self.task.scheduler_client.select_destinations(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn( [{'host': 'host1'}]) self.task._check_compatible_with_source_hypervisor("host1")\ .AndRaise(error) self.task.scheduler_client.select_destinations(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn( [{'host': 'host2'}]) self.task._check_compatible_with_source_hypervisor("host2") self.task._call_livem_checks_on_host("host2") self.mox.ReplayAll() self.assertEqual("host2", self.task._find_destination())
def _test_find_destination_retry_hypervisor_raises(self, error): self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(self.task.scheduler_rpcapi, 'select_destinations') self.mox.StubOutWithMock(self.task, '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') compute_utils.get_image_metadata(self.context, self.task.image_service, self.instance_image, self.instance).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) self.task.scheduler_rpcapi.select_destinations( self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn([{ 'host': 'host1' }]) self.task._check_compatible_with_source_hypervisor("host1")\ .AndRaise(error) self.task.scheduler_rpcapi.select_destinations( self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn([{ 'host': 'host2' }]) self.task._check_compatible_with_source_hypervisor("host2") self.task._call_livem_checks_on_host("host2") self.mox.ReplayAll() self.assertEqual("host2", self.task._find_destination())
def test_get_image_meta_with_image_id_none(self, mock_flavor_get): mock_flavor_get.return_value = objects.Flavor(extra_specs={}) self.image['properties'] = {'fake_property': 'fake_value'} inst = self.instance_obj with mock.patch.object(flavors, "extract_flavor") as mock_extract_flavor: with mock.patch.object( utils, "get_system_metadata_from_image") as mock_get_sys_metadata: image_meta = compute_utils.get_image_metadata( self.ctx, self.mock_image_api, None, inst) self.assertEqual(0, self.mock_image_api.get.call_count) self.assertEqual(0, mock_extract_flavor.call_count) self.assertEqual(0, mock_get_sys_metadata.call_count) self.assertNotIn('fake_property', image_meta['properties']) # Checking mock_image_api_get is called with 0 image_id # as 0 is a valid image ID image_meta = compute_utils.get_image_metadata(self.ctx, self.mock_image_api, 0, self.instance_obj) self.assertEqual(1, self.mock_image_api.get.call_count) self.assertIn('fake_property', image_meta['properties'])
def test_find_destination_retry_exceeds_max(self): self.flags(migrate_max_retries=0) self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group') self.mox.StubOutWithMock(self.task.scheduler_client, 'select_destinations') self.mox.StubOutWithMock(self.task, '_check_compatible_with_source_hypervisor') compute_utils.get_image_metadata(self.context, self.task.image_api, self.instance_image, self.instance).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) scheduler_utils.setup_instance_group( self.context, {}, {'ignore_hosts': [self.instance_host]}) self.task.scheduler_client.select_destinations( self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn([{ 'host': 'host1' }]) self.task._check_compatible_with_source_hypervisor("host1")\ .AndRaise(exception.DestinationHypervisorTooOld) self.mox.ReplayAll() self.assertRaises(exception.NoValidHost, self.task._find_destination)
def test_find_destination_retry_with_invalid_livem_checks(self): self.flags(migrate_max_retries=1) self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(self.task.scheduler_rpcapi, 'select_destinations') self.mox.StubOutWithMock(self.task, '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') compute_utils.get_image_metadata(self.context, self.task.image_service, self.instance_image, self.instance).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) self.task.scheduler_rpcapi.select_destinations(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn( [{'host': 'host1'}]) self.task._check_compatible_with_source_hypervisor("host1") self.task._call_livem_checks_on_host("host1")\ .AndRaise(exception.Invalid) self.task.scheduler_rpcapi.select_destinations(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn( [{'host': 'host2'}]) self.task._check_compatible_with_source_hypervisor("host2") self.task._call_livem_checks_on_host("host2") self.mox.ReplayAll() self.assertEqual("host2", self.task._find_destination())
def test_find_destination_retry_with_invalid_livem_checks(self): self.flags(migrate_max_retries=1) self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') self.mox.StubOutWithMock(flavors, 'extract_flavor') self.mox.StubOutWithMock(self.task.scheduler_rpcapi, 'select_hosts') self.mox.StubOutWithMock(self.task, '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') compute_utils.get_image_metadata(self.context, self.task.image_service, self.instance_image, self.instance).AndReturn("image") flavors.extract_flavor(self.instance).AndReturn("inst_type") self.task.scheduler_rpcapi.select_hosts(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn( ["host1"]) self.task._check_compatible_with_source_hypervisor("host1") self.task._call_livem_checks_on_host("host1")\ .AndRaise(exception.Invalid) self.task.scheduler_rpcapi.select_hosts(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn( ["host2"]) self.task._check_compatible_with_source_hypervisor("host2") self.task._call_livem_checks_on_host("host2") self.mox.ReplayAll() self.assertEqual("host2", self.task._find_destination())
def test_find_destination_when_runs_out_of_hosts(self): self.mox.StubOutWithMock(compute_utils, "get_image_metadata") self.mox.StubOutWithMock(scheduler_utils, "build_request_spec") self.mox.StubOutWithMock(self.task.scheduler_client, "select_destinations") compute_utils.get_image_metadata( self.context, self.task.image_api, self.instance_image, self.instance ).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) self.task.scheduler_client.select_destinations(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndRaise( exception.NoValidHost(reason="") ) self.mox.ReplayAll() self.assertRaises(exception.NoValidHost, self.task._find_destination)
def test_find_destination_retry_exceeds_max(self): self.flags(migrate_max_retries=0) self.mox.StubOutWithMock(compute_utils, "get_image_metadata") self.mox.StubOutWithMock(scheduler_utils, "build_request_spec") self.mox.StubOutWithMock(self.task.scheduler_rpcapi, "select_hosts") self.mox.StubOutWithMock(self.task, "_check_compatible_with_source_hypervisor") compute_utils.get_image_metadata( self.context, self.task.image_service, self.instance_image, self.instance ).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) self.task.scheduler_rpcapi.select_hosts(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(["host1"]) self.task._check_compatible_with_source_hypervisor("host1").AndRaise(exception.DestinationHypervisorTooOld) self.mox.ReplayAll() self.assertRaises(exception.NoValidHost, self.task._find_destination)
def _find_destination(self): #TODO(johngarbutt) this retry loop should be shared attempted_hosts = [self.source] image = None if self.instance.image_ref: image = compute_utils.get_image_metadata(self.context, self.image_service, self.instance.image_ref, self.instance) instance_type = flavors.extract_flavor(self.instance) host = None while host is None: self._check_not_over_max_retries(attempted_hosts) host = self._get_candidate_destination(image, instance_type, attempted_hosts) try: self._check_compatible_with_source_hypervisor(host) self._call_livem_checks_on_host(host) except exception.Invalid as e: LOG.debug(_("Skipping host: %(host)s because: %(e)s") % {"host": host, "e": e}) attempted_hosts.append(host) host = None return host
def _cold_migrate(self, context, instance, flavor, filter_properties, reservations): image_ref = instance.image_ref image = compute_utils.get_image_metadata(context, self.image_service, image_ref, instance) request_spec = scheduler_utils.build_request_spec(context, image, [instance], instance_type=flavor) try: hosts = self.scheduler_rpcapi.select_destinations( context, request_spec, filter_properties) host_state = hosts[0] except exception.NoValidHost as ex: vm_state = instance['vm_state'] if not vm_state: vm_state = vm_states.ACTIVE updates = {'vm_state': vm_state, 'task_state': None} self._set_vm_state_and_notify(context, 'migrate_server', updates, ex, request_spec) if reservations: self.quotas.rollback(context, reservations) LOG.warning(_("No valid host found for cold migrate"), instance=instance) return try: scheduler_utils.populate_filter_properties(filter_properties, host_state) # context is not serializable filter_properties.pop('context', None) # TODO(timello): originally, instance_type in request_spec # on compute.api.resize does not have 'extra_specs', so we # remove it for now to keep tests backward compatibility. request_spec['instance_type'].pop('extra_specs') (host, node) = (host_state['host'], host_state['nodename']) self.compute_rpcapi.prep_resize( context, image, instance, flavor, host, reservations, request_spec=request_spec, filter_properties=filter_properties, node=node) except Exception as ex: with excutils.save_and_reraise_exception(): updates = { 'vm_state': instance['vm_state'], 'task_state': None } self._set_vm_state_and_notify(context, 'migrate_server', updates, ex, request_spec) if reservations: self.quotas.rollback(context, reservations)
def _find_destination(self): #TODO(johngarbutt) this retry loop should be shared attempted_hosts = [self.source] image = None if self.instance.image_ref: image = compute_utils.get_image_metadata(self.context, self.image_service, self.instance.image_ref, self.instance) instance_type = flavors.extract_flavor(self.instance) host = None while host is None: self._check_not_over_max_retries(attempted_hosts) host = self._get_candidate_destination(image, instance_type, attempted_hosts) try: self._check_compatible_with_source_hypervisor(host) self._call_livem_checks_on_host(host) except exception.Invalid as e: LOG.debug( _("Skipping host: %(host)s because: %(e)s") % { "host": host, "e": e }) attempted_hosts.append(host) host = None return host
def test_find_destination_when_runs_out_of_hosts(self): self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(self.task.scheduler_rpcapi, 'select_destinations') compute_utils.get_image_metadata(self.context, self.task.image_service, self.instance_image, self.instance).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) self.task.scheduler_rpcapi.select_destinations( self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndRaise(exception.NoValidHost(reason="")) self.mox.ReplayAll() self.assertRaises(exception.NoValidHost, self.task._find_destination)
def _find_destination(self): #TODO(johngarbutt) this retry loop should be shared attempted_hosts = [self.source] image = None if self.instance.image_ref: image = compute_utils.get_image_metadata(self.context, self.image_service, self.instance.image_ref, self.instance) request_spec = scheduler_utils.build_request_spec( self.context, image, [self.instance]) host = None while host is None: self._check_not_over_max_retries(attempted_hosts) filter_properties = {'ignore_hosts': attempted_hosts} host = self.scheduler_rpcapi.select_destinations( self.context, request_spec, filter_properties)[0]['host'] try: self._check_compatible_with_source_hypervisor(host) self._call_livem_checks_on_host(host) except exception.Invalid as e: LOG.debug( _("Skipping host: %(host)s because: %(e)s") % { "host": host, "e": e }) attempted_hosts.append(host) host = None return host
def test_get_image_meta(self, mock_get): mock_get.return_value = objects.Flavor(extra_specs={}) image_meta = compute_utils.get_image_metadata( self.ctx, self.mock_image_api, 'fake-image', self.instance_obj) self.image['properties'] = 'DONTCARE' self.assertThat(self.image, matchers.DictMatches(image_meta))
def _find_destination(self): # TODO(johngarbutt) this retry loop should be shared attempted_hosts = [self.source] image = None if self.instance.image_ref: image = compute_utils.get_image_metadata(self.context, self.image_api, self.instance.image_ref, self.instance) request_spec = scheduler_utils.build_request_spec(self.context, image, [self.instance]) host = None while host is None: self._check_not_over_max_retries(attempted_hosts) filter_properties = {'ignore_hosts': attempted_hosts} scheduler_utils.setup_instance_group(self.context, request_spec, filter_properties) host = self.scheduler_client.select_destinations(self.context, request_spec, filter_properties)[0]['host'] try: self._check_compatible_with_source_hypervisor(host) self._call_livem_checks_on_host(host) except exception.Invalid as e: LOG.debug("Skipping host: %(host)s because: %(e)s", {"host": host, "e": e}) attempted_hosts.append(host) host = None return host
def _cold_migrate(self, context, instance, flavor, filter_properties, reservations): image_ref = instance.image_ref image = compute_utils.get_image_metadata( context, self.image_api, image_ref, instance) request_spec = scheduler_utils.build_request_spec( context, image, [instance], instance_type=flavor) quotas = objects.Quotas.from_reservations(context, reservations, instance=instance) scheduler_utils.setup_instance_group(context, request_spec, filter_properties) try: scheduler_utils.populate_retry(filter_properties, instance['uuid']) hosts = self.scheduler_client.select_destinations( context, request_spec, filter_properties) host_state = hosts[0] except exception.NoValidHost as ex: vm_state = instance['vm_state'] if not vm_state: vm_state = vm_states.ACTIVE updates = {'vm_state': vm_state, 'task_state': None} self._set_vm_state_and_notify(context, 'migrate_server', updates, ex, request_spec) quotas.rollback() # if the flavor IDs match, it's migrate; otherwise resize if flavor['id'] == instance['instance_type_id']: msg = _("No valid host found for cold migrate") else: msg = _("No valid host found for resize") raise exception.NoValidHost(reason=msg) try: scheduler_utils.populate_filter_properties(filter_properties, host_state) # context is not serializable filter_properties.pop('context', None) # TODO(timello): originally, instance_type in request_spec # on compute.api.resize does not have 'extra_specs', so we # remove it for now to keep tests backward compatibility. request_spec['instance_type'].pop('extra_specs', None) (host, node) = (host_state['host'], host_state['nodename']) self.compute_rpcapi.prep_resize( context, image, instance, flavor, host, reservations, request_spec=request_spec, filter_properties=filter_properties, node=node) except Exception as ex: with excutils.save_and_reraise_exception(): updates = {'vm_state': instance['vm_state'], 'task_state': None} self._set_vm_state_and_notify(context, 'migrate_server', updates, ex, request_spec) quotas.rollback()
def test_find_destination_when_runs_out_of_hosts(self): self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') self.mox.StubOutWithMock(flavors, 'extract_flavor') self.mox.StubOutWithMock(self.task.scheduler_rpcapi, 'select_hosts') self.mox.StubOutWithMock(self.task, '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') compute_utils.get_image_metadata(self.context, self.task.image_service, self.instance_image, self.instance).AndReturn("image") flavors.extract_flavor(self.instance).AndReturn("inst_type") self.task.scheduler_rpcapi.select_hosts(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndRaise(exception.NoValidHost(reason="")) self.mox.ReplayAll() self.assertRaises(exception.NoValidHost, self.task._find_destination)
def test_find_destination_works(self): self.mox.StubOutWithMock(compute_utils, "get_image_metadata") self.mox.StubOutWithMock(scheduler_utils, "build_request_spec") self.mox.StubOutWithMock(self.task.scheduler_rpcapi, "select_hosts") self.mox.StubOutWithMock(self.task, "_check_compatible_with_source_hypervisor") self.mox.StubOutWithMock(self.task, "_call_livem_checks_on_host") compute_utils.get_image_metadata( self.context, self.task.image_service, self.instance_image, self.instance ).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) self.task.scheduler_rpcapi.select_hosts(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(["host1"]) self.task._check_compatible_with_source_hypervisor("host1") self.task._call_livem_checks_on_host("host1") self.mox.ReplayAll() self.assertEqual("host1", self.task._find_destination())
def test_get_image_meta_with_image_id_none(self): self.image["properties"] = {"fake_property": "fake_value"} with mock.patch.object(flavors, "extract_flavor") as mock_extract_flavor: with mock.patch.object(utils, "get_system_metadata_from_image") as mock_get_sys_metadata: image_meta = compute_utils.get_image_metadata(self.ctx, self.mock_image_api, None, self.instance_obj) self.assertEqual(0, self.mock_image_api.get.call_count) self.assertEqual(0, mock_extract_flavor.call_count) self.assertEqual(0, mock_get_sys_metadata.call_count) self.assertNotIn("fake_property", image_meta["properties"]) # Checking mock_image_api_get is called with 0 image_id # as 0 is a valid image ID image_meta = compute_utils.get_image_metadata(self.ctx, self.mock_image_api, 0, self.instance_obj) self.assertEqual(1, self.mock_image_api.get.call_count) self.assertIn("fake_property", image_meta["properties"])
def test_get_image_meta(self): image_meta = compute_utils.get_image_metadata(self.ctx, self.image_service, 'fake-image', self.instance_obj) self.image['properties'] = 'DONTCARE' self.assertThat(self.image, matchers.DictMatches(image_meta))
def _cold_migrate(self, context, instance, flavor, filter_properties, reservations, clean_shutdown): image_ref = instance.image_ref image = compute_utils.get_image_metadata(context, self.image_api, image_ref, instance) request_spec = scheduler_utils.build_request_spec(context, image, [instance], instance_type=flavor) quotas = objects.Quotas.from_reservations(context, reservations, instance=instance) try: scheduler_utils.setup_instance_group(context, request_spec, filter_properties) scheduler_utils.populate_retry(filter_properties, instance["uuid"]) hosts = self.scheduler_client.select_destinations(context, request_spec, filter_properties) host_state = hosts[0] except exception.NoValidHost as ex: vm_state = instance.vm_state if not vm_state: vm_state = vm_states.ACTIVE updates = {"vm_state": vm_state, "task_state": None} self._set_vm_state_and_notify(context, instance.uuid, "migrate_server", updates, ex, request_spec) quotas.rollback() # if the flavor IDs match, it's migrate; otherwise resize if flavor["id"] == instance["instance_type_id"]: msg = _("No valid host found for cold migrate") else: msg = _("No valid host found for resize") raise exception.NoValidHost(reason=msg) except exception.UnsupportedPolicyException as ex: with excutils.save_and_reraise_exception(): vm_state = instance.vm_state if not vm_state: vm_state = vm_states.ACTIVE updates = {"vm_state": vm_state, "task_state": None} self._set_vm_state_and_notify(context, instance.uuid, "migrate_server", updates, ex, request_spec) quotas.rollback() try: scheduler_utils.populate_filter_properties(filter_properties, host_state) # context is not serializable filter_properties.pop("context", None) (host, node) = (host_state["host"], host_state["nodename"]) self.compute_rpcapi.prep_resize( context, image, instance, flavor, host, reservations, request_spec=request_spec, filter_properties=filter_properties, node=node, clean_shutdown=clean_shutdown, ) except Exception as ex: with excutils.save_and_reraise_exception(): updates = {"vm_state": instance.vm_state, "task_state": None} self._set_vm_state_and_notify(context, instance.uuid, "migrate_server", updates, ex, request_spec) quotas.rollback()
def test_find_destination_when_runs_out_of_hosts(self): self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') self.mox.StubOutWithMock(flavors, 'extract_flavor') self.mox.StubOutWithMock(self.task.scheduler_rpcapi, 'select_hosts') self.mox.StubOutWithMock(self.task, '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') compute_utils.get_image_metadata(self.context, self.task.image_service, self.instance_image, self.instance).AndReturn("image") flavors.extract_flavor(self.instance).AndReturn("inst_type") self.task.scheduler_rpcapi.select_hosts( self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndRaise(exception.NoValidHost(reason="")) self.mox.ReplayAll() self.assertRaises(exception.NoValidHost, self.task._find_destination)
def test_get_image_meta_no_image_system_meta(self): for k in self.instance["system_metadata"].keys(): if k.startswith("image_"): del self.instance["system_metadata"][k] image_meta = compute_utils.get_image_metadata(self.ctx, self.image_service, "fake-image", self.instance_obj) self.image["properties"] = "DONTCARE" self.assertThat(self.image, matchers.DictMatches(image_meta))
def _cold_migrate(self, context, instance, flavor, filter_properties, reservations): image_ref = instance.image_ref image = compute_utils.get_image_metadata( context, self.image_api, image_ref, instance) request_spec = scheduler_utils.build_request_spec( context, image, [instance], instance_type=flavor) quotas = objects.Quotas.from_reservations(context, reservations, instance=instance) try: scheduler_utils.populate_retry(filter_properties, instance['uuid']) hosts = self.scheduler_client.select_destinations( context, request_spec, filter_properties) host_state = hosts[0] except exception.NoValidHost as ex: vm_state = instance['vm_state'] if not vm_state: vm_state = vm_states.ACTIVE updates = {'vm_state': vm_state, 'task_state': None} self._set_vm_state_and_notify(context, 'migrate_server', updates, ex, request_spec) quotas.rollback() # if the flavor IDs match, it's migrate; otherwise resize if flavor['id'] == instance['instance_type_id']: msg = _("No valid host found for cold migrate") else: msg = _("No valid host found for resize") raise exception.NoValidHost(reason=msg) try: scheduler_utils.populate_filter_properties(filter_properties, host_state) # context is not serializable filter_properties.pop('context', None) # TODO(timello): originally, instance_type in request_spec # on compute.api.resize does not have 'extra_specs', so we # remove it for now to keep tests backward compatibility. request_spec['instance_type'].pop('extra_specs') (host, node) = (host_state['host'], host_state['nodename']) self.compute_rpcapi.prep_resize( context, image, instance, flavor, host, reservations, request_spec=request_spec, filter_properties=filter_properties, node=node) except Exception as ex: with excutils.save_and_reraise_exception(): updates = {'vm_state': instance['vm_state'], 'task_state': None} self._set_vm_state_and_notify(context, 'migrate_server', updates, ex, request_spec) quotas.rollback()
def test_find_destination_works(self): self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') self.mox.StubOutWithMock(flavors, 'extract_flavor') self.mox.StubOutWithMock(self.task.scheduler_rpcapi, 'select_hosts') self.mox.StubOutWithMock(self.task, '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') compute_utils.get_image_metadata(self.context, self.task.image_service, self.instance_image, self.instance).AndReturn("image") flavors.extract_flavor(self.instance).AndReturn("inst_type") self.task.scheduler_rpcapi.select_hosts(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(["host1"]) self.task._check_compatible_with_source_hypervisor("host1") self.task._call_livem_checks_on_host("host1") self.mox.ReplayAll() self.assertEqual("host1", self.task._find_destination())
def _test_get_image_meta_exception(self, error): self.mock_image_api.get.side_effect = error image_meta = compute_utils.get_image_metadata(self.ctx, self.mock_image_api, "fake-image", self.instance_obj) self.image["properties"] = "DONTCARE" # NOTE(danms): The trip through system_metadata will stringify things for key in self.image: self.image[key] = str(self.image[key]) self.assertThat(self.image, matchers.DictMatches(image_meta))
def test_get_image_meta_no_image_system_meta(self): for k in self.instance['system_metadata'].keys(): if k.startswith('image_'): del self.instance['system_metadata'][k] image_meta = compute_utils.get_image_metadata( self.ctx, self.image_service, 'fake-image', self.instance_obj) self.image['properties'] = 'DONTCARE' self.assertThat(self.image, matchers.DictMatches(image_meta))
def test_get_image_meta_no_image(self): def fake_show(ctx, image_id): raise exception.ImageNotFound(image_id='fake-image') self.stubs.Set(self.image_service, 'show', fake_show) image_meta = compute_utils.get_image_metadata( self.ctx, self.image_service, 'fake-image', self.instance_obj) self.image['properties'] = 'DONTCARE' self.assertThat(self.image, matchers.DictMatches(image_meta))
def _test_get_image_meta_exception(self, error): self.mock_image_api.get.side_effect = error image_meta = compute_utils.get_image_metadata( self.ctx, self.mock_image_api, 'fake-image', self.instance_obj) self.image['properties'] = 'DONTCARE' # NOTE(danms): The trip through system_metadata will stringify things for key in self.image: self.image[key] = str(self.image[key]) self.assertThat(self.image, matchers.DictMatches(image_meta))
def test_find_destination_retry_exceeds_max(self): self.flags(migrate_max_retries=0) self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') self.mox.StubOutWithMock(flavors, 'extract_flavor') self.mox.StubOutWithMock(self.task.scheduler_rpcapi, 'select_hosts') self.mox.StubOutWithMock(self.task, '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') compute_utils.get_image_metadata(self.context, self.task.image_service, self.instance_image, self.instance).AndReturn("image") flavors.extract_flavor(self.instance).AndReturn("inst_type") self.task.scheduler_rpcapi.select_hosts(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(["host1"]) self.task._check_compatible_with_source_hypervisor("host1")\ .AndRaise(exception.DestinationHypervisorTooOld) self.mox.ReplayAll() self.assertRaises(exception.NoValidHost, self.task._find_destination)
def test_get_image_meta_no_image_system_meta(self): for k in self.instance_obj.system_metadata.keys(): if k.startswith('image_'): del self.instance_obj.system_metadata[k] with mock.patch('nova.objects.Flavor.get_by_flavor_id') as get: get.return_value = objects.Flavor(extra_specs={}) image_meta = compute_utils.get_image_metadata( self.ctx, self.mock_image_api, 'fake-image', self.instance_obj) self.image['properties'] = 'DONTCARE' self.assertThat(self.image, matchers.DictMatches(image_meta))
def test_get_image_meta_no_image(self): e = exception.ImageNotFound(image_id='fake-image') self.mock_image_api.get.side_effect = e image_meta = compute_utils.get_image_metadata( self.ctx, self.mock_image_api, 'fake-image', self.instance_obj) self.image['properties'] = 'DONTCARE' # NOTE(danms): The trip through system_metadata will stringify things for key in self.image: self.image[key] = str(self.image[key]) self.assertThat(self.image, matchers.DictMatches(image_meta))
def test_get_image_meta_no_image_no_image_system_meta(self): e = exception.ImageNotFound(image_id="fake-image") self.mock_image_api.get.side_effect = e for k in self.instance["system_metadata"].keys(): if k.startswith("image_"): del self.instance["system_metadata"][k] image_meta = compute_utils.get_image_metadata(self.ctx, self.mock_image_api, "fake-image", self.instance_obj) expected = {"properties": "DONTCARE"} self.assertThat(expected, matchers.DictMatches(image_meta))
def _cold_migrate(self, context, instance, flavor, filter_properties, reservations): image_ref = instance.image_ref image = compute_utils.get_image_metadata( context, self.image_service, image_ref, instance) request_spec = scheduler_utils.build_request_spec( context, image, [instance], instance_type=flavor) try: hosts = self.scheduler_rpcapi.select_destinations( context, request_spec, filter_properties) host_state = hosts[0] except exception.NoValidHost as ex: vm_state = instance['vm_state'] if not vm_state: vm_state = vm_states.ACTIVE updates = {'vm_state': vm_state, 'task_state': None} self._set_vm_state_and_notify(context, 'migrate_server', updates, ex, request_spec) if reservations: self.quotas.rollback(context, reservations) LOG.warning(_("No valid host found for cold migrate"), instance=instance) return try: scheduler_utils.populate_filter_properties(filter_properties, host_state) # context is not serializable filter_properties.pop('context', None) # TODO(timello): originally, instance_type in request_spec # on compute.api.resize does not have 'extra_specs', so we # remove it for now to keep tests backward compatibility. request_spec['instance_type'].pop('extra_specs') (host, node) = (host_state['host'], host_state['nodename']) self.compute_rpcapi.prep_resize( context, image, instance, flavor, host, reservations, request_spec=request_spec, filter_properties=filter_properties, node=node) except Exception as ex: with excutils.save_and_reraise_exception(): updates = {'vm_state': vm_states.ERROR, 'task_state': None} self._set_vm_state_and_notify(context, 'migrate_server', updates, ex, request_spec) if reservations: self.quotas.rollback(context, reservations)
def test_get_image_meta_no_image(self): def fake_show(ctx, image_id): raise exception.ImageNotFound(image_id='fake-image') self.stubs.Set(self.image_service, 'show', fake_show) image_meta = compute_utils.get_image_metadata(self.ctx, self.image_service, 'fake-image', self.instance_obj) self.image['properties'] = 'DONTCARE' self.assertThat(self.image, matchers.DictMatches(image_meta))
def test_get_image_meta_no_image(self): def fake_show(ctx, image_id): raise exception.ImageNotFound(image_id="fake-image") self.stubs.Set(self.image_service, "show", fake_show) image_meta = compute_utils.get_image_metadata(self.ctx, self.image_service, "fake-image", self.instance_obj) self.image["properties"] = "DONTCARE" # NOTE(danms): The trip through system_metadata will stringify things for key in self.image: self.image[key] = str(self.image[key]) self.assertThat(self.image, matchers.DictMatches(image_meta))
def test_get_image_meta_no_image_no_image_system_meta(self): e = exception.ImageNotFound(image_id='fake-image') self.mock_image_api.get.side_effect = e for k in self.instance['system_metadata'].keys(): if k.startswith('image_'): del self.instance['system_metadata'][k] image_meta = compute_utils.get_image_metadata( self.ctx, self.mock_image_api, 'fake-image', self.instance_obj) expected = {'properties': 'DONTCARE'} self.assertThat(expected, matchers.DictMatches(image_meta))
def test_get_image_meta_no_image(self): def fake_show(ctx, image_id): raise exception.ImageNotFound(image_id='fake-image') self.stubs.Set(self.image_service, 'show', fake_show) image_meta = compute_utils.get_image_metadata( self.ctx, self.image_service, 'fake-image', self.instance_obj) self.image['properties'] = 'DONTCARE' # NOTE(danms): The trip through system_metadata will stringify things for key in self.image: self.image[key] = str(self.image[key]) self.assertThat(self.image, matchers.DictMatches(image_meta))
def test_get_image_meta_no_image_no_image_system_meta(self): def fake_show(ctx, image_id): raise exception.ImageNotFound(image_id="fake-image") self.stubs.Set(self.image_service, "show", fake_show) for k in self.instance["system_metadata"].keys(): if k.startswith("image_"): del self.instance["system_metadata"][k] image_meta = compute_utils.get_image_metadata(self.ctx, self.image_service, "fake-image", self.instance_obj) expected = {"properties": "DONTCARE"} self.assertThat(expected, matchers.DictMatches(image_meta))
def _cold_migrate(self, context, instance, flavor, filter_properties, reservations): image_ref = instance.image_ref image = compute_utils.get_image_metadata(context, self.image_api, image_ref, instance) request_spec = scheduler_utils.build_request_spec(context, image, [instance], instance_type=flavor) quotas = quotas_obj.Quotas.from_reservations(context, reservations, instance=instance) try: scheduler_utils.populate_retry(filter_properties, instance["uuid"]) hosts = self.scheduler_rpcapi.select_destinations(context, request_spec, filter_properties) host_state = hosts[0] except exception.NoValidHost as ex: vm_state = instance["vm_state"] if not vm_state: vm_state = vm_states.ACTIVE updates = {"vm_state": vm_state, "task_state": None} self._set_vm_state_and_notify(context, "migrate_server", updates, ex, request_spec) quotas.rollback() msg = _("No valid host found for cold migrate") raise exception.NoValidHost(reason=msg) try: scheduler_utils.populate_filter_properties(filter_properties, host_state) # context is not serializable filter_properties.pop("context", None) # TODO(timello): originally, instance_type in request_spec # on compute.api.resize does not have 'extra_specs', so we # remove it for now to keep tests backward compatibility. request_spec["instance_type"].pop("extra_specs") (host, node) = (host_state["host"], host_state["nodename"]) self.compute_rpcapi.prep_resize( context, image, instance, flavor, host, reservations, request_spec=request_spec, filter_properties=filter_properties, node=node, ) except Exception as ex: with excutils.save_and_reraise_exception(): updates = {"vm_state": instance["vm_state"], "task_state": None} self._set_vm_state_and_notify(context, "migrate_server", updates, ex, request_spec) quotas.rollback()
def test_get_image_meta_no_image_no_image_system_meta(self): e = exception.ImageNotFound(image_id='fake-image') self.mock_image_api.get.side_effect = e for k in self.instance_obj.system_metadata.keys(): if k.startswith('image_'): del self.instance_obj.system_metadata[k] with mock.patch('nova.objects.Flavor.get_by_flavor_id') as get: get.return_value = objects.Flavor(extra_specs={}) image_meta = compute_utils.get_image_metadata( self.ctx, self.mock_image_api, 'fake-image', self.instance_obj) expected = {'properties': 'DONTCARE'} self.assertThat(expected, matchers.DictMatches(image_meta))
def test_get_image_meta_no_image_no_image_system_meta(self): def fake_show(ctx, image_id): raise exception.ImageNotFound(image_id='fake-image') self.stubs.Set(self.image_service, 'show', fake_show) for k in self.instance['system_metadata'].keys(): if k.startswith('image_'): del self.instance['system_metadata'][k] image_meta = compute_utils.get_image_metadata( self.ctx, self.image_service, 'fake-image', self.instance_obj) expected = {'properties': 'DONTCARE'} self.assertThat(expected, matchers.DictMatches(image_meta))
def snapshot(self, context, instance, image_id, update_task_state): """Snapshots the specified instance. :param context: security context :param instance: Instance object as returned by DB layer. :param image_id: Reference to a pre-created image that will hold the snapshot. :param update_task_state: Function reference that allows for updates to the instance task state. """ snapshot_start = time.time() # get current image info glance_service, old_image_id = glance.get_remote_image_service( context, instance['image_ref']) image_meta = compute_utils.get_image_metadata(context, glance_service, old_image_id, instance) # build updated snapshot metadata snapshot_meta = glance_service.show(context, image_id) new_snapshot_meta = { 'is_public': False, 'name': snapshot_meta['name'], 'status': 'active', 'properties': { 'image_location': 'snapshot', 'image_state': 'available', 'owner_id': instance['project_id'] }, 'disk_format': image_meta['disk_format'], 'container_format': image_meta['container_format'] } # disk capture and glance upload self._powervm.capture_image(context, instance, image_id, new_snapshot_meta, update_task_state) snapshot_time = time.time() - snapshot_start inst_name = instance['name'] LOG.info(_("%(inst_name)s captured in %(snapshot_time)s seconds"), { 'inst_name': inst_name, 'snapshot_time': snapshot_time })
def _cloudlet_create_image(self, context, instance, name, image_type, extra_properties=None): """Create new image entry in the image service. This new image will be reserved for the compute manager to upload a snapshot or backup. :param context: security context :param instance: nova.db.sqlalchemy.models.Instance :param name: string for name of the snapshot :param image_type: snapshot | backup :param extra_properties: dict of extra image properties to include """ if extra_properties is None: extra_properties = {} instance_uuid = instance['uuid'] properties = { 'instance_uuid': instance_uuid, 'user_id': str(context.user_id), 'image_type': image_type, } image_ref = instance.image_ref if hasattr(self.nova_api, "image_service"): # icehouse image_api_ref = self.nova_api.image_service else: # kilo image_api_ref = self.image_api sent_meta = compute_utils.get_image_metadata(context, image_api_ref, image_ref, instance) sent_meta['name'] = name sent_meta['is_public'] = False # The properties set up above and in extra_properties have precedence properties.update(extra_properties or {}) sent_meta['properties'].update(properties) return image_api_ref.create(context, sent_meta)
def _cold_migrate(self, context, instance, flavor, filter_properties, reservations, clean_shutdown): image_ref = instance.image_ref image = compute_utils.get_image_metadata(context, self.image_api, image_ref, instance) request_spec = scheduler_utils.build_request_spec(context, image, [instance], instance_type=flavor) quotas = objects.Quotas.from_reservations(context, reservations, instance=instance) try: scheduler_utils.setup_instance_group(context, request_spec, filter_properties) scheduler_utils.populate_retry(filter_properties, instance['uuid']) hosts = self.scheduler_client.select_destinations( context, request_spec, filter_properties) host_state = hosts[0] except exception.NoValidHost as ex: vm_state = instance.vm_state if not vm_state: vm_state = vm_states.ACTIVE updates = {'vm_state': vm_state, 'task_state': None} self._set_vm_state_and_notify(context, instance.uuid, 'migrate_server', updates, ex, request_spec) quotas.rollback() # if the flavor IDs match, it's migrate; otherwise resize if flavor['id'] == instance['instance_type_id']: msg = _("No valid host found for cold migrate") else: msg = _("No valid host found for resize") raise exception.NoValidHost(reason=msg) except exception.UnsupportedPolicyException as ex: with excutils.save_and_reraise_exception(): vm_state = instance.vm_state if not vm_state: vm_state = vm_states.ACTIVE updates = {'vm_state': vm_state, 'task_state': None} self._set_vm_state_and_notify(context, instance.uuid, 'migrate_server', updates, ex, request_spec) quotas.rollback() try: scheduler_utils.populate_filter_properties(filter_properties, host_state) # context is not serializable filter_properties.pop('context', None) (host, node) = (host_state['host'], host_state['nodename']) self.compute_rpcapi.prep_resize( context, image, instance, flavor, host, reservations, request_spec=request_spec, filter_properties=filter_properties, node=node, clean_shutdown=clean_shutdown) except Exception as ex: with excutils.save_and_reraise_exception(): updates = {'vm_state': instance.vm_state, 'task_state': None} self._set_vm_state_and_notify(context, instance.uuid, 'migrate_server', updates, ex, request_spec) quotas.rollback()