def test_dont_suspend_unexistent_stack(self): mock_heat_client = Mock() mock_heat_client.stacks.get.side_effect = [HTTPNotFound] job = SuspenderJob(self.configuration) with patch.multiple( job, get_heat_client=Mock(return_value=mock_heat_client)): job.run() mock_heat_client.actions.suspend.assert_not_called()
def test_dont_suspend_unexistent_stack(self): # Setup mock_suspend_task = self.get_suspend_task_mock() # Run job = SuspenderJob(self.settings) job.run() # Assert mock_suspend_task.apply_async.assert_not_called()
def test_suspend_concurrency(self): self.configuration["suspend_concurrency"] = 2 suspend_timeout = self.configuration.get("suspend_timeout") timedelta = timezone.timedelta(seconds=(suspend_timeout + 1)) suspend_timestamp = timezone.now() - timedelta state = 'CREATE_COMPLETE' stack1_name = 'bogus_stack_1' stack1 = Stack(student_id=self.student_id, course_id=self.course_id, name=stack1_name, suspend_timestamp=suspend_timestamp, status=state) stack1.save() stack2_name = 'bogus_stack_2' stack2 = Stack(student_id=self.student_id, course_id=self.course_id, name=stack2_name, suspend_timestamp=suspend_timestamp, status=state) stack2.save() stack3_name = 'bogus_stack_3' stack3 = Stack(student_id=self.student_id, course_id=self.course_id, name=stack3_name, suspend_timestamp=suspend_timestamp, status=state) stack3.save() mock_heat_client = Mock() mock_heat_client.stacks.get.side_effect = [ self.stacks[state], self.stacks[state] ] job = SuspenderJob(self.configuration) with patch.multiple( job, get_heat_client=Mock(return_value=mock_heat_client)): job.run() mock_heat_client.actions.suspend.assert_has_calls( [call(stack_id=stack1_name), call(stack_id=stack2_name)]) self.assertNotIn(call(stack_id=stack3_name), mock_heat_client.actions.suspend.mock_calls) stack1 = Stack.objects.get(name=stack1_name) self.assertEqual(stack1.status, SUSPEND_ISSUED_STATE) stack2 = Stack.objects.get(name=stack2_name) self.assertEqual(stack2.status, SUSPEND_ISSUED_STATE) stack3 = Stack.objects.get(name=stack3_name) self.assertEqual(stack3.status, state)
def test_suspend_concurrency(self): # Setup self.settings["suspend_concurrency"] = 2 suspend_timeout = self.settings.get("suspend_timeout") timedelta = timezone.timedelta(seconds=(suspend_timeout + 1)) suspend_timestamp = timezone.now() - timedelta state = "CREATE_COMPLETE" stack1_name = "bogus_stack_1" stack1 = Stack(student_id=self.student_id, course_id=self.course_id, name=stack1_name, suspend_timestamp=suspend_timestamp, provider="provider1", status=state) stack1.save() stack2_name = "bogus_stack_2" stack2 = Stack(student_id=self.student_id, course_id=self.course_id, name=stack2_name, suspend_timestamp=suspend_timestamp, provider="provider2", status=state) stack2.save() stack3_name = "bogus_stack_3" stack3 = Stack(student_id=self.student_id, course_id=self.course_id, name=stack3_name, suspend_timestamp=suspend_timestamp, provider="provider3", status=state) stack3.save() mock_suspend_task = self.get_suspend_task_mock() # Run job = SuspenderJob(self.settings) job.run() # Assert self.assertEqual(2, len(mock_suspend_task.apply_async.mock_calls)) stack1 = Stack.objects.get(name=stack1_name) self.assertEqual(stack1.status, SUSPEND_PENDING) stack2 = Stack.objects.get(name=stack2_name) self.assertEqual(stack2.status, SUSPEND_PENDING) stack3 = Stack.objects.get(name=stack3_name) self.assertEqual(stack3.status, state)
def handle(self, *args, **options): # Get configuration settings = get_xblock_settings() # Schedule scheduler = BlockingScheduler() suspender = SuspenderJob(settings) interval = settings.get("suspend_interval", 60) scheduler.add_job(suspender.run, 'interval', seconds=interval) scheduler.start()
def test_dont_suspend_deleted_stack(self): suspend_timeout = self.configuration.get("suspend_timeout") timedelta = timezone.timedelta(seconds=(suspend_timeout + 1)) suspend_timestamp = timezone.now() - timedelta state = 'RESUME_COMPLETE' stack = Stack(student_id=self.student_id, course_id=self.course_id, suspend_timestamp=suspend_timestamp, name=self.stack_name, status=state) stack.save() mock_heat_client = Mock() mock_heat_client.stacks.get.side_effect = [HTTPNotFound] job = SuspenderJob(self.configuration) with patch.multiple( job, get_heat_client=Mock(return_value=mock_heat_client)): job.run() mock_heat_client.actions.suspend.assert_not_called() stack = Stack.objects.get(name=self.stack_name) self.assertEqual(stack.status, DELETED_STATE)
def test_dont_suspend_stack_with_no_provider(self): # Setup suspend_timeout = self.settings.get("suspend_timeout") timedelta = timezone.timedelta(seconds=(suspend_timeout + 1)) suspend_timestamp = timezone.now() - timedelta state = "RESUME_COMPLETE" stack = Stack(student_id=self.student_id, course_id=self.course_id, suspend_timestamp=suspend_timestamp, name=self.stack_name, status=state) stack.save() mock_suspend_task = self.get_suspend_task_mock() # Run job = SuspenderJob(self.settings) job.run() # Assert mock_suspend_task.apply_async.assert_not_called() stack = Stack.objects.get(name=self.stack_name) self.assertEqual(stack.status, state)
def test_stack_log(self): suspend_timeout = self.configuration.get("suspend_timeout") timedelta = timezone.timedelta(seconds=(suspend_timeout + 1)) suspend_timestamp = timezone.now() - timedelta state = 'CREATE_COMPLETE' stack = Stack(student_id=self.student_id, course_id=self.course_id, suspend_timestamp=suspend_timestamp, name=self.stack_name) stack.status = state stack.save() mock_heat_client = Mock() mock_heat_client.stacks.get.side_effect = [self.stacks[state]] job = SuspenderJob(self.configuration) with patch.multiple( job, get_heat_client=Mock(return_value=mock_heat_client)): job.run() stacklog = StackLog.objects.filter(stack_id=stack.id) states = [l.status for l in stacklog] expected_states = [state, 'SUSPEND_PENDING', 'SUSPEND_ISSUED'] self.assertEqual(states, expected_states)
def test_suspend_stack_for_the_first_time(self): # Setup suspend_timeout = self.settings.get("suspend_timeout") timedelta = timezone.timedelta(seconds=(suspend_timeout + 1)) suspend_timestamp = timezone.now() - timedelta state = "CREATE_COMPLETE" stack = Stack(student_id=self.student_id, course_id=self.course_id, suspend_timestamp=suspend_timestamp, name=self.stack_name, provider="provider1", status=state) stack.save() mock_suspend_task = self.get_suspend_task_mock() # Run job = SuspenderJob(self.settings) job.run() # Assert mock_suspend_task.apply_async.assert_called() stack = Stack.objects.get(name=self.stack_name) self.assertEqual(stack.status, SUSPEND_PENDING)
def test_stack_log(self): # Setup suspend_timeout = self.settings.get("suspend_timeout") timedelta = timezone.timedelta(seconds=(suspend_timeout + 1)) suspend_timestamp = timezone.now() - timedelta state = 'CREATE_COMPLETE' stack = Stack(student_id=self.student_id, course_id=self.course_id, suspend_timestamp=suspend_timestamp, provider='provider1', name=self.stack_name) stack.status = state stack.save() # Run job = SuspenderJob(self.settings) job.run() # Assert stacklog = StackLog.objects.filter(stack_id=stack.id) states = [l.status for l in stacklog] expected_states = [state, SUSPEND_PENDING] self.assertEqual(states, expected_states)
def handle(self, *args, **options): # Get configuration xblock_settings = django_settings.XBLOCK_SETTINGS if xblock_settings: settings = xblock_settings.get(SETTINGS_KEY, DEFAULT_SETTINGS) else: settings = DEFAULT_SETTINGS # Schedule scheduler = BlockingScheduler() suspender = SuspenderJob(settings) interval = settings.get("suspend_interval", 60) scheduler.add_job(suspender.run, 'interval', seconds=interval) scheduler.start()