diff --git a/releasenotes/notes/fix-oem-loading-52da045252b6c33e.yaml b/releasenotes/notes/fix-oem-loading-52da045252b6c33e.yaml new file mode 100644 index 00000000..8050478c --- /dev/null +++ b/releasenotes/notes/fix-oem-loading-52da045252b6c33e.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Fixes Sushy OEM extension loading when using multiple servers that + caused loaded extensions to point to server for which the extension + was loaded first. diff --git a/sushy/resources/oem/common.py b/sushy/resources/oem/common.py index 10fb4db0..5a0b9c0e 100644 --- a/sushy/resources/oem/common.py +++ b/sushy/resources/oem/common.py @@ -85,26 +85,6 @@ def _get_extension_manager_of_resource(resource_name): return _global_extn_mgrs_by_resource[resource_name] -@utils.synchronized -def _get_resource_vendor_extension_obj(extension, resource, vendor): - """Get the object returned by extension's plugin() method. - - :param extension: stevedore Extension - :param resource: The Sushy resource instance - :param vendor: This is the OEM vendor string which is the vendor-specific - extensibility identifier. Examples are: 'Contoso', 'Hpe'. As a matter - of fact the lowercase of this string will be the plugin entry point - name. - :returns: The object returned by ``plugin(*args, **kwds)`` of extension. - """ - if extension.obj is None: - oem_resource = extension.plugin() - extension.obj = resource.clone_resource( - oem_resource).set_parent_resource(resource, vendor) - - return extension.obj - - def get_resource_extension_by_vendor( resource_name, vendor, resource): """Helper method to get Resource specific OEM extension object for vendor @@ -131,7 +111,6 @@ def get_resource_extension_by_vendor( raise exceptions.OEMExtensionNotFoundError( resource=resource_name, name=vendor.lower()) - if resource_vendor_extn.obj is None: - return _get_resource_vendor_extension_obj( - resource_vendor_extn, resource, vendor) - return resource_vendor_extn.obj + oem_resource = resource_vendor_extn.plugin() + return resource.clone_resource( + oem_resource).set_parent_resource(resource, vendor) diff --git a/sushy/tests/unit/resources/oem/test_common.py b/sushy/tests/unit/resources/oem/test_common.py index 4debd855..9a8a0564 100644 --- a/sushy/tests/unit/resources/oem/test_common.py +++ b/sushy/tests/unit/resources/oem/test_common.py @@ -114,32 +114,6 @@ class ResourceOEMCommonMethodsTestCase(base.TestCase): self.assertTrue(extension in (self.contoso_extn, self.faux_extn)) - def test__get_resource_vendor_extension_obj_lazy_plugin_invoke(self): - resource_instance_mock = mock.Mock() - extension_mock = mock.MagicMock() - extension_mock.obj = None - - mock_oem_resource = extension_mock.plugin.return_value - - result = oem_common._get_resource_vendor_extension_obj( - extension_mock, resource_instance_mock, 'fish-n-chips') - - mock_clone_resource = resource_instance_mock.clone_resource - mock_clone_resource.assert_called_once_with(mock_oem_resource) - mock_ext = mock_clone_resource.return_value - mock_ext.set_parent_resource.assert_called_once_with( - resource_instance_mock, 'fish-n-chips') - mock_ext = mock_ext.set_parent_resource.return_value - self.assertEqual(result, mock_ext) - - extension_mock.reset_mock() - - # extension_mock.obj is not None anymore - oem_common._get_resource_vendor_extension_obj( - extension_mock, resource_instance_mock, 'fish-n-chips') - - self.assertFalse(extension_mock.plugin.called) - @mock.patch.object(stevedore, 'ExtensionManager', autospec=True) def test_get_resource_extension_by_vendor(self, ExtensionManager_mock): oem_resource_mock = mock.Mock() @@ -192,3 +166,30 @@ class ResourceOEMCommonMethodsTestCase(base.TestCase): 'by name "faux"', oem_common.get_resource_extension_by_vendor, 'sushy.resources.system.oems', 'Faux', resource_instance_mock) + + @mock.patch.object(stevedore, 'ExtensionManager', autospec=True) + def test_get_resource_extension_by_vendor_different_resources( + self, ExtensionManager_mock): + oem_resource_mock = mock.Mock() + oem_resource_mock.set_parent_resource = lambda *x: oem_resource_mock + resource_instance_mock = mock.Mock() + resource_instance_mock.clone_resource = lambda *x: oem_resource_mock + oem_resource_mock2 = mock.Mock() + oem_resource_mock2.set_parent_resource = lambda *x: oem_resource_mock2 + resource_instance_mock2 = mock.Mock() + resource_instance_mock2.clone_resource = lambda *x: oem_resource_mock2 + ExtensionManager_mock.side_effect = [self.fake_ext_mgr] + + result = oem_common.get_resource_extension_by_vendor( + 'system', 'Faux', resource_instance_mock) + self.assertEqual(result, oem_resource_mock) + ExtensionManager_mock.assert_called_once_with( + 'sushy.resources.system.oems', propagate_map_exceptions=True, + on_load_failure_callback=oem_common._raise) + ExtensionManager_mock.reset_mock() + + result2 = oem_common.get_resource_extension_by_vendor( + 'system', 'Faux', resource_instance_mock2) + self.assertEqual(result2, oem_resource_mock2) + ExtensionManager_mock.assert_not_called() + ExtensionManager_mock.reset_mock()