From 692cf843c617c8c02f829bfc3a34ade1b6490f32 Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Tue, 7 Jul 2020 12:37:08 +0200 Subject: [PATCH] Allow deleting nodes with a broken driver The only reason we need a driver is to stop serial console. Only try to load the driver in this case. Change-Id: I5a4e0a40659042087b7a466baae0a8c3dc136211 (cherry picked from commit 53325881527467891044618685e942c660e65a0b) --- ironic/conductor/manager.py | 12 ++++++++++++ ironic/conductor/task_manager.py | 4 ++++ ironic/tests/unit/conductor/test_manager.py | 9 +++++++++ .../notes/destroy-broken-8b13de8382199aca.yaml | 5 +++++ 4 files changed, 30 insertions(+) create mode 100644 releasenotes/notes/destroy-broken-8b13de8382199aca.yaml diff --git a/ironic/conductor/manager.py b/ironic/conductor/manager.py index 50f126d576..5607bd658d 100644 --- a/ironic/conductor/manager.py +++ b/ironic/conductor/manager.py @@ -2329,6 +2329,7 @@ class ConductorManager(base_manager.BaseConductorManager): # we would disallow it otherwise. That's done for recovering hopelessly # broken nodes (e.g. with broken BMC). with task_manager.acquire(context, node_id, + load_driver=False, purpose='node deletion') as task: node = task.node if not node.maintenance and node.instance_uuid is not None: @@ -2363,6 +2364,17 @@ class ConductorManager(base_manager.BaseConductorManager): if node.console_enabled: notify_utils.emit_console_notification( task, 'console_set', fields.NotificationStatus.START) + + try: + task.load_driver() + except Exception: + with excutils.save_and_reraise_exception(): + LOG.exception('Could not load the driver for node %s ' + 'to shut down its console', node.uuid) + notify_utils.emit_console_notification( + task, 'console_set', + fields.NotificationStatus.ERROR) + try: task.driver.console.stop_console(task) except Exception as err: diff --git a/ironic/conductor/task_manager.py b/ironic/conductor/task_manager.py index b99cd10842..83db66fc69 100644 --- a/ironic/conductor/task_manager.py +++ b/ironic/conductor/task_manager.py @@ -253,6 +253,10 @@ class TaskManager(object): self.fsm.initialize(start_state=self.node.provision_state, target_state=self.node.target_provision_state) + def load_driver(self): + if self.driver is None: + self.driver = driver_factory.build_driver_for_task(self) + def _lock(self): self._debug_timer.restart() diff --git a/ironic/tests/unit/conductor/test_manager.py b/ironic/tests/unit/conductor/test_manager.py index c17bdc4277..03e31283b3 100644 --- a/ironic/tests/unit/conductor/test_manager.py +++ b/ironic/tests/unit/conductor/test_manager.py @@ -5617,6 +5617,15 @@ class DestroyNodeTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase): self.service.destroy_node(self.context, node.uuid) self.assertFalse(mock_power.called) + def test_destroy_node_broken_driver(self): + node = obj_utils.create_test_node(self.context, + power_interface='broken') + self._start_service() + self.service.destroy_node(self.context, node.uuid) + self.assertRaises(exception.NodeNotFound, + self.dbapi.get_node_by_uuid, + node.uuid) + @mgr_utils.mock_record_keepalive class CreatePortTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase): diff --git a/releasenotes/notes/destroy-broken-8b13de8382199aca.yaml b/releasenotes/notes/destroy-broken-8b13de8382199aca.yaml new file mode 100644 index 0000000000..7db6a1ff80 --- /dev/null +++ b/releasenotes/notes/destroy-broken-8b13de8382199aca.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Allows deleting nodes with a broken driver unless they require stopping + serial console.