def test_blank_attach_fail_volume(self): no_blank_volume = self.blank_bdm_dict.copy() no_blank_volume['volume_id'] = None test_bdm = self.driver_classes['blank']( fake_block_device.fake_bdm_object( self.context, no_blank_volume)) instance = fake_instance.fake_instance_obj(mock.sentinel.ctx, **{'uuid': uuids.uuid}) volume = {'id': 'fake-volume-id-2', 'display_name': '%s-blank-vol' % uuids.uuid} with test.nested( mock.patch.object(self.volume_api, 'create', return_value=volume), mock.patch.object(self.volume_api, 'delete'), ) as (vol_create, vol_delete): wait_func = mock.MagicMock() mock_exception = exception.VolumeNotCreated(volume_id=volume['id'], seconds=1, attempts=1, volume_status='error') wait_func.side_effect = mock_exception self.assertRaises(exception.VolumeNotCreated, test_bdm.attach, context=self.context, instance=instance, volume_api=self.volume_api, virt_driver=self.virt_driver, wait_func=wait_func) vol_create.assert_called_once_with( self.context, test_bdm.volume_size, '%s-blank-vol' % uuids.uuid, '', availability_zone=None) vol_delete.assert_called_once_with( self.context, volume['id'])
def test_blank_attach_volume(self): no_blank_volume = self.blank_bdm_dict.copy() no_blank_volume['volume_id'] = None test_bdm = self.driver_classes['blank']( fake_block_device.fake_bdm_object( self.context, no_blank_volume)) instance = fake_instance.fake_instance_obj(mock.sentinel.ctx, **{'uuid': uuids.uuid}) volume_class = self.driver_classes['volume'] volume = {'id': 'fake-volume-id-2', 'display_name': '%s-blank-vol' % uuids.uuid} with test.nested( mock.patch.object(self.volume_api, 'create', return_value=volume), mock.patch.object(volume_class, 'attach') ) as (vol_create, vol_attach): test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) vol_create.assert_called_once_with( self.context, test_bdm.volume_size, '%s-blank-vol' % uuids.uuid, '', availability_zone=None) vol_attach.assert_called_once_with(self.context, instance, self.volume_api, self.virt_driver, do_check_attach=True) self.assertEqual('fake-volume-id-2', test_bdm.volume_id)
def test_image_attach_fail_volume(self): fail_volume_image = self.image_bdm_dict.copy() fail_volume_image['volume_id'] = None test_bdm = self.driver_classes['image']( fake_block_device.fake_bdm_object( self.context, fail_volume_image)) image = {'id': 'fake-image-id-1'} volume = {'id': 'fake-volume-id-2', 'attach_status': 'detached'} instance = fake_instance.fake_instance_obj(mock.sentinel.ctx, **{'uuid': 'fake-uuid'}) with test.nested( mock.patch.object(self.volume_api, 'create', return_value=volume), mock.patch.object(self.volume_api, 'delete'), ) as (vol_create, vol_delete): wait_func = mock.MagicMock() mock_exception = exception.VolumeNotCreated(volume_id=volume['id'], seconds=1, attempts=1, volume_status='error') wait_func.side_effect = mock_exception self.assertRaises(exception.VolumeNotCreated, test_bdm.attach, context=self.context, instance=instance, volume_api=self.volume_api, virt_driver=self.virt_driver, wait_func=wait_func) vol_create.assert_called_once_with( self.context, 1, '', '', image_id=image['id'], availability_zone=None) vol_delete.assert_called_once_with(self.context, volume['id'])
def test_create_server_with_pci_dev_and_numa(self, img_mock): """Verifies that an instance can be booted with cpu pinning and with an assigned pci device. """ host_info = fakelibvirt.NUMAHostInfo(cpu_nodes=2, cpu_sockets=1, cpu_cores=2, cpu_threads=2, kB_mem=15740000) pci_info = fakelibvirt.HostPciSRIOVDevicesInfo(num_pfs=1, numa_node=1) fake_connection = self._get_connection(host_info, pci_info) # Create a flavor extra_spec = {"pci_passthrough:alias": "%s:1" % self.pfs_alias_name, 'hw:numa_nodes': '1', 'hw:cpu_policy': 'dedicated', 'hw:cpu_thread_policy': 'prefer'} flavor_id = self._create_flavor(extra_spec=extra_spec) host_pass_mock = self._get_pci_passthrough_filter_spy() with test.nested( mock.patch('nova.virt.libvirt.host.Host.get_connection', return_value=fake_connection), mock.patch('nova.scheduler.filters' '.pci_passthrough_filter.PciPassthroughFilter' '.host_passes', side_effect=host_pass_mock)) as (conn_mock, filter_mock): pf_server = self._run_build_test(flavor_id, filter_mock) self._delete_server(pf_server['id'])
def test_finish_migration(self, mo): context = mock.Mock() migration = {'source_compute': 'fake-source', 'dest_compute': 'fake-dest'} instance = stubs._fake_instance() bdevice_info = mock.Mock() disk_info = mock.Mock() network_info = mock.Mock() with test.nested( mock.patch.object(session.LXDAPISession, 'container_defined'), mock.patch.object(session.LXDAPISession, 'container_stop'), mock.patch.object(session.LXDAPISession, 'container_init'), ) as ( container_defined, container_stop, container_init ): def side_effect(*args, **kwargs): # XXX: rockstar (7 Dec 2015) - This mock is a little greedy, # and hits too many interfaces. It should become more specific # to the single places it needs to fully mocked. Truthiness of # the mock changes in py3. if args[0] == 'defined': return False container_defined.side_effect = side_effect self.assertEqual(None, (self.migrate.finish_migration(context, migration, instance, disk_info, network_info, bdevice_info)))
def test_plug_ivs_hybrid(self): calls = { "device_exists": [mock.call("qbrvif-xxx-yyy"), mock.call("qvovif-xxx-yyy")], "_create_veth_pair": [mock.call("qvbvif-xxx-yyy", "qvovif-xxx-yyy")], "execute": [ mock.call("brctl", "addbr", "qbrvif-xxx-yyy", run_as_root=True), mock.call("brctl", "setfd", "qbrvif-xxx-yyy", 0, run_as_root=True), mock.call("brctl", "stp", "qbrvif-xxx-yyy", "off", run_as_root=True), mock.call( "tee", ("/sys/class/net/qbrvif-xxx-yyy" "/bridge/multicast_snooping"), process_input="0", run_as_root=True, check_exit_code=[0, 1], ), mock.call("ip", "link", "set", "qbrvif-xxx-yyy", "up", run_as_root=True), mock.call("brctl", "addif", "qbrvif-xxx-yyy", "qvbvif-xxx-yyy", run_as_root=True), ], "create_ivs_vif_port": [ mock.call("qvovif-xxx-yyy", "aaa-bbb-ccc", "ca:fe:de:ad:be:ef", "f0000000-0000-0000-0000-000000000001") ], } with test.nested( mock.patch.object(linux_net, "device_exists", return_value=False), mock.patch.object(utils, "execute"), mock.patch.object(linux_net, "_create_veth_pair"), mock.patch.object(linux_net, "create_ivs_vif_port"), ) as (device_exists, execute, _create_veth_pair, create_ivs_vif_port): d = vif.LibvirtGenericVIFDriver() d.plug_ivs_hybrid(self.instance, self.vif_ivs) device_exists.assert_has_calls(calls["device_exists"]) _create_veth_pair.assert_has_calls(calls["_create_veth_pair"]) execute.assert_has_calls(calls["execute"]) create_ivs_vif_port.assert_has_calls(calls["create_ivs_vif_port"])
def _test_attach_volume_iscsi(self, adapter_type=None): connection_info = {'driver_volume_type': constants.DISK_FORMAT_ISCSI, 'serial': 'volume-fake-id', 'data': {'volume': 'vm-10', 'volume_id': 'volume-fake-id'}} vm_ref = 'fake-vm-ref' default_adapter_type = constants.DEFAULT_ADAPTER_TYPE adapter_type = adapter_type or default_adapter_type with test.nested( mock.patch.object(vm_util, 'get_vm_ref', return_value=vm_ref), mock.patch.object(self._volumeops, '_iscsi_discover_target', return_value=(mock.sentinel.device_name, mock.sentinel.uuid)), mock.patch.object(vm_util, 'get_scsi_adapter_type', return_value=adapter_type), mock.patch.object(self._volumeops, 'attach_disk_to_vm') ) as (get_vm_ref, iscsi_discover_target, get_scsi_adapter_type, attach_disk_to_vm): self._volumeops.attach_volume(connection_info, self._instance, adapter_type) get_vm_ref.assert_called_once_with(self._volumeops._session, self._instance) iscsi_discover_target.assert_called_once_with( connection_info['data']) if adapter_type is None: self.assertTrue(get_scsi_adapter_type.called) attach_disk_to_vm.assert_called_once_with(vm_ref, self._instance, adapter_type, 'rdmp', device_name=mock.sentinel.device_name)
def test_iscsi_get_host_iqn_instance_not_found(self): host_mor = mock.Mock() iqn = 'iscsi-name' hba = vmwareapi_fake.HostInternetScsiHba(iqn) hbas = mock.MagicMock(HostHostBusAdapter=[hba]) with test.nested( mock.patch.object(vm_util, 'get_host_ref_for_vm', side_effect=exception.InstanceNotFound('fake')), mock.patch.object(vm_util, 'get_host_ref', return_value=host_mor), mock.patch.object(self._volumeops._session, '_call_method', return_value=hbas) ) as (fake_get_host_ref_for_vm, fake_get_host_ref, fake_call_method): result = self._volumeops._iscsi_get_host_iqn(self._instance) fake_get_host_ref_for_vm.assert_called_once_with( self._volumeops._session, self._instance) fake_get_host_ref.assert_called_once_with( self._volumeops._session, self._volumeops._cluster) fake_call_method.assert_called_once_with(vutil, "get_object_property", host_mor, "config.storageDevice.hostBusAdapter") self.assertEqual(iqn, result)
def test_file_copy(self): def fake_call_method(module, method, *args, **kwargs): self.assertEqual('CopyDatastoreFile_Task', method) src_name = kwargs.get('sourceName') self.assertEqual('[ds] fake/path/src_file', src_name) src_dc_ref = kwargs.get('sourceDatacenter') self.assertEqual('fake-src-dc-ref', src_dc_ref) dst_name = kwargs.get('destinationName') self.assertEqual('[ds] fake/path/dst_file', dst_name) dst_dc_ref = kwargs.get('destinationDatacenter') self.assertEqual('fake-dst-dc-ref', dst_dc_ref) return 'fake_copy_task' with test.nested( mock.patch.object(self.session, '_wait_for_task'), mock.patch.object(self.session, '_call_method', fake_call_method) ) as (_wait_for_task, _call_method): src_ds_path = ds_obj.DatastorePath('ds', 'fake/path', 'src_file') dst_ds_path = ds_obj.DatastorePath('ds', 'fake/path', 'dst_file') ds_util.file_copy(self.session, str(src_ds_path), 'fake-src-dc-ref', str(dst_ds_path), 'fake-dst-dc-ref') _wait_for_task.assert_has_calls([ mock.call('fake_copy_task')])
def _test_detach_disk_from_vm(self, destroy_disk=False): def fake_call_method(module, method, *args, **kwargs): vmdk_detach_config_spec = kwargs.get('spec') virtual_device_config = vmdk_detach_config_spec.deviceChange[0] self.assertEqual('remove', virtual_device_config.operation) self.assertEqual('ns0:VirtualDeviceConfigSpec', virtual_device_config.obj_name) if destroy_disk: self.assertEqual('destroy', virtual_device_config.fileOperation) else: self.assertFalse(hasattr(virtual_device_config, 'fileOperation')) return 'fake_configure_task' with test.nested( mock.patch.object(self._session, '_wait_for_task'), mock.patch.object(self._session, '_call_method', fake_call_method) ) as (_wait_for_task, _call_method): fake_device = vmwareapi_fake.DataObject() fake_device.backing = vmwareapi_fake.DataObject() fake_device.backing.fileName = 'fake_path' fake_device.key = 'fake_key' self._volumeops.detach_disk_from_vm('fake_vm_ref', self._instance, fake_device, destroy_disk) _wait_for_task.assert_has_calls([ mock.call('fake_configure_task')])
def test_authorize_console_encoding(self): with test.nested( mock.patch.object(self.manager.mc_instance, 'set', return_value=None), mock.patch.object(self.manager.mc_instance, 'get', return_value='["token"]'), mock.patch.object(self.manager.mc, 'set', return_value=None), mock.patch.object(self.manager.mc, 'get', return_value=None), mock.patch.object(self.manager.mc, 'get_multi', return_value=["token1"]), ) as ( mock_instance_set, mock_instance_get, mock_set, mock_get, mock_get_multi): self.manager.authorize_console(self.context, self.u_token, 'novnc', '127.0.0.1', '8080', 'host', self.u_instance) mock_set.assert_has_calls([mock.call(b'token', mock.ANY)]) mock_instance_get.assert_has_calls([mock.call(b'instance')]) mock_get_multi.assert_has_calls([mock.call([b'token'])]) mock_instance_set.assert_has_calls( [mock.call(b'instance', mock.ANY)])
def test_execute_without_destination(self): self.destination = None self._generate_task() self.assertIsNone(self.task.destination) with test.nested( mock.patch.object(self.task, '_check_host_is_up'), mock.patch.object(self.task, '_find_destination'), mock.patch.object(self.task.compute_rpcapi, 'live_migration'), mock.patch.object(self.migration, 'save') ) as (mock_check, mock_find, mock_mig, mock_save): mock_find.return_value = "found_host" mock_mig.return_value = "bob" self.assertEqual("bob", self.task.execute()) mock_check.assert_called_once_with(self.instance_host) mock_find.assert_called_once_with() mock_mig.assert_called_once_with(self.context, host=self.instance_host, instance=self.instance, dest="found_host", block_migration=self.block_migration, migration=self.migration, migrate_data=None) self.assertTrue(mock_save.called) self.assertEqual('found_host', self.migration.dest_compute)
def test_sum_domain_memory_mb_file_backed(self): class DiagFakeDomain(object): def __init__(self, id, memmb): self.id = id self.memmb = memmb def info(self): return [0, 0, self.memmb * 1024] def ID(self): return self.id def name(self): return "instance000001" def UUIDString(self): return uuids.fake with test.nested( mock.patch.object(host.Host, "list_guests"), mock.patch('sys.platform', 'linux2'), ) as (mock_list, mock_platform): mock_list.return_value = [ libvirt_guest.Guest(DiagFakeDomain(0, 4096)), libvirt_guest.Guest(DiagFakeDomain(1, 2048)), libvirt_guest.Guest(DiagFakeDomain(2, 1024)), libvirt_guest.Guest(DiagFakeDomain(3, 1024))] self.assertEqual(8192, self.host._sum_domain_memory_mb(include_host=False))
def test_create_server_with_VF_no_PF(self, img_mock): host_info = fakelibvirt.NUMAHostInfo(cpu_nodes=2, cpu_sockets=1, cpu_cores=2, cpu_threads=2, kB_mem=15740000) pci_info = fakelibvirt.HostPciSRIOVDevicesInfo(num_pfs=1, num_vfs=4) fake_connection = self._get_connection(host_info, pci_info) # Create a flavor extra_spec = {"pci_passthrough:alias": "%s:1" % self.pfs_alias_name} extra_spec_vfs = {"pci_passthrough:alias": "%s:1" % self.vfs_alias_name} flavor_id = self._create_flavor(extra_spec=extra_spec) flavor_id_vfs = self._create_flavor(extra_spec=extra_spec_vfs) host_pass_mock = self._get_pci_passthrough_filter_spy() with test.nested( mock.patch('nova.virt.libvirt.host.Host.get_connection', return_value=fake_connection), mock.patch('nova.scheduler.filters' '.pci_passthrough_filter.PciPassthroughFilter' '.host_passes', side_effect=host_pass_mock)) as (conn_mock, filter_mock): vf_server = self._run_build_test(flavor_id_vfs, filter_mock) pf_server = self._run_build_test(flavor_id, filter_mock, end_status='ERROR') self._delete_server(pf_server['id']) self._delete_server(vf_server['id'])
def _test_cert_api(self, method, **kwargs): ctxt = context.RequestContext('fake_user', 'fake_project') rpcapi = cert_rpcapi.CertAPI() self.assertIsNotNone(rpcapi.client) self.assertEqual(CONF.cert_topic, rpcapi.client.target.topic) orig_prepare = rpcapi.client.prepare with test.nested( mock.patch.object(rpcapi.client, 'call'), mock.patch.object(rpcapi.client, 'prepare'), mock.patch.object(rpcapi.client, 'can_send_version'), ) as ( rpc_mock, prepare_mock, csv_mock ): prepare_mock.return_value = rpcapi.client rpc_mock.return_value = 'foo' csv_mock.side_effect = ( lambda v: orig_prepare().can_send_version()) retval = getattr(rpcapi, method)(ctxt, **kwargs) self.assertEqual(rpc_mock.return_value, retval) prepare_mock.assert_called_once_with() rpc_mock.assert_called_once_with(ctxt, method, **kwargs)
def test_create_server_with_pinning(self): host_info = NumaHostInfo(cpu_nodes=1, cpu_sockets=1, cpu_cores=5, cpu_threads=2, kB_mem=15740000) fake_connection = self._get_connection(host_info=host_info) # Create a flavor extra_spec = { 'hw:cpu_policy': 'dedicated', 'hw:cpu_thread_policy': 'prefer', } flavor_id = self._create_flavor(vcpu=5, extra_spec=extra_spec) host_pass_mock = self._get_topology_filter_spy() with test.nested( mock.patch('nova.virt.libvirt.host.Host.get_connection', return_value=fake_connection), mock.patch('nova.scheduler.filters' '.numa_topology_filter.NUMATopologyFilter.host_passes', side_effect=host_pass_mock)) as (conn_mock, filter_mock): server = self._run_build_test(flavor_id, filter_mock) ctx = nova_context.get_admin_context() inst = objects.Instance.get_by_uuid(ctx, server['id']) self.assertEqual(1, len(inst.numa_topology.cells)) self.assertEqual(5, inst.numa_topology.cells[0].cpu_topology.cores)
def _test_create_mocked(self, update_or_create=False): values = {'source_type': 'volume', 'volume_id': 'fake-vol-id', 'destination_type': 'volume', 'instance_uuid': uuids.instance, 'attachment_id': None} fake_bdm = fake_block_device.FakeDbBlockDeviceDict(values) with test.nested( mock.patch.object( db, 'block_device_mapping_create', return_value=fake_bdm), mock.patch.object( db, 'block_device_mapping_update_or_create', return_value=fake_bdm), ) as (bdm_create_mock, bdm_update_or_create_mock): bdm = objects.BlockDeviceMapping(context=self.context, **values) if update_or_create: method = bdm.update_or_create else: method = bdm.create method() if update_or_create: bdm_update_or_create_mock.assert_called_once_with( self.context, values, legacy=False) else: bdm_create_mock.assert_called_once_with( self.context, values, legacy=False)
def test_free_allocated_VF(self): self._create_fake_instance() with test.nested( mock.patch.object(objects.PciDevice, 'get_by_dev_addr', side_effect=self._fake_pci_device_get_by_addr), mock.patch.object(objects.PciDeviceList, 'get_by_parent_address', side_effect=self._fake_get_by_parent_address)): self._create_pci_devices() vf = self.sriov_vf_devices[0] dependents = self._fake_get_by_parent_address(None, None, vf.parent_addr) for devobj in dependents: devobj.claim(self.inst) devobj.allocate(self.inst) self.assertEqual(devobj.status, fields.PciDeviceStatus.ALLOCATED) for devobj in dependents[:3]: devobj.free(self.inst) # check if parent device status is still UNAVAILABLE parent = self._fake_pci_device_get_by_addr(None, None, devobj.parent_addr) self.assertTrue(fields.PciDeviceStatus.UNAVAILABLE, parent.status) for devobj in dependents[3:]: devobj.free(self.inst) # check if parent device status is now AVAILABLE parent = self._fake_pci_device_get_by_addr(None, None, devobj.parent_addr) self.assertTrue(fields.PciDeviceStatus.AVAILABLE, parent.status)
def test_confirm_migration(self): migration = mock.Mock() instance = stubs._fake_instance() network_info = mock.Mock() with test.nested( mock.patch.object(session.LXDAPISession, 'container_defined'), mock.patch.object(session.LXDAPISession, 'profile_delete'), mock.patch.object(session.LXDAPISession, 'container_destroy'), mock.patch.object(operations.LXDContainerOperations, 'unplug_vifs'), ) as ( mock_container_defined, mock_profile_delete, mock_container_destroy, mock_unplug_vifs): self.assertEqual(None, self.migrate.confirm_migration(migration, instance, network_info)) mock_container_defined.assert_called_once_with(instance.name, instance) mock_profile_delete.assert_called_once_with(instance) mock_unplug_vifs.assert_called_once_with(instance, network_info)
def test_extend_qcow_success(self, mock_exec, mock_inst, mock_resize, mock_extendable, mock_can_resize): imgfile = tempfile.NamedTemporaryFile() self.addCleanup(imgfile.close) imgsize = 10 device = "/dev/sdh" image = imgmodel.LocalFileImage(imgfile, imgmodel.FORMAT_QCOW2) self.flags(resize_fs_using_block_device=True) mounter = FakeMount.instance_for_format( image, None, None) mounter.device = device mock_inst.return_value = mounter with test.nested( mock.patch.object(mounter, 'get_dev', autospec=True, return_value=True), mock.patch.object(mounter, 'unget_dev', autospec=True), ) as (mock_get_dev, mock_unget_dev): api.extend(image, imgsize) mock_can_resize.assert_called_once_with(imgfile, imgsize) mock_exec.assert_called_once_with('qemu-img', 'resize', imgfile, imgsize) mock_extendable.assert_called_once_with(image) mock_inst.assert_called_once_with(image, None, None) mock_resize.assert_called_once_with(mounter.device, run_as_root=True, check_exit_code=[0]) mock_get_dev.assert_called_once_with() mock_unget_dev.assert_called_once_with()
def test_list_base_images(self): def fake_get_object_property(vim, mobj, property_name): return 'fake-ds-browser' def fake_get_sub_folders(session, ds_browser, ds_path): files = set() files.add('image-ref-uuid') return files with test.nested( mock.patch.object(vutil, 'get_object_property', fake_get_object_property), mock.patch.object(ds_util, 'get_sub_folders', fake_get_sub_folders) ) as (_get_dynamic, _get_sub_folders): fake_ds_ref = fake.ManagedObjectReference('fake-ds-ref') datastore = ds_obj.Datastore(name='ds', ref=fake_ds_ref) ds_path = datastore.build_path('base_folder') images = self._imagecache._list_datastore_images( ds_path, datastore) originals = set() originals.add('image-ref-uuid') self.assertEqual({'originals': originals, 'unexplained_images': []}, images)
def test_timestamp_cleanup(self): def fake_get_timestamp(ds_browser, ds_path): self.assertEqual('fake-ds-browser', ds_browser) self.assertEqual('[fake-ds] fake-path', str(ds_path)) if not self.exists: return ts = '%s%s' % (imagecache.TIMESTAMP_PREFIX, self._time.strftime(imagecache.TIMESTAMP_FORMAT)) return ts with test.nested( mock.patch.object(self._imagecache, '_get_timestamp', fake_get_timestamp), mock.patch.object(ds_util, 'file_delete') ) as (_get_timestamp, _file_delete): self.exists = False self._imagecache.timestamp_cleanup( 'fake-dc-ref', 'fake-ds-browser', ds_obj.DatastorePath('fake-ds', 'fake-path')) self.assertEqual(0, _file_delete.call_count) self.exists = True self._imagecache.timestamp_cleanup( 'fake-dc-ref', 'fake-ds-browser', ds_obj.DatastorePath('fake-ds', 'fake-path')) expected_ds_path = ds_obj.DatastorePath( 'fake-ds', 'fake-path', self._file_name) _file_delete.assert_called_once_with(self._session, expected_ds_path, 'fake-dc-ref')
def test_execute_without_destination(self): self.destination = None self._generate_task() self.assertIsNone(self.task.destination) with test.nested( mock.patch.object(self.task, '_check_host_is_up'), mock.patch.object(self.task, '_find_destination'), mock.patch.object(self.task.compute_rpcapi, 'live_migration'), mock.patch.object(self.migration, 'save'), mock.patch('nova.conductor.tasks.migrate.' 'replace_allocation_with_migration'), ) as (mock_check, mock_find, mock_mig, mock_save, mock_alloc): mock_find.return_value = ("found_host", "found_node") mock_mig.return_value = "bob" mock_alloc.return_value = (mock.MagicMock(), mock.MagicMock()) self.assertEqual("bob", self.task.execute()) mock_check.assert_called_once_with(self.instance_host) mock_find.assert_called_once_with() mock_mig.assert_called_once_with(self.context, host=self.instance_host, instance=self.instance, dest="found_host", block_migration=self.block_migration, migration=self.migration, migrate_data=None) self.assertTrue(mock_save.called) self.assertEqual('found_host', self.migration.dest_compute) self.assertEqual('found_node', self.migration.dest_node) self.assertEqual(self.instance.node, self.migration.source_node) self.assertTrue(mock_alloc.called)
def test_release_dhcp(self): ctxt = context.RequestContext('fake_user', 'fake_project') dev = 'eth0' address = '192.168.65.158' vif_address = '00:0c:29:2c:b2:64' host = 'fake-host' rpcapi = network_rpcapi.NetworkAPI() call_mock = mock.Mock() cctxt_mock = mock.Mock(call=call_mock) with test.nested( mock.patch.object(rpcapi.client, 'can_send_version', return_value=True), mock.patch.object(rpcapi.client, 'prepare', return_value=cctxt_mock) ) as ( can_send_mock, prepare_mock ): rpcapi.release_dhcp(ctxt, host, dev, address, vif_address) can_send_mock.assert_called_once_with('1.17') prepare_mock.assert_called_once_with(server=host, version='1.17') call_mock.assert_called_once_with(ctxt, 'release_dhcp', dev=dev, address=address, vif_address=vif_address)
def _test_compute_api(self, method, rpc_method, expected_args=None, **kwargs): ctxt = context.RequestContext('fake_user', 'fake_project') rpcapi = kwargs.pop('rpcapi_class', compute_rpcapi.ComputeAPI)() self.assertIsNotNone(rpcapi.client) self.assertEqual(rpcapi.client.target.topic, CONF.compute_topic) orig_prepare = rpcapi.client.prepare base_version = rpcapi.client.target.version expected_version = kwargs.pop('version', base_version) expected_kwargs = kwargs.copy() if expected_args: expected_kwargs.update(expected_args) if 'host_param' in expected_kwargs: expected_kwargs['host'] = expected_kwargs.pop('host_param') else: expected_kwargs.pop('host', None) cast_and_call = ['confirm_resize', 'stop_instance'] if rpc_method == 'call' and method in cast_and_call: if method == 'confirm_resize': kwargs['cast'] = False else: kwargs['do_cast'] = False if 'host' in kwargs: host = kwargs['host'] elif 'instances' in kwargs: host = kwargs['instances'][0]['host'] else: host = kwargs['instance']['host'] if method == 'rebuild_instance' and 'node' in expected_kwargs: expected_kwargs['scheduled_node'] = expected_kwargs.pop('node') with test.nested( mock.patch.object(rpcapi.client, rpc_method), mock.patch.object(rpcapi.client, 'prepare'), mock.patch.object(rpcapi.client, 'can_send_version'), ) as ( rpc_mock, prepare_mock, csv_mock ): prepare_mock.return_value = rpcapi.client if '_return_value' in kwargs: rpc_mock.return_value = kwargs.pop('_return_value') del expected_kwargs['_return_value'] elif rpc_method == 'call': rpc_mock.return_value = 'foo' else: rpc_mock.return_value = None csv_mock.side_effect = ( lambda v: orig_prepare(version=v).can_send_version()) retval = getattr(rpcapi, method)(ctxt, **kwargs) self.assertEqual(retval, rpc_mock.return_value) prepare_mock.assert_called_once_with(version=expected_version, server=host) rpc_mock.assert_called_once_with(ctxt, method, **expected_kwargs)
def _get_group_details_with_filter_not_configured(self, policy): wrong_filter = { 'affinity': 'ServerGroupAntiAffinityFilter', 'anti-affinity': 'ServerGroupAffinityFilter', } self.flags(scheduler_default_filters=[wrong_filter[policy]]) instance = fake_instance.fake_instance_obj(self.context, params={'host': 'hostA'}) group = objects.InstanceGroup() group.uuid = str(uuid.uuid4()) group.members = [instance.uuid] group.policies = [policy] with test.nested( mock.patch.object(objects.InstanceGroup, 'get_by_instance_uuid', return_value=group), mock.patch.object(objects.InstanceGroup, 'get_hosts', return_value=['hostA']), ) as (get_group, get_hosts): scheduler_utils._SUPPORTS_ANTI_AFFINITY = None scheduler_utils._SUPPORTS_AFFINITY = None self.assertRaises(exception.UnsupportedPolicyException, scheduler_utils._get_group_details, self.context, 'fake-uuid')
def test_cloudpipe_list(self): def network_api_get(context, network_id): self.assertEqual(context.project_id, project_id) return {'vpn_public_address': '127.0.0.1', 'vpn_public_port': 22} def fake_get_nw_info_for_instance(instance): return fake_network.fake_get_instance_nw_info(self) with test.nested( mock.patch.object(utils, 'vpn_ping', return_value=True), mock.patch.object(compute_utils, 'get_nw_info_for_instance', side_effect=fake_get_nw_info_for_instance), mock.patch.object(self.controller.network_api, "get", side_effect=network_api_get), mock.patch.object(self.controller.compute_api, "get_all", side_effect=compute_api_get_all) ) as (mock_vpn_ping, mock_utils_get, mock_nw_get, mock_cpu_get_all): res_dict = self.controller.index(self.req) response = {'cloudpipes': [{'project_id': project_id, 'internal_ip': '192.168.1.100', 'public_ip': '127.0.0.1', 'public_port': 22, 'state': 'running', 'instance_id': uuid, 'created_at': '1981-10-20T00:00:00Z'}]} self.assertThat(response, matchers.DictMatches(res_dict)) self.assertTrue(mock_cpu_get_all.called) self.assertTrue(mock_nw_get.called) self.assertTrue(mock_utils_get.called) self.assertTrue(mock_vpn_ping.called)
def test_detach_volume_vmdk_invalid(self): connection_info = {'driver_volume_type': 'vmdk', 'serial': 'volume-fake-id', 'data': {'volume': 'vm-10', 'volume_id': 'volume-fake-id'}} instance = mock.MagicMock(name='fake-name', vm_state=vm_states.ACTIVE) vmdk_info = vm_util.VmdkInfo('fake-path', constants.ADAPTER_TYPE_IDE, constants.DISK_TYPE_PREALLOCATED, 1024, 'fake-device') with test.nested( mock.patch.object(vm_util, 'get_vm_ref', return_value=mock.sentinel.vm_ref), mock.patch.object(self._volumeops, '_get_volume_ref'), mock.patch.object(self._volumeops, '_get_vmdk_backed_disk_device'), mock.patch.object(vm_util, 'get_vmdk_info', return_value=vmdk_info), mock.patch.object(vm_util, 'get_vm_state', return_value=power_state.RUNNING) ) as (get_vm_ref, get_volume_ref, get_vmdk_backed_disk_device, get_vmdk_info, get_vm_state): self.assertRaises(exception.Invalid, self._volumeops._detach_volume_vmdk, connection_info, instance) get_vm_ref.assert_called_once_with(self._volumeops._session, instance) get_volume_ref.assert_called_once_with( connection_info['data']['volume']) get_vmdk_backed_disk_device.assert_called_once_with( mock.sentinel.vm_ref, connection_info['data']) self.assertTrue(get_vmdk_info.called) get_vm_state.assert_called_once_with(self._volumeops._session, instance)
def test_create_server_with_pci_dev_and_numa_fails(self, img_mock): """This test ensures that it is not possible to allocated CPU and memory resources from one NUMA node and a PCI device from another. """ host_info = fakelibvirt.NUMAHostInfo(cpu_nodes=2, cpu_sockets=1, cpu_cores=2, cpu_threads=2, kB_mem=15740000) pci_info = fakelibvirt.HostPciSRIOVDevicesInfo(num_pfs=1, numa_node=0) fake_connection = self._get_connection(host_info, pci_info) # Create a flavor extra_spec_vm = {'hw:cpu_policy': 'dedicated', 'hw:numa_node': '1'} extra_spec = {'pci_passthrough:alias': '%s:1' % self.pfs_alias_name, 'hw:numa_nodes': '1', 'hw:cpu_policy': 'dedicated', 'hw:cpu_thread_policy': 'prefer'} vm_flavor_id = self._create_flavor(vcpu=4, extra_spec=extra_spec_vm) pf_flavor_id = self._create_flavor(extra_spec=extra_spec) host_pass_mock = self._get_pci_passthrough_filter_spy() with test.nested( mock.patch('nova.virt.libvirt.host.Host.get_connection', return_value=fake_connection), mock.patch('nova.scheduler.filters' '.pci_passthrough_filter.PciPassthroughFilter' '.host_passes', side_effect=host_pass_mock)) as (conn_mock, filter_mock): vm_server = self._run_build_test(vm_flavor_id, filter_mock) pf_server = self._run_build_test(pf_flavor_id, filter_mock, end_status='ERROR') self._delete_server(vm_server['id']) self._delete_server(pf_server['id'])
def test_migrate_disk_power_off_resize(self): self.flags(my_ip='fakeip') instance = stubs._fake_instance() network_info = mock.Mock() flavor = mock.Mock() context = mock.Mock() dest = 'fakeip' with test.nested( mock.patch.object(session.LXDAPISession, 'container_defined'), mock.patch.object(config.LXDContainerConfig, 'create_profile'), mock.patch.object(session.LXDAPISession, 'profile_update') ) as ( mock_container_defined, mock_create_profile, mock_profile_update ): self.assertEqual('', self.migrate.migrate_disk_and_power_off( context, instance, dest, flavor, network_info)) mock_container_defined.assert_called_once_with(instance.name, instance) mock_create_profile.assert_called_once_with(instance, network_info)
def _test_execute(self, cross_cell_exec_mock, 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, same_cell=True): 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, allow_cross_cell_move=not same_cell) 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 test.nested( mock.patch.object(scheduler_utils, 'fill_provider_mapping'), mock.patch.object( task, '_is_selected_host_in_source_cell', return_value=same_cell)) as (fill_mock, _is_source_cell_mock): task.execute() fill_mock.assert_called_once_with(task.context, task.reportclient, task.request_spec, selection) _is_source_cell_mock.assert_called_once_with(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) if same_cell: 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') cross_cell_exec_mock.assert_not_called() else: cross_cell_exec_mock.assert_called_once_with() az_mock.assert_not_called() prep_resize_mock.assert_not_called() 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) self.assertEqual( not same_cell, self.request_spec.requested_destination.allow_cross_cell_move) mock_get_resources.assert_called_once_with(self.context, self.instance.uuid) self.assertEqual([], self.request_spec.requested_resources)
def _test_compute_api(self, method, rpc_method, expected_args=None, **kwargs): ctxt = context.RequestContext('fake_user', 'fake_project') rpcapi = kwargs.pop('rpcapi_class', compute_rpcapi.ComputeAPI)() self.assertIsNotNone(rpcapi.client) self.assertEqual(rpcapi.client.target.topic, CONF.compute_topic) orig_prepare = rpcapi.client.prepare base_version = rpcapi.client.target.version expected_version = kwargs.pop('version', base_version) expected_kwargs = kwargs.copy() if expected_args: expected_kwargs.update(expected_args) if 'host_param' in expected_kwargs: expected_kwargs['host'] = expected_kwargs.pop('host_param') else: expected_kwargs.pop('host', None) cast_and_call = ['confirm_resize', 'stop_instance'] if rpc_method == 'call' and method in cast_and_call: if method == 'confirm_resize': kwargs['cast'] = False else: kwargs['do_cast'] = False if 'host' in kwargs: host = kwargs['host'] elif 'instances' in kwargs: host = kwargs['instances'][0]['host'] else: host = kwargs['instance']['host'] if method == 'rebuild_instance' and 'node' in expected_kwargs: expected_kwargs['scheduled_node'] = expected_kwargs.pop('node') with test.nested( mock.patch.object(rpcapi.client, rpc_method), mock.patch.object(rpcapi.client, 'prepare'), mock.patch.object(rpcapi.client, 'can_send_version'), ) as (rpc_mock, prepare_mock, csv_mock): prepare_mock.return_value = rpcapi.client if '_return_value' in kwargs: rpc_mock.return_value = kwargs.pop('_return_value') del expected_kwargs['_return_value'] elif rpc_method == 'call': rpc_mock.return_value = 'foo' else: rpc_mock.return_value = None csv_mock.side_effect = ( lambda v: orig_prepare(version=v).can_send_version()) retval = getattr(rpcapi, method)(ctxt, **kwargs) self.assertEqual(retval, rpc_mock.return_value) prepare_mock.assert_called_once_with(version=expected_version, server=host) rpc_mock.assert_called_once_with(ctxt, method, **expected_kwargs)
def test_delete_during_create(self): compute = self._start_compute('compute1') def delete_race(instance): self.api.delete_server(instance.uuid) self._wait_for_server_parameter( self.api, {'id': instance.uuid}, {'OS-EXT-STS:task_state': task_states.DELETING}, ) orig_save = objects.Instance.save # an in-memory record of the current instance task state as persisted # to the db. db_task_states = collections.defaultdict(str) active_after_deleting_error = [False] # A wrapper round instance.save() which allows us to inject a race # under specific conditions before calling the original instance.save() def wrap_save(instance, *wrap_args, **wrap_kwargs): # We're looking to inject the race before: # instance.save(expected_task_state=task_states.SPAWNING) # towards the end of _build_and_run_instance. # # At this point the driver has finished creating the instance, but # we're still on the compute host and still holding the compute # host instance lock. # # This is just a convenient interception point. In order to race # the delete could have happened at any point prior to this since # the previous instance.save() expected_task_state = wrap_kwargs.get('expected_task_state') if (instance.vm_state == vm_states.ACTIVE and instance.task_state is None and expected_task_state == task_states.SPAWNING): delete_race(instance) orig_save(instance, *wrap_args, **wrap_kwargs) if (db_task_states[instance.uuid] == task_states.DELETING and instance.vm_state == vm_states.ACTIVE and instance.task_state is None): # the instance was in the DELETING task state in the db, and we # overwrote that to set it to ACTIVE with no task state. # Bug 1848666. active_after_deleting_error[0] = True db_task_states[instance.uuid] = instance.task_state with test.nested( mock.patch('nova.objects.Instance.save', wrap_save), mock.patch.object(compute.driver, 'spawn'), mock.patch.object(compute.driver, 'unplug_vifs'), ) as (_, mock_spawn, mock_unplug_vifs): # the compute manager doesn't set the ERROR state in cleanup since # it might race with delete, therefore we'll be left in BUILDING server_req = self._build_server(networks='none') created_server = self.api.post_server({'server': server_req}) self._wait_until_deleted(created_server) # assert that we spawned the instance, and unplugged vifs on # cleanup mock_spawn.assert_called() # FIXME(mdbooth): We should have called unplug_vifs in cleanup, but # we didn't due to bug 1831771 mock_unplug_vifs.assert_not_called() # FIXME(mdbooth): Bug 1848666 self.assertTrue(active_after_deleting_error[0])
def test_get_domain_capabilities_non_native_kvm(self): # This test assumes that we are on a x86 host and the # virt-type is set to kvm. In that case we would expect # libvirt to raise an error if you try to get the domain # capabilities for non-native archs specifying the kvm virt # type. archs = { 'sparc': 'SS-5', 'mips': 'malta', 'mipsel': 'malta', 'ppc': 'g3beige', 'armv7l': 'virt-2.11', } # Because we are mocking out the libvirt connection and # supplying fake data, no exception will be raised, so we # first store a reference to the original # _get_domain_capabilities function local__get_domain_caps = self.host._get_domain_capabilities # We then define our own version that will raise for # non-native archs and otherwise delegates to the private # function. def _get_domain_capabilities(**kwargs): arch = kwargs['arch'] if arch not in archs: return local__get_domain_caps(**kwargs) else: exc = fakelibvirt.make_libvirtError( fakelibvirt.libvirtError, "invalid argument: KVM is not supported by " "'/usr/bin/qemu-system-%s' on this host" % arch, error_code=fakelibvirt.VIR_ERR_INVALID_ARG) raise exc # Finally we patch to use our own version with test.nested( mock.patch.object(host.LOG, 'debug'), mock.patch.object(self.host, "_get_domain_capabilities"), ) as (mock_log, mock_caps): mock_caps.side_effect = _get_domain_capabilities self.flags(virt_type='kvm', group='libvirt') # and call self.host.get_domain_capabilities() directly as # the exception should be caught internally caps = self.host.get_domain_capabilities() # We don't really care what mock_caps is called with, # as we assert the behavior we expect below. However we # can at least check for the expected debug messages. mock_caps.assert_called() warnings = [] for call in mock_log.mock_calls: name, args, kwargs = call if "Error from libvirt when retrieving domain capabilities" \ in args[0]: warnings.append(call) self.assertTrue(len(warnings) > 0) # The resulting capabilities object should be non-empty # as the x86 archs won't raise a libvirtError exception self.assertTrue(len(caps) > 0) # but all of the archs we mocked out should be skipped and # not included in the result set for arch in archs: self.assertNotIn(arch, caps)
def test_execute_with_destination(self, mock_get_az): dest_node = objects.ComputeNode(hypervisor_hostname='dest_node') with test.nested( mock.patch.object(self.task, '_check_host_is_up'), mock.patch.object(self.task, '_check_requested_destination'), mock.patch.object(scheduler_utils, 'claim_resources_on_destination'), mock.patch.object(self.migration, 'save'), mock.patch.object(self.task.compute_rpcapi, 'live_migration'), mock.patch('nova.conductor.tasks.migrate.' 'replace_allocation_with_migration'), mock.patch.object(self.task, '_check_destination_is_not_source'), mock.patch.object(self.task, '_check_destination_has_enough_memory'), mock.patch.object(self.task, '_check_compatible_with_source_hypervisor', return_value=(mock.sentinel.source_node, dest_node)), ) as (mock_check_up, mock_check_dest, mock_claim, mock_save, mock_mig, m_alloc, m_check_diff, m_check_enough_mem, m_check_compatible): mock_mig.return_value = "bob" m_alloc.return_value = (mock.MagicMock(), mock.sentinel.allocs) self.assertEqual("bob", self.task.execute()) mock_check_up.assert_has_calls([ mock.call(self.instance_host), mock.call(self.destination)]) mock_check_dest.assert_called_once_with() m_check_diff.assert_called_once() m_check_enough_mem.assert_called_once() m_check_compatible.assert_called_once() allocs = mock.sentinel.allocs mock_claim.assert_called_once_with( self.context, self.task.report_client, self.instance, mock.sentinel.source_node, dest_node, source_allocations=allocs, consumer_generation=None) mock_mig.assert_called_once_with( self.context, host=self.instance_host, instance=self.instance, dest=self.destination, block_migration=self.block_migration, migration=self.migration, migrate_data=None) self.assertTrue(mock_save.called) mock_get_az.assert_called_once_with(self.context, self.destination) self.assertEqual('fake-az', self.instance.availability_zone) # make sure the source/dest fields were set on the migration object self.assertEqual(self.instance.node, self.migration.source_node) self.assertEqual(dest_node.hypervisor_hostname, self.migration.dest_node) self.assertEqual(self.task.destination, self.migration.dest_compute) m_alloc.assert_called_once_with(self.context, self.instance, self.migration) # When the task is executed with a destination it means the host is # being forced and we don't call the scheduler, so we don't need to # heal the request spec. self.heal_reqspec_is_bfv_mock.assert_not_called() # When the task is executed with a destination it means the host is # being forced and we don't call the scheduler, so we don't need to # modify the request spec self.ensure_network_metadata_mock.assert_not_called()
def test_execute_with_destination(self, new_mode=True): dest_node = objects.ComputeNode(hypervisor_hostname='dest_node') with test.nested( mock.patch.object(self.task, '_check_host_is_up'), mock.patch.object(self.task, '_check_requested_destination', return_value=(mock.sentinel.source_node, dest_node)), mock.patch.object(scheduler_utils, 'claim_resources_on_destination'), mock.patch.object(self.migration, 'save'), mock.patch.object(self.task.compute_rpcapi, 'live_migration'), mock.patch('nova.conductor.tasks.migrate.' 'replace_allocation_with_migration'), mock.patch( 'nova.conductor.tasks.live_migrate.' 'should_do_migration_allocation')) as (mock_check_up, mock_check_dest, mock_claim, mock_save, mock_mig, m_alloc, mock_sda): mock_mig.return_value = "bob" m_alloc.return_value = (mock.MagicMock(), mock.sentinel.allocs) mock_sda.return_value = new_mode self.assertEqual("bob", self.task.execute()) mock_check_up.assert_called_once_with(self.instance_host) mock_check_dest.assert_called_once_with() if new_mode: allocs = mock.sentinel.allocs else: allocs = None mock_claim.assert_called_once_with( self.context, self.task.scheduler_client.reportclient, self.instance, mock.sentinel.source_node, dest_node, source_node_allocations=allocs) mock_mig.assert_called_once_with( self.context, host=self.instance_host, instance=self.instance, dest=self.destination, block_migration=self.block_migration, migration=self.migration, migrate_data=None) self.assertTrue(mock_save.called) # make sure the source/dest fields were set on the migration object self.assertEqual(self.instance.node, self.migration.source_node) self.assertEqual(dest_node.hypervisor_hostname, self.migration.dest_node) self.assertEqual(self.task.destination, self.migration.dest_compute) if new_mode: m_alloc.assert_called_once_with(self.context, self.instance, self.migration) else: m_alloc.assert_not_called() # When the task is executed with a destination it means the host is # being forced and we don't call the scheduler, so we don't need to # heal the request spec. self.heal_reqspec_is_bfv_mock.assert_not_called() # When the task is executed with a destination it means the host is # being forced and we don't call the scheduler, so we don't need to # modify the request spec self.ensure_network_metadata_mock.assert_not_called()
def test_fetch_image_ova(self, mock_tar_open, mock_write_class, mock_read_class): session = mock.MagicMock() ovf_descriptor = None ovf_path = os.path.join(os.path.dirname(__file__), 'ovf.xml') with open(ovf_path) as f: ovf_descriptor = f.read() with test.nested( mock.patch.object(images.IMAGE_API, 'get'), mock.patch.object(images.IMAGE_API, 'download'), mock.patch.object(images, 'start_transfer'), mock.patch.object(images, '_build_shadow_vm_config_spec'), mock.patch.object( session, '_call_method')) as (mock_image_api_get, mock_image_api_download, mock_start_transfer, mock_build_shadow_vm_config_spec, mock_call_method): image_data = {'id': 'fake-id', 'disk_format': 'vmdk', 'size': 512} instance = mock.MagicMock() instance.image_ref = image_data['id'] mock_image_api_get.return_value = image_data vm_folder_ref = mock.MagicMock() res_pool_ref = mock.MagicMock() context = mock.MagicMock() mock_read_handle = mock.MagicMock() mock_read_class.return_value = mock_read_handle mock_write_handle = mock.MagicMock() mock_write_class.return_value = mock_write_handle mock_write_handle.get_imported_vm.return_value = \ mock.sentinel.vm_ref mock_ovf = mock.MagicMock() mock_ovf.name = 'dsl.ovf' mock_vmdk = mock.MagicMock() mock_vmdk.name = "Damn_Small_Linux-disk1.vmdk" def fake_extract(name): if name == mock_ovf: m = mock.MagicMock() m.read.return_value = ovf_descriptor return m elif name == mock_vmdk: return mock_read_handle mock_tar = mock.MagicMock() mock_tar.__iter__ = mock.Mock( return_value=iter([mock_ovf, mock_vmdk])) mock_tar.extractfile = fake_extract mock_tar_open.return_value.__enter__.return_value = mock_tar images.fetch_image_ova(context, instance, session, 'fake-vm', 'fake-datastore', vm_folder_ref, res_pool_ref) mock_tar_open.assert_called_once_with(mode='r|', fileobj=mock_read_handle) mock_start_transfer.assert_called_once_with( context, mock_read_handle, 512, write_file_handle=mock_write_handle) mock_call_method.assert_called_once_with(session.vim, "UnregisterVM", mock.sentinel.vm_ref)
def test_sev_trait_off_on(self): """Test that the compute service reports the SEV trait in the list of global traits, but doesn't immediately register it on the compute host resource provider in the placement API, due to the kvm-amd kernel module's sev parameter file being (mocked as) absent. Then test that if the SEV capability appears (again via mocking), after a restart of the compute service, the trait gets registered on the compute host. Also test that on both occasions, the inventory of the MEM_ENCRYPTION_CONTEXT resource class on the compute host corresponds to the absence or presence of the SEV capability. """ self.assertFalse(self.compute.driver._host.supports_amd_sev) sev_trait = ost.HW_CPU_X86_AMD_SEV global_traits = self._get_all_traits() self.assertIn(sev_trait, global_traits) traits = self._get_provider_traits(self.host_uuid) self.assertNotIn(sev_trait, traits) self.assertMemEncryptionSlotsEqual(0) # Now simulate the host gaining SEV functionality. Here we # simulate a kernel update or reconfiguration which causes the # kvm-amd kernel module's "sev" parameter to become available # and set to 1, however it could also happen via a libvirt # upgrade, for instance. sev_features = \ fakelibvirt.virConnect._domain_capability_features_with_SEV with test.nested( self.patch_exists(SEV_KERNEL_PARAM_FILE, True), self.patch_open(SEV_KERNEL_PARAM_FILE, "1\n"), mock.patch.object(fakelibvirt.virConnect, '_domain_capability_features', new=sev_features)) as (mock_exists, mock_open, mock_features): # Retrigger the detection code. In the real world this # would be a restart of the compute service. self.compute.driver._host._set_amd_sev_support() self.assertTrue(self.compute.driver._host.supports_amd_sev) mock_exists.assert_has_calls([mock.call(SEV_KERNEL_PARAM_FILE)]) mock_open.assert_has_calls([mock.call(SEV_KERNEL_PARAM_FILE)]) # However it won't disappear in the provider tree and get synced # back to placement until we force a reinventory: self.compute.manager.reset() self._run_periodics() traits = self._get_provider_traits(self.host_uuid) self.assertIn(sev_trait, traits) # Sanity check that we've still got the trait globally. self.assertIn(sev_trait, self._get_all_traits()) self.assertMemEncryptionSlotsEqual(db_const.MAX_INT)
def _test_network_api(self, method, rpc_method, **kwargs): ctxt = context.RequestContext('fake_user', 'fake_project') rpcapi = network_rpcapi.NetworkAPI() self.assertIsNotNone(rpcapi.client) self.assertEqual(CONF.network_topic, rpcapi.client.target.topic) expected_retval = 'foo' if rpc_method == 'call' else None expected_version = kwargs.pop('version', None) expected_fanout = kwargs.pop('fanout', None) expected_kwargs = kwargs.copy() for k, v in expected_kwargs.items(): if isinstance(v, self.DefaultArg): expected_kwargs[k] = v.value kwargs.pop(k) prepare_kwargs = {} if expected_version: prepare_kwargs['version'] = expected_version if expected_fanout: prepare_kwargs['fanout'] = True if 'source_compute' in expected_kwargs: # Fix up for migrate_instance_* calls. expected_kwargs['source'] = expected_kwargs.pop('source_compute') expected_kwargs['dest'] = expected_kwargs.pop('dest_compute') targeted_methods = [ 'lease_fixed_ip', 'release_fixed_ip', 'rpc_setup_network_on_host', '_rpc_allocate_fixed_ip', 'deallocate_fixed_ip', 'update_dns', '_associate_floating_ip', '_disassociate_floating_ip', 'lease_fixed_ip', 'release_fixed_ip', 'migrate_instance_start', 'migrate_instance_finish', 'allocate_for_instance', 'deallocate_for_instance', ] targeted_by_instance = ['deallocate_for_instance'] if method in targeted_methods and ('host' in expected_kwargs or 'instance' in expected_kwargs): if method in targeted_by_instance: host = expected_kwargs['instance']['host'] else: host = expected_kwargs['host'] if method not in ['allocate_for_instance', 'deallocate_fixed_ip']: expected_kwargs.pop('host') if CONF.multi_host: prepare_kwargs['server'] = host with test.nested( mock.patch.object(rpcapi.client, rpc_method), mock.patch.object(rpcapi.client, 'prepare'), mock.patch.object(rpcapi.client, 'can_send_version'), ) as ( rpc_mock, prepare_mock, csv_mock ): version_check = [ 'deallocate_for_instance', 'deallocate_fixed_ip', 'allocate_for_instance', 'release_fixed_ip', 'set_network_host', 'setup_networks_on_host' ] if method in version_check: csv_mock.return_value = True if prepare_kwargs: prepare_mock.return_value = rpcapi.client if rpc_method == 'call': rpc_mock.return_value = 'foo' else: rpc_mock.return_value = None retval = getattr(rpcapi, method)(ctxt, **kwargs) self.assertEqual(expected_retval, retval) if method in version_check: csv_mock.assert_called_once_with(mock.ANY) if prepare_kwargs: prepare_mock.assert_called_once_with(**prepare_kwargs) rpc_mock.assert_called_once_with(ctxt, method, **expected_kwargs)
def test_detach_volume_vmdk(self): client_factory = self._volumeops._session.vim.client.factory virtual_controller = client_factory.create( 'ns0:VirtualLsiLogicController') virtual_controller.key = 100 virtual_disk = client_factory.create('ns0:VirtualDisk') virtual_disk.controllerKey = virtual_controller.key with test.nested( mock.patch.object(vm_util, 'get_vm_ref', return_value=mock.sentinel.vm_ref), mock.patch.object(self._volumeops, '_get_volume_ref', return_value=mock.sentinel.volume_ref), mock.patch.object(self._volumeops, '_get_vmdk_backed_disk_device', return_value=virtual_disk), mock.patch.object(vm_util, '_get_device_disk_type', return_value='fake-disk-type'), mock.patch.object(self._volumeops, '_consolidate_vmdk_volume'), mock.patch.object(self._volumeops, 'detach_disk_from_vm'), mock.patch.object(self._volumeops, '_update_volume_details'), mock.patch.object( self._volumeops._session, '_call_method', return_value=[ virtual_controller ])) as (get_vm_ref, get_volume_ref, get_vmdk_backed_disk_device, _get_device_disk_type, consolidate_vmdk_volume, detach_disk_from_vm, update_volume_details, session_call_method): connection_info = { 'driver_volume_type': 'vmdk', 'serial': 'volume-fake-id', 'data': { 'volume': 'vm-10', 'volume_id': 'd11a82de-ddaa-448d-b50a-a255a7e61a1e' } } instance = mock.MagicMock(name='fake-name', vm_state=vm_states.ACTIVE) self._volumeops._detach_volume_vmdk(connection_info, instance) get_vm_ref.assert_called_once_with(self._volumeops._session, instance) get_volume_ref.assert_called_once_with( connection_info['data']['volume']) get_vmdk_backed_disk_device.assert_called_once_with( mock.sentinel.vm_ref, connection_info['data']) adapter_type = vm_util.CONTROLLER_TO_ADAPTER_TYPE.get( virtual_controller.__class__.__name__) consolidate_vmdk_volume.assert_called_once_with( instance, mock.sentinel.vm_ref, virtual_disk, mock.sentinel.volume_ref, adapter_type=adapter_type, disk_type='fake-disk-type') detach_disk_from_vm.assert_called_once_with( mock.sentinel.vm_ref, instance, virtual_disk) update_volume_details.assert_called_once_with( mock.sentinel.vm_ref, connection_info['data']['volume_id'], "")
def _test_attach_volume_vmdk(self, adapter_type=None): connection_info = { 'driver_volume_type': constants.DISK_FORMAT_VMDK, 'serial': 'volume-fake-id', 'data': { 'volume': 'vm-10', 'volume_id': 'volume-fake-id' } } vm_ref = 'fake-vm-ref' volume_device = mock.MagicMock() volume_device.backing.fileName = 'fake-path' default_adapter_type = constants.DEFAULT_ADAPTER_TYPE disk_type = constants.DEFAULT_DISK_TYPE disk_uuid = 'e97f357b-331e-4ad1-b726-89be048fb811' backing = mock.Mock(uuid=disk_uuid) device = mock.Mock(backing=backing) vmdk_info = vm_util.VmdkInfo('fake-path', default_adapter_type, disk_type, 1024, device) adapter_type = adapter_type or default_adapter_type if adapter_type == constants.ADAPTER_TYPE_IDE: vm_state = 'PoweredOff' else: vm_state = 'PoweredOn' with test.nested( mock.patch.object(vm_util, 'get_vm_ref', return_value=vm_ref), mock.patch.object(self._volumeops, '_get_volume_ref'), mock.patch.object(vm_util, 'get_vmdk_info', return_value=vmdk_info), mock.patch.object(self._volumeops, 'attach_disk_to_vm'), mock.patch.object(self._volumeops, '_update_volume_details'), mock.patch.object( vm_util, 'get_vm_state', return_value=vm_state)) as (get_vm_ref, get_volume_ref, get_vmdk_info, attach_disk_to_vm, update_volume_details, get_vm_state): self._volumeops.attach_volume(connection_info, self._instance, adapter_type) get_vm_ref.assert_called_once_with(self._volumeops._session, self._instance) get_volume_ref.assert_called_once_with( connection_info['data']['volume']) self.assertTrue(get_vmdk_info.called) attach_disk_to_vm.assert_called_once_with( vm_ref, self._instance, adapter_type, constants.DISK_TYPE_PREALLOCATED, vmdk_path='fake-path') update_volume_details.assert_called_once_with( vm_ref, connection_info['data']['volume_id'], disk_uuid) if adapter_type == constants.ADAPTER_TYPE_IDE: get_vm_state.assert_called_once_with(self._volumeops._session, self._instance) else: self.assertFalse(get_vm_state.called)
def _shelve_instance(self, shelved_offload_time, mock_notify, mock_notify_instance_usage, mock_get_power_state, mock_snapshot, mock_power_off, mock_terminate, mock_get_bdms, clean_shutdown=True): mock_get_power_state.return_value = 123 CONF.set_override('shelved_offload_time', shelved_offload_time) host = 'fake-mini' instance = self._create_fake_instance_obj(params={'host': host}) image_id = 'fake_image_id' host = 'fake-mini' self.useFixture(utils_fixture.TimeFixture()) instance.task_state = task_states.SHELVING instance.save() fake_bdms = None if shelved_offload_time == 0: fake_bdms = objects.BlockDeviceMappingList() mock_get_bdms.return_value = fake_bdms tracking = {'last_state': instance.vm_state} def check_save(expected_task_state=None): self.assertEqual(123, instance.power_state) if tracking['last_state'] == vm_states.ACTIVE: if CONF.shelved_offload_time == 0: self.assertEqual(task_states.SHELVING_OFFLOADING, instance.task_state) else: self.assertIsNone(instance.task_state) self.assertEqual(vm_states.SHELVED, instance.vm_state) self.assertEqual([task_states.SHELVING, task_states.SHELVING_IMAGE_UPLOADING], expected_task_state) self.assertIn('shelved_at', instance.system_metadata) self.assertEqual(image_id, instance.system_metadata['shelved_image_id']) self.assertEqual(host, instance.system_metadata['shelved_host']) tracking['last_state'] = instance.vm_state elif (tracking['last_state'] == vm_states.SHELVED and CONF.shelved_offload_time == 0): self.assertIsNone(instance.task_state) self.assertEqual(vm_states.SHELVED_OFFLOADED, instance.vm_state) self.assertEqual([task_states.SHELVING, task_states.SHELVING_OFFLOADING], expected_task_state) tracking['last_state'] = instance.vm_state elif (tracking['last_state'] == vm_states.SHELVED_OFFLOADED and CONF.shelved_offload_time == 0): self.assertIsNone(instance.host) self.assertIsNone(instance.node) self.assertIsNone(expected_task_state) else: self.fail('Unexpected save!') with test.nested( mock.patch.object(instance, 'save'), mock.patch.object(self.compute.network_api, 'cleanup_instance_network_on_host')) as ( mock_save, mock_cleanup ): mock_save.side_effect = check_save self.compute.shelve_instance(self.context, instance, image_id=image_id, clean_shutdown=clean_shutdown) mock_notify.assert_has_calls([ mock.call(self.context, instance, 'fake-mini', action='shelve', phase='start', bdms=fake_bdms), mock.call(self.context, instance, 'fake-mini', action='shelve', phase='end', bdms=fake_bdms)]) # prepare expect call lists mock_notify_instance_usage_call_list = [ mock.call(self.context, instance, 'shelve.start'), mock.call(self.context, instance, 'shelve.end')] mock_power_off_call_list = [] mock_get_power_state_call_list = [ mock.call(self.context, instance)] mock_cleanup_call_list = [] if clean_shutdown: mock_power_off_call_list.append( mock.call(instance, CONF.shutdown_timeout, CONF.compute.shutdown_retry_interval)) else: mock_power_off_call_list.append(mock.call(instance, 0, 0)) if CONF.shelved_offload_time == 0: mock_notify_instance_usage_call_list.extend([ mock.call(self.context, instance, 'shelve_offload.start'), mock.call(self.context, instance, 'shelve_offload.end')]) mock_power_off_call_list.append(mock.call(instance, 0, 0)) mock_get_power_state_call_list.append(mock.call(self.context, instance)) # instance.host is replaced with host because # original instance.host is clear after # ComputeManager.shelve_instance execute with # shelved_offload_time == 0 mock_cleanup_call_list.append(mock.call(self.context, instance, host)) mock_notify_instance_usage.assert_has_calls( mock_notify_instance_usage_call_list) mock_power_off.assert_has_calls(mock_power_off_call_list) mock_cleanup.assert_has_calls(mock_cleanup_call_list) mock_snapshot.assert_called_once_with(self.context, instance, 'fake_image_id', mock.ANY) mock_get_power_state.assert_has_calls(mock_get_power_state_call_list) if CONF.shelved_offload_time == 0: self.assertTrue(mock_terminate.called)
def _test_compute_api(self, method, rpc_method, expected_args=None, **kwargs): ctxt = context.RequestContext('fake_user', 'fake_project') rpcapi = kwargs.pop('rpcapi_class', compute_rpcapi.ComputeAPI)() self.assertIsNotNone(rpcapi.router) self.assertEqual(rpcapi.router.target.topic, compute_rpcapi.RPC_TOPIC) # This test wants to run the real prepare function, so must use # a real client object default_client = rpcapi.router.default_client orig_prepare = default_client.prepare base_version = rpcapi.router.target.version expected_version = kwargs.pop('version', base_version) prepare_extra_kwargs = {} cm_timeout = kwargs.pop('call_monitor_timeout', None) timeout = kwargs.pop('timeout', None) if cm_timeout: prepare_extra_kwargs['call_monitor_timeout'] = cm_timeout if timeout: prepare_extra_kwargs['timeout'] = timeout expected_kwargs = kwargs.copy() if expected_args: expected_kwargs.update(expected_args) if 'host_param' in expected_kwargs: expected_kwargs['host'] = expected_kwargs.pop('host_param') else: expected_kwargs.pop('host', None) cast_and_call = ['confirm_resize', 'stop_instance'] if rpc_method == 'call' and method in cast_and_call: if method == 'confirm_resize': kwargs['cast'] = False else: kwargs['do_cast'] = False if 'host' in kwargs: host = kwargs['host'] elif 'instances' in kwargs: host = kwargs['instances'][0]['host'] elif 'destination' in kwargs: host = expected_kwargs.pop('destination') else: host = kwargs['instance']['host'] if method == 'rebuild_instance' and 'node' in expected_kwargs: expected_kwargs['scheduled_node'] = expected_kwargs.pop('node') with test.nested( mock.patch.object(default_client, rpc_method), mock.patch.object(default_client, 'prepare'), mock.patch.object(default_client, 'can_send_version'), ) as (rpc_mock, prepare_mock, csv_mock): prepare_mock.return_value = default_client if '_return_value' in kwargs: rpc_mock.return_value = kwargs.pop('_return_value') del expected_kwargs['_return_value'] elif rpc_method == 'call': rpc_mock.return_value = 'foo' else: rpc_mock.return_value = None csv_mock.side_effect = ( lambda v: orig_prepare(version=v).can_send_version()) retval = getattr(rpcapi, method)(ctxt, **kwargs) self.assertEqual(retval, rpc_mock.return_value) prepare_mock.assert_called_once_with(version=expected_version, server=host, **prepare_extra_kwargs) rpc_mock.assert_called_once_with(ctxt, method, **expected_kwargs)
def _test_create_volume_backed_image_with_metadata_from_volume( self, extra_metadata=None): def _fake_id(x): return '%s-%s-%s-%s' % (x * 8, x * 4, x * 4, x * 12) body = dict(createImage=dict(name='snapshot_of_volume_backed')) if extra_metadata: body['createImage']['metadata'] = extra_metadata image_service = glance.get_default_image_service() def fake_block_device_mapping_get_all_by_instance(context, inst_id, use_slave=False): return [fake_block_device.FakeDbBlockDeviceDict( {'volume_id': _fake_id('a'), 'source_type': 'snapshot', 'destination_type': 'volume', 'volume_size': 1, 'device_name': 'vda', 'snapshot_id': 1, 'boot_index': 0, 'delete_on_termination': False, 'no_device': None})] self.stub_out('nova.db.block_device_mapping_get_all_by_instance', fake_block_device_mapping_get_all_by_instance) instance = fakes.fake_instance_get( image_ref='', vm_state=vm_states.ACTIVE, root_device_name='/dev/vda', system_metadata={'image_test_key1': 'test_value1', 'image_test_key2': 'test_value2'}) self.stub_out('nova.db.instance_get_by_uuid', instance) volume = dict(id=_fake_id('a'), size=1, host='fake', display_description='fake') snapshot = dict(id=_fake_id('d')) with test.nested( mock.patch.object( self.controller.compute_api.volume_api, 'get_absolute_limits', return_value={'totalSnapshotsUsed': 0, 'maxTotalSnapshots': 10}), mock.patch.object(self.controller.compute_api.compute_rpcapi, 'quiesce_instance', side_effect=exception.InstanceQuiesceNotSupported( instance_id='fake', reason='test')), mock.patch.object(self.controller.compute_api.volume_api, 'get', return_value=volume), mock.patch.object(self.controller.compute_api.volume_api, 'create_snapshot_force', return_value=snapshot), ) as (mock_get_limits, mock_quiesce, mock_vol_get, mock_vol_create): response = self.controller._action_create_image(self.req, FAKE_UUID, body=body) location = response.headers['Location'] image_id = location.replace(self.image_base_url, '') image = image_service.show(None, image_id) properties = image['properties'] self.assertEqual(properties['test_key1'], 'test_value1') self.assertEqual(properties['test_key2'], 'test_value2') if extra_metadata: for key, val in extra_metadata.items(): self.assertEqual(properties[key], val) mock_quiesce.assert_called_once_with(mock.ANY, mock.ANY) mock_vol_get.assert_called_once_with(mock.ANY, volume['id']) mock_vol_create.assert_called_once_with(mock.ANY, volume['id'], mock.ANY, mock.ANY)
def test_disconnect_volume_called_during_pre_live_migration_failure(self): server = { 'name': 'test', 'imageRef': '', 'flavorRef': 1, 'networks': 'none', 'host': 'src', 'block_device_mapping_v2': [{ 'source_type': 'volume', 'destination_type': 'volume', 'boot_index': 0, 'uuid': nova_fixtures.CinderFixture.IMAGE_BACKED_VOL }] } with test.nested( mock.patch.object(self.computes['src'].driver, 'get_volume_connector'), mock.patch.object(self.computes['src'].driver, '_connect_volume'), ) as (mock_src_connector, mock_src_connect): server = self.api.post_server({'server': server}) self._wait_for_state_change(server, 'ACTIVE') # Assert that we called the src connector and connect mocks mock_src_connector.assert_called_once() mock_src_connect.assert_called_once() # Fetch the connection_info from the src ctxt = context.get_admin_context() bdm = objects.BlockDeviceMapping.get_by_volume_id( ctxt, nova_fixtures.CinderFixture.IMAGE_BACKED_VOL, instance_uuid=server['id']) src_connection_info = jsonutils.loads(bdm.connection_info) with test.nested( mock.patch.object(self.computes['dest'].driver, 'get_volume_connector'), mock.patch.object(self.computes['dest'].driver, '_connect_volume'), mock.patch.object(self.computes['dest'].driver, '_disconnect_volume'), mock.patch('nova.volume.cinder.API.attachment_create', side_effect=test.TestingException)) as ( mock_dest_connector, mock_dest_connect, mock_dest_disconnect, mock_attachment_create): # Attempt to live migrate and ensure it is marked as failed self._live_migrate(server, 'failed') # Assert that we called the dest connector and attachment_create mocks mock_dest_connector.assert_called_once() mock_attachment_create.assert_called_once() # Assert that connect_volume hasn't been called on the dest mock_dest_connect.assert_not_called() # FIXME(lyarwood): This is bug #1899835, disconnect_volume shouldn't be # called on the destination host without connect_volume first being # called and especially using with the connection_info from the source mock_dest_disconnect.assert_called_with(mock.ANY, src_connection_info, mock.ANY, encryption=mock.ANY)
def _do_test_create_volume_backed_image( self, extra_properties, mock_vol_create_side_effect=None): def _fake_id(x): return '%s-%s-%s-%s' % (x * 8, x * 4, x * 4, x * 12) body = dict(createImage=dict(name='snapshot_of_volume_backed')) if extra_properties: body['createImage']['metadata'] = extra_properties image_service = glance.get_default_image_service() bdm = [dict(volume_id=_fake_id('a'), volume_size=1, device_name='vda', delete_on_termination=False)] def fake_block_device_mapping_get_all_by_instance(context, inst_id, use_slave=False): return [fake_block_device.FakeDbBlockDeviceDict( {'volume_id': _fake_id('a'), 'source_type': 'snapshot', 'destination_type': 'volume', 'volume_size': 1, 'device_name': 'vda', 'snapshot_id': 1, 'boot_index': 0, 'delete_on_termination': False, 'no_device': None})] self.stub_out('nova.db.block_device_mapping_get_all_by_instance', fake_block_device_mapping_get_all_by_instance) system_metadata = dict(image_kernel_id=_fake_id('b'), image_ramdisk_id=_fake_id('c'), image_root_device_name='/dev/vda', image_block_device_mapping=str(bdm), image_container_format='ami') instance = fakes.fake_instance_get(image_ref=uuids.fake, vm_state=vm_states.ACTIVE, root_device_name='/dev/vda', system_metadata=system_metadata) self.stub_out('nova.db.instance_get_by_uuid', instance) volume = dict(id=_fake_id('a'), size=1, host='fake', display_description='fake') snapshot = dict(id=_fake_id('d')) with test.nested( mock.patch.object( self.controller.compute_api.volume_api, 'get_absolute_limits', return_value={'totalSnapshotsUsed': 0, 'maxTotalSnapshots': 10}), mock.patch.object(self.controller.compute_api.compute_rpcapi, 'quiesce_instance', side_effect=exception.InstanceQuiesceNotSupported( instance_id='fake', reason='test')), mock.patch.object(self.controller.compute_api.volume_api, 'get', return_value=volume), mock.patch.object(self.controller.compute_api.volume_api, 'create_snapshot_force', return_value=snapshot), ) as (mock_get_limits, mock_quiesce, mock_vol_get, mock_vol_create): if mock_vol_create_side_effect: mock_vol_create.side_effect = mock_vol_create_side_effect response = self.controller._action_create_image(self.req, FAKE_UUID, body=body) location = response.headers['Location'] image_id = location.replace(self.image_url or self.image_api.generate_image_url('', self.context), '') image = image_service.show(None, image_id) self.assertEqual(image['name'], 'snapshot_of_volume_backed') properties = image['properties'] self.assertEqual(properties['kernel_id'], _fake_id('b')) self.assertEqual(properties['ramdisk_id'], _fake_id('c')) self.assertEqual(properties['root_device_name'], '/dev/vda') self.assertTrue(properties['bdm_v2']) bdms = properties['block_device_mapping'] self.assertEqual(len(bdms), 1) self.assertEqual(bdms[0]['boot_index'], 0) self.assertEqual(bdms[0]['source_type'], 'snapshot') self.assertEqual(bdms[0]['destination_type'], 'volume') self.assertEqual(bdms[0]['snapshot_id'], snapshot['id']) self.assertEqual('/dev/vda', bdms[0]['device_name']) for fld in ('connection_info', 'id', 'instance_uuid'): self.assertNotIn(fld, bdms[0]) for k in extra_properties.keys(): self.assertEqual(properties[k], extra_properties[k]) mock_quiesce.assert_called_once_with(mock.ANY, mock.ANY) mock_vol_get.assert_called_once_with(mock.ANY, volume['id']) mock_vol_create.assert_called_once_with(mock.ANY, volume['id'], mock.ANY, mock.ANY)
def _test_spawn(self, mock_copy_virtual_disk, mock_power_on_instance, mock_get_and_set_vnc_config, mock_enlist_image, mock_set_machine_id, mock_mkdir, mock_create_vm, mock_get_create_spec, mock_is_neutron, mock_get_vif_info, mock_get_datacenter_ref_and_name, mock_get_datastore, mock_configure_config_drive, mock_update_vnic_index, mock_create_folders, block_device_info=None, extra_specs=None, config_drive=False): if extra_specs is None: extra_specs = vm_util.ExtraSpecs() image_size = (self._instance.root_gb) * units.Gi / 2 image = { 'id': self._image_id, 'disk_format': 'vmdk', 'size': image_size, } image = objects.ImageMeta.from_dict(image) image_info = images.VMwareImage( image_id=self._image_id, file_size=image_size) vi = self._vmops._get_vm_config_info( self._instance, image_info, extra_specs) self._vmops._volumeops = mock.Mock() network_info = mock.Mock() mock_get_datastore.return_value = self._ds mock_get_datacenter_ref_and_name.return_value = self._dc_info mock_call_method = mock.Mock(return_value='fake_task') if extra_specs is None: extra_specs = vm_util.ExtraSpecs() with test.nested( mock.patch.object(self._session, '_wait_for_task'), mock.patch.object(self._session, '_call_method', mock_call_method), mock.patch.object(uuidutils, 'generate_uuid', return_value='tmp-uuid'), mock.patch.object(images, 'fetch_image'), mock.patch('nova.image.api.API.get'), mock.patch.object(vutil, 'get_inventory_path', return_value=self._dc_info.name), mock.patch.object(self._vmops, '_get_extra_specs', return_value=extra_specs), mock.patch.object(self._vmops, '_get_instance_metadata', return_value='fake-metadata') ) as (_wait_for_task, _call_method, _generate_uuid, _fetch_image, _get_img_svc, _get_inventory_path, _get_extra_specs, _get_instance_metadata): self._vmops.spawn(self._context, self._instance, image, injected_files='fake_files', admin_password='******', network_info=network_info, block_device_info=block_device_info) mock_is_neutron.assert_called_once_with() self.assertEqual(2, mock_mkdir.call_count) mock_get_vif_info.assert_called_once_with( self._session, self._cluster.obj, False, constants.DEFAULT_VIF_MODEL, network_info) mock_get_create_spec.assert_called_once_with( self._session.vim.client.factory, self._instance, 'fake_ds', [], extra_specs, constants.DEFAULT_OS_TYPE, profile_spec=None, metadata='fake-metadata') mock_create_vm.assert_called_once_with( self._session, self._instance, 'fake_vm_folder', 'fake_create_spec', self._cluster.resourcePool) mock_get_and_set_vnc_config.assert_called_once_with( self._session.vim.client.factory, self._instance, 'fake_vm_ref') mock_set_machine_id.assert_called_once_with( self._session.vim.client.factory, self._instance, network_info, vm_ref='fake_vm_ref') mock_power_on_instance.assert_called_once_with( self._session, self._instance, vm_ref='fake_vm_ref') if (block_device_info and 'block_device_mapping' in block_device_info): bdms = block_device_info['block_device_mapping'] for bdm in bdms: mock_attach_root = ( self._vmops._volumeops.attach_root_volume) mock_attach = self._vmops._volumeops.attach_volume adapter_type = bdm.get('disk_bus') or vi.ii.adapter_type if bdm.get('boot_index') == 0: mock_attach_root.assert_any_call( bdm['connection_info'], self._instance, self._ds.ref, adapter_type) else: mock_attach.assert_any_call( bdm['connection_info'], self._instance, self._ds.ref, adapter_type) mock_enlist_image.assert_called_once_with( self._image_id, self._ds, self._dc_info.ref) upload_file_name = 'vmware_temp/tmp-uuid/%s/%s-flat.vmdk' % ( self._image_id, self._image_id) _fetch_image.assert_called_once_with( self._context, self._instance, self._session._host, self._session._port, self._dc_info.name, self._ds.name, upload_file_name, cookies='Fake-CookieJar') self.assertGreater(len(_wait_for_task.mock_calls), 0) _get_inventory_path.call_count = 1 extras = None if block_device_info and ('ephemerals' in block_device_info or 'swap' in block_device_info): extras = ['CreateVirtualDisk_Task'] self._verify_spawn_method_calls(_call_method, extras) dc_ref = 'fake_dc_ref' source_file = six.text_type('[fake_ds] vmware_base/%s/%s.vmdk' % (self._image_id, self._image_id)) dest_file = six.text_type('[fake_ds] vmware_base/%s/%s.%d.vmdk' % (self._image_id, self._image_id, self._instance['root_gb'])) # TODO(dims): add more tests for copy_virtual_disk after # the disk/image code in spawn gets refactored mock_copy_virtual_disk.assert_called_with(self._session, dc_ref, source_file, dest_file) if config_drive: mock_configure_config_drive.assert_called_once_with( self._instance, 'fake_vm_ref', self._dc_info, self._ds, 'fake_files', 'password', network_info) mock_update_vnic_index.assert_called_once_with( self._context, self._instance, network_info)