From 7f46a03fca14fa013915fa5d55d1c197617fe2c4 Mon Sep 17 00:00:00 2001 From: Jim Rollenhagen Date: Mon, 29 Feb 2016 01:16:03 +0000 Subject: [PATCH] Refactor driver loading to load a driver instance per node This paves the way for composable drivers. It: Creates a BareDriver class, which is a minimal subclass of BaseDriver, with no interfaces attached. Adds a method driver_factory.build_driver_for_task, that accepts a task argument and builds an instance of BareDriver that does have interfaces attached. These interfaces come from loading the driver in node.driver, and attaching each of the core, standard, and vendor interfaces to the BareDriver created. This also accepts a driver_name argument, for loading a driver that is not the one specified in node.driver (for example, when updating the driver for a node). This method will eventually need to take arguments for each interface that is broken out of the main driver singleton. By doing this, we create a driver instance per node, instead of using the monolithic driver singletons shared across nodes. Note that the attached interfaces are references to the interfaces in the driver singleton, and thus themselves still singletons. It is *which* interface implementations are referenced that will vary by node. This means that in the future, we can dynamically load and attach these interfaces, with the implementation chosen being defined by a property of the node. This patch also does a small refactoring as to how the list of interfaces attached to a driver are referenced, for cleanliness. Change-Id: Ic2b2525f2abd0d252f36442097e68f73aeaec9f7 --- ironic/common/driver_factory.py | 29 +++++ ironic/conductor/base_manager.py | 4 +- ironic/conductor/manager.py | 3 +- ironic/conductor/task_manager.py | 4 +- ironic/drivers/base.py | 28 ++++- .../tests/unit/conductor/test_base_manager.py | 1 + .../tests/unit/conductor/test_task_manager.py | 107 ++++++++++-------- 7 files changed, 115 insertions(+), 61 deletions(-) diff --git a/ironic/common/driver_factory.py b/ironic/common/driver_factory.py index f6b62c9234..191ced70a0 100644 --- a/ironic/common/driver_factory.py +++ b/ironic/common/driver_factory.py @@ -23,6 +23,7 @@ from stevedore import dispatch from ironic.common import exception from ironic.common.i18n import _ from ironic.common.i18n import _LI +from ironic.drivers import base as driver_base LOG = log.getLogger(__name__) @@ -47,6 +48,34 @@ CONF.register_opts(driver_opts) EM_SEMAPHORE = 'extension_manager' +def build_driver_for_task(task, driver_name=None): + """Builds a composable driver for a given task. + + Starts with a `BareDriver` object, and attaches implementations of the + various driver interfaces to it. Currently these all come from the + monolithic driver singleton, but later will come from separate + driver factories and configurable via the database. + + :param task: The task containing the node to build a driver for. + :param driver_name: The name of the monolithic driver to use as a base, + if different than task.node.driver. + :returns: A driver object for the task. + :raises: DriverNotFound if node.driver could not be + found in the "ironic.drivers" namespace. + """ + node = task.node + driver = driver_base.BareDriver() + _attach_interfaces_to_driver(driver, node, driver_name=driver_name) + return driver + + +def _attach_interfaces_to_driver(driver, node, driver_name=None): + driver_singleton = get_driver(driver_name or node.driver) + for iface in driver_singleton.all_interfaces: + impl = getattr(driver_singleton, iface, None) + setattr(driver, iface, impl) + + def get_driver(driver_name): """Simple method to get a ref to an instance of a driver. diff --git a/ironic/conductor/base_manager.py b/ironic/conductor/base_manager.py index da5d9daf22..ab928595a3 100644 --- a/ironic/conductor/base_manager.py +++ b/ironic/conductor/base_manager.py @@ -119,9 +119,7 @@ class BaseConductorManager(object): self._collect_periodic_tasks(self, (admin_context,)) for driver_obj in drivers.values(): self._collect_periodic_tasks(driver_obj, (self, admin_context)) - for iface_name in (driver_obj.core_interfaces + - driver_obj.standard_interfaces + - ['vendor']): + for iface_name in driver_obj.all_interfaces: iface = getattr(driver_obj, iface_name, None) if iface and iface.__class__ not in periodic_task_classes: self._collect_periodic_tasks(iface, (self, admin_context)) diff --git a/ironic/conductor/manager.py b/ironic/conductor/manager.py index b4bde13982..7e5679fb8c 100644 --- a/ironic/conductor/manager.py +++ b/ironic/conductor/manager.py @@ -1468,8 +1468,7 @@ class ConductorManager(base_manager.BaseConductorManager): iwdi = images.is_whole_disk_image(context, task.node.instance_info) task.node.driver_internal_info['is_whole_disk_image'] = iwdi - for iface_name in (task.driver.core_interfaces + - task.driver.standard_interfaces): + for iface_name in task.driver.non_vendor_interfaces: iface = getattr(task.driver, iface_name, None) result = reason = None if iface: diff --git a/ironic/conductor/task_manager.py b/ironic/conductor/task_manager.py index 5a0c3da176..77c32d1a00 100644 --- a/ironic/conductor/task_manager.py +++ b/ironic/conductor/task_manager.py @@ -208,8 +208,8 @@ class TaskManager(object): self.ports = objects.Port.list_by_node_id(context, self.node.id) self.portgroups = objects.Portgroup.list_by_node_id(context, self.node.id) - self.driver = driver_factory.get_driver(driver_name or - self.node.driver) + self.driver = driver_factory.build_driver_for_task( + self, driver_name=driver_name) # NOTE(deva): this handles the Juno-era NOSTATE state # and should be deleted after Kilo is released diff --git a/ironic/drivers/base.py b/ironic/drivers/base.py index 7b4bd60bff..02c3a75066 100644 --- a/ironic/drivers/base.py +++ b/ironic/drivers/base.py @@ -41,7 +41,6 @@ RAID_CONFIG_SCHEMA = os.path.join(os.path.dirname(__file__), CONF = cfg.CONF -CONF.import_opt('periodic_interval', 'ironic.common.service') @six.add_metaclass(abc.ABCMeta) @@ -132,6 +131,14 @@ class BaseDriver(object): def __init__(self): pass + @property + def all_interfaces(self): + return self.core_interfaces + self.standard_interfaces + ['vendor'] + + @property + def non_vendor_interfaces(self): + return self.core_interfaces + self.standard_interfaces + def get_properties(self): """Get the properties of the driver. @@ -139,15 +146,23 @@ class BaseDriver(object): """ properties = {} - for iface_name in (self.core_interfaces + - self.standard_interfaces + - ['vendor']): + for iface_name in self.all_interfaces: iface = getattr(self, iface_name, None) if iface: properties.update(iface.get_properties()) return properties +class BareDriver(BaseDriver): + """A bare driver object which will have interfaces attached later. + + Any composable interfaces should be added as class attributes of this + class, as well as appended to core_interfaces or standard_interfaces here. + """ + def __init__(self): + pass + + class BaseInterface(object): """A base interface implementing common functions for Driver Interfaces.""" interface_type = 'base' @@ -1145,6 +1160,11 @@ def driver_periodic_task(**kwargs): new_kwargs[arg] = kwargs.pop(arg) except KeyError: pass + + # NOTE(jroll) this is here to avoid a circular import when a module + # imports ironic.common.service. Normally I would balk at this, but this + # option is deprecared for removal and this code only runs at startup. + CONF.import_opt('periodic_interval', 'ironic.common.service') new_kwargs.setdefault('spacing', CONF.periodic_interval) if kwargs: diff --git a/ironic/tests/unit/conductor/test_base_manager.py b/ironic/tests/unit/conductor/test_base_manager.py index ce45434533..1245b65375 100644 --- a/ironic/tests/unit/conductor/test_base_manager.py +++ b/ironic/tests/unit/conductor/test_base_manager.py @@ -112,6 +112,7 @@ class StartStopTestCase(mgr_utils.ServiceSetUpMixin, tests_db_base.DbTestCase): class Driver(object): core_interfaces = [] standard_interfaces = ['iface'] + all_interfaces = core_interfaces + standard_interfaces iface = TestInterface() diff --git a/ironic/tests/unit/conductor/test_task_manager.py b/ironic/tests/unit/conductor/test_task_manager.py index 7aadc7bcba..986d57748b 100644 --- a/ironic/tests/unit/conductor/test_task_manager.py +++ b/ironic/tests/unit/conductor/test_task_manager.py @@ -34,7 +34,7 @@ from ironic.tests.unit.objects import utils as obj_utils @mock.patch.object(objects.Node, 'get') @mock.patch.object(objects.Node, 'release') @mock.patch.object(objects.Node, 'reserve') -@mock.patch.object(driver_factory, 'get_driver') +@mock.patch.object(driver_factory, 'build_driver_for_task') @mock.patch.object(objects.Port, 'list_by_node_id') @mock.patch.object(objects.Portgroup, 'list_by_node_id') class TaskManagerTestCase(tests_db_base.DbTestCase): @@ -48,7 +48,7 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): self.future_mock = mock.Mock(spec=['cancel', 'add_done_callback']) def test_excl_lock(self, get_portgroups_mock, get_ports_mock, - get_driver_mock, reserve_mock, release_mock, + build_driver_mock, reserve_mock, release_mock, node_get_mock): reserve_mock.return_value = self.node with task_manager.TaskManager(self.context, 'fake-node-id') as task: @@ -56,20 +56,20 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): self.assertEqual(self.node, task.node) self.assertEqual(get_ports_mock.return_value, task.ports) self.assertEqual(get_portgroups_mock.return_value, task.portgroups) - self.assertEqual(get_driver_mock.return_value, task.driver) + self.assertEqual(build_driver_mock.return_value, task.driver) self.assertFalse(task.shared) + build_driver_mock.assert_called_once_with(task, driver_name=None) reserve_mock.assert_called_once_with(self.context, self.host, 'fake-node-id') get_ports_mock.assert_called_once_with(self.context, self.node.id) get_portgroups_mock.assert_called_once_with(self.context, self.node.id) - get_driver_mock.assert_called_once_with(self.node.driver) release_mock.assert_called_once_with(self.context, self.host, self.node.id) self.assertFalse(node_get_mock.called) def test_excl_lock_with_driver( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): reserve_mock.return_value = self.node with task_manager.TaskManager(self.context, 'fake-node-id', @@ -78,20 +78,21 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): self.assertEqual(self.node, task.node) self.assertEqual(get_ports_mock.return_value, task.ports) self.assertEqual(get_portgroups_mock.return_value, task.portgroups) - self.assertEqual(get_driver_mock.return_value, task.driver) + self.assertEqual(build_driver_mock.return_value, task.driver) self.assertFalse(task.shared) + build_driver_mock.assert_called_once_with( + task, driver_name='fake-driver') reserve_mock.assert_called_once_with(self.context, self.host, 'fake-node-id') get_ports_mock.assert_called_once_with(self.context, self.node.id) get_portgroups_mock.assert_called_once_with(self.context, self.node.id) - get_driver_mock.assert_called_once_with('fake-driver') release_mock.assert_called_once_with(self.context, self.host, self.node.id) self.assertFalse(node_get_mock.called) def test_excl_nested_acquire( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): node2 = obj_utils.create_test_node(self.context, uuid=uuidutils.generate_uuid(), @@ -100,13 +101,13 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): reserve_mock.return_value = self.node get_ports_mock.return_value = mock.sentinel.ports1 get_portgroups_mock.return_value = mock.sentinel.portgroups1 - get_driver_mock.return_value = mock.sentinel.driver1 + build_driver_mock.return_value = mock.sentinel.driver1 with task_manager.TaskManager(self.context, 'node-id1') as task: reserve_mock.return_value = node2 get_ports_mock.return_value = mock.sentinel.ports2 get_portgroups_mock.return_value = mock.sentinel.portgroups2 - get_driver_mock.return_value = mock.sentinel.driver2 + build_driver_mock.return_value = mock.sentinel.driver2 with task_manager.TaskManager(self.context, 'node-id2') as task2: self.assertEqual(self.context, task.context) self.assertEqual(self.node, task.node) @@ -121,15 +122,16 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): self.assertEqual(mock.sentinel.driver2, task2.driver) self.assertFalse(task2.shared) + self.assertEqual([mock.call(task, driver_name=None), + mock.call(task2, driver_name=None)], + build_driver_mock.call_args_list) + self.assertEqual([mock.call(self.context, self.host, 'node-id1'), mock.call(self.context, self.host, 'node-id2')], reserve_mock.call_args_list) self.assertEqual([mock.call(self.context, self.node.id), mock.call(self.context, node2.id)], get_ports_mock.call_args_list) - self.assertEqual([mock.call(self.node.driver), - mock.call(node2.driver)], - get_driver_mock.call_args_list) # release should be in reverse order self.assertEqual([mock.call(self.context, self.host, node2.id), mock.call(self.context, self.host, self.node.id)], @@ -137,7 +139,7 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): self.assertFalse(node_get_mock.called) def test_excl_lock_exception_then_lock( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): retry_attempts = 3 self.config(node_locked_retry_attempts=retry_attempts, @@ -157,7 +159,7 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): self.assertEqual(2, reserve_mock.call_count) def test_excl_lock_reserve_exception( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): retry_attempts = 3 self.config(node_locked_retry_attempts=retry_attempts, @@ -175,12 +177,12 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): self.assertEqual(retry_attempts, reserve_mock.call_count) self.assertFalse(get_ports_mock.called) self.assertFalse(get_portgroups_mock.called) - self.assertFalse(get_driver_mock.called) + self.assertFalse(build_driver_mock.called) self.assertFalse(release_mock.called) self.assertFalse(node_get_mock.called) def test_excl_lock_get_ports_exception( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): reserve_mock.return_value = self.node get_ports_mock.side_effect = exception.IronicException('foo') @@ -193,13 +195,13 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): reserve_mock.assert_called_once_with(self.context, self.host, 'fake-node-id') get_ports_mock.assert_called_once_with(self.context, self.node.id) - self.assertFalse(get_driver_mock.called) + self.assertFalse(build_driver_mock.called) release_mock.assert_called_once_with(self.context, self.host, self.node.id) self.assertFalse(node_get_mock.called) def test_excl_lock_get_portgroups_exception( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): reserve_mock.return_value = self.node get_portgroups_mock.side_effect = exception.IronicException('foo') @@ -212,16 +214,16 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): reserve_mock.assert_called_once_with(self.context, self.host, 'fake-node-id') get_portgroups_mock.assert_called_once_with(self.context, self.node.id) - self.assertFalse(get_driver_mock.called) + self.assertFalse(build_driver_mock.called) release_mock.assert_called_once_with(self.context, self.host, self.node.id) self.assertFalse(node_get_mock.called) - def test_excl_lock_get_driver_exception( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + def test_excl_lock_build_driver_exception( + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): reserve_mock.return_value = self.node - get_driver_mock.side_effect = ( + build_driver_mock.side_effect = ( exception.DriverNotFound(driver_name='foo')) self.assertRaises(exception.DriverNotFound, @@ -233,13 +235,13 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): 'fake-node-id') get_ports_mock.assert_called_once_with(self.context, self.node.id) get_portgroups_mock.assert_called_once_with(self.context, self.node.id) - get_driver_mock.assert_called_once_with(self.node.driver) + build_driver_mock.assert_called_once_with(mock.ANY, driver_name=None) release_mock.assert_called_once_with(self.context, self.host, self.node.id) self.assertFalse(node_get_mock.called) def test_shared_lock( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): node_get_mock.return_value = self.node with task_manager.TaskManager(self.context, 'fake-node-id', @@ -248,18 +250,19 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): self.assertEqual(self.node, task.node) self.assertEqual(get_ports_mock.return_value, task.ports) self.assertEqual(get_portgroups_mock.return_value, task.portgroups) - self.assertEqual(get_driver_mock.return_value, task.driver) + self.assertEqual(build_driver_mock.return_value, task.driver) self.assertTrue(task.shared) + build_driver_mock.assert_called_once_with(task, driver_name=None) + self.assertFalse(reserve_mock.called) self.assertFalse(release_mock.called) node_get_mock.assert_called_once_with(self.context, 'fake-node-id') get_ports_mock.assert_called_once_with(self.context, self.node.id) get_portgroups_mock.assert_called_once_with(self.context, self.node.id) - get_driver_mock.assert_called_once_with(self.node.driver) def test_shared_lock_with_driver( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): node_get_mock.return_value = self.node with task_manager.TaskManager(self.context, @@ -270,18 +273,20 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): self.assertEqual(self.node, task.node) self.assertEqual(get_ports_mock.return_value, task.ports) self.assertEqual(get_portgroups_mock.return_value, task.portgroups) - self.assertEqual(get_driver_mock.return_value, task.driver) + self.assertEqual(build_driver_mock.return_value, task.driver) self.assertTrue(task.shared) + build_driver_mock.assert_called_once_with( + task, driver_name='fake-driver') + self.assertFalse(reserve_mock.called) self.assertFalse(release_mock.called) node_get_mock.assert_called_once_with(self.context, 'fake-node-id') get_ports_mock.assert_called_once_with(self.context, self.node.id) get_portgroups_mock.assert_called_once_with(self.context, self.node.id) - get_driver_mock.assert_called_once_with('fake-driver') def test_shared_lock_node_get_exception( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): node_get_mock.side_effect = exception.NodeNotFound(node='foo') @@ -296,10 +301,10 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): node_get_mock.assert_called_once_with(self.context, 'fake-node-id') self.assertFalse(get_ports_mock.called) self.assertFalse(get_portgroups_mock.called) - self.assertFalse(get_driver_mock.called) + self.assertFalse(build_driver_mock.called) def test_shared_lock_get_ports_exception( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): node_get_mock.return_value = self.node get_ports_mock.side_effect = exception.IronicException('foo') @@ -314,10 +319,10 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): self.assertFalse(release_mock.called) node_get_mock.assert_called_once_with(self.context, 'fake-node-id') get_ports_mock.assert_called_once_with(self.context, self.node.id) - self.assertFalse(get_driver_mock.called) + self.assertFalse(build_driver_mock.called) def test_shared_lock_get_portgroups_exception( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): node_get_mock.return_value = self.node get_portgroups_mock.side_effect = exception.IronicException('foo') @@ -332,13 +337,13 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): self.assertFalse(release_mock.called) node_get_mock.assert_called_once_with(self.context, 'fake-node-id') get_portgroups_mock.assert_called_once_with(self.context, self.node.id) - self.assertFalse(get_driver_mock.called) + self.assertFalse(build_driver_mock.called) - def test_shared_lock_get_driver_exception( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + def test_shared_lock_build_driver_exception( + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): node_get_mock.return_value = self.node - get_driver_mock.side_effect = ( + build_driver_mock.side_effect = ( exception.DriverNotFound(driver_name='foo')) self.assertRaises(exception.DriverNotFound, @@ -352,10 +357,10 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): node_get_mock.assert_called_once_with(self.context, 'fake-node-id') get_ports_mock.assert_called_once_with(self.context, self.node.id) get_portgroups_mock.assert_called_once_with(self.context, self.node.id) - get_driver_mock.assert_called_once_with(self.node.driver) + build_driver_mock.assert_called_once_with(mock.ANY, driver_name=None) def test_upgrade_lock( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): node_get_mock.return_value = self.node reserve_mock.return_value = self.node @@ -365,7 +370,7 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): self.assertEqual(self.node, task.node) self.assertEqual(get_ports_mock.return_value, task.ports) self.assertEqual(get_portgroups_mock.return_value, task.portgroups) - self.assertEqual(get_driver_mock.return_value, task.driver) + self.assertEqual(build_driver_mock.return_value, task.driver) self.assertTrue(task.shared) self.assertFalse(reserve_mock.called) @@ -375,6 +380,9 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): task.upgrade_lock() self.assertFalse(task.shared) + build_driver_mock.assert_called_once_with(mock.ANY, + driver_name=None) + # make sure reserve() was called only once reserve_mock.assert_called_once_with(self.context, self.host, 'fake-node-id') @@ -383,10 +391,9 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): node_get_mock.assert_called_once_with(self.context, 'fake-node-id') get_ports_mock.assert_called_once_with(self.context, self.node.id) get_portgroups_mock.assert_called_once_with(self.context, self.node.id) - get_driver_mock.assert_called_once_with(self.node.driver) def test_spawn_after( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): spawn_mock = mock.Mock(return_value=self.future_mock) task_release_mock = mock.Mock() @@ -406,7 +413,7 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): self.assertFalse(task_release_mock.called) def test_spawn_after_exception_while_yielded( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): spawn_mock = mock.Mock() task_release_mock = mock.Mock() @@ -423,7 +430,7 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): task_release_mock.assert_called_once_with() def test_spawn_after_spawn_fails( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): spawn_mock = mock.Mock(side_effect=exception.IronicException('foo')) task_release_mock = mock.Mock() @@ -440,7 +447,7 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): task_release_mock.assert_called_once_with() def test_spawn_after_link_fails( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): self.future_mock.add_done_callback.side_effect = ( exception.IronicException('foo')) @@ -463,7 +470,7 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): task_release_mock.assert_called_once_with() def test_spawn_after_on_error_hook( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): expected_exception = exception.IronicException('foo') spawn_mock = mock.Mock(side_effect=expected_exception) @@ -485,7 +492,7 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): 'fake-argument') def test_spawn_after_on_error_hook_exception( - self, get_portgroups_mock, get_ports_mock, get_driver_mock, + self, get_portgroups_mock, get_ports_mock, build_driver_mock, reserve_mock, release_mock, node_get_mock): expected_exception = exception.IronicException('foo') spawn_mock = mock.Mock(side_effect=expected_exception) @@ -512,7 +519,7 @@ class TaskManagerTestCase(tests_db_base.DbTestCase): @mock.patch.object(states.machine, 'copy') def test_init_prepares_fsm( self, copy_mock, get_portgroups_mock, get_ports_mock, - get_driver_mock, reserve_mock, release_mock, node_get_mock): + build_driver_mock, reserve_mock, release_mock, node_get_mock): m = mock.Mock(spec=fsm.FSM) reserve_mock.return_value = self.node copy_mock.return_value = m