From ea65d0a5105d0a1e258cd26f653fef91b6336746 Mon Sep 17 00:00:00 2001 From: Claudiu Belu Date: Wed, 31 Jan 2018 00:35:41 -0800 Subject: [PATCH] Ensures that all classes have the same interface as their parents VMUtils10 has a few extra methods when compared to VMUtils. This patch adds those methods to VMUtils (raising NotImplementedError). Adds unit test that checks for future inconsistentcies. ISCSIInitiatorCLIUtils has been deprecated and removed, but it was not removed from utilsfactory.utils_map. This patch addresses this issue. Closes-Bug: #1746986 Change-Id: I2a963304fc67595bc18e719e6b4420f553519c41 --- os_win/tests/unit/test_utilsfactory.py | 45 +++++++++++++++++++ .../tests/unit/utils/compute/test_vmutils.py | 18 ++++++++ os_win/utils/compute/vmutils.py | 27 +++++++++++ os_win/utilsfactory.py | 5 --- 4 files changed, 90 insertions(+), 5 deletions(-) diff --git a/os_win/tests/unit/test_utilsfactory.py b/os_win/tests/unit/test_utilsfactory.py index 6b43edab..011987a8 100644 --- a/os_win/tests/unit/test_utilsfactory.py +++ b/os_win/tests/unit/test_utilsfactory.py @@ -17,8 +17,11 @@ Unit tests for the Hyper-V utils factory. """ +import inspect + import mock from oslo_config import cfg +from oslo_utils import importutils from os_win import exceptions from os_win.tests.unit import test_base @@ -141,3 +144,45 @@ class TestHyperVUtilsFactory(test_base.OsWinBaseTestCase): self._check_get_class( expected_class=processutils.ProcessUtils, class_type='processutils') + + def test_utils_public_signatures(self): + for module_name in utilsfactory.utils_map.keys(): + classes = utilsfactory.utils_map[module_name] + class_names = list(classes.keys()) + if len(class_names) < 2: + continue + + base_class_dict = classes[class_names[0]] + base_class = importutils.import_object(base_class_dict['path']) + for i in range(1, len(class_names)): + tested_class_dict = classes[class_names[i]] + tested_class = importutils.import_object( + tested_class_dict['path']) + self.assertPublicAPISignatures(base_class, tested_class) + self.assertPublicAPISignatures(tested_class, base_class) + + def assertPublicAPISignatures(self, baseinst, inst): + def get_public_apis(inst): + methods = {} + for (name, value) in inspect.getmembers(inst, inspect.ismethod): + if name.startswith("_"): + continue + methods[name] = value + return methods + + baseclass = baseinst.__class__.__name__ + basemethods = get_public_apis(baseinst) + implmethods = get_public_apis(inst) + + extranames = [name for name in sorted(implmethods.keys()) if + name not in basemethods] + self.assertEqual([], extranames, + "public methods not listed in class %s" % baseclass) + + for name in sorted(implmethods.keys()): + baseargs = inspect.getargspec(basemethods[name]) + implargs = inspect.getargspec(implmethods[name]) + + self.assertEqual(baseargs, implargs, + "%s args don't match class %s" % + (name, baseclass)) diff --git a/os_win/tests/unit/utils/compute/test_vmutils.py b/os_win/tests/unit/utils/compute/test_vmutils.py index e97d6429..dbaa8743 100644 --- a/os_win/tests/unit/utils/compute/test_vmutils.py +++ b/os_win/tests/unit/utils/compute/test_vmutils.py @@ -1503,6 +1503,24 @@ class VMUtilsTestCase(test_base.OsWinBaseTestCase): def test_remove_all_pci_devices(self): self._vmutils.remove_all_pci_devices(mock.sentinel.vm_name) + def test_populate_fsk(self): + self.assertRaises(NotImplementedError, + self._vmutils.populate_fsk, + mock.sentinel.fsk_filepath, + mock.sentinel.fsk_pairs) + + def test_add_vtpm(self): + self.assertRaises(NotImplementedError, + self._vmutils.add_vtpm, + mock.sentinel.vm_name, mock.sentinel.pdk_filepath, + mock.sentinel.shielded) + + def test_provision_vm(self): + self.assertRaises(NotImplementedError, + self._vmutils.provision_vm, + mock.sentinel.vm_name, mock.sentinel.fsk_filepath, + mock.sentinel.pdk_filepath) + class VMUtils6_3TestCase(test_base.OsWinBaseTestCase): diff --git a/os_win/utils/compute/vmutils.py b/os_win/utils/compute/vmutils.py index 38376108..7f02a459 100644 --- a/os_win/utils/compute/vmutils.py +++ b/os_win/utils/compute/vmutils.py @@ -1225,6 +1225,33 @@ class VMUtils(baseutils.BaseUtilsVirt): # Supported on Windows Server 2016 or newer. pass + def populate_fsk(self, fsk_filepath, fsk_pairs): + """Writes the given FSK pairs into the give file. + + :raises NotImplementedError: This method is required for Shielded VMs, + which is supported on Windows / Hyper-V Server 2016 or newer. + """ + raise NotImplementedError(_('This method is supported on Windows / ' + 'Hyper-V Server 2016 or newer')) + + def add_vtpm(self, vm_name, pdk_filepath, shielded): + """Adds a vtpm and enables it with encryption or shielded option. + + :raises NotImplementedError: This method is required for Shielded VMs, + which is supported on Windows / Hyper-V Server 2016 or newer. + """ + raise NotImplementedError(_('This method is supported on Windows / ' + 'Hyper-V Server 2016 or newer')) + + def provision_vm(self, vm_name, fsk_filepath, pdk_filepath): + """Provisions the given VM with the given FSK and PDK files. + + :raises NotImplementedError: This method is required for Shielded VMs, + which is supported on Windows / Hyper-V Server 2016 or newer. + """ + raise NotImplementedError(_('This method is supported on Windows / ' + 'Hyper-V Server 2016 or newer')) + class VMUtils6_3(VMUtils): diff --git a/os_win/utilsfactory.py b/os_win/utilsfactory.py index 31ee2bd5..e30b96a5 100644 --- a/os_win/utilsfactory.py +++ b/os_win/utilsfactory.py @@ -38,11 +38,6 @@ utils_map = { 'max_version': None, 'path': 'os_win.utils.hostutils10.HostUtils10'}}, 'iscsi_initiator_utils': { - 'ISCSIInitiatorCLIUtils': { - 'min_version': 6.0, - 'max_version': 6.2, - 'path': 'os_win.utils.storage.initiator.iscsi_cli_utils.' - 'ISCSIInitiatorCLIUtils'}, 'ISCSIInitiatorUtils': { 'min_version': 6.2, 'max_version': None,