Ejemplo n.º 1
0
    def test_retry_deletion(self):
        delete_age = self.configuration.get("delete_age")
        delete_delta = timezone.timedelta(days=(delete_age + 1))
        delete_timestamp = timezone.now() - delete_delta
        state = 'RESUME_COMPLETE'
        stack_name = 'bogus_stack'
        stack = Stack(student_id=self.student_id,
                      course_id=self.course_id,
                      name=stack_name,
                      suspend_timestamp=delete_timestamp)
        stack.status = state
        stack.save()
        mock_heat_client = Mock()
        mock_heat_client.stacks.get.side_effect = [
            self.stacks[state], self.stacks[DELETE_FAILED_STATE],
            self.stacks[DELETE_FAILED_STATE], self.stacks[DELETE_FAILED_STATE]
        ]

        job = ReaperJob(self.configuration)
        with patch.multiple(
                job, get_heat_client=Mock(return_value=mock_heat_client)):
            job.run()

        mock_heat_client.stacks.delete.assert_has_calls([
            call(stack_id=stack_name),
            call(stack_id=stack_name),
            call(stack_id=stack_name)
        ])
        stack = Stack.objects.get(name=stack_name)
        self.assertEqual(stack.status, DELETE_FAILED_STATE)
Ejemplo n.º 2
0
    def test_exception_destroying_zombies(self):
        # Setup
        mock_provider = self.mocks["Provider"].init.return_value
        mock_provider.get_stacks.side_effect = ProviderException("")
        self.settings["providers"] = {"provider": {}}

        # Run
        job = ReaperJob(self.settings)
        job.run()
Ejemplo n.º 3
0
    def test_dont_try_to_delete_certain_stack_states(self):
        # Setup
        delete_age = self.settings.get("delete_age")
        delete_delta = timezone.timedelta(days=(delete_age + 1))
        delete_timestamp = timezone.now() - delete_delta
        stack1_name = "bogus_stack_1"
        stack1 = Stack(student_id=self.student_id,
                       course_id=self.course_id,
                       name=stack1_name,
                       suspend_timestamp=delete_timestamp,
                       provider="provider1",
                       status=DELETE_PENDING)
        stack1.save()
        stack2_name = "bogus_stack_2"
        stack2 = Stack(student_id=self.student_id,
                       course_id=self.course_id,
                       name=stack2_name,
                       suspend_timestamp=delete_timestamp,
                       provider="provider2",
                       status=DELETE_IN_PROGRESS)
        stack2.save()
        stack3_name = "bogus_stack_3"
        stack3 = Stack(student_id=self.student_id,
                       course_id=self.course_id,
                       name=stack3_name,
                       suspend_timestamp=delete_timestamp,
                       provider="provider3",
                       status=DELETE_COMPLETE)
        stack3.save()
        stack4_name = "bogus_stack_4"
        stack4 = Stack(student_id=self.student_id,
                       course_id=self.course_id,
                       name=stack4_name,
                       suspend_timestamp=delete_timestamp,
                       status="CREATE_FAILED")
        stack4.save()
        mock_delete_task = self.get_delete_task_mock()

        # Run
        job = ReaperJob(self.settings)
        job.run()

        # Assert
        mock_delete_task.apply_async.assert_not_called()
        stack1 = Stack.objects.get(name=stack1_name)
        self.assertEqual(stack1.status, DELETE_PENDING)
        stack2 = Stack.objects.get(name=stack2_name)
        self.assertEqual(stack2.status, DELETE_IN_PROGRESS)
        stack3 = Stack.objects.get(name=stack3_name)
        self.assertEqual(stack3.status, DELETE_COMPLETE)
        stack4 = Stack.objects.get(name=stack4_name)
        self.assertEqual(stack4.status, "CREATE_FAILED")
Ejemplo n.º 4
0
    def test_delete_old_stacks(self):
        delete_age = self.configuration.get("delete_age")
        delete_delta = timezone.timedelta(days=(delete_age + 1))
        delete_timestamp = timezone.now() - delete_delta
        dont_delete_delta = timezone.timedelta(days=(delete_age - 1))
        dont_delete_timestamp = timezone.now() - dont_delete_delta
        state = 'RESUME_COMPLETE'
        stack1_name = 'bogus_stack_1'
        stack1 = Stack(student_id=self.student_id,
                       course_id=self.course_id,
                       name=stack1_name,
                       suspend_timestamp=delete_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=delete_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=dont_delete_timestamp,
                       status=state)
        stack3.save()
        mock_heat_client = Mock()
        mock_heat_client.stacks.get.side_effect = [
            self.stacks[state], self.stacks[DELETE_IN_PROGRESS_STATE],
            HTTPNotFound, self.stacks[state],
            self.stacks[DELETE_IN_PROGRESS_STATE], HTTPNotFound
        ]

        job = ReaperJob(self.configuration)
        with patch.multiple(
                job, get_heat_client=Mock(return_value=mock_heat_client)):
            job.run()

        mock_heat_client.stacks.delete.assert_has_calls(
            [call(stack_id=stack1_name),
             call(stack_id=stack2_name)])
        self.assertNotIn(call(stack_id=stack3_name),
                         mock_heat_client.stacks.delete.mock_calls)
        stack1 = Stack.objects.get(name=stack1_name)
        self.assertEqual(stack1.status, DELETED_STATE)
        stack2 = Stack.objects.get(name=stack2_name)
        self.assertEqual(stack2.status, DELETED_STATE)
        stack3 = Stack.objects.get(name=stack3_name)
        self.assertEqual(stack3.status, state)
Ejemplo n.º 5
0
    def test_delete_old_stacks(self):
        # Setup
        delete_age = self.settings.get("delete_age")
        delete_delta = timezone.timedelta(days=(delete_age + 1))
        delete_timestamp = timezone.now() - delete_delta
        dont_delete_delta = timezone.timedelta(days=(delete_age - 1))
        dont_delete_timestamp = timezone.now() - dont_delete_delta
        state = "RESUME_COMPLETE"
        stack1_name = "bogus_stack_1"
        stack1 = Stack(student_id=self.student_id,
                       course_id=self.course_id,
                       name=stack1_name,
                       suspend_timestamp=delete_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=delete_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=dont_delete_timestamp,
                       provider='provider3',
                       status=state)
        stack3.save()
        mock_delete_task = self.get_delete_task_mock()

        # Run
        job = ReaperJob(self.settings)
        job.run()

        # Assert
        self.assertEqual(2, len(mock_delete_task.apply_async.mock_calls))
        stack1 = Stack.objects.get(name=stack1_name)
        self.assertEqual(stack1.status, DELETE_PENDING)
        stack2 = Stack.objects.get(name=stack2_name)
        self.assertEqual(stack2.status, DELETE_PENDING)
        stack3 = Stack.objects.get(name=stack3_name)
        self.assertEqual(stack3.status, state)
Ejemplo n.º 6
0
    def handle(self, *args, **options):
        # Get configuration
        settings = get_xblock_settings()

        # Schedule
        scheduler = BlockingScheduler()
        job = ReaperJob(settings)
        interval = settings.get("delete_interval", 3600)
        scheduler.add_job(job.run, 'interval', seconds=interval)
        scheduler.start()
Ejemplo n.º 7
0
    def test_dont_delete_if_age_is_zero(self):
        self.configuration["delete_age"] = 0
        delete_delta = timezone.timedelta(days=15)
        delete_timestamp = timezone.now() - delete_delta
        state = 'RESUME_COMPLETE'
        stack_name = 'bogus_stack'
        stack = Stack(student_id=self.student_id,
                      course_id=self.course_id,
                      name=stack_name,
                      suspend_timestamp=delete_timestamp,
                      status=state)
        stack.save()
        mock_heat_client = Mock()

        job = ReaperJob(self.configuration)
        with patch.multiple(
                job, get_heat_client=Mock(return_value=mock_heat_client)):
            job.run()

        mock_heat_client.stacks.delete.assert_not_called()
        stack = Stack.objects.get(name=stack_name)
        self.assertEqual(stack.status, state)
Ejemplo n.º 8
0
    def test_dont_try_to_delete_certain_stack_states(self):
        delete_age = self.configuration.get("delete_age")
        delete_delta = timezone.timedelta(days=(delete_age + 1))
        delete_timestamp = timezone.now() - delete_delta
        stack1_name = 'bogus_stack_1'
        stack1 = Stack(student_id=self.student_id,
                       course_id=self.course_id,
                       name=stack1_name,
                       suspend_timestamp=delete_timestamp,
                       status=DELETE_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=delete_timestamp,
                       status=DELETE_IN_PROGRESS_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=delete_timestamp,
                       status=DELETED_STATE)
        stack3.save()
        mock_heat_client = Mock()

        job = ReaperJob(self.configuration)
        with patch.multiple(
                job, get_heat_client=Mock(return_value=mock_heat_client)):
            job.run()

        mock_heat_client.stacks.delete.assert_not_called()
        stack1 = Stack.objects.get(name=stack1_name)
        self.assertEqual(stack1.status, DELETE_STATE)
        stack2 = Stack.objects.get(name=stack2_name)
        self.assertEqual(stack2.status, DELETE_IN_PROGRESS_STATE)
        stack3 = Stack.objects.get(name=stack3_name)
        self.assertEqual(stack3.status, DELETED_STATE)
Ejemplo n.º 9
0
    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()
        job = ReaperJob(settings)
        interval = settings.get("delete_interval", 3600)
        scheduler.add_job(job.run, 'interval', seconds=interval)
        scheduler.start()
Ejemplo n.º 10
0
    def test_dont_delete_if_age_is_zero(self):
        # Setup
        self.settings["delete_age"] = 0
        delete_delta = timezone.timedelta(days=15)
        delete_timestamp = timezone.now() - delete_delta
        state = 'RESUME_COMPLETE'
        stack_name = 'bogus_stack'
        stack = Stack(student_id=self.student_id,
                      course_id=self.course_id,
                      name=stack_name,
                      suspend_timestamp=delete_timestamp,
                      provider='provider1',
                      status=state)
        stack.save()
        mock_delete_task = self.get_delete_task_mock()

        # Run
        job = ReaperJob(self.settings)
        job.run()

        mock_delete_task.apply_async.assert_not_called()
        stack = Stack.objects.get(name=stack_name)
        self.assertEqual(stack.status, state)
Ejemplo n.º 11
0
    def test_destroy_zombies(self):
        # Setup
        delete_age = self.settings.get("delete_age")
        delete_delta = timezone.timedelta(days=(delete_age + 1))
        delete_timestamp = timezone.now() - delete_delta
        dont_delete_delta = timezone.timedelta(days=(delete_age - 1))
        dont_delete_timestamp = timezone.now() - dont_delete_delta
        stack_names = ('zombie_stack_1', 'zombie_stack_2', 'zombie_stack_3',
                       'zombie_stack_4', 'not_a_zombie_stack')

        # Create zombie stacks
        for i in range(0, 4):
            _stack = Stack(student_id=self.student_id,
                           course_id=self.course_id,
                           name=stack_names[i],
                           suspend_timestamp=delete_timestamp,
                           status=DELETE_COMPLETE)
            _stack.save()

        # Create living stack
        _stack = Stack(student_id=self.student_id,
                       course_id=self.course_id,
                       name=stack_names[4],
                       suspend_timestamp=dont_delete_timestamp,
                       status=CREATE_COMPLETE)
        _stack.save()

        mock_provider = self.mocks["Provider"].init.return_value
        provider1_stacks = []
        for i in range(0, 3):
            provider1_stacks.append({
                "name": stack_names[i],
                "status": CREATE_COMPLETE
            })
        provider2_stacks = []
        for i in range(3, 5):
            provider2_stacks.append({
                "name": stack_names[i],
                "status": CREATE_COMPLETE
            })
        provider3_stacks = [{"name": "unknown", "status": CREATE_COMPLETE}]
        mock_provider.get_stacks.side_effect = [
            provider1_stacks, provider2_stacks, provider3_stacks
        ]
        self.settings["providers"] = {
            "provider1": {},
            "provider2": {},
            "provider3": {}
        }
        mock_delete_task = self.get_delete_task_mock()

        # Run
        job = ReaperJob(self.settings)
        job.run()

        # Assert
        self.assertEqual(4, len(mock_delete_task.apply_async.mock_calls))
        stack = Stack.objects.get(name=stack_names[0])
        self.assertEqual(stack.status, DELETE_PENDING)
        stack = Stack.objects.get(name=stack_names[1])
        self.assertEqual(stack.status, DELETE_PENDING)
        stack = Stack.objects.get(name=stack_names[2])
        self.assertEqual(stack.status, DELETE_PENDING)
        stack = Stack.objects.get(name=stack_names[3])
        self.assertEqual(stack.status, DELETE_PENDING)
        stack = Stack.objects.get(name=stack_names[4])
        self.assertEqual(stack.status, CREATE_COMPLETE)