more iso cleanup and bug fixes

This commit is contained in:
Ryan Petrello
2019-03-25 13:39:52 -04:00
parent d0c952692d
commit 495dc2202f
4 changed files with 48 additions and 24 deletions

View File

@@ -95,19 +95,24 @@ class IsolatedManager(object):
def path_to(self, *args): def path_to(self, *args):
return os.path.join(self.private_data_dir, *args) return os.path.join(self.private_data_dir, *args)
def dispatch(self, playbook): def dispatch(self, playbook=None, module=None, module_args=None):
''' '''
Ship the runner payload to a remote host for isolated execution. Ship the runner payload to a remote host for isolated execution.
''' '''
self.handled_events = set()
self.started_at = time.time() self.started_at = time.time()
self.build_isolated_job_data() self.build_isolated_job_data()
extra_vars = { extra_vars = {
'src': self.private_data_dir, 'src': self.private_data_dir,
'dest': settings.AWX_PROOT_BASE_PATH, 'dest': settings.AWX_PROOT_BASE_PATH,
'playbook': playbook,
'ident': self.ident 'ident': self.ident
} }
if playbook:
extra_vars['playbook'] = playbook
if module and module_args:
extra_vars['module'] = module
extra_vars['module_args'] = module_args
# Run ansible-playbook to launch a job on the isolated host. This: # Run ansible-playbook to launch a job on the isolated host. This:
# #
@@ -129,12 +134,12 @@ class IsolatedManager(object):
output = buff.getvalue() output = buff.getvalue()
playbook_logger.info('Isolated job {} dispatch:\n{}'.format(self.instance.id, output)) playbook_logger.info('Isolated job {} dispatch:\n{}'.format(self.instance.id, output))
if status != 'successful': if status != 'successful':
event_data = { for event_data in [
'event': 'verbose', {'event': 'verbose', 'stdout': output},
'stdout': output {'event': 'EOF', 'final_counter': 1},
} ]:
event_data.setdefault(self.event_data_key, self.instance.id) event_data.setdefault(self.event_data_key, self.instance.id)
CallbackQueueDispatcher().dispatch(event_data) CallbackQueueDispatcher().dispatch(event_data)
return status, rc return status, rc
@classmethod @classmethod
@@ -207,7 +212,6 @@ class IsolatedManager(object):
buff = StringIO() buff = StringIO()
last_check = time.time() last_check = time.time()
job_timeout = remaining = self.job_timeout job_timeout = remaining = self.job_timeout
handled_events = set()
dispatcher = CallbackQueueDispatcher() dispatcher = CallbackQueueDispatcher()
while status == 'failed': while status == 'failed':
if job_timeout != 0: if job_timeout != 0:
@@ -241,15 +245,20 @@ class IsolatedManager(object):
# discover new events and ingest them # discover new events and ingest them
events_path = self.path_to('artifacts', self.ident, 'job_events') events_path = self.path_to('artifacts', self.ident, 'job_events')
for event in set(os.listdir(events_path)) - handled_events:
path = os.path.join(events_path, event) # it's possible that `events_path` doesn't exist *yet*, because runner
if os.path.exists(path): # hasn't actually written any events yet (if you ran e.g., a sleep 30)
event_data = json.load( # only attempt to consume events if any were rsynced back
open(os.path.join(events_path, event), 'r') if os.path.exists(events_path):
) for event in set(os.listdir(events_path)) - self.handled_events:
event_data.setdefault(self.event_data_key, self.instance.id) path = os.path.join(events_path, event)
dispatcher.dispatch(event_data) if os.path.exists(path):
handled_events.add(event) event_data = json.load(
open(os.path.join(events_path, event), 'r')
)
event_data.setdefault(self.event_data_key, self.instance.id)
dispatcher.dispatch(event_data)
self.handled_events.add(event)
last_check = time.time() last_check = time.time()
@@ -264,7 +273,7 @@ class IsolatedManager(object):
# emit an EOF event # emit an EOF event
event_data = { event_data = {
'event': 'EOF', 'event': 'EOF',
'final_counter': len(handled_events) 'final_counter': len(self.handled_events)
} }
event_data.setdefault(self.event_data_key, self.instance.id) event_data.setdefault(self.event_data_key, self.instance.id)
dispatcher.dispatch(event_data) dispatcher.dispatch(event_data)
@@ -372,7 +381,8 @@ class IsolatedManager(object):
if os.path.exists(facts_path): if os.path.exists(facts_path):
shutil.rmtree(facts_path) shutil.rmtree(facts_path)
def run(self, instance, private_data_dir, playbook, event_data_key, ident=None): def run(self, instance, private_data_dir, playbook, module, module_args,
event_data_key, ident=None):
""" """
Run a job on an isolated host. Run a job on an isolated host.
@@ -381,6 +391,8 @@ class IsolatedManager(object):
where job-specific data should be written where job-specific data should be written
(i.e., `/tmp/ansible_awx_xyz/`) (i.e., `/tmp/ansible_awx_xyz/`)
:param playbook: the playbook to run :param playbook: the playbook to run
:param module: the module to run
:param module_args: the module args to use
:param event_data_key: e.g., job_id, inventory_id, ... :param event_data_key: e.g., job_id, inventory_id, ...
For a completed job run, this function returns (status, rc), For a completed job run, this function returns (status, rc),
@@ -392,7 +404,7 @@ class IsolatedManager(object):
self.instance = instance self.instance = instance
self.host = instance.execution_node self.host = instance.execution_node
self.private_data_dir = private_data_dir self.private_data_dir = private_data_dir
status, rc = self.dispatch(playbook) status, rc = self.dispatch(playbook, module, module_args)
if status == 'successful': if status == 'successful':
status, rc = self.check() status, rc = self.check()
self.cleanup() self.cleanup()

View File

@@ -1172,7 +1172,11 @@ class BaseTask(object):
del params[v] del params[v]
if self.instance.is_isolated() is True: if self.instance.is_isolated() is True:
playbook = params['playbook'] module_args = None
if 'module_args' in params:
module_args = ansible_runner.utils.args2cmdline(
params.get('module_args'),
)
shutil.move( shutil.move(
params.pop('inventory'), params.pop('inventory'),
os.path.join(private_data_dir, 'inventory') os.path.join(private_data_dir, 'inventory')
@@ -1182,9 +1186,12 @@ class BaseTask(object):
manager_instance = isolated_manager.IsolatedManager(env, **_kw) manager_instance = isolated_manager.IsolatedManager(env, **_kw)
status, rc = manager_instance.run(self.instance, status, rc = manager_instance.run(self.instance,
private_data_dir, private_data_dir,
playbook, params.get('playbook'),
params.get('module'),
module_args,
event_data_key=self.event_data_key, event_data_key=self.event_data_key,
ident=str(self.instance.pk)) ident=str(self.instance.pk))
self.event_ct = len(manager_instance.handled_events)
else: else:
res = ansible_runner.interface.run(**params) res = ansible_runner.interface.run(**params)
status = res.status status = res.status

View File

@@ -27,6 +27,11 @@
- name: spawn the playbook - name: spawn the playbook
command: "ansible-runner start {{src}} -p {{playbook}} -i {{ident}}" command: "ansible-runner start {{src}} -p {{playbook}} -i {{ident}}"
when: playbook is defined
- name: spawn the adhoc command
command: "ansible-runner start {{src}} -m {{module}} -a {{module_args}} -i {{ident}}"
when: module is defined
- name: write the secret environment data - name: write the secret environment data
mkfifo: mkfifo:

View File

@@ -10,7 +10,7 @@ RUN yum -y update && yum -y install openssh-server ansible mg vim tmux git pytho
RUN ln -s /usr/bin/python36 /usr/bin/python3 RUN ln -s /usr/bin/python36 /usr/bin/python3
RUN python36 -m ensurepip RUN python36 -m ensurepip
RUN pip3 install virtualenv RUN pip3 install virtualenv
RUN pip3 install git+https://github.com/ansible/ansible-runner@master#egg=ansible_runner RUN pip3 install ansible-runner
WORKDIR /tmp WORKDIR /tmp
RUN make requirements_ansible RUN make requirements_ansible
RUN localedef -c -i en_US -f UTF-8 en_US.UTF-8 RUN localedef -c -i en_US -f UTF-8 en_US.UTF-8