Merge "Add helpers for single-node tasks."
This commit is contained in:
commit
05e18bba0e
|
@ -34,25 +34,9 @@ exclusive lock is represented in the database to coordinate between
|
||||||
different hosts.
|
different hosts.
|
||||||
|
|
||||||
:class:`TaskManager` methods, as well as driver methods, may be decorated to
|
:class:`TaskManager` methods, as well as driver methods, may be decorated to
|
||||||
determine whether their invocation requires an exclusive lock. For example::
|
determine whether their invocation requires an exclusive lock.
|
||||||
|
|
||||||
from ironic.conductor import task_manager
|
For now, you can access the drivers directly in this way::
|
||||||
|
|
||||||
node_ids = [1, 2, 3]
|
|
||||||
try:
|
|
||||||
# Get an exclusive lock so we can manage power state.
|
|
||||||
# This is the default behaviour of acquire_nodes.
|
|
||||||
with task_manager.acquire(node_ids) as task:
|
|
||||||
task.power_on()
|
|
||||||
states = task.get_power_state()
|
|
||||||
except exception.NodeLocked:
|
|
||||||
LOG.info(_("Unable to power nodes on."))
|
|
||||||
# Get a shared lock, just to check the power state.
|
|
||||||
with task_manager.acquire(node_ids, shared=True) as task:
|
|
||||||
states = nodes.get_power_state()
|
|
||||||
|
|
||||||
In case :class:`TaskManager` does not provide a method wrapping a particular
|
|
||||||
driver function, you can access the drivers directly in this way::
|
|
||||||
|
|
||||||
with task_manager.acquire(node_ids) as task:
|
with task_manager.acquire(node_ids) as task:
|
||||||
states = []
|
states = []
|
||||||
|
@ -60,6 +44,28 @@ driver function, you can access the drivers directly in this way::
|
||||||
for r in task.resources]:
|
for r in task.resources]:
|
||||||
# the driver is loaded based on that node's configuration.
|
# the driver is loaded based on that node's configuration.
|
||||||
states.append(driver.power.get_power_state(task, node)
|
states.append(driver.power.get_power_state(task, node)
|
||||||
|
|
||||||
|
If you have a task with just a single node, the `node` property provides
|
||||||
|
a shorthand to access it. For example::
|
||||||
|
|
||||||
|
with task_manager.acquire(node_id) as task:
|
||||||
|
driver = task.node.driver
|
||||||
|
driver.power.power_on(task.node)
|
||||||
|
|
||||||
|
Eventually, driver functionality may be wrapped by tasks to facilitate
|
||||||
|
multi-node tasks more easily. Once implemented, it might look like this::
|
||||||
|
|
||||||
|
node_ids = [1, 2, 3]
|
||||||
|
try:
|
||||||
|
with task_manager.acquire(node_ids) as task:
|
||||||
|
task.power_on()
|
||||||
|
states = task.get_power_state()
|
||||||
|
except exception.NodeLocked:
|
||||||
|
LOG.info(_("Unable to power on nodes %s.") % node_ids)
|
||||||
|
# Get a shared lock, just to check the power state.
|
||||||
|
with task_manager.acquire(node_ids, shared=True) as task:
|
||||||
|
states = task.get_power_state()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
|
@ -106,6 +112,10 @@ def acquire(node_ids, shared=False):
|
||||||
|
|
||||||
t = TaskManager(shared)
|
t = TaskManager(shared)
|
||||||
|
|
||||||
|
# instead of generating an exception, DTRT and convert to a list
|
||||||
|
if not isinstance(node_ids, list):
|
||||||
|
node_ids = [node_ids]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if not shared:
|
if not shared:
|
||||||
t.dbapi.reserve_nodes(CONF.host, node_ids)
|
t.dbapi.reserve_nodes(CONF.host, node_ids)
|
||||||
|
@ -126,3 +136,21 @@ class TaskManager(object):
|
||||||
self.shared = shared
|
self.shared = shared
|
||||||
self.resources = []
|
self.resources = []
|
||||||
self.dbapi = dbapi.get_instance()
|
self.dbapi = dbapi.get_instance()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def node(self):
|
||||||
|
"""Special accessor for single-node tasks."""
|
||||||
|
if len(self.resources) == 1:
|
||||||
|
return self.resources[0].node
|
||||||
|
else:
|
||||||
|
raise AttributeError(_("Multi-node TaskManager "
|
||||||
|
"has no attribute 'node'"))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def driver(self):
|
||||||
|
"""Special accessor for single-node tasks."""
|
||||||
|
if len(self.resources) == 1:
|
||||||
|
return self.resources[0].driver
|
||||||
|
else:
|
||||||
|
raise AttributeError(_("Multi-node TaskManager "
|
||||||
|
"has no attribute 'driver'"))
|
||||||
|
|
|
@ -159,3 +159,20 @@ class ExclusiveLockDecoratorTestCase(base.DbTestCase):
|
||||||
for uuid in self.uuids:
|
for uuid in self.uuids:
|
||||||
res = self.dbapi.get_node(uuid)
|
res = self.dbapi.get_node(uuid)
|
||||||
self.assertEqual('test-state', res.task_state)
|
self.assertEqual('test-state', res.task_state)
|
||||||
|
|
||||||
|
def test_one_node_per_task_properties(self):
|
||||||
|
with task_manager.acquire(self.uuids) as task:
|
||||||
|
self.assertEqual(task.node, task.resources[0].node)
|
||||||
|
self.assertEqual(task.driver, task.resources[0].driver)
|
||||||
|
|
||||||
|
def test_one_node_per_task_properties_fail(self):
|
||||||
|
self.uuids.append(create_fake_node(456))
|
||||||
|
with task_manager.acquire(self.uuids) as task:
|
||||||
|
def get_node():
|
||||||
|
return task.node
|
||||||
|
|
||||||
|
def get_driver():
|
||||||
|
return task.driver
|
||||||
|
|
||||||
|
self.assertRaises(AttributeError, get_node)
|
||||||
|
self.assertRaises(AttributeError, get_driver)
|
||||||
|
|
Loading…
Reference in New Issue