#193 updates to service validation, will retry validation for validation_timer period, instead of just waiting, using configurable validation_period
This commit is contained in:
parent
11088c716a
commit
00920afbce
3 changed files with 79 additions and 44 deletions
|
@ -269,7 +269,7 @@ class ServiceManager(object):
|
||||||
cls.add(service)
|
cls.add(service)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
service_errors.append(service.name)
|
service_errors.append(service.name)
|
||||||
logger.warn("not loading service: %s", e.message)
|
logger.warn("not loading service: %s", e)
|
||||||
return service_errors
|
return service_errors
|
||||||
|
|
||||||
|
|
||||||
|
@ -462,7 +462,8 @@ class CoreServices(object):
|
||||||
:param CoreService service: service to start
|
:param CoreService service: service to start
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
logger.info("starting node(%s) service(%s)", node.name, service.name)
|
logger.info("starting node(%s) service(%s) validation(%s)", node.name, service.name,
|
||||||
|
service.validation_mode.name)
|
||||||
|
|
||||||
# create service directories
|
# create service directories
|
||||||
for directory in service.dirs:
|
for directory in service.dirs:
|
||||||
|
@ -477,14 +478,26 @@ class CoreServices(object):
|
||||||
if status:
|
if status:
|
||||||
raise ServiceBootError("node(%s) service(%s) error during startup" % (node.name, service.name))
|
raise ServiceBootError("node(%s) service(%s) error during startup" % (node.name, service.name))
|
||||||
|
|
||||||
# wait for time if provided, default to a time previously used to provide a small buffer
|
# blocking mode is finished
|
||||||
time.sleep(0.125)
|
if wait:
|
||||||
if service.validation_timer:
|
return
|
||||||
time.sleep(service.validation_timer)
|
|
||||||
|
# timer mode, sleep and return
|
||||||
|
if service.validation_mode == ServiceMode.TIMER:
|
||||||
|
time.sleep(service.validation_timer)
|
||||||
|
# non-blocking, attempt to validate periodically, up to validation_timer time
|
||||||
|
elif service.validation_mode == ServiceMode.NON_BLOCKING:
|
||||||
|
start = time.time()
|
||||||
|
while True:
|
||||||
|
status = self.validate_service(node, service)
|
||||||
|
if not status:
|
||||||
|
break
|
||||||
|
|
||||||
|
if time.time() - start > service.validation_timer:
|
||||||
|
break
|
||||||
|
|
||||||
|
time.sleep(service.validation_period)
|
||||||
|
|
||||||
# run validation commands, if present and not timer mode
|
|
||||||
if service.validation_mode != ServiceMode.TIMER:
|
|
||||||
status = self.validate_service(node, service)
|
|
||||||
if status:
|
if status:
|
||||||
raise ServiceBootError("node(%s) service(%s) failed validation" % (node.name, service.name))
|
raise ServiceBootError("node(%s) service(%s) failed validation" % (node.name, service.name))
|
||||||
|
|
||||||
|
@ -528,9 +541,11 @@ class CoreServices(object):
|
||||||
logger.debug("validating service(%s) using: %s", service.name, cmd)
|
logger.debug("validating service(%s) using: %s", service.name, cmd)
|
||||||
try:
|
try:
|
||||||
node.check_cmd(cmd)
|
node.check_cmd(cmd)
|
||||||
except CoreCommandError:
|
except CoreCommandError as e:
|
||||||
logger.exception("node(%s) service(%s) validate command failed", node.name, service.name)
|
logger.error("node(%s) service(%s) validate failed", node.name, service.name)
|
||||||
|
logger.error("cmd(%s): %s", e.cmd, e.output)
|
||||||
status = -1
|
status = -1
|
||||||
|
break
|
||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
@ -753,8 +768,11 @@ class CoreService(object):
|
||||||
# validation mode, used to determine startup success
|
# validation mode, used to determine startup success
|
||||||
validation_mode = ServiceMode.NON_BLOCKING
|
validation_mode = ServiceMode.NON_BLOCKING
|
||||||
|
|
||||||
# time to wait for determining if service started successfully
|
# time to wait in seconds for determining if service started successfully
|
||||||
validation_timer = 0
|
validation_timer = 5
|
||||||
|
|
||||||
|
# validation period in seconds, how frequent validation is attempted
|
||||||
|
validation_period = 0.5
|
||||||
|
|
||||||
# metadata associated with this service
|
# metadata associated with this service
|
||||||
meta = None
|
meta = None
|
||||||
|
|
|
@ -28,12 +28,15 @@ class MyService(CoreService):
|
||||||
# Commands used to validate that a service was started, any non-zero exit code will cause a failure.
|
# Commands used to validate that a service was started, any non-zero exit code will cause a failure.
|
||||||
validate = ()
|
validate = ()
|
||||||
# Validation mode, used to determine startup success.
|
# Validation mode, used to determine startup success.
|
||||||
|
#
|
||||||
# * NON_BLOCKING - runs startup commands, and validates success with validation commands
|
# * NON_BLOCKING - runs startup commands, and validates success with validation commands
|
||||||
# * BLOCKING - runs startup commands, and validates success with the startup commands themselves
|
# * BLOCKING - runs startup commands, and validates success with the startup commands themselves
|
||||||
# * TIMER - runs startup commands, and validates success by waiting for "validation_timer" alone
|
# * TIMER - runs startup commands, and validates success by waiting for "validation_timer" alone
|
||||||
validation_mode = ServiceMode.NON_BLOCKING
|
validation_mode = ServiceMode.NON_BLOCKING
|
||||||
# Time for a service to wait before running validation commands or determining success in TIMER mode.
|
# Time in seconds for a service to wait for validation, before determining success in TIMER/NON_BLOCKING modes.
|
||||||
validation_timer = 0
|
validation_timer = 5
|
||||||
|
# Period in seconds to wait before retrying validation, only used in NON_BLOCKING mode.
|
||||||
|
validation_period = 0.5
|
||||||
# Shutdown commands to stop this service.
|
# Shutdown commands to stop this service.
|
||||||
shutdown = ()
|
shutdown = ()
|
||||||
|
|
||||||
|
|
|
@ -114,11 +114,11 @@
|
||||||
<div class='octowrap'>
|
<div class='octowrap'>
|
||||||
<a class='octothorpe' href='#section-8'>#</a>
|
<a class='octothorpe' href='#section-8'>#</a>
|
||||||
</div>
|
</div>
|
||||||
<p>Files that this service will generate, without a full path this file goes in the node's directory.
|
<p>Files that this service will generate, without a full path this file goes in the node’s directory.
|
||||||
e.g. /tmp/pycore.12345/n1.conf/myfile</p>
|
e.g. /tmp/pycore.12345/n1.conf/myfile</p>
|
||||||
</div>
|
</div>
|
||||||
<div class='code'>
|
<div class='code'>
|
||||||
<div class="highlight"><pre> <span class="n">configs</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"sh myservice1.sh"</span><span class="p">,</span> <span class="s2">"sh myservice2.sh"</span><span class="p">)</span></pre></div>
|
<div class="highlight"><pre> <span class="n">configs</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"myservice1.sh"</span><span class="p">,</span> <span class="s2">"myservice2.sh"</span><span class="p">)</span></pre></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='clearall'></div>
|
<div class='clearall'></div>
|
||||||
|
@ -151,10 +151,12 @@ e.g. /tmp/pycore.12345/n1.conf/myfile</p>
|
||||||
<div class='octowrap'>
|
<div class='octowrap'>
|
||||||
<a class='octothorpe' href='#section-11'>#</a>
|
<a class='octothorpe' href='#section-11'>#</a>
|
||||||
</div>
|
</div>
|
||||||
<p>Validation mode, used to determine startup success.
|
<p>Validation mode, used to determine startup success.</p>
|
||||||
<em> NON_BLOCKING - runs startup commands, and validates success with validation commands
|
<ul>
|
||||||
</em> BLOCKING - runs startup commands, and validates success with the startup commands themselves
|
<li>NON_BLOCKING - runs startup commands, and validates success with validation commands</li>
|
||||||
* TIMER - runs startup commands, and validates success by waiting for "validation_timer" alone</p>
|
<li>BLOCKING - runs startup commands, and validates success with the startup commands themselves</li>
|
||||||
|
<li>TIMER - runs startup commands, and validates success by waiting for “validation_timer” alone</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class='code'>
|
<div class='code'>
|
||||||
<div class="highlight"><pre> <span class="n">validation_mode</span> <span class="o">=</span> <span class="n">ServiceMode</span><span class="o">.</span><span class="n">NON_BLOCKING</span></pre></div>
|
<div class="highlight"><pre> <span class="n">validation_mode</span> <span class="o">=</span> <span class="n">ServiceMode</span><span class="o">.</span><span class="n">NON_BLOCKING</span></pre></div>
|
||||||
|
@ -166,10 +168,10 @@ e.g. /tmp/pycore.12345/n1.conf/myfile</p>
|
||||||
<div class='octowrap'>
|
<div class='octowrap'>
|
||||||
<a class='octothorpe' href='#section-12'>#</a>
|
<a class='octothorpe' href='#section-12'>#</a>
|
||||||
</div>
|
</div>
|
||||||
<p>Time for a service to wait before running validation commands or determining success in TIMER mode.</p>
|
<p>Time in seconds for a service to wait for validation, before determining success in TIMER/NON_BLOCKING modes.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class='code'>
|
<div class='code'>
|
||||||
<div class="highlight"><pre> <span class="n">validation_timer</span> <span class="o">=</span> <span class="mi">0</span></pre></div>
|
<div class="highlight"><pre> <span class="n">validation_timer</span> <span class="o">=</span> <span class="mi">5</span></pre></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='clearall'></div>
|
<div class='clearall'></div>
|
||||||
|
@ -178,10 +180,10 @@ e.g. /tmp/pycore.12345/n1.conf/myfile</p>
|
||||||
<div class='octowrap'>
|
<div class='octowrap'>
|
||||||
<a class='octothorpe' href='#section-13'>#</a>
|
<a class='octothorpe' href='#section-13'>#</a>
|
||||||
</div>
|
</div>
|
||||||
<p>Shutdown commands to stop this service.</p>
|
<p>Period in seconds to wait before retrying validation, only used in NON_BLOCKING mode.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class='code'>
|
<div class='code'>
|
||||||
<div class="highlight"><pre> <span class="n">shutdown</span> <span class="o">=</span> <span class="p">()</span></pre></div>
|
<div class="highlight"><pre> <span class="n">validation_period</span> <span class="o">=</span> <span class="mf">0.5</span></pre></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='clearall'></div>
|
<div class='clearall'></div>
|
||||||
|
@ -190,6 +192,18 @@ e.g. /tmp/pycore.12345/n1.conf/myfile</p>
|
||||||
<div class='octowrap'>
|
<div class='octowrap'>
|
||||||
<a class='octothorpe' href='#section-14'>#</a>
|
<a class='octothorpe' href='#section-14'>#</a>
|
||||||
</div>
|
</div>
|
||||||
|
<p>Shutdown commands to stop this service.</p>
|
||||||
|
</div>
|
||||||
|
<div class='code'>
|
||||||
|
<div class="highlight"><pre> <span class="n">shutdown</span> <span class="o">=</span> <span class="p">()</span></pre></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class='clearall'></div>
|
||||||
|
<div class='section' id='section-15'>
|
||||||
|
<div class='docs'>
|
||||||
|
<div class='octowrap'>
|
||||||
|
<a class='octothorpe' href='#section-15'>#</a>
|
||||||
|
</div>
|
||||||
<h2>On Load</h2>
|
<h2>On Load</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class='code'>
|
<div class='code'>
|
||||||
|
@ -198,10 +212,10 @@ e.g. /tmp/pycore.12345/n1.conf/myfile</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='clearall'></div>
|
<div class='clearall'></div>
|
||||||
<div class='section' id='section-15'>
|
<div class='section' id='section-16'>
|
||||||
<div class='docs'>
|
<div class='docs'>
|
||||||
<div class='octowrap'>
|
<div class='octowrap'>
|
||||||
<a class='octothorpe' href='#section-15'>#</a>
|
<a class='octothorpe' href='#section-16'>#</a>
|
||||||
</div>
|
</div>
|
||||||
<p>Provides a way to run some arbitrary logic when the service is loaded, possibly to help facilitate
|
<p>Provides a way to run some arbitrary logic when the service is loaded, possibly to help facilitate
|
||||||
dynamic settings for the environment.</p>
|
dynamic settings for the environment.</p>
|
||||||
|
@ -211,10 +225,10 @@ dynamic settings for the environment.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='clearall'></div>
|
<div class='clearall'></div>
|
||||||
<div class='section' id='section-16'>
|
<div class='section' id='section-17'>
|
||||||
<div class='docs'>
|
<div class='docs'>
|
||||||
<div class='octowrap'>
|
<div class='octowrap'>
|
||||||
<a class='octothorpe' href='#section-16'>#</a>
|
<a class='octothorpe' href='#section-17'>#</a>
|
||||||
</div>
|
</div>
|
||||||
<h2>Get Configs</h2>
|
<h2>Get Configs</h2>
|
||||||
</div>
|
</div>
|
||||||
|
@ -224,10 +238,10 @@ dynamic settings for the environment.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='clearall'></div>
|
<div class='clearall'></div>
|
||||||
<div class='section' id='section-17'>
|
<div class='section' id='section-18'>
|
||||||
<div class='docs'>
|
<div class='docs'>
|
||||||
<div class='octowrap'>
|
<div class='octowrap'>
|
||||||
<a class='octothorpe' href='#section-17'>#</a>
|
<a class='octothorpe' href='#section-18'>#</a>
|
||||||
</div>
|
</div>
|
||||||
<p>Provides a way to dynamically generate the config files from the node a service will run.
|
<p>Provides a way to dynamically generate the config files from the node a service will run.
|
||||||
Defaults to the class definition and can be left out entirely if not needed.</p>
|
Defaults to the class definition and can be left out entirely if not needed.</p>
|
||||||
|
@ -237,10 +251,10 @@ Defaults to the class definition and can be left out entirely if not needed.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='clearall'></div>
|
<div class='clearall'></div>
|
||||||
<div class='section' id='section-18'>
|
<div class='section' id='section-19'>
|
||||||
<div class='docs'>
|
<div class='docs'>
|
||||||
<div class='octowrap'>
|
<div class='octowrap'>
|
||||||
<a class='octothorpe' href='#section-18'>#</a>
|
<a class='octothorpe' href='#section-19'>#</a>
|
||||||
</div>
|
</div>
|
||||||
<h2>Generate Config</h2>
|
<h2>Generate Config</h2>
|
||||||
</div>
|
</div>
|
||||||
|
@ -250,13 +264,13 @@ Defaults to the class definition and can be left out entirely if not needed.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='clearall'></div>
|
<div class='clearall'></div>
|
||||||
<div class='section' id='section-19'>
|
<div class='section' id='section-20'>
|
||||||
<div class='docs'>
|
<div class='docs'>
|
||||||
<div class='octowrap'>
|
<div class='octowrap'>
|
||||||
<a class='octothorpe' href='#section-19'>#</a>
|
<a class='octothorpe' href='#section-20'>#</a>
|
||||||
</div>
|
</div>
|
||||||
<p>Returns a string representation for a file, given the node the service is starting on the config filename
|
<p>Returns a string representation for a file, given the node the service is starting on the config filename
|
||||||
that this information will be used for. This must be defined, if "configs" are defined.</p>
|
that this information will be used for. This must be defined, if “configs” are defined.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class='code'>
|
<div class='code'>
|
||||||
<div class="highlight"><pre> <span class="n">cfg</span> <span class="o">=</span> <span class="s2">"#!/bin/sh</span><span class="se">\n</span><span class="s2">"</span>
|
<div class="highlight"><pre> <span class="n">cfg</span> <span class="o">=</span> <span class="s2">"#!/bin/sh</span><span class="se">\n</span><span class="s2">"</span>
|
||||||
|
@ -272,10 +286,10 @@ that this information will be used for. This must be defined, if "configs" are d
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='clearall'></div>
|
<div class='clearall'></div>
|
||||||
<div class='section' id='section-20'>
|
<div class='section' id='section-21'>
|
||||||
<div class='docs'>
|
<div class='docs'>
|
||||||
<div class='octowrap'>
|
<div class='octowrap'>
|
||||||
<a class='octothorpe' href='#section-20'>#</a>
|
<a class='octothorpe' href='#section-21'>#</a>
|
||||||
</div>
|
</div>
|
||||||
<h2>Get Startup</h2>
|
<h2>Get Startup</h2>
|
||||||
</div>
|
</div>
|
||||||
|
@ -285,10 +299,10 @@ that this information will be used for. This must be defined, if "configs" are d
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='clearall'></div>
|
<div class='clearall'></div>
|
||||||
<div class='section' id='section-21'>
|
<div class='section' id='section-22'>
|
||||||
<div class='docs'>
|
<div class='docs'>
|
||||||
<div class='octowrap'>
|
<div class='octowrap'>
|
||||||
<a class='octothorpe' href='#section-21'>#</a>
|
<a class='octothorpe' href='#section-22'>#</a>
|
||||||
</div>
|
</div>
|
||||||
<p>Provides a way to dynamically generate the startup commands from the node a service will run.
|
<p>Provides a way to dynamically generate the startup commands from the node a service will run.
|
||||||
Defaults to the class definition and can be left out entirely if not needed.</p>
|
Defaults to the class definition and can be left out entirely if not needed.</p>
|
||||||
|
@ -298,10 +312,10 @@ Defaults to the class definition and can be left out entirely if not needed.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='clearall'></div>
|
<div class='clearall'></div>
|
||||||
<div class='section' id='section-22'>
|
<div class='section' id='section-23'>
|
||||||
<div class='docs'>
|
<div class='docs'>
|
||||||
<div class='octowrap'>
|
<div class='octowrap'>
|
||||||
<a class='octothorpe' href='#section-22'>#</a>
|
<a class='octothorpe' href='#section-23'>#</a>
|
||||||
</div>
|
</div>
|
||||||
<h2>Get Validate</h2>
|
<h2>Get Validate</h2>
|
||||||
</div>
|
</div>
|
||||||
|
@ -311,10 +325,10 @@ Defaults to the class definition and can be left out entirely if not needed.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='clearall'></div>
|
<div class='clearall'></div>
|
||||||
<div class='section' id='section-23'>
|
<div class='section' id='section-24'>
|
||||||
<div class='docs'>
|
<div class='docs'>
|
||||||
<div class='octowrap'>
|
<div class='octowrap'>
|
||||||
<a class='octothorpe' href='#section-23'>#</a>
|
<a class='octothorpe' href='#section-24'>#</a>
|
||||||
</div>
|
</div>
|
||||||
<p>Provides a way to dynamically generate the validate commands from the node a service will run.
|
<p>Provides a way to dynamically generate the validate commands from the node a service will run.
|
||||||
Defaults to the class definition and can be left out entirely if not needed.</p>
|
Defaults to the class definition and can be left out entirely if not needed.</p>
|
||||||
|
|
Loading…
Reference in a new issue