diff --git a/docs/model/netbox_sys_vm_assigned_virtual_machine_type.md b/docs/model/netbox_sys_vm_assigned_virtual_machine_type.md new file mode 100644 index 0000000000000000000000000000000000000000..791b6dacb5cf970b9274aa60b8726088bb92190e --- /dev/null +++ b/docs/model/netbox_sys_vm_assigned_virtual_machine_type.md @@ -0,0 +1,11 @@ +## netbox_sys_virtual_machine_type + +**Mapping Redirect definition class** + +| FIELD | TYPE | DESCRIPTION | +|------------------------------- |-----------------------------------|---------------------------------------------------------------------------| +| id | Big (8 byte) integer | Unique ID | +| assigned_object_type_id | Big (8 byte) integer | cluster type type ID | +| assigned_object_id | Big (8 byte) integer | cluster type unique ID | +| virtual_machine_type_assignment_id | String | Virtual Machine type ID (refers to the table virtual_machine_tye) | +| virtual_machine_type_assignment_desc | String | Virtual Machine type assignment description | \ No newline at end of file diff --git a/netbox_sys_plugin/api/serializers.py b/netbox_sys_plugin/api/serializers.py index 4e7d71252af3e90c88eafaed2385eccbbb202f86..d1809016266178755b7da6318ff158e10fb77af0 100644 --- a/netbox_sys_plugin/api/serializers.py +++ b/netbox_sys_plugin/api/serializers.py @@ -1,8 +1,9 @@ from rest_framework import serializers -from virtualization.models import VirtualMachine, Cluster -from .. models import VirtualMachineMaintenance, ProviderCredentials +from virtualization.models import VirtualMachine, Cluster, ClusterType +from .. models import VirtualMachineMaintenance, ProviderCredentials,VmAssignedVirtualMachineType, VirtualMachineType from django.contrib.contenttypes.models import ContentType +#Netbox Data Serializer class VirtualMachineSerializer(serializers.ModelSerializer): class Meta: model = VirtualMachine @@ -13,6 +14,13 @@ class ClusterSerializer(serializers.ModelSerializer): model = Cluster fields = ['id', 'name'] +class ClusterTypeSerializer(serializers.ModelSerializer): + class Meta: + model = ClusterType + fields = ['id', 'name'] + + +#Plugin Data Serializer class VirtualMachineMaintenanceSerializer(serializers.ModelSerializer): id = serializers.IntegerField(read_only=True) virtual_machine = VirtualMachineSerializer(source='assigned_object', read_only=True) @@ -33,4 +41,26 @@ class ProviderCredentialsSerializer(serializers.ModelSerializer): class Meta: model = ProviderCredentials #fields = ['id','maintenance_window','assigned_object_type','assigned_object_id','assigned_object_type','virtual_machine'] - fields = '__all__' \ No newline at end of file + fields = '__all__' + +class VmAssignedVirtualMachineTypeSerializer(serializers.ModelSerializer): + id = serializers.IntegerField(read_only=True) + virtual_machine = VirtualMachineSerializer(source='assigned_object', read_only=True) + assigned_object_id = serializers.IntegerField(write_only=True) + assigned_object_type = serializers.CharField(write_only=True) + + class Meta: + model = VmAssignedVirtualMachineType + #fields = ['id','maintenance_window','assigned_object_type','assigned_object_id','assigned_object_type','virtual_machine'] + fields = '__all__' + +class VirtualMachineTypeSerializer(serializers.ModelSerializer): + id = serializers.IntegerField(read_only=True) + cluster_type = ClusterTypeSerializer(source='assigned_object', read_only=True) + assigned_object_id = serializers.IntegerField(write_only=True) + assigned_object_type = serializers.CharField(write_only=True) + + class Meta: + model = VirtualMachineType + #fields = ['id','maintenance_window','assigned_object_type','assigned_object_id','assigned_object_type','virtual_machine'] + fields = '__all__' diff --git a/netbox_sys_plugin/api/urls.py b/netbox_sys_plugin/api/urls.py index 6f3fb348f4a9948d63374a4e95b2368f9c804c42..95a045abaaba90a578a4e890f1bb85402a669b0f 100644 --- a/netbox_sys_plugin/api/urls.py +++ b/netbox_sys_plugin/api/urls.py @@ -1,9 +1,11 @@ from rest_framework.routers import DefaultRouter -from .views import VirtualMachineMaintenanceViewSet, ProviderCredentialsViewSet +from .views import VirtualMachineMaintenanceViewSet, ProviderCredentialsViewSet, VmAssignedVirtualMachineTypeViewSet, VirtualMachineTypeViewSet router = DefaultRouter() router.register(r'MaintenanceWindow', VirtualMachineMaintenanceViewSet) router.register(r'ProviderCredentials', ProviderCredentialsViewSet) +router.register(r'AssignedVmType', VmAssignedVirtualMachineTypeViewSet) +router.register(r'VmType', VirtualMachineTypeViewSet) app_name = "netbox_sys_plugin" diff --git a/netbox_sys_plugin/api/views.py b/netbox_sys_plugin/api/views.py index b3753336d640c500ab179f011441ee3f6ee6fd5a..96667303820824a48752b3f937d3b2ad629c4fc8 100644 --- a/netbox_sys_plugin/api/views.py +++ b/netbox_sys_plugin/api/views.py @@ -1,8 +1,8 @@ from rest_framework import viewsets, status from rest_framework.decorators import action from rest_framework.response import Response -from .. models import VirtualMachineMaintenance, ProviderCredentials -from . serializers import VirtualMachineMaintenanceSerializer, ProviderCredentialsSerializer +from .. models import VirtualMachineMaintenance, ProviderCredentials, VmAssignedVirtualMachineType, VirtualMachineType +from . serializers import VirtualMachineMaintenanceSerializer, ProviderCredentialsSerializer, VmAssignedVirtualMachineTypeSerializer, VirtualMachineTypeSerializer class VirtualMachineMaintenanceViewSet(viewsets.ModelViewSet): queryset = VirtualMachineMaintenance.objects.all() @@ -13,4 +13,15 @@ class VirtualMachineMaintenanceViewSet(viewsets.ModelViewSet): class ProviderCredentialsViewSet(viewsets.ModelViewSet): queryset = ProviderCredentials.objects.all() serializer_class = ProviderCredentialsSerializer - http_method_names = ["get", "post", "patch", "delete", "options"] \ No newline at end of file + http_method_names = ["get", "post", "patch", "delete", "options"] + + +class VmAssignedVirtualMachineTypeViewSet(viewsets.ModelViewSet): + queryset = VmAssignedVirtualMachineType.objects.all() + serializer_class = VmAssignedVirtualMachineTypeSerializer + http_method_names = ["get", "post", "patch", "delete", "options"] + +class VirtualMachineTypeViewSet(viewsets.ModelViewSet): + queryset = VirtualMachineType.objects.all() + serializer_class = VirtualMachineTypeSerializer + http_method_names = ["get", "post", "patch", "delete", "options"] diff --git a/netbox_sys_plugin/filtersets.py b/netbox_sys_plugin/filtersets.py index 75a77e077fc1b3c897ee22dd79dbd8df3d567bbf..3c031b65bbb3c12746fd097f044a2a0f0f0ba351 100644 --- a/netbox_sys_plugin/filtersets.py +++ b/netbox_sys_plugin/filtersets.py @@ -2,9 +2,9 @@ import django_filters from netbox.filtersets import NetBoxModelFilterSet -from virtualization.models import VirtualMachine, Cluster +from virtualization.models import VirtualMachine, Cluster, ClusterType from django.db.models import Q -from .models import VirtualMachineMaintenance, ProviderCredentials +from .models import VirtualMachineMaintenance, ProviderCredentials, VmAssignedVirtualMachineType, VirtualMachineType class VmMaintenanceFilterSet(NetBoxModelFilterSet): @@ -28,6 +28,51 @@ class VmMaintenanceFilterSet(NetBoxModelFilterSet): if not value.strip(): return queryset return queryset.filter(Q(maintenance_window__icontains=value)) + +class VmAssignedVmTypeFilterSet(NetBoxModelFilterSet): + """VirtualMachineAssignType filterset definition class""" + + virtualmachine = django_filters.ModelMultipleChoiceFilter( + field_name="VirtualMachine__name", + queryset=VirtualMachine.objects.all(), + to_field_name="name", + label="Virtual Machine (name)", + ) + + class Meta: + """Meta class""" + model = VmAssignedVirtualMachineType + fields = ('virtual_machine_type','virtual_machine_type_assignment_desc', 'virtualmachine') + + # pylint: disable=W0613 + def search(self, queryset, name, value): + """override""" + if not value.strip(): + return queryset + return queryset.filter(Q(virtual_machine_type__icontains=value)|Q(virtual_machine_type_desc__icontains=value)) + +class VmTypeFilterSet(NetBoxModelFilterSet): + """VirtualMachineType filterset definition class""" + + cluster_type = django_filters.ModelMultipleChoiceFilter( + field_name="ClusterType__name", + queryset=ClusterType.objects.all(), + to_field_name="name", + label="Cluster Type (name)", + ) + + class Meta: + """Meta class""" + model = VirtualMachineType + fields = ('virtual_machine_type_name','virtual_machine_type_desc', 'cluster_type') + + # pylint: disable=W0613 + def search(self, queryset, name, value): + """override""" + if not value.strip(): + return queryset + return queryset.filter(Q(virtual_machine_type_name__icontains=value)|Q(virtual_machine_type_desc__icontains=value)) + class ProviderCredentialsFilterSet(NetBoxModelFilterSet): """ProviderCredentials filterset definition class""" diff --git a/netbox_sys_plugin/forms/__init__.py b/netbox_sys_plugin/forms/__init__.py index 0f3ba6e3f9a49b62cca63d22474239cfb7bb79a3..c3fb247bad95a70159b9ba089d4a04ad53783736 100644 --- a/netbox_sys_plugin/forms/__init__.py +++ b/netbox_sys_plugin/forms/__init__.py @@ -1,4 +1,4 @@ """Forms definitions""" -from .maintenance import * -from .provider import * \ No newline at end of file +from .provider import * +from .machine import * \ No newline at end of file diff --git a/netbox_sys_plugin/forms/machine.py b/netbox_sys_plugin/forms/machine.py new file mode 100644 index 0000000000000000000000000000000000000000..7dbb43771f9cab5b6596fe70802ba52896c2de75 --- /dev/null +++ b/netbox_sys_plugin/forms/machine.py @@ -0,0 +1,213 @@ +"""Forms definitions""" + +from virtualization.models import VirtualMachine, ClusterType +from django.contrib.contenttypes.models import ContentType +from django.utils.translation import gettext_lazy as _ +from django.core.exceptions import ValidationError +from django import forms +from django.utils.safestring import mark_safe +from netbox.forms import ( + NetBoxModelForm, + NetBoxModelFilterSetForm, +) +from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField +from ..models import VmAssignedVirtualMachineType, VirtualMachineMaintenance, VirtualMachineType + +class VmAssignedVmTypeForm(NetBoxModelForm): + """ + GUI form to add or edit a Virtual Machine Type. + """ + + virtual_machine = DynamicModelChoiceField( + queryset=VirtualMachine.objects.all(), required=True, label="Virtual Machine" + ) + + + def __init__(self, *args, **kwargs): + # Initialize helper selectors + instance = kwargs.get("instance") + initial = kwargs.get("initial", {}).copy() + if instance: + if isinstance(instance.assigned_object, VirtualMachine): + initial["virtual_machine"] = instance.assigned_object + kwargs["initial"] = initial + super().__init__(*args, **kwargs) + + if instance: + current_vm_id = instance.assigned_object.id if instance.assigned_object else None + else: + current_vm_id = None + + assigned_vms = VmAssignedVirtualMachineType.objects.filter( + assigned_object_type=ContentType.objects.get_for_model(VirtualMachine) + ).exclude(assigned_object_id=current_vm_id).values_list('assigned_object_id', flat=True) + self.fields['virtual_machine'].queryset = VirtualMachine.objects.exclude(id__in=assigned_vms) + + class Meta: + """Meta class""" + model = VmAssignedVirtualMachineType + fields = ('virtual_machine','virtual_machine_type', 'virtual_machine_type_assignment_desc','tags') + + def clean(self): + """ + Validates form inputs before submitting: + """ + super().clean() + + + vm = self.cleaned_data.get("virtual_machine") + + #Check if Virtual Machine is assigned corretly + if (not vm): + raise ValidationError( + {"__all__": "Can't assign more than one Type to the same Virtual Machine"}, + ) + + if self.errors.get("virtual_machine"): + return + + def save(self, *args, **kwargs): + # Set assigned object + self.instance.assigned_object = ( + self.cleaned_data.get("virtual_machine") + ) + return super().save(*args, **kwargs) + +class VmAssignedVmTypeFilterForm(NetBoxModelFilterSetForm): + """Virtual Machine Type filter form definition class""" + + model = VmAssignedVirtualMachineType + +class VmTypeForm(NetBoxModelForm): + """ + GUI form to add or edit a Virtual Machine Type. + """ + + cluster_type = DynamicModelChoiceField( + queryset=ClusterType.objects.all(), required=True, label="Cluster Type" + ) + virtual_machine_type_name = forms.CharField( + max_length=200, min_length=1, required=True, label="Name" + ) + virtual_machine_type_desc = forms.CharField( + max_length=50, min_length=1, required=False, label="Description" + ) + + + def __init__(self, *args, **kwargs): + # Initialize helper selectors + instance = kwargs.get("instance") + initial = kwargs.get("initial", {}).copy() + if instance: + if isinstance(instance.assigned_object, ClusterType): + initial["cluster_type"] = instance.assigned_object + kwargs["initial"] = initial + super().__init__(*args, **kwargs) + + + class Meta: + """Meta class""" + model = VirtualMachineType + fields = ('cluster_type','virtual_machine_type_name', 'virtual_machine_type_desc','tags') + + def clean(self): + """ + Validates form inputs before submitting: + """ + super().clean() + + virtual_machine_type_name = self.cleaned_data.get("virtual_machine_type_name") + cluster_type = self.cleaned_data.get("cluster_type") + cluster_type_ct = ContentType.objects.get_for_model(ClusterType) + + if VirtualMachineType.objects.filter( + virtual_machine_type_name =virtual_machine_type_name, + assigned_object_type=cluster_type_ct, + assigned_object_id=cluster_type.id + ).exclude(pk=self.instance.pk).exists(): + raise ValidationError( + {"__all__":"A Type with this name and cluster type already exists"} + ) + + + def save(self, *args, **kwargs): + # Set assigned object + self.instance.assigned_object = self.cleaned_data.get("cluster_type") + return super().save(*args, **kwargs) + +class VmTypeFilterForm(NetBoxModelFilterSetForm): + """Virtual Machine Type filter form definition class""" + + model = VirtualMachineType + +class VmMaitenanceForm(NetBoxModelForm): + """ + GUI form to add or edit a VM Maitenance. + """ + virtual_machine = DynamicModelChoiceField( + queryset=VirtualMachine.objects.none(), required=True, label="Virtual Machine" + ) + maintenance_window = forms.CharField( + max_length=7, min_length=1, required=True, label="Maintenance Window", + help_text=mark_safe( + "<b>*Note:</b> Day of the week and a time of the day, 0 = Sunday , 1 = monday. Format 0-00:00", + ), + ) + + def __init__(self, *args, **kwargs): + # Initialize helper selectors + instance = kwargs.get("instance") + initial = kwargs.get("initial", {}).copy() + if instance: + if isinstance(instance.assigned_object, VirtualMachine): + initial["virtual_machine"] = instance.assigned_object + kwargs["initial"] = initial + super().__init__(*args, **kwargs) + + if instance: + current_vm_id = instance.assigned_object.id if instance.assigned_object else None + else: + current_vm_id = None + + assigned_vms = VirtualMachineMaintenance.objects.filter( + assigned_object_type=ContentType.objects.get_for_model(VirtualMachine) + ).exclude(assigned_object_id=current_vm_id).values_list('assigned_object_id', flat=True) + self.fields['virtual_machine'].queryset = VirtualMachine.objects.exclude(id__in=assigned_vms) + + class Meta: + """Meta class""" + model = VirtualMachineMaintenance + fields = ( 'virtual_machine','maintenance_window','tags') + + + def clean(self): + """ + Validates form inputs before submitting: + """ + super().clean() + + + vm = self.cleaned_data.get("virtual_machine") + + #Check if Virtual Machine is assigned corretly + if (not vm): + raise ValidationError( + {"__all__": "Can't assign more than one Maintenance Window to the same Virtual Machine"}, + ) + + if self.errors.get("virtual_machine"): + return + + + + def save(self, *args, **kwargs): + # Set assigned object + self.instance.assigned_object = ( + self.cleaned_data.get("virtual_machine") + ) + return super().save(*args, **kwargs) + +class VmMaintenanceFilterForm(NetBoxModelFilterSetForm): + """MacAddress filter form definition class""" + + model = VirtualMachineMaintenance \ No newline at end of file diff --git a/netbox_sys_plugin/forms/maintenance.py b/netbox_sys_plugin/forms/maintenance.py deleted file mode 100644 index 46618c6ba442ab8ea7e2eb7b996e1b8b480b328a..0000000000000000000000000000000000000000 --- a/netbox_sys_plugin/forms/maintenance.py +++ /dev/null @@ -1,99 +0,0 @@ -"""Forms definitions""" - -from virtualization.models import VirtualMachine -from django.contrib.contenttypes.models import ContentType -from django.utils.translation import gettext_lazy as _ -from django.core.exceptions import ValidationError -from django import forms -from django.utils.safestring import mark_safe -from netbox.forms import ( - NetBoxModelForm, - NetBoxModelFilterSetForm, -) -from utilities.forms.fields import DynamicModelChoiceField -from ..models import VirtualMachineMaintenance - -class VmMaitenanceForm(NetBoxModelForm): - """ - GUI form to add or edit a VM Maitenance. - """ - virtual_machine = DynamicModelChoiceField( - queryset=VirtualMachine.objects.none(), required=True, label="Virtual Machine" - ) - maintenance_window = forms.CharField( - max_length=7, min_length=1, required=True, label="Maintenance Window", - help_text=mark_safe( - "<b>*Note:</b> Day of the week and a time of the day, 0 = Sunday , 1 = monday. Format 0-00:00", - ), - ) - - def __init__(self, *args, **kwargs): - # Initialize helper selectors - instance = kwargs.get("instance") - initial = kwargs.get("initial", {}).copy() - if instance: - if isinstance(instance.assigned_object, VirtualMachine): - initial["virtual_machine"] = instance.assigned_object - kwargs["initial"] = initial - super().__init__(*args, **kwargs) - - if instance: - current_vm_id = instance.assigned_object.id if instance.assigned_object else None - else: - current_vm_id = None - - assigned_vms = VirtualMachineMaintenance.objects.filter( - assigned_object_type=ContentType.objects.get_for_model(VirtualMachine) - ).exclude(assigned_object_id=current_vm_id).values_list('assigned_object_id', flat=True) - self.fields['virtual_machine'].queryset = VirtualMachine.objects.exclude(id__in=assigned_vms) - - class Meta: - """Meta class""" - model = VirtualMachineMaintenance - fields = ( 'virtual_machine','maintenance_window','tags') - - def clean_virtual_machine(self): - - virtual_machine = self.cleaned_data.get("virtual_machine") - - virtual_machine_ct = ContentType.objects.get_for_model(VirtualMachine) - - if VirtualMachineMaintenance.objects.filter( - assigned_object_type=virtual_machine_ct, - assigned_object_id=virtual_machine.id - ).exclude(pk=self.instance.pk).exists(): - raise ValidationError() - return virtual_machine - - - - def clean(self): - """ - Validates form inputs before submitting: - """ - super().clean() - - if self.errors.get("maintenance_window"): - return - - virtual_machine = self.cleaned_data.get("virtual_machine") - - #Check if VM is assigned corretly - if (not virtual_machine): - raise ValidationError( - {"__all__": "A Virtual Machine needs to be associated with the maintenance window"}, - ) - - - - def save(self, *args, **kwargs): - # Set assigned object - self.instance.assigned_object = ( - self.cleaned_data.get("virtual_machine") - ) - return super().save(*args, **kwargs) - -class VmMaintenanceFilterForm(NetBoxModelFilterSetForm): - """MacAddress filter form definition class""" - - model = VirtualMachineMaintenance \ No newline at end of file diff --git a/netbox_sys_plugin/forms/provider.py b/netbox_sys_plugin/forms/provider.py index 1909d38f09c73b4d7ef2584810b144cfa9c7ad23..ffd747cc137659a4aa8793087c261c0c38a0c2ce 100644 --- a/netbox_sys_plugin/forms/provider.py +++ b/netbox_sys_plugin/forms/provider.py @@ -55,18 +55,6 @@ class ProviderCredentialsForm(NetBoxModelForm): model = ProviderCredentials fields = ('cluster','provider_url', 'provider_username', 'provider_password_vault_url','tags') - def clean_cluster(self): - - cluster = self.cleaned_data.get("cluster") - - cluster_ct = ContentType.objects.get_for_model(Cluster) - - if ProviderCredentials.objects.filter( - assigned_object_type=cluster_ct, - assigned_object_id=cluster.id - ).exclude(pk=self.instance.pk).exists(): - raise ValidationError() - return cluster def clean(self): """ @@ -74,16 +62,18 @@ class ProviderCredentialsForm(NetBoxModelForm): """ super().clean() - if self.errors.get(f"provider_url"): - return + cluster = self.cleaned_data.get("cluster") #Check if cluster is assigned corretly if (not cluster): raise ValidationError( - {"__all__": "A Virtual Machine needs to be associated with the maintenance window"}, + {"__all__": "Can't assign more than one Credential to the same Cluster"}, ) + + if self.errors.get(f"provider_url"): + return def save(self, *args, **kwargs): # Set assigned object diff --git a/netbox_sys_plugin/migrations/0003_virtualmachinetype_vmassignedvirtualmachinetype.py b/netbox_sys_plugin/migrations/0003_virtualmachinetype_vmassignedvirtualmachinetype.py new file mode 100644 index 0000000000000000000000000000000000000000..cad573fcee3f7aff474b4b679f9bc66d4f04f67d --- /dev/null +++ b/netbox_sys_plugin/migrations/0003_virtualmachinetype_vmassignedvirtualmachinetype.py @@ -0,0 +1,58 @@ +# Generated by Django 4.2.16 on 2024-11-21 17:06 + +from django.db import migrations, models +import django.db.models.deletion +import taggit.managers +import utilities.json + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('extras', '0098_webhook_custom_field_data_webhook_tags'), + ('netbox_sys_plugin', '0002_alter_virtualmachinemaintenance_maintenance_window_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='VirtualMachineType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), + ('created', models.DateTimeField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ('virtual_machine_type_name', models.CharField(default=None, max_length=50)), + ('virtual_machine_type_desc', models.CharField(blank=True, default=None, max_length=100, null=True)), + ('assigned_object_id', models.PositiveBigIntegerField(blank=True, null=True)), + ('assigned_object_type', models.ForeignKey(blank=True, limit_choices_to=models.Q(models.Q(('app_label', 'virtualization'), ('model', 'ClusterType'))), null=True, on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype')), + ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), + ], + options={ + 'verbose_name': 'Virtual Machine Type', + 'verbose_name_plural': 'Virtual Machine Types', + 'ordering': ['assigned_object_id'], + 'unique_together': {('assigned_object_id', 'virtual_machine_type_name')}, + }, + ), + migrations.CreateModel( + name='VmAssignedVirtualMachineType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), + ('created', models.DateTimeField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ('virtual_machine_type_assignment_desc', models.CharField(blank=True, default=None, max_length=100, null=True)), + ('assigned_object_id', models.PositiveBigIntegerField(blank=True, null=True)), + ('assigned_object_type', models.ForeignKey(blank=True, limit_choices_to=models.Q(models.Q(('app_label', 'virtualization'), ('model', 'VirtualMachine'))), null=True, on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype')), + ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), + ('virtual_machine_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='assigned_vm_type', to='netbox_sys_plugin.virtualmachinetype')), + ], + options={ + 'verbose_name': 'Assigned Machine Type', + 'verbose_name_plural': 'Assigned Machine Types', + 'ordering': ['assigned_object_id'], + 'unique_together': {('assigned_object_id',)}, + }, + ), + ] diff --git a/netbox_sys_plugin/models/__init__.py b/netbox_sys_plugin/models/__init__.py index cef638b62a297a72c847e8871ce914dc13626cd9..bf52380ddb0d34078cc29b9010dcecc79e6caf9b 100644 --- a/netbox_sys_plugin/models/__init__.py +++ b/netbox_sys_plugin/models/__init__.py @@ -1,4 +1,4 @@ """Models definitions""" -from .maintenance import VirtualMachineMaintenance -from .provider import ProviderCredentials \ No newline at end of file +from .provider import * +from .machine import * \ No newline at end of file diff --git a/netbox_sys_plugin/models/machine.py b/netbox_sys_plugin/models/machine.py new file mode 100644 index 0000000000000000000000000000000000000000..690faa705e44557debdb42ce19a07cef7d6fb304 --- /dev/null +++ b/netbox_sys_plugin/models/machine.py @@ -0,0 +1,167 @@ +"""Models definitions""" + +from django.core.validators import ( + RegexValidator, +) +from django.urls import reverse +from django.core.validators import ( + URLValidator, +) # pylint: disable=import-error +from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation +from django.contrib.contenttypes.models import ContentType +from django.db import models +from virtualization.models import VirtualMachine, ClusterType +from netbox.models import NetBoxModel + +VM_ASSIGNMENT_MODELS = models.Q(models.Q(app_label="virtualization", model="VirtualMachine")) +CLUSTERTYPE_ASSIGNMENT_MODELS = models.Q(models.Q(app_label="virtualization", model="ClusterType")) + +#VM Type +class VirtualMachineType(NetBoxModel): + """Cluster ProviderInfo definition class""" + + virtual_machine_type_name = models.CharField( + default=None, blank=False, null=False, + max_length=50, + ) + + virtual_machine_type_desc = models.CharField( + default=None, blank=True, null=True, + max_length=100) + + assigned_object_type = models.ForeignKey( + to=ContentType, + limit_choices_to=CLUSTERTYPE_ASSIGNMENT_MODELS, + on_delete=models.PROTECT, + null=True, + blank=True, + ) + assigned_object_id = models.PositiveBigIntegerField(null=True, blank=True) + assigned_object = GenericForeignKey( + ct_field="assigned_object_type", + fk_field="assigned_object_id", + ) + + class Meta: + """Meta class""" + unique_together = ["assigned_object_id","virtual_machine_type_name"] + ordering = ["assigned_object_id"] + verbose_name = "Virtual Machine Type" + verbose_name_plural = "Virtual Machine Types" + + + def __str__(self): + return self.virtual_machine_type_name + + def get_absolute_url(self): + """override""" + return reverse("plugins:netbox_sys_plugin:virtualmachinetype", args=[self.pk]) + +GenericRelation( + to=VirtualMachineType, + content_type_field="assigned_object_type", + object_id_field="assigned_object_id", + related_query_name="ClusterType", +).contribute_to_class(ClusterType, "VirtualMachineType") + +#VM Assigned Type +class VmAssignedVirtualMachineType(NetBoxModel): + """Virtual Machine Type Info definition class""" + + virtual_machine_type = models.ForeignKey( + to="VirtualMachineType", + on_delete=models.PROTECT, + null=False, + blank=False, + related_name="assigned_vm_type" + ) + + virtual_machine_type_assignment_desc = models.CharField( + default=None, blank=True, null=True, + max_length=100) + + assigned_object_type = models.ForeignKey( + to=ContentType, + limit_choices_to=VM_ASSIGNMENT_MODELS, + on_delete=models.PROTECT, + null=True, + blank=True, + ) + assigned_object_id = models.PositiveBigIntegerField(null=True, blank=True) + assigned_object = GenericForeignKey( + ct_field="assigned_object_type", + fk_field="assigned_object_id", + ) + + class Meta: + """Meta class""" + unique_together = ["assigned_object_id"] + ordering = ["assigned_object_id"] + verbose_name = "Assigned Machine Type" + verbose_name_plural = "Assigned Machine Types" + + + def __str__(self): + return f"Virtual machine ID {self.assigned_object_id}" + + def get_absolute_url(self): + """override""" + return reverse("plugins:netbox_sys_plugin:vmassignedvirtualmachinetype", args=[self.pk]) + +GenericRelation( + to=VmAssignedVirtualMachineType, + content_type_field="assigned_object_type", + object_id_field="assigned_object_id", + related_query_name="VirtualMachine", +).contribute_to_class(VirtualMachine, "VmAssignedVirtualMachineType") + +#VM Maintenance +class VirtualMachineMaintenance(NetBoxModel): + """virtual machine maintenance definition class""" + + maintenance_window = models.CharField( + default=None, blank=True, null=True, + max_length=200, + validators=[ + RegexValidator( + regex='(^([0-6])-[0-1]?[0-9]|2[0-3]):[0-5][0-9]$', + message='Incorrect maintenance window format', + ), + ], + ) + + assigned_object_type = models.ForeignKey( + to=ContentType, + limit_choices_to=VM_ASSIGNMENT_MODELS, + on_delete=models.PROTECT, + null=True, + blank=True, + ) + assigned_object_id = models.PositiveBigIntegerField(null=True, blank=True) + assigned_object = GenericForeignKey( + ct_field="assigned_object_type", + fk_field="assigned_object_id", + ) + + class Meta: + """Meta class""" + unique_together = ["assigned_object_id"] + ordering = ["assigned_object_id"] + verbose_name = "Maintenance Information" + verbose_name_plural = "Maintenance Informations" + + + def __str__(self): + return f"For Virtual machine ID {self.assigned_object_id}" + + def get_absolute_url(self): + """override""" + return reverse("plugins:netbox_sys_plugin:virtualmachinemaintenance", args=[self.pk]) + +GenericRelation( + to=VirtualMachineMaintenance, + content_type_field="assigned_object_type", + object_id_field="assigned_object_id", + related_query_name="VirtualMachine", +).contribute_to_class(VirtualMachine, "VirtualMachineMaintenance") + diff --git a/netbox_sys_plugin/models/maintenance.py b/netbox_sys_plugin/models/maintenance.py deleted file mode 100644 index 53e1a81b02c7ca91c37503c2825a5f0b86e1fca5..0000000000000000000000000000000000000000 --- a/netbox_sys_plugin/models/maintenance.py +++ /dev/null @@ -1,66 +0,0 @@ -"""Models definitions""" - -from django.core.validators import ( - RegexValidator, -) -from django.urls import reverse -from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation -from django.contrib.contenttypes.models import ContentType -from django.db import models -from django.db.models import Q -from virtualization.models import VirtualMachine -from netbox.models import NetBoxModel - -MAINT_ASSIGNMENT_MODELS = models.Q(models.Q(app_label="virtualization", model="VirtualMachine")) - - - -class VirtualMachineMaintenance(NetBoxModel): - """virtual machine maintenance definition class""" - - maintenance_window = models.CharField( - default=None, blank=True, null=True, - max_length=200, - validators=[ - RegexValidator( - regex='(^([0-6])-[0-1]?[0-9]|2[0-3]):[0-5][0-9]$', - message='Incorrect maintenance window format', - ), - ], - ) - - assigned_object_type = models.ForeignKey( - to=ContentType, - limit_choices_to=MAINT_ASSIGNMENT_MODELS, - on_delete=models.PROTECT, - null=True, - blank=True, - ) - assigned_object_id = models.PositiveBigIntegerField(null=True, blank=True) - assigned_object = GenericForeignKey( - ct_field="assigned_object_type", - fk_field="assigned_object_id", - ) - - class Meta: - """Meta class""" - unique_together = ["assigned_object_id"] - ordering = ["assigned_object_id"] - verbose_name = "Maintenance Information" - verbose_name_plural = "Maintenance Informations" - - - def __str__(self): - return f"For Virtual machine ID {self.assigned_object_id}" - - def get_absolute_url(self): - """override""" - return reverse("plugins:netbox_sys_plugin:virtualmachinemaintenance", args=[self.pk]) - -GenericRelation( - to=VirtualMachineMaintenance, - content_type_field="assigned_object_type", - object_id_field="assigned_object_id", - related_query_name="VirtualMachine", -).contribute_to_class(VirtualMachine, "VirtualMachineMaintenance") - diff --git a/netbox_sys_plugin/navigation.py b/netbox_sys_plugin/navigation.py index 2a39a83fbd5c89ea6965ea9b76e2ad64e36c6b07..c9e7582f08bf7fb1d4d32730a88824ed052edb19 100644 --- a/netbox_sys_plugin/navigation.py +++ b/netbox_sys_plugin/navigation.py @@ -1,14 +1,19 @@ """Navigation Menu definitions""" +from django.utils.translation import gettext as _ from extras.plugins import PluginMenuButton, PluginMenuItem, PluginMenu +from netbox.registry import registry from utilities.choices import ButtonColorChoices +from . import * +#Buttons vm_maintenance_buttons = [ PluginMenuButton( link="plugins:netbox_sys_plugin:virtualmachinemaintenance_add", title="Add", icon_class="mdi mdi-plus-thick", color=ButtonColorChoices.GREEN, + permissions=["netbox_sys_plugin.add_maintenance"], ), ] @@ -18,30 +23,68 @@ cluster_provider_credentials_buttons = [ title="Add", icon_class="mdi mdi-plus-thick", color=ButtonColorChoices.GREEN, + permissions=["netbox_sys_plugin.add_providercredentials"], ), ] -vmMaintenanceItem = [ - PluginMenuItem( - link="plugins:netbox_sys_plugin:virtualmachinemaintenance_list", - link_text="Virtual Machine Maintenance", - buttons=vm_maintenance_buttons, +vm_assigned_machine_type_buttons = [ + PluginMenuButton( + link="plugins:netbox_sys_plugin:vmassignedvirtualmachinetype_add", + title="Add", + icon_class="mdi mdi-plus-thick", + color=ButtonColorChoices.GREEN, + permissions=["netbox_sys_plugin.add_vmassignedmachinetype"], + ), +] + +vm_machine_type_buttons = [ + PluginMenuButton( + link="plugins:netbox_sys_plugin:virtualmachinetype_add", + title="Add", + icon_class="mdi mdi-plus-thick", + color=ButtonColorChoices.GREEN, + permissions=["netbox_sys_plugin.add_vmmachinetype"], ), ] +#Items + clusterProviderCredentialsItem = [ PluginMenuItem( link="plugins:netbox_sys_plugin:providercredentials_list", - link_text="Provider Credentials", + link_text="Credentials", buttons=cluster_provider_credentials_buttons, ), ] +vmMachineItem = [ + PluginMenuItem( + link="plugins:netbox_sys_plugin:vmassignedvirtualmachinetype_list", + link_text="Type Assignment", + buttons=vm_assigned_machine_type_buttons, + ), + PluginMenuItem( + link="plugins:netbox_sys_plugin:virtualmachinemaintenance_list", + link_text="Maintenance", + buttons=vm_maintenance_buttons, + ), +] + +operItem =[ + PluginMenuItem( + link="plugins:netbox_sys_plugin:virtualmachinetype_list", + link_text="Virtual Machine Types", + buttons=vm_machine_type_buttons, + ), + +] +#Menu menu = PluginMenu( label="Sys", groups=( - ("Maintenance", vmMaintenanceItem), + ("Virtual Machine", (vmMachineItem)), ("Provider", clusterProviderCredentialsItem), + ("Operation", (operItem)), ), icon_class="mdi mdi-all-inclusive-box-outline", -) +) \ No newline at end of file diff --git a/netbox_sys_plugin/tables.py b/netbox_sys_plugin/tables.py index bea34c6f4dbb4a0631e26a78ee9ea3c4157d69fb..001f223b15772828d3171e3fa9321d9122056c2b 100644 --- a/netbox_sys_plugin/tables.py +++ b/netbox_sys_plugin/tables.py @@ -2,9 +2,9 @@ import django_tables2 as tables from netbox.tables import NetBoxTable, columns -from .models import VirtualMachineMaintenance, ProviderCredentials - +from .models import VirtualMachineMaintenance, ProviderCredentials, VmAssignedVirtualMachineType, VirtualMachineType +#VmMaintenance class VmMaintenanceTable(NetBoxTable): """VM Maintenance Table definition class""" @@ -35,7 +35,7 @@ class VmMaintenanceTable(NetBoxTable): default_columns = ('id','maintenance_window','assigned_object') - +#ProviderCredentials class ProviderCredentialsTable(NetBoxTable): """VM Maintenance Table definition class""" @@ -79,3 +79,74 @@ class ProviderCredentialsTable(NetBoxTable): ) default_columns = ('id','provider_url','provider_username','provider_password_vault_url','assigned_object') + +#VmAssignedType +class VmAssignedVmTypeTable(NetBoxTable): + """VM Maintenance Table definition class""" + + pk = columns.ToggleColumn() + id = tables.Column( + linkify=True, + ) + + assigned_object = tables.Column( + linkify=True, + orderable=False, + verbose_name="Virtual Machine", + ) + virtual_machine_type = tables.Column( + linkify=True, + verbose_name="Virtual Machine Type", + ) + virtual_machine_type_assignment_desc = tables.Column( + linkify=False, + verbose_name="Description", + ) + + class Meta(NetBoxTable.Meta): + """Meta class""" + model = VmAssignedVirtualMachineType + fields = ( + "pk", + "id", + "virtual_machine_type", + "virtual_machine_type_assignment_desc", + ) + + default_columns = ('id','assigned_object','virtual_machine_type','virtual_machine_type_assignment_desc') + +#VmType +class VmTypeTable(NetBoxTable): + """VM Maintenance Table definition class""" + + pk = columns.ToggleColumn() + id = tables.Column( + linkify=True, + ) + + assigned_object = tables.Column( + linkify=True, + orderable=False, + verbose_name="Cluster Type", + ) + + virtual_machine_type_name = tables.Column( + linkify=True, + verbose_name="Virtual Machine Type", + ) + virtual_machine_type_desc = tables.Column( + linkify=True, + verbose_name="Descritpion", + ) + + class Meta(NetBoxTable.Meta): + """Meta class""" + model = VirtualMachineType + fields = ( + "pk", + "id", + "virtual_machine_type_name", + "virtual_machine_type_desc", + ) + + default_columns = ('id','virtual_machine_type_name','assigned_object','virtual_machine_type_desc') diff --git a/netbox_sys_plugin/template_content.py b/netbox_sys_plugin/template_content.py index d23d99bd4e02badcbcab133fc3d8a6dca8defe0f..4400d886690f8ac956676a00f23fc477cf6b9294 100644 --- a/netbox_sys_plugin/template_content.py +++ b/netbox_sys_plugin/template_content.py @@ -4,14 +4,26 @@ from extras.plugins import PluginTemplateExtension from netbox_sys_plugin import models -class VmMaintenanceTable(PluginTemplateExtension): - """VM Maintenance object template""" +class VmTable(PluginTemplateExtension): + """VM object template""" model = 'virtualization.virtualmachine' def left_page(self): - return self.render('netbox_sys_plugin/vm_vmmaintenance_table.html', extra_context={'vmmaintenanceinfo': models.VirtualMachineMaintenance.objects.filter(VirtualMachine=self.context['object'])}) + return self.render('netbox_sys_plugin/vm_vmmaintenance.html', extra_context={'vmmaintenanceinfo': models.VirtualMachineMaintenance.objects.filter(VirtualMachine=self.context['object'])}) + def right_page(self): + return self.render('netbox_sys_plugin/vm_vmassignedvirtualmachinetype.html', extra_context={'vmassigntypeinfo': models.VmAssignedVirtualMachineType.objects.filter(VirtualMachine=self.context['object'])}) + +class VmTypeTable(PluginTemplateExtension): + """Cluster object template""" + + model = 'virtualization.clustertype' + + def right_page(self): + return self.render('netbox_sys_plugin/clustertype_virtualmachinetype.html', extra_context={'vmtypesinfo': models.VirtualMachineType.objects.filter(ClusterType=self.context['object'])}) + + class ProviderCredentialsTable(PluginTemplateExtension): """Provider Credentials object template""" @@ -21,4 +33,4 @@ class ProviderCredentialsTable(PluginTemplateExtension): return self.render('netbox_sys_plugin/cluster_providercredentials.html', extra_context={'providercredentialsinfo': models.ProviderCredentials.objects.filter(Cluster=self.context['object'])}) -template_extensions = [VmMaintenanceTable,ProviderCredentialsTable] +template_extensions = [VmTable,ProviderCredentialsTable,VmTypeTable] diff --git a/netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html b/netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html index 82082e0f10bbd4fc3e959becf040866bb8d431c1..71616afe681b2ecf0fa3ec8e16dcfd4596f59637 100644 --- a/netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html +++ b/netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html @@ -34,7 +34,7 @@ </tr> {% empty %} <tr> - <td colspan="3">No maintenance window found.</td> + <td colspan="3">No Provider Credentials found.</td> </tr> {% endfor %} </tr> diff --git a/netbox_sys_plugin/templates/netbox_sys_plugin/clustertype_virtualmachinetype.html b/netbox_sys_plugin/templates/netbox_sys_plugin/clustertype_virtualmachinetype.html new file mode 100644 index 0000000000000000000000000000000000000000..cd3a25c92ddca611cca2db4c41b300794c5ff816 --- /dev/null +++ b/netbox_sys_plugin/templates/netbox_sys_plugin/clustertype_virtualmachinetype.html @@ -0,0 +1,39 @@ +{% block content %} + <div class="row mb-3"> + <div class="col col-md-12"> + <div class="card"> + <h5 class="card-header">Provider Credentials</h5> + <div class="card-body"> + <table class="table table-responsive"> + <th scope="row">Virtual Machine Type</th> + <th scope="row">Description</th> + {% for vmtypes in vmtypesinfo %} + <tr> + <td> + {% if vmtypes.virtual_machine_type_name %} + <a href="{{ vmtypes.get_absolute_url }}">{{ vmtypes.virtual_machine_type_name }}</a> + {% else %} + {{ ''|placeholder }} + {% endif %} + </td> + <td> + {% if vmtypes.virtual_machine_type_desc %} + {{ vmtypes.virtual_machine_type_desc }} + {% else %} + {{ ''|placeholder }} + {% endif %} + </td> + </tr> + {% empty %} + <tr> + <td colspan="3">No Virtual Machine Types found.</td> + </tr> + {% endfor %} + </tr> + </table> + </div> + </div> + {% include 'inc/panels/custom_fields.html' %} + </div> + </div> +{% endblock content %} \ No newline at end of file diff --git a/netbox_sys_plugin/templates/netbox_sys_plugin/virtualmachinetype.html b/netbox_sys_plugin/templates/netbox_sys_plugin/virtualmachinetype.html new file mode 100644 index 0000000000000000000000000000000000000000..c33372aff238cb09b3a6254b74a08d11b1617a38 --- /dev/null +++ b/netbox_sys_plugin/templates/netbox_sys_plugin/virtualmachinetype.html @@ -0,0 +1,48 @@ +{% extends 'generic/object.html' %} + +{% block title%} +Virtual Machine Type for {{ object.assigned_object }} +{% endblock title%} + +{% block content %} +<div class="row mb-3"> + <div class="col col-md-6"> + <div class="card"> + <h5 class="card-header">Virtual Machine Type</h5> + <div class="card-body"> + <table class="table table-hover attr-table"> + <tr> + <th scope="row">Name</th> + <td>{{ object.virtual_machine_type_name }}</td> + </tr> + <tr> + <th scope="row">Description</th> + <td>{{ object.virtual_machine_type_desc }}</td> + </tr> + </table> + </div> + </div> + {% include 'inc/panels/custom_fields.html' %} + {% include 'inc/panels/tags.html' %} + </div> + <div class="col col-md-6"> + <div class="card"> + <h5 class="card-header">Assigned Object</h5> + <div class="card-body"> + <table class="table table-hover attr-table"> + <tr> + <th scope="row">{{ object.assigned_object_type|cut:"virtualization | " }}</th> + <td> + {% if object.assigned_object %} + <a href="{{ object.assigned_object.get_absolute_url }}">{{ object.assigned_object }}</a> + {% else %} + {{ ''|placeholder }} + {% endif %} + </td> + </tr> + </table> + </div> + </div> + </div> +</div> +{% endblock content %} diff --git a/netbox_sys_plugin/templates/netbox_sys_plugin/vm_vmassignedvirtualmachinetype.html b/netbox_sys_plugin/templates/netbox_sys_plugin/vm_vmassignedvirtualmachinetype.html new file mode 100644 index 0000000000000000000000000000000000000000..bdebafb67c7ff8a90694e0f821d34558e945fc6c --- /dev/null +++ b/netbox_sys_plugin/templates/netbox_sys_plugin/vm_vmassignedvirtualmachinetype.html @@ -0,0 +1,41 @@ +{% block content %} + <div class="row mb-3"> + <div class="col col-md-12"> + <div class="card"> + <h5 class="card-header">Virtual Machine Type</h5> + <div class="card-body"> + <table class="table table-responsive"> + <th scope="row">ID</th> + <th scope="row">Type</th> + <th scope="row">Description</th> + {% for vmassigntype in vmassigntypeinfo %} + <tr> + <td>{{ vmassigntype.id }}</td> + <td> + {% if vmassigntype.virtual_machine_type %} + <a href="{{ vmassigntype.get_absolute_url }}">{{ vmassigntype.virtual_machine_type }}</a> + {% else %} + {{ ''|placeholder }} + {% endif %} + </td> + <td> + {% if vmassigntype.virtual_machine_type_assignment_desc %} + {{ vmassigntype.virtual_machine_type_assignment_desc }} + {% else %} + {{ ''|placeholder }} + {% endif %} + </td> + </tr> + {% empty %} + <tr> + <td colspan="3">Virtual Machine Types Found</td> + </tr> + {% endfor %} + </tr> + </table> + </div> + </div> + {% include 'inc/panels/custom_fields.html' %} + </div> + </div> +{% endblock content %} \ No newline at end of file diff --git a/netbox_sys_plugin/templates/netbox_sys_plugin/vm_vmmaintenance_table.html b/netbox_sys_plugin/templates/netbox_sys_plugin/vm_vmmaintenance.html similarity index 100% rename from netbox_sys_plugin/templates/netbox_sys_plugin/vm_vmmaintenance_table.html rename to netbox_sys_plugin/templates/netbox_sys_plugin/vm_vmmaintenance.html diff --git a/netbox_sys_plugin/templates/netbox_sys_plugin/vmassignedvirtualmachinetype.html b/netbox_sys_plugin/templates/netbox_sys_plugin/vmassignedvirtualmachinetype.html new file mode 100644 index 0000000000000000000000000000000000000000..5fa41aecb2ef3948bb3fe275bdc1b8dbbcda414a --- /dev/null +++ b/netbox_sys_plugin/templates/netbox_sys_plugin/vmassignedvirtualmachinetype.html @@ -0,0 +1,55 @@ +{% extends 'generic/object.html' %} + +{% block title%} +Virtual Machine Type for {{ object.assigned_object }} +{% endblock title%} + +{% block content %} +<div class="row mb-3"> + <div class="col col-md-6"> + <div class="card"> + <h5 class="card-header">Virtual Machine Type Assignement </h5> + <div class="card-body"> + <table class="table table-hover attr-table"> + <tr> + <th scope="row">Name</th> + <td> + {% if object.virtual_machine_type %} + <a href="{{ object.virtual_machine_type.get_absolute_url }}">{{ object.virtual_machine_type }}</a> + {% else %} + {{ ''|placeholder }} + {% endif %} + </td> + </tr> + + <tr> + <th scope="row">Description</th> + <td>{{ object.virtual_machine_type_assignment_desc }}</td> + </tr> + </table> + </div> + </div> + {% include 'inc/panels/custom_fields.html' %} + {% include 'inc/panels/tags.html' %} + </div> + <div class="col col-md-6"> + <div class="card"> + <h5 class="card-header">Assigned Object</h5> + <div class="card-body"> + <table class="table table-hover attr-table"> + <tr> + <th scope="row">{{ object.assigned_object_type|cut:"virtualization | " }}</th> + <td> + {% if object.assigned_object %} + <a href="{{ object.assigned_object.get_absolute_url }}">{{ object.assigned_object }}</a> + {% else %} + {{ ''|placeholder }} + {% endif %} + </td> + </tr> + </table> + </div> + </div> + </div> +</div> +{% endblock content %} diff --git a/netbox_sys_plugin/urls.py b/netbox_sys_plugin/urls.py index 4d3e076563d02898711c6e3714bf759eeb8dbf4f..94b7d552e890d57eb2ed6bc8d410e9902081912b 100644 --- a/netbox_sys_plugin/urls.py +++ b/netbox_sys_plugin/urls.py @@ -5,29 +5,39 @@ from netbox.views.generic import ObjectChangeLogView, ObjectJournalView from netbox_sys_plugin import models, views urlpatterns = ( - + #maintenance + path('vm-maintenance/<int:pk>/', views.VmMaintenanceView.as_view(), name='virtualmachinemaintenance'), path('vm-maintenance/', views.VmMaintenanceListView.as_view(), name='virtualmachinemaintenance_list'), path('vm-maintenance/add/', views.VmMaintenanceEditView.as_view(), name='virtualmachinemaintenance_add'), - path('vm-maintenance/<int:pk>/', views.VmMaintenanceView.as_view(), name='virtualmachinemaintenance'), path('vm-maintenance/<int:pk>/edit/', views.VmMaintenanceEditView.as_view(), name='virtualmachinemaintenance_edit'), path('vm-maintenance/<int:pk>/delete/', views.VmMaintenanceDeleteView.as_view(), name='virtualmachinemaintenance_delete'), - path('vm-maintenance/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='virtualmachinemaintenance_changelog', kwargs={ - 'model': models.VirtualMachineMaintenance - }), - path('vm-maintenance/<int:pk>/journal/', ObjectJournalView.as_view(), name='virtualmachinemaintenance_journal', kwargs={ - 'model': models.VirtualMachineMaintenance - }), + path('vm-maintenance/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='virtualmachinemaintenance_changelog', kwargs={'model': models.VirtualMachineMaintenance }), + path('vm-maintenance/<int:pk>/journal/', ObjectJournalView.as_view(), name='virtualmachinemaintenance_journal', kwargs={'model': models.VirtualMachineMaintenance}), + #providerCredentials + path('provider-credentials/<int:pk>/', views.ProviderCredentialsView.as_view(), name='providercredentials'), path('provider-credentials/', views.ProviderCredentialsListView.as_view(), name='providercredentials_list'), path('provider-credentials/add/', views.ProviderCredentialsEditView.as_view(), name='providercredentials_add'), - path('provider-credentials/<int:pk>/', views.ProviderCredentialsView.as_view(), name='providercredentials'), path('provider-credentials/<int:pk>/edit/', views.ProviderCredentialsEditView.as_view(), name='providercredentials_edit'), path('provider-credentials/<int:pk>/delete/', views.ProviderCredentialsDeleteView.as_view(), name='providercredentials_delete'), - path('provider-credentials/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='providercredentials_changelog', kwargs={ - 'model': models.VirtualMachineMaintenance - }), - path('provider-credentials/<int:pk>/journal/', ObjectJournalView.as_view(), name='providercredentials_journal', kwargs={ - 'model': models.VirtualMachineMaintenance - }), + path('provider-credentials/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='providercredentials_changelog', kwargs={'model': models.ProviderCredentials}), + path('provider-credentials/<int:pk>/journal/', ObjectJournalView.as_view(), name='providercredentials_journal', kwargs={'model': models.ProviderCredentials}), + #virtualMachineAssignedType + path('vm-assigned-type/<int:pk>/', views.VmAssignedVmTypeView.as_view(), name='vmassignedvirtualmachinetype'), + path('vm-assigned-type/', views.VmAssignedVmTypeListView.as_view(), name='vmassignedvirtualmachinetype_list'), + path('vm-assigned-type/add/', views.VmAssignedVmTypeEditView.as_view(), name='vmassignedvirtualmachinetype_add'), + path('vm-assigned-type/<int:pk>/edit/', views.VmAssignedVmTypeEditView.as_view(), name='vmassignedvirtualmachinetype_edit'), + path('vm-assigned-type/<int:pk>/delete/', views.VmAssignedVmTypeDeleteView.as_view(), name='vmassignedvirtualmachinetype_delete'), + path('vm-assigned-type/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='vmassignedvirtualmachinetype_changelog', kwargs={'model': models.VmAssignedVirtualMachineType}), + path('vm-assigned-type/<int:pk>/journal/', ObjectJournalView.as_view(), name='vmassignedvirtualmachinetype_journal', kwargs={'model': models.VmAssignedVirtualMachineType}), + #virtualMachineType + path('vm-type/<int:pk>/', views.VmTypeView.as_view(), name='virtualmachinetype'), + path('vm-type/', views.VmTypeListView.as_view(), name='virtualmachinetype_list'), + path('vm-type/add/', views.VmTypeEditView.as_view(), name='virtualmachinetype_add'), + path('vm-type/<int:pk>/edit/', views.VmTypeEditView.as_view(), name='virtualmachinetype_edit'), + path('vm-type/<int:pk>/delete/', views.VmTypeDeleteView.as_view(), name='virtualmachinetype_delete'), + path('vm-type/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='virtualmachinetype_changelog', kwargs={'model': models.VirtualMachineType}), + path('vm-type/<int:pk>/journal/', ObjectJournalView.as_view(), name='virtualmachinetype_journal', kwargs={'model': models.VirtualMachineType}), + ) diff --git a/netbox_sys_plugin/views.py b/netbox_sys_plugin/views.py index f80387da4da95bb779f063d16729e12e4bf85104..f93e69dfe88eb965ea4bd91154d294f5c669d82d 100644 --- a/netbox_sys_plugin/views.py +++ b/netbox_sys_plugin/views.py @@ -3,6 +3,7 @@ from netbox.views import generic from . import forms, models, tables, filtersets +#VmMaintenance class VmMaintenanceView(generic.ObjectView): """ Vm maintenance view definition""" @@ -30,7 +31,7 @@ class VmMaintenanceDeleteView(generic.ObjectDeleteView): queryset = models.VirtualMachineMaintenance.objects.all() - +#ProviderCredentials class ProviderCredentialsView(generic.ObjectView): """ Provider Credentials view definition""" @@ -56,4 +57,61 @@ class ProviderCredentialsEditView(generic.ObjectEditView): Defines the edit view for the Vm maintenance django model. """ queryset = models.ProviderCredentials.objects.all() - form = forms.ProviderCredentialsForm \ No newline at end of file + form = forms.ProviderCredentialsForm + +#VmAssignedType +class VmAssignedVmTypeView(generic.ObjectView): + """ Virtual Machine Type view definition""" + + queryset = ( + models.VmAssignedVirtualMachineType.objects.all() + ) + +class VmAssignedVmTypeListView(generic.ObjectListView): + """Cluster Type Virtual Machine Type list view definition""" + + queryset = models.VmAssignedVirtualMachineType.objects.all() + table = tables.VmAssignedVmTypeTable + filterset = filtersets.VmAssignedVmTypeFilterSet + filterset_form = forms.VmAssignedVmTypeFilterForm + +class VmAssignedVmTypeDeleteView(generic.ObjectDeleteView): + """Vm maintenance delete view definition""" + + queryset = models.VmAssignedVirtualMachineType.objects.all() + +class VmAssignedVmTypeEditView(generic.ObjectEditView): + """ + Defines the edit view for the Vm maintenance django model. + """ + queryset = models.VmAssignedVirtualMachineType.objects.all() + form = forms.VmAssignedVmTypeForm + + +#VmType +class VmTypeView(generic.ObjectView): + """ Virtual Machine Type view definition""" + + queryset = ( + models.VirtualMachineType.objects.all() + ) + +class VmTypeListView(generic.ObjectListView): + """Cluster Type Virtual Machine Type list view definition""" + + queryset = models.VirtualMachineType.objects.all() + table = tables.VmTypeTable + filterset = filtersets.VmTypeFilterSet + filterset_form = forms.VmTypeFilterForm + +class VmTypeDeleteView(generic.ObjectDeleteView): + """Vm maintenance delete view definition""" + + queryset = models.VirtualMachineType.objects.all() + +class VmTypeEditView(generic.ObjectEditView): + """ + Defines the edit view for the Vm maintenance django model. + """ + queryset = models.VirtualMachineType.objects.all() + form = forms.VmTypeForm