diff --git a/docs/model/netbox_sys_domain_names.md b/docs/model/netbox_sys_domain_names.md new file mode 100644 index 0000000000000000000000000000000000000000..9bef37ad811f28ee49a4da724acc64bdaf15fccb --- /dev/null +++ b/docs/model/netbox_sys_domain_names.md @@ -0,0 +1,11 @@ +## netbox_sys_domain_names + +**Virtual Machine domain names definition class** + +| FIELD | TYPE | DESCRIPTION | +|----------------------------------------------------|----------------------------------|---------------------------------------------------------------------------| +| id | Big (8 byte) integer | Unique ID | +| assigned_object_type_id | Big (8 byte) integer | virtual machine Type ID | +| assigned_object_id | Big (8 byte) integer | virtual machine unique ID | +| domain_names | Json | Information about all the domains for a Virtual Machine in a Json format| + diff --git a/docs/model/netbox_sys_virtual_machine_maintenance.md b/docs/model/netbox_sys_virtual_machine_maintenance.md index c8b181d006279dd1e04ae5fb3f972f76a340fdb0..4c5fb9d637d9795dea1f6c6eeb00205b437af516 100644 --- a/docs/model/netbox_sys_virtual_machine_maintenance.md +++ b/docs/model/netbox_sys_virtual_machine_maintenance.md @@ -5,7 +5,7 @@ | FIELD | TYPE | DESCRIPTION | |----------------------------------------------------|----------------------------------|---------------------------------------------------------------------------| | id | Big (8 byte) integer | Unique ID | -| assigned_object_type_id | Big (8 byte) integer | virtual machine type ID | +| assigned_object_type_id | Big (8 byte) integer | virtual machine Type ID | | assigned_object_id | Big (8 byte) integer | virtual machine unique ID | | virtual_machine_maintenance_window | String | A string representing a day of the week and a time of the day, 0 = Sunday , 1 = monday | diff --git a/netbox_sys_plugin/api/serializers.py b/netbox_sys_plugin/api/serializers.py index bc249e4cf7c54db0f333d21e850954bf83d66033..afba76ed210d6a41ceca4d33a9de098cd29078f7 100644 --- a/netbox_sys_plugin/api/serializers.py +++ b/netbox_sys_plugin/api/serializers.py @@ -8,7 +8,7 @@ from dcim.api.nested_serializers import ( from ipam.api.nested_serializers import ( NestedIPAddressSerializer, NestedServiceSerializer ) -from .. models import VirtualMachineMaintenance, ProviderCredentials,VmAssignedVirtualMachineType, VirtualMachineType +from .. models import VirtualMachineMaintenance, ProviderCredentials,VmAssignedVirtualMachineType, VirtualMachineType,DomainNames from django.contrib.contenttypes.models import ContentType from .nested_serializers import * from virtualization.choices import * @@ -34,13 +34,11 @@ class ClusterSerializer(serializers.ModelSerializer): ) return NestedProviderCredentialsSerializer(provider_credentials, many=True).data - class ClusterTypeSerializer(serializers.ModelSerializer): class Meta: model = ClusterType fields = ['id', 'name'] - #Plugin Data Serializer class VirtualMachineMaintenanceSerializer(serializers.ModelSerializer): id = serializers.IntegerField(read_only=True) @@ -63,6 +61,7 @@ class ProviderCredentialsSerializer(serializers.ModelSerializer): model = ProviderCredentials #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) @@ -74,7 +73,6 @@ class VirtualMachineTypeSerializer(serializers.ModelSerializer): #fields = ['id','maintenance_window','assigned_object_type','assigned_object_id','assigned_object_type','virtual_machine'] fields = '__all__' - class VmAssignedVirtualMachineTypeSerializer(serializers.ModelSerializer): id = serializers.IntegerField(read_only=True) virtual_machine = VirtualMachineSerializer(source='assigned_object', read_only=True) @@ -87,6 +85,17 @@ class VmAssignedVirtualMachineTypeSerializer(serializers.ModelSerializer): #fields = ['id','maintenance_window','assigned_object_type','assigned_object_id','assigned_object_type','virtual_machine'] fields = '__all__' +class DomainNamesSerializer(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 = DomainNames + #fields = ['id','maintenance_window','assigned_object_type','assigned_object_id','assigned_object_type','virtual_machine'] + fields = '__all__' + class VirtualMachineSerializer(NetBoxModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:virtualmachine-detail') status = ChoiceField(choices=VirtualMachineStatusChoices, required=False) diff --git a/netbox_sys_plugin/api/urls.py b/netbox_sys_plugin/api/urls.py index 47d606ca7bdeb44b5baf85fae14d1c7ffc2f28ae..51e074e3a5341e1831abcd58be086c0bcac0e926 100644 --- a/netbox_sys_plugin/api/urls.py +++ b/netbox_sys_plugin/api/urls.py @@ -6,6 +6,7 @@ router.register(r'MaintenanceWindow', VirtualMachineMaintenanceViewSet) router.register(r'ProviderCredentials', ProviderCredentialsViewSet) router.register(r'AssignedVmType', VmAssignedVirtualMachineTypeViewSet) router.register(r'VmType', VirtualMachineTypeViewSet) +router.register(r'DomainNames', VirtualMachineTypeViewSet) router.register(r'VirtualMachine', VirtualMachineViewSet) app_name = "netbox_sys_plugin" diff --git a/netbox_sys_plugin/api/views.py b/netbox_sys_plugin/api/views.py index 094873d383f46d46f82353d7ca0e2fde641f8592..bc4c63e144a5c1aa828790de89fd4a1fbc78ef40 100644 --- a/netbox_sys_plugin/api/views.py +++ b/netbox_sys_plugin/api/views.py @@ -4,7 +4,7 @@ from rest_framework.response import Response from django.db.models import Prefetch from netbox.api.viewsets import NetBoxModelViewSet from virtualization import filtersets -from .. models import VirtualMachineMaintenance, ProviderCredentials, VmAssignedVirtualMachineType, VirtualMachineType +from .. models import VirtualMachineMaintenance, ProviderCredentials, VmAssignedVirtualMachineType, VirtualMachineType,DomainNames from . serializers import * class VirtualMachineMaintenanceViewSet(viewsets.ModelViewSet): @@ -12,6 +12,10 @@ class VirtualMachineMaintenanceViewSet(viewsets.ModelViewSet): serializer_class = VirtualMachineMaintenanceSerializer http_method_names = ["get", "post", "patch", "delete", "options"] +class DomainNamesViewSet(viewsets.ModelViewSet): + queryset = VirtualMachineMaintenance.objects.all() + serializer_class = DomainNamesSerializer + http_method_names = ["get", "post", "patch", "delete", "options"] class ProviderCredentialsViewSet(viewsets.ModelViewSet): queryset = ProviderCredentials.objects.all() diff --git a/netbox_sys_plugin/forms/createvm.py b/netbox_sys_plugin/forms/createvm.py index 6f96ce9e329c252aa5fbd7adeadad3773ee84b18..6b71a49e35ff34c8453348e3b54338b6b51f2aca 100644 --- a/netbox_sys_plugin/forms/createvm.py +++ b/netbox_sys_plugin/forms/createvm.py @@ -165,10 +165,6 @@ class CreateVmForm(NetBoxModelForm): self.fields.pop('tags', None) # Initialize formsets - # Cluster + Cluster type - self.cluster_formsets = [] - empty_cluster_formset = ClusterFormSet(data=data, prefix='clusters') - self.cluster_formsets.append(('new', empty_cluster_formset)) # Virtual Machine self.virtual_machine_formsets = [] empty_vm_formset = VirtualMachineFormSet(data=data, prefix='vms_new') @@ -206,19 +202,6 @@ class CreateVmForm(NetBoxModelForm): empty_tagformset = TagFormSet(data=data, prefix='tag_new') self.tagformsets.append(('new', empty_tagformset)) - @staticmethod - def check_cluster_exist(data): - """Validate whether a cluster already exists based on the input.""" - new_clustertype = data.get('name', '').strip() - new_cluster = data.get('clusters-0-name', '').strip() - existing_cluster_type = data.get('cl_list_new-cluster_type', '').strip() - existing_cluster = data.get('cl_list_new-cluster', '').strip() - - if new_clustertype and new_cluster and existing_cluster_type and existing_cluster: - raise ValueError("Cannot create a provider and choose an existing one at the same time.") - - return bool(existing_cluster_type and existing_cluster) - @staticmethod def parse_ports(ports_field): """Parse the port numbers.""" @@ -254,43 +237,7 @@ class CreateVmForm(NetBoxModelForm): ) @staticmethod - def create_cluster_type(data): - """Create and save a ClusterType object.""" - cluster_type = ClusterType( - name=data.get('name', ''), - slug=data.get('slug', ''), - description=data.get('description', ''), - tags = CreateVmForm.get_parse_tags(data) - ) - cluster_type.full_clean() - cluster_type.save() - CreateVmForm.assign_tags(cluster_type,data) - return cluster_type - - @staticmethod - def create_cluster(data, cluster_type): - """Create and save a Cluster object.""" - site_id = data.get('clusters-0-site', '') - try: - site = Site.objects.get(pk=site_id) - except Site.DoesNotExist: - raise ValueError(f"Invalid Site ID: {site_id}") - - cluster = Cluster( - name=data.get('clusters-0-name', ''), - type=cluster_type, - status=data.get('clusters-0-status', ''), - site=site, - description=data.get('clusters-0-description', ''), - tags = CreateVmForm.get_parse_tags(data) - ) - cluster.full_clean() - cluster.save() - CreateVmForm.assign_tags(cluster,data) - return cluster - - @staticmethod - def create_virtual_machine(data, cluster, cluster_existence): + def create_virtual_machine(data, cluster): """Create and save a VirtualMachine object.""" role_id = data.get('vms_new-0-role', '') try: @@ -380,22 +327,16 @@ class CreateVmForm(NetBoxModelForm): return ip_address - def create_all_ip_adresses(self, data, vm_interface,): - self.create_ip_address(data,vm_interface,'ip_new','IP Address') - self.create_ip_address(data,vm_interface,'gateway_new','Gateway') + def create_all_ip_adresses(self, data, vm_interface): + self.create_ip_address(data,vm_interface,'ip_new','Network IP Address') + self.create_ip_address(data,vm_interface,'gateway_new','Network Gateway') def process_creation(self, data): """Object creation""" try: with transaction.atomic(): - cluster_exists = self.check_cluster_exist(data) - if not cluster_exists: - cluster_type = self.create_cluster_type(data) - cluster = self.create_cluster(data, cluster_type) - else: - cluster = Cluster.objects.get(pk=data.get('cl_list_new-cluster', '')) - - vm = self.create_virtual_machine(data, cluster, cluster_exists) + cluster = Cluster.objects.get(pk=data.get('cl_list_new-cluster', '')) + vm = self.create_virtual_machine(data, cluster) vmi = self.create_vm_interface(data, vm) self.create_all_services(data, vm) self.create_all_ip_adresses(data, vmi) diff --git a/netbox_sys_plugin/forms/machine.py b/netbox_sys_plugin/forms/machine.py index 4396562f70e7cc5034387b8678c33079a950be60..a217ed73f1528fe455f88fda908a202ffb24b62b 100644 --- a/netbox_sys_plugin/forms/machine.py +++ b/netbox_sys_plugin/forms/machine.py @@ -10,8 +10,8 @@ from netbox.forms import ( NetBoxModelForm, NetBoxModelFilterSetForm, ) -from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField -from ..models import VmAssignedVirtualMachineType, VirtualMachineMaintenance, VirtualMachineType +from utilities.forms.fields import DynamicModelChoiceField, JSONField +from ..models import VmAssignedVirtualMachineType, VirtualMachineMaintenance, VirtualMachineType, DomainNames class VmAssignedVmTypeForm(NetBoxModelForm): """ @@ -214,4 +214,74 @@ class VmMaitenanceForm(NetBoxModelForm): class VmMaintenanceFilterForm(NetBoxModelFilterSetForm): """MacAddress filter form definition class""" + model = VirtualMachineMaintenance + +class DomainNamesForm(NetBoxModelForm): + """ + GUI form to add or edit a VM Maitenance. + """ + virtual_machine = DynamicModelChoiceField( + queryset=VirtualMachine.objects.none(), required=True, label="Virtual Machine" + ) + domain_names = JSONField( + label=_('Domain Names'), + required=False + ) + + 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 = DomainNames.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 = DomainNames + fields = ( 'virtual_machine','domain_names','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 DomainNamesFilterForm(NetBoxModelFilterSetForm): + """MacAddress filter form definition class""" + model = VirtualMachineMaintenance \ No newline at end of file diff --git a/netbox_sys_plugin/migrations/0006_domainnames.py b/netbox_sys_plugin/migrations/0006_domainnames.py new file mode 100644 index 0000000000000000000000000000000000000000..b0fbbf9710675a9de726b5dcf364d5aa591971e2 --- /dev/null +++ b/netbox_sys_plugin/migrations/0006_domainnames.py @@ -0,0 +1,37 @@ +# Generated by Django 4.2.16 on 2024-12-06 12:19 + +from django.db import migrations, models +import django.db.models.deletion +import taggit.managers +import utilities.json + + +class Migration(migrations.Migration): + + dependencies = [ + ('extras', '0098_webhook_custom_field_data_webhook_tags'), + ('contenttypes', '0002_remove_content_type_name'), + ('netbox_sys_plugin', '0005_remove_providercredentials_provider_url_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='DomainNames', + 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)), + ('domain_names', models.JSONField(blank=True, 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', 'ipam'), ('model', 'IPAddress'))), 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': 'Domain Name', + 'verbose_name_plural': 'Domain Names', + 'ordering': ['assigned_object_id'], + 'unique_together': {('assigned_object_id',)}, + }, + ), + ] diff --git a/netbox_sys_plugin/migrations/0007_alter_domainnames_assigned_object_type.py b/netbox_sys_plugin/migrations/0007_alter_domainnames_assigned_object_type.py new file mode 100644 index 0000000000000000000000000000000000000000..2d74afec8a1b3f4e1c0a037c2c305e42496ce9f7 --- /dev/null +++ b/netbox_sys_plugin/migrations/0007_alter_domainnames_assigned_object_type.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.16 on 2024-12-06 14:58 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('netbox_sys_plugin', '0006_domainnames'), + ] + + operations = [ + migrations.AlterField( + model_name='domainnames', + name='assigned_object_type', + field=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'), + ), + ] diff --git a/netbox_sys_plugin/models/machine.py b/netbox_sys_plugin/models/machine.py index 690faa705e44557debdb42ce19a07cef7d6fb304..f1e195be4d017cfbb493ada736972cb8bac6ab56 100644 --- a/netbox_sys_plugin/models/machine.py +++ b/netbox_sys_plugin/models/machine.py @@ -165,3 +165,46 @@ GenericRelation( related_query_name="VirtualMachine", ).contribute_to_class(VirtualMachine, "VirtualMachineMaintenance") +#Domain Names +class DomainNames(NetBoxModel): + """Cluster ProviderInfo definition class""" + + domain_names = models.JSONField( + blank=True, + null=True, + ) + + 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 = "Domain Name" + verbose_name_plural = "Domain Names" + + + def __str__(self): + return f"for Virtual Machine Address {self.assigned_object_id}" + + def get_absolute_url(self): + """override""" + return reverse("plugins:netbox_sys_plugin:domainnames", args=[self.pk]) + +GenericRelation( + to=DomainNames, + content_type_field="assigned_object_type", + object_id_field="assigned_object_id", + related_query_name="VirtualMachine", +).contribute_to_class(VirtualMachine, "DomainNames") \ No newline at end of file diff --git a/netbox_sys_plugin/navigation.py b/netbox_sys_plugin/navigation.py index bd6fefccd9a1ba684a95a242ed8a5f991a8a7df8..ca9245db9e5a0c79b702797650005b5e4615f1d2 100644 --- a/netbox_sys_plugin/navigation.py +++ b/netbox_sys_plugin/navigation.py @@ -57,6 +57,17 @@ create_vm_buttons = [ ), ] +create_domainnames_buttons = [ + PluginMenuButton( + link="plugins:netbox_sys_plugin:domainnames_add", + title="Add", + icon_class="mdi mdi-plus-thick", + color=ButtonColorChoices.GREEN, + permissions=["netbox_sys_plugin.add_domainnames"], + ), +] + + #Items clusterProviderCredentialsItem = [ @@ -87,6 +98,12 @@ vmMachineItem = [ buttons=vm_maintenance_buttons, permissions=["netbox_sys_plugin.list_maintenance"], ), + PluginMenuItem( + link="plugins:netbox_sys_plugin:domainnames_list", + link_text="VM Domain Names", + buttons=create_domainnames_buttons, + permissions=["netbox_sys_plugin.add_domainnames"], + ), PluginMenuItem( link="plugins:netbox_sys_plugin:creatvm_add", link_text="Create VM", diff --git a/netbox_sys_plugin/tables.py b/netbox_sys_plugin/tables.py index 374b9b275fe8a584134f5c4882adf352a4f97ea6..a92222722138363bb0f54f4e0d9e1ac84cc97d3c 100644 --- a/netbox_sys_plugin/tables.py +++ b/netbox_sys_plugin/tables.py @@ -145,3 +145,34 @@ class VmTypeTable(NetBoxTable): ) default_columns = ('id','virtual_machine_type_name','assigned_object','virtual_machine_type_desc') + +#DomainNames +class DomainNamesTable(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", + ) + + domain_names = tables.Column( + linkify=True, + verbose_name="Domain Names", + ) + + class Meta(NetBoxTable.Meta): + """Meta class""" + model = VirtualMachineType + fields = ( + "pk", + "id", + "domain_names", + ) + + default_columns = ('id','domain_names','assigned_object') \ No newline at end of file diff --git a/netbox_sys_plugin/template_content.py b/netbox_sys_plugin/template_content.py index 4400d886690f8ac956676a00f23fc477cf6b9294..99b8625fc8d89b938fb9ef6ddf5dd9b8e3a6fc1a 100644 --- a/netbox_sys_plugin/template_content.py +++ b/netbox_sys_plugin/template_content.py @@ -15,6 +15,15 @@ class VmTable(PluginTemplateExtension): 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 VmTableDomainNames(PluginTemplateExtension): + """VM Domain names object template""" + + model = 'virtualization.virtualmachine' + + def left_page(self): + return self.render('netbox_sys_plugin/vm_domainnames.html', extra_context={'domainnamesinfo': models.DomainNames.objects.filter(VirtualMachine=self.context['object'])}) + + class VmTypeTable(PluginTemplateExtension): """Cluster object template""" @@ -33,4 +42,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 = [VmTable,ProviderCredentialsTable,VmTypeTable] +template_extensions = [VmTable,ProviderCredentialsTable,VmTypeTable,VmTableDomainNames] diff --git a/netbox_sys_plugin/templates/netbox_sys_plugin/create_vm.html b/netbox_sys_plugin/templates/netbox_sys_plugin/create_vm.html index d1d14b2fd98161f3e1fba433513d14ef184cb778..3e562fdca0ece46896f68a4f87525bd58eff415f 100644 --- a/netbox_sys_plugin/templates/netbox_sys_plugin/create_vm.html +++ b/netbox_sys_plugin/templates/netbox_sys_plugin/create_vm.html @@ -37,46 +37,14 @@ SYS - Virtual Machine <form method="post" enctype="multipart/form-data" class="form-object-edit mt-5"> {% csrf_token %} <div class="field-group my-5"> - <div class="row mb-2"> - <ul class="nav nav-pills" role="tablist"> - <li role="presentation" class="nav-item"> - <button role="tab" type="button" id="device_tab" data-bs-toggle="tab" aria-controls="device" data-bs-target="#device" class="nav-link active"> - New Provider - </button> - </li> - <li role="presentation" class="nav-item"> - <button role="tab" type="button" id="vm_tab" data-bs-toggle="tab" aria-controls="vm" data-bs-target="#vm" class="nav-link"> - Existing Provider - </button> - </li> - </ul> - </div> - <div class="tab-content p-0 border-0"> - <div class="tab-pane active" id="device" role="tabpanel" aria-labeled-by="device_tab"> - <h5>Provider Type</h5> - <div class="form-group" class="field-group mb-5"> - {{ form.as_p }} - </div> - <h5>Provider</h5> - {% for cluster_formset in form.cluster_formsets %} - {% for vl_form in cluster_formset %} - <div class="form-group" class="field-group mb-5"> - {{ vl_form.as_p }} - </div> - {% endfor %} - {% endfor %} - </div> - <div class="tab-pane" id="vm" role="tabpanel" aria-labeled-by="vm_tab"> - <h5>Provider</h5> - {% for cl_list_formset in form.cl_list_formsets %} - {% for ct_form in cl_list_formset %} - <div class="form-group" class="field-group mb-5"> - {{ ct_form.as_p }} - </div> - {% endfor %} - {% endfor %} - </div> + <h5>Provider</h5> + {% for cl_list_formset in form.cl_list_formsets %} + {% for ct_form in cl_list_formset %} + <div class="form-group" class="field-group mb-5"> + {{ ct_form.as_p }} </div> + {% endfor %} + {% endfor %} </div> <div class="field-group my-5"> <h5>Virtual Machine</h5> diff --git a/netbox_sys_plugin/templates/netbox_sys_plugin/domainnames.html b/netbox_sys_plugin/templates/netbox_sys_plugin/domainnames.html new file mode 100644 index 0000000000000000000000000000000000000000..a203221eea9113fcc5ed57cbe6e121805fcea1b3 --- /dev/null +++ b/netbox_sys_plugin/templates/netbox_sys_plugin/domainnames.html @@ -0,0 +1,46 @@ +{% extends 'generic/object.html' %} + +{% block title%} +{{ object.assigned_object }} Domain Names +{% endblock title%} + +{% block content %} +<div class="row mb-3"> + <div class="col col-md-6"> + <div class="card"> + <h5 class="card-header">Virtual Machine Maintenance</h5> + + <div class="card-body"> + <table class="table table-hover attr-table"> + <tr> + <th scope="row">Domain Names</th> + <td>{% include 'extras/inc/configcontext_data.html' with data=object.domain_names format=json %}</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">Details</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_domainnames.html b/netbox_sys_plugin/templates/netbox_sys_plugin/vm_domainnames.html new file mode 100644 index 0000000000000000000000000000000000000000..0293a29bd398d9973ddc978549a6e08154069430 --- /dev/null +++ b/netbox_sys_plugin/templates/netbox_sys_plugin/vm_domainnames.html @@ -0,0 +1,33 @@ +{% block content %} + <div class="row mb-3"> + <div class="col col-md-12"> + <div class="card"> + <h5 class="card-header">Domain Names Information</h5> + <div class="card-body"> + <table class="table table-responsive"> + <th scope="row">ID</th> + <th scope="row">Domain Names</th> + {% for domainnames in domainnamesinfo %} + <tr> + <td>{{ domainnames.id }}</td> + <td> + {% if domainnames.domain_names %} + <a href="{{ domainnames.get_absolute_url }}">{{ domainnames.domain_names }}</a> + {% else %} + {{ ''|placeholder }} + {% endif %} + </td> + </tr> + {% empty %} + <tr> + <td colspan="3">No domain names 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/urls.py b/netbox_sys_plugin/urls.py index 299078a6455f0cb56bc6e5d682d880f1b6ac68b8..c43d9b11fdfc1399a0d9dcd74c2ee7bea72864e6 100644 --- a/netbox_sys_plugin/urls.py +++ b/netbox_sys_plugin/urls.py @@ -38,10 +38,15 @@ urlpatterns = ( 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}), - + #DomainNames + path('domain-names/<int:pk>/', views.DomainNamesView.as_view(), name='domainnames'), + path('domain-names/', views.DomainNamesListView.as_view(), name='domainnames_list'), + path('domain-names/add/', views.DomainNamesEditView.as_view(), name='domainnames_add'), + path('domain-names/<int:pk>/edit/', views.DomainNamesEditView.as_view(), name='domainnames_edit'), + path('domain-names/<int:pk>/delete/', views.DomainNamesDeleteView.as_view(), name='domainnames_delete'), + path('domain-names/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='domainnames_changelog', kwargs={'model': models.DomainNames}), + path('domain-names/<int:pk>/journal/', ObjectJournalView.as_view(), name='domainnames_journal', kwargs={'model': models.DomainNames}), #CreateVM - path('create-vm/', CreateVmView.as_view(), name='creatvm_add'), - ) diff --git a/netbox_sys_plugin/views.py b/netbox_sys_plugin/views.py index fd8bbc9e1d399dce48e3ecfa0246795299321c90..0b1f59b63d4b46b106f3c036a53594d0c046f3ee 100644 --- a/netbox_sys_plugin/views.py +++ b/netbox_sys_plugin/views.py @@ -141,4 +141,33 @@ class CreateVmView(generic.ObjectView): return redirect(reverse('virtualization:virtualmachine_list')) except ValueError as e: messages.error(request, f"Error: {str(e)}") - return render(request, self.template_name, {'form': form}) \ No newline at end of file + return render(request, self.template_name, {'form': form}) + +#Domain Names +class DomainNamesView(generic.ObjectView): + + """ Domain names view definition""" + + queryset = ( + models.DomainNames.objects.all() + ) + +class DomainNamesListView(generic.ObjectListView): + """Domain Names list view definition""" + + queryset = models.DomainNames.objects.all() + table = tables.DomainNamesTable + #filterset = filtersets.VmTypeFilterSet + filterset_form = forms.DomainNamesFilterForm + +class DomainNamesEditView(generic.ObjectEditView): + """ + Defines the edit view for the Domain Names django model. + """ + queryset = models.DomainNames.objects.all() + form = forms.DomainNamesForm + +class DomainNamesDeleteView(generic.ObjectDeleteView): + """Domain Names delete view definition""" + + queryset = models.DomainNames.objects.all() \ No newline at end of file