From 330693306a0b719d98e5f126f23ebe15382da0c7 Mon Sep 17 00:00:00 2001 From: Chris Krelle Date: Fri, 17 Sep 2021 15:24:22 -0700 Subject: [PATCH] add snmp power action delay This patch adds a new snmp configuration value for power_action_delay. It is a pause before power on and again after power off. some of PDU equipment fails to perform correctly if commands are sent to quickly. This patch add a configurable delay to correct that behavior. Change-Id: I433af25f03e5baf96c0868a28b99be290adca5eb --- ironic/conf/snmp.py | 10 ++++++++++ ironic/drivers/modules/snmp.py | 2 ++ ironic/tests/unit/drivers/modules/test_snmp.py | 10 ++++++++-- .../snmp_add_power_action_delay-eba6c3a9cbd6ada3.yaml | 8 ++++++++ 4 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 releasenotes/notes/snmp_add_power_action_delay-eba6c3a9cbd6ada3.yaml diff --git a/ironic/conf/snmp.py b/ironic/conf/snmp.py index 1a7026e2cc..f6787deb14 100644 --- a/ironic/conf/snmp.py +++ b/ironic/conf/snmp.py @@ -30,6 +30,16 @@ opts = [ min=0, help=_('Time (in seconds) to sleep between when rebooting ' '(powering off and on again)')), + cfg.IntOpt('power_action_delay', + default=0, + min=0, + help=_('Time (in seconds) to sleep before power on and ' + 'after powering off. Which may be needed with some ' + 'PDUs as they may not honor toggling a specific power ' + 'port in rapid succession without a delay. This option ' + 'may be useful if the attached physical machine has a ' + 'substantial power supply to hold it over in the event ' + 'of a brownout.')), cfg.FloatOpt('udp_transport_timeout', default=1.0, min=0.0, diff --git a/ironic/drivers/modules/snmp.py b/ironic/drivers/modules/snmp.py index ab6c3ade4b..a200b67175 100644 --- a/ironic/drivers/modules/snmp.py +++ b/ironic/drivers/modules/snmp.py @@ -511,6 +511,7 @@ class SNMPDriverBase(object, metaclass=abc.ABCMeta): :raises: SNMPFailure if an SNMP request fails. :returns: power state. One of :class:`ironic.common.states`. """ + time.sleep(CONF.snmp.power_action_delay) self._snmp_power_on() return self._snmp_wait_for_state(states.POWER_ON) @@ -521,6 +522,7 @@ class SNMPDriverBase(object, metaclass=abc.ABCMeta): :returns: power state. One of :class:`ironic.common.states`. """ self._snmp_power_off() + time.sleep(CONF.snmp.power_action_delay) return self._snmp_wait_for_state(states.POWER_OFF) def power_reset(self): diff --git a/ironic/tests/unit/drivers/modules/test_snmp.py b/ironic/tests/unit/drivers/modules/test_snmp.py index ba6fd6bc4a..36a59a3964 100644 --- a/ironic/tests/unit/drivers/modules/test_snmp.py +++ b/ironic/tests/unit/drivers/modules/test_snmp.py @@ -725,23 +725,29 @@ class SNMPDeviceDriverTestCase(db_base.DbTestCase): driver.power_state) mock_client.get.assert_called_once_with(driver._snmp_oid()) - def test_power_on(self, mock_get_client): + @mock.patch.object(time, 'sleep', autospec=True) + def test_power_on(self, mock_sleep, mock_get_client): # Ensure the device is powered on correctly + self.config(power_action_delay=1, group='snmp') mock_client = mock_get_client.return_value driver = snmp._get_driver(self.node) mock_client.get.return_value = driver.value_power_on pstate = driver.power_on() + mock_sleep.assert_called_once_with(1) mock_client.set.assert_called_once_with(driver._snmp_oid(), driver.value_power_on) mock_client.get.assert_called_once_with(driver._snmp_oid()) self.assertEqual(states.POWER_ON, pstate) - def test_power_off(self, mock_get_client): + @mock.patch.object(time, 'sleep', autospec=True) + def test_power_off(self, mock_sleep, mock_get_client): # Ensure the device is powered off correctly + self.config(power_action_delay=1, group='snmp') mock_client = mock_get_client.return_value driver = snmp._get_driver(self.node) mock_client.get.return_value = driver.value_power_off pstate = driver.power_off() + mock_sleep.assert_called_once_with(1) mock_client.set.assert_called_once_with(driver._snmp_oid(), driver.value_power_off) mock_client.get.assert_called_once_with(driver._snmp_oid()) diff --git a/releasenotes/notes/snmp_add_power_action_delay-eba6c3a9cbd6ada3.yaml b/releasenotes/notes/snmp_add_power_action_delay-eba6c3a9cbd6ada3.yaml new file mode 100644 index 0000000000..a3805d2144 --- /dev/null +++ b/releasenotes/notes/snmp_add_power_action_delay-eba6c3a9cbd6ada3.yaml @@ -0,0 +1,8 @@ +features: + - | + Adds new configuration option: ``[snmp]power_action_delay`` + This option will add a delay in seconds before a snmp power on and after + power off. Which may be needed with some PDUs as they may not honor + toggling a specific power port in rapid succession without a delay. + This option may be useful if the attached physical machine has a + substantial power supply to hold it over in the event of a brownout.