Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate sw job filters #397

Draft
wants to merge 7 commits into
base: next3.0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/user/lifecycle_reporting.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ You can run these reports two ways:

![](../images/lcm_software_validation_report_run.png)

- The "Jobs" dropdown and navigating to **Device/Sofware Lifecycle Reporting** section. The jobs will appear here and all you will need to do is click the play button.
- The "Jobs" dropdown and navigating to **Device/Sofware Lifecycle Reporting** section. The jobs will appear here and all you will need to do is click the play button. You'll then be able to select the platforms and tenants to run the report for, and click on **Run Job Now** execute button on right side of screen.

![](../images/lcm_software_validation_report_run_jobs.png)

Expand Down
2 changes: 2 additions & 0 deletions nautobot_device_lifecycle_mgmt/choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,12 @@ class ReportRunTypeChoices(ChoiceSet):

REPORT_SINGLE_OBJECT_RUN = "single-object-run"
REPORT_FULL_RUN = "full-report-run"
REPORT_FILTERED_RUN = "filtered-report-run"

CHOICES = (
(REPORT_SINGLE_OBJECT_RUN, "Single Object Run"),
(REPORT_FULL_RUN, "Full Report Run"),
(REPORT_FILTERED_RUN, "Filtered Report Run"),
)


Expand Down
71 changes: 64 additions & 7 deletions nautobot_device_lifecycle_mgmt/jobs/lifecycle_reporting.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
"""Jobs for the Lifecycle Management app."""

from datetime import datetime
from itertools import product

from nautobot.dcim.models import Device, InventoryItem
from nautobot.extras.jobs import Job
from nautobot.dcim.models import Device, InventoryItem, Platform
from nautobot.extras.jobs import Job, MultiObjectVar
from nautobot.tenancy.models import Tenant

from nautobot_device_lifecycle_mgmt import choices
from nautobot_device_lifecycle_mgmt.models import (
Expand Down Expand Up @@ -84,34 +86,89 @@ class DeviceSoftwareValidationFullReport(Job):
description = "Validates software version on devices."
read_only = False

# Add dropdowns for platform and tenant filters; Defaults to all platforms and tenants
platform = MultiObjectVar(
model=Platform,
label="Platform",
description="Filter by platform; defaults to all platforms",
required=False,
)
tenant = MultiObjectVar(
model=Tenant,
label="Tenant",
description="Filter by tenant; defaults to all tenants",
required=False,
)

filters = [platform, tenant]

class Meta:
"""Meta class for the job."""

has_sensitive_variables = False

def run(self) -> None: # pylint: disable=arguments-differ
def run(self, **filters) -> None: # pylint: disable=arguments-differ
"""Check if software assigned to each device is valid. If no software is assigned return warning message."""
job_run_time = datetime.now()
validation_count = 0

for device in Device.objects.filter(software_version__isnull=True):
# Create empty lists for versioned and non-versioned devices
versioned_devices = [] # Devices with software version
non_versioned_devices = [] # Devices without software version
all_tenants = False
all_platforms = False

# Get filters
platforms = filters.get("platform")
tenants = filters.get("tenant")

# If no platforms or tenants are provided, use all platforms and tenants
if not platforms:
platforms = Platform.objects.all()
all_platforms = True

if not tenants:
tenants = Tenant.objects.all()
all_tenants = True

# Get all combinations of platforms and tenants
filtered_products = product(platforms, tenants)

# Get versioned and non-versioned devices
for platform, tenant in filtered_products:
versioned_devices.extend(
Device.objects.filter(platform=platform, tenant=tenant, software_version__isnull=False)
)
non_versioned_devices.extend(
Device.objects.filter(platform=platform, tenant=tenant, software_version__isnull=True)
)

# Validate devices without software version
for device in non_versioned_devices:
validate_obj, _ = DeviceSoftwareValidationResult.objects.get_or_create(device=device)
validate_obj.is_validated = False
validate_obj.valid_software.set(ValidatedSoftwareLCM.objects.get_for_object(device))
validate_obj.software = None
validate_obj.last_run = job_run_time
validate_obj.run_type = choices.ReportRunTypeChoices.REPORT_FULL_RUN
if all_tenants and all_platforms:
validate_obj.run_type = choices.ReportRunTypeChoices.REPORT_FULL_RUN
else:
validate_obj.run_type = choices.ReportRunTypeChoices.REPORT_FILTERED_RUN
validate_obj.validated_save()
validation_count += 1

for device in Device.objects.filter(software_version__isnull=False):
# Validate devices with software version
for device in versioned_devices:
device_software = DeviceSoftware(device)
validate_obj, _ = DeviceSoftwareValidationResult.objects.get_or_create(device=device)
validate_obj.is_validated = device_software.validate_software()
validate_obj.valid_software.set(ValidatedSoftwareLCM.objects.get_for_object(device))
validate_obj.software = device.software_version
validate_obj.last_run = job_run_time
validate_obj.run_type = choices.ReportRunTypeChoices.REPORT_FULL_RUN
if all_tenants and all_platforms:
validate_obj.run_type = choices.ReportRunTypeChoices.REPORT_FULL_RUN
else:
validate_obj.run_type = choices.ReportRunTypeChoices.REPORT_FILTERED_RUN
validate_obj.validated_save()
validation_count += 1

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Generated by Django 4.2.15 on 2024-12-13 15:10

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("nautobot_device_lifecycle_mgmt", "0022_alter_softwareimagelcm_inventory_items_and_more"),
]

operations = [
migrations.AddField(
model_name="cvelcm",
name="affected_softwares_tmp",
field=models.JSONField(default=list),
),
migrations.AddField(
model_name="devicesoftwarevalidationresult",
name="software_tmp",
field=models.UUIDField(blank=True, null=True),
),
migrations.AddField(
model_name="inventoryitemsoftwarevalidationresult",
name="software_tmp",
field=models.UUIDField(blank=True, null=True),
),
migrations.AddField(
model_name="validatedsoftwarelcm",
name="software_tmp",
field=models.UUIDField(blank=True, null=True),
),
migrations.AddField(
model_name="vulnerabilitylcm",
name="software_tmp",
field=models.UUIDField(blank=True, null=True),
),
]
Loading