diff options
285 files changed, 2102 insertions, 2379 deletions
diff --git a/nova/tests/hyperv/README.rst b/nova/tests/hyperv/README.rst deleted file mode 100644 index c7ba16046..000000000 --- a/nova/tests/hyperv/README.rst +++ /dev/null @@ -1,83 +0,0 @@ -===================================== -OpenStack Hyper-V Nova Testing Architecture -===================================== - -The Hyper-V Nova Compute plugin uses Windows Management Instrumentation (WMI) -as the main API for hypervisor related operations. -WMI has a database / procedural oriented nature that can become difficult to -test with a traditional static mock / stub based unit testing approach. - -The included Hyper-V testing framework has been developed with the -following goals: - -1) Dynamic mock generation. -2) Decoupling. No dependencies on WMI or any other module. - The tests are designed to work with mocked objects in all cases, including - OS-dependent (e.g. wmi, os, subprocess) and non-deterministic - (e.g. time, uuid) modules -3) Transparency. Mocks and real objects can be swapped via DI - or monkey patching. -4) Platform independence. -5) Tests need to be executed against the real object or against the mocks - with a simple configuration switch. Development efforts can highly - benefit from this feature. -6) It must be possible to change a mock's behavior without running the tests - against the hypervisor (e.g. by manually adding a value / return value). - -The tests included in this package include dynamically generated mock objects, -based on the recording of the attribute values and invocations on the -real WMI objects and other OS dependent features. -The generated mock objects are serialized in the nova/tests/hyperv/stubs -directory as gzipped pickled objects. - -An environment variable controls the execution mode of the tests. - -Recording mode: - -NOVA_GENERATE_TEST_MOCKS=True -Tests are executed on the hypervisor (without mocks), and mock objects are -generated. - -Replay mode: - -NOVA_GENERATE_TEST_MOCKS= -Tests are executed with the existing mock objects (default). - -Mock generation is performed by nova.tests.hyperv.mockproxy.MockProxy. -Instances of this class wrap objects that need to be mocked and act as a -delegate on the wrapped object by leveraging Python's __getattr__ feature. -Attribute values and method call return values are recorded at each access. -Objects returned by attributes and method invocations are wrapped in a -MockProxy consistently. -From a caller perspective, the MockProxy is completely transparent, -with the exception of calls to the type(...) builtin function. - -At the end of the test, a mock is generated by each MockProxy by calling -the get_mock() method. A mock is represented by an instance of the -nova.tests.hyperv.mockproxy.Mock class. - -The Mock class task consists of replicating the behaviour of the mocked -objects / modules by returning the same values in the same order, for example: - -def check_path(path): - if not os.path.exists(path): - os.makedirs(path) - -check_path(path) -# The second time os.path.exists returns True -check_path(path) - -The injection of MockProxy / Mock instances is performed by the -nova.tests.hyperv.basetestcase.BaseTestCase class in the setUp() -method via selective monkey patching. -Mocks are serialized in tearDown() during recording. - -The actual Hyper-V test case inherits from BaseTestCase: -nova.tests.hyperv.test_hypervapi.HyperVAPITestCase - - -Future directions: - -1) Replace the pickled files with a more generic serialization option (e.g. json) -2) Add methods to statically extend the mocks (e.g. method call return values) -3) Extend an existing framework, e.g. mox diff --git a/nova/tests/hyperv/__init__.py b/nova/tests/hyperv/__init__.py index e69de29bb..090fc0639 100644 --- a/nova/tests/hyperv/__init__.py +++ b/nova/tests/hyperv/__init__.py @@ -0,0 +1,16 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Cloudbase Solutions Srl +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. diff --git a/nova/tests/hyperv/basetestcase.py b/nova/tests/hyperv/basetestcase.py deleted file mode 100644 index c4f6cf95f..000000000 --- a/nova/tests/hyperv/basetestcase.py +++ /dev/null @@ -1,105 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 Cloudbase Solutions Srl -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -TestCase for MockProxy based tests and related classes. -""" - -import gzip -import os -import pickle -import sys - -from nova import test -from nova.tests.hyperv import mockproxy - -gen_test_mocks_key = 'NOVA_GENERATE_TEST_MOCKS' - - -class BaseTestCase(test.TestCase): - """TestCase for MockProxy based tests.""" - - def run(self, result=None): - self._currentResult = result - super(BaseTestCase, self).run(result) - - def setUp(self): - super(BaseTestCase, self).setUp() - self._mps = {} - - def tearDown(self): - super(BaseTestCase, self).tearDown() - - # python-subunit will wrap test results with a decorator. - # Need to access the decorated member of results to get the - # actual test result when using python-subunit. - if hasattr(self._currentResult, 'decorated'): - result = self._currentResult.decorated - else: - result = self._currentResult - has_errors = len([test for (test, msgs) in result.errors - if test.id() == self.id()]) > 0 - failed = len([test for (test, msgs) in result.failures - if test.id() == self.id()]) > 0 - - if not has_errors and not failed: - self._save_mock_proxies() - - def _save_mock(self, name, mock): - path = self._get_stub_file_path(self.id(), name) - pickle.dump(mock, gzip.open(path, 'wb')) - - def _get_stub_file_path(self, test_name, mock_name): - # test naming differs between platforms - prefix = 'nova.tests.' - if test_name.startswith(prefix): - test_name = test_name[len(prefix):] - file_name = '{0}_{1}.p.gz'.format(test_name, mock_name) - return os.path.join(os.path.dirname(mockproxy.__file__), - "stubs", file_name) - - def _load_mock(self, name): - path = self._get_stub_file_path(self.id(), name) - if os.path.exists(path): - return pickle.load(gzip.open(path, 'rb')) - else: - return None - - def _load_mock_or_create_proxy(self, module_name): - m = None - if not gen_test_mocks_key in os.environ or \ - os.environ[gen_test_mocks_key].lower() \ - not in ['true', 'yes', '1']: - m = self._load_mock(module_name) - else: - __import__(module_name) - module = sys.modules[module_name] - m = mockproxy.MockProxy(module) - self._mps[module_name] = m - return m - - def _inject_mocks_in_modules(self, objects_to_mock, modules_to_test): - for module_name in objects_to_mock: - mp = self._load_mock_or_create_proxy(module_name) - for mt in modules_to_test: - module_local_name = module_name.split('.')[-1] - setattr(mt, module_local_name, mp) - - def _save_mock_proxies(self): - for name, mp in self._mps.items(): - m = mp.get_mock() - if m.has_values(): - self._save_mock(name, m) diff --git a/nova/tests/hyperv/db_fakes.py b/nova/tests/hyperv/db_fakes.py index 16d894df8..e384e909a 100644 --- a/nova/tests/hyperv/db_fakes.py +++ b/nova/tests/hyperv/db_fakes.py @@ -29,35 +29,35 @@ from nova import utils def get_fake_instance_data(name, project_id, user_id): return {'name': name, - 'id': 1, - 'uuid': str(uuid.uuid4()), - 'project_id': project_id, - 'user_id': user_id, - 'image_ref': "1", - 'kernel_id': "1", - 'ramdisk_id': "1", - 'mac_address': "de:ad:be:ef:be:ef", - 'instance_type': - {'name': 'm1.tiny', - 'memory_mb': 512, - 'vcpus': 1, - 'root_gb': 0, - 'flavorid': 1, - 'rxtx_factor': 1} - } + 'id': 1, + 'uuid': str(uuid.uuid4()), + 'project_id': project_id, + 'user_id': user_id, + 'image_ref': "1", + 'kernel_id': "1", + 'ramdisk_id': "1", + 'mac_address': "de:ad:be:ef:be:ef", + 'instance_type': + {'name': 'm1.tiny', + 'memory_mb': 512, + 'vcpus': 1, + 'root_gb': 0, + 'flavorid': 1, + 'rxtx_factor': 1} + } def get_fake_image_data(project_id, user_id): return {'name': 'image1', - 'id': 1, - 'project_id': project_id, - 'user_id': user_id, - 'image_ref': "1", - 'kernel_id': "1", - 'ramdisk_id': "1", - 'mac_address': "de:ad:be:ef:be:ef", - 'instance_type': 'm1.tiny', - } + 'id': 1, + 'project_id': project_id, + 'user_id': user_id, + 'image_ref': "1", + 'kernel_id': "1", + 'ramdisk_id': "1", + 'mac_address': "de:ad:be:ef:be:ef", + 'instance_type': 'm1.tiny', + } def get_fake_volume_info_data(target_portal, volume_id): @@ -72,25 +72,25 @@ def get_fake_volume_info_data(target_portal, volume_id): 'auth_method': 'fake', 'auth_method': 'fake', } -} + } def get_fake_block_device_info(target_portal, volume_id): - return { - 'block_device_mapping': [{'connection_info': { - 'driver_volume_type': 'iscsi', - 'data': {'target_lun': 1, - 'volume_id': volume_id, - 'target_iqn': 'iqn.2010-10.org.openstack:volume-' + - volume_id, - 'target_portal': target_portal, - 'target_discovered': False}}, - 'mount_device': 'vda', - 'delete_on_termination': False}], + return {'block_device_mapping': [{'connection_info': { + 'driver_volume_type': 'iscsi', + 'data': {'target_lun': 1, + 'volume_id': volume_id, + 'target_iqn': + 'iqn.2010-10.org.openstack:volume-' + + volume_id, + 'target_portal': target_portal, + 'target_discovered': False}}, + 'mount_device': 'vda', + 'delete_on_termination': False}], 'root_device_name': None, 'ephemerals': [], 'swap': None - } + } def stub_out_db_instance_api(stubs): @@ -99,11 +99,9 @@ def stub_out_db_instance_api(stubs): INSTANCE_TYPES = { 'm1.tiny': dict(memory_mb=512, vcpus=1, root_gb=0, flavorid=1), 'm1.small': dict(memory_mb=2048, vcpus=1, root_gb=20, flavorid=2), - 'm1.medium': - dict(memory_mb=4096, vcpus=2, root_gb=40, flavorid=3), + 'm1.medium': dict(memory_mb=4096, vcpus=2, root_gb=40, flavorid=3), 'm1.large': dict(memory_mb=8192, vcpus=4, root_gb=80, flavorid=4), - 'm1.xlarge': - dict(memory_mb=16384, vcpus=8, root_gb=160, flavorid=5)} + 'm1.xlarge': dict(memory_mb=16384, vcpus=8, root_gb=160, flavorid=5)} class FakeModel(object): """Stubs out for model.""" @@ -152,7 +150,7 @@ def stub_out_db_instance_api(stubs): 'vcpus': instance_type['vcpus'], 'mac_addresses': [{'address': values['mac_address']}], 'root_gb': instance_type['root_gb'], - } + } return FakeModel(base_options) def fake_network_get_by_instance(context, instance_id): @@ -181,4 +179,4 @@ def stub_out_db_instance_api(stubs): stubs.Set(db, 'instance_type_get_all', fake_instance_type_get_all) stubs.Set(db, 'instance_type_get_by_name', fake_instance_type_get_by_name) stubs.Set(db, 'block_device_mapping_get_all_by_instance', - fake_block_device_mapping_get_all_by_instance) + fake_block_device_mapping_get_all_by_instance) diff --git a/nova/tests/hyperv/fake.py b/nova/tests/hyperv/fake.py new file mode 100644 index 000000000..9890a5462 --- /dev/null +++ b/nova/tests/hyperv/fake.py @@ -0,0 +1,46 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Cloudbase Solutions Srl +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import io +import os + + +class PathUtils(object): + def open(self, path, mode): + return io.BytesIO(b'fake content') + + def get_instances_path(self): + return 'C:\\FakePath\\' + + def get_instance_path(self, instance_name): + return os.path.join(self.get_instances_path(), instance_name) + + def get_vhd_path(self, instance_name): + instance_path = self.get_instance_path(instance_name) + return os.path.join(instance_path, instance_name + ".vhd") + + def get_base_vhd_path(self, image_name): + base_dir = os.path.join(self.get_instances_path(), '_base') + return os.path.join(base_dir, image_name + ".vhd") + + def make_export_path(self, instance_name): + export_folder = os.path.join(self.get_instances_path(), "export", + instance_name) + return export_folder + + def vhd_exists(self, path): + return False diff --git a/nova/tests/hyperv/hypervutils.py b/nova/tests/hyperv/hypervutils.py deleted file mode 100644 index b71e60229..000000000 --- a/nova/tests/hyperv/hypervutils.py +++ /dev/null @@ -1,262 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 Cloudbase Solutions Srl -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Hyper-V classes to be used in testing. -""" - -import sys -import time - -from nova import exception -from nova.virt.hyperv import constants -from nova.virt.hyperv import volumeutilsV2 -from xml.etree import ElementTree - -# Check needed for unit testing on Unix -if sys.platform == 'win32': - import wmi - - -class HyperVUtils(object): - def __init__(self): - self.__conn = None - self.__conn_v2 = None - self.__conn_cimv2 = None - self.__conn_wmi = None - self.__conn_storage = None - self._volumeutils = volumeutilsV2.VolumeUtilsV2( - self._conn_storage, self._conn_wmi) - - @property - def _conn(self): - if self.__conn is None: - self.__conn = wmi.WMI(moniker='//./root/virtualization') - return self.__conn - - @property - def _conn_v2(self): - if self.__conn_v2 is None: - self.__conn_v2 = wmi.WMI(moniker='//./root/virtualization/v2') - return self.__conn_v2 - - @property - def _conn_cimv2(self): - if self.__conn_cimv2 is None: - self.__conn_cimv2 = wmi.WMI(moniker='//./root/cimv2') - return self.__conn_cimv2 - - @property - def _conn_wmi(self): - if self.__conn_wmi is None: - self.__conn_wmi = wmi.WMI(moniker='//./root/wmi') - return self.__conn_wmi - - @property - def _conn_storage(self): - if self.__conn_storage is None: - storage_namespace = '//./Root/Microsoft/Windows/Storage' - self.__conn_storage = wmi.WMI(moniker=storage_namespace) - return self.__conn_storage - - def create_vhd(self, path): - image_service = self._conn.query( - "Select * from Msvm_ImageManagementService")[0] - (job, ret_val) = image_service.CreateDynamicVirtualHardDisk( - Path=path, MaxInternalSize=3 * 1024 * 1024) - - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self._check_job_status(job) - else: - success = (ret_val == 0) - if not success: - raise Exception('Failed to create Dynamic disk %s with error %d' - % (path, ret_val)) - - def _check_job_status(self, jobpath): - """Poll WMI job state for completion.""" - job_wmi_path = jobpath.replace('\\', '/') - job = wmi.WMI(moniker=job_wmi_path) - - while job.JobState == constants.WMI_JOB_STATE_RUNNING: - time.sleep(0.1) - job = wmi.WMI(moniker=job_wmi_path) - return job.JobState == constants.WMI_JOB_STATE_COMPLETED - - def _get_vm(self, vm_name, conn=None): - if conn is None: - conn = self._conn - vml = conn.Msvm_ComputerSystem(ElementName=vm_name) - if not len(vml): - raise exception.InstanceNotFound(instance=vm_name) - return vml[0] - - def remote_vm_exists(self, server, vm_name): - conn = wmi.WMI(moniker='//' + server + '/root/virtualization') - return self._vm_exists(conn, vm_name) - - def vm_exists(self, vm_name): - return self._vm_exists(self._conn, vm_name) - - def _vm_exists(self, conn, vm_name): - return len(conn.Msvm_ComputerSystem(ElementName=vm_name)) > 0 - - def _get_vm_summary(self, vm_name): - vm = self._get_vm(vm_name) - vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0] - vmsettings = vm.associators( - wmi_association_class='Msvm_SettingsDefineState', - wmi_result_class='Msvm_VirtualSystemSettingData') - settings_paths = [v.path_() for v in vmsettings] - return vs_man_svc.GetSummaryInformation([100, 105], - settings_paths)[1][0] - - def get_vm_uptime(self, vm_name): - return self._get_vm_summary(vm_name).UpTime - - def get_vm_state(self, vm_name): - return self._get_vm_summary(vm_name).EnabledState - - def set_vm_state(self, vm_name, req_state): - self._set_vm_state(self._conn, vm_name, req_state) - - def _set_vm_state(self, conn, vm_name, req_state): - vm = self._get_vm(vm_name, conn) - (job, ret_val) = vm.RequestStateChange(req_state) - - success = False - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self._check_job_status(job) - elif ret_val == 0: - success = True - elif ret_val == 32775: - #Invalid state for current operation. Typically means it is - #already in the state requested - success = True - if not success: - raise Exception(_("Failed to change vm state of %(vm_name)s" - " to %(req_state)s") % locals()) - - def get_vm_disks(self, vm_name): - return self._get_vm_disks(self._conn, vm_name) - - def _get_vm_disks(self, conn, vm_name): - vm = self._get_vm(vm_name, conn) - vmsettings = vm.associators( - wmi_result_class='Msvm_VirtualSystemSettingData') - rasds = vmsettings[0].associators( - wmi_result_class='MSVM_ResourceAllocationSettingData') - - disks = [r for r in rasds - if r.ResourceSubType == 'Microsoft Virtual Hard Disk'] - disk_files = [] - for disk in disks: - disk_files.extend([c for c in disk.Connection]) - - volumes = [r for r in rasds - if r.ResourceSubType == 'Microsoft Physical Disk Drive'] - volume_drives = [] - for volume in volumes: - hostResources = volume.HostResource - drive_path = hostResources[0] - volume_drives.append(drive_path) - - dvds = [r for r in rasds - if r.ResourceSubType == 'Microsoft Virtual CD/DVD Disk'] - dvd_files = [] - for dvd in dvds: - dvd_files.extend([c for c in dvd.Connection]) - - return (disk_files, volume_drives, dvd_files) - - def remove_remote_vm(self, server, vm_name): - conn = wmi.WMI(moniker='//' + server + '/root/virtualization') - conn_cimv2 = wmi.WMI(moniker='//' + server + '/root/cimv2') - self._remove_vm(vm_name, conn, conn_cimv2) - - def remove_vm(self, vm_name): - self._remove_vm(vm_name, self._conn, self._conn_cimv2) - - def _remove_vm(self, vm_name, conn, conn_cimv2): - vm = self._get_vm(vm_name, conn) - vs_man_svc = conn.Msvm_VirtualSystemManagementService()[0] - #Stop the VM first. - self._set_vm_state(conn, vm_name, 3) - - (disk_files, volume_drives, dvd_files) = self._get_vm_disks(conn, - vm_name) - - (job, ret_val) = vs_man_svc.DestroyVirtualSystem(vm.path_()) - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self._check_job_status(job) - elif ret_val == 0: - success = True - if not success: - raise Exception(_('Failed to destroy vm %s') % vm_name) - - #Delete associated vhd disk files. - for disk in disk_files + dvd_files: - vhd_file = conn_cimv2.query( - "Select * from CIM_DataFile where Name = '" + - disk.replace("'", "''") + "'")[0] - vhd_file.Delete() - - def _get_target_iqn(self, volume_id): - return 'iqn.2010-10.org.openstack:volume-' + volume_id - - def logout_iscsi_volume_sessions(self, volume_id): - target_iqn = self._get_target_iqn(volume_id) - if (self.iscsi_volume_sessions_exist(volume_id)): - self._volumeutils.logout_storage_target(target_iqn) - - def iscsi_volume_sessions_exist(self, volume_id): - target_iqn = self._get_target_iqn(volume_id) - return len(self._conn_wmi.query( - "SELECT * FROM MSiSCSIInitiator_SessionClass \ - WHERE TargetName='" + target_iqn + "'")) > 0 - - def get_vm_count(self): - return len(self._conn.query( - "Select * from Msvm_ComputerSystem where Description " - "<> 'Microsoft Hosting Computer System'")) - - def get_vm_snapshots_count(self, vm_name): - return len(self._conn.query( - "Select * from Msvm_VirtualSystemSettingData where \ - SettingType = 5 and SystemName = '" + vm_name + "'")) - - def get_vhd_parent_path(self, vhd_path): - - image_man_svc = self._conn.Msvm_ImageManagementService()[0] - - (vhd_info, job_path, ret_val) = \ - image_man_svc.GetVirtualHardDiskInfo(vhd_path) - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self._check_job_status(job_path) - else: - success = (ret_val == 0) - if not success: - raise Exception(_("Failed to get info for disk %s") % - (vhd_path)) - - base_disk_path = None - et = ElementTree.fromstring(vhd_info) - for item in et.findall("PROPERTY"): - if item.attrib["NAME"] == "ParentPath": - base_disk_path = item.find("VALUE").text - break - - return base_disk_path diff --git a/nova/tests/hyperv/mockproxy.py b/nova/tests/hyperv/mockproxy.py deleted file mode 100644 index 513422c13..000000000 --- a/nova/tests/hyperv/mockproxy.py +++ /dev/null @@ -1,272 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 Cloudbase Solutions Srl -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations - -""" -Classes for dynamic generation of mock objects. -""" - -import inspect - - -def serialize_obj(obj): - if isinstance(obj, float): - val = str(round(obj, 10)) - elif isinstance(obj, dict): - d = {} - for k1, v1 in obj.items(): - d[k1] = serialize_obj(v1) - val = str(d) - elif isinstance(obj, list): - l1 = [] - for i1 in obj: - l1.append(serialize_obj(i1)) - val = str(l1) - elif isinstance(obj, tuple): - l1 = () - for i1 in obj: - l1 = l1 + (serialize_obj(i1),) - val = str(l1) - else: - if isinstance(obj, str) or isinstance(obj, unicode): - val = obj - elif hasattr(obj, '__str__') and inspect.ismethod(obj.__str__): - val = str(obj) - else: - val = str(type(obj)) - return val - - -def serialize_args(*args, **kwargs): - """Workaround for float string conversion issues in Python 2.6.""" - return serialize_obj((args, kwargs)) - - -class MockException(Exception): - def __init__(self, message): - super(MockException, self).__init__(message) - - -class Mock(object): - def _get_next_value(self, name): - c = self._access_count.get(name) - if c is None: - c = 0 - else: - c = c + 1 - self._access_count[name] = c - - try: - value = self._values[name][c] - except IndexError as ex: - raise MockException(_('Couldn\'t find invocation num. %(c)d ' - 'of attribute "%(name)s"') % locals()) - return value - - def _get_next_ret_value(self, name, params): - d = self._access_count.get(name) - if d is None: - d = {} - self._access_count[name] = d - c = d.get(params) - if c is None: - c = 0 - else: - c = c + 1 - d[params] = c - - try: - m = self._values[name] - except KeyError as ex: - raise MockException(_('Couldn\'t find attribute "%s"') % (name)) - - try: - value = m[params][c] - except KeyError as ex: - raise MockException(_('Couldn\'t find attribute "%(name)s" ' - 'with arguments "%(params)s"') % locals()) - except IndexError as ex: - raise MockException(_('Couldn\'t find invocation num. %(c)d ' - 'of attribute "%(name)s" with arguments "%(params)s"') - % locals()) - - return value - - def __init__(self, values): - self._values = values - self._access_count = {} - - def has_values(self): - return len(self._values) > 0 - - def __getattr__(self, name): - if name.startswith('__') and name.endswith('__'): - return object.__getattribute__(self, name) - else: - try: - isdict = isinstance(self._values[name], dict) - except KeyError as ex: - raise MockException(_('Couldn\'t find attribute "%s"') - % (name)) - - if isdict: - def newfunc(*args, **kwargs): - params = serialize_args(args, kwargs) - return self._get_next_ret_value(name, params) - return newfunc - else: - return self._get_next_value(name) - - def __str__(self): - return self._get_next_value('__str__') - - def __iter__(self): - return getattr(self._get_next_value('__iter__'), '__iter__')() - - def __len__(self): - return self._get_next_value('__len__') - - def __getitem__(self, key): - return self._get_next_ret_value('__getitem__', str(key)) - - def __call__(self, *args, **kwargs): - params = serialize_args(args, kwargs) - return self._get_next_ret_value('__call__', params) - - -class MockProxy(object): - def __init__(self, wrapped): - self._wrapped = wrapped - self._recorded_values = {} - - def _get_proxy_object(self, obj): - if hasattr(obj, '__dict__') or isinstance(obj, tuple) or \ - isinstance(obj, list) or isinstance(obj, dict): - p = MockProxy(obj) - else: - p = obj - return p - - def __getattr__(self, name): - if name in ['_wrapped']: - return object.__getattribute__(self, name) - else: - attr = getattr(self._wrapped, name) - if inspect.isfunction(attr) or inspect.ismethod(attr) or \ - inspect.isbuiltin(attr): - def newfunc(*args, **kwargs): - result = attr(*args, **kwargs) - p = self._get_proxy_object(result) - params = serialize_args(args, kwargs) - self._add_recorded_ret_value(name, params, p) - return p - return newfunc - elif hasattr(attr, '__dict__') or (hasattr(attr, '__getitem__') - and not (isinstance(attr, str) or isinstance(attr, unicode))): - p = MockProxy(attr) - else: - p = attr - self._add_recorded_value(name, p) - return p - - def __setattr__(self, name, value): - if name in ['_wrapped', '_recorded_values']: - object.__setattr__(self, name, value) - else: - setattr(self._wrapped, name, value) - - def _add_recorded_ret_value(self, name, params, val): - d = self._recorded_values.get(name) - if d is None: - d = {} - self._recorded_values[name] = d - l = d.get(params) - if l is None: - l = [] - d[params] = l - l.append(val) - - def _add_recorded_value(self, name, val): - if not name in self._recorded_values: - self._recorded_values[name] = [] - self._recorded_values[name].append(val) - - def get_mock(self): - values = {} - for k, v in self._recorded_values.items(): - if isinstance(v, dict): - d = {} - values[k] = d - for k1, v1 in v.items(): - l = [] - d[k1] = l - for i1 in v1: - if isinstance(i1, MockProxy): - l.append(i1.get_mock()) - else: - l.append(i1) - else: - l = [] - values[k] = l - for i in v: - if isinstance(i, MockProxy): - l.append(i.get_mock()) - elif isinstance(i, dict): - d = {} - for k1, v1 in v.items(): - if isinstance(v1, MockProxy): - d[k1] = v1.get_mock() - else: - d[k1] = v1 - l.append(d) - elif isinstance(i, list): - l1 = [] - for i1 in i: - if isinstance(i1, MockProxy): - l1.append(i1.get_mock()) - else: - l1.append(i1) - l.append(l1) - else: - l.append(i) - return Mock(values) - - def __str__(self): - s = str(self._wrapped) - self._add_recorded_value('__str__', s) - return s - - def __len__(self): - l = len(self._wrapped) - self._add_recorded_value('__len__', l) - return l - - def __iter__(self): - it = [] - for i in self._wrapped: - it.append(self._get_proxy_object(i)) - self._add_recorded_value('__iter__', it) - return iter(it) - - def __getitem__(self, key): - p = self._get_proxy_object(self._wrapped[key]) - self._add_recorded_ret_value('__getitem__', str(key), p) - return p - - def __call__(self, *args, **kwargs): - c = self._wrapped(*args, **kwargs) - p = self._get_proxy_object(c) - params = serialize_args(args, kwargs) - self._add_recorded_ret_value('__call__', params, p) - return p diff --git a/nova/tests/hyperv/stubs/README.rst b/nova/tests/hyperv/stubs/README.rst deleted file mode 100644 index 150fd3ad1..000000000 --- a/nova/tests/hyperv/stubs/README.rst +++ /dev/null @@ -1,2 +0,0 @@ -Files with extension p.gz are compressed pickle files containing serialized -mocks used during unit testing diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_os.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_os.p.gz Binary files differdeleted file mode 100644 index c65832c57..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_subprocess.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_subprocess.p.gz Binary files differdeleted file mode 100644 index 7076c4868..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_subprocess.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_time.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_time.p.gz Binary files differdeleted file mode 100644 index c251f9d6c..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_uuid.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_uuid.p.gz Binary files differdeleted file mode 100644 index cac08e3d0..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_os.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_os.p.gz Binary files differdeleted file mode 100644 index d6e624bb0..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_subprocess.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_subprocess.p.gz Binary files differdeleted file mode 100644 index bb18f7453..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_subprocess.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_time.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_time.p.gz Binary files differdeleted file mode 100644 index a5f592a74..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_uuid.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_uuid.p.gz Binary files differdeleted file mode 100644 index 4bebe0e72..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_wmi.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_wmi.p.gz Binary files differdeleted file mode 100644 index 29a610f36..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_wmi.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_wmi.p.gz Binary files differdeleted file mode 100644 index ca92ece00..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_attach_volume_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_boot_from_volume_subprocess.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_boot_from_volume_subprocess.p.gz Binary files differdeleted file mode 100644 index 58269455d..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_boot_from_volume_subprocess.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_boot_from_volume_time.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_boot_from_volume_time.p.gz Binary files differdeleted file mode 100644 index 97cd7e62b..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_boot_from_volume_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_boot_from_volume_uuid.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_boot_from_volume_uuid.p.gz Binary files differdeleted file mode 100644 index 708197430..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_boot_from_volume_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_boot_from_volume_wmi.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_boot_from_volume_wmi.p.gz Binary files differdeleted file mode 100644 index d5eb4d746..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_boot_from_volume_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_detach_volume_os.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_detach_volume_os.p.gz Binary files differdeleted file mode 100644 index d8c63d8ad..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_detach_volume_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_detach_volume_subprocess.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_detach_volume_subprocess.p.gz Binary files differdeleted file mode 100644 index d0b27d201..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_detach_volume_subprocess.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_detach_volume_time.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_detach_volume_time.p.gz Binary files differdeleted file mode 100644 index 657379cec..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_detach_volume_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_detach_volume_uuid.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_detach_volume_uuid.p.gz Binary files differdeleted file mode 100644 index 8bf58ef5c..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_detach_volume_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_detach_volume_wmi.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_detach_volume_wmi.p.gz Binary files differdeleted file mode 100644 index c20281811..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_detach_volume_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_os.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_os.p.gz Binary files differdeleted file mode 100644 index a198af844..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_time.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_time.p.gz Binary files differdeleted file mode 100644 index 749eabe40..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_uuid.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_uuid.p.gz Binary files differdeleted file mode 100644 index c40e6f995..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_os.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_os.p.gz Binary files differdeleted file mode 100644 index c67dc9271..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_time.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_time.p.gz Binary files differdeleted file mode 100644 index 0d671fc18..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_uuid.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_uuid.p.gz Binary files differdeleted file mode 100644 index 66583beb1..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_wmi.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_wmi.p.gz Binary files differdeleted file mode 100644 index efdef819f..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_wmi.p.gz b/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_wmi.p.gz Binary files differdeleted file mode 100644 index 5edd6f147..000000000 --- a/nova/tests/hyperv/stubs/nova.tests.test_hypervapi.HyperVAPITestCase.test_live_migration_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_nova.utils.p.gz Binary files differdeleted file mode 100644 index f968e2af5..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index bd5ced9f8..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_os.p.gz Binary files differdeleted file mode 100644 index a48a21ca9..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_shutil.p.gz Binary files differdeleted file mode 100644 index c662b602a..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_subprocess.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_subprocess.p.gz Binary files differdeleted file mode 100644 index 6a692b3d8..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_subprocess.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_time.p.gz Binary files differdeleted file mode 100644 index f2ae56be1..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_uuid.p.gz Binary files differdeleted file mode 100644 index 2d24523aa..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_nova.utils.p.gz Binary files differdeleted file mode 100644 index aca0d6f0c..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index bbeec53df..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_os.p.gz Binary files differdeleted file mode 100644 index 3bf9bd13a..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_shutil.p.gz Binary files differdeleted file mode 100644 index 62e3fa329..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_subprocess.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_subprocess.p.gz Binary files differdeleted file mode 100644 index 36970348a..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_subprocess.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_time.p.gz Binary files differdeleted file mode 100644 index 8db997abf..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_uuid.p.gz Binary files differdeleted file mode 100644 index 73f90ac2b..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_wmi.p.gz Binary files differdeleted file mode 100644 index 3ae9a6f46..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_with_target_connection_failure_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_wmi.p.gz Binary files differdeleted file mode 100644 index 5b851f9b7..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_attach_volume_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_nova.utils.p.gz Binary files differdeleted file mode 100644 index 7a1c47449..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index 48583265e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_shutil.p.gz Binary files differdeleted file mode 100644 index 90d6a2ca6..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_subprocess.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_subprocess.p.gz Binary files differdeleted file mode 100644 index 3b17cc74f..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_subprocess.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_time.p.gz Binary files differdeleted file mode 100644 index 162f52457..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_uuid.p.gz Binary files differdeleted file mode 100644 index f88f8bc86..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_wmi.p.gz Binary files differdeleted file mode 100644 index f671dc247..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_boot_from_volume_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_nova.utils.p.gz Binary files differdeleted file mode 100644 index 37892d051..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index 9aec45796..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_os.p.gz Binary files differdeleted file mode 100644 index ffc21536e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_shutil.p.gz Binary files differdeleted file mode 100644 index b47c49202..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_time.p.gz Binary files differdeleted file mode 100644 index 78e4292b6..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_uuid.p.gz Binary files differdeleted file mode 100644 index 5bc7602a8..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_wmi.p.gz Binary files differdeleted file mode 100644 index 9ba025e55..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_destroy_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_nova.utils.p.gz Binary files differdeleted file mode 100644 index 3341bca28..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index 56cb9d103..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_os.p.gz Binary files differdeleted file mode 100644 index 81205e04d..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_shutil.p.gz Binary files differdeleted file mode 100644 index 9d1311341..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_subprocess.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_subprocess.p.gz Binary files differdeleted file mode 100644 index a151a99b4..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_subprocess.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_time.p.gz Binary files differdeleted file mode 100644 index b1d0b0f3a..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_uuid.p.gz Binary files differdeleted file mode 100644 index c2985c424..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_wmi.p.gz Binary files differdeleted file mode 100644 index 2c4901c9f..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_detach_volume_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_available_resource_ctypes.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_available_resource_ctypes.p.gz Binary files differdeleted file mode 100644 index 2481a7b3e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_available_resource_ctypes.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_available_resource_multiprocessing.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_available_resource_multiprocessing.p.gz Binary files differdeleted file mode 100644 index 61cbc1854..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_available_resource_multiprocessing.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_available_resource_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_available_resource_os.p.gz Binary files differdeleted file mode 100644 index 09b86b24e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_available_resource_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_available_resource_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_available_resource_shutil.p.gz Binary files differdeleted file mode 100644 index ba89bfd7e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_available_resource_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_available_resource_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_available_resource_wmi.p.gz Binary files differdeleted file mode 100644 index cfce8c10a..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_available_resource_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_host_stats_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_host_stats_os.p.gz Binary files differdeleted file mode 100644 index 6092f36ab..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_host_stats_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_host_stats_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_host_stats_shutil.p.gz Binary files differdeleted file mode 100644 index 010c07e56..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_host_stats_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_host_stats_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_host_stats_wmi.p.gz Binary files differdeleted file mode 100644 index 9d3adec48..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_host_stats_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_nova.utils.p.gz Binary files differdeleted file mode 100644 index 995dde1b5..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index 12d18d12e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_os.p.gz Binary files differdeleted file mode 100644 index 64c756ffa..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_shutil.p.gz Binary files differdeleted file mode 100644 index d2cefdc37..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_time.p.gz Binary files differdeleted file mode 100644 index 9fdef3b90..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_uuid.p.gz Binary files differdeleted file mode 100644 index c34d2308b..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_wmi.p.gz Binary files differdeleted file mode 100644 index 36a342e7c..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_get_info_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_list_instances_detail_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_list_instances_detail_shutil.p.gz Binary files differdeleted file mode 100644 index 3ab35a29f..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_list_instances_detail_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_list_instances_detail_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_list_instances_detail_wmi.p.gz Binary files differdeleted file mode 100644 index 411c0ed07..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_list_instances_detail_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_list_instances_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_list_instances_shutil.p.gz Binary files differdeleted file mode 100644 index 1af20acde..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_list_instances_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_list_instances_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_list_instances_wmi.p.gz Binary files differdeleted file mode 100644 index d84122d77..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_list_instances_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_nova.utils.p.gz Binary files differdeleted file mode 100644 index d650f40a5..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index a03d442a4..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_os.p.gz Binary files differdeleted file mode 100644 index 993d9bb2d..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_shutil.p.gz Binary files differdeleted file mode 100644 index 6693c2ce9..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_time.p.gz Binary files differdeleted file mode 100644 index 07898dd55..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_uuid.p.gz Binary files differdeleted file mode 100644 index 56e583449..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_nova.utils.p.gz Binary files differdeleted file mode 100644 index 5d4c0e111..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index cb52cb974..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_os.p.gz Binary files differdeleted file mode 100644 index 8b2ff15f3..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_shutil.p.gz Binary files differdeleted file mode 100644 index aee1fb14d..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_time.p.gz Binary files differdeleted file mode 100644 index f926d206f..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_uuid.p.gz Binary files differdeleted file mode 100644 index 483b23d53..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_wmi.p.gz Binary files differdeleted file mode 100644 index 14d61039f..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_with_target_failure_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_wmi.p.gz Binary files differdeleted file mode 100644 index daecf0156..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_live_migration_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_nova.utils.p.gz Binary files differdeleted file mode 100644 index 548b88148..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index 8545a1833..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_os.p.gz Binary files differdeleted file mode 100644 index c1daf3db9..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_shutil.p.gz Binary files differdeleted file mode 100644 index 750d68d29..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_time.p.gz Binary files differdeleted file mode 100644 index 6e91b72a2..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_uuid.p.gz Binary files differdeleted file mode 100644 index 2d0349d96..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_wmi.p.gz Binary files differdeleted file mode 100644 index 6b9ef360a..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_already_paused_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_nova.utils.p.gz Binary files differdeleted file mode 100644 index 3e582226f..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index 723966011..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_os.p.gz Binary files differdeleted file mode 100644 index 29b73888b..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_shutil.p.gz Binary files differdeleted file mode 100644 index 595124af2..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_time.p.gz Binary files differdeleted file mode 100644 index 03d53be74..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_uuid.p.gz Binary files differdeleted file mode 100644 index 2a0663e6f..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_wmi.p.gz Binary files differdeleted file mode 100644 index e651c02fc..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pause_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_nova.utils.p.gz Binary files differdeleted file mode 100644 index a50935649..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index 4b07271c1..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_os.p.gz Binary files differdeleted file mode 100644 index f62298ed7..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_shutil.p.gz Binary files differdeleted file mode 100644 index 12a164f23..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_time.p.gz Binary files differdeleted file mode 100644 index 33f1862e6..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_uuid.p.gz Binary files differdeleted file mode 100644 index 80853eea4..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_wmi.p.gz Binary files differdeleted file mode 100644 index 5cebe527d..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_already_powered_off_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_nova.utils.p.gz Binary files differdeleted file mode 100644 index d0c431b9d..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index d231f803d..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_os.p.gz Binary files differdeleted file mode 100644 index 25fe5f3ff..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_shutil.p.gz Binary files differdeleted file mode 100644 index 8be80ba56..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_time.p.gz Binary files differdeleted file mode 100644 index 51b6f2df8..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_uuid.p.gz Binary files differdeleted file mode 100644 index 97812405e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_wmi.p.gz Binary files differdeleted file mode 100644 index 20b2e021e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_off_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_nova.utils.p.gz Binary files differdeleted file mode 100644 index c32f9ecd2..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index 672376a0e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_os.p.gz Binary files differdeleted file mode 100644 index aa6f4ca8a..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_shutil.p.gz Binary files differdeleted file mode 100644 index 00f5770a7..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_time.p.gz Binary files differdeleted file mode 100644 index 1631f35df..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_uuid.p.gz Binary files differdeleted file mode 100644 index ec28756ad..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_wmi.p.gz Binary files differdeleted file mode 100644 index 699ccde76..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_already_running_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_nova.utils.p.gz Binary files differdeleted file mode 100644 index 2b99fb9cd..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index a43bfeb7e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_os.p.gz Binary files differdeleted file mode 100644 index 57e74e618..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_shutil.p.gz Binary files differdeleted file mode 100644 index 273364d95..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_time.p.gz Binary files differdeleted file mode 100644 index 732a0f2e6..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_uuid.p.gz Binary files differdeleted file mode 100644 index d6cb32559..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_wmi.p.gz Binary files differdeleted file mode 100644 index e44197039..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_power_on_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_nova.utils.p.gz Binary files differdeleted file mode 100644 index 456af2816..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_os.p.gz Binary files differdeleted file mode 100644 index 93568dcef..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_shutil.p.gz Binary files differdeleted file mode 100644 index 6a4b90850..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_time.p.gz Binary files differdeleted file mode 100644 index fc816320f..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_uuid.p.gz Binary files differdeleted file mode 100644 index 83cf9c071..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_wmi.p.gz Binary files differdeleted file mode 100644 index 93977743f..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_cow_image_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_no_cow_image_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_no_cow_image_nova.utils.p.gz Binary files differdeleted file mode 100644 index f58f80a79..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_no_cow_image_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_no_cow_image_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_no_cow_image_shutil.p.gz Binary files differdeleted file mode 100644 index 18a8aed13..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_no_cow_image_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_no_cow_image_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_no_cow_image_uuid.p.gz Binary files differdeleted file mode 100644 index 4225a72b0..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_no_cow_image_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_no_cow_image_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_no_cow_image_wmi.p.gz Binary files differdeleted file mode 100644 index 363c431d4..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_pre_live_migration_no_cow_image_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_nova.utils.p.gz Binary files differdeleted file mode 100644 index 8761703dc..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index fc907ed31..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_os.p.gz Binary files differdeleted file mode 100644 index 0eca8e6ce..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_shutil.p.gz Binary files differdeleted file mode 100644 index 0886c942d..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_time.p.gz Binary files differdeleted file mode 100644 index d0fb77bd1..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_uuid.p.gz Binary files differdeleted file mode 100644 index df3961276..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_wmi.p.gz Binary files differdeleted file mode 100644 index 4df451154..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_reboot_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_nova.utils.p.gz Binary files differdeleted file mode 100644 index 59724b43d..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index 4b3711ec0..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_os.p.gz Binary files differdeleted file mode 100644 index 2f9a5de9c..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_shutil.p.gz Binary files differdeleted file mode 100644 index 8ffa516c0..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_time.p.gz Binary files differdeleted file mode 100644 index 6aade88c6..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_uuid.p.gz Binary files differdeleted file mode 100644 index 276c06397..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_wmi.p.gz Binary files differdeleted file mode 100644 index 77a1650d4..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_already_running_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_nova.utils.p.gz Binary files differdeleted file mode 100644 index ce19ed290..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index b2dadcd4d..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_os.p.gz Binary files differdeleted file mode 100644 index aa378fedd..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_shutil.p.gz Binary files differdeleted file mode 100644 index 333a27b89..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_time.p.gz Binary files differdeleted file mode 100644 index 16ca553f6..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_uuid.p.gz Binary files differdeleted file mode 100644 index 8cf3b564e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_wmi.p.gz Binary files differdeleted file mode 100644 index 0a2c8513b..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_resume_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_nova.utils.p.gz Binary files differdeleted file mode 100644 index ae42d7734..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index 4fec34d08..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_os.p.gz Binary files differdeleted file mode 100644 index 74e8e95a6..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_shutil.p.gz Binary files differdeleted file mode 100644 index da0528797..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_time.p.gz Binary files differdeleted file mode 100644 index 63f02bc75..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_uuid.p.gz Binary files differdeleted file mode 100644 index c014d5003..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_nova.utils.p.gz Binary files differdeleted file mode 100644 index 592658541..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index 892f3c346..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_os.p.gz Binary files differdeleted file mode 100644 index 9996339f5..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_shutil.p.gz Binary files differdeleted file mode 100644 index 409ee5ef7..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_time.p.gz Binary files differdeleted file mode 100644 index 9e799c196..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_uuid.p.gz Binary files differdeleted file mode 100644 index 848024366..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_wmi.p.gz Binary files differdeleted file mode 100644 index 687952c4c..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_with_update_failure_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_wmi.p.gz Binary files differdeleted file mode 100644 index 57988a6b6..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_snapshot_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_nova.utils.p.gz Binary files differdeleted file mode 100644 index 303a47019..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index c211622e1..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_os.p.gz Binary files differdeleted file mode 100644 index 5e5303cbc..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_shutil.p.gz Binary files differdeleted file mode 100644 index 1bcbd48f3..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_time.p.gz Binary files differdeleted file mode 100644 index ae557d73d..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_uuid.p.gz Binary files differdeleted file mode 100644 index 90ebff4e7..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_wmi.p.gz Binary files differdeleted file mode 100644 index beccc2737..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_cdrom_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_nova.utils.p.gz Binary files differdeleted file mode 100644 index af5082ab6..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index 837d81b70..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_os.p.gz Binary files differdeleted file mode 100644 index ecea62a01..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_shutil.p.gz Binary files differdeleted file mode 100644 index 283cd7fdd..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_time.p.gz Binary files differdeleted file mode 100644 index 44dcc89ae..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_uuid.p.gz Binary files differdeleted file mode 100644 index 5c520c768..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_wmi.p.gz Binary files differdeleted file mode 100644 index aec53305d..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_config_drive_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_nova.utils.p.gz Binary files differdeleted file mode 100644 index a16c88e54..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index d9c4e9c82..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_os.p.gz Binary files differdeleted file mode 100644 index 94aafb39a..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_shutil.p.gz Binary files differdeleted file mode 100644 index e0ad00bf6..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_time.p.gz Binary files differdeleted file mode 100644 index 00f7839ba..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_uuid.p.gz Binary files differdeleted file mode 100644 index 77422d3f5..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_wmi.p.gz Binary files differdeleted file mode 100644 index 414194a9d..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_cow_image_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_nova.utils.p.gz Binary files differdeleted file mode 100644 index b1e825822..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index 1e3d89fea..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_os.p.gz Binary files differdeleted file mode 100644 index 627c78d7e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_shutil.p.gz Binary files differdeleted file mode 100644 index e577cdb5e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_time.p.gz Binary files differdeleted file mode 100644 index 72962fc52..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_uuid.p.gz Binary files differdeleted file mode 100644 index 5d1351a14..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_wmi.p.gz Binary files differdeleted file mode 100644 index eb0ed7241..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_config_drive_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_nova.utils.p.gz Binary files differdeleted file mode 100644 index c65264688..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index ca40d6413..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_os.p.gz Binary files differdeleted file mode 100644 index 1d8081a3e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_shutil.p.gz Binary files differdeleted file mode 100644 index e03633b90..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_time.p.gz Binary files differdeleted file mode 100644 index 00c56dacc..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_uuid.p.gz Binary files differdeleted file mode 100644 index 7381c3cc6..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_wmi.p.gz Binary files differdeleted file mode 100644 index 115ed1dd5..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_cow_image_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_nova.utils.p.gz Binary files differdeleted file mode 100644 index df40b08c0..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index b51766f75..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_os.p.gz Binary files differdeleted file mode 100644 index 092a1f933..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_shutil.p.gz Binary files differdeleted file mode 100644 index 77f333c00..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_time.p.gz Binary files differdeleted file mode 100644 index 8ab166a60..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_uuid.p.gz Binary files differdeleted file mode 100644 index 97e96be17..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_wmi.p.gz Binary files differdeleted file mode 100644 index 728464ca9..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_spawn_no_vswitch_exception_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_nova.utils.p.gz Binary files differdeleted file mode 100644 index 4aa6d171a..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index df063a22e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_os.p.gz Binary files differdeleted file mode 100644 index b30363fcc..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_shutil.p.gz Binary files differdeleted file mode 100644 index 1681d9947..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_time.p.gz Binary files differdeleted file mode 100644 index 4469fd90e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_uuid.p.gz Binary files differdeleted file mode 100644 index f94f2ebb9..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_wmi.p.gz Binary files differdeleted file mode 100644 index 03afe2235..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_already_suspended_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_nova.utils.p.gz Binary files differdeleted file mode 100644 index 2f95f62bf..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index 2e7ab44ad..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_os.p.gz Binary files differdeleted file mode 100644 index eb514d086..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_shutil.p.gz Binary files differdeleted file mode 100644 index 810c9e14d..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_time.p.gz Binary files differdeleted file mode 100644 index 2eb2a8372..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_uuid.p.gz Binary files differdeleted file mode 100644 index 67311757a..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_wmi.p.gz Binary files differdeleted file mode 100644 index 0779125b3..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_suspend_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_nova.utils.p.gz Binary files differdeleted file mode 100644 index 7e6cc708e..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index 0ce4bbf63..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_os.p.gz Binary files differdeleted file mode 100644 index 9068792c7..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_shutil.p.gz Binary files differdeleted file mode 100644 index 9b06cb884..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_time.p.gz Binary files differdeleted file mode 100644 index e91e6c965..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_uuid.p.gz Binary files differdeleted file mode 100644 index 271ded270..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_wmi.p.gz Binary files differdeleted file mode 100644 index 253bdfc82..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_already_running_wmi.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_nova.utils.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_nova.utils.p.gz Binary files differdeleted file mode 100644 index 20486b189..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_nova.utils.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_nova.virt.configdrive.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_nova.virt.configdrive.p.gz Binary files differdeleted file mode 100644 index be92217ed..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_nova.virt.configdrive.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_os.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_os.p.gz Binary files differdeleted file mode 100644 index 36059e753..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_os.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_shutil.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_shutil.p.gz Binary files differdeleted file mode 100644 index aea394e9f..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_shutil.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_time.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_time.p.gz Binary files differdeleted file mode 100644 index 4850d3cda..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_time.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_uuid.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_uuid.p.gz Binary files differdeleted file mode 100644 index 99bf1806c..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_uuid.p.gz +++ /dev/null diff --git a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_wmi.p.gz b/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_wmi.p.gz Binary files differdeleted file mode 100644 index 87b571e4a..000000000 --- a/nova/tests/hyperv/stubs/test_hypervapi.HyperVAPITestCase.test_unpause_wmi.p.gz +++ /dev/null diff --git a/nova/tests/test_hypervapi.py b/nova/tests/test_hypervapi.py index 9fec9d151..3b624e6d1 100644 --- a/nova/tests/test_hypervapi.py +++ b/nova/tests/test_hypervapi.py @@ -18,37 +18,53 @@ Test suite for the Hyper-V driver and related APIs. """ -import json +import io +import mox import os import platform import shutil -import sys +import time import uuid +from nova.api.metadata import base as instance_metadata from nova.compute import power_state from nova.compute import task_states from nova import context from nova import db from nova.image import glance from nova.openstack.common import cfg +from nova import test from nova.tests import fake_network -from nova.tests.hyperv import basetestcase from nova.tests.hyperv import db_fakes -from nova.tests.hyperv import hypervutils -from nova.tests.hyperv import mockproxy -import nova.tests.image.fake as fake_image +from nova.tests.hyperv import fake +from nova.tests.image import fake as fake_image from nova.tests import matchers +from nova import utils +from nova.virt import configdrive +from nova.virt.hyperv import basevolumeutils from nova.virt.hyperv import constants from nova.virt.hyperv import driver as driver_hyperv +from nova.virt.hyperv import hostutils +from nova.virt.hyperv import livemigrationutils +from nova.virt.hyperv import networkutils +from nova.virt.hyperv import pathutils +from nova.virt.hyperv import vhdutils from nova.virt.hyperv import vmutils +from nova.virt.hyperv import volumeutils +from nova.virt.hyperv import volumeutilsv2 from nova.virt import images CONF = cfg.CONF +CONF.import_opt('vswitch_name', 'nova.virt.hyperv.vif') -class HyperVAPITestCase(basetestcase.BaseTestCase): +class HyperVAPITestCase(test.TestCase): """Unit tests for Hyper-V driver calls.""" + def __init__(self, test_case_name): + self._mox = mox.Mox() + super(HyperVAPITestCase, self).__init__(test_case_name) + def setUp(self): super(HyperVAPITestCase, self).setUp() @@ -56,22 +72,22 @@ class HyperVAPITestCase(basetestcase.BaseTestCase): self._project_id = 'fake' self._instance_data = None self._image_metadata = None - self._dest_server = None self._fetched_image = None self._update_image_raise_exception = False - self._post_method_called = False - self._recover_method_called = False self._volume_target_portal = 'testtargetportal:3260' - self._volume_id = '8957e088-dbee-4216-8056-978353a3e737' + self._volume_id = '0ef5d708-45ab-4129-8c59-d774d2837eb7' self._context = context.RequestContext(self._user_id, self._project_id) + self._instance_ide_disks = [] + self._instance_ide_dvds = [] + self._instance_volume_disks = [] self._setup_stubs() self.flags(instances_path=r'C:\Hyper-V\test\instances', vswitch_name='external', - network_api_class='nova.network.quantumv2.api.API') + network_api_class='nova.network.quantumv2.api.API', + force_volumeutils_v1=True) - self._hypervutils = hypervutils.HyperVUtils() self._conn = driver_hyperv.HyperVDriver(None) def _setup_stubs(self): @@ -79,14 +95,8 @@ class HyperVAPITestCase(basetestcase.BaseTestCase): fake_image.stub_out_image_service(self.stubs) fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs) - def fake_dumps(msg, default=None, **kwargs): - return '""' - self.stubs.Set(json, 'dumps', fake_dumps) - def fake_fetch(context, image_id, target, user, project): self._fetched_image = target - if not os.path.exists(target): - self._hypervutils.create_vhd(target) self.stubs.Set(images, 'fetch', fake_fetch) def fake_get_remote_image_service(context, name): @@ -98,104 +108,198 @@ class HyperVAPITestCase(basetestcase.BaseTestCase): self._image_metadata = image_metadata return (FakeGlanceImageService(), 1) self.stubs.Set(glance, 'get_remote_image_service', - fake_get_remote_image_service) - - # Modules to mock - modules_to_mock = [ - 'wmi', - 'os', - 'shutil', - 'uuid', - 'time', - 'multiprocessing', - '_winreg', - 'nova.virt.configdrive', - 'nova.utils', - 'ctypes' - ] + fake_get_remote_image_service) + + def fake_sleep(ms): + pass + self.stubs.Set(time, 'sleep', fake_sleep) + + self.stubs.Set(pathutils, 'PathUtils', fake.PathUtils) + self._mox.StubOutWithMock(fake.PathUtils, 'open') + + self._mox.StubOutWithMock(vmutils.VMUtils, 'vm_exists') + self._mox.StubOutWithMock(vmutils.VMUtils, 'create_vm') + self._mox.StubOutWithMock(vmutils.VMUtils, 'destroy_vm') + self._mox.StubOutWithMock(vmutils.VMUtils, 'attach_ide_drive') + self._mox.StubOutWithMock(vmutils.VMUtils, 'create_scsi_controller') + self._mox.StubOutWithMock(vmutils.VMUtils, 'create_nic') + self._mox.StubOutWithMock(vmutils.VMUtils, 'set_vm_state') + self._mox.StubOutWithMock(vmutils.VMUtils, 'list_instances') + self._mox.StubOutWithMock(vmutils.VMUtils, 'get_vm_summary_info') + self._mox.StubOutWithMock(vmutils.VMUtils, 'take_vm_snapshot') + self._mox.StubOutWithMock(vmutils.VMUtils, 'remove_vm_snapshot') + self._mox.StubOutWithMock(vmutils.VMUtils, 'set_nic_connection') + self._mox.StubOutWithMock(vmutils.VMUtils, 'get_vm_iscsi_controller') + self._mox.StubOutWithMock(vmutils.VMUtils, 'get_vm_ide_controller') + self._mox.StubOutWithMock(vmutils.VMUtils, 'get_attached_disks_count') + self._mox.StubOutWithMock(vmutils.VMUtils, + 'attach_volume_to_controller') + self._mox.StubOutWithMock(vmutils.VMUtils, + 'get_mounted_disk_by_drive_number') + self._mox.StubOutWithMock(vmutils.VMUtils, 'detach_vm_disk') + + self._mox.StubOutWithMock(vhdutils.VHDUtils, 'create_differencing_vhd') + self._mox.StubOutWithMock(vhdutils.VHDUtils, 'reconnect_parent_vhd') + self._mox.StubOutWithMock(vhdutils.VHDUtils, 'merge_vhd') + self._mox.StubOutWithMock(vhdutils.VHDUtils, 'get_vhd_parent_path') + + self._mox.StubOutWithMock(hostutils.HostUtils, 'get_cpus_info') + self._mox.StubOutWithMock(hostutils.HostUtils, + 'is_cpu_feature_present') + self._mox.StubOutWithMock(hostutils.HostUtils, 'get_memory_info') + self._mox.StubOutWithMock(hostutils.HostUtils, 'get_volume_info') + self._mox.StubOutWithMock(hostutils.HostUtils, 'get_windows_version') + + self._mox.StubOutWithMock(networkutils.NetworkUtils, + 'get_external_vswitch') + self._mox.StubOutWithMock(networkutils.NetworkUtils, + 'create_vswitch_port') + + self._mox.StubOutWithMock(livemigrationutils.LiveMigrationUtils, + 'live_migrate_vm') + self._mox.StubOutWithMock(livemigrationutils.LiveMigrationUtils, + 'check_live_migration_config') + + self._mox.StubOutWithMock(basevolumeutils.BaseVolumeUtils, + 'volume_in_mapping') + self._mox.StubOutWithMock(basevolumeutils.BaseVolumeUtils, + 'get_session_id_from_mounted_disk') + self._mox.StubOutWithMock(basevolumeutils.BaseVolumeUtils, + 'get_device_number_for_target') + + self._mox.StubOutWithMock(volumeutils.VolumeUtils, + 'login_storage_target') + self._mox.StubOutWithMock(volumeutils.VolumeUtils, + 'logout_storage_target') + self._mox.StubOutWithMock(volumeutils.VolumeUtils, + 'execute_log_out') + + self._mox.StubOutWithMock(volumeutilsv2.VolumeUtilsV2, + 'login_storage_target') + self._mox.StubOutWithMock(volumeutilsv2.VolumeUtilsV2, + 'logout_storage_target') + self._mox.StubOutWithMock(volumeutilsv2.VolumeUtilsV2, + 'execute_log_out') + + self._mox.StubOutWithMock(shutil, 'copyfile') + self._mox.StubOutWithMock(shutil, 'rmtree') + + self._mox.StubOutWithMock(os, 'remove') + + self._mox.StubOutClassWithMocks(instance_metadata, 'InstanceMetadata') + self._mox.StubOutWithMock(instance_metadata.InstanceMetadata, + 'metadata_for_config_drive') + + # Can't use StubOutClassWithMocks due to __exit__ and __enter__ + self._mox.StubOutWithMock(configdrive, 'ConfigDriveBuilder') + self._mox.StubOutWithMock(configdrive.ConfigDriveBuilder, 'make_drive') + + self._mox.StubOutWithMock(utils, 'execute') - # Modules in which the mocks are going to be injected - from nova.virt.hyperv import baseops - from nova.virt.hyperv import basevolumeutils - from nova.virt.hyperv import hostops - from nova.virt.hyperv import livemigrationops - from nova.virt.hyperv import snapshotops - from nova.virt.hyperv import vif - from nova.virt.hyperv import vmops - from nova.virt.hyperv import volumeops - from nova.virt.hyperv import volumeutils - from nova.virt.hyperv import volumeutilsV2 - - modules_to_test = [ - driver_hyperv, - basevolumeutils, - baseops, - hostops, - vif, - vmops, - vmutils, - volumeops, - volumeutils, - volumeutilsV2, - snapshotops, - livemigrationops, - hypervutils, - db_fakes, - sys.modules[__name__] - ] + def tearDown(self): + self._mox.UnsetStubs() + super(HyperVAPITestCase, self).tearDown() - self._inject_mocks_in_modules(modules_to_mock, modules_to_test) + def test_get_available_resource(self): + cpu_info = {'Architecture': 'fake', + 'Name': 'fake', + 'Manufacturer': 'ACME, Inc.', + 'NumberOfCores': 2, + 'NumberOfLogicalProcessors': 4} - if isinstance(snapshotops.wmi, mockproxy.Mock): - from nova.virt.hyperv import ioutils - import StringIO + tot_mem_kb = 2000000L + free_mem_kb = 1000000L - def fake_open(name, mode): - return StringIO.StringIO("fake file content") - self.stubs.Set(ioutils, 'open', fake_open) + tot_hdd_b = 4L * 1024 ** 3 + free_hdd_b = 3L * 1024 ** 3 - def tearDown(self): - try: - if self._instance_data and self._hypervutils.vm_exists( - self._instance_data["name"]): - self._hypervutils.remove_vm(self._instance_data["name"]) + windows_version = '6.2.9200' - if self._dest_server and \ - self._hypervutils.remote_vm_exists(self._dest_server, - self._instance_data["name"]): - self._hypervutils.remove_remote_vm(self._dest_server, - self._instance_data["name"]) + hostutils.HostUtils.get_memory_info().AndReturn((tot_mem_kb, + free_mem_kb)) - self._hypervutils.logout_iscsi_volume_sessions(self._volume_id) + m = hostutils.HostUtils.get_volume_info(mox.IsA(str)) + m.AndReturn((tot_hdd_b, free_hdd_b)) - shutil.rmtree(CONF.instances_path, True) + hostutils.HostUtils.get_cpus_info().AndReturn([cpu_info]) + m = hostutils.HostUtils.is_cpu_feature_present(mox.IsA(int)) + m.MultipleTimes() - fake_image.FakeImageService_reset() - finally: - super(HyperVAPITestCase, self).tearDown() + m = hostutils.HostUtils.get_windows_version() + m.AndReturn(windows_version) - def test_get_available_resource(self): + self._mox.ReplayAll() dic = self._conn.get_available_resource(None) + self._mox.VerifyAll() + self.assertEquals(dic['vcpus'], cpu_info['NumberOfLogicalProcessors']) self.assertEquals(dic['hypervisor_hostname'], platform.node()) + self.assertEquals(dic['memory_mb'], tot_mem_kb / 1024) + self.assertEquals(dic['memory_mb_used'], + tot_mem_kb / 1024 - free_mem_kb / 1024) + self.assertEquals(dic['local_gb'], tot_hdd_b / 1024 ** 3) + self.assertEquals(dic['local_gb_used'], + tot_hdd_b / 1024 ** 3 - free_hdd_b / 1024 ** 3) + self.assertEquals(dic['hypervisor_version'], + windows_version.replace('.', '')) def test_get_host_stats(self): + tot_mem_kb = 2000000L + free_mem_kb = 1000000L + + tot_hdd_b = 4L * 1024 ** 3 + free_hdd_b = 3L * 1024 ** 3 + + hostutils.HostUtils.get_memory_info().AndReturn((tot_mem_kb, + free_mem_kb)) + + m = hostutils.HostUtils.get_volume_info(mox.IsA(str)) + m.AndReturn((tot_hdd_b, free_hdd_b)) + + self._mox.ReplayAll() dic = self._conn.get_host_stats(True) + self._mox.VerifyAll() + + self.assertEquals(dic['disk_total'], tot_hdd_b / 1024 ** 3) + self.assertEquals(dic['disk_available'], free_hdd_b / 1024 ** 3) + + self.assertEquals(dic['host_memory_total'], tot_mem_kb / 1024) + self.assertEquals(dic['host_memory_free'], free_mem_kb / 1024) self.assertEquals(dic['disk_total'], - dic['disk_used'] + dic['disk_available']) + dic['disk_used'] + dic['disk_available']) self.assertEquals(dic['host_memory_total'], - dic['host_memory_overhead'] + dic['host_memory_free']) + dic['host_memory_overhead'] + + dic['host_memory_free']) def test_list_instances(self): - num_vms = self._hypervutils.get_vm_count() + fake_instances = ['fake1', 'fake2'] + vmutils.VMUtils.list_instances().AndReturn(fake_instances) + + self._mox.ReplayAll() instances = self._conn.list_instances() + self._mox.VerifyAll() - self.assertEquals(len(instances), num_vms) + self.assertEquals(instances, fake_instances) def test_get_info(self): - self._spawn_instance(True) + self._instance_data = self._get_instance_data() + + summary_info = {'NumberOfProcessors': 2, + 'EnabledState': constants.HYPERV_VM_STATE_ENABLED, + 'MemoryUsage': 1000, + 'UpTime': 1} + + m = vmutils.VMUtils.vm_exists(mox.Func(self._check_instance_name)) + m.AndReturn(True) + + func = mox.Func(self._check_instance_name) + m = vmutils.VMUtils.get_vm_summary_info(func) + m.AndReturn(summary_info) + + self._mox.ReplayAll() info = self._conn.get_info(self._instance_data) + self._mox.VerifyAll() self.assertEquals(info["state"], power_state.RUNNING) @@ -205,189 +309,237 @@ class HyperVAPITestCase(basetestcase.BaseTestCase): def test_spawn_no_cow_image(self): self._test_spawn_instance(False) - def test_spawn_config_drive(self): - self.skip('broken by move to contextlib for configdrive') - + def _setup_spawn_config_drive_mocks(self, use_cdrom): + im = instance_metadata.InstanceMetadata(mox.IgnoreArg(), + content=mox.IsA(list), + extra_md=mox.IsA(dict)) + + cdb = self._mox.CreateMockAnything() + m = configdrive.ConfigDriveBuilder(instance_md=mox.IgnoreArg()) + m.AndReturn(cdb) + # __enter__ and __exit__ are required by "with" + cdb.__enter__().AndReturn(cdb) + cdb.make_drive(mox.IsA(str)) + cdb.__exit__(None, None, None).AndReturn(None) + + if not use_cdrom: + utils.execute(CONF.qemu_img_cmd, + 'convert', + '-f', + 'raw', + '-O', + 'vpc', + mox.IsA(str), + mox.IsA(str), + attempts=1) + os.remove(mox.IsA(str)) + + m = vmutils.VMUtils.attach_ide_drive(mox.IsA(str), + mox.IsA(str), + mox.IsA(int), + mox.IsA(int), + mox.IsA(str)) + m.WithSideEffects(self._add_ide_disk) + + def _test_spawn_config_drive(self, use_cdrom): self.flags(force_config_drive=True) + self.flags(config_drive_cdrom=use_cdrom) self.flags(mkisofs_cmd='mkisofs.exe') - self._spawn_instance(True) + self._setup_spawn_config_drive_mocks(use_cdrom) - (vhd_paths, _, dvd_paths) = self._hypervutils.get_vm_disks( - self._instance_data["name"]) - self.assertEquals(len(dvd_paths), 0) - self.assertEquals(len(vhd_paths), 2) + if use_cdrom: + expected_ide_disks = 1 + expected_ide_dvds = 1 + else: + expected_ide_disks = 2 + expected_ide_dvds = 0 - def test_spawn_config_drive_cdrom(self): - self.skip('broken by move to contextlib for configdrive') + self._test_spawn_instance(expected_ide_disks=expected_ide_disks, + expected_ide_dvds=expected_ide_dvds) - self.flags(force_config_drive=True) - self.flags(config_drive_cdrom=True) - self.flags(mkisofs_cmd='mkisofs.exe') - - self._spawn_instance(True) + def test_spawn_config_drive(self): + self._test_spawn_config_drive(False) - (vhd_paths, _, dvd_paths) = self._hypervutils.get_vm_disks( - self._instance_data["name"]) - self.assertEquals(len(dvd_paths), 1) - self.assertEquals(len(vhd_paths), 1) - self.assertTrue(os.path.exists(dvd_paths[0])) + def test_spawn_config_drive_cdrom(self): + self._test_spawn_config_drive(True) def test_spawn_no_config_drive(self): self.flags(force_config_drive=False) - self._spawn_instance(True) + expected_ide_disks = 1 + expected_ide_dvds = 0 + + self._test_spawn_instance(expected_ide_disks=expected_ide_disks, + expected_ide_dvds=expected_ide_dvds) + + def test_spawn_nova_net_vif(self): + self.flags(network_api_class='nova.network.api.API') + # Reinstantiate driver, as the VIF plugin is loaded during __init__ + self._conn = driver_hyperv.HyperVDriver(None) + + def setup_vif_mocks(): + fake_vswitch_path = 'fake vswitch path' + fake_vswitch_port = 'fake port' + + m = networkutils.NetworkUtils.get_external_vswitch( + CONF.vswitch_name) + m.AndReturn(fake_vswitch_path) + + m = networkutils.NetworkUtils.create_vswitch_port( + fake_vswitch_path, mox.IsA(str)) + m.AndReturn(fake_vswitch_port) - (_, _, dvd_paths) = self._hypervutils.get_vm_disks( - self._instance_data["name"]) - self.assertEquals(len(dvd_paths), 0) + vmutils.VMUtils.set_nic_connection(mox.IsA(str), mox.IsA(str), + fake_vswitch_port) - def test_spawn_no_vswitch_exception(self): + self._test_spawn_instance(setup_vif_mocks_func=setup_vif_mocks) + + def test_spawn_nova_net_vif_no_vswitch_exception(self): self.flags(network_api_class='nova.network.api.API') # Reinstantiate driver, as the VIF plugin is loaded during __init__ self._conn = driver_hyperv.HyperVDriver(None) - # Set flag to a non existing vswitch - self.flags(vswitch_name=str(uuid.uuid4())) - self.assertRaises(vmutils.HyperVException, self._spawn_instance, True) - self.assertFalse(self._hypervutils.vm_exists( - self._instance_data["name"])) + def setup_vif_mocks(): + m = networkutils.NetworkUtils.get_external_vswitch( + CONF.vswitch_name) + m.AndRaise(vmutils.HyperVException(_('fake vswitch not found'))) + + self.assertRaises(vmutils.HyperVException, self._test_spawn_instance, + setup_vif_mocks_func=setup_vif_mocks, + with_exception=True) + + def _check_instance_name(self, vm_name): + return vm_name == self._instance_data['name'] def _test_vm_state_change(self, action, from_state, to_state): - self._spawn_instance(True) - if from_state: - self._hypervutils.set_vm_state(self._instance_data["name"], - from_state) - action(self._instance_data) + self._instance_data = self._get_instance_data() - vmstate = self._hypervutils.get_vm_state(self._instance_data["name"]) - self.assertEquals(vmstate, to_state) + vmutils.VMUtils.set_vm_state(mox.Func(self._check_instance_name), + to_state) + + self._mox.ReplayAll() + action(self._instance_data) + self._mox.VerifyAll() def test_pause(self): self._test_vm_state_change(self._conn.pause, None, - constants.HYPERV_VM_STATE_PAUSED) + constants.HYPERV_VM_STATE_PAUSED) def test_pause_already_paused(self): self._test_vm_state_change(self._conn.pause, - constants.HYPERV_VM_STATE_PAUSED, - constants.HYPERV_VM_STATE_PAUSED) + constants.HYPERV_VM_STATE_PAUSED, + constants.HYPERV_VM_STATE_PAUSED) def test_unpause(self): self._test_vm_state_change(self._conn.unpause, - constants.HYPERV_VM_STATE_PAUSED, - constants.HYPERV_VM_STATE_ENABLED) + constants.HYPERV_VM_STATE_PAUSED, + constants.HYPERV_VM_STATE_ENABLED) def test_unpause_already_running(self): self._test_vm_state_change(self._conn.unpause, None, - constants.HYPERV_VM_STATE_ENABLED) + constants.HYPERV_VM_STATE_ENABLED) def test_suspend(self): self._test_vm_state_change(self._conn.suspend, None, - constants.HYPERV_VM_STATE_SUSPENDED) + constants.HYPERV_VM_STATE_SUSPENDED) def test_suspend_already_suspended(self): self._test_vm_state_change(self._conn.suspend, - constants.HYPERV_VM_STATE_SUSPENDED, - constants.HYPERV_VM_STATE_SUSPENDED) + constants.HYPERV_VM_STATE_SUSPENDED, + constants.HYPERV_VM_STATE_SUSPENDED) def test_resume(self): self._test_vm_state_change(lambda i: self._conn.resume(i, None), - constants.HYPERV_VM_STATE_SUSPENDED, - constants.HYPERV_VM_STATE_ENABLED) + constants.HYPERV_VM_STATE_SUSPENDED, + constants.HYPERV_VM_STATE_ENABLED) def test_resume_already_running(self): self._test_vm_state_change(lambda i: self._conn.resume(i, None), None, - constants.HYPERV_VM_STATE_ENABLED) + constants.HYPERV_VM_STATE_ENABLED) def test_power_off(self): self._test_vm_state_change(self._conn.power_off, None, - constants.HYPERV_VM_STATE_DISABLED) + constants.HYPERV_VM_STATE_DISABLED) def test_power_off_already_powered_off(self): - self._test_vm_state_change(self._conn.suspend, - constants.HYPERV_VM_STATE_DISABLED, - constants.HYPERV_VM_STATE_DISABLED) + self._test_vm_state_change(self._conn.power_off, + constants.HYPERV_VM_STATE_DISABLED, + constants.HYPERV_VM_STATE_DISABLED) def test_power_on(self): self._test_vm_state_change(self._conn.power_on, - constants.HYPERV_VM_STATE_DISABLED, - constants.HYPERV_VM_STATE_ENABLED) + constants.HYPERV_VM_STATE_DISABLED, + constants.HYPERV_VM_STATE_ENABLED) def test_power_on_already_running(self): self._test_vm_state_change(self._conn.power_on, None, - constants.HYPERV_VM_STATE_ENABLED) + constants.HYPERV_VM_STATE_ENABLED) def test_reboot(self): - self._spawn_instance(True) network_info = fake_network.fake_get_instance_nw_info(self.stubs, spectacular=True) - self._conn.reboot(self._instance_data, network_info, None) + self._instance_data = self._get_instance_data() - vmstate = self._hypervutils.get_vm_state(self._instance_data["name"]) - self.assertEquals(vmstate, constants.HYPERV_VM_STATE_ENABLED) + vmutils.VMUtils.set_vm_state(mox.Func(self._check_instance_name), + constants.HYPERV_VM_STATE_REBOOT) + + self._mox.ReplayAll() + self._conn.reboot(self._instance_data, network_info, None) + self._mox.VerifyAll() def test_destroy(self): - self._spawn_instance(True) - (vhd_paths, _, _) = self._hypervutils.get_vm_disks( - self._instance_data["name"]) + self._instance_data = self._get_instance_data() - self._conn.destroy(self._instance_data) + m = vmutils.VMUtils.vm_exists(mox.Func(self._check_instance_name)) + m.AndReturn(True) - self.assertFalse(self._hypervutils.vm_exists( - self._instance_data["name"])) - self._instance_data = None + m = vmutils.VMUtils.destroy_vm(mox.Func(self._check_instance_name), + True) + m.AndReturn([]) - for vhd_path in vhd_paths: - self.assertFalse(os.path.exists(vhd_path)) + self._mox.ReplayAll() + self._conn.destroy(self._instance_data) + self._mox.VerifyAll() def test_live_migration(self): - self.flags(limit_cpu_features=True) - self._spawn_instance(False) + self._test_live_migration(False) - # Existing server - self._dest_server = "HV12OSDEMO2" + def test_live_migration_with_target_failure(self): + self._test_live_migration(True) - self._live_migration(self._dest_server) + def _test_live_migration(self, test_failure): + dest_server = 'fake_server' - instance_name = self._instance_data["name"] - self.assertFalse(self._hypervutils.vm_exists(instance_name)) - self.assertTrue(self._hypervutils.remote_vm_exists(self._dest_server, - instance_name)) + instance_data = self._get_instance_data() - self.assertTrue(self._post_method_called) - self.assertFalse(self._recover_method_called) + fake_post_method = self._mox.CreateMockAnything() + if not test_failure: + fake_post_method(self._context, instance_data, dest_server, + False) - def test_live_migration_with_target_failure(self): - self.flags(limit_cpu_features=True) - self._spawn_instance(False) + fake_recover_method = self._mox.CreateMockAnything() + if test_failure: + fake_recover_method(self._context, instance_data, dest_server, + False) - dest_server = "nonexistingserver" + m = livemigrationutils.LiveMigrationUtils.live_migrate_vm( + instance_data['name'], dest_server) + if test_failure: + m.AndRaise(Exception('Simulated failure')) - exception_raised = False + self._mox.ReplayAll() try: - self._live_migration(dest_server) + self._conn.live_migration(self._context, instance_data, + dest_server, fake_post_method, + fake_recover_method) + exception_raised = False except Exception: exception_raised = True - # Cannot use assertRaises with pythoncom.com_error on Linux - self.assertTrue(exception_raised) - - instance_name = self._instance_data["name"] - self.assertTrue(self._hypervutils.vm_exists(instance_name)) - - self.assertFalse(self._post_method_called) - self.assertTrue(self._recover_method_called) - - def _live_migration(self, dest_server): - def fake_post_method(context, instance_ref, dest, block_migration): - self._post_method_called = True - - def fake_recover_method(context, instance_ref, dest, block_migration): - self._recover_method_called = True - - self._conn.live_migration(self._context, self._instance_data, - dest_server, fake_post_method, fake_recover_method) + self.assertTrue(not test_failure ^ exception_raised) + self._mox.VerifyAll() def test_pre_live_migration_cow_image(self): self._test_pre_live_migration(True) @@ -398,83 +550,134 @@ class HyperVAPITestCase(basetestcase.BaseTestCase): def _test_pre_live_migration(self, cow): self.flags(use_cow_images=cow) - instance_name = 'openstack_unit_test_vm_' + str(uuid.uuid4()) + instance_data = self._get_instance_data() network_info = fake_network.fake_get_instance_nw_info(self.stubs, spectacular=True) - instance_data = db_fakes.get_fake_instance_data(instance_name, - self._project_id, self._user_id) - block_device_info = None + m = livemigrationutils.LiveMigrationUtils.check_live_migration_config() + m.AndReturn(True) + + if cow: + m = basevolumeutils.BaseVolumeUtils.volume_in_mapping(mox.IsA(str), + None) + m.AndReturn([]) + + self._mox.ReplayAll() self._conn.pre_live_migration(self._context, instance_data, - block_device_info, network_info) + None, network_info) + self._mox.VerifyAll() if cow: - self.assertTrue(not self._fetched_image is None) + self.assertTrue(self._fetched_image is not None) else: self.assertTrue(self._fetched_image is None) def test_snapshot_with_update_failure(self): - expected_calls = [ - {'args': (), - 'kwargs': - {'task_state': task_states.IMAGE_PENDING_UPLOAD}}, - {'args': (), - 'kwargs': - {'task_state': task_states.IMAGE_UPLOADING, - 'expected_state': task_states.IMAGE_PENDING_UPLOAD}}] - func_call_matcher = matchers.FunctionCallMatcher(expected_calls) - - self._spawn_instance(True) + (snapshot_name, func_call_matcher) = self._setup_snapshot_mocks() self._update_image_raise_exception = True - snapshot_name = 'test_snapshot_' + str(uuid.uuid4()) + + self._mox.ReplayAll() self.assertRaises(vmutils.HyperVException, self._conn.snapshot, self._context, self._instance_data, snapshot_name, func_call_matcher.call) + self._mox.VerifyAll() - # assert states changed in correct order + # Assert states changed in correct order self.assertIsNone(func_call_matcher.match()) - # assert VM snapshots have been removed - self.assertEquals(self._hypervutils.get_vm_snapshots_count( - self._instance_data["name"]), 0) - - def test_snapshot(self): + def _setup_snapshot_mocks(self): expected_calls = [ {'args': (), - 'kwargs': - {'task_state': task_states.IMAGE_PENDING_UPLOAD}}, - {'args': (), - 'kwargs': - {'task_state': task_states.IMAGE_UPLOADING, - 'expected_state': task_states.IMAGE_PENDING_UPLOAD}}] + 'kwargs': {'task_state': task_states.IMAGE_PENDING_UPLOAD}}, + {'args': (), + 'kwargs': {'task_state': task_states.IMAGE_UPLOADING, + 'expected_state': task_states.IMAGE_PENDING_UPLOAD}} + ] func_call_matcher = matchers.FunctionCallMatcher(expected_calls) - self._spawn_instance(True) - snapshot_name = 'test_snapshot_' + str(uuid.uuid4()) + + fake_hv_snapshot_path = 'fake_snapshot_path' + fake_parent_vhd_path = 'C:\\fake_vhd_path\\parent.vhd' + + self._instance_data = self._get_instance_data() + + func = mox.Func(self._check_instance_name) + m = vmutils.VMUtils.take_vm_snapshot(func) + m.AndReturn(fake_hv_snapshot_path) + + m = vhdutils.VHDUtils.get_vhd_parent_path(mox.IsA(str)) + m.AndReturn(fake_parent_vhd_path) + + self._fake_dest_disk_path = None + + def copy_dest_disk_path(src, dest): + self._fake_dest_disk_path = dest + + m = shutil.copyfile(mox.IsA(str), mox.IsA(str)) + m.WithSideEffects(copy_dest_disk_path) + + self._fake_dest_base_disk_path = None + + def copy_dest_base_disk_path(src, dest): + self._fake_dest_base_disk_path = dest + + m = shutil.copyfile(fake_parent_vhd_path, mox.IsA(str)) + m.WithSideEffects(copy_dest_base_disk_path) + + def check_dest_disk_path(path): + return path == self._fake_dest_disk_path + + def check_dest_base_disk_path(path): + return path == self._fake_dest_base_disk_path + + func1 = mox.Func(check_dest_disk_path) + func2 = mox.Func(check_dest_base_disk_path) + # Make sure that the hyper-v base and differential VHDs are merged + vhdutils.VHDUtils.reconnect_parent_vhd(func1, func2) + vhdutils.VHDUtils.merge_vhd(func1, func2) + + def check_snapshot_path(snapshot_path): + return snapshot_path == fake_hv_snapshot_path + + # Make sure that the Hyper-V snapshot is removed + func = mox.Func(check_snapshot_path) + vmutils.VMUtils.remove_vm_snapshot(func) + + shutil.rmtree(mox.IsA(str)) + + m = fake.PathUtils.open(func2, 'rb') + m.AndReturn(io.BytesIO(b'fake content')) + + return (snapshot_name, func_call_matcher) + + def test_snapshot(self): + (snapshot_name, func_call_matcher) = self._setup_snapshot_mocks() + + self._mox.ReplayAll() self._conn.snapshot(self._context, self._instance_data, snapshot_name, func_call_matcher.call) + self._mox.VerifyAll() self.assertTrue(self._image_metadata and - "disk_format" in self._image_metadata and - self._image_metadata["disk_format"] == "vhd") + "disk_format" in self._image_metadata and + self._image_metadata["disk_format"] == "vhd") - # assert states changed in correct order + # Assert states changed in correct order self.assertIsNone(func_call_matcher.match()) - # assert VM snapshots have been removed - self.assertEquals(self._hypervutils.get_vm_snapshots_count( - self._instance_data["name"]), 0) + def _get_instance_data(self): + instance_name = 'openstack_unit_test_vm_' + str(uuid.uuid4()) + return db_fakes.get_fake_instance_data(instance_name, + self._project_id, + self._user_id) def _spawn_instance(self, cow, block_device_info=None): self.flags(use_cow_images=cow) - instance_name = 'openstack_unit_test_vm_' + str(uuid.uuid4()) - - self._instance_data = db_fakes.get_fake_instance_data(instance_name, - self._project_id, self._user_id) + self._instance_data = self._get_instance_data() instance = db.instance_create(self._context, self._instance_data) image = db_fakes.get_fake_image_data(self._project_id, self._user_id) @@ -487,73 +690,216 @@ class HyperVAPITestCase(basetestcase.BaseTestCase): network_info=network_info, block_device_info=block_device_info) - def _test_spawn_instance(self, cow): - self._spawn_instance(cow) + def _add_ide_disk(self, vm_name, path, ctrller_addr, + drive_addr, drive_type): + if drive_type == constants.IDE_DISK: + self._instance_ide_disks.append(path) + elif drive_type == constants.IDE_DVD: + self._instance_ide_dvds.append(path) + + def _add_volume_disk(self, vm_name, controller_path, address, + mounted_disk_path): + self._instance_volume_disks.append(mounted_disk_path) - self.assertTrue(self._hypervutils.vm_exists( - self._instance_data["name"])) + def _setup_spawn_instance_mocks(self, cow, setup_vif_mocks_func=None, + with_exception=False, + block_device_info=None): + self._test_vm_name = None - vmstate = self._hypervutils.get_vm_state(self._instance_data["name"]) - self.assertEquals(vmstate, constants.HYPERV_VM_STATE_ENABLED) + def set_vm_name(vm_name): + self._test_vm_name = vm_name - (vhd_paths, _, _) = self._hypervutils.get_vm_disks( - self._instance_data["name"]) - self.assertEquals(len(vhd_paths), 1) + def check_vm_name(vm_name): + return vm_name == self._test_vm_name + + m = vmutils.VMUtils.vm_exists(mox.IsA(str)) + m.WithSideEffects(set_vm_name).AndReturn(False) + + if not block_device_info: + m = basevolumeutils.BaseVolumeUtils.volume_in_mapping(mox.IsA(str), + None) + m.AndReturn([]) + else: + m = basevolumeutils.BaseVolumeUtils.volume_in_mapping( + mox.IsA(str), block_device_info) + m.AndReturn(True) - parent_path = self._hypervutils.get_vhd_parent_path(vhd_paths[0]) if cow: - self.assertTrue(not parent_path is None) - self.assertEquals(self._fetched_image, parent_path) + def check_path(parent_path): + return parent_path == self._fetched_image + + vhdutils.VHDUtils.create_differencing_vhd(mox.IsA(str), + mox.Func(check_path)) + + vmutils.VMUtils.create_vm(mox.Func(check_vm_name), mox.IsA(int), + mox.IsA(int), mox.IsA(bool)) + + if not block_device_info: + m = vmutils.VMUtils.attach_ide_drive(mox.Func(check_vm_name), + mox.IsA(str), + mox.IsA(int), + mox.IsA(int), + mox.IsA(str)) + m.WithSideEffects(self._add_ide_disk).InAnyOrder() + + m = vmutils.VMUtils.create_scsi_controller(mox.Func(check_vm_name)) + m.InAnyOrder() + + vmutils.VMUtils.create_nic(mox.Func(check_vm_name), mox.IsA(str), + mox.IsA(str)).InAnyOrder() + + if setup_vif_mocks_func: + setup_vif_mocks_func() + + # TODO(alexpilotti) Based on where the exception is thrown + # some of the above mock calls need to be skipped + if with_exception: + m = vmutils.VMUtils.vm_exists(mox.Func(check_vm_name)) + m.AndReturn(True) + + vmutils.VMUtils.destroy_vm(mox.Func(check_vm_name), True) else: - self.assertTrue(parent_path is None) - self.assertEquals(self._fetched_image, vhd_paths[0]) + vmutils.VMUtils.set_vm_state(mox.Func(check_vm_name), + constants.HYPERV_VM_STATE_ENABLED) + + def _test_spawn_instance(self, cow=True, + expected_ide_disks=1, + expected_ide_dvds=0, + setup_vif_mocks_func=None, + with_exception=False): + self._setup_spawn_instance_mocks(cow, setup_vif_mocks_func, + with_exception) + + self._mox.ReplayAll() + self._spawn_instance(cow, ) + self._mox.VerifyAll() + + self.assertEquals(len(self._instance_ide_disks), expected_ide_disks) + self.assertEquals(len(self._instance_ide_dvds), expected_ide_dvds) + + if not cow: + self.assertEquals(self._fetched_image, self._instance_ide_disks[0]) + + def test_attach_volume(self): + instance_data = self._get_instance_data() + instance_name = instance_data['name'] - def _attach_volume(self): - self._spawn_instance(True) connection_info = db_fakes.get_fake_volume_info_data( self._volume_target_portal, self._volume_id) + data = connection_info['data'] + target_lun = data['target_lun'] + target_iqn = data['target_iqn'] + target_portal = data['target_portal'] - self._conn.attach_volume(connection_info, - self._instance_data, '/dev/sdc') + mount_point = '/dev/sdc' - def test_attach_volume(self): - self._attach_volume() + volumeutils.VolumeUtils.login_storage_target(target_lun, + target_iqn, + target_portal) + + fake_mounted_disk = "fake_mounted_disk" + fake_device_number = 0 + fake_controller_path = 'fake_scsi_controller_path' + fake_free_slot = 1 + + m = volumeutils.VolumeUtils.get_device_number_for_target(target_iqn, + target_lun) + m.AndReturn(fake_device_number) + + m = vmutils.VMUtils.get_mounted_disk_by_drive_number( + fake_device_number) + m.AndReturn(fake_mounted_disk) - (_, volumes_paths, _) = self._hypervutils.get_vm_disks( - self._instance_data["name"]) - self.assertEquals(len(volumes_paths), 1) + m = vmutils.VMUtils.get_vm_iscsi_controller(instance_name) + m.AndReturn(fake_controller_path) - sessions_exist = self._hypervutils.iscsi_volume_sessions_exist( - self._volume_id) - self.assertTrue(sessions_exist) + m = vmutils.VMUtils.get_attached_disks_count(fake_controller_path) + m.AndReturn(fake_free_slot) + + m = vmutils.VMUtils.attach_volume_to_controller(instance_name, + fake_controller_path, + fake_free_slot, + fake_mounted_disk) + m.WithSideEffects(self._add_volume_disk) + + self._mox.ReplayAll() + self._conn.attach_volume(connection_info, instance_data, mount_point) + self._mox.VerifyAll() + + self.assertEquals(len(self._instance_volume_disks), 1) def test_detach_volume(self): - self._attach_volume() + instance_data = self._get_instance_data() + instance_name = instance_data['name'] + connection_info = db_fakes.get_fake_volume_info_data( self._volume_target_portal, self._volume_id) + data = connection_info['data'] + target_lun = data['target_lun'] + target_iqn = data['target_iqn'] + target_portal = data['target_portal'] + mount_point = '/dev/sdc' - self._conn.detach_volume(connection_info, - self._instance_data, '/dev/sdc') + fake_mounted_disk = "fake_mounted_disk" + fake_device_number = 0 + fake_free_slot = 1 + m = volumeutils.VolumeUtils.get_device_number_for_target(target_iqn, + target_lun) + m.AndReturn(fake_device_number) - (_, volumes_paths, _) = self._hypervutils.get_vm_disks( - self._instance_data["name"]) - self.assertEquals(len(volumes_paths), 0) + m = vmutils.VMUtils.get_mounted_disk_by_drive_number( + fake_device_number) + m.AndReturn(fake_mounted_disk) - sessions_exist = self._hypervutils.iscsi_volume_sessions_exist( - self._volume_id) - self.assertFalse(sessions_exist) + vmutils.VMUtils.detach_vm_disk(mox.IsA(str), fake_mounted_disk) + + volumeutils.VolumeUtils.logout_storage_target(mox.IsA(str)) + + self._mox.ReplayAll() + self._conn.detach_volume(connection_info, instance_data, mount_point) + self._mox.VerifyAll() def test_boot_from_volume(self): + connection_info = db_fakes.get_fake_volume_info_data( + self._volume_target_portal, self._volume_id) + data = connection_info['data'] + target_lun = data['target_lun'] + target_iqn = data['target_iqn'] + target_portal = data['target_portal'] + block_device_info = db_fakes.get_fake_block_device_info( self._volume_target_portal, self._volume_id) - self._spawn_instance(False, block_device_info) + fake_mounted_disk = "fake_mounted_disk" + fake_device_number = 0 + fake_controller_path = 'fake_scsi_controller_path' + + volumeutils.VolumeUtils.login_storage_target(target_lun, + target_iqn, + target_portal) + + m = volumeutils.VolumeUtils.get_device_number_for_target(target_iqn, + target_lun) + m.AndReturn(fake_device_number) - (_, volumes_paths, _) = self._hypervutils.get_vm_disks( - self._instance_data["name"]) + m = vmutils.VMUtils.get_mounted_disk_by_drive_number( + fake_device_number) + m.AndReturn(fake_mounted_disk) - self.assertEquals(len(volumes_paths), 1) + m = vmutils.VMUtils.get_vm_ide_controller(mox.IsA(str), mox.IsA(int)) + m.AndReturn(fake_controller_path) + + m = vmutils.VMUtils.attach_volume_to_controller(mox.IsA(str), + fake_controller_path, + 0, + fake_mounted_disk) + m.WithSideEffects(self._add_volume_disk) + + self._setup_spawn_instance_mocks(cow=False, + block_device_info=block_device_info) + + self._mox.ReplayAll() + self._spawn_instance(False, block_device_info) + self._mox.VerifyAll() - sessions_exist = self._hypervutils.iscsi_volume_sessions_exist( - self._volume_id) - self.assertTrue(sessions_exist) + self.assertEquals(len(self._instance_volume_disks), 1) diff --git a/nova/virt/hyperv/__init__.py b/nova/virt/hyperv/__init__.py index e69de29bb..090fc0639 100644 --- a/nova/virt/hyperv/__init__.py +++ b/nova/virt/hyperv/__init__.py @@ -0,0 +1,16 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Cloudbase Solutions Srl +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. diff --git a/nova/virt/hyperv/baseops.py b/nova/virt/hyperv/baseops.py deleted file mode 100644 index 5b617f898..000000000 --- a/nova/virt/hyperv/baseops.py +++ /dev/null @@ -1,69 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 Cloudbase Solutions Srl -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Management base class for Hyper-V operations. -""" -import sys - -from nova.openstack.common import log as logging - -# Check needed for unit testing on Unix -if sys.platform == 'win32': - import wmi - -LOG = logging.getLogger(__name__) - - -class BaseOps(object): - def __init__(self): - self.__conn = None - self.__conn_v2 = None - self.__conn_cimv2 = None - self.__conn_wmi = None - self.__conn_storage = None - - @property - def _conn(self): - if self.__conn is None: - self.__conn = wmi.WMI(moniker='//./root/virtualization') - return self.__conn - - @property - def _conn_v2(self): - if self.__conn_v2 is None: - self.__conn_v2 = wmi.WMI(moniker='//./root/virtualization/v2') - return self.__conn_v2 - - @property - def _conn_cimv2(self): - if self.__conn_cimv2 is None: - self.__conn_cimv2 = wmi.WMI(moniker='//./root/cimv2') - return self.__conn_cimv2 - - @property - def _conn_wmi(self): - if self.__conn_wmi is None: - self.__conn_wmi = wmi.WMI(moniker='//./root/wmi') - return self.__conn_wmi - - @property - def _conn_storage(self): - if self.__conn_storage is None: - storage_namespace = '//./Root/Microsoft/Windows/Storage' - self.__conn_storage = wmi.WMI(moniker=storage_namespace) - return self.__conn_storage diff --git a/nova/virt/hyperv/basevolumeutils.py b/nova/virt/hyperv/basevolumeutils.py index 2352c3bef..34b15ea53 100644 --- a/nova/virt/hyperv/basevolumeutils.py +++ b/nova/virt/hyperv/basevolumeutils.py @@ -1,6 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # # Copyright 2012 Pedro Navarro Perez +# Copyright 2013 Cloudbase Solutions Srl # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -20,17 +21,18 @@ Helper methods for operations related to the management of volumes, and storage repositories """ +import abc import sys +if sys.platform == 'win32': + import _winreg + import wmi + from nova import block_device from nova.openstack.common import cfg from nova.openstack.common import log as logging from nova.virt import driver -# Check needed for unit testing on Unix -if sys.platform == 'win32': - import _winreg - LOG = logging.getLogger(__name__) CONF = cfg.CONF CONF.import_opt('my_ip', 'nova.netconf') @@ -38,25 +40,40 @@ CONF.import_opt('my_ip', 'nova.netconf') class BaseVolumeUtils(object): + def __init__(self): + if sys.platform == 'win32': + self._conn_wmi = wmi.WMI(moniker='//./root/wmi') + + @abc.abstractmethod + def login_storage_target(self, target_lun, target_iqn, target_portal): + pass + + @abc.abstractmethod + def logout_storage_target(self, target_iqn): + pass + + @abc.abstractmethod + def execute_log_out(self, session_id): + pass + def get_iscsi_initiator(self, cim_conn): """Get iscsi initiator name for this machine.""" computer_system = cim_conn.Win32_ComputerSystem()[0] hostname = computer_system.name - keypath = \ - r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\iSCSI\Discovery" + keypath = ("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\" + "iSCSI\\Discovery") try: key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keypath, 0, - _winreg.KEY_ALL_ACCESS) + _winreg.KEY_ALL_ACCESS) temp = _winreg.QueryValueEx(key, 'DefaultInitiatorName') initiator_name = str(temp[0]) _winreg.CloseKey(key) except Exception: LOG.info(_("The ISCSI initiator name can't be found. " - "Choosing the default one")) + "Choosing the default one")) computer_system = cim_conn.Win32_ComputerSystem()[0] - initiator_name = "iqn.1991-05.com.microsoft:" + \ - hostname.lower() + initiator_name = "iqn.1991-05.com.microsoft:" + hostname.lower() return { 'ip': CONF.my_ip, 'initiator': initiator_name, @@ -78,3 +95,33 @@ class BaseVolumeUtils(object): LOG.debug(_("block_device_list %s"), block_device_list) return block_device.strip_dev(mount_device) in block_device_list + + def _get_drive_number_from_disk_path(self, disk_path): + # TODO(pnavarro) replace with regex + start_device_id = disk_path.find('"', disk_path.find('DeviceID')) + end_device_id = disk_path.find('"', start_device_id + 1) + device_id = disk_path[start_device_id + 1:end_device_id] + return device_id[device_id.find("\\") + 2:] + + def get_session_id_from_mounted_disk(self, physical_drive_path): + drive_number = self._get_drive_number_from_disk_path( + physical_drive_path) + initiator_sessions = self._conn_wmi.query("SELECT * FROM " + "MSiSCSIInitiator_Session" + "Class") + for initiator_session in initiator_sessions: + devices = initiator_session.Devices + for device in devices: + device_number = str(device.DeviceNumber) + if device_number == drive_number: + return initiator_session.SessionId + + def get_device_number_for_target(self, target_iqn, target_lun): + initiator_session = self._conn_wmi.query("SELECT * FROM " + "MSiSCSIInitiator_Session" + "Class WHERE TargetName='%s'" + % target_iqn)[0] + devices = initiator_session.Devices + for device in devices: + if device.ScsiLun == target_lun: + return device.DeviceNumber diff --git a/nova/virt/hyperv/constants.py b/nova/virt/hyperv/constants.py index 4be569e88..31323f0f4 100644 --- a/nova/virt/hyperv/constants.py +++ b/nova/virt/hyperv/constants.py @@ -35,15 +35,6 @@ HYPERV_POWER_STATE = { HYPERV_VM_STATE_SUSPENDED: power_state.SUSPENDED } -REQ_POWER_STATE = { - 'Enabled': HYPERV_VM_STATE_ENABLED, - 'Disabled': HYPERV_VM_STATE_DISABLED, - 'Reboot': HYPERV_VM_STATE_REBOOT, - 'Reset': HYPERV_VM_STATE_RESET, - 'Paused': HYPERV_VM_STATE_PAUSED, - 'Suspended': HYPERV_VM_STATE_SUSPENDED, -} - WMI_WIN32_PROCESSOR_ARCHITECTURE = { 0: 'x86', 1: 'MIPS', diff --git a/nova/virt/hyperv/driver.py b/nova/virt/hyperv/driver.py index 9316b2598..e8bf8c416 100644 --- a/nova/virt/hyperv/driver.py +++ b/nova/virt/hyperv/driver.py @@ -16,49 +16,7 @@ # under the License. """ -A connection to Hyper-V . -Uses Windows Management Instrumentation (WMI) calls to interact with Hyper-V -Hyper-V WMI usage: - http://msdn.microsoft.com/en-us/library/cc723875%28v=VS.85%29.aspx -The Hyper-V object model briefly: - The physical computer and its hosted virtual machines are each represented - by the Msvm_ComputerSystem class. - - Each virtual machine is associated with a - Msvm_VirtualSystemGlobalSettingData (vs_gs_data) instance and one or more - Msvm_VirtualSystemSettingData (vmsetting) instances. For each vmsetting - there is a series of Msvm_ResourceAllocationSettingData (rasd) objects. - The rasd objects describe the settings for each device in a VM. - Together, the vs_gs_data, vmsettings and rasds describe the configuration - of the virtual machine. - - Creating new resources such as disks and nics involves cloning a default - rasd object and appropriately modifying the clone and calling the - AddVirtualSystemResources WMI method - Changing resources such as memory uses the ModifyVirtualSystemResources - WMI method - -Using the Python WMI library: - Tutorial: - http://timgolden.me.uk/python/wmi/tutorial.html - Hyper-V WMI objects can be retrieved simply by using the class name - of the WMI object and optionally specifying a column to filter the - result set. More complex filters can be formed using WQL (sql-like) - queries. - The parameters and return tuples of WMI method calls can gleaned by - examining the doc string. For example: - >>> vs_man_svc.ModifyVirtualSystemResources.__doc__ - ModifyVirtualSystemResources (ComputerSystem, ResourceSettingData[]) - => (Job, ReturnValue)' - When passing setting data (ResourceSettingData) to the WMI method, - an XML representation of the data is passed in using GetText_(1). - Available methods on a service can be determined using method.keys(): - >>> vs_man_svc.methods.keys() - vmsettings and rasds for a vm can be retrieved using the 'associators' - method with the appropriate return class. - Long running WMI commands generally return a Job (an instance of - Msvm_ConcreteJob) whose state can be polled to determine when it finishes - +A Hyper-V Nova Compute driver. """ from nova.openstack.common import log as logging @@ -84,7 +42,7 @@ class HyperVDriver(driver.ComputeDriver): self._volumeops) def init_host(self, host): - self._host = host + pass def list_instances(self): return self._vmops.list_instances() @@ -92,7 +50,7 @@ class HyperVDriver(driver.ComputeDriver): def spawn(self, context, instance, image_meta, injected_files, admin_password, network_info=None, block_device_info=None): self._vmops.spawn(context, instance, image_meta, injected_files, - admin_password, network_info, block_device_info) + admin_password, network_info, block_device_info) def reboot(self, instance, network_info, reboot_type, block_device_info=None): @@ -106,16 +64,12 @@ class HyperVDriver(driver.ComputeDriver): return self._vmops.get_info(instance) def attach_volume(self, connection_info, instance, mountpoint): - """Attach volume storage to VM instance.""" return self._volumeops.attach_volume(connection_info, - instance['name'], - mountpoint) + instance['name']) def detach_volume(self, connection_info, instance, mountpoint): - """Detach volume storage to VM instance.""" return self._volumeops.detach_volume(connection_info, - instance['name'], - mountpoint) + instance['name']) def get_volume_connector(self, instance): return self._volumeops.get_volume_connector(instance) @@ -151,30 +105,38 @@ class HyperVDriver(driver.ComputeDriver): self._vmops.power_on(instance) def live_migration(self, context, instance_ref, dest, post_method, - recover_method, block_migration=False, migrate_data=None): + recover_method, block_migration=False, + migrate_data=None): self._livemigrationops.live_migration(context, instance_ref, dest, - post_method, recover_method, block_migration, migrate_data) + post_method, recover_method, + block_migration, migrate_data) def compare_cpu(self, cpu_info): return self._livemigrationops.compare_cpu(cpu_info) def pre_live_migration(self, context, instance, block_device_info, - network_info, migrate_data=None): + network_info, migrate_data=None): self._livemigrationops.pre_live_migration(context, instance, - block_device_info, network_info) + block_device_info, + network_info) def post_live_migration_at_destination(self, ctxt, instance_ref, - network_info, block_migration, block_device_info=None): + network_info, + block_migr=False, + block_device_info=None): self._livemigrationops.post_live_migration_at_destination(ctxt, - instance_ref, network_info, block_migration) - - def check_can_live_migrate_destination(self, ctxt, instance, - src_compute_info, dst_compute_info, - block_migration, disk_over_commit): + instance_ref, + network_info, + block_migr) + + def check_can_live_migrate_destination(self, ctxt, instance_ref, + src_compute_info, dst_compute_info, + block_migration=False, + disk_over_commit=False): pass def check_can_live_migrate_destination_cleanup(self, ctxt, - dest_check_data): + dest_check_data): pass def check_can_live_migrate_source(self, ctxt, instance, dest_check_data): @@ -188,25 +150,21 @@ class HyperVDriver(driver.ComputeDriver): def ensure_filtering_rules_for_instance(self, instance_ref, network_info): LOG.debug(_("ensure_filtering_rules_for_instance called"), - instance=instance_ref) + instance=instance_ref) def unfilter_instance(self, instance, network_info): - """Stop filtering instance.""" LOG.debug(_("unfilter_instance called"), instance=instance) def confirm_migration(self, migration, instance, network_info): - """Confirms a resize, destroying the source VM.""" LOG.debug(_("confirm_migration called"), instance=instance) def finish_revert_migration(self, instance, network_info, block_device_info=None): - """Finish reverting a resize, powering back on the instance.""" LOG.debug(_("finish_revert_migration called"), instance=instance) def finish_migration(self, context, migration, instance, disk_info, - network_info, image_meta, resize_instance=False, - block_device_info=None): - """Completes a resize, turning on the migrated instance.""" + network_info, image_meta, resize_instance=False, + block_device_info=None): LOG.debug(_("finish_migration called"), instance=instance) def get_console_output(self, instance): diff --git a/nova/virt/hyperv/hostops.py b/nova/virt/hyperv/hostops.py index 5cbe46c1c..5a22b60de 100644 --- a/nova/virt/hyperv/hostops.py +++ b/nova/virt/hyperv/hostops.py @@ -18,25 +18,23 @@ """ Management class for host operations. """ -import ctypes -import multiprocessing import os import platform -from nova.openstack.common import cfg from nova.openstack.common import jsonutils from nova.openstack.common import log as logging -from nova.virt.hyperv import baseops from nova.virt.hyperv import constants +from nova.virt.hyperv import hostutils +from nova.virt.hyperv import pathutils -CONF = cfg.CONF LOG = logging.getLogger(__name__) -class HostOps(baseops.BaseOps): +class HostOps(object): def __init__(self): - super(HostOps, self).__init__() self._stats = None + self._hostutils = hostutils.HostUtils() + self._pathutils = pathutils.PathUtils() def _get_cpu_info(self): """Get the CPU information. @@ -44,94 +42,51 @@ class HostOps(baseops.BaseOps): of the central processor in the hypervisor. """ cpu_info = dict() - processor = self._conn_cimv2.query( - "SELECT * FROM Win32_Processor WHERE ProcessorType = 3") - cpu_info['arch'] = constants.WMI_WIN32_PROCESSOR_ARCHITECTURE\ - .get(processor[0].Architecture, 'Unknown') - cpu_info['model'] = processor[0].Name - cpu_info['vendor'] = processor[0].Manufacturer + processors = self._hostutils.get_cpus_info() + + w32_arch_dict = constants.WMI_WIN32_PROCESSOR_ARCHITECTURE + cpu_info['arch'] = w32_arch_dict.get(processors[0]['Architecture'], + 'Unknown') + cpu_info['model'] = processors[0]['Name'] + cpu_info['vendor'] = processors[0]['Manufacturer'] topology = dict() - topology['sockets'] = len(processor) - topology['cores'] = processor[0].NumberOfCores - topology['threads'] = processor[0].NumberOfLogicalProcessors\ - / processor[0].NumberOfCores + topology['sockets'] = len(processors) + topology['cores'] = processors[0]['NumberOfCores'] + topology['threads'] = (processors[0]['NumberOfLogicalProcessors'] / + processors[0]['NumberOfCores']) cpu_info['topology'] = topology features = list() for fkey, fname in constants.PROCESSOR_FEATURE.items(): - if ctypes.windll.kernel32.IsProcessorFeaturePresent(fkey): + if self._hostutils.is_cpu_feature_present(fkey): features.append(fname) cpu_info['features'] = features - return jsonutils.dumps(cpu_info) + return cpu_info - def _get_vcpu_total(self): - """Get vcpu number of physical computer. - :returns: the number of cpu core. - """ - # On certain platforms, this will raise a NotImplementedError. - try: - return multiprocessing.cpu_count() - except NotImplementedError: - LOG.warn(_("Cannot get the number of cpu, because this " - "function is not implemented for this platform. " - "This error can be safely ignored for now.")) - return 0 - - def _get_memory_mb_total(self): - """Get the total memory size(MB) of physical computer. - :returns: the total amount of memory(MB). - """ - total_kb = self._conn_cimv2.query( - "SELECT TotalVisibleMemorySize FROM win32_operatingsystem")[0]\ - .TotalVisibleMemorySize - total_mb = long(total_kb) / 1024 - return total_mb + def _get_memory_info(self): + (total_mem_kb, free_mem_kb) = self._hostutils.get_memory_info() + total_mem_mb = total_mem_kb / 1024 + free_mem_mb = free_mem_kb / 1024 + return (total_mem_mb, free_mem_mb, total_mem_mb - free_mem_mb) def _get_local_hdd_info_gb(self): - """Get the total and used size of the volume containing - CONF.instances_path expressed in GB. - :returns: - A tuple with the total and used space in GB. - """ - normalized_path = os.path.normpath(CONF.instances_path) - drive, path = os.path.splitdrive(normalized_path) - hdd_info = self._conn_cimv2.query( - ("SELECT FreeSpace,Size FROM win32_logicaldisk WHERE DeviceID='%s'" - ) % drive)[0] - total_gb = long(hdd_info.Size) / (1024 ** 3) - free_gb = long(hdd_info.FreeSpace) / (1024 ** 3) - used_gb = total_gb - free_gb - return total_gb, used_gb + (drive, _) = os.path.splitdrive(self._pathutils.get_instances_path()) + (size, free_space) = self._hostutils.get_volume_info(drive) - def _get_vcpu_used(self): - """Get vcpu usage number of physical computer. - :returns: The total number of vcpu that currently used. - """ - #TODO(jordanrinke) figure out a way to count assigned VCPUs - total_vcpu = 0 - return total_vcpu - - def _get_memory_mb_used(self): - """Get the free memory size(MB) of physical computer. - :returns: the total usage of memory(MB). - """ - total_kb = self._conn_cimv2.query( - "SELECT FreePhysicalMemory FROM win32_operatingsystem")[0]\ - .FreePhysicalMemory - total_mb = long(total_kb) / 1024 - - return total_mb + total_gb = size / (1024 ** 3) + free_gb = free_space / (1024 ** 3) + used_gb = total_gb - free_gb + return (total_gb, free_gb, used_gb) def _get_hypervisor_version(self): """Get hypervisor version. :returns: hypervisor version (ex. 12003) """ - version = self._conn_cimv2.Win32_OperatingSystem()[0]\ - .Version.replace('.', '') - LOG.info(_('Windows version: %s ') % version) + version = self._hostutils.get_windows_version().replace('.', '') + LOG.debug(_('Windows version: %s ') % version) return version def get_available_resource(self): @@ -143,36 +98,53 @@ class HostOps(baseops.BaseOps): :returns: dictionary describing resources """ - LOG.info(_('get_available_resource called')) - - local_gb, used_gb = self._get_local_hdd_info_gb() - dic = {'vcpus': self._get_vcpu_total(), - 'memory_mb': self._get_memory_mb_total(), - 'local_gb': local_gb, - 'vcpus_used': self._get_vcpu_used(), - 'memory_mb_used': self._get_memory_mb_used(), - 'local_gb_used': used_gb, + LOG.debug(_('get_available_resource called')) + + (total_mem_mb, + free_mem_mb, + used_mem_mb) = self._get_memory_info() + + (total_hdd_gb, + free_hdd_gb, + used_hdd_gb) = self._get_local_hdd_info_gb() + + cpu_info = self._get_cpu_info() + cpu_topology = cpu_info['topology'] + vcpus = (cpu_topology['sockets'] * + cpu_topology['cores'] * + cpu_topology['threads']) + + dic = {'vcpus': vcpus, + 'memory_mb': total_mem_mb, + 'memory_mb_used': used_mem_mb, + 'local_gb': total_hdd_gb, + 'local_gb_used': used_hdd_gb, 'hypervisor_type': "hyperv", 'hypervisor_version': self._get_hypervisor_version(), 'hypervisor_hostname': platform.node(), - 'cpu_info': self._get_cpu_info()} + 'vcpus_used': 0, + 'cpu_info': jsonutils.dumps(cpu_info)} return dic def _update_stats(self): LOG.debug(_("Updating host stats")) + (total_mem_mb, free_mem_mb, used_mem_mb) = self._get_memory_info() + (total_hdd_gb, + free_hdd_gb, + used_hdd_gb) = self._get_local_hdd_info_gb() + data = {} - data["disk_total"], data["disk_used"] = self._get_local_hdd_info_gb() - data["disk_available"] = data["disk_total"] - data["disk_used"] - data["host_memory_total"] = self._get_memory_mb_total() - data["host_memory_overhead"] = self._get_memory_mb_used() - data["host_memory_free"] = \ - data["host_memory_total"] - data["host_memory_overhead"] - data["host_memory_free_computed"] = data["host_memory_free"] - data["supported_instances"] = \ - [('i686', 'hyperv', 'hvm'), - ('x86_64', 'hyperv', 'hvm')] + data["disk_total"] = total_hdd_gb + data["disk_used"] = used_hdd_gb + data["disk_available"] = free_hdd_gb + data["host_memory_total"] = total_mem_mb + data["host_memory_overhead"] = used_mem_mb + data["host_memory_free"] = free_mem_mb + data["host_memory_free_computed"] = free_mem_mb + data["supported_instances"] = [('i686', 'hyperv', 'hvm'), + ('x86_64', 'hyperv', 'hvm')] data["hypervisor_hostname"] = platform.node() self._stats = data diff --git a/nova/virt/hyperv/hostutils.py b/nova/virt/hyperv/hostutils.py new file mode 100644 index 000000000..71f3bc5b2 --- /dev/null +++ b/nova/virt/hyperv/hostutils.py @@ -0,0 +1,74 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Cloudbase Solutions Srl +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import ctypes +import sys + +if sys.platform == 'win32': + import wmi + +from nova.openstack.common import log as logging + +LOG = logging.getLogger(__name__) + + +class HostUtils(object): + def __init__(self): + if sys.platform == 'win32': + self._conn_cimv2 = wmi.WMI(moniker='//./root/cimv2') + + def get_cpus_info(self): + cpus = self._conn_cimv2.query("SELECT * FROM Win32_Processor " + "WHERE ProcessorType = 3") + cpus_list = [] + for cpu in cpus: + cpu_info = {'Architecture': cpu.Architecture, + 'Name': cpu.Name, + 'Manufacturer': cpu.Manufacturer, + 'NumberOfCores': cpu.NumberOfCores, + 'NumberOfLogicalProcessors': + cpu.NumberOfLogicalProcessors} + cpus_list.append(cpu_info) + return cpus_list + + def is_cpu_feature_present(self, feature_key): + return ctypes.windll.kernel32.IsProcessorFeaturePresent(feature_key) + + def get_memory_info(self): + """ + Returns a tuple with total visible memory and free physical memory + expressed in kB. + """ + mem_info = self._conn_cimv2.query("SELECT TotalVisibleMemorySize, " + "FreePhysicalMemory " + "FROM win32_operatingsystem")[0] + return (long(mem_info.TotalVisibleMemorySize), + long(mem_info.FreePhysicalMemory)) + + def get_volume_info(self, drive): + """ + Returns a tuple with total size and free space + expressed in bytes. + """ + logical_disk = self._conn_cimv2.query("SELECT Size, FreeSpace " + "FROM win32_logicaldisk " + "WHERE DeviceID='%s'" + % drive)[0] + return (long(logical_disk.Size), long(logical_disk.FreeSpace)) + + def get_windows_version(self): + return self._conn_cimv2.Win32_OperatingSystem()[0].Version diff --git a/nova/virt/hyperv/ioutils.py b/nova/virt/hyperv/ioutils.py deleted file mode 100644 index d927e317f..000000000 --- a/nova/virt/hyperv/ioutils.py +++ /dev/null @@ -1,26 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 Cloudbase Solutions Srl -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Utility class to ease the task of creating stubs of built in IO functions. -""" - -import __builtin__ - - -def open(name, mode): - return __builtin__.open(name, mode) diff --git a/nova/virt/hyperv/livemigrationops.py b/nova/virt/hyperv/livemigrationops.py index 232cbd660..8ee3005f1 100644 --- a/nova/virt/hyperv/livemigrationops.py +++ b/nova/virt/hyperv/livemigrationops.py @@ -19,144 +19,66 @@ Management class for live migration VM operations. """ import os -import sys -from nova import exception from nova.openstack.common import cfg from nova.openstack.common import excutils from nova.openstack.common import log as logging -from nova.virt.hyperv import baseops -from nova.virt.hyperv import constants +from nova.virt.hyperv import livemigrationutils +from nova.virt.hyperv import pathutils from nova.virt.hyperv import vmutils - -# Check needed for unit testing on Unix -if sys.platform == 'win32': - import wmi +from nova.virt import images LOG = logging.getLogger(__name__) CONF = cfg.CONF CONF.import_opt('use_cow_images', 'nova.virt.driver') -class LiveMigrationOps(baseops.BaseOps): +class LiveMigrationOps(object): def __init__(self, volumeops): - super(LiveMigrationOps, self).__init__() + self._pathutils = pathutils.PathUtils() self._vmutils = vmutils.VMUtils() + self._livemigrutils = livemigrationutils.LiveMigrationUtils() self._volumeops = volumeops - def _check_live_migration_config(self): - try: - self._conn_v2 - except Exception: - raise vmutils.HyperVException( - _('Live migration is not supported " \ - "by this version of Hyper-V')) - - migration_svc = self._conn_v2.Msvm_VirtualSystemMigrationService()[0] - vsmssd = migration_svc.associators( - wmi_association_class='Msvm_ElementSettingData', - wmi_result_class='Msvm_VirtualSystemMigrationServiceSettingData')[0] - if not vsmssd.EnableVirtualSystemMigration: - raise vmutils.HyperVException( - _('Live migration is not enabled on this host')) - if not migration_svc.MigrationServiceListenerIPAddressList: - raise vmutils.HyperVException( - _('Live migration networks are not configured on this host')) - def live_migration(self, context, instance_ref, dest, post_method, - recover_method, block_migration=False, migrate_data=None): + recover_method, block_migration=False, + migrate_data=None): LOG.debug(_("live_migration called"), instance=instance_ref) instance_name = instance_ref["name"] try: - self._check_live_migration_config() - - vm_name = self._vmutils.lookup(self._conn, instance_name) - if vm_name is None: - raise exception.InstanceNotFound(instance=instance_name) - vm = self._conn_v2.Msvm_ComputerSystem( - ElementName=instance_name)[0] - vm_settings = vm.associators( - wmi_association_class='Msvm_SettingsDefineState', - wmi_result_class='Msvm_VirtualSystemSettingData')[0] - - new_resource_setting_data = [] - sasds = vm_settings.associators( - wmi_association_class='Msvm_VirtualSystemSettingDataComponent', - wmi_result_class='Msvm_StorageAllocationSettingData') - for sasd in sasds: - if sasd.ResourceType == 31 and \ - sasd.ResourceSubType == \ - "Microsoft:Hyper-V:Virtual Hard Disk": - #sasd.PoolId = "" - new_resource_setting_data.append(sasd.GetText_(1)) - - LOG.debug(_("Getting live migration networks for remote " - "host: %s"), dest) - _conn_v2_remote = wmi.WMI( - moniker='//' + dest + '/root/virtualization/v2') - migration_svc_remote = \ - _conn_v2_remote.Msvm_VirtualSystemMigrationService()[0] - remote_ip_address_list = \ - migration_svc_remote.MigrationServiceListenerIPAddressList - - # VirtualSystemAndStorage - vsmsd = self._conn_v2.query("select * from " - "Msvm_VirtualSystemMigrationSettingData " - "where MigrationType = 32771")[0] - vsmsd.DestinationIPAddressList = remote_ip_address_list - migration_setting_data = vsmsd.GetText_(1) - - migration_svc =\ - self._conn_v2.Msvm_VirtualSystemMigrationService()[0] - - LOG.debug(_("Starting live migration for instance: %s"), - instance_name) - (job_path, ret_val) = migration_svc.MigrateVirtualSystemToHost( - ComputerSystem=vm.path_(), - DestinationHost=dest, - MigrationSettingData=migration_setting_data, - NewResourceSettingData=new_resource_setting_data) - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self._vmutils.check_job_status(job_path) - else: - success = (ret_val == 0) - if not success: - raise vmutils.HyperVException( - _('Failed to live migrate VM %s') % instance_name) + self._livemigrutils.live_migrate_vm(instance_name, dest) except Exception: with excutils.save_and_reraise_exception(): LOG.debug(_("Calling live migration recover_method " - "for instance: %s"), instance_name) + "for instance: %s"), instance_name) recover_method(context, instance_ref, dest, block_migration) LOG.debug(_("Calling live migration post_method for instance: %s"), - instance_name) + instance_name) post_method(context, instance_ref, dest, block_migration) def pre_live_migration(self, context, instance, block_device_info, - network_info): + network_info): LOG.debug(_("pre_live_migration called"), instance=instance) - self._check_live_migration_config() + self._livemigrutils.check_live_migration_config() if CONF.use_cow_images: ebs_root = self._volumeops.volume_in_mapping( self._volumeops.get_default_root_device(), block_device_info) if not ebs_root: - base_vhd_path = self._vmutils.get_base_vhd_path( + base_vhd_path = self._pathutils.get_base_vhd_path( instance["image_ref"]) if not os.path.exists(base_vhd_path): - self._vmutils.fetch_image(base_vhd_path, context, - instance["image_ref"], - instance["user_id"], - instance["project_id"]) + images.fetch(context, instance["image_ref"], base_vhd_path, + instance["user_id"], instance["project_id"]) def post_live_migration_at_destination(self, ctxt, instance_ref, - network_info, block_migration): + network_info, block_migration): LOG.debug(_("post_live_migration_at_destination called"), - instance=instance_ref) + instance=instance_ref) def compare_cpu(self, cpu_info): LOG.debug(_("compare_cpu called %s"), cpu_info) diff --git a/nova/virt/hyperv/livemigrationutils.py b/nova/virt/hyperv/livemigrationutils.py new file mode 100644 index 000000000..6af4f0fa5 --- /dev/null +++ b/nova/virt/hyperv/livemigrationutils.py @@ -0,0 +1,115 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Cloudbase Solutions Srl +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import sys + +if sys.platform == 'win32': + import wmi + +from nova.openstack.common import log as logging +from nova.virt.hyperv import vmutils + +LOG = logging.getLogger(__name__) + + +class LiveMigrationUtils(object): + + def __init__(self): + self._vmutils = vmutils.VMUtils() + + def _get_conn_v2(self, host='localhost'): + try: + return wmi.WMI(moniker='//%s/root/virtualization/v2' % host) + except wmi.x_wmi as ex: + LOG.exception(ex) + if ex.com_error.hresult == -2147217394: + msg = (_('Live migration is not supported on target host "%s"') + % host) + elif ex.com_error.hresult == -2147023174: + msg = (_('Target live migration host "%s" is unreachable') + % host) + else: + msg = _('Live migration failed: %s') % ex.message + raise vmutils.HyperVException(msg) + + def check_live_migration_config(self): + conn_v2 = self._get_conn_v2() + migration_svc = conn_v2.Msvm_VirtualSystemMigrationService()[0] + vsmssds = migration_svc.associators( + wmi_association_class='Msvm_ElementSettingData', + wmi_result_class='Msvm_VirtualSystemMigrationServiceSettingData') + vsmssd = vsmssds[0] + if not vsmssd.EnableVirtualSystemMigration: + raise vmutils.HyperVException( + _('Live migration is not enabled on this host')) + if not migration_svc.MigrationServiceListenerIPAddressList: + raise vmutils.HyperVException( + _('Live migration networks are not configured on this host')) + + def _get_vm(self, conn_v2, vm_name): + vms = conn_v2.Msvm_ComputerSystem(ElementName=vm_name) + n = len(vms) + if not n: + raise vmutils.HyperVException(_('VM not found: %s') % vm_name) + elif n > 1: + raise vmutils.HyperVException(_('Duplicate VM name found: %s') + % vm_name) + return vms[0] + + def live_migrate_vm(self, vm_name, dest_host): + self.check_live_migration_config() + + # We need a v2 namespace VM object + conn_v2_local = self._get_conn_v2() + + vm = self._get_vm(conn_v2_local, vm_name) + vm_settings = vm.associators( + wmi_association_class='Msvm_SettingsDefineState', + wmi_result_class='Msvm_VirtualSystemSettingData')[0] + + new_resource_setting_data = [] + sasds = vm_settings.associators( + wmi_association_class='Msvm_VirtualSystemSettingDataComponent', + wmi_result_class='Msvm_StorageAllocationSettingData') + for sasd in sasds: + if (sasd.ResourceType == 31 and sasd.ResourceSubType == + "Microsoft:Hyper-V:Virtual Hard Disk"): + #sasd.PoolId = "" + new_resource_setting_data.append(sasd.GetText_(1)) + + LOG.debug(_("Getting live migration networks for remote host: %s"), + dest_host) + conn_v2_remote = self._get_conn_v2(dest_host) + migr_svc_rmt = conn_v2_remote.Msvm_VirtualSystemMigrationService()[0] + rmt_ip_addr_list = migr_svc_rmt.MigrationServiceListenerIPAddressList + + # VirtualSystemAndStorage + vsmsd = conn_v2_local.query("select * from " + "Msvm_VirtualSystemMigrationSettingData " + "where MigrationType = 32771")[0] + vsmsd.DestinationIPAddressList = rmt_ip_addr_list + migration_setting_data = vsmsd.GetText_(1) + + migr_svc = conn_v2_local.Msvm_VirtualSystemMigrationService()[0] + + LOG.debug(_("Starting live migration for VM: %s"), vm_name) + (job_path, ret_val) = migr_svc.MigrateVirtualSystemToHost( + ComputerSystem=vm.path_(), + DestinationHost=dest_host, + MigrationSettingData=migration_setting_data, + NewResourceSettingData=new_resource_setting_data) + self._vmutils.check_ret_val(ret_val, job_path) diff --git a/nova/virt/hyperv/networkutils.py b/nova/virt/hyperv/networkutils.py new file mode 100644 index 000000000..4e1f68685 --- /dev/null +++ b/nova/virt/hyperv/networkutils.py @@ -0,0 +1,62 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# +# Copyright 2013 Cloudbase Solutions Srl +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +Utility class for network related operations. +""" + +import sys +import uuid + +if sys.platform == 'win32': + import wmi + +from nova.virt.hyperv import vmutils + + +class NetworkUtils(object): + def __init__(self): + if sys.platform == 'win32': + self._conn = wmi.WMI(moniker='//./root/virtualization') + + def get_external_vswitch(self, vswitch_name): + if vswitch_name: + vswitches = self._conn.Msvm_VirtualSwitch(ElementName=vswitch_name) + else: + # Find the vswitch that is connected to the first physical nic. + ext_port = self._conn.Msvm_ExternalEthernetPort(IsBound='TRUE')[0] + port = ext_port.associators(wmi_result_class='Msvm_SwitchPort')[0] + vswitches = port.associators(wmi_result_class='Msvm_VirtualSwitch') + + if not len(vswitches): + raise vmutils.HyperVException(_('vswitch "%s" not found') + % vswitch_name) + return vswitches[0].path_() + + def create_vswitch_port(self, vswitch_path, port_name): + switch_svc = self._conn.Msvm_VirtualSwitchManagementService()[0] + #Create a port on the vswitch. + (new_port, ret_val) = switch_svc.CreateSwitchPort( + Name=str(uuid.uuid4()), + FriendlyName=port_name, + ScopeOfResidence="", + VirtualSwitch=vswitch_path) + if ret_val != 0: + raise vmutils.HyperVException(_("Failed to create vswitch port " + "%(port_name)s on switch " + "%(vswitch_path)s") % locals()) + return new_port diff --git a/nova/virt/hyperv/pathutils.py b/nova/virt/hyperv/pathutils.py new file mode 100644 index 000000000..7bc2e7ac2 --- /dev/null +++ b/nova/virt/hyperv/pathutils.py @@ -0,0 +1,67 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# +# Copyright 2013 Cloudbase Solutions Srl +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import os +import shutil + +from nova.openstack.common import cfg +from nova.openstack.common import log as logging + +LOG = logging.getLogger(__name__) + +CONF = cfg.CONF +CONF.import_opt('instances_path', 'nova.compute.manager') + + +class PathUtils(object): + def open(self, path, mode): + """Wrapper on __builin__.open used to simplify unit testing.""" + import __builtin__ + return __builtin__.open(path, mode) + + def get_instances_path(self): + return os.path.normpath(CONF.instances_path) + + def get_instance_path(self, instance_name): + instance_path = os.path.join(self.get_instances_path(), instance_name) + if not os.path.exists(instance_path): + LOG.debug(_('Creating folder %s '), instance_path) + os.makedirs(instance_path) + return instance_path + + def get_vhd_path(self, instance_name): + instance_path = self.get_instance_path(instance_name) + return os.path.join(instance_path, instance_name + ".vhd") + + def get_base_vhd_path(self, image_name): + base_dir = os.path.join(self.get_instances_path(), '_base') + if not os.path.exists(base_dir): + os.makedirs(base_dir) + return os.path.join(base_dir, image_name + ".vhd") + + def make_export_path(self, instance_name): + export_folder = os.path.join(self.get_instances_path(), "export", + instance_name) + if os.path.isdir(export_folder): + LOG.debug(_('Removing existing folder %s '), export_folder) + shutil.rmtree(export_folder) + LOG.debug(_('Creating folder %s '), export_folder) + os.makedirs(export_folder) + return export_folder + + def vhd_exists(self, path): + return os.path.exists(path) diff --git a/nova/virt/hyperv/snapshotops.py b/nova/virt/hyperv/snapshotops.py index cdc6e45a4..c43f59b70 100644 --- a/nova/virt/hyperv/snapshotops.py +++ b/nova/virt/hyperv/snapshotops.py @@ -20,173 +20,97 @@ Management class for VM snapshot operations. """ import os import shutil -import sys from nova.compute import task_states -from nova import exception from nova.image import glance from nova.openstack.common import cfg from nova.openstack.common import log as logging -from nova.virt.hyperv import baseops -from nova.virt.hyperv import constants -from nova.virt.hyperv import ioutils +from nova.virt.hyperv import pathutils +from nova.virt.hyperv import vhdutils from nova.virt.hyperv import vmutils -from xml.etree import ElementTree - -# Check needed for unit testing on Unix -if sys.platform == 'win32': - import wmi CONF = cfg.CONF LOG = logging.getLogger(__name__) -class SnapshotOps(baseops.BaseOps): +class SnapshotOps(object): def __init__(self): - super(SnapshotOps, self).__init__() + self._pathutils = pathutils.PathUtils() self._vmutils = vmutils.VMUtils() + self._vhdutils = vhdutils.VHDUtils() + + def _save_glance_image(self, context, name, image_vhd_path): + (glance_image_service, + image_id) = glance.get_remote_image_service(context, name) + image_metadata = {"is_public": False, + "disk_format": "vhd", + "container_format": "bare", + "properties": {}} + with self._pathutils.open(image_vhd_path, 'rb') as f: + glance_image_service.update(context, image_id, image_metadata, f) def snapshot(self, context, instance, name, update_task_state): """Create snapshot from a running VM instance.""" instance_name = instance["name"] - vm = self._vmutils.lookup(self._conn, instance_name) - if vm is None: - raise exception.InstanceNotFound(instance=instance_name) - vm = self._conn.Msvm_ComputerSystem(ElementName=instance_name)[0] - vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0] LOG.debug(_("Creating snapshot for instance %s"), instance_name) - (job_path, ret_val, snap_setting_data) = \ - vs_man_svc.CreateVirtualSystemSnapshot(vm.path_()) - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self._vmutils.check_job_status(job_path) - if success: - job_wmi_path = job_path.replace('\\', '/') - job = wmi.WMI(moniker=job_wmi_path) - snap_setting_data = job.associators( - wmi_result_class='Msvm_VirtualSystemSettingData')[0] - else: - success = (ret_val == 0) - if not success: - raise vmutils.HyperVException( - _('Failed to create snapshot for VM %s') % - instance_name) - else: - update_task_state(task_state=task_states.IMAGE_PENDING_UPLOAD) + snapshot_path = self._vmutils.take_vm_snapshot(instance_name) + update_task_state(task_state=task_states.IMAGE_PENDING_UPLOAD) export_folder = None - f = None try: - src_vhd_path = os.path.join(CONF.instances_path, instance_name, - instance_name + ".vhd") - - image_man_svc = self._conn.Msvm_ImageManagementService()[0] + src_vhd_path = self._pathutils.get_vhd_path(instance_name) LOG.debug(_("Getting info for VHD %s"), src_vhd_path) - (src_vhd_info, job_path, ret_val) = \ - image_man_svc.GetVirtualHardDiskInfo(src_vhd_path) - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self._vmutils.check_job_status(job_path) - else: - success = (ret_val == 0) - if not success: - raise vmutils.HyperVException( - _("Failed to get info for disk %s") % - (src_vhd_path)) + src_base_disk_path = self._vhdutils.get_vhd_parent_path( + src_vhd_path) - src_base_disk_path = None - et = ElementTree.fromstring(src_vhd_info) - for item in et.findall("PROPERTY"): - if item.attrib["NAME"] == "ParentPath": - src_base_disk_path = item.find("VALUE").text - break - - export_folder = self._vmutils.make_export_path(instance_name) + export_folder = self._pathutils.make_export_path(instance_name) dest_vhd_path = os.path.join(export_folder, os.path.basename( src_vhd_path)) LOG.debug(_('Copying VHD %(src_vhd_path)s to %(dest_vhd_path)s'), - locals()) + locals()) shutil.copyfile(src_vhd_path, dest_vhd_path) image_vhd_path = None if not src_base_disk_path: image_vhd_path = dest_vhd_path else: - dest_base_disk_path = os.path.join(export_folder, - os.path.basename(src_base_disk_path)) + basename = os.path.basename(src_base_disk_path) + dest_base_disk_path = os.path.join(export_folder, basename) LOG.debug(_('Copying base disk %(src_vhd_path)s to ' - '%(dest_base_disk_path)s'), locals()) + '%(dest_base_disk_path)s'), locals()) shutil.copyfile(src_base_disk_path, dest_base_disk_path) LOG.debug(_("Reconnecting copied base VHD " - "%(dest_base_disk_path)s and diff VHD %(dest_vhd_path)s"), - locals()) - (job_path, ret_val) = \ - image_man_svc.ReconnectParentVirtualHardDisk( - ChildPath=dest_vhd_path, - ParentPath=dest_base_disk_path, - Force=True) - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self._vmutils.check_job_status(job_path) - else: - success = (ret_val == 0) - if not success: - raise vmutils.HyperVException( - _("Failed to reconnect base disk " - "%(dest_base_disk_path)s and diff disk " - "%(dest_vhd_path)s") % - locals()) + "%(dest_base_disk_path)s and diff " + "VHD %(dest_vhd_path)s"), locals()) + self._vhdutils.reconnect_parent_vhd(dest_vhd_path, + dest_base_disk_path) LOG.debug(_("Merging base disk %(dest_base_disk_path)s and " - "diff disk %(dest_vhd_path)s"), - locals()) - (job_path, ret_val) = image_man_svc.MergeVirtualHardDisk( - SourcePath=dest_vhd_path, - DestinationPath=dest_base_disk_path) - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self._vmutils.check_job_status(job_path) - else: - success = (ret_val == 0) - if not success: - raise vmutils.HyperVException( - _("Failed to merge base disk %(dest_base_disk_path)s " - "and diff disk %(dest_vhd_path)s") % - locals()) + "diff disk %(dest_vhd_path)s"), locals()) + self._vhdutils.merge_vhd(dest_vhd_path, dest_base_disk_path) image_vhd_path = dest_base_disk_path - (glance_image_service, image_id) = \ - glance.get_remote_image_service(context, name) - image_metadata = {"is_public": False, - "disk_format": "vhd", - "container_format": "bare", - "properties": {}} - f = ioutils.open(image_vhd_path, 'rb') - LOG.debug( - _("Updating Glance image %(image_id)s with content from " - "merged disk %(image_vhd_path)s"), - locals()) + LOG.debug(_("Updating Glance image %(image_id)s with content from " + "merged disk %(image_vhd_path)s"), locals()) update_task_state(task_state=task_states.IMAGE_UPLOADING, expected_state=task_states.IMAGE_PENDING_UPLOAD) - glance_image_service.update(context, image_id, image_metadata, f) + self._save_glance_image(context, name, image_vhd_path) LOG.debug(_("Snapshot image %(image_id)s updated for VM " - "%(instance_name)s"), locals()) + "%(instance_name)s"), locals()) finally: - LOG.debug(_("Removing snapshot %s"), name) - (job_path, ret_val) = vs_man_svc.RemoveVirtualSystemSnapshot( - snap_setting_data.path_()) - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self._vmutils.check_job_status(job_path) - else: - success = (ret_val == 0) - if not success: - raise vmutils.HyperVException( - _('Failed to remove snapshot for VM %s') % - instance_name) - if f: - f.close() + try: + LOG.debug(_("Removing snapshot %s"), name) + self._vmutils.remove_vm_snapshot(snapshot_path) + except Exception as ex: + LOG.exception(ex) + LOG.warning(_('Failed to remove snapshot for VM %s') + % instance_name) if export_folder: LOG.debug(_('Removing folder %s '), export_folder) shutil.rmtree(export_folder) diff --git a/nova/virt/hyperv/vhdutils.py b/nova/virt/hyperv/vhdutils.py new file mode 100644 index 000000000..21c4b4a6d --- /dev/null +++ b/nova/virt/hyperv/vhdutils.py @@ -0,0 +1,72 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Cloudbase Solutions Srl +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import sys + +if sys.platform == 'win32': + import wmi + +from nova.virt.hyperv import vmutils +from xml.etree import ElementTree + + +class VHDUtils(object): + + def __init__(self): + self._vmutils = vmutils.VMUtils() + if sys.platform == 'win32': + self._conn = wmi.WMI(moniker='//./root/virtualization') + + def create_differencing_vhd(self, path, parent_path): + image_man_svc = self._conn.Msvm_ImageManagementService()[0] + + (job_path, ret_val) = image_man_svc.CreateDifferencingVirtualHardDisk( + Path=path, ParentPath=parent_path) + self._vmutils.check_ret_val(ret_val, job_path) + + def reconnect_parent_vhd(self, child_vhd_path, parent_vhd_path): + image_man_svc = self._conn.Msvm_ImageManagementService()[0] + + (job_path, ret_val) = image_man_svc.ReconnectParentVirtualHardDisk( + ChildPath=child_vhd_path, + ParentPath=parent_vhd_path, + Force=True) + self._vmutils.check_ret_val(ret_val, job_path) + + def merge_vhd(self, src_vhd_path, dest_vhd_path): + image_man_svc = self._conn.Msvm_ImageManagementService()[0] + + (job_path, ret_val) = image_man_svc.MergeVirtualHardDisk( + SourcePath=src_vhd_path, + DestinationPath=dest_vhd_path) + self._vmutils.check_ret_val(ret_val, job_path) + + def get_vhd_parent_path(self, vhd_path): + image_man_svc = self._conn.Msvm_ImageManagementService()[0] + + (vhd_info, + job_path, + ret_val) = image_man_svc.GetVirtualHardDiskInfo(vhd_path) + self._vmutils.check_ret_val(ret_val, job_path) + + base_disk_path = None + et = ElementTree.fromstring(vhd_info) + for item in et.findall("PROPERTY"): + if item.attrib["NAME"] == "ParentPath": + base_disk_path = item.find("VALUE").text + break + return base_disk_path diff --git a/nova/virt/hyperv/vif.py b/nova/virt/hyperv/vif.py index e01006eaa..cfe7c6a4c 100644 --- a/nova/virt/hyperv/vif.py +++ b/nova/virt/hyperv/vif.py @@ -15,17 +15,12 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -import abc -import sys -import uuid - -# Check needed for unit testing on Unix -if sys.platform == 'win32': - import wmi +import abc from nova.openstack.common import cfg from nova.openstack.common import log as logging +from nova.virt.hyperv import networkutils from nova.virt.hyperv import vmutils @@ -70,65 +65,17 @@ class HyperVNovaNetworkVIFDriver(HyperVBaseVIFDriver): def __init__(self): self._vmutils = vmutils.VMUtils() - self._conn = wmi.WMI(moniker='//./root/virtualization') - - def _find_external_network(self): - """Find the vswitch that is connected to the physical nic. - Assumes only one physical nic on the host - """ - #If there are no physical nics connected to networks, return. - LOG.debug(_("Attempting to bind NIC to %s ") - % CONF.vswitch_name) - if CONF.vswitch_name: - LOG.debug(_("Attempting to bind NIC to %s ") - % CONF.vswitch_name) - bound = self._conn.Msvm_VirtualSwitch( - ElementName=CONF.vswitch_name) - else: - LOG.debug(_("No vSwitch specified, attaching to default")) - self._conn.Msvm_ExternalEthernetPort(IsBound='TRUE') - if len(bound) == 0: - return None - if CONF.vswitch_name: - return self._conn.Msvm_VirtualSwitch( - ElementName=CONF.vswitch_name)[0]\ - .associators(wmi_result_class='Msvm_SwitchPort')[0]\ - .associators(wmi_result_class='Msvm_VirtualSwitch')[0] - else: - return self._conn.Msvm_ExternalEthernetPort(IsBound='TRUE')\ - .associators(wmi_result_class='Msvm_SwitchPort')[0]\ - .associators(wmi_result_class='Msvm_VirtualSwitch')[0] + self._netutils = networkutils.NetworkUtils() def plug(self, instance, vif): - extswitch = self._find_external_network() - if extswitch is None: - raise vmutils.HyperVException(_('Cannot find vSwitch')) + vswitch_path = self._netutils.get_external_vswitch( + CONF.vswitch_name) vm_name = instance['name'] - - nic_data = self._conn.Msvm_SyntheticEthernetPortSettingData( - ElementName=vif['id'])[0] - - switch_svc = self._conn.Msvm_VirtualSwitchManagementService()[0] - #Create a port on the vswitch. - (new_port, ret_val) = switch_svc.CreateSwitchPort( - Name=str(uuid.uuid4()), - FriendlyName=vm_name, - ScopeOfResidence="", - VirtualSwitch=extswitch.path_()) - if ret_val != 0: - LOG.error(_('Failed creating a port on the external vswitch')) - raise vmutils.HyperVException(_('Failed creating port for %s') % - vm_name) - ext_path = extswitch.path_() - LOG.debug(_("Created switch port %(vm_name)s on switch %(ext_path)s") - % locals()) - - vms = self._conn.MSVM_ComputerSystem(ElementName=vm_name) - vm = vms[0] - - nic_data.Connection = [new_port] - self._vmutils.modify_virt_resource(self._conn, nic_data, vm) + LOG.debug(_('Creating vswitch port for instance: %s') % vm_name) + vswitch_port = self._netutils.create_vswitch_port(vswitch_path, + vm_name) + self._vmutils.set_nic_connection(vm_name, vif['id'], vswitch_port) def unplug(self, instance, vif): #TODO(alepilotti) Not implemented diff --git a/nova/virt/hyperv/vmops.py b/nova/virt/hyperv/vmops.py index 3d8958266..8ce1d508b 100644 --- a/nova/virt/hyperv/vmops.py +++ b/nova/virt/hyperv/vmops.py @@ -19,7 +19,6 @@ Management class for basic VM operations. """ import os -import uuid from nova.api.metadata import base as instance_metadata from nova import exception @@ -29,29 +28,31 @@ from nova.openstack.common import lockutils from nova.openstack.common import log as logging from nova import utils from nova.virt import configdrive -from nova.virt.hyperv import baseops from nova.virt.hyperv import constants +from nova.virt.hyperv import pathutils +from nova.virt.hyperv import vhdutils from nova.virt.hyperv import vmutils +from nova.virt import images LOG = logging.getLogger(__name__) hyperv_opts = [ cfg.BoolOpt('limit_cpu_features', - default=False, - help='Required for live migration among ' - 'hosts with different CPU features'), + default=False, + help='Required for live migration among ' + 'hosts with different CPU features'), cfg.BoolOpt('config_drive_inject_password', - default=False, - help='Sets the admin password in the config drive image'), + default=False, + help='Sets the admin password in the config drive image'), cfg.StrOpt('qemu_img_cmd', default="qemu-img.exe", help='qemu-img is used to convert between ' 'different image types'), cfg.BoolOpt('config_drive_cdrom', - default=False, - help='Attaches the Config Drive image as a cdrom drive ' - 'instead of a disk drive') - ] + default=False, + help='Attaches the Config Drive image as a cdrom drive ' + 'instead of a disk drive') +] CONF = cfg.CONF CONF.register_opts(hyperv_opts) @@ -59,19 +60,20 @@ CONF.import_opt('use_cow_images', 'nova.virt.driver') CONF.import_opt('network_api_class', 'nova.network') -class VMOps(baseops.BaseOps): +class VMOps(object): _vif_driver_class_map = { 'nova.network.quantumv2.api.API': - 'nova.virt.hyperv.vif.HyperVQuantumVIFDriver', + 'nova.virt.hyperv.vif.HyperVQuantumVIFDriver', 'nova.network.api.API': - 'nova.virt.hyperv.vif.HyperVNovaNetworkVIFDriver', + 'nova.virt.hyperv.vif.HyperVNovaNetworkVIFDriver', } def __init__(self, volumeops): - super(VMOps, self).__init__() - self._vmutils = vmutils.VMUtils() + self._vhdutils = vhdutils.VHDUtils() + self._pathutils = pathutils.PathUtils() self._volumeops = volumeops + self._vif_driver = None self._load_vif_driver_class() def _load_vif_driver_class(self): @@ -84,124 +86,106 @@ class VMOps(baseops.BaseOps): CONF.network_api_class) def list_instances(self): - """Return the names of all the instances known to Hyper-V.""" - vms = [v.ElementName - for v in self._conn.Msvm_ComputerSystem(['ElementName'], - Caption="Virtual Machine")] - return vms + return self._vmutils.list_instances() def get_info(self, instance): """Get information about the VM.""" LOG.debug(_("get_info called for instance"), instance=instance) - return self._get_info(instance['name']) - - def _get_info(self, instance_name): - vm = self._vmutils.lookup(self._conn, instance_name) - if vm is None: - raise exception.InstanceNotFound(instance=instance_name) - vm = self._conn.Msvm_ComputerSystem( - ElementName=instance_name)[0] - vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0] - vmsettings = vm.associators( - wmi_association_class='Msvm_SettingsDefineState', - wmi_result_class='Msvm_VirtualSystemSettingData') - settings_paths = [v.path_() for v in vmsettings] - #See http://msdn.microsoft.com/en-us/library/cc160706%28VS.85%29.aspx - summary_info = vs_man_svc.GetSummaryInformation( - [constants.VM_SUMMARY_NUM_PROCS, - constants.VM_SUMMARY_ENABLED_STATE, - constants.VM_SUMMARY_MEMORY_USAGE, - constants.VM_SUMMARY_UPTIME], - settings_paths)[1] - info = summary_info[0] - - LOG.debug(_("hyperv vm state: %s"), info.EnabledState) - state = constants.HYPERV_POWER_STATE[info.EnabledState] - memusage = str(info.MemoryUsage) - numprocs = str(info.NumberOfProcessors) - uptime = str(info.UpTime) - - LOG.debug(_("Got Info for vm %(instance_name)s: state=%(state)d," - " mem=%(memusage)s, num_cpu=%(numprocs)s," - " uptime=%(uptime)s"), locals()) + instance_name = instance['name'] + if not self._vmutils.vm_exists(instance_name): + raise exception.InstanceNotFound(instance=instance) + + info = self._vmutils.get_vm_summary_info(instance_name) + + state = constants.HYPERV_POWER_STATE[info['EnabledState']] return {'state': state, - 'max_mem': info.MemoryUsage, - 'mem': info.MemoryUsage, - 'num_cpu': info.NumberOfProcessors, - 'cpu_time': info.UpTime} + 'max_mem': info['MemoryUsage'], + 'mem': info['MemoryUsage'], + 'num_cpu': info['NumberOfProcessors'], + 'cpu_time': info['UpTime']} def spawn(self, context, instance, image_meta, injected_files, - admin_password, network_info, block_device_info=None): + admin_password, network_info, block_device_info=None): """Create a new VM and start it.""" - vm = self._vmutils.lookup(self._conn, instance['name']) - if vm is not None: - raise exception.InstanceExists(name=instance['name']) + + instance_name = instance['name'] + if self._vmutils.vm_exists(instance_name): + raise exception.InstanceExists(name=instance_name) ebs_root = self._volumeops.volume_in_mapping( self._volumeops.get_default_root_device(), - block_device_info) + block_device_info) #If is not a boot from volume spawn if not (ebs_root): #Fetch the file, assume it is a VHD file. - vhdfile = self._vmutils.get_vhd_path(instance['name']) + vhdfile = self._pathutils.get_vhd_path(instance_name) try: - self._cache_image(fn=self._vmutils.fetch_image, - context=context, - target=vhdfile, - fname=instance['image_ref'], - image_id=instance['image_ref'], - user=instance['user_id'], - project=instance['project_id'], - cow=CONF.use_cow_images) + self._cache_image(fn=self._fetch_image, + context=context, + target=vhdfile, + fname=instance['image_ref'], + image_id=instance['image_ref'], + user=instance['user_id'], + project=instance['project_id'], + cow=CONF.use_cow_images) except Exception as exn: LOG.exception(_('cache image failed: %s'), exn) - self.destroy(instance) + raise try: - self._create_vm(instance) + self._vmutils.create_vm(instance_name, + instance['memory_mb'], + instance['vcpus'], + CONF.limit_cpu_features) if not ebs_root: - self._attach_ide_drive(instance['name'], vhdfile, 0, 0, - constants.IDE_DISK) + self._vmutils.attach_ide_drive(instance_name, + vhdfile, + 0, + 0, + constants.IDE_DISK) else: self._volumeops.attach_boot_volume(block_device_info, - instance['name']) + instance_name) - #A SCSI controller for volumes connection is created - self._create_scsi_controller(instance['name']) + self._vmutils.create_scsi_controller(instance_name) for vif in network_info: - self._create_nic(instance['name'], vif) + LOG.debug(_('Creating nic for instance: %s'), instance_name) + self._vmutils.create_nic(instance_name, + vif['id'], + vif['address']) self._vif_driver.plug(instance, vif) if configdrive.required_by(instance): self._create_config_drive(instance, injected_files, - admin_password) + admin_password) - LOG.debug(_('Starting VM %s '), instance['name']) - self._set_vm_state(instance['name'], 'Enabled') - LOG.info(_('Started VM %s '), instance['name']) - except Exception as exn: - LOG.exception(_('spawn vm failed: %s'), exn) + self._set_vm_state(instance_name, + constants.HYPERV_VM_STATE_ENABLED) + except Exception as ex: + LOG.exception(ex) self.destroy(instance) - raise exn + raise vmutils.HyperVException(_('Spawn instance failed')) def _create_config_drive(self, instance, injected_files, admin_password): if CONF.config_drive_format != 'iso9660': vmutils.HyperVException(_('Invalid config_drive_format "%s"') % - CONF.config_drive_format) + CONF.config_drive_format) + + LOG.info(_('Using config drive for instance: %s'), instance=instance) - LOG.info(_('Using config drive'), instance=instance) extra_md = {} if admin_password and CONF.config_drive_inject_password: extra_md['admin_pass'] = admin_password inst_md = instance_metadata.InstanceMetadata(instance, - content=injected_files, extra_md=extra_md) + content=injected_files, + extra_md=extra_md) - instance_path = self._vmutils.get_instance_path( + instance_path = self._pathutils.get_instance_path( instance['name']) configdrive_path_iso = os.path.join(instance_path, 'configdrive.iso') LOG.info(_('Creating config drive at %(path)s'), @@ -218,7 +202,7 @@ class VMOps(baseops.BaseOps): if not CONF.config_drive_cdrom: drive_type = constants.IDE_DISK configdrive_path = os.path.join(instance_path, - 'configdrive.vhd') + 'configdrive.vhd') utils.execute(CONF.qemu_img_cmd, 'convert', '-f', @@ -233,302 +217,88 @@ class VMOps(baseops.BaseOps): drive_type = constants.IDE_DVD configdrive_path = configdrive_path_iso - self._attach_ide_drive(instance['name'], configdrive_path, 1, 0, - drive_type) - - def _create_vm(self, instance): - """Create a VM but don't start it.""" - vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0] + self._vmutils.attach_ide_drive(instance['name'], configdrive_path, + 1, 0, drive_type) - vs_gs_data = self._conn.Msvm_VirtualSystemGlobalSettingData.new() - vs_gs_data.ElementName = instance["name"] - (job, ret_val) = vs_man_svc.DefineVirtualSystem( - [], None, vs_gs_data.GetText_(1))[1:] - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self._vmutils.check_job_status(job) - else: - success = (ret_val == 0) - - if not success: - raise vmutils.HyperVException(_('Failed to create VM %s') % - instance["name"]) - - LOG.debug(_('Created VM %s...'), instance["name"]) - vm = self._conn.Msvm_ComputerSystem(ElementName=instance["name"])[0] - - vmsettings = vm.associators( - wmi_result_class='Msvm_VirtualSystemSettingData') - vmsetting = [s for s in vmsettings - if s.SettingType == 3][0] # avoid snapshots - memsetting = vmsetting.associators( - wmi_result_class='Msvm_MemorySettingData')[0] - #No Dynamic Memory, so reservation, limit and quantity are identical. - mem = long(str(instance['memory_mb'])) - memsetting.VirtualQuantity = mem - memsetting.Reservation = mem - memsetting.Limit = mem - - (job, ret_val) = vs_man_svc.ModifyVirtualSystemResources( - vm.path_(), [memsetting.GetText_(1)]) - LOG.debug(_('Set memory for vm %s...'), instance["name"]) - procsetting = vmsetting.associators( - wmi_result_class='Msvm_ProcessorSettingData')[0] - vcpus = long(instance['vcpus']) - procsetting.VirtualQuantity = vcpus - procsetting.Reservation = vcpus - procsetting.Limit = 100000 # static assignment to 100% - - if CONF.limit_cpu_features: - procsetting.LimitProcessorFeatures = True - - (job, ret_val) = vs_man_svc.ModifyVirtualSystemResources( - vm.path_(), [procsetting.GetText_(1)]) - LOG.debug(_('Set vcpus for vm %s...'), instance["name"]) - - def _create_scsi_controller(self, vm_name): - """Create an iscsi controller ready to mount volumes.""" - LOG.debug(_('Creating a scsi controller for %(vm_name)s for volume ' - 'attaching') % locals()) - vms = self._conn.MSVM_ComputerSystem(ElementName=vm_name) - vm = vms[0] - scsicontrldefault = self._conn.query( - "SELECT * FROM Msvm_ResourceAllocationSettingData \ - WHERE ResourceSubType = 'Microsoft Synthetic SCSI Controller'\ - AND InstanceID LIKE '%Default%'")[0] - if scsicontrldefault is None: - raise vmutils.HyperVException(_('Controller not found')) - scsicontrl = self._vmutils.clone_wmi_obj(self._conn, - 'Msvm_ResourceAllocationSettingData', scsicontrldefault) - scsicontrl.VirtualSystemIdentifiers = ['{' + str(uuid.uuid4()) + '}'] - scsiresource = self._vmutils.add_virt_resource(self._conn, - scsicontrl, vm) - if scsiresource is None: - raise vmutils.HyperVException( - _('Failed to add scsi controller to VM %s') % - vm_name) - - def _get_ide_controller(self, vm, ctrller_addr): - #Find the IDE controller for the vm. - vmsettings = vm.associators( - wmi_result_class='Msvm_VirtualSystemSettingData') - rasds = vmsettings[0].associators( - wmi_result_class='MSVM_ResourceAllocationSettingData') - ctrller = [r for r in rasds - if r.ResourceSubType == 'Microsoft Emulated IDE Controller' - and r.Address == str(ctrller_addr)] - return ctrller - - def _attach_ide_drive(self, vm_name, path, ctrller_addr, drive_addr, - drive_type=constants.IDE_DISK): - """Create an IDE drive and attach it to the vm.""" - LOG.debug(_('Creating disk for %(vm_name)s by attaching' - ' disk file %(path)s') % locals()) - - vms = self._conn.MSVM_ComputerSystem(ElementName=vm_name) - vm = vms[0] - - ctrller = self._get_ide_controller(vm, ctrller_addr) - - if drive_type == constants.IDE_DISK: - resSubType = 'Microsoft Synthetic Disk Drive' - elif drive_type == constants.IDE_DVD: - resSubType = 'Microsoft Synthetic DVD Drive' - - #Find the default disk drive object for the vm and clone it. - drivedflt = self._conn.query( - "SELECT * FROM Msvm_ResourceAllocationSettingData \ - WHERE ResourceSubType LIKE '%(resSubType)s'\ - AND InstanceID LIKE '%%Default%%'" % locals())[0] - drive = self._vmutils.clone_wmi_obj(self._conn, - 'Msvm_ResourceAllocationSettingData', drivedflt) - #Set the IDE ctrller as parent. - drive.Parent = ctrller[0].path_() - drive.Address = drive_addr - #Add the cloned disk drive object to the vm. - new_resources = self._vmutils.add_virt_resource(self._conn, - drive, vm) - if new_resources is None: - raise vmutils.HyperVException( - _('Failed to add drive to VM %s') % - vm_name) - drive_path = new_resources[0] - LOG.debug(_('New %(drive_type)s drive path is %(drive_path)s') % - locals()) - - if drive_type == constants.IDE_DISK: - resSubType = 'Microsoft Virtual Hard Disk' - elif drive_type == constants.IDE_DVD: - resSubType = 'Microsoft Virtual CD/DVD Disk' - - #Find the default VHD disk object. - drivedefault = self._conn.query( - "SELECT * FROM Msvm_ResourceAllocationSettingData \ - WHERE ResourceSubType LIKE '%(resSubType)s' AND \ - InstanceID LIKE '%%Default%%' " % locals())[0] - - #Clone the default and point it to the image file. - res = self._vmutils.clone_wmi_obj(self._conn, - 'Msvm_ResourceAllocationSettingData', drivedefault) - #Set the new drive as the parent. - res.Parent = drive_path - res.Connection = [path] - - #Add the new vhd object as a virtual hard disk to the vm. - new_resources = self._vmutils.add_virt_resource(self._conn, res, vm) - if new_resources is None: - raise vmutils.HyperVException( - _('Failed to add %(drive_type)s image to VM %(vm_name)s') % - locals()) - LOG.info(_('Created drive type %(drive_type)s for %(vm_name)s') % - locals()) - - def _create_nic(self, vm_name, vif): - """Create a (synthetic) nic and attach it to the vm.""" - LOG.debug(_('Creating nic for %s '), vm_name) - - #Create a new nic - syntheticnics_data = self._conn.Msvm_SyntheticEthernetPortSettingData() - default_nic_data = [n for n in syntheticnics_data - if n.InstanceID.rfind('Default') > 0] - new_nic_data = self._vmutils.clone_wmi_obj(self._conn, - 'Msvm_SyntheticEthernetPortSettingData', - default_nic_data[0]) - - #Configure the nic - new_nic_data.ElementName = vif['id'] - new_nic_data.Address = vif['address'].replace(':', '') - new_nic_data.StaticMacAddress = 'True' - new_nic_data.VirtualSystemIdentifiers = ['{' + str(uuid.uuid4()) + '}'] - - #Add the new nic to the vm - vms = self._conn.Msvm_ComputerSystem(ElementName=vm_name) - vm = vms[0] - - new_resources = self._vmutils.add_virt_resource(self._conn, - new_nic_data, vm) - if new_resources is None: - raise vmutils.HyperVException(_('Failed to add nic to VM %s') % - vm_name) - LOG.info(_("Created nic for %s "), vm_name) + def destroy(self, instance, network_info=None, cleanup=True, + destroy_disks=True): + instance_name = instance['name'] + LOG.debug(_("Got request to destroy instance: %s"), instance_name) + try: + if self._vmutils.vm_exists(instance_name): + volumes_drives_list = self._vmutils.destroy_vm(instance_name, + destroy_disks) + #Disconnect volumes + for volume_drive in volumes_drives_list: + self._volumeops.disconnect_volume(volume_drive) + else: + LOG.debug(_("Instance not found: %s"), instance_name) + except Exception as ex: + LOG.exception(ex) + raise vmutils.HyperVException(_('Failed to destroy instance: %s') % + instance_name) def reboot(self, instance, network_info, reboot_type): """Reboot the specified instance.""" - vm = self._vmutils.lookup(self._conn, instance['name']) - if vm is None: - raise exception.InstanceNotFound(instance_id=instance["id"]) - self._set_vm_state(instance['name'], 'Reboot') - - def destroy(self, instance, network_info=None, cleanup=True, - destroy_disks=True): - """Destroy the VM. Also destroy the associated VHD disk files.""" - LOG.debug(_("Got request to destroy vm %s"), instance['name']) - vm = self._vmutils.lookup(self._conn, instance['name']) - if vm is None: - return - vm = self._conn.Msvm_ComputerSystem(ElementName=instance['name'])[0] - vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0] - #Stop the VM first. - self._set_vm_state(instance['name'], 'Disabled') - vmsettings = vm.associators( - wmi_result_class='Msvm_VirtualSystemSettingData') - rasds = vmsettings[0].associators( - wmi_result_class='MSVM_ResourceAllocationSettingData') - disks = [r for r in rasds - if r.ResourceSubType == 'Microsoft Virtual Hard Disk'] - disk_files = [] - volumes = [r for r in rasds - if r.ResourceSubType == 'Microsoft Physical Disk Drive'] - volumes_drives_list = [] - #collect the volumes information before destroying the VM. - for volume in volumes: - hostResources = volume.HostResource - drive_path = hostResources[0] - #Appending the Msvm_Disk path - volumes_drives_list.append(drive_path) - #Collect disk file information before destroying the VM. - for disk in disks: - disk_files.extend([c for c in disk.Connection]) - #Nuke the VM. Does not destroy disks. - (job, ret_val) = vs_man_svc.DestroyVirtualSystem(vm.path_()) - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self._vmutils.check_job_status(job) - elif ret_val == 0: - success = True - if not success: - raise vmutils.HyperVException(_('Failed to destroy vm %s') % - instance['name']) - if destroy_disks: - #Disconnect volumes - for volume_drive in volumes_drives_list: - self._volumeops.disconnect_volume(volume_drive) - #Delete associated vhd disk files. - for disk in disk_files: - vhdfile = self._conn_cimv2.query( - "Select * from CIM_DataFile where Name = '" + - disk.replace("'", "''") + "'")[0] - LOG.debug(_("Del: disk %(vhdfile)s vm %(name)s") - % {'vhdfile': vhdfile, 'name': instance['name']}) - vhdfile.Delete() + LOG.debug(_("reboot instance"), instance=instance) + self._set_vm_state(instance['name'], + constants.HYPERV_VM_STATE_REBOOT) def pause(self, instance): """Pause VM instance.""" LOG.debug(_("Pause instance"), instance=instance) - self._set_vm_state(instance["name"], 'Paused') + self._set_vm_state(instance["name"], + constants.HYPERV_VM_STATE_PAUSED) def unpause(self, instance): """Unpause paused VM instance.""" LOG.debug(_("Unpause instance"), instance=instance) - self._set_vm_state(instance["name"], 'Enabled') + self._set_vm_state(instance["name"], + constants.HYPERV_VM_STATE_ENABLED) def suspend(self, instance): """Suspend the specified instance.""" print instance LOG.debug(_("Suspend instance"), instance=instance) - self._set_vm_state(instance["name"], 'Suspended') + self._set_vm_state(instance["name"], + constants.HYPERV_VM_STATE_SUSPENDED) def resume(self, instance): """Resume the suspended VM instance.""" LOG.debug(_("Resume instance"), instance=instance) - self._set_vm_state(instance["name"], 'Enabled') + self._set_vm_state(instance["name"], + constants.HYPERV_VM_STATE_ENABLED) def power_off(self, instance): """Power off the specified instance.""" LOG.debug(_("Power off instance"), instance=instance) - self._set_vm_state(instance["name"], 'Disabled') + self._set_vm_state(instance["name"], + constants.HYPERV_VM_STATE_DISABLED) def power_on(self, instance): """Power on the specified instance.""" LOG.debug(_("Power on instance"), instance=instance) - self._set_vm_state(instance["name"], 'Enabled') + self._set_vm_state(instance["name"], + constants.HYPERV_VM_STATE_ENABLED) def _set_vm_state(self, vm_name, req_state): - """Set the desired state of the VM.""" - vms = self._conn.Msvm_ComputerSystem(ElementName=vm_name) - if len(vms) == 0: - return False - (job, ret_val) = vms[0].RequestStateChange( - constants.REQ_POWER_STATE[req_state]) - success = False - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self._vmutils.check_job_status(job) - elif ret_val == 0: - success = True - elif ret_val == 32775: - #Invalid state for current operation. Typically means it is - #already in the state requested - success = True - if success: - LOG.info(_("Successfully changed vm state of %(vm_name)s" - " to %(req_state)s") % locals()) - else: + try: + self._vmutils.set_vm_state(vm_name, req_state) + LOG.debug(_("Successfully changed state of VM %(vm_name)s" + " to: %(req_state)s") % locals()) + except Exception as ex: + LOG.exception(ex) msg = _("Failed to change vm state of %(vm_name)s" " to %(req_state)s") % locals() - LOG.error(msg) raise vmutils.HyperVException(msg) - def _cache_image(self, fn, target, fname, cow=False, Size=None, - *args, **kwargs): - """Wrapper for a method that creates an image that caches the image. + def _fetch_image(self, target, context, image_id, user, project, + *args, **kwargs): + images.fetch(context, image_id, target, user, project) + + def _cache_image(self, fn, target, fname, cow=False, size=None, + *args, **kwargs): + """Wrapper for a method that creates and caches an image. This wrapper will save the image into a common store and create a copy for use by the hypervisor. @@ -543,32 +313,23 @@ class VMOps(baseops.BaseOps): """ @lockutils.synchronized(fname, 'nova-') def call_if_not_exists(path, fn, *args, **kwargs): - if not os.path.exists(path): - fn(target=path, *args, **kwargs) + if not os.path.exists(path): + fn(target=path, *args, **kwargs) - if not os.path.exists(target): - LOG.debug(_("use_cow_image:%s"), cow) + if not self._pathutils.vhd_exists(target): + LOG.debug(_("Use CoW image: %s"), cow) if cow: - base = self._vmutils.get_base_vhd_path(fname) - call_if_not_exists(base, fn, *args, **kwargs) - - image_service = self._conn.query( - "Select * from Msvm_ImageManagementService")[0] - (job, ret_val) = \ - image_service.CreateDifferencingVirtualHardDisk( - Path=target, ParentPath=base) - LOG.debug( - "Creating difference disk: JobID=%s, Source=%s, Target=%s", - job, base, target) - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self._vmutils.check_job_status(job) - else: - success = (ret_val == 0) - - if not success: + parent_path = self._pathutils.get_base_vhd_path(fname) + call_if_not_exists(parent_path, fn, *args, **kwargs) + + LOG.debug(_("Creating differencing VHD. Parent: " + "%(parent_path)s, Target: %(target)s") % locals()) + try: + self._vhdutils.create_differencing_vhd(target, parent_path) + except Exception as ex: + LOG.exception(ex) raise vmutils.HyperVException( - _('Failed to create Difference Disk from ' - '%(base)s to %(target)s') % locals()) - + _('Failed to create a differencing disk from ' + '%(parent_path)s to %(target)s') % locals()) else: call_if_not_exists(target, fn, *args, **kwargs) diff --git a/nova/virt/hyperv/vmutils.py b/nova/virt/hyperv/vmutils.py index d899f977d..0305d8306 100644 --- a/nova/virt/hyperv/vmutils.py +++ b/nova/virt/hyperv/vmutils.py @@ -16,24 +16,20 @@ # under the License. """ -Utility class for VM related operations. +Utility class for VM related operations on Hyper-V. """ -import os -import shutil import sys import time import uuid +if sys.platform == 'win32': + import wmi + from nova import exception from nova.openstack.common import cfg from nova.openstack.common import log as logging from nova.virt.hyperv import constants -from nova.virt import images - -# Check needed for unit testing on Unix -if sys.platform == 'win32': - import wmi CONF = cfg.CONF LOG = logging.getLogger(__name__) @@ -45,19 +41,342 @@ class HyperVException(exception.NovaException): class VMUtils(object): - def lookup(self, conn, i): - vms = conn.Msvm_ComputerSystem(ElementName=i) + + def __init__(self): + if sys.platform == 'win32': + self._conn = wmi.WMI(moniker='//./root/virtualization') + self._conn_cimv2 = wmi.WMI(moniker='//./root/cimv2') + + def list_instances(self): + """Return the names of all the instances known to Hyper-V.""" + vm_names = [v.ElementName + for v in self._conn.Msvm_ComputerSystem(['ElementName'], + Caption="Virtual Machine")] + return vm_names + + def get_vm_summary_info(self, vm_name): + vm = self._lookup_vm_check(vm_name) + + vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0] + vmsettings = vm.associators( + wmi_association_class='Msvm_SettingsDefineState', + wmi_result_class='Msvm_VirtualSystemSettingData') + settings_paths = [v.path_() for v in vmsettings] + #See http://msdn.microsoft.com/en-us/library/cc160706%28VS.85%29.aspx + (ret_val, summary_info) = vs_man_svc.GetSummaryInformation( + [constants.VM_SUMMARY_NUM_PROCS, + constants.VM_SUMMARY_ENABLED_STATE, + constants.VM_SUMMARY_MEMORY_USAGE, + constants.VM_SUMMARY_UPTIME], + settings_paths) + if ret_val: + raise HyperVException(_('Cannot get VM summary data for: %s') + % vm_name) + + si = summary_info[0] + memory_usage = None + if si.MemoryUsage is not None: + memory_usage = long(si.MemoryUsage) + up_time = None + if si.UpTime is not None: + up_time = long(si.UpTime) + + summary_info_dict = {'NumberOfProcessors': si.NumberOfProcessors, + 'EnabledState': si.EnabledState, + 'MemoryUsage': memory_usage, + 'UpTime': up_time} + return summary_info_dict + + def _lookup_vm_check(self, vm_name): + vm = self._lookup_vm(vm_name) + if not vm: + raise HyperVException(_('VM not found: %s') % vm_name) + return vm + + def _lookup_vm(self, vm_name): + vms = self._conn.Msvm_ComputerSystem(ElementName=vm_name) n = len(vms) if n == 0: return None elif n > 1: - raise HyperVException(_('duplicate name found: %s') % i) + raise HyperVException(_('Duplicate VM name found: %s') % vm_name) else: - return vms[0].ElementName + return vms[0] + + def vm_exists(self, vm_name): + return self._lookup_vm(vm_name) is not None + + def _get_vm_setting_data(self, vm): + vmsettings = vm.associators( + wmi_result_class='Msvm_VirtualSystemSettingData') + # Avoid snapshots + return [s for s in vmsettings if s.SettingType == 3][0] + + def _set_vm_memory(self, vm, vmsetting, memory_mb): + memsetting = vmsetting.associators( + wmi_result_class='Msvm_MemorySettingData')[0] + #No Dynamic Memory, so reservation, limit and quantity are identical. + mem = long(memory_mb) + memsetting.VirtualQuantity = mem + memsetting.Reservation = mem + memsetting.Limit = mem + + self._modify_virt_resource(memsetting, vm.path_()) + + def _set_vm_vcpus(self, vm, vmsetting, vcpus_num, limit_cpu_features): + procsetting = vmsetting.associators( + wmi_result_class='Msvm_ProcessorSettingData')[0] + vcpus = long(vcpus_num) + procsetting.VirtualQuantity = vcpus + procsetting.Reservation = vcpus + procsetting.Limit = 100000 # static assignment to 100% + procsetting.LimitProcessorFeatures = limit_cpu_features + + self._modify_virt_resource(procsetting, vm.path_()) + + def create_vm(self, vm_name, memory_mb, vcpus_num, limit_cpu_features): + """Creates a VM.""" + vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0] + + vs_gs_data = self._conn.Msvm_VirtualSystemGlobalSettingData.new() + vs_gs_data.ElementName = vm_name + + LOG.debug(_('Creating VM %s'), vm_name) + (job_path, + ret_val) = vs_man_svc.DefineVirtualSystem([], None, + vs_gs_data.GetText_(1))[1:] + self.check_ret_val(ret_val, job_path) + + vm = self._lookup_vm_check(vm_name) + vmsetting = self._get_vm_setting_data(vm) + + LOG.debug(_('Setting memory for vm %s'), vm_name) + self._set_vm_memory(vm, vmsetting, memory_mb) + + LOG.debug(_('Set vCPUs for vm %s'), vm_name) + self._set_vm_vcpus(vm, vmsetting, vcpus_num, limit_cpu_features) + + def get_vm_iscsi_controller(self, vm_name): + vm = self._lookup_vm_check(vm_name) + + vmsettings = vm.associators( + wmi_result_class='Msvm_VirtualSystemSettingData') + rasds = vmsettings[0].associators( + wmi_result_class='MSVM_ResourceAllocationSettingData') + res = [r for r in rasds + if r.ResourceSubType == + 'Microsoft Synthetic SCSI Controller'][0] + return res.path_() + + def _get_vm_ide_controller(self, vm, ctrller_addr): + vmsettings = vm.associators( + wmi_result_class='Msvm_VirtualSystemSettingData') + rasds = vmsettings[0].associators( + wmi_result_class='MSVM_ResourceAllocationSettingData') + return [r for r in rasds + if r.ResourceSubType == 'Microsoft Emulated IDE Controller' + and r.Address == str(ctrller_addr)][0].path_() + + def get_vm_ide_controller(self, vm_name, ctrller_addr): + vm = self._lookup_vm_check(vm_name) + return self._get_vm_ide_controller(vm, ctrller_addr) + + def get_attached_disks_count(self, scsi_controller_path): + volumes = self._conn.query("SELECT * FROM " + "Msvm_ResourceAllocationSettingData " + "WHERE ResourceSubType LIKE " + "'Microsoft Physical Disk Drive' " + "AND Parent = '%s'" % + scsi_controller_path.replace("'", "''")) + return len(volumes) + + def attach_ide_drive(self, vm_name, path, ctrller_addr, drive_addr, + drive_type=constants.IDE_DISK): + """Create an IDE drive and attach it to the vm.""" + + vm = self._lookup_vm_check(vm_name) + + ctrller_path = self._get_vm_ide_controller(vm, ctrller_addr) + + if drive_type == constants.IDE_DISK: + res_sub_type = 'Microsoft Synthetic Disk Drive' + elif drive_type == constants.IDE_DVD: + res_sub_type = 'Microsoft Synthetic DVD Drive' + + #Find the default disk drive object for the vm and clone it. + drivedflt = self._conn.query("SELECT * FROM " + "Msvm_ResourceAllocationSettingData " + "WHERE ResourceSubType LIKE " + "'%(res_sub_type)s' AND InstanceID LIKE " + "'%%Default%%'" % locals())[0] + drive = self._clone_wmi_obj('Msvm_ResourceAllocationSettingData', + drivedflt) + #Set the IDE ctrller as parent. + drive.Parent = ctrller_path + drive.Address = drive_addr + #Add the cloned disk drive object to the vm. + new_resources = self._add_virt_resource(drive, vm.path_()) + drive_path = new_resources[0] + + if drive_type == constants.IDE_DISK: + res_sub_type = 'Microsoft Virtual Hard Disk' + elif drive_type == constants.IDE_DVD: + res_sub_type = 'Microsoft Virtual CD/DVD Disk' + + #Find the default VHD disk object. + drivedefault = self._conn.query("SELECT * FROM " + "Msvm_ResourceAllocationSettingData " + "WHERE ResourceSubType LIKE " + "'%(res_sub_type)s' AND " + "InstanceID LIKE '%%Default%%'" + % locals())[0] + + #Clone the default and point it to the image file. + res = self._clone_wmi_obj('Msvm_ResourceAllocationSettingData', + drivedefault) + #Set the new drive as the parent. + res.Parent = drive_path + res.Connection = [path] + + #Add the new vhd object as a virtual hard disk to the vm. + self._add_virt_resource(res, vm.path_()) + + def create_scsi_controller(self, vm_name): + """Create an iscsi controller ready to mount volumes.""" + + vm = self._lookup_vm_check(vm_name) + scsicontrldflt = self._conn.query("SELECT * FROM " + "Msvm_ResourceAllocationSettingData " + "WHERE ResourceSubType = 'Microsoft " + "Synthetic SCSI Controller' AND " + "InstanceID LIKE '%Default%'")[0] + if scsicontrldflt is None: + raise HyperVException(_('Controller not found')) + scsicontrl = self._clone_wmi_obj('Msvm_ResourceAllocationSettingData', + scsicontrldflt) + scsicontrl.VirtualSystemIdentifiers = ['{' + str(uuid.uuid4()) + '}'] + scsiresource = self._add_virt_resource(scsicontrl, vm.path_()) + + def attach_volume_to_controller(self, vm_name, controller_path, address, + mounted_disk_path): + """Attach a volume to a controller.""" - def check_job_status(self, jobpath): - """Poll WMI job state for completion.""" - job_wmi_path = jobpath.replace('\\', '/') + vm = self._lookup_vm_check(vm_name) + + diskdflt = self._conn.query("SELECT * FROM " + "Msvm_ResourceAllocationSettingData " + "WHERE ResourceSubType LIKE " + "'Microsoft Physical Disk Drive' " + "AND InstanceID LIKE '%Default%'")[0] + diskdrive = self._clone_wmi_obj('Msvm_ResourceAllocationSettingData', + diskdflt) + diskdrive.Address = address + diskdrive.Parent = controller_path + diskdrive.HostResource = [mounted_disk_path] + self._add_virt_resource(diskdrive, vm.path_()) + + def set_nic_connection(self, vm_name, nic_name, vswitch_port): + nic_data = self._get_nic_data_by_name(nic_name) + nic_data.Connection = [vswitch_port] + + vm = self._lookup_vm_check(vm_name) + self._modify_virt_resource(nic_data, vm.path_()) + + def _get_nic_data_by_name(self, name): + return self._conn.Msvm_SyntheticEthernetPortSettingData( + ElementName=name)[0] + + def create_nic(self, vm_name, nic_name, mac_address): + """Create a (synthetic) nic and attach it to the vm.""" + #Create a new nic + syntheticnics_data = self._conn.Msvm_SyntheticEthernetPortSettingData() + default_nic_data = [n for n in syntheticnics_data + if n.InstanceID.rfind('Default') > 0] + new_nic_data = self._clone_wmi_obj( + 'Msvm_SyntheticEthernetPortSettingData', default_nic_data[0]) + + #Configure the nic + new_nic_data.ElementName = nic_name + new_nic_data.Address = mac_address.replace(':', '') + new_nic_data.StaticMacAddress = 'True' + new_nic_data.VirtualSystemIdentifiers = ['{' + str(uuid.uuid4()) + '}'] + + #Add the new nic to the vm + vm = self._lookup_vm_check(vm_name) + + self._add_virt_resource(new_nic_data, vm.path_()) + + def set_vm_state(self, vm_name, req_state): + """Set the desired state of the VM.""" + + vm = self._lookup_vm_check(vm_name) + (job_path, ret_val) = vm.RequestStateChange(req_state) + #Invalid state for current operation (32775) typically means that + #the VM is already in the state requested + self.check_ret_val(ret_val, job_path, [0, 32775]) + LOG.debug(_("Successfully changed vm state of %(vm_name)s" + " to %(req_state)s") % locals()) + + def destroy_vm(self, vm_name, destroy_disks=True): + """Destroy the VM. Also destroy the associated VHD disk files.""" + + vm = self._lookup_vm_check(vm_name) + + #Stop the VM first. + self.set_vm_state(vm_name, constants.HYPERV_VM_STATE_DISABLED) + + vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0] + vmsettings = vm.associators( + wmi_result_class='Msvm_VirtualSystemSettingData') + rasds = vmsettings[0].associators( + wmi_result_class='MSVM_ResourceAllocationSettingData') + disk_resources = [r for r in rasds + if r.ResourceSubType == + 'Microsoft Virtual Hard Disk'] + volume_resources = [r for r in rasds + if r.ResourceSubType == + 'Microsoft Physical Disk Drive'] + + #Collect volumes information before destroying the VM. + volumes_drives_list = [] + for volume_resource in volume_resources: + drive_path = volume_resource.HostResource[0] + #Appending the Msvm_Disk path + volumes_drives_list.append(drive_path) + + #Collect disk file information before destroying the VM. + disk_files = [] + for disk_resource in disk_resources: + disk_files.extend([c for c in disk_resource.Connection]) + + #Remove the VM. Does not destroy disks. + (job_path, ret_val) = vs_man_svc.DestroyVirtualSystem(vm.path_()) + self.check_ret_val(ret_val, job_path) + + if destroy_disks: + #Delete associated vhd disk files. + for disk in disk_files: + LOG.debug(_("Deleting disk file: %(disk)s") % locals()) + self._delete_file(disk) + + return volumes_drives_list + + def _delete_file(self, path): + f = self._conn_cimv2.query("Select * from CIM_DataFile where " + "Name = '%s'" % path.replace("'", "''"))[0] + f.Delete() + + def check_ret_val(self, ret_val, job_path, success_values=[0]): + if ret_val == constants.WMI_JOB_STATUS_STARTED: + self._wait_for_job(job_path) + elif ret_val not in success_values: + raise HyperVException(_('Operation failed with return value: %s') + % ret_val) + + def _wait_for_job(self, job_path): + """Poll WMI job state and wait for completion.""" + + job_wmi_path = job_path.replace('\\', '/') job = wmi.WMI(moniker=job_wmi_path) while job.JobState == constants.WMI_JOB_STATE_RUNNING: @@ -69,54 +388,30 @@ class VMUtils(object): err_sum_desc = job.ErrorSummaryDescription err_desc = job.ErrorDescription err_code = job.ErrorCode - LOG.debug(_("WMI job failed with status %(job_state)d. " - "Error details: %(err_sum_desc)s - %(err_desc)s - " - "Error code: %(err_code)d") % locals()) + raise HyperVException(_("WMI job failed with status " + "%(job_state)d. Error details: " + "%(err_sum_desc)s - %(err_desc)s - " + "Error code: %(err_code)d") + % locals()) else: (error, ret_val) = job.GetError() if not ret_val and error: - LOG.debug(_("WMI job failed with status %(job_state)d. " - "Error details: %(error)s") % locals()) + raise HyperVException(_("WMI job failed with status " + "%(job_state)d. Error details: " + "%(error)s") % locals()) else: - LOG.debug(_("WMI job failed with status %(job_state)d. " - "No error description available") % locals()) - return False + raise HyperVException(_("WMI job failed with status " + "%(job_state)d. No error " + "description available") + % locals()) desc = job.Description elap = job.ElapsedTime LOG.debug(_("WMI job succeeded: %(desc)s, Elapsed=%(elap)s") - % locals()) - return True - - def get_instance_path(self, instance_name): - instance_path = os.path.join(CONF.instances_path, instance_name) - if not os.path.exists(instance_path): - LOG.debug(_('Creating folder %s '), instance_path) - os.makedirs(instance_path) - return instance_path - - def get_vhd_path(self, instance_name): - instance_path = self.get_instance_path(instance_name) - return os.path.join(instance_path, instance_name + ".vhd") - - def get_base_vhd_path(self, image_name): - base_dir = os.path.join(CONF.instances_path, '_base') - if not os.path.exists(base_dir): - os.makedirs(base_dir) - return os.path.join(base_dir, image_name + ".vhd") - - def make_export_path(self, instance_name): - export_folder = os.path.join(CONF.instances_path, "export", - instance_name) - if os.path.isdir(export_folder): - LOG.debug(_('Removing existing folder %s '), export_folder) - shutil.rmtree(export_folder) - LOG.debug(_('Creating folder %s '), export_folder) - os.makedirs(export_folder) - return export_folder - - def clone_wmi_obj(self, conn, wmi_class, wmi_obj): + % locals()) + + def _clone_wmi_obj(self, wmi_class, wmi_obj): """Clone a WMI object.""" - cl = conn.__getattr__(wmi_class) # get the class + cl = getattr(self._conn, wmi_class) # get the class newinst = cl.new() #Copy the properties from the original. for prop in wmi_obj._properties: @@ -125,51 +420,78 @@ class VMUtils(object): strguid.append(str(uuid.uuid4())) newinst.Properties_.Item(prop).Value = strguid else: - newinst.Properties_.Item(prop).Value = \ - wmi_obj.Properties_.Item(prop).Value + prop_value = wmi_obj.Properties_.Item(prop).Value + newinst.Properties_.Item(prop).Value = prop_value + return newinst - def add_virt_resource(self, conn, res_setting_data, target_vm): + def _add_virt_resource(self, res_setting_data, vm_path): """Adds a new resource to the VM.""" - vs_man_svc = conn.Msvm_VirtualSystemManagementService()[0] - (job, new_resources, ret_val) = vs_man_svc.\ - AddVirtualSystemResources([res_setting_data.GetText_(1)], - target_vm.path_()) - success = True - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self.check_job_status(job) - else: - success = (ret_val == 0) - if success: - return new_resources - else: - return None + vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0] + res_xml = [res_setting_data.GetText_(1)] + (job_path, + new_resources, + ret_val) = vs_man_svc.AddVirtualSystemResources(res_xml, vm_path) + self.check_ret_val(ret_val, job_path) + return new_resources - def modify_virt_resource(self, conn, res_setting_data, target_vm): + def _modify_virt_resource(self, res_setting_data, vm_path): """Updates a VM resource.""" - vs_man_svc = conn.Msvm_VirtualSystemManagementService()[0] - (job, ret_val) = vs_man_svc.ModifyVirtualSystemResources( + vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0] + (job_path, ret_val) = vs_man_svc.ModifyVirtualSystemResources( ResourceSettingData=[res_setting_data.GetText_(1)], - ComputerSystem=target_vm.path_()) - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self.check_job_status(job) - else: - success = (ret_val == 0) - return success + ComputerSystem=vm_path) + self.check_ret_val(ret_val, job_path) - def remove_virt_resource(self, conn, res_setting_data, target_vm): + def _remove_virt_resource(self, res_setting_data, vm_path): """Removes a VM resource.""" - vs_man_svc = conn.Msvm_VirtualSystemManagementService()[0] - (job, ret_val) = vs_man_svc.\ - RemoveVirtualSystemResources([res_setting_data.path_()], - target_vm.path_()) - success = True - if ret_val == constants.WMI_JOB_STATUS_STARTED: - success = self.check_job_status(job) - else: - success = (ret_val == 0) - return success + vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0] + res_path = [res_setting_data.path_()] + (job_path, ret_val) = vs_man_svc.RemoveVirtualSystemResources(res_path, + vm_path) + self.check_ret_val(ret_val, job_path) + + def take_vm_snapshot(self, vm_name): + vm = self._lookup_vm_check(vm_name) + + vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0] + + (job_path, ret_val, + snp_setting_data) = vs_man_svc.CreateVirtualSystemSnapshot(vm.path_()) + self.check_ret_val(ret_val, job_path) + + job_wmi_path = job_path.replace('\\', '/') + job = wmi.WMI(moniker=job_wmi_path) + snp_setting_data = job.associators( + wmi_result_class='Msvm_VirtualSystemSettingData')[0] + return snp_setting_data.path_() + + def remove_vm_snapshot(self, snapshot_path): + vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0] + + (job_path, ret_val) = vs_man_svc.RemoveVirtualSystemSnapshot( + snapshot_path) + self.check_ret_val(ret_val, job_path) + + def detach_vm_disk(self, vm_name, disk_path): + vm = self._lookup_vm_check(vm_name) + physical_disk = self._get_mounted_disk_resource_from_path( + disk_path) + self._remove_virt_resource(physical_disk, vm.path_()) + + def _get_mounted_disk_resource_from_path(self, disk_path): + physical_disks = self._conn.query("SELECT * FROM " + "Msvm_ResourceAllocationSettingData" + " WHERE ResourceSubType = " + "'Microsoft Physical Disk Drive'") + for physical_disk in physical_disks: + if physical_disk.HostResource: + if physical_disk.HostResource[0].lower() == disk_path.lower(): + return physical_disk - def fetch_image(self, target, context, image_id, user, project, - *args, **kwargs): - images.fetch(context, image_id, target, user, project) + def get_mounted_disk_by_drive_number(self, device_number): + mounted_disks = self._conn.query("SELECT * FROM Msvm_DiskDrive " + "WHERE DriveNumber=" + + str(device_number)) + if len(mounted_disks): + return mounted_disks[0].path_() diff --git a/nova/virt/hyperv/volumeops.py b/nova/virt/hyperv/volumeops.py index b69cf7bf1..a7e56b739 100644 --- a/nova/virt/hyperv/volumeops.py +++ b/nova/virt/hyperv/volumeops.py @@ -1,6 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright 2012 Pedro Navarro Perez +# Copyright 2013 Cloudbase Solutions Srl # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -20,210 +21,140 @@ Management class for Storage-related functions (attach, detach, etc). """ import time -from nova import block_device from nova.openstack.common import cfg from nova.openstack.common import log as logging from nova.virt import driver -from nova.virt.hyperv import baseops +from nova.virt.hyperv import hostutils from nova.virt.hyperv import vmutils from nova.virt.hyperv import volumeutils -from nova.virt.hyperv import volumeutilsV2 +from nova.virt.hyperv import volumeutilsv2 LOG = logging.getLogger(__name__) hyper_volumeops_opts = [ cfg.IntOpt('hyperv_attaching_volume_retry_count', - default=10, - help='The number of times we retry on attaching volume '), + default=10, + help='The number of times we retry on attaching volume '), cfg.IntOpt('hyperv_wait_between_attach_retry', - default=5, - help='The seconds to wait between a volume attachment attempt'), + default=5, + help='The seconds to wait between an volume ' + 'attachment attempt'), cfg.BoolOpt('force_volumeutils_v1', - default=False, - help='Force volumeutils v1'), - ] + default=False, + help='Force volumeutils v1'), +] CONF = cfg.CONF CONF.register_opts(hyper_volumeops_opts) CONF.import_opt('my_ip', 'nova.netconf') -class VolumeOps(baseops.BaseOps): +class VolumeOps(object): """ Management class for Volume-related tasks """ def __init__(self): - super(VolumeOps, self).__init__() - + self._hostutils = hostutils.HostUtils() self._vmutils = vmutils.VMUtils() - self._driver = driver - self._block_device = block_device - self._time = time + self._volutils = self._get_volume_utils() self._initiator = None self._default_root_device = 'vda' - self._attaching_volume_retry_count = \ - CONF.hyperv_attaching_volume_retry_count - self._wait_between_attach_retry = \ - CONF.hyperv_wait_between_attach_retry - self._volutils = self._get_volume_utils() def _get_volume_utils(self): - if(not CONF.force_volumeutils_v1) and \ - (self._get_hypervisor_version() >= 6.2): - return volumeutilsV2.VolumeUtilsV2( - self._conn_storage, self._conn_wmi) + if(not CONF.force_volumeutils_v1 and + self._hostutils.get_windows_version() >= 6.2): + return volumeutilsv2.VolumeUtilsV2() else: - return volumeutils.VolumeUtils(self._conn_wmi) - - def _get_hypervisor_version(self): - """Get hypervisor version. - :returns: hypervisor version (ex. 12003) - """ - version = self._conn_cimv2.Win32_OperatingSystem()[0]\ - .Version - LOG.info(_('Windows version: %s ') % version) - return version + return volumeutils.VolumeUtils() def attach_boot_volume(self, block_device_info, vm_name): """Attach the boot volume to the IDE controller.""" + LOG.debug(_("block device info: %s"), block_device_info) - ebs_root = self._driver.block_device_info_get_mapping( + ebs_root = driver.block_device_info_get_mapping( block_device_info)[0] + connection_info = ebs_root['connection_info'] data = connection_info['data'] target_lun = data['target_lun'] target_iqn = data['target_iqn'] target_portal = data['target_portal'] self._volutils.login_storage_target(target_lun, target_iqn, - target_portal) + target_portal) try: #Getting the mounted disk - mounted_disk = self._get_mounted_disk_from_lun(target_iqn, - target_lun) - #Attach to IDE controller + mounted_disk_path = self._get_mounted_disk_from_lun(target_iqn, + target_lun) #Find the IDE controller for the vm. - vms = self._conn.MSVM_ComputerSystem(ElementName=vm_name) - vm = vms[0] - vmsettings = vm.associators( - wmi_result_class='Msvm_VirtualSystemSettingData') - rasds = vmsettings[0].associators( - wmi_result_class='MSVM_ResourceAllocationSettingData') - ctrller = [r for r in rasds - if r.ResourceSubType == 'Microsoft Emulated IDE Controller' - and r.Address == "0"] + ctrller_path = self._vmutils.get_vm_ide_controller(vm_name, 0) #Attaching to the same slot as the VHD disk file - self._attach_volume_to_controller(ctrller, 0, mounted_disk, vm) + self._vmutils.attach_volume_to_controller(vm_name, + ctrller_path, 0, + mounted_disk_path) except Exception as exn: LOG.exception(_('Attach boot from volume failed: %s'), exn) self._volutils.logout_storage_target(target_iqn) raise vmutils.HyperVException( - _('Unable to attach boot volume to instance %s') - % vm_name) + _('Unable to attach boot volume to instance %s') % vm_name) def volume_in_mapping(self, mount_device, block_device_info): return self._volutils.volume_in_mapping(mount_device, - block_device_info) + block_device_info) - def attach_volume(self, connection_info, instance_name, mountpoint): + def attach_volume(self, connection_info, instance_name): """Attach a volume to the SCSI controller.""" - LOG.debug(_("Attach_volume: %(connection_info)s, %(instance_name)s," - " %(mountpoint)s") % locals()) + LOG.debug(_("Attach_volume: %(connection_info)s to %(instance_name)s") + % locals()) data = connection_info['data'] target_lun = data['target_lun'] target_iqn = data['target_iqn'] target_portal = data['target_portal'] self._volutils.login_storage_target(target_lun, target_iqn, - target_portal) + target_portal) try: #Getting the mounted disk - mounted_disk = self._get_mounted_disk_from_lun(target_iqn, - target_lun) + mounted_disk_path = self._get_mounted_disk_from_lun(target_iqn, + target_lun) #Find the SCSI controller for the vm - vms = self._conn.MSVM_ComputerSystem(ElementName=instance_name) - vm = vms[0] - vmsettings = vm.associators( - wmi_result_class='Msvm_VirtualSystemSettingData') - rasds = vmsettings[0].associators( - wmi_result_class='MSVM_ResourceAllocationSettingData') - ctrller = [r for r in rasds - if r.ResourceSubType == 'Microsoft Synthetic SCSI Controller'] - self._attach_volume_to_controller( - ctrller, self._get_free_controller_slot(ctrller[0]), - mounted_disk, vm) + ctrller_path = self._vmutils.get_vm_iscsi_controller(instance_name) + + slot = self._get_free_controller_slot(ctrller_path) + self._vmutils.attach_volume_to_controller(instance_name, + ctrller_path, + slot, + mounted_disk_path) except Exception as exn: LOG.exception(_('Attach volume failed: %s'), exn) self._volutils.logout_storage_target(target_iqn) - raise vmutils.HyperVException( - _('Unable to attach volume to instance %s') - % instance_name) + raise vmutils.HyperVException(_('Unable to attach volume ' + 'to instance %s') % instance_name) - def _attach_volume_to_controller(self, controller, address, mounted_disk, - instance): - """Attach a volume to a controller.""" - #Find the default disk drive object for the vm and clone it. - diskdflt = self._conn.query( - "SELECT * FROM Msvm_ResourceAllocationSettingData \ - WHERE ResourceSubType LIKE 'Microsoft Physical Disk Drive'\ - AND InstanceID LIKE '%Default%'")[0] - diskdrive = self._vmutils.clone_wmi_obj(self._conn, - 'Msvm_ResourceAllocationSettingData', diskdflt) - diskdrive.Address = address - diskdrive.Parent = controller[0].path_() - diskdrive.HostResource = [mounted_disk[0].path_()] - new_resources = self._vmutils.add_virt_resource(self._conn, diskdrive, - instance) - if new_resources is None: - raise vmutils.HyperVException(_('Failed to add volume to VM %s') % - instance) + def _get_free_controller_slot(self, scsi_controller_path): + #Slots starts from 0, so the lenght of the disks gives us the free slot + return self._vmutils.get_attached_disks_count(scsi_controller_path) - def _get_free_controller_slot(self, scsi_controller): - #Getting volumes mounted in the SCSI controller - volumes = self._conn.query( - "SELECT * FROM Msvm_ResourceAllocationSettingData \ - WHERE ResourceSubType LIKE 'Microsoft Physical Disk Drive'\ - AND Parent = '" + scsi_controller.path_() + "'") - #Slots starts from 0, so the length of the disks gives us the free slot - return len(volumes) - - def detach_volume(self, connection_info, instance_name, mountpoint): + def detach_volume(self, connection_info, instance_name): """Dettach a volume to the SCSI controller.""" - LOG.debug(_("Detach_volume: %(connection_info)s, %(instance_name)s," - " %(mountpoint)s") % locals()) + LOG.debug(_("Detach_volume: %(connection_info)s " + "from %(instance_name)s") % locals()) data = connection_info['data'] target_lun = data['target_lun'] target_iqn = data['target_iqn'] #Getting the mounted disk - mounted_disk = self._get_mounted_disk_from_lun(target_iqn, target_lun) - physical_list = self._conn.query( - "SELECT * FROM Msvm_ResourceAllocationSettingData \ - WHERE ResourceSubType LIKE 'Microsoft Physical Disk Drive'") - physical_disk = 0 - for phydisk in physical_list: - host_resource_list = phydisk.HostResource - if host_resource_list is None: - continue - host_resource = str(host_resource_list[0].lower()) - mounted_disk_path = str(mounted_disk[0].path_().lower()) - LOG.debug(_("Mounted disk to detach is: %s"), mounted_disk_path) - LOG.debug(_("host_resource disk detached is: %s"), host_resource) - if host_resource == mounted_disk_path: - physical_disk = phydisk - LOG.debug(_("Physical disk detached is: %s"), physical_disk) - vms = self._conn.MSVM_ComputerSystem(ElementName=instance_name) - vm = vms[0] - remove_result = self._vmutils.remove_virt_resource(self._conn, - physical_disk, vm) - if remove_result is False: - raise vmutils.HyperVException( - _('Failed to remove volume from VM %s') % - instance_name) + mounted_disk_path = self._get_mounted_disk_from_lun(target_iqn, + target_lun) + + LOG.debug(_("Detaching physical disk from instance: %s"), + mounted_disk_path) + self._vmutils.detach_vm_disk(instance_name, mounted_disk_path) + #Sending logout self._volutils.logout_storage_target(target_iqn) def get_volume_connector(self, instance): if not self._initiator: - self._initiator = self._get_iscsi_initiator() + self._initiator = self._volutils.get_iscsi_initiator() if not self._initiator: LOG.warn(_('Could not determine iscsi initiator name'), instance=instance) @@ -232,87 +163,35 @@ class VolumeOps(baseops.BaseOps): 'initiator': self._initiator, } - def _get_iscsi_initiator(self): - return self._volutils.get_iscsi_initiator(self._conn_cimv2) - def _get_mounted_disk_from_lun(self, target_iqn, target_lun): - initiator_session = self._conn_wmi.query( - "SELECT * FROM MSiSCSIInitiator_SessionClass \ - WHERE TargetName='" + target_iqn + "'")[0] - devices = initiator_session.Devices - device_number = None - for device in devices: - LOG.debug(_("device.InitiatorName: %s"), device.InitiatorName) - LOG.debug(_("device.TargetName: %s"), device.TargetName) - LOG.debug(_("device.ScsiPortNumber: %s"), device.ScsiPortNumber) - LOG.debug(_("device.ScsiPathId: %s"), device.ScsiPathId) - LOG.debug(_("device.ScsiTargetId): %s"), device.ScsiTargetId) - LOG.debug(_("device.ScsiLun: %s"), device.ScsiLun) - LOG.debug(_("device.DeviceInterfaceGuid :%s"), - device.DeviceInterfaceGuid) - LOG.debug(_("device.DeviceInterfaceName: %s"), - device.DeviceInterfaceName) - LOG.debug(_("device.LegacyName: %s"), device.LegacyName) - LOG.debug(_("device.DeviceType: %s"), device.DeviceType) - LOG.debug(_("device.DeviceNumber %s"), device.DeviceNumber) - LOG.debug(_("device.PartitionNumber :%s"), device.PartitionNumber) - scsi_lun = device.ScsiLun - if scsi_lun == target_lun: - device_number = device.DeviceNumber + device_number = self._volutils.get_device_number_for_target(target_iqn, + target_lun) if device_number is None: - raise vmutils.HyperVException( - _('Unable to find a mounted disk for' - ' target_iqn: %s') % target_iqn) - LOG.debug(_("Device number : %s"), device_number) - LOG.debug(_("Target lun : %s"), target_lun) + raise vmutils.HyperVException(_('Unable to find a mounted ' + 'disk for target_iqn: %s') + % target_iqn) + LOG.debug(_('Device number: %(device_number)s, ' + 'target lun: %(target_lun)s') % locals()) #Finding Mounted disk drive - for i in range(1, self._attaching_volume_retry_count): - mounted_disk = self._conn.query( - "SELECT * FROM Msvm_DiskDrive WHERE DriveNumber=" + - str(device_number) + "") - LOG.debug(_("Mounted disk is: %s"), mounted_disk) - if len(mounted_disk) > 0: + for i in range(1, CONF.hyperv_attaching_volume_retry_count): + mounted_disk_path = self._vmutils.get_mounted_disk_by_drive_number( + device_number) + if mounted_disk_path: break - self._time.sleep(self._wait_between_attach_retry) - mounted_disk = self._conn.query( - "SELECT * FROM Msvm_DiskDrive WHERE DriveNumber=" + - str(device_number) + "") - LOG.debug(_("Mounted disk is: %s"), mounted_disk) - if len(mounted_disk) == 0: - raise vmutils.HyperVException( - _('Unable to find a mounted disk for' - ' target_iqn: %s') % target_iqn) - return mounted_disk + time.sleep(CONF.hyperv_wait_between_attach_retry) + + if not mounted_disk_path: + raise vmutils.HyperVException(_('Unable to find a mounted disk ' + 'for target_iqn: %s') + % target_iqn) + return mounted_disk_path def disconnect_volume(self, physical_drive_path): #Get the session_id of the ISCSI connection - session_id = self._get_session_id_from_mounted_disk( + session_id = self._volutils.get_session_id_from_mounted_disk( physical_drive_path) #Logging out the target self._volutils.execute_log_out(session_id) - def _get_session_id_from_mounted_disk(self, physical_drive_path): - drive_number = self._get_drive_number_from_disk_path( - physical_drive_path) - LOG.debug(_("Drive number to disconnect is: %s"), drive_number) - initiator_sessions = self._conn_wmi.query( - "SELECT * FROM MSiSCSIInitiator_SessionClass") - for initiator_session in initiator_sessions: - devices = initiator_session.Devices - for device in devices: - deviceNumber = str(device.DeviceNumber) - LOG.debug(_("DeviceNumber : %s"), deviceNumber) - if deviceNumber == drive_number: - return initiator_session.SessionId - - def _get_drive_number_from_disk_path(self, disk_path): - LOG.debug(_("Disk path to parse: %s"), disk_path) - start_device_id = disk_path.find('"', disk_path.find('DeviceID')) - LOG.debug(_("start_device_id: %s"), start_device_id) - end_device_id = disk_path.find('"', start_device_id + 1) - LOG.debug(_("end_device_id: %s"), end_device_id) - deviceID = disk_path[start_device_id + 1:end_device_id] - return deviceID[deviceID.find("\\") + 2:] - def get_default_root_device(self): return self._default_root_device diff --git a/nova/virt/hyperv/volumeutils.py b/nova/virt/hyperv/volumeutils.py index 051c37fd6..713ace258 100644 --- a/nova/virt/hyperv/volumeutils.py +++ b/nova/virt/hyperv/volumeutils.py @@ -1,6 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # # Copyright 2012 Pedro Navarro Perez +# Copyright 2013 Cloudbase Solutions Srl # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -35,47 +36,48 @@ CONF = cfg.CONF class VolumeUtils(basevolumeutils.BaseVolumeUtils): - def __init__(self, conn_wmi): - self._conn_wmi = conn_wmi + def __init__(self): + super(VolumeUtils, self).__init__() - def execute(self, *args, **kwargs): - _PIPE = subprocess.PIPE # pylint: disable=E1101 - proc = subprocess.Popen( - [args], - stdin=_PIPE, - stdout=_PIPE, - stderr=_PIPE, - ) - stdout_value, stderr_value = proc.communicate() - if stdout_value.find('The operation completed successfully') == -1: - raise vmutils.HyperVException(_('An error has occurred when ' - 'calling the iscsi initiator: %s') % stdout_value) + def execute(self, *args, **kwargs): + _PIPE = subprocess.PIPE # pylint: disable=E1101 + proc = subprocess.Popen( + [args], + stdin=_PIPE, + stdout=_PIPE, + stderr=_PIPE, + ) + stdout_value, stderr_value = proc.communicate() + if stdout_value.find('The operation completed successfully') == -1: + raise vmutils.HyperVException(_('An error has occurred when ' + 'calling the iscsi initiator: %s') + % stdout_value) - def login_storage_target(self, target_lun, target_iqn, target_portal): - """Add target portal, list targets and logins to the target.""" - separator = target_portal.find(':') - target_address = target_portal[:separator] - target_port = target_portal[separator + 1:] - #Adding target portal to iscsi initiator. Sending targets - self.execute('iscsicli.exe ' + 'AddTargetPortal ' + - target_address + ' ' + target_port + - ' * * * * * * * * * * * * *') - #Listing targets - self.execute('iscsicli.exe ' + 'LisTargets') - #Sending login - self.execute('iscsicli.exe ' + 'qlogintarget ' + target_iqn) - #Waiting the disk to be mounted. Research this to avoid sleep - time.sleep(CONF.hyperv_wait_between_attach_retry) + def login_storage_target(self, target_lun, target_iqn, target_portal): + """Add target portal, list targets and logins to the target.""" + separator = target_portal.find(':') + target_address = target_portal[:separator] + target_port = target_portal[separator + 1:] + #Adding target portal to iscsi initiator. Sending targets + self.execute('iscsicli.exe ' + 'AddTargetPortal ' + + target_address + ' ' + target_port + + ' * * * * * * * * * * * * *') + #Listing targets + self.execute('iscsicli.exe ' + 'LisTargets') + #Sending login + self.execute('iscsicli.exe ' + 'qlogintarget ' + target_iqn) + #Waiting the disk to be mounted. Research this to avoid sleep + time.sleep(CONF.hyperv_wait_between_attach_retry) - def logout_storage_target(self, target_iqn): - """Logs out storage target through its session id.""" + def logout_storage_target(self, target_iqn): + """Logs out storage target through its session id.""" - sessions = self._conn_wmi.query( - "SELECT * FROM MSiSCSIInitiator_SessionClass \ - WHERE TargetName='" + target_iqn + "'") - for session in sessions: - self.execute_log_out(session.SessionId) + sessions = self._conn_wmi.query("SELECT * FROM " + "MSiSCSIInitiator_SessionClass " + "WHERE TargetName='%s'" % target_iqn) + for session in sessions: + self.execute_log_out(session.SessionId) - def execute_log_out(self, session_id): - """Executes log out of the session described by its session ID.""" - self.execute('iscsicli.exe ' + 'logouttarget ' + session_id) + def execute_log_out(self, session_id): + """Executes log out of the session described by its session ID.""" + self.execute('iscsicli.exe ' + 'logouttarget ' + session_id) diff --git a/nova/virt/hyperv/volumeutilsV2.py b/nova/virt/hyperv/volumeutilsV2.py deleted file mode 100644 index 6f5bcdac9..000000000 --- a/nova/virt/hyperv/volumeutilsV2.py +++ /dev/null @@ -1,70 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# -# Copyright 2012 Pedro Navarro Perez -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Helper methods for operations related to the management of volumes, -and storage repositories for Windows 2012 -""" -import time - -from nova.openstack.common import cfg -from nova.openstack.common import log as logging -from nova.virt.hyperv import basevolumeutils - -LOG = logging.getLogger(__name__) -CONF = cfg.CONF - - -class VolumeUtilsV2(basevolumeutils.BaseVolumeUtils): - - def __init__(self, conn_storage, conn_wmi): - self._conn_storage = conn_storage - self._conn_wmi = conn_wmi - - def login_storage_target(self, target_lun, target_iqn, - target_portal): - """Add target portal, list targets and logins to the target.""" - separator = target_portal.find(':') - target_address = target_portal[:separator] - target_port = target_portal[separator + 1:] - #Adding target portal to iscsi initiator. Sending targets - portal = self._conn_storage.__getattr__("MSFT_iSCSITargetPortal") - portal.New(TargetPortalAddress=target_address, - TargetPortalPortNumber=target_port) - #Connecting to the target - target = self._conn_storage.__getattr__("MSFT_iSCSITarget") - target.Connect(NodeAddress=target_iqn, - IsPersistent=True) - #Waiting the disk to be mounted. Research this - time.sleep(CONF.hyperv_wait_between_attach_retry) - - def logout_storage_target(self, target_iqn): - """Logs out storage target through its session id.""" - - target = self._conn_storage.MSFT_iSCSITarget( - NodeAddress=target_iqn)[0] - if target.IsConnected: - session = self._conn_storage.MSFT_iSCSISession( - TargetNodeAddress=target_iqn)[0] - if session.IsPersistent: - session.Unregister() - target.Disconnect() - - def execute_log_out(self, session_id): - session = self._conn_wmi.MSiSCSIInitiator_SessionClass( - SessionId=session_id)[0] - self.logout_storage_target(session.TargetName) diff --git a/nova/virt/hyperv/volumeutilsv2.py b/nova/virt/hyperv/volumeutilsv2.py new file mode 100644 index 000000000..8322d31d3 --- /dev/null +++ b/nova/virt/hyperv/volumeutilsv2.py @@ -0,0 +1,75 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# +# Copyright 2012 Pedro Navarro Perez +# Copyright 2013 Cloudbase Solutions Srl +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +Helper methods for operations related to the management of volumes +and storage repositories on Windows Server 2012 and above +""" +import sys +import time + +if sys.platform == 'win32': + import wmi + +from nova.openstack.common import cfg +from nova.openstack.common import log as logging +from nova.virt.hyperv import basevolumeutils + +LOG = logging.getLogger(__name__) +CONF = cfg.CONF + + +class VolumeUtilsV2(basevolumeutils.BaseVolumeUtils): + def __init__(self): + super(VolumeUtilsV2, self).__init__() + + storage_namespace = '//./root/microsoft/windows/storage' + if sys.platform == 'win32': + self._conn_storage = wmi.WMI(moniker=storage_namespace) + + def login_storage_target(self, target_lun, target_iqn, target_portal): + """Add target portal, list targets and logins to the target.""" + separator = target_portal.find(':') + target_address = target_portal[:separator] + target_port = target_portal[separator + 1:] + #Adding target portal to iscsi initiator. Sending targets + portal = self._conn_storage.MSFT_iSCSITargetPortal + portal.New(TargetPortalAddress=target_address, + TargetPortalPortNumber=target_port) + #Connecting to the target + target = self._conn_storage.MSFT_iSCSITarget + target.Connect(NodeAddress=target_iqn, + IsPersistent=True) + #Waiting the disk to be mounted. Research this + time.sleep(CONF.hyperv_wait_between_attach_retry) + + def logout_storage_target(self, target_iqn): + """Logs out storage target through its session id.""" + + target = self._conn_storage.MSFT_iSCSITarget(NodeAddress=target_iqn)[0] + if target.IsConnected: + session = self._conn_storage.MSFT_iSCSISession( + TargetNodeAddress=target_iqn)[0] + if session.IsPersistent: + session.Unregister() + target.Disconnect() + + def execute_log_out(self, session_id): + session = self._conn_wmi.MSiSCSIInitiator_SessionClass( + SessionId=session_id)[0] + self.logout_storage_target(session.TargetName) |