diff --git a/os_win/tests/utils/compute/test_livemigrationutils.py b/os_win/tests/utils/compute/test_livemigrationutils.py index a33f509f..3d50c449 100644 --- a/os_win/tests/utils/compute/test_livemigrationutils.py +++ b/os_win/tests/utils/compute/test_livemigrationutils.py @@ -37,11 +37,12 @@ class LiveMigrationUtilsTestCase(test_base.OsWinBaseTestCase): def setUp(self): super(LiveMigrationUtilsTestCase, self).setUp() self.liveutils = livemigrationutils.LiveMigrationUtils() + self._conn = mock.MagicMock() + self.liveutils._conn = self._conn self.liveutils._vmutils = mock.MagicMock() self.liveutils._iscsi_initiator = mock.MagicMock() self.liveutils._jobutils = mock.Mock() - self._conn = mock.MagicMock() self.liveutils._get_conn_v2 = mock.MagicMock(return_value=self._conn) self.liveutils._conn_v2 = self._conn diff --git a/os_win/tests/utils/compute/test_vmutils.py b/os_win/tests/utils/compute/test_vmutils.py index 0c14c7ce..5c02c233 100644 --- a/os_win/tests/utils/compute/test_vmutils.py +++ b/os_win/tests/utils/compute/test_vmutils.py @@ -74,14 +74,6 @@ class VMUtilsTestCase(test_base.OsWinBaseTestCase): self._vmutils._metricsutils = mock.MagicMock() self._vmutils._pathutils = mock.MagicMock() - def test_vs_man_svc(self): - expected = self._vmutils._conn.Msvm_VirtualSystemManagementService()[0] - self.assertEqual(expected, self._vmutils._vs_man_svc) - - def test_vs_man_svc_cached(self): - self._vmutils._vs_man_svc_attr = mock.sentinel.fake_svc - self.assertEqual(mock.sentinel.fake_svc, self._vmutils._vs_man_svc) - def test_get_vm_summary_info(self): self._lookup_vm() @@ -453,14 +445,14 @@ class VMUtilsTestCase(test_base.OsWinBaseTestCase): mock_get_new_rsd.return_value, mock_vm) @mock.patch.object(vmutils.VMUtils, '_get_new_resource_setting_data') - @mock.patch.object(vmutils, 'wmi', create=True) - def _test_attach_volume_to_controller(self, mock_wmi, mock_get_new_rsd, - disk_serial=None): + @mock.patch.object(vmutils.VMUtils, '_get_wmi_obj') + def _test_attach_volume_to_controller(self, mock_get_wmi_obj, + mock_get_new_rsd, disk_serial=None): mock_vm = self._lookup_vm() mock_diskdrive = mock.MagicMock() jobutils = self._vmutils._jobutils jobutils.add_virt_resource.return_value = [mock_diskdrive] - mock_wmi.WMI.return_value = mock_diskdrive + mock_get_wmi_obj.return_value = mock_diskdrive self._vmutils.attach_volume_to_controller( self._FAKE_VM_NAME, self._FAKE_CTRL_PATH, self._FAKE_CTRL_ADDR, @@ -542,9 +534,9 @@ class VMUtilsTestCase(test_base.OsWinBaseTestCase): result = self._vmutils.get_vm_physical_disk_mapping(self._FAKE_VM_NAME) self.assertEqual(expected_mapping, result) - @mock.patch.object(vmutils, 'wmi', create=True) - def test_set_disk_host_res(self, mock_wmi): - mock_diskdrive = mock_wmi.WMI.return_value + @mock.patch.object(vmutils.VMUtils, '_get_wmi_obj') + def test_set_disk_host_res(self, mock_get_wmi_obj): + mock_diskdrive = mock_get_wmi_obj.return_value self._vmutils.set_disk_host_res(self._FAKE_RES_PATH, self._FAKE_MOUNTED_DISK_PATH) @@ -552,7 +544,7 @@ class VMUtilsTestCase(test_base.OsWinBaseTestCase): self._vmutils._jobutils.modify_virt_resource.assert_called_once_with( mock_diskdrive) - mock_wmi.WMI.assert_called_once_with(moniker=self._FAKE_RES_PATH) + mock_get_wmi_obj.assert_called_once_with(self._FAKE_RES_PATH) self.assertEqual(mock_diskdrive.HostResource, [self._FAKE_MOUNTED_DISK_PATH]) @@ -578,8 +570,7 @@ class VMUtilsTestCase(test_base.OsWinBaseTestCase): mock.sentinel.fake_new_mounted_disk_path, mock_rasds[0].HostResource[0]) - @mock.patch.object(vmutils, 'wmi', create=True) - def test_take_vm_snapshot(self, mock_wmi): + def test_take_vm_snapshot(self): self._lookup_vm() mock_svc = self._get_snapshot_service() diff --git a/os_win/tests/utils/metrics/test_metricsutils.py b/os_win/tests/utils/metrics/test_metricsutils.py index 96ce4b43..60fc9d24 100644 --- a/os_win/tests/utils/metrics/test_metricsutils.py +++ b/os_win/tests/utils/metrics/test_metricsutils.py @@ -30,7 +30,12 @@ class MetricsUtilsTestCase(base.BaseTestCase): def setUp(self, mock_cache_metrics_defs): super(MetricsUtilsTestCase, self).setUp() self.utils = metricsutils.MetricsUtils() - self.utils._conn_obj = mock.MagicMock() + self.utils._conn = mock.MagicMock() + + def test_cache_metrics_defs_no_conn(self): + self.utils._conn = None + self.utils._cache_metrics_defs() + self.assertEqual({}, self.utils._metrics_defs) @mock.patch.object(metricsutils.MetricsUtils, '_enable_metrics') @mock.patch.object(metricsutils.MetricsUtils, '_get_vm_resources') diff --git a/os_win/tests/utils/test_baseutils.py b/os_win/tests/utils/test_baseutils.py new file mode 100644 index 00000000..db2cc904 --- /dev/null +++ b/os_win/tests/utils/test_baseutils.py @@ -0,0 +1,84 @@ +# Copyright 2016 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. + +import mock + +from os_win.tests import test_base +from os_win.utils import baseutils + + +class BaseUtilsTestCase(test_base.OsWinBaseTestCase): + """Unit tests for the os-win BaseUtils class.""" + + def setUp(self): + super(BaseUtilsTestCase, self).setUp() + self.utils = baseutils.BaseUtils() + self.utils._conn = mock.MagicMock() + + @mock.patch.object(baseutils, 'wmi', create=True) + def test_get_wmi_obj(self, mock_wmi): + result = self.utils._get_wmi_obj(mock.sentinel.moniker) + + self.assertEqual(mock_wmi.WMI.return_value, result) + mock_wmi.WMI.assert_called_once_with(moniker=mock.sentinel.moniker) + + @mock.patch.object(baseutils.BaseUtils, '_get_wmi_obj') + @mock.patch.object(baseutils, 'sys') + def _check_get_wmi_conn(self, mock_sys, mock_get_wmi_obj, **kwargs): + mock_sys.platform = 'win32' + result = self.utils._get_wmi_conn(mock.sentinel.moniker, **kwargs) + + self.assertEqual(mock_get_wmi_obj.return_value, result) + mock_get_wmi_obj.assert_called_once_with(mock.sentinel.moniker, + **kwargs) + + def test_get_wmi_conn_kwargs(self): + self.utils._WMI_CONS.clear() + self._check_get_wmi_conn(privileges=mock.sentinel.privileges) + self.assertNotIn(mock.sentinel.moniker, baseutils.BaseUtils._WMI_CONS) + + def test_get_wmi_conn(self): + self._check_get_wmi_conn() + self.assertIn(mock.sentinel.moniker, baseutils.BaseUtils._WMI_CONS) + + @mock.patch.object(baseutils.BaseUtils, '_get_wmi_obj') + @mock.patch.object(baseutils, 'sys') + def test_get_wmi_conn_cached(self, mock_sys, mock_get_wmi_obj): + mock_sys.platform = 'win32' + baseutils.BaseUtils._WMI_CONS[mock.sentinel.moniker] = ( + mock.sentinel.conn) + result = self.utils._get_wmi_conn(mock.sentinel.moniker) + + self.assertEqual(mock.sentinel.conn, result) + self.assertFalse(mock_get_wmi_obj.called) + + @mock.patch.object(baseutils, 'sys') + def test_get_wmi_conn_linux(self, mock_sys): + mock_sys.platform = 'linux' + result = self.utils._get_wmi_conn(mock.sentinel.moniker) + + self.assertIsNone(result) + + +class BaseUtilsVirtTestCase(test_base.OsWinBaseTestCase): + """Unit tests for the os-win BaseUtilsVirt class.""" + + def setUp(self): + super(BaseUtilsVirtTestCase, self).setUp() + self.utils = baseutils.BaseUtilsVirt() + self.utils._conn = mock.MagicMock() + + def test_vs_man_svc(self): + expected = self.utils._conn.Msvm_VirtualSystemManagementService()[0] + self.assertEqual(expected, self.utils._vs_man_svc) diff --git a/os_win/tests/utils/test_hostutils.py b/os_win/tests/utils/test_hostutils.py index 2bbdf643..7908a746 100644 --- a/os_win/tests/utils/test_hostutils.py +++ b/os_win/tests/utils/test_hostutils.py @@ -47,35 +47,10 @@ class HostUtilsTestCase(base.BaseTestCase): def setUp(self): self._hostutils = hostutils.HostUtils() self._hostutils._conn_cimv2 = mock.MagicMock() - self._hostutils._virt_v2 = mock.MagicMock() + self._hostutils._conn = mock.MagicMock() super(HostUtilsTestCase, self).setUp() - @mock.patch.object(hostutils, 'wmi', create=True) - def test_init_wmi_virt_conn(self, mock_wmi): - self._hostutils._init_wmi_virt_conn() - - self.assertEqual(mock_wmi.WMI.return_value, self._hostutils._virt_v2) - mock_wmi.WMI.assert_called_once_with( - moniker='//./root/virtualization/v2') - - @mock.patch.object(hostutils, 'wmi', create=True) - def test_init_wmi_virt_conn_exception(self, mock_wmi): - self._hostutils._virt_v2 = None - mock_wmi.WMI.side_effect = Exception - - self._hostutils._init_wmi_virt_conn() - self.assertIsNone(self._hostutils._virt_v2) - - def test_conn_virt(self): - self._hostutils._virt_v2 = mock.sentinel.conn - self.assertEqual(mock.sentinel.conn, self._hostutils._conn_virt) - - def test_conn_virt_uninitialized(self): - self._hostutils._virt_v2 = None - self.assertRaises(exceptions.HyperVException, - getattr, self._hostutils, '_conn_virt') - @mock.patch('os_win.utils.hostutils.ctypes') def test_get_host_tick_count64(self, mock_ctypes): tick_count64 = "100" @@ -193,7 +168,7 @@ class HostUtilsTestCase(base.BaseTestCase): def _check_get_numa_nodes_missing_info(self): numa_node = mock.MagicMock() - self._hostutils._conn_virt.Msvm_NumaNode.return_value = [ + self._hostutils._conn.Msvm_NumaNode.return_value = [ numa_node, numa_node] nodes_info = self._hostutils.get_numa_nodes() @@ -218,7 +193,7 @@ class HostUtilsTestCase(base.BaseTestCase): host_cpu = mock.MagicMock(DeviceID=self._DEVICE_ID) mock_get_cpu_info.return_value = [host_cpu] numa_node = mock.MagicMock(NodeID=self._NODE_ID) - self._hostutils._conn_virt.Msvm_NumaNode.return_value = [ + self._hostutils._conn.Msvm_NumaNode.return_value = [ numa_node, numa_node] nodes_info = self._hostutils.get_numa_nodes() @@ -276,7 +251,7 @@ class HostUtilsTestCase(base.BaseTestCase): fake_gpu.DriverVersion = mock.sentinel.Fake_gpu_driver_version mock_phys_3d_proc = ( - self._hostutils._conn_virt.Msvm_Physical3dGraphicsProcessor) + self._hostutils._conn.Msvm_Physical3dGraphicsProcessor) mock_phys_3d_proc.return_value = [fake_gpu] return_gpus = self._hostutils.get_remotefx_gpu_info() @@ -292,7 +267,7 @@ class HostUtilsTestCase(base.BaseTestCase): def _set_verify_host_remotefx_capability_mocks(self, isGpuCapable=True, isSlatCapable=True): - s3d_video_pool = self._hostutils._conn_virt.Msvm_Synth3dVideoPool()[0] + s3d_video_pool = self._hostutils._conn.Msvm_Synth3dVideoPool()[0] s3d_video_pool.IsGpuCapable = isGpuCapable s3d_video_pool.IsSlatCapable = isSlatCapable diff --git a/os_win/tests/utils/test_jobutils.py b/os_win/tests/utils/test_jobutils.py index 1e53bd17..cbcf2dc9 100644 --- a/os_win/tests/utils/test_jobutils.py +++ b/os_win/tests/utils/test_jobutils.py @@ -37,14 +37,6 @@ class JobUtilsTestCase(base.BaseTestCase): self.jobutils = jobutils.JobUtils() self.jobutils._conn = mock.MagicMock() - def test_vs_man_svc(self): - expected = self.jobutils._conn.Msvm_VirtualSystemManagementService()[0] - self.assertEqual(expected, self.jobutils._vs_man_svc) - - def test_vs_man_svc_cached(self): - self.jobutils._vs_man_svc_attr = mock.sentinel.fake_svc - self.assertEqual(mock.sentinel.fake_svc, self.jobutils._vs_man_svc) - @mock.patch.object(jobutils.JobUtils, '_wait_for_job') def test_check_ret_val_started(self, mock_wait_for_job): self.jobutils.check_ret_val(constants.WMI_JOB_STATUS_STARTED, @@ -96,8 +88,8 @@ class JobUtilsTestCase(base.BaseTestCase): job = self.jobutils._wait_for_job(self._FAKE_JOB_PATH) self.assertEqual(mock_job, job) - @mock.patch.object(jobutils, 'wmi', create=True) - def test_stop_jobs(self, mock_wmi): + @mock.patch.object(jobutils.JobUtils, '_get_wmi_obj') + def test_stop_jobs(self, mock_get_wmi_obj): mock_job1 = mock.MagicMock(Cancellable=True) mock_job2 = mock.MagicMock(Cancellable=True) mock_job3 = mock.MagicMock(Cancellable=True) @@ -105,7 +97,7 @@ class JobUtilsTestCase(base.BaseTestCase): mock_job2.JobState = 3 mock_job3.JobState = constants.JOB_STATE_KILLED - mock_wmi.WMI.side_effect = [mock_job1, mock_job2, mock_job3] + mock_get_wmi_obj.side_effect = [mock_job1, mock_job2, mock_job3] mock_vm = mock.MagicMock() mock_vm_jobs = [mock_job1, mock_job2, mock_job3] @@ -135,10 +127,10 @@ class JobUtilsTestCase(base.BaseTestCase): mock_job.Description = self._FAKE_JOB_DESCRIPTION mock_job.ElapsedTime = self._FAKE_ELAPSED_TIME - wmi_patcher = mock.patch.object(jobutils, 'wmi', create=True) + wmi_patcher = mock.patch.object(jobutils.JobUtils, '_get_wmi_obj') mock_wmi = wmi_patcher.start() self.addCleanup(wmi_patcher.stop) - mock_wmi.WMI.return_value = mock_job + mock_wmi.return_value = mock_job return mock_job def test_modify_virt_resource(self): diff --git a/os_win/utils/baseutils.py b/os_win/utils/baseutils.py new file mode 100644 index 00000000..4d03a2df --- /dev/null +++ b/os_win/utils/baseutils.py @@ -0,0 +1,60 @@ +# Copyright 2016 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. + +""" +Base WMI utility class. +""" + +import sys + +if sys.platform == 'win32': + import wmi + + +class BaseUtils(object): + + _WMI_CONS = {} + + def _get_wmi_obj(self, moniker, **kwargs): + return wmi.WMI(moniker=moniker, **kwargs) + + def _get_wmi_conn(self, moniker, **kwargs): + if sys.platform != 'win32': + return None + if kwargs: + return self._get_wmi_obj(moniker, **kwargs) + if moniker in self._WMI_CONS: + return self._WMI_CONS[moniker] + + wmi_conn = self._get_wmi_obj(moniker) + self._WMI_CONS[moniker] = wmi_conn + return wmi_conn + + +class BaseUtilsVirt(BaseUtils): + + _wmi_namespace = '//%s/root/virtualization/v2' + + def __init__(self, host='.'): + self._vs_man_svc_attr = None + self._conn = self._get_wmi_conn(self._wmi_namespace % host) + + @property + def _vs_man_svc(self): + if not self._vs_man_svc_attr: + self._vs_man_svc_attr = ( + self._conn.Msvm_VirtualSystemManagementService()[0]) + return self._vs_man_svc_attr diff --git a/os_win/utils/compute/livemigrationutils.py b/os_win/utils/compute/livemigrationutils.py index 117fd42c..0b938ac5 100644 --- a/os_win/utils/compute/livemigrationutils.py +++ b/os_win/utils/compute/livemigrationutils.py @@ -24,6 +24,7 @@ from oslo_log import log as logging from os_win._i18n import _, _LE from os_win import exceptions from os_win.utils import _wqlutils +from os_win.utils import baseutils from os_win.utils.compute import vmutils from os_win.utils import jobutils from os_win.utils.storage.initiator import iscsi_wmi_utils @@ -31,19 +32,19 @@ from os_win.utils.storage.initiator import iscsi_wmi_utils LOG = logging.getLogger(__name__) -class LiveMigrationUtils(object): +class LiveMigrationUtils(baseutils.BaseUtilsVirt): _STORAGE_ALLOC_SETTING_DATA_CLASS = 'Msvm_StorageAllocationSettingData' _CIM_RES_ALLOC_SETTING_DATA_CLASS = 'CIM_ResourceAllocationSettingData' def __init__(self): - self._conn_v2 = self._get_conn_v2() + super(LiveMigrationUtils, self).__init__() self._vmutils = vmutils.VMUtils() self._jobutils = jobutils.JobUtils() self._iscsi_initiator = iscsi_wmi_utils.ISCSIInitiatorWMIUtils() def _get_conn_v2(self, host='localhost'): try: - return wmi.WMI(moniker='//%s/root/virtualization/v2' % host) + return self._get_wmi_conn(self._wmi_namespace % host) except wmi.x_wmi as ex: LOG.exception(_LE('Get version 2 connection error')) if ex.com_error.hresult == -2147217394: @@ -57,9 +58,9 @@ class LiveMigrationUtils(object): raise exceptions.HyperVException(msg) def check_live_migration_config(self): - migration_svc = self._conn_v2.Msvm_VirtualSystemMigrationService()[0] + migration_svc = self._conn.Msvm_VirtualSystemMigrationService()[0] vsmssd = ( - self._conn_v2.Msvm_VirtualSystemMigrationServiceSettingData()[0]) + self._conn.Msvm_VirtualSystemMigrationServiceSettingData()[0]) if not vsmssd.EnableVirtualSystemMigration: raise exceptions.HyperVException( _('Live migration is not enabled on this host')) @@ -163,7 +164,7 @@ class LiveMigrationUtils(object): disk_paths_remote): updated_resource_setting_data = [] sasds = _wqlutils.get_element_associated_class( - self._conn_v2, self._CIM_RES_ALLOC_SETTING_DATA_CLASS, + self._conn, self._CIM_RES_ALLOC_SETTING_DATA_CLASS, element_uuid=planned_vm.Name) for sasd in sasds: if (sasd.ResourceType == 17 and sasd.ResourceSubType == @@ -192,7 +193,7 @@ class LiveMigrationUtils(object): def _get_vhd_setting_data(self, vm): new_resource_setting_data = [] sasds = _wqlutils.get_element_associated_class( - self._conn_v2, self._STORAGE_ALLOC_SETTING_DATA_CLASS, + self._conn, self._STORAGE_ALLOC_SETTING_DATA_CLASS, element_uuid=vm.Name) for sasd in sasds: if (sasd.ResourceType == 31 and sasd.ResourceSubType == @@ -230,10 +231,9 @@ class LiveMigrationUtils(object): def live_migrate_vm(self, vm_name, dest_host): self.check_live_migration_config() - conn_v2_local = self._conn_v2 conn_v2_remote = self._get_conn_v2(dest_host) - vm = self._get_vm(conn_v2_local, vm_name) + vm = self._get_vm(self._conn, vm_name) rmt_ip_addr_list = self._get_ip_address_list(conn_v2_remote, dest_host) @@ -257,7 +257,7 @@ class LiveMigrationUtils(object): disk_paths, dest_host) planned_vm = self._create_planned_vm(conn_v2_remote, - conn_v2_local, + self._conn, vm, rmt_ip_addr_list, dest_host) self._update_planned_vm_disk_resources( @@ -266,7 +266,7 @@ class LiveMigrationUtils(object): planned_vm = planned_vms[0] new_resource_setting_data = self._get_vhd_setting_data(vm) - self._live_migrate_vm(conn_v2_local, vm, planned_vm, rmt_ip_addr_list, + self._live_migrate_vm(self._conn, vm, planned_vm, rmt_ip_addr_list, new_resource_setting_data, dest_host) def create_planned_vm(self, vm_name, src_host, disk_path_mapping): @@ -274,22 +274,21 @@ class LiveMigrationUtils(object): dest_host = platform.node() vmutils_remote = vmutils.VMUtils(src_host) - conn_v2_local = self._conn_v2 conn_v2_remote = self._get_conn_v2(src_host) vm = self._get_vm(conn_v2_remote, vm_name) # Make sure there are no planned VMs already. - self._destroy_existing_planned_vms(conn_v2_local, vm) + self._destroy_existing_planned_vms(self._conn, vm) - ip_addr_list = self._get_ip_address_list(conn_v2_local, + ip_addr_list = self._get_ip_address_list(self._conn, dest_host) disk_paths = self._get_disk_data(vm_name, vmutils_remote, disk_path_mapping) - planned_vm = self._create_planned_vm(conn_v2_local, + planned_vm = self._create_planned_vm(self._conn, conn_v2_remote, vm, ip_addr_list, dest_host) - self._update_planned_vm_disk_resources(conn_v2_local, planned_vm, + self._update_planned_vm_disk_resources(self._conn, planned_vm, vm_name, disk_paths) diff --git a/os_win/utils/compute/rdpconsoleutils.py b/os_win/utils/compute/rdpconsoleutils.py index a1dbd127..ce9eb958 100644 --- a/os_win/utils/compute/rdpconsoleutils.py +++ b/os_win/utils/compute/rdpconsoleutils.py @@ -13,17 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. -import sys - -if sys.platform == 'win32': - import wmi +from os_win.utils import baseutils -class RDPConsoleUtils(object): - def __init__(self): - if sys.platform == 'win32': - self._conn = wmi.WMI(moniker='//./root/virtualization/v2') - +class RDPConsoleUtils(baseutils.BaseUtilsVirt): def get_rdp_console_port(self): rdp_setting_data = self._conn.Msvm_TerminalServiceSettingData()[0] return rdp_setting_data.ListenerPort diff --git a/os_win/utils/compute/vmutils.py b/os_win/utils/compute/vmutils.py index d6a1cfc6..a9ed04c1 100644 --- a/os_win/utils/compute/vmutils.py +++ b/os_win/utils/compute/vmutils.py @@ -20,12 +20,8 @@ Based on the "root/virtualization/v2" namespace available starting with Hyper-V Server / Windows Server 2012. """ -import sys import uuid -if sys.platform == 'win32': - import wmi - from oslo_config import cfg from oslo_log import log as logging from oslo_utils import uuidutils @@ -36,6 +32,7 @@ from os_win._i18n import _, _LW from os_win import constants from os_win import exceptions from os_win.utils import _wqlutils +from os_win.utils import baseutils from os_win.utils import jobutils from os_win.utils.metrics import metricsutils from os_win.utils import pathutils @@ -44,7 +41,7 @@ CONF = cfg.CONF LOG = logging.getLogger(__name__) -class VMUtils(object): +class VMUtils(baseutils.BaseUtilsVirt): # These constants can be overridden by inherited classes _PHYS_DISK_RES_SUB_TYPE = 'Microsoft:Hyper-V:Physical Disk Drive' @@ -118,24 +115,12 @@ class VMUtils(object): constants.HYPERV_VM_STATE_SUSPENDED: 6} def __init__(self, host='.'): - self._vs_man_svc_attr = None + super(VMUtils, self).__init__() self._jobutils = jobutils.JobUtils() self._metricsutils = metricsutils.MetricsUtils() self._pathutils = pathutils.PathUtils() self._enabled_states_map = {v: k for k, v in six.iteritems(self._vm_power_states_map)} - if sys.platform == 'win32': - self._init_hyperv_wmi_conn(host) - - def _init_hyperv_wmi_conn(self, host): - self._conn = wmi.WMI(moniker='//%s/root/virtualization/v2' % host) - - @property - def _vs_man_svc(self): - if not self._vs_man_svc_attr: - self._vs_man_svc_attr = ( - self._conn.Msvm_VirtualSystemManagementService()[0]) - return self._vs_man_svc_attr def list_instance_notes(self): instance_notes = [] @@ -490,7 +475,7 @@ class VMUtils(object): if serial: # Apparently this can't be set when the resource is added. - diskdrive = wmi.WMI(moniker=diskdrive_path) + diskdrive = self._get_wmi_obj(diskdrive_path) diskdrive.ElementName = serial self._jobutils.modify_virt_resource(diskdrive) @@ -507,7 +492,7 @@ class VMUtils(object): return disk_resource.AddressOnParent def set_disk_host_res(self, disk_res_path, mounted_disk_path): - diskdrive = wmi.WMI(moniker=disk_res_path) + diskdrive = self._get_wmi_obj(disk_res_path) diskdrive.HostResource = [mounted_disk_path] self._jobutils.modify_virt_resource(diskdrive) @@ -647,9 +632,6 @@ class VMUtils(object): (job_path, ret_val) = self._vs_man_svc.DestroySystem(vm.path_()) self._jobutils.check_ret_val(ret_val, job_path) - def _get_wmi_obj(self, path): - return wmi.WMI(moniker=path.replace('\\', '/')) - def take_vm_snapshot(self, vm_name): vm = self._lookup_vm_check(vm_name, as_vssd=False) vs_snap_svc = self._conn.Msvm_VirtualSystemSnapshotService()[0] diff --git a/os_win/utils/hostutils.py b/os_win/utils/hostutils.py index 60b1b84a..6c83ea19 100644 --- a/os_win/utils/hostutils.py +++ b/os_win/utils/hostutils.py @@ -15,21 +15,18 @@ import ctypes import socket -import sys - -if sys.platform == 'win32': - import wmi from oslo_log import log as logging from os_win._i18n import _, _LW from os_win import constants from os_win import exceptions +from os_win.utils import baseutils LOG = logging.getLogger(__name__) -class HostUtils(object): +class HostUtils(baseutils.BaseUtilsVirt): _windows_version = None @@ -46,24 +43,12 @@ class HostUtils(object): FEATURE_RDS_VIRTUALIZATION = 322 FEATURE_MPIO = 57 + _wmi_cimv2_namespace = '//./root/cimv2' + def __init__(self): - self._virt_v2 = None - if sys.platform == 'win32': - self._conn_cimv2 = wmi.WMI(privileges=["Shutdown"]) - self._init_wmi_virt_conn() - - def _init_wmi_virt_conn(self): - try: - self._virt_v2 = wmi.WMI(moniker='//./root/virtualization/v2') - except Exception: - pass - - @property - def _conn_virt(self): - if self._virt_v2: - return self._virt_v2 - raise exceptions.HyperVException( - _("No connection to the 'root/virtualization/v2' WMI namespace.")) + super(HostUtils, self).__init__() + self._conn_cimv2 = self._get_wmi_conn(self._wmi_cimv2_namespace, + privileges=["Shutdown"]) def get_cpus_info(self): # NOTE(abalutoiu): Specifying exactly the fields that we need @@ -160,10 +145,10 @@ class HostUtils(object): return len(self._conn_cimv2.Win32_ServerFeature(ID=feature_id)) > 0 def get_numa_nodes(self): - numa_nodes = self._conn_virt.Msvm_NumaNode() + numa_nodes = self._conn.Msvm_NumaNode() nodes_info = [] - system_memory = self._conn_virt.Msvm_Memory(['NumberOfBlocks']) - processors = self._conn_virt.Msvm_Processor(['DeviceID']) + system_memory = self._conn.Msvm_Memory(['NumberOfBlocks']) + processors = self._conn.Msvm_Processor(['DeviceID']) for node in numa_nodes: # Due to a bug in vmms, getting Msvm_Processor for the numa @@ -174,7 +159,7 @@ class HostUtils(object): # Msvm_NumaNode and Msvm_Processor. We need to use this class to # relate the two because using associators on Msvm_Processor # will also result in a crash. - numa_assoc = self._conn_virt.Msvm_HostedDependency( + numa_assoc = self._conn.Msvm_HostedDependency( Antecedent=node.path_()) numa_node_assoc_paths = [item.Dependent for item in numa_assoc] @@ -231,7 +216,7 @@ class HostUtils(object): def get_remotefx_gpu_info(self): gpus = [] - all_gpus = self._conn_virt.Msvm_Physical3dGraphicsProcessor( + all_gpus = self._conn.Msvm_Physical3dGraphicsProcessor( EnabledForVirtualization=True) for gpu in all_gpus: gpus.append({'name': gpu.Name, @@ -242,7 +227,7 @@ class HostUtils(object): return gpus def verify_host_remotefx_capability(self): - synth_3d_video_pool = self._conn_virt.Msvm_Synth3dVideoPool()[0] + synth_3d_video_pool = self._conn.Msvm_Synth3dVideoPool()[0] if not synth_3d_video_pool.IsGpuCapable: raise exceptions.HyperVRemoteFXException( _("To enable RemoteFX on Hyper-V at least one GPU supporting " diff --git a/os_win/utils/jobutils.py b/os_win/utils/jobutils.py index c36c1dfe..1a105a41 100644 --- a/os_win/utils/jobutils.py +++ b/os_win/utils/jobutils.py @@ -18,25 +18,20 @@ Base Utility class for operations on Hyper-V. """ -import sys import time -if sys.platform == 'win32': - import wmi - from oslo_log import log as logging from oslo_service import loopingcall from os_win._i18n import _ from os_win import constants from os_win import exceptions +from os_win.utils import baseutils LOG = logging.getLogger(__name__) -class JobUtils(object): - - _WMI_NAMESPACE = '//%s/root/virtualization/v2' +class JobUtils(baseutils.BaseUtilsVirt): _CONCRETE_JOB_CLASS = "Msvm_ConcreteJob" @@ -47,21 +42,6 @@ class JobUtils(object): constants.JOB_STATE_KILLED, constants.JOB_STATE_COMPLETED_WITH_WARNINGS] - def __init__(self, host='.'): - self._vs_man_svc_attr = None - if sys.platform == 'win32': - self._init_hyperv_wmi_conn(host) - - def _init_hyperv_wmi_conn(self, host): - self._conn = wmi.WMI(moniker=self._WMI_NAMESPACE % host) - - @property - def _vs_man_svc(self): - if not self._vs_man_svc_attr: - self._vs_man_svc_attr = ( - self._conn.Msvm_VirtualSystemManagementService()[0]) - return self._vs_man_svc_attr - def check_ret_val(self, ret_val, job_path, success_values=[0]): if ret_val in [constants.WMI_JOB_STATUS_STARTED, constants.WMI_JOB_STATE_RUNNING]: @@ -74,11 +54,11 @@ class JobUtils(object): """Poll WMI job state and wait for completion.""" job_wmi_path = job_path.replace('\\', '/') - job = wmi.WMI(moniker=job_wmi_path) + job = self._get_wmi_obj(job_wmi_path) while job.JobState == constants.WMI_JOB_STATE_RUNNING: time.sleep(0.1) - job = wmi.WMI(moniker=job_wmi_path) + job = self._get_wmi_obj(job_wmi_path) if job.JobState == constants.JOB_STATE_KILLED: LOG.debug("WMI job killed with status %s.", job.JobState) @@ -122,7 +102,7 @@ class JobUtils(object): AffectedElement=element.path_()) for job in jobs_affecting_element: element_jobs.append( - wmi.WMI(moniker=job.AffectingElement.replace('\\', '/'))) + self._get_wmi_obj(job.AffectingElement.replace('\\', '/'))) for job in element_jobs: if job and job.Cancellable and not self._is_job_completed(job): diff --git a/os_win/utils/metrics/metricsutils.py b/os_win/utils/metrics/metricsutils.py index ced1f072..0f214483 100644 --- a/os_win/utils/metrics/metricsutils.py +++ b/os_win/utils/metrics/metricsutils.py @@ -19,20 +19,16 @@ Based on the "root/virtualization/v2" namespace available starting with Hyper-V Server / Windows Server 2012. """ -import sys - -if sys.platform == 'win32': - import wmi - from oslo_log import log as logging from os_win._i18n import _, _LW from os_win import exceptions +from os_win.utils import baseutils LOG = logging.getLogger(__name__) -class MetricsUtils(object): +class MetricsUtils(baseutils.BaseUtilsVirt): _VIRTUAL_SYSTEM_TYPE_REALIZED = 'Microsoft:Hyper-V:System:Realized' _DVD_DISK_RES_SUB_TYPE = 'Microsoft:Hyper-V:Virtual CD/DVD Disk' @@ -56,19 +52,11 @@ class MetricsUtils(object): _METRICS_ENABLED = 2 - _wmi_namespace = '//./root/virtualization/v2' - def __init__(self, host='.'): - self._conn_obj = None + super(MetricsUtils, self).__init__(host) self._metrics_svc_obj = None self._cache_metrics_defs() - @property - def _conn(self): - if not self._conn_obj: - self._conn_obj = wmi.WMI(moniker=self._wmi_namespace) - return self._conn_obj - @property def _metrics_svc(self): if not self._metrics_svc_obj: @@ -77,6 +65,11 @@ class MetricsUtils(object): def _cache_metrics_defs(self): self._metrics_defs = {} + if not self._conn: + # NOTE(claudiub): self._conn is None on Linux, causing unit tests + # to fail. + return + for metrics_def in self._conn.CIM_BaseMetricDefinition(): self._metrics_defs[metrics_def.ElementName] = metrics_def diff --git a/os_win/utils/network/networkutils.py b/os_win/utils/network/networkutils.py index 63a21295..4973cc1d 100644 --- a/os_win/utils/network/networkutils.py +++ b/os_win/utils/network/networkutils.py @@ -28,10 +28,11 @@ if sys.platform == 'win32': from os_win._i18n import _ from os_win import exceptions +from os_win.utils import baseutils from os_win.utils import jobutils -class NetworkUtils(object): +class NetworkUtils(baseutils.BaseUtilsVirt): EVENT_TYPE_CREATE = "__InstanceCreationEvent" EVENT_TYPE_DELETE = "__InstanceDeletionEvent" @@ -80,14 +81,13 @@ class NetworkUtils(object): _VNIC_LISTENER_TIMEOUT_MS = 2000 def __init__(self): + super(NetworkUtils, self).__init__() self._jobutils = jobutils.JobUtils() self._switches = {} self._switch_ports = {} self._vlan_sds = {} self._vsid_sds = {} self._sg_acl_sds = {} - if sys.platform == 'win32': - self._conn = wmi.WMI(moniker='//./root/virtualization/v2') def init_caches(self): for vswitch in self._conn.Msvm_VirtualEthernetSwitch(): @@ -426,11 +426,10 @@ class NetworkUtils(object): return True def _is_port_vm_started(self, port): - vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0] vmsettings = port.associators( wmi_result_class=self._VIRTUAL_SYSTEM_SETTING_DATA) # See http://msdn.microsoft.com/en-us/library/cc160706%28VS.85%29.aspx - (ret_val, summary_info) = vs_man_svc.GetSummaryInformation( + (ret_val, summary_info) = self._vs_man_svc.GetSummaryInformation( [self._VM_SUMMARY_ENABLED_STATE], [v.path_() for v in vmsettings]) if ret_val or not summary_info: diff --git a/os_win/utils/network/nvgreutils.py b/os_win/utils/network/nvgreutils.py index 1a02c856..4b661a8c 100644 --- a/os_win/utils/network/nvgreutils.py +++ b/os_win/utils/network/nvgreutils.py @@ -13,23 +13,18 @@ # License for the specific language governing permissions and limitations # under the License. -import sys - from oslo_log import log as logging from os_win._i18n import _, _LI, _LW, _LE # noqa from os_win import constants from os_win import exceptions +from os_win.utils import baseutils from os_win.utils.network import networkutils -# Check needed for unit testing on Unix -if sys.platform == 'win32': - import wmi - LOG = logging.getLogger(__name__) -class NvgreUtils(object): +class NvgreUtils(baseutils.BaseUtils): _HYPERV_VIRT_ADAPTER = 'Hyper-V Virtual Ethernet Adapter' _IPV4_ADDRESS_FAMILY = 2 @@ -45,8 +40,7 @@ class NvgreUtils(object): super(NvgreUtils, self).__init__() self._utils = networkutils.NetworkUtils() self._net_if_indexes = {} - if sys.platform == 'win32': - self._scimv2 = wmi.WMI(moniker=self._STDCIMV2_NAMESPACE) + self._scimv2 = self._get_wmi_conn(moniker=self._STDCIMV2_NAMESPACE) def create_provider_address(self, network_name, provider_vlan_id): iface_index = self._get_network_iface_index(network_name) diff --git a/os_win/utils/storage/diskutils.py b/os_win/utils/storage/diskutils.py index 20e801ae..461654c2 100644 --- a/os_win/utils/storage/diskutils.py +++ b/os_win/utils/storage/diskutils.py @@ -14,25 +14,23 @@ # under the License. import re -import sys - -if sys.platform == 'win32': - import wmi from oslo_log import log as logging from os_win._i18n import _ from os_win import _utils from os_win import exceptions +from os_win.utils import baseutils LOG = logging.getLogger(__name__) -class DiskUtils(object): +class DiskUtils(baseutils.BaseUtils): + + _wmi_namespace = 'root/microsoft/windows/storage' + def __init__(self): - if sys.platform == 'win32': - self._conn_storage = wmi.WMI( - moniker='root/microsoft/windows/storage') + self._conn_storage = self._get_wmi_conn(self._wmi_namespace) # Physical device names look like \\.\PHYSICALDRIVE1 self._phys_dev_name_regex = re.compile(r'\\\\.*\\[a-zA-Z]*([\d]+)') diff --git a/os_win/utils/storage/initiator/base_iscsi_utils.py b/os_win/utils/storage/initiator/base_iscsi_utils.py index 489e360e..a4db8d62 100644 --- a/os_win/utils/storage/initiator/base_iscsi_utils.py +++ b/os_win/utils/storage/initiator/base_iscsi_utils.py @@ -26,22 +26,21 @@ import sys if sys.platform == 'win32': from six.moves import winreg - import wmi from oslo_log import log as logging from os_win._i18n import _LI +from os_win.utils import baseutils LOG = logging.getLogger(__name__) -class BaseISCSIInitiatorUtils(object): +class BaseISCSIInitiatorUtils(baseutils.BaseUtils): _FILE_DEVICE_DISK = 7 def __init__(self, host='.'): - if sys.platform == 'win32': - self._conn_wmi = wmi.WMI(moniker='//%s/root/wmi' % host) - self._conn_cimv2 = wmi.WMI(moniker='//%s/root/cimv2' % host) + self._conn_wmi = self._get_wmi_conn('//%s/root/wmi' % host) + self._conn_cimv2 = self._get_wmi_conn('//%s/root/cimv2' % host) self._drive_number_regex = re.compile(r'DeviceID=\"[^,]*\\(\d+)\"') @abc.abstractmethod diff --git a/os_win/utils/storage/initiator/iscsi_wmi_utils.py b/os_win/utils/storage/initiator/iscsi_wmi_utils.py index 442df44a..27356511 100644 --- a/os_win/utils/storage/initiator/iscsi_wmi_utils.py +++ b/os_win/utils/storage/initiator/iscsi_wmi_utils.py @@ -44,8 +44,7 @@ class ISCSIInitiatorWMIUtils(base_iscsi_utils.BaseISCSIInitiatorUtils): super(ISCSIInitiatorWMIUtils, self).__init__(host) storage_namespace = '//%s/root/microsoft/windows/storage' % host - if sys.platform == 'win32': - self._conn_storage = wmi.WMI(moniker=storage_namespace) + self._conn_storage = self._get_wmi_conn(storage_namespace) def _login_target_portal(self, target_portal): (target_address, diff --git a/os_win/utils/storage/smbutils.py b/os_win/utils/storage/smbutils.py index 95983e69..396efbbd 100644 --- a/os_win/utils/storage/smbutils.py +++ b/os_win/utils/storage/smbutils.py @@ -21,6 +21,7 @@ from oslo_log import log as logging from os_win._i18n import _, _LE from os_win import exceptions +from os_win.utils import baseutils from os_win.utils import win32utils if sys.platform == 'win32': @@ -30,11 +31,10 @@ if sys.platform == 'win32': LOG = logging.getLogger(__name__) -class SMBUtils(object): +class SMBUtils(baseutils.BaseUtils): def __init__(self): self._win32_utils = win32utils.Win32Utils() - if sys.platform == "win32": - self._smb_conn = wmi.WMI(moniker=r"root\Microsoft\Windows\SMB") + self._smb_conn = self._get_wmi_conn(r"root\Microsoft\Windows\SMB") def check_smb_mapping(self, share_path, remove_unavailable_mapping=False): mappings = self._smb_conn.Msft_SmbMapping(RemotePath=share_path)