Browse Source

Fixes #1886: Allow setting the primary IPv4/v6 address for a VirtualMachine via the web UI

Jeremy Stretch 7 years ago
parent
commit
b837e8ea0b

+ 9 - 2
netbox/templates/virtualization/virtualmachine_edit.html

@@ -6,9 +6,7 @@
         <div class="panel-heading"><strong>Virtual Machine</strong></div>
         <div class="panel-heading"><strong>Virtual Machine</strong></div>
         <div class="panel-body">
         <div class="panel-body">
             {% render_field form.name %}
             {% render_field form.name %}
-            {% render_field form.status %}
             {% render_field form.role %}
             {% render_field form.role %}
-            {% render_field form.platform %}
         </div>
         </div>
     </div>
     </div>
     <div class="panel panel-default">
     <div class="panel panel-default">
@@ -19,6 +17,15 @@
         </div>
         </div>
     </div>
     </div>
     <div class="panel panel-default">
     <div class="panel panel-default">
+        <div class="panel-heading"><strong>Management</strong></div>
+        <div class="panel-body">
+            {% render_field form.status %}
+            {% render_field form.platform %}
+            {% render_field form.primary_ip4 %}
+            {% render_field form.primary_ip6 %}
+        </div>
+    </div>
+    <div class="panel panel-default">
         <div class="panel-heading"><strong>Resources</strong></div>
         <div class="panel-heading"><strong>Resources</strong></div>
         <div class="panel-body">
         <div class="panel-body">
             {% render_field form.vcpus %}
             {% render_field form.vcpus %}

+ 38 - 2
netbox/virtualization/forms.py

@@ -9,6 +9,7 @@ from dcim.constants import IFACE_FF_VIRTUAL
 from dcim.formfields import MACAddressFormField
 from dcim.formfields import MACAddressFormField
 from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, Site
 from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, Site
 from extras.forms import CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm
 from extras.forms import CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm
+from ipam.models import IPAddress
 from tenancy.forms import TenancyForm
 from tenancy.forms import TenancyForm
 from tenancy.models import Tenant
 from tenancy.models import Tenant
 from utilities.forms import (
 from utilities.forms import (
@@ -246,8 +247,8 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldForm):
     class Meta:
     class Meta:
         model = VirtualMachine
         model = VirtualMachine
         fields = [
         fields = [
-            'name', 'status', 'cluster_group', 'cluster', 'role', 'tenant', 'platform', 'vcpus', 'memory', 'disk',
+            'name', 'status', 'cluster_group', 'cluster', 'role', 'tenant', 'platform', 'primary_ip4', 'primary_ip6',
-            'comments',
+            'vcpus', 'memory', 'disk', 'comments',
         ]
         ]
 
 
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
@@ -261,6 +262,41 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldForm):
 
 
         super(VirtualMachineForm, self).__init__(*args, **kwargs)
         super(VirtualMachineForm, self).__init__(*args, **kwargs)
 
 
+        if self.instance.pk:
+
+            # Compile list of choices for primary IPv4 and IPv6 addresses
+            for family in [4, 6]:
+                ip_choices = [(None, '---------')]
+                # Collect interface IPs
+                interface_ips = IPAddress.objects.select_related('interface').filter(
+                    family=family, interface__virtual_machine=self.instance
+                )
+                if interface_ips:
+                    ip_choices.append(
+                        ('Interface IPs', [
+                            (ip.id, '{} ({})'.format(ip.address, ip.interface)) for ip in interface_ips
+                        ])
+                    )
+                # Collect NAT IPs
+                nat_ips = IPAddress.objects.select_related('nat_inside').filter(
+                    family=family, nat_inside__interface__virtual_machine=self.instance
+                )
+                if nat_ips:
+                    ip_choices.append(
+                        ('NAT IPs', [
+                            (ip.id, '{} ({})'.format(ip.address, ip.nat_inside.address)) for ip in nat_ips
+                        ])
+                    )
+                self.fields['primary_ip{}'.format(family)].choices = ip_choices
+
+        else:
+
+            # An object that doesn't exist yet can't have any IPs assigned to it
+            self.fields['primary_ip4'].choices = []
+            self.fields['primary_ip4'].widget.attrs['readonly'] = True
+            self.fields['primary_ip6'].choices = []
+            self.fields['primary_ip6'].widget.attrs['readonly'] = True
+
 
 
 class VirtualMachineCSVForm(forms.ModelForm):
 class VirtualMachineCSVForm(forms.ModelForm):
     status = CSVChoiceField(
     status = CSVChoiceField(