Skip to content

Commit

Permalink
Merge pull request #3235 from Uninett/feature/cancel-maintenance-task…
Browse files Browse the repository at this point in the history
…s-without-components

Cancel  scheduled maintenance tasks when all their components are missing
  • Loading branch information
lunkwill42 authored Nov 29, 2024
2 parents 1953020 + fa8994b commit 2acf2ce
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 4 deletions.
1 change: 1 addition & 0 deletions changelog.d/3229.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Active maintenance tasks that only reference deleted components will be automatically cancelled
20 changes: 16 additions & 4 deletions python/nav/maintengine.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,8 @@ def check_tasks_without_end():

@transaction.atomic()
def do_state_transitions():
"""
Finds active or scheduled tasks that have run out and sets them as passed,
and finds scheduled scheduled tasks in the current window and sets them
as active.
"""Finds active or scheduled tasks that have run out and sets them as passed,
and finds scheduled tasks in the current window and sets them as active.
"""
tasks = MaintenanceTask.objects.past().filter(
state__in=[MaintenanceTask.STATE_ACTIVE, MaintenanceTask.STATE_SCHEDULED]
Expand All @@ -105,6 +103,20 @@ def do_state_transitions():

_logger.debug("Tasks transitioned to active state: %r", tasks)

cancel_tasks_without_components()


def cancel_tasks_without_components():
"""Cancels active tasks where all components are missing"""
tasks = MaintenanceTask.objects.filter(
state=MaintenanceTask.STATE_ACTIVE
).prefetch_related('maintenance_components')
for task in tasks:
if not any(task.get_components()):
task.state = MaintenanceTask.STATE_CANCELED
task.save()
_logger.debug("Task %r canceled because all components were missing", task)


def check_state_differences():
"""
Expand Down
61 changes: 61 additions & 0 deletions tests/integration/maintengine_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from datetime import datetime, timedelta

import pytest

from nav import maintengine
from nav.models.msgmaint import MaintenanceTask, MaintenanceComponent


class TestCancelTasksWithoutComponents:
def test_it_should_cancel_active_empty_tasks(self, empty_task):
assert empty_task.state == MaintenanceTask.STATE_ACTIVE
maintengine.cancel_tasks_without_components()
empty_task.refresh_from_db()
assert empty_task.state == MaintenanceTask.STATE_CANCELED

def test_it_should_not_cancel_scheduled_empty_tasks(self, scheduled_empty_task):
assert scheduled_empty_task.state == MaintenanceTask.STATE_SCHEDULED
maintengine.cancel_tasks_without_components()
scheduled_empty_task.refresh_from_db()
assert scheduled_empty_task.state == MaintenanceTask.STATE_SCHEDULED

def test_it_should_not_cancel_nonempty_tasks(self, half_empty_task):
assert half_empty_task.state == MaintenanceTask.STATE_ACTIVE
maintengine.cancel_tasks_without_components()
half_empty_task.refresh_from_db()
assert half_empty_task.state == MaintenanceTask.STATE_ACTIVE


@pytest.fixture
def empty_task(db):
task = MaintenanceTask(
start_time=datetime.now() - timedelta(minutes=30),
end_time=datetime.now() + timedelta(minutes=30),
description="Test task",
state=MaintenanceTask.STATE_ACTIVE,
)
task.save()
component = MaintenanceComponent(
maintenance_task=task,
key="netbox",
value=99999,
)
component.save()

yield task


@pytest.fixture
def scheduled_empty_task(empty_task):
empty_task.state = MaintenanceTask.STATE_SCHEDULED
empty_task.start_time = datetime.now() + timedelta(minutes=30)
empty_task.end_time = datetime.now() + timedelta(minutes=60)
empty_task.save()
yield empty_task


@pytest.fixture
def half_empty_task(empty_task, localhost):
component = MaintenanceComponent(maintenance_task=empty_task, component=localhost)
component.save()
yield empty_task

0 comments on commit 2acf2ce

Please sign in to comment.