Feature: retry on subset of jobs hosts

This commit is contained in:
AlanCoding
2017-10-16 09:58:56 -04:00
parent f1813c35ed
commit 0ae9283fba
7 changed files with 176 additions and 4 deletions

View File

@@ -37,6 +37,7 @@ from polymorphic.models import PolymorphicModel
# AWX
from awx.main.constants import SCHEDULEABLE_PROVIDERS, ANSI_SGR_PATTERN
from awx.main.models import * # noqa
from awx.main.models.unified_jobs import ACTIVE_STATES
from awx.main.access import get_user_capabilities
from awx.main.fields import ImplicitRoleField
from awx.main.utils import (
@@ -2642,9 +2643,19 @@ class JobCancelSerializer(JobSerializer):
class JobRelaunchSerializer(JobSerializer):
passwords_needed_to_start = serializers.SerializerMethodField()
retry_counts = serializers.SerializerMethodField()
hosts = serializers.ChoiceField(
required=False, allow_null=True, default='all',
choices=[
('all', _('No change to job limit')),
('failed', _('All failed and unreachable hosts')),
('unreachable', _('Unreachable hosts'))
],
write_only=True
)
class Meta:
fields = ('passwords_needed_to_start',)
fields = ('passwords_needed_to_start', 'retry_counts', 'hosts',)
def to_internal_value(self, data):
obj = self.context.get('obj')
@@ -2666,6 +2677,14 @@ class JobRelaunchSerializer(JobSerializer):
return obj.passwords_needed_to_start
return ''
def get_retry_counts(self, obj):
if obj.status in ACTIVE_STATES:
return _('Relaunch by host status not available until job finishes running.')
data = OrderedDict([])
for status in self.fields['hosts'].choices.keys():
data[status] = obj.retry_qs(status).count()
return data
def validate_passwords_needed_to_start(self, value):
obj = self.context.get('obj')
data = self.context.get('data')
@@ -2685,6 +2704,7 @@ class JobRelaunchSerializer(JobSerializer):
raise serializers.ValidationError(dict(errors=[_("Job Template Project is missing or undefined.")]))
if obj.inventory is None or obj.inventory.pending_deletion:
raise serializers.ValidationError(dict(errors=[_("Job Template Inventory is missing or undefined.")]))
attrs.pop('hosts', None)
attrs = super(JobRelaunchSerializer, self).validate(attrs)
return attrs

View File

@@ -3834,7 +3834,26 @@ class JobRelaunch(RetrieveAPIView):
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
new_job = obj.copy_unified_job()
copy_kwargs = {}
retry_hosts = request.data.get('hosts', None)
if retry_hosts and retry_hosts != 'all':
if obj.status in ACTIVE_STATES:
return Response({'hosts': _(
'Wait until job finishes before retrying on {status_value} hosts.'
).format(status_value=retry_hosts)}, status=status.HTTP_400_BAD_REQUEST)
host_qs = obj.retry_qs(retry_hosts)
if not obj.job_events.filter(event='playbook_on_stats').exists():
return Response({'hosts': _(
'Cannot retry on {status_value} hosts, playbook stats not available.'
).format(status_value=retry_hosts)}, status=status.HTTP_400_BAD_REQUEST)
retry_host_list = host_qs.values_list('name', flat=True)
if len(retry_host_list) == 0:
return Response({'hosts': _(
'Cannot relaunch because previous job had 0 {status_value} hosts.'
).format(status_value=retry_hosts)}, status=status.HTTP_400_BAD_REQUEST)
copy_kwargs['limit'] = ','.join(retry_host_list)
new_job = obj.copy_unified_job(**copy_kwargs)
result = new_job.signal_start(**request.data)
if not result:
data = dict(passwords_needed_to_start=new_job.passwords_needed_to_start)