Add TaskManager tests and fix decorator.

Fix the require_exclusive_lock decorator so it works on both
functions and class methods.

Add unit tests for TaskManager and require_exclusive_lock().

Change-Id: I5b86b365cce1ceb2d4926634ebcb0b412740c37d
This commit is contained in:
Devananda van der Veen 2013-05-30 00:09:13 -07:00
parent db1568b729
commit 8df05652d8
2 changed files with 133 additions and 10 deletions

View File

@ -82,8 +82,8 @@ def require_exclusive_lock(f):
"""
def wrapper(*args, **kwargs):
tracker = args[0]
if tracker.shared:
task = args[0] if isinstance(args[0], TaskManager) else args[1]
if task.shared:
raise exception.ExclusiveLockRequired()
return f(*args, **kwargs)
return wrapper

View File

@ -16,14 +16,34 @@
# License for the specific language governing permissions and limitations
# under the License.
"""Test class for Ironic TaskManagers."""
"""Tests for :class:`ironic.manager.task_manager`."""
from testtools import matchers
from ironic.common import exception
from ironic.db import api as dbapi
#from ironic.drivers import fake as fake_driver
#from ironic.manager import task_manager
#from ironic.manager import resource_manager
from ironic.manager import task_manager
from ironic.openstack.common import uuidutils
from ironic.tests.db import base
from ironic.tests.db import utils
from ironic.tests.manager import utils as mgr_utils
def create_fake_node(i):
dbh = dbapi.get_instance()
node = utils.get_test_node(id=i,
uuid=uuidutils.generate_uuid(),
control_driver='fake',
deploy_driver='fake')
dbh.create_node(node)
return node['uuid']
def ContainsUUIDs(uuids):
def _task_uuids(task):
return [r.node.uuid for r in task.resources]
return matchers.AfterPreprocessing(_task_uuids,
matchers.Equals(uuids))
class TaskManagerTestCase(base.DbTestCase):
@ -31,8 +51,111 @@ class TaskManagerTestCase(base.DbTestCase):
def setUp(self):
super(TaskManagerTestCase, self).setUp()
self.dbapi = dbapi.get_instance()
(self.controller, self.deployer) = mgr_utils.get_mocked_node_manager()
def _init(self):
self.node = utils.get_test_node(control_driver='fake',
deploy_driver='fake')
self.dbapi.create_node(self.node)
self.uuids = [create_fake_node(i) for i in xrange(1, 6)]
self.uuids.sort()
def test_get_one_node(self):
uuids = [self.uuids[0]]
self.config(host='test-host')
with task_manager.acquire(uuids) as task:
node = task.resources[0].node
self.assertEqual(uuids[0], node.uuid)
self.assertEqual('test-host', node.reservation)
def test_get_many_nodes(self):
uuids = self.uuids[1:3]
self.config(host='test-host')
with task_manager.acquire(uuids) as task:
self.assertThat(task, ContainsUUIDs(uuids))
for node in [r.node for r in task.resources]:
self.assertEqual('test-host', node.reservation)
def test_get_nodes_nested(self):
uuids = self.uuids[0:2]
more_uuids = self.uuids[3:4]
with task_manager.acquire(uuids) as task:
self.assertThat(task, ContainsUUIDs(uuids))
with task_manager.acquire(more_uuids) as another_task:
self.assertThat(another_task, ContainsUUIDs(more_uuids))
def test_get_locked_node(self):
uuids = self.uuids[0:2]
def _lock_again(u):
with task_manager.acquire(u):
raise exception.IronicException("Acquired lock twice.")
with task_manager.acquire(uuids) as task:
self.assertThat(task, ContainsUUIDs(uuids))
self.assertRaises(exception.NodeLocked,
_lock_again,
uuids)
def test_get_shared_lock(self):
uuids = self.uuids[0:2]
# confirm we can elevate from shared -> exclusive
with task_manager.acquire(uuids, shared=True) as task:
self.assertThat(task, ContainsUUIDs(uuids))
with task_manager.acquire(uuids, shared=False) as inner_task:
self.assertThat(inner_task, ContainsUUIDs(uuids))
# confirm someone else can still get a shared lock
with task_manager.acquire(uuids, shared=False) as task:
self.assertThat(task, ContainsUUIDs(uuids))
with task_manager.acquire(uuids, shared=True) as inner_task:
self.assertThat(inner_task, ContainsUUIDs(uuids))
class ExclusiveLockDecoratorTestCase(base.DbTestCase):
def setUp(self):
super(ExclusiveLockDecoratorTestCase, self).setUp()
self.dbapi = dbapi.get_instance()
(self.controller, self.deployer) = mgr_utils.get_mocked_node_manager()
self.uuids = [create_fake_node(123)]
def test_require_exclusive_lock(self):
@task_manager.require_exclusive_lock
def do_state_change(task):
for r in task.resources:
task.dbapi.update_node(r.node.uuid,
{'task_state': 'test-state'})
with task_manager.acquire(self.uuids, shared=True) as task:
self.assertRaises(exception.ExclusiveLockRequired,
do_state_change,
task)
with task_manager.acquire(self.uuids, shared=False) as task:
do_state_change(task)
for uuid in self.uuids:
res = self.dbapi.get_node(uuid)
self.assertEqual('test-state', res.task_state)
@task_manager.require_exclusive_lock
def _do_state_change(self, task):
for r in task.resources:
task.dbapi.update_node(r.node.uuid,
{'task_state': 'test-state'})
def test_require_exclusive_lock_on_object(self):
with task_manager.acquire(self.uuids, shared=True) as task:
self.assertRaises(exception.ExclusiveLockRequired,
self._do_state_change,
task)
with task_manager.acquire(self.uuids, shared=False) as task:
self._do_state_change(task)
for uuid in self.uuids:
res = self.dbapi.get_node(uuid)
self.assertEqual('test-state', res.task_state)