summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ironic/conductor/utils.py8
-rw-r--r--ironic/conf/pxe.py2
-rw-r--r--ironic/drivers/modules/iscsi_deploy.py3
-rw-r--r--ironic/tests/unit/conductor/test_utils.py30
-rw-r--r--ironic/tests/unit/drivers/modules/test_iscsi_deploy.py26
-rw-r--r--releasenotes/notes/cleanwait_timeout_fail-4323ba7d4d4da3e6.yaml8
-rw-r--r--releasenotes/notes/fix-instance-master-path-config-fa524c907a7888e5.yaml6
-rw-r--r--zuul.d/project.yaml7
8 files changed, 75 insertions, 15 deletions
diff --git a/ironic/conductor/utils.py b/ironic/conductor/utils.py
index 2667862e1..e7f2588b1 100644
--- a/ironic/conductor/utils.py
+++ b/ironic/conductor/utils.py
@@ -359,8 +359,10 @@ def cleanup_cleanwait_timeout(task):
"check if the ramdisk responsible for the cleaning is "
"running on the node. Failed on step %(step)s.") %
{'step': task.node.clean_step})
- cleaning_error_handler(task, msg=last_error,
- set_fail_state=True)
+ # NOTE(rloo): this is called from the periodic task for cleanwait timeouts,
+ # via the task manager's process_event(). The node has already been moved
+ # to CLEANFAIL, so the error handler doesn't need to set the fail state.
+ cleaning_error_handler(task, msg=last_error, set_fail_state=False)
def cleaning_error_handler(task, msg, tear_down_cleaning=True,
@@ -393,7 +395,7 @@ def cleaning_error_handler(task, msg, tear_down_cleaning=True,
'reason: %(err)s' % {'err': e, 'uuid': node.uuid})
LOG.exception(msg)
- if set_fail_state:
+ if set_fail_state and node.provision_state != states.CLEANFAIL:
target_state = states.MANAGEABLE if manual_clean else None
task.process_event('fail', target_state=target_state)
diff --git a/ironic/conf/pxe.py b/ironic/conf/pxe.py
index cb251d9a2..a37e5ae75 100644
--- a/ironic/conf/pxe.py
+++ b/ironic/conf/pxe.py
@@ -36,7 +36,7 @@ opts = [
default='/var/lib/ironic/master_images',
help=_('On the ironic-conductor node, directory where master '
'instance images are stored on disk. '
- 'Setting to <None> disables image caching.')),
+ 'Setting to the empty string disables image caching.')),
cfg.IntOpt('image_cache_size',
default=20480,
help=_('Maximum size (in MiB) of cache for master images, '
diff --git a/ironic/drivers/modules/iscsi_deploy.py b/ironic/drivers/modules/iscsi_deploy.py
index 76a262b2c..609661654 100644
--- a/ironic/drivers/modules/iscsi_deploy.py
+++ b/ironic/drivers/modules/iscsi_deploy.py
@@ -47,8 +47,9 @@ DISK_LAYOUT_PARAMS = ('root_gb', 'swap_mb', 'ephemeral_gb')
class InstanceImageCache(image_cache.ImageCache):
def __init__(self):
+ master_path = CONF.pxe.instance_master_path or None
super(self.__class__, self).__init__(
- CONF.pxe.instance_master_path,
+ master_path,
# MiB -> B
cache_size=CONF.pxe.image_cache_size * 1024 * 1024,
# min -> sec
diff --git a/ironic/tests/unit/conductor/test_utils.py b/ironic/tests/unit/conductor/test_utils.py
index 7c3649ef1..0d371fdd8 100644
--- a/ironic/tests/unit/conductor/test_utils.py
+++ b/ironic/tests/unit/conductor/test_utils.py
@@ -1116,7 +1116,7 @@ class ErrorHandlersTestCase(tests_base.TestCase):
msg="Timeout reached while cleaning the node. Please "
"check if the ramdisk responsible for the cleaning is "
"running on the node. Failed on step {}.",
- set_fail_state=True)
+ set_fail_state=False)
def test_cleanup_cleanwait_timeout(self):
self.node.provision_state = states.CLEANFAIL
@@ -1133,16 +1133,18 @@ class ErrorHandlersTestCase(tests_base.TestCase):
conductor_utils.cleanup_cleanwait_timeout(self.task)
self.assertEqual({}, self.node.clean_step)
self.assertNotIn('clean_step_index', self.node.driver_internal_info)
- self.task.process_event.assert_called_once_with('fail',
- target_state=None)
+ self.assertFalse(self.task.process_event.called)
self.assertTrue(self.node.maintenance)
self.assertEqual(clean_error, self.node.maintenance_reason)
- def test_cleaning_error_handler(self):
- self.node.provision_state = states.CLEANING
+ def _test_cleaning_error_handler(self, prov_state=states.CLEANING):
+ self.node.provision_state = prov_state
target = 'baz'
self.node.target_provision_state = target
- self.node.driver_internal_info = {}
+ self.node.clean_step = {'key': 'val'}
+ self.node.driver_internal_info = {
+ 'cleaning_reboot': True,
+ 'clean_step_index': 0}
msg = 'error bar'
conductor_utils.cleaning_error_handler(self.task, msg)
self.node.save.assert_called_once_with()
@@ -1153,8 +1155,20 @@ class ErrorHandlersTestCase(tests_base.TestCase):
self.assertEqual(msg, self.node.maintenance_reason)
driver = self.task.driver.deploy
driver.tear_down_cleaning.assert_called_once_with(self.task)
- self.task.process_event.assert_called_once_with('fail',
- target_state=None)
+ if prov_state == states.CLEANFAIL:
+ self.assertFalse(self.task.process_event.called)
+ else:
+ self.task.process_event.assert_called_once_with('fail',
+ target_state=None)
+
+ def test_cleaning_error_handler(self):
+ self._test_cleaning_error_handler()
+
+ def test_cleaning_error_handler_cleanwait(self):
+ self._test_cleaning_error_handler(prov_state=states.CLEANWAIT)
+
+ def test_cleaning_error_handler_cleanfail(self):
+ self._test_cleaning_error_handler(prov_state=states.CLEANFAIL)
def test_cleaning_error_handler_manual(self):
target = states.MANAGEABLE
diff --git a/ironic/tests/unit/drivers/modules/test_iscsi_deploy.py b/ironic/tests/unit/drivers/modules/test_iscsi_deploy.py
index 93dbaa790..f1f614c20 100644
--- a/ironic/tests/unit/drivers/modules/test_iscsi_deploy.py
+++ b/ironic/tests/unit/drivers/modules/test_iscsi_deploy.py
@@ -1009,3 +1009,29 @@ class CleanUpFullFlowTestCase(db_base.DbTestCase):
+ self.files):
self.assertFalse(os.path.exists(path),
'%s is not expected to exist' % path)
+
+
+class InstanceImageCacheTestCase(db_base.DbTestCase):
+ @mock.patch.object(fileutils, 'ensure_tree')
+ def test_with_master_path(self, mock_ensure_tree):
+ self.config(instance_master_path='/fake/path', group='pxe')
+ self.config(image_cache_size=500, group='pxe')
+ self.config(image_cache_ttl=30, group='pxe')
+
+ cache = iscsi_deploy.InstanceImageCache()
+
+ mock_ensure_tree.assert_called_once_with('/fake/path')
+ self.assertEqual(500 * 1024 * 1024, cache._cache_size)
+ self.assertEqual(30 * 60, cache._cache_ttl)
+
+ @mock.patch.object(fileutils, 'ensure_tree')
+ def test_without_master_path(self, mock_ensure_tree):
+ self.config(instance_master_path='', group='pxe')
+ self.config(image_cache_size=500, group='pxe')
+ self.config(image_cache_ttl=30, group='pxe')
+
+ cache = iscsi_deploy.InstanceImageCache()
+
+ mock_ensure_tree.assert_not_called()
+ self.assertEqual(500 * 1024 * 1024, cache._cache_size)
+ self.assertEqual(30 * 60, cache._cache_ttl)
diff --git a/releasenotes/notes/cleanwait_timeout_fail-4323ba7d4d4da3e6.yaml b/releasenotes/notes/cleanwait_timeout_fail-4323ba7d4d4da3e6.yaml
new file mode 100644
index 000000000..9587fe80d
--- /dev/null
+++ b/releasenotes/notes/cleanwait_timeout_fail-4323ba7d4d4da3e6.yaml
@@ -0,0 +1,8 @@
+---
+fixes:
+ - |
+ Fixes an issue with a baremetal node that times out during cleaning.
+ The ironic-conductor was attempting to change the node's provision state
+ to 'clean failed' twice, resulting in the node's ``last_error`` being set
+ incorrectly. This no longer happens. For more information, see
+ `story 2004299 <https://storyboard.openstack.org/#!/story/2004299>`_.
diff --git a/releasenotes/notes/fix-instance-master-path-config-fa524c907a7888e5.yaml b/releasenotes/notes/fix-instance-master-path-config-fa524c907a7888e5.yaml
new file mode 100644
index 000000000..4184a4cd7
--- /dev/null
+++ b/releasenotes/notes/fix-instance-master-path-config-fa524c907a7888e5.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+ - |
+ Fixes an issue where the master instance image cache could not be disabled.
+ The configuration option ``[pxe]/instance_master_path`` may now be set to
+ the empty string to disable the cache.
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index 971976465..8af55b5f0 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -10,7 +10,9 @@
jobs:
- ironic-dsvm-standalone
- ironic-grenade-dsvm
- - ironic-grenade-dsvm-multinode-multitenant
+ # Temporarily mark job as non-voting
+ - ironic-grenade-dsvm-multinode-multitenant:
+ voting: false
- ironic-tempest-dsvm-bfv
- ironic-tempest-dsvm-ipa-partition-redfish-tinyipa
- ironic-tempest-dsvm-ipa-partition-uefi-pxe_ipmitool-tinyipa
@@ -29,7 +31,8 @@
jobs:
- ironic-dsvm-standalone
- ironic-grenade-dsvm
- - ironic-grenade-dsvm-multinode-multitenant
+ # Temporarily disable job since it's non-voting
+ # - ironic-grenade-dsvm-multinode-multitenant
- ironic-tempest-dsvm-bfv
- ironic-tempest-dsvm-ipa-partition-redfish-tinyipa
- ironic-tempest-dsvm-ipa-partition-uefi-pxe_ipmitool-tinyipa