termination handling
- moved to base cli class to handle centrally and duplicate less code - now avoids duplication and reiteration of signal handler by reassigning it - left note on how to do non-graceful in case we add in future as I won't remember everything i did here and don't want to 'relearn' it.
This commit is contained in:
parent
371c7315b0
commit
38120c1075
3 changed files with 19 additions and 22 deletions
|
@ -27,6 +27,7 @@ import time
|
||||||
import yaml
|
import yaml
|
||||||
import re
|
import re
|
||||||
import getpass
|
import getpass
|
||||||
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from ansible import __version__
|
from ansible import __version__
|
||||||
|
@ -44,7 +45,7 @@ except ImportError:
|
||||||
class SortedOptParser(optparse.OptionParser):
|
class SortedOptParser(optparse.OptionParser):
|
||||||
'''Optparser which sorts the options by opt before outputting --help'''
|
'''Optparser which sorts the options by opt before outputting --help'''
|
||||||
|
|
||||||
# TODO: epilog parsing: OptionParser.format_epilog = lambda self, formatter: self.epilog
|
#FIXME: epilog parsing: OptionParser.format_epilog = lambda self, formatter: self.epilog
|
||||||
|
|
||||||
def format_help(self, formatter=None, epilog=None):
|
def format_help(self, formatter=None, epilog=None):
|
||||||
self.option_list.sort(key=operator.methodcaller('get_opt_string'))
|
self.option_list.sort(key=operator.methodcaller('get_opt_string'))
|
||||||
|
@ -77,6 +78,20 @@ class CLI(object):
|
||||||
self.action = None
|
self.action = None
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
|
|
||||||
|
def _terminate(self, signum=None, framenum=None):
|
||||||
|
if signum == signal.SIGTERM:
|
||||||
|
if hasattr(os, 'getppid'):
|
||||||
|
display.debug("Termination requested in parent, shutting down gracefully")
|
||||||
|
signal.signal(signal.SIGTERM, signal.SIG_DFL)
|
||||||
|
else:
|
||||||
|
display.debug("Term signal in child, harakiri!")
|
||||||
|
signal.signal(signal.SIGTERM, signal.SIG_IGN)
|
||||||
|
|
||||||
|
raise SystemExit
|
||||||
|
|
||||||
|
#NOTE: if ever want to make this immediately kill children use on parent:
|
||||||
|
#os.killpg(os.getpgid(0), signal.SIGTERM)
|
||||||
|
|
||||||
def set_action(self):
|
def set_action(self):
|
||||||
"""
|
"""
|
||||||
Get the action the user wants to execute from the sys argv list.
|
Get the action the user wants to execute from the sys argv list.
|
||||||
|
@ -109,6 +124,9 @@ class CLI(object):
|
||||||
else:
|
else:
|
||||||
display.display(u"No config file found; using defaults")
|
display.display(u"No config file found; using defaults")
|
||||||
|
|
||||||
|
# Manage user interruptions
|
||||||
|
signal.signal(signal.SIGTERM, self._terminate)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def ask_vault_passwords(ask_new_vault_pass=False, rekey=False):
|
def ask_vault_passwords(ask_new_vault_pass=False, rekey=False):
|
||||||
''' prompt for vault password and/or password change '''
|
''' prompt for vault password and/or password change '''
|
||||||
|
|
|
@ -21,7 +21,6 @@ __metaclass__ = type
|
||||||
########################################################
|
########################################################
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import signal
|
|
||||||
|
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.cli import CLI
|
from ansible.cli import CLI
|
||||||
|
@ -89,11 +88,6 @@ class AdHocCLI(CLI):
|
||||||
tasks = [ dict(action=dict(module=self.options.module_name, args=parse_kv(self.options.module_args)), async=async, poll=poll) ]
|
tasks = [ dict(action=dict(module=self.options.module_name, args=parse_kv(self.options.module_args)), async=async, poll=poll) ]
|
||||||
)
|
)
|
||||||
|
|
||||||
def _terminate(self, signum=None, framenum=None):
|
|
||||||
if signum is not None:
|
|
||||||
display.debug("Termination signal detected, shutting down gracefully")
|
|
||||||
raise SystemExit
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
''' use Runner lib to do SSH things '''
|
''' use Runner lib to do SSH things '''
|
||||||
|
|
||||||
|
@ -176,9 +170,6 @@ class AdHocCLI(CLI):
|
||||||
# now create a task queue manager to execute the play
|
# now create a task queue manager to execute the play
|
||||||
self._tqm = None
|
self._tqm = None
|
||||||
try:
|
try:
|
||||||
# Manage user interruptions
|
|
||||||
signal.signal(signal.SIGTERM, self._terminate)
|
|
||||||
|
|
||||||
self._tqm = TaskQueueManager(
|
self._tqm = TaskQueueManager(
|
||||||
inventory=inventory,
|
inventory=inventory,
|
||||||
variable_manager=variable_manager,
|
variable_manager=variable_manager,
|
||||||
|
|
|
@ -19,11 +19,7 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
import getpass
|
|
||||||
import locale
|
|
||||||
import os
|
import os
|
||||||
import signal
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from ansible.compat.six import string_types
|
from ansible.compat.six import string_types
|
||||||
|
|
||||||
|
@ -32,8 +28,6 @@ from ansible.executor.task_queue_manager import TaskQueueManager
|
||||||
from ansible.playbook import Playbook
|
from ansible.playbook import Playbook
|
||||||
from ansible.template import Templar
|
from ansible.template import Templar
|
||||||
|
|
||||||
from ansible.utils.unicode import to_unicode
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from __main__ import display
|
from __main__ import display
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -69,8 +63,6 @@ class PlaybookExecutor:
|
||||||
may limit the runs to serialized groups, etc.
|
may limit the runs to serialized groups, etc.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
signal.signal(signal.SIGTERM, self._terminate)
|
|
||||||
|
|
||||||
result = 0
|
result = 0
|
||||||
entrylist = []
|
entrylist = []
|
||||||
entry = {}
|
entry = {}
|
||||||
|
@ -207,10 +199,6 @@ class PlaybookExecutor:
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _terminate(self, signum=None, framenum=None):
|
|
||||||
display.debug("Termination signal detected, shutting down gracefully")
|
|
||||||
raise SystemExit
|
|
||||||
|
|
||||||
def _get_serialized_batches(self, play):
|
def _get_serialized_batches(self, play):
|
||||||
'''
|
'''
|
||||||
Returns a list of hosts, subdivided into batches based on
|
Returns a list of hosts, subdivided into batches based on
|
||||||
|
|
Loading…
Reference in a new issue