diff --git a/netbox/templates/virtualization/virtualmachine_edit.html b/netbox/templates/virtualization/virtualmachine_edit.html index 7c240857f..706591ab4 100644 --- a/netbox/templates/virtualization/virtualmachine_edit.html +++ b/netbox/templates/virtualization/virtualmachine_edit.html @@ -6,9 +6,7 @@
Virtual Machine
{% render_field form.name %} - {% render_field form.status %} {% render_field form.role %} - {% render_field form.platform %}
@@ -18,6 +16,15 @@ {% render_field form.cluster %}
+
+
Management
+
+ {% render_field form.status %} + {% render_field form.platform %} + {% render_field form.primary_ip4 %} + {% render_field form.primary_ip6 %} +
+
Resources
diff --git a/netbox/virtualization/forms.py b/netbox/virtualization/forms.py index 34e3fd5cc..ae2987775 100644 --- a/netbox/virtualization/forms.py +++ b/netbox/virtualization/forms.py @@ -9,6 +9,7 @@ from dcim.constants import IFACE_FF_VIRTUAL from dcim.formfields import MACAddressFormField from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, Site from extras.forms import CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm +from ipam.models import IPAddress from tenancy.forms import TenancyForm from tenancy.models import Tenant from utilities.forms import ( @@ -246,8 +247,8 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldForm): class Meta: model = VirtualMachine fields = [ - 'name', 'status', 'cluster_group', 'cluster', 'role', 'tenant', 'platform', 'vcpus', 'memory', 'disk', - 'comments', + 'name', 'status', 'cluster_group', 'cluster', 'role', 'tenant', 'platform', 'primary_ip4', 'primary_ip6', + 'vcpus', 'memory', 'disk', 'comments', ] def __init__(self, *args, **kwargs): @@ -261,6 +262,41 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldForm): 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): status = CSVChoiceField(