Skip to content

Commit

Permalink
Merge pull request #215 from observatorycontrolsystem/fix_cancel_in_p…
Browse files Browse the repository at this point in the history
…rogress

Add preemption_enabled flag to cancel endpoint to allow cancelling of…
  • Loading branch information
jnation3406 committed Sep 9, 2021
2 parents 3ce206a + 415a0ce commit 9dc37ed
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 6 deletions.
1 change: 1 addition & 0 deletions observation_portal/observations/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ class CancelObservationsSerializer(serializers.Serializer):
include_normal = serializers.BooleanField(required=False, default=True)
include_rr = serializers.BooleanField(required=False, default=False)
include_direct = serializers.BooleanField(required=False, default=False)
preemption_enabled = serializers.BooleanField(required=False, default=False)

def validate(self, data):
if 'ids' not in data and ('start' not in data or 'end' not in data):
Expand Down
37 changes: 37 additions & 0 deletions observation_portal/observations/test/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,43 @@ def test_cancel_current_observations_aborts_them(self):
observation_obj = Observation.objects.first()
self.assertEqual(observation_obj.state, 'ABORTED')

def test_cancel_current_in_progress_observation_fails(self):
self.window.start = datetime(2016, 8, 28, tzinfo=timezone.utc)
self.window.save()
observation = self._generate_observation_data(self.requestgroup.requests.first().id,
[self.requestgroup.requests.first().configurations.first().id])
observation['start'] = "2016-08-31T23:35:39Z"
observation['end'] = "2016-09-01T01:35:39Z"
self._create_observation(observation)
obs = Observation.objects.first()
obs.state = 'IN_PROGRESS'
obs.save()
cancel_dict = {'start': "2016-09-01T00:00:00Z", 'end': "2016-09-18T00:00:00Z"}
response = self.client.post(reverse('api:observations-cancel'), data=cancel_dict)
self.assertContains(response, 'Cannot cancel IN_PROGRESS observations', status_code=400)
obs.refresh_from_db()
self.assertEqual(obs.state, 'IN_PROGRESS')

def test_cancel_current_in_progress_observation_succeeds_with_preemption(self):
self.window.start = datetime(2016, 8, 28, tzinfo=timezone.utc)
self.window.save()
observation = self._generate_observation_data(self.requestgroup.requests.first().id,
[self.requestgroup.requests.first().configurations.first().id])
observation['start'] = "2016-08-31T23:35:39Z"
observation['end'] = "2016-09-01T01:35:39Z"
self._create_observation(observation)
obs = Observation.objects.first()
obs.state = 'IN_PROGRESS'
obs.save()
cancel_dict = {'start': "2016-09-01T00:00:00Z", 'end': "2016-09-18T00:00:00Z", 'preemption_enabled': True}
response = self.client.post(reverse('api:observations-cancel'), data=cancel_dict)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json()['canceled'], 1)
self.assertEqual(len(Observation.objects.all()), 1)
self.assertEqual(len(ConfigurationStatus.objects.all()), 1)
obs.refresh_from_db()
self.assertEqual(obs.state, 'ABORTED')

def test_cancel_by_time_range_observations_succeeds(self):
observation = self._generate_observation_data(self.requestgroup.requests.first().id,
[self.requestgroup.requests.first().configurations.first().id])
Expand Down
17 changes: 11 additions & 6 deletions observation_portal/observations/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,14 @@ def cancel(self, request):
cancel_serializer = import_string(settings.SERIALIZERS['observations']['Cancel'])(data=request.data)
if cancel_serializer.is_valid():
observations = self.get_queryset()
# Two modes of cancelling, by id or by start/end time range
if 'ids' in cancel_serializer.data:
observations = observations.filter(pk__in=cancel_serializer.data['ids'])
if 'start' in cancel_serializer.data:
observations = observations.filter(end__gt=cancel_serializer.data['start'])
if 'end' in cancel_serializer.data:
observations = observations.filter(start__lt=cancel_serializer.data['end'])
else:
if 'start' in cancel_serializer.data:
observations = observations.filter(end__gt=cancel_serializer.data['start'])
if 'end' in cancel_serializer.data:
observations = observations.filter(start__lt=cancel_serializer.data['end'])
if 'site' in cancel_serializer.data:
observations = observations.filter(site=cancel_serializer.data['site'])
if 'enclosure' in cancel_serializer.data:
Expand All @@ -115,10 +117,13 @@ def cancel(self, request):
observations = observations.exclude(request__request_group__observation_type=RequestGroup.DIRECT)
if request.user and not request.user.is_staff:
observations = observations.filter(request__request_group__proposal__direct_submission=True)
# First check if we have an in_progress observation that overlaps with the time range and resource.
# If we do and preemption is not enabled in the call, return a 400 error without cancelling anything.
if observations.filter(state='IN_PROGRESS').count() > 0 and not cancel_serializer.data.get('preemption_enabled', False):
return Response({'error': 'Cannot cancel IN_PROGRESS observations unless preemption_enabled is True'}, status=400)
observations = observations.filter(state__in=['PENDING', 'IN_PROGRESS'])
# Receive a list of observation id's to cancel
num_canceled = Observation.cancel(observations)

num_canceled = Observation.cancel(observations)
return Response({'canceled': num_canceled}, status=200)
else:
return Response(cancel_serializer.errors, status=400)
Expand Down

0 comments on commit 9dc37ed

Please sign in to comment.