mirror of
https://github.com/ansible/awx.git
synced 2024-11-02 09:51:09 +03:00
AC-620 Some cleanup of job events to reduce extra queries, test case to reproduce deadlocks.
This commit is contained in:
parent
a1ff025488
commit
9b49e80dc5
@ -615,54 +615,59 @@ class JobEvent(BaseModel):
|
|||||||
# If update_fields has been specified, add our field names to it,
|
# If update_fields has been specified, add our field names to it,
|
||||||
# if it hasn't been specified, then we're just doing a normal save.
|
# if it hasn't been specified, then we're just doing a normal save.
|
||||||
update_fields = kwargs.get('update_fields', [])
|
update_fields = kwargs.get('update_fields', [])
|
||||||
res = self.event_data.get('res', None)
|
# Skip normal checks on save if we're only updating failed/changed
|
||||||
# Workaround for Ansible 1.2, where the runner_on_async_ok event is
|
# flags triggered from a child event.
|
||||||
# created even when the async task failed. Change the event to be
|
from_parent_update = kwargs.pop('from_parent_update', False)
|
||||||
# correct.
|
if not from_parent_update:
|
||||||
if self.event == 'runner_on_async_ok':
|
res = self.event_data.get('res', None)
|
||||||
try:
|
# Workaround for Ansible 1.2, where the runner_on_async_ok event is
|
||||||
if res.get('failed', False) or res.get('rc', 0) != 0:
|
# created even when the async task failed. Change the event to be
|
||||||
self.event = 'runner_on_async_failed'
|
# correct.
|
||||||
except (AttributeError, TypeError):
|
if self.event == 'runner_on_async_ok':
|
||||||
pass
|
try:
|
||||||
if self.event in self.FAILED_EVENTS:
|
if res.get('failed', False) or res.get('rc', 0) != 0:
|
||||||
if not self.event_data.get('ignore_errors', False):
|
self.event = 'runner_on_async_failed'
|
||||||
self.failed = True
|
except (AttributeError, TypeError):
|
||||||
if 'failed' not in update_fields:
|
pass
|
||||||
update_fields.append('failed')
|
if self.event in self.FAILED_EVENTS:
|
||||||
if isinstance(res, dict) and res.get('changed', False):
|
if not self.event_data.get('ignore_errors', False):
|
||||||
self.changed = True
|
self.failed = True
|
||||||
if 'changed' not in update_fields:
|
if 'failed' not in update_fields:
|
||||||
update_fields.append('changed')
|
update_fields.append('failed')
|
||||||
if self.event == 'playbook_on_stats':
|
if isinstance(res, dict) and res.get('changed', False):
|
||||||
try:
|
self.changed = True
|
||||||
failures_dict = self.event_data.get('failures', {})
|
|
||||||
dark_dict = self.event_data.get('dark', {})
|
|
||||||
self.failed = bool(sum(failures_dict.values()) +
|
|
||||||
sum(dark_dict.values()))
|
|
||||||
if 'failed' not in update_fields:
|
|
||||||
update_fields.append('failed')
|
|
||||||
changed_dict = self.event_data.get('changed', {})
|
|
||||||
self.changed = bool(sum(changed_dict.values()))
|
|
||||||
if 'changed' not in update_fields:
|
if 'changed' not in update_fields:
|
||||||
update_fields.append('changed')
|
update_fields.append('changed')
|
||||||
except (AttributeError, TypeError):
|
if self.event == 'playbook_on_stats':
|
||||||
|
try:
|
||||||
|
failures_dict = self.event_data.get('failures', {})
|
||||||
|
dark_dict = self.event_data.get('dark', {})
|
||||||
|
self.failed = bool(sum(failures_dict.values()) +
|
||||||
|
sum(dark_dict.values()))
|
||||||
|
if 'failed' not in update_fields:
|
||||||
|
update_fields.append('failed')
|
||||||
|
changed_dict = self.event_data.get('changed', {})
|
||||||
|
self.changed = bool(sum(changed_dict.values()))
|
||||||
|
if 'changed' not in update_fields:
|
||||||
|
update_fields.append('changed')
|
||||||
|
except (AttributeError, TypeError):
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
if not self.host and self.event_data.get('host', ''):
|
||||||
|
self.host = self.job.inventory.hosts.get(name=self.event_data['host'])
|
||||||
|
if 'host' not in update_fields:
|
||||||
|
update_fields.append('host')
|
||||||
|
except (Host.DoesNotExist, AttributeError):
|
||||||
pass
|
pass
|
||||||
try:
|
self.play = self.event_data.get('play', '')
|
||||||
if not self.host and self.event_data.get('host', ''):
|
self.task = self.event_data.get('task', '')
|
||||||
self.host = self.job.inventory.hosts.get(name=self.event_data['host'])
|
self.parent = self._find_parent()
|
||||||
if 'host' not in update_fields:
|
update_fields.extend(['play', 'task', 'parent'])
|
||||||
update_fields.append('host')
|
|
||||||
except (Host.DoesNotExist, AttributeError):
|
|
||||||
pass
|
|
||||||
self.play = self.event_data.get('play', '')
|
|
||||||
self.task = self.event_data.get('task', '')
|
|
||||||
self.parent = self._find_parent()
|
|
||||||
update_fields.extend(['play', 'task', 'parent'])
|
|
||||||
super(JobEvent, self).save(*args, **kwargs)
|
super(JobEvent, self).save(*args, **kwargs)
|
||||||
self.update_parent_failed_and_changed()
|
if not from_parent_update:
|
||||||
self.update_hosts()
|
self.update_parent_failed_and_changed()
|
||||||
self.update_host_summary_from_stats()
|
self.update_hosts()
|
||||||
|
self.update_host_summary_from_stats()
|
||||||
|
|
||||||
def update_parent_failed_and_changed(self):
|
def update_parent_failed_and_changed(self):
|
||||||
# Propagage failed and changed flags to parent events.
|
# Propagage failed and changed flags to parent events.
|
||||||
@ -676,7 +681,7 @@ class JobEvent(BaseModel):
|
|||||||
parent.changed = True
|
parent.changed = True
|
||||||
update_fields.append('changed')
|
update_fields.append('changed')
|
||||||
if update_fields:
|
if update_fields:
|
||||||
parent.save(update_fields=update_fields)
|
parent.save(update_fields=update_fields, from_parent_update=True)
|
||||||
parent.update_parent_failed_and_changed()
|
parent.update_parent_failed_and_changed()
|
||||||
|
|
||||||
def update_hosts(self, extra_hosts=None):
|
def update_hosts(self, extra_hosts=None):
|
||||||
|
@ -1364,16 +1364,14 @@ class JobTransactionTest(BaseJobTestMixin, django.test.LiveServerTestCase):
|
|||||||
finally:
|
finally:
|
||||||
t.join(20)
|
t.join(20)
|
||||||
|
|
||||||
# FIXME: This test isn't working for now.
|
def test_for_job_deadlocks(self):
|
||||||
def _test_get_job_detail_while_job_running(self):
|
# Create lots of extra test hosts to trigger job event callbacks
|
||||||
self.proj_async = self.make_project('async', 'async test',
|
job = self.job_eng_run
|
||||||
self.user_sue, TEST_ASYNC_PLAYBOOK)
|
inv = job.inventory
|
||||||
self.org_eng.projects.add(self.proj_async)
|
for x in xrange(100):
|
||||||
job = self.job_ops_east_run
|
h = inv.hosts.create(name='local-%d' % x)
|
||||||
job.project = self.proj_async
|
for g in inv.groups.all():
|
||||||
job.playbook = self.proj_async.playbooks[0]
|
g.hosts.add(h)
|
||||||
job.verbosity = 3
|
|
||||||
job.save()
|
|
||||||
|
|
||||||
job_detail_url = reverse('api:job_detail', args=(job.pk,))
|
job_detail_url = reverse('api:job_detail', args=(job.pk,))
|
||||||
job_detail_url = urlparse.urljoin(self.live_server_url, job_detail_url)
|
job_detail_url = urlparse.urljoin(self.live_server_url, job_detail_url)
|
||||||
|
Loading…
Reference in New Issue
Block a user