Merge "Add an iboot reboot_delay setting"

This commit is contained in:
Jenkins 2015-10-22 22:00:15 +00:00 committed by Gerrit Code Review
commit ac3e7f8f06
3 changed files with 108 additions and 35 deletions

View File

@ -166,7 +166,11 @@
# The name of a logging configuration file. This file is # The name of a logging configuration file. This file is
# appended to any existing logging configuration files. For # appended to any existing logging configuration files. For
# details about logging configuration files, see the Python # details about logging configuration files, see the Python
# logging module documentation. (string value) # logging module documentation. Note that when logging
# configuration files are used then all logging configuration
# is set in the configuration file and other logging
# configuration options are ignored (for example, log_format).
# (string value)
# Deprecated group/name - [DEFAULT]/log_config # Deprecated group/name - [DEFAULT]/log_config
#log_config_append=<None> #log_config_append=<None>
@ -174,38 +178,54 @@
# which may use any of the available logging.LogRecord # which may use any of the available logging.LogRecord
# attributes. This option is deprecated. Please use # attributes. This option is deprecated. Please use
# logging_context_format_string and # logging_context_format_string and
# logging_default_format_string instead. (string value) # logging_default_format_string instead. This option is
# ignored if log_config_append is set. (string value)
#log_format=<None> #log_format=<None>
# Format string for %%(asctime)s in log records. Default: # Format string for %%(asctime)s in log records. Default:
# %(default)s . (string value) # %(default)s . This option is ignored if log_config_append is
# set. (string value)
#log_date_format=%Y-%m-%d %H:%M:%S #log_date_format=%Y-%m-%d %H:%M:%S
# (Optional) Name of log file to output to. If no default is # (Optional) Name of log file to output to. If no default is
# set, logging will go to stdout. (string value) # set, logging will go to stdout. This option is ignored if
# log_config_append is set. (string value)
# Deprecated group/name - [DEFAULT]/logfile # Deprecated group/name - [DEFAULT]/logfile
#log_file=<None> #log_file=<None>
# (Optional) The base directory used for relative --log-file # (Optional) The base directory used for relative --log-file
# paths. (string value) # paths. This option is ignored if log_config_append is set.
# (string value)
# Deprecated group/name - [DEFAULT]/logdir # Deprecated group/name - [DEFAULT]/logdir
#log_dir=<None> #log_dir=<None>
# (Optional) Uses logging handler designed to watch file
# system. When log file is moved or removed this handler will
# open a new log file with specified path instantaneously. It
# makes sense only if log-file option is specified and Linux
# platform is used. This option is ignored if
# log_config_append is set. (boolean value)
#watch_log_file=false
# Use syslog for logging. Existing syslog format is DEPRECATED # Use syslog for logging. Existing syslog format is DEPRECATED
# and will be changed later to honor RFC5424. (boolean value) # and will be changed later to honor RFC5424. This option is
# ignored if log_config_append is set. (boolean value)
#use_syslog=false #use_syslog=false
# (Optional) Enables or disables syslog rfc5424 format for # (Optional) Enables or disables syslog rfc5424 format for
# logging. If enabled, prefixes the MSG part of the syslog # logging. If enabled, prefixes the MSG part of the syslog
# message with APP-NAME (RFC5424). The format without the APP- # message with APP-NAME (RFC5424). The format without the APP-
# NAME is deprecated in Kilo, and will be removed in Mitaka, # NAME is deprecated in Kilo, and will be removed in Mitaka,
# along with this option. (boolean value) # along with this option. This option is ignored if
# log_config_append is set. (boolean value)
#use_syslog_rfc_format=true #use_syslog_rfc_format=true
# Syslog facility to receive log lines. (string value) # Syslog facility to receive log lines. This option is ignored
# if log_config_append is set. (string value)
#syslog_log_facility=LOG_USER #syslog_log_facility=LOG_USER
# Log output to standard error. (boolean value) # Log output to standard error. This option is ignored if
# log_config_append is set. (boolean value)
#use_stderr=true #use_stderr=true
# Format string to use for log messages with context. (string # Format string to use for log messages with context. (string
@ -224,7 +244,8 @@
# (string value) # (string value)
#logging_exception_prefix=%(asctime)s.%(msecs)03d %(process)d ERROR %(name)s %(instance)s #logging_exception_prefix=%(asctime)s.%(msecs)03d %(process)d ERROR %(name)s %(instance)s
# List of logger=LEVEL pairs. (list value) # List of logger=LEVEL pairs. This option is ignored if
# log_config_append is set. (list value)
#default_log_levels=amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,oslo.messaging=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN,urllib3.connectionpool=WARN,websocket=WARN,requests.packages.urllib3.util.retry=WARN,urllib3.util.retry=WARN,keystonemiddleware=WARN,routes.middleware=WARN,stevedore=WARN,taskflow=WARN #default_log_levels=amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,oslo.messaging=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN,urllib3.connectionpool=WARN,websocket=WARN,requests.packages.urllib3.util.retry=WARN,urllib3.util.retry=WARN,keystonemiddleware=WARN,routes.middleware=WARN,stevedore=WARN,taskflow=WARN
# Enables or disables publication of error events. (boolean # Enables or disables publication of error events. (boolean
@ -257,10 +278,15 @@
#rpc_zmq_bind_address=* #rpc_zmq_bind_address=*
# MatchMaker driver. (string value) # MatchMaker driver. (string value)
#rpc_zmq_matchmaker=local #rpc_zmq_matchmaker=redis
# ZeroMQ receiver listening port. (integer value) # Use REQ/REP pattern for all methods CALL/CAST/FANOUT.
#rpc_zmq_port=9501 # (boolean value)
#rpc_zmq_all_req_rep=true
# Type of concurrency used. Either "native" or "eventlet"
# (string value)
#rpc_zmq_concurrency=eventlet
# Number of ZeroMQ contexts, defaults to 1. (integer value) # Number of ZeroMQ contexts, defaults to 1. (integer value)
#rpc_zmq_contexts=1 #rpc_zmq_contexts=1
@ -281,11 +307,23 @@
# by impl_zmq. (integer value) # by impl_zmq. (integer value)
#rpc_cast_timeout=30 #rpc_cast_timeout=30
# Heartbeat frequency. (integer value) # The default number of seconds that poll should wait. Poll
#matchmaker_heartbeat_freq=300 # raises timeout exception when timeout expired. (integer
# value)
#rpc_poll_timeout=1
# Heartbeat time-to-live. (integer value) # Shows whether zmq-messaging uses broker or not. (boolean
#matchmaker_heartbeat_ttl=600 # value)
#zmq_use_broker=true
# Host to locate redis. (string value)
#host=127.0.0.1
# Use this port to connect to redis host. (integer value)
#port=6379
# Password for Redis server (optional). (string value)
#password=
# Size of executor thread pool. (integer value) # Size of executor thread pool. (integer value)
# Deprecated group/name - [DEFAULT]/rpc_thread_pool_size # Deprecated group/name - [DEFAULT]/rpc_thread_pool_size
@ -998,6 +1036,10 @@
# operations (integer value) # operations (integer value)
#retry_interval=1 #retry_interval=1
# Time (in seconds) to sleep between when rebooting (powering
# off and on again). (integer value)
#reboot_delay=5
[ilo] [ilo]
@ -1376,18 +1418,7 @@
#port=6379 #port=6379
# Password for Redis server (optional). (string value) # Password for Redis server (optional). (string value)
#password=<None> #password=
[matchmaker_ring]
#
# Options defined in oslo.messaging
#
# Matchmaker ring file (JSON). (string value)
# Deprecated group/name - [DEFAULT]/matchmaker_ringfile
#ringfile=/etc/oslo/matchmaker_ring.json
[neutron] [neutron]
@ -1444,7 +1475,7 @@
# Max connection retries to check changes on OneView (integer # Max connection retries to check changes on OneView (integer
# value) # value)
#max_polling_attempts=20 #max_polling_attempts=12
[oslo_concurrency] [oslo_concurrency]
@ -1511,6 +1542,24 @@
# Accept clients using either SSL or plain TCP (boolean value) # Accept clients using either SSL or plain TCP (boolean value)
#allow_insecure_clients=false #allow_insecure_clients=false
# Space separated list of acceptable SASL mechanisms (string
# value)
#sasl_mechanisms=
# Path to directory that contains the SASL configuration
# (string value)
#sasl_config_dir=
# Name of configuration file (without .conf suffix) (string
# value)
#sasl_config_name=
# User name for message broker authentication (string value)
#username=
# Password for message broker authentication (string value)
#password=
[oslo_messaging_qpid] [oslo_messaging_qpid]
@ -1782,7 +1831,7 @@
#ipxe_boot_script=$pybasedir/drivers/modules/boot.ipxe #ipxe_boot_script=$pybasedir/drivers/modules/boot.ipxe
# The IP version that will be used for PXE booting. Can be # The IP version that will be used for PXE booting. Can be
# either 4 or 6. Defaults to 4. EXPERIMENTAL (integer value) # either 4 or 6. Defaults to 4. EXPERIMENTAL (string value)
#ip_version=4 #ip_version=4

View File

@ -19,6 +19,8 @@
Ironic iBoot PDU power manager. Ironic iBoot PDU power manager.
""" """
import time
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log as logging from oslo_log import log as logging
from oslo_service import loopingcall from oslo_service import loopingcall
@ -41,6 +43,11 @@ opts = [
default=1, default=1,
help=_('Time (in seconds) between retry attempts for iBoot ' help=_('Time (in seconds) between retry attempts for iBoot '
'operations')), 'operations')),
cfg.IntOpt('reboot_delay',
default=5,
min=0,
help=_('Time (in seconds) to sleep between when rebooting '
'(powering off and on again).'))
] ]
CONF = cfg.CONF CONF = cfg.CONF
@ -139,6 +146,11 @@ def _switch(driver_info, enabled):
return mutable['response'] return mutable['response']
def _sleep_switch(seconds):
"""Function broken out for testing purpose."""
time.sleep(seconds)
def _power_status(driver_info): def _power_status(driver_info):
conn = _get_connection(driver_info) conn = _get_connection(driver_info)
relay_id = driver_info['relay_id'] relay_id = driver_info['relay_id']
@ -258,6 +270,7 @@ class IBootPower(base.PowerInterface):
""" """
driver_info = _parse_driver_info(task.node) driver_info = _parse_driver_info(task.node)
_switch(driver_info, False) _switch(driver_info, False)
_sleep_switch(CONF.iboot.reboot_delay)
_switch(driver_info, True) _switch(driver_info, True)
state = _power_status(driver_info) state = _power_status(driver_info)

View File

@ -259,6 +259,7 @@ class IBootDriverTestCase(db_base.DbTestCase):
super(IBootDriverTestCase, self).setUp() super(IBootDriverTestCase, self).setUp()
self.config(max_retry=0, group='iboot') self.config(max_retry=0, group='iboot')
self.config(retry_interval=0, group='iboot') self.config(retry_interval=0, group='iboot')
self.config(reboot_delay=0, group='iboot')
mgr_utils.mock_the_extension_manager(driver='fake_iboot') mgr_utils.mock_the_extension_manager(driver='fake_iboot')
self.driver = driver_factory.get_driver('fake_iboot') self.driver = driver_factory.get_driver('fake_iboot')
self.node = obj_utils.create_test_node( self.node = obj_utils.create_test_node(
@ -310,14 +311,19 @@ class IBootDriverTestCase(db_base.DbTestCase):
task.driver.power.set_power_state, task.driver.power.set_power_state,
task, states.NOSTATE) task, states.NOSTATE)
@mock.patch.object(iboot, '_sleep_switch', spec_set=types.FunctionType)
@mock.patch.object(iboot, '_power_status', autospec=True) @mock.patch.object(iboot, '_power_status', autospec=True)
@mock.patch.object(iboot, '_switch', spec_set=types.FunctionType) @mock.patch.object(iboot, '_switch', spec_set=types.FunctionType)
def test_reboot_good(self, mock_switch, mock_power_status): def test_reboot_good(self, mock_switch, mock_power_status,
manager = mock.MagicMock(spec_set=['switch']) mock_sleep_switch):
self.config(reboot_delay=3, group='iboot')
manager = mock.MagicMock(spec_set=['switch', 'sleep'])
mock_power_status.return_value = states.POWER_ON mock_power_status.return_value = states.POWER_ON
manager.attach_mock(mock_switch, 'switch') manager.attach_mock(mock_switch, 'switch')
manager.attach_mock(mock_sleep_switch, 'sleep')
expected = [mock.call.switch(self.info, False), expected = [mock.call.switch(self.info, False),
mock.call.sleep(3),
mock.call.switch(self.info, True)] mock.call.switch(self.info, True)]
with task_manager.acquire(self.context, self.node.uuid) as task: with task_manager.acquire(self.context, self.node.uuid) as task:
@ -325,14 +331,19 @@ class IBootDriverTestCase(db_base.DbTestCase):
self.assertEqual(manager.mock_calls, expected) self.assertEqual(manager.mock_calls, expected)
@mock.patch.object(iboot, '_sleep_switch', spec_set=types.FunctionType)
@mock.patch.object(iboot, '_power_status', autospec=True) @mock.patch.object(iboot, '_power_status', autospec=True)
@mock.patch.object(iboot, '_switch', spec_set=types.FunctionType) @mock.patch.object(iboot, '_switch', spec_set=types.FunctionType)
def test_reboot_bad(self, mock_switch, mock_power_status): def test_reboot_bad(self, mock_switch, mock_power_status,
manager = mock.MagicMock(spec_set=['switch']) mock_sleep_switch):
self.config(reboot_delay=3, group='iboot')
manager = mock.MagicMock(spec_set=['switch', 'sleep'])
mock_power_status.return_value = states.POWER_OFF mock_power_status.return_value = states.POWER_OFF
manager.attach_mock(mock_switch, 'switch') manager.attach_mock(mock_switch, 'switch')
manager.attach_mock(mock_sleep_switch, 'sleep')
expected = [mock.call.switch(self.info, False), expected = [mock.call.switch(self.info, False),
mock.call.sleep(3),
mock.call.switch(self.info, True)] mock.call.switch(self.info, True)]
with task_manager.acquire(self.context, self.node.uuid) as task: with task_manager.acquire(self.context, self.node.uuid) as task: