Skip to content
Merged
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
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ The Netbox Lifecycle plugin is a Hardware EOS/EOL, License and Support Contract

## Features

* Tracking EOL/EOS data
* Tracking License
* Tracking Support Contracts
* Tracking EOL/EOS data for DeviceTypes and ModuleTypes
* Tracking Licenses (assignable to Devices and Virtual Machines)
* Tracking Support Contracts (assignable to Devices, Modules, and Virtual Machines)

# Requirements

Expand Down Expand Up @@ -49,15 +49,15 @@ PLUGINS_CONFIG = {
| Setting | Default | Description |
|---------|---------|-------------|
| `lifecycle_card_position` | `right_page` | Position of the Hardware Lifecycle Info card on Device, Module, DeviceType, and ModuleType detail pages. Options: `left_page`, `right_page`, `full_width_page`. |
| `contract_card_position` | `right_page` | Position of the Support Contracts card on Device detail pages. Options: `left_page`, `right_page`, `full_width_page`. |
| `contract_card_position` | `right_page` | Position of the Support Contracts card on Device and VirtualMachine detail pages. Options: `left_page`, `right_page`, `full_width_page`. |

### Hardware Lifecycle Info Card

Displays EOL/EOS information for the hardware type on Device, Module, DeviceType, and ModuleType detail pages.

### Support Contracts Card

Displays all contract assignments on Device detail pages, grouped by status:
Displays all contract assignments on Device and VirtualMachine detail pages, grouped by status:

- **Active**: Contracts currently in effect
- **Future**: Contracts with a start date in the future
Expand Down
6 changes: 6 additions & 0 deletions netbox_lifecycle/api/_serializers/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from dcim.api.serializers_.devices import DeviceSerializer, ModuleSerializer
from dcim.api.serializers_.manufacturers import ManufacturerSerializer
from netbox.api.serializers import NetBoxModelSerializer
from virtualization.api.serializers_.virtualmachines import VirtualMachineSerializer
from netbox_lifecycle.api._serializers.license import LicenseAssignmentSerializer
from netbox_lifecycle.api._serializers.vendor import VendorSerializer
from netbox_lifecycle.models import (
Expand Down Expand Up @@ -88,6 +89,9 @@ class SupportContractAssignmentSerializer(NetBoxModelSerializer):
sku = SupportSKUSerializer(nested=True, required=False, allow_null=True)
device = DeviceSerializer(nested=True, required=False, allow_null=True)
module = ModuleSerializer(nested=True, required=False, allow_null=True)
virtual_machine = VirtualMachineSerializer(
nested=True, required=False, allow_null=True
)
license = LicenseAssignmentSerializer(nested=True, required=False, allow_null=True)

class Meta:
Expand All @@ -100,6 +104,7 @@ class Meta:
'sku',
'device',
'module',
'virtual_machine',
'license',
'end',
'description',
Expand All @@ -116,5 +121,6 @@ class Meta:
'sku',
'device',
'module',
'virtual_machine',
'license',
)
7 changes: 7 additions & 0 deletions netbox_lifecycle/api/_serializers/license.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from dcim.api.serializers_.devices import DeviceSerializer
from dcim.api.serializers_.manufacturers import ManufacturerSerializer
from netbox.api.serializers import NetBoxModelSerializer
from virtualization.api.serializers_.virtualmachines import VirtualMachineSerializer
from netbox_lifecycle.api._serializers.vendor import VendorSerializer
from netbox_lifecycle.models import License, LicenseAssignment

Expand Down Expand Up @@ -46,6 +47,9 @@ class LicenseAssignmentSerializer(NetBoxModelSerializer):
license = LicenseSerializer(nested=True)
vendor = VendorSerializer(nested=True)
device = DeviceSerializer(nested=True, required=False, allow_null=True)
virtual_machine = VirtualMachineSerializer(
nested=True, required=False, allow_null=True
)

class Meta:
model = LicenseAssignment
Expand All @@ -56,6 +60,8 @@ class Meta:
'vendor',
'license',
'device',
'virtual_machine',
'quantity',
'description',
'comments',
'tags',
Expand All @@ -68,4 +74,5 @@ class Meta:
'vendor',
'license',
'device',
'virtual_machine',
)
14 changes: 14 additions & 0 deletions netbox_lifecycle/filtersets/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from dcim.models import Manufacturer, Device, Module
from netbox.filtersets import NetBoxModelFilterSet
from virtualization.models import VirtualMachine
from netbox_lifecycle.models import (
Vendor,
SupportContract,
Expand Down Expand Up @@ -149,6 +150,17 @@ class SupportContractAssignmentFilterSet(NetBoxModelFilterSet):
to_field_name='name',
label=_('License (SKU)'),
)
virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
field_name='virtual_machine',
queryset=VirtualMachine.objects.all(),
label=_('Virtual Machine (ID)'),
)
virtual_machine = django_filters.ModelMultipleChoiceFilter(
field_name='virtual_machine__name',
queryset=VirtualMachine.objects.all(),
to_field_name='name',
label=_('Virtual Machine (name)'),
)
device_status = django_filters.ModelMultipleChoiceFilter(
field_name='device__status',
queryset=Device.objects.all(),
Expand All @@ -173,7 +185,9 @@ def search(self, queryset, name, value):
| Q(device__name__icontains=value)
| Q(module__serial__icontains=value)
| Q(module__module_type__model__icontains=value)
| Q(virtual_machine__name__icontains=value)
| Q(license__device__name__icontains=value)
| Q(license__virtual_machine__name__icontains=value)
| Q(license__license__name__icontains=value)
)
return queryset.filter(qs_filter).distinct()
13 changes: 13 additions & 0 deletions netbox_lifecycle/filtersets/license.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from dcim.models import Manufacturer, Device
from netbox.filtersets import NetBoxModelFilterSet
from virtualization.models import VirtualMachine
from netbox_lifecycle.models import Vendor, License, LicenseAssignment

__all__ = (
Expand Down Expand Up @@ -74,6 +75,17 @@ class LicenseAssignmentFilterSet(NetBoxModelFilterSet):
to_field_name='name',
label=_('Device'),
)
virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
field_name='virtual_machine',
queryset=VirtualMachine.objects.all(),
label=_('Virtual Machine'),
)
virtual_machine = django_filters.ModelMultipleChoiceFilter(
field_name='virtual_machine__name',
queryset=VirtualMachine.objects.all(),
to_field_name='name',
label=_('Virtual Machine'),
)

class Meta:
model = LicenseAssignment
Expand All @@ -90,5 +102,6 @@ def search(self, queryset, name, value):
| Q(license__name__icontains=value)
| Q(vendor__name__icontains=value)
| Q(device__name__icontains=value)
| Q(virtual_machine__name__icontains=value)
)
return queryset.filter(qs_filter).distinct()
22 changes: 21 additions & 1 deletion netbox_lifecycle/forms/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from dcim.choices import DeviceStatusChoices
from dcim.models import Device, Manufacturer, Module
from netbox.forms import NetBoxModelFilterSetForm
from virtualization.models import VirtualMachine
from netbox_lifecycle.models import (
HardwareLifecycle,
SupportContract,
Expand Down Expand Up @@ -138,6 +139,7 @@ class SupportContractAssignmentFilterForm(NetBoxModelFilterSetForm):
'contract_id',
'device_id',
'module_id',
'virtual_machine_id',
'license_id',
'device_status',
name='Assignment',
Expand Down Expand Up @@ -166,6 +168,12 @@ class SupportContractAssignmentFilterForm(NetBoxModelFilterSetForm):
required=False,
label=_('Module'),
)
virtual_machine_id = DynamicModelMultipleChoiceField(
queryset=VirtualMachine.objects.all(),
required=False,
selector=True,
label=_('Virtual Machines'),
)
device_status = forms.MultipleChoiceField(
label=_('Status'), choices=DeviceStatusChoices, required=False
)
Expand All @@ -176,7 +184,13 @@ class LicenseAssignmentFilterForm(NetBoxModelFilterSetForm):
model = LicenseAssignment
fieldsets = (
FieldSet('q', 'filter_id', 'tag'),
FieldSet('license_id', 'vendor_id', 'device_id', name='Assignment'),
FieldSet(
'license_id',
'vendor_id',
'device_id',
'virtual_machine_id',
name='Assignment',
),
)
license_id = DynamicModelMultipleChoiceField(
queryset=License.objects.all(),
Expand All @@ -196,4 +210,10 @@ class LicenseAssignmentFilterForm(NetBoxModelFilterSetForm):
selector=True,
label=_('Devices'),
)
virtual_machine_id = DynamicModelMultipleChoiceField(
queryset=VirtualMachine.objects.all(),
required=False,
selector=True,
label=_('Virtual Machines'),
)
tag = TagFilterField(model)
Loading