Add decorator that requires a lock for Drac management driver

Add decorator that requires a exclusive lock for set_boot_device
in Drac management driver. Default lock is shared, which
is useful for non-interfering operation, like get_boot_device.
Have exclusive lock with an action, can avoid multiple threads 
to modify the node at same time. This is necessary for 
changing the boot device for a node.

Change-Id: I8482da70cbb859a8da05025f2ee12a1e614f7928
This commit is contained in:
Tan Lin
2014-11-28 13:39:53 +08:00
parent aca4eeb231
commit 0c0db1f3b2
2 changed files with 19 additions and 9 deletions

View File

@@ -26,6 +26,7 @@ from ironic.common import boot_devices
from ironic.common import exception
from ironic.common.i18n import _
from ironic.common.i18n import _LE
from ironic.conductor import task_manager
from ironic.drivers import base
from ironic.drivers.modules.drac import common as drac_common
from ironic.drivers.modules.drac import resource_uris
@@ -204,6 +205,7 @@ class DracManagement(base.ManagementInterface):
"""
return list(_BOOT_DEVICES_MAP.keys())
@task_manager.require_exclusive_lock
def set_boot_device(self, task, device, persistent=False):
"""Set the boot device for a node.

View File

@@ -23,6 +23,7 @@ import mock
from ironic.common import boot_devices
from ironic.common import exception
from ironic.conductor import task_manager
from ironic.drivers.modules.drac import client as drac_client
from ironic.drivers.modules.drac import common as drac_common
from ironic.drivers.modules.drac import management as drac_mgmt
@@ -237,7 +238,10 @@ class DracManagementTestCase(db_base.DbTestCase):
mock_pywsman.enumerate.return_value = mock_xml_enum
mock_pywsman.invoke.return_value = mock_xml_invk
result = self.driver.set_boot_device(self.task, boot_devices.PXE)
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
task.node = self.node
result = self.driver.set_boot_device(task, boot_devices.PXE)
self.assertIsNone(result)
mock_pywsman.enumerate.assert_called_once_with(mock.ANY, mock.ANY,
@@ -264,10 +268,12 @@ class DracManagementTestCase(db_base.DbTestCase):
mock_pywsman = mock_client_pywsman.Client.return_value
mock_pywsman.enumerate.return_value = mock_xml_enum
mock_pywsman.invoke.return_value = mock_xml_invk
self.assertRaises(exception.DracOperationError,
self.driver.set_boot_device, self.task,
boot_devices.PXE)
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
task.node = self.node
self.assertRaises(exception.DracOperationError,
self.driver.set_boot_device, task,
boot_devices.PXE)
mock_pywsman.enumerate.assert_called_once_with(mock.ANY, mock.ANY,
resource_uris.DCIM_BootSourceSetting)
@@ -282,10 +288,12 @@ class DracManagementTestCase(db_base.DbTestCase):
def test_set_boot_device_client_error(self, mock_cfcj, mock_we,
mock_client_pywsman):
mock_we.side_effect = exception.DracClientError('E_FAKE')
self.assertRaises(exception.DracClientError,
self.driver.set_boot_device, self.task,
boot_devices.PXE)
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
task.node = self.node
self.assertRaises(exception.DracClientError,
self.driver.set_boot_device, task,
boot_devices.PXE)
mock_we.assert_called_once_with(resource_uris.DCIM_BootSourceSetting,
mock.ANY, filter_query=mock.ANY)