""" This script allows you to create a VM, an interface and primary IP address all in one screen. Workaround for issues: https://github.com/netbox-community/netbox/issues/1492 https://github.com/netbox-community/netbox/issues/648 """ from django.contrib.contenttypes.models import ContentType from dcim.choices import InterfaceTypeChoices from dcim.models import DeviceRole, Platform, Interface from django.core.exceptions import ObjectDoesNotExist from ipam.choices import IPAddressStatusChoices from ipam.models import IPAddress, VRF from tenancy.models import Tenant from virtualization.choices import VirtualMachineStatusChoices from virtualization.models import Cluster, VirtualMachine from extras.scripts import ( BaseScript, BooleanVar, ChoiceVar, FileVar, IntegerVar, IPAddressVar, IPAddressWithMaskVar, IPNetworkVar, MultiObjectVar, ObjectVar, Script, StringVar, TextVar, ) # from extras.choices import * # from extras.filters import CustomFieldFilter, CustomFieldFilterSet # from extras.models import ( # CustomField, # CustomFieldValue, # CustomFieldChoice, # CustomFieldModel, # ) from utilities.forms import APISelect, APISelectMultiple, DatePicker class NewVM(Script): class Meta: name = "New VM" description = "Create a new VM" field_order = [ "vm_name", "dns_name", "vrf", "primary_ip4", "secondary_ip4", "primary_ip6", "role", "status", "cluster", # 'tenant', "platform", "interface_name", "mac_address", "vcpus", "memory", "disk", "comments", # "cf_last_updated", # , 'cf_environment' ] vm_name = StringVar(label="VM name") dns_name = StringVar(label="DNS name", required=False) vrf = ObjectVar( label="VRF", queryset=VRF.objects.all(), required=False, widget=APISelect(filter_for={"secondary_ip4": "vrf_id"}), ) primary_ip4 = IPAddressWithMaskVar(label="IPv4 address") secondary_ip4 = MultiObjectVar( queryset=IPAddress.objects.all(), label="IP Address", required=False, widget=APISelectMultiple( api_url="/api/ipam/ip-addresses/", display_field="address" ), ) primary_ip6 = IPAddressWithMaskVar(label="IPv6 address", required=False) role = ObjectVar(DeviceRole.objects.filter(vm_role=True), required=False) status = ChoiceVar( VirtualMachineStatusChoices, default=VirtualMachineStatusChoices.STATUS_ACTIVE ) cluster = ObjectVar(Cluster.objects) # tenant = ObjectVar(Tenant.objects, required=False) platform = ObjectVar(Platform.objects, required=False) interface_name = StringVar(default="eth0") mac_address = StringVar(label="MAC address", required=False) vcpus = IntegerVar(label="VCPUs", required=False) memory = IntegerVar(label="Memory (MB)", required=False) disk = IntegerVar(label="Disk (GB)", required=False) comments = TextVar(label="Comments", required=False) # cf_last_updated = StringVar( # label="Last Updated", required=False, widget=DatePicker() # ) # content_type = ContentType.objects.get_for_model(VirtualMachine) # custom_fields = CustomField.objects.get(obj_type=content_type, name="Env") # ENV_VALS = CustomFieldChoice.objects.filter(field=custom_fields).values() # ENV_CHOICES = () # for val in ENV_VALS: # ENV_CHOICES = ENV_CHOICES + ((f"{val['id']}", f"{val['value']}"),) # cf_environment = ChoiceVar(choices=ENV_CHOICES, label="Environment", required=False) def run(self, data): vm = VirtualMachine( name=data["vm_name"], role=data["role"], status=data["status"], cluster=data["cluster"], platform=data["platform"], vcpus=data["vcpus"], memory=data["memory"], disk=data["disk"], comments=data["comments"], tenant=data.get("tenant"), ) vm.save() interface = Interface( name=data["interface_name"], type=InterfaceTypeChoices.TYPE_VIRTUAL, mac_address=data["mac_address"], virtual_machine=vm, ) interface.save() def add_addr(addr, expect_family, is_primary): if not addr: return if is_primary: if addr.version != expect_family: raise RuntimeError("Wrong family for %r" % addr) try: a = IPAddress.objects.get(address=addr, vrf=data.get("vrf"),) result = "Assigned" except ObjectDoesNotExist: a = IPAddress(address=addr, vrf=data.get("vrf"),) result = "Created" a.status = IPAddressStatusChoices.STATUS_ACTIVE a.dns_name = data["dns_name"] if a.interface: raise RuntimeError("Address %s is already assigned" % addr) a.interface = interface a.tenant = data.get("tenant") a.save() self.log_info("%s IP address %s %s" % (result, a.address, a.vrf or "")) if is_primary: setattr(vm, "primary_ip%d" % a.family, a) add_addr(data["primary_ip4"], 4, True) add_addr(data["primary_ip6"], 6, True) for ip_addr in data["secondary_ip4"]: add_addr(ip_addr.address, 4, False) # content_type = ContentType.objects.get_for_model(VirtualMachine) # custom_fields = CustomFieldValue.objects.filter( # obj_type=content_type, obj_id=vm.id # ) # cf_lastupdate = custom_fields.filter(field_id=1) # cf_env = custom_fields.filter(field_id=5) # cf_lastupdate.update_or_create( # obj_id=vm.id, # obj_type_id=80, # field_id=1, # serialized_value=data["cf_last_updated"], # ) # cf_env.update_or_create( # obj_id=vm.id, # obj_type_id=80, # field_id=5, # serialized_value=data["cf_environment"], # ) vm.save() self.log_success( "Created VM [%s](https:///virtualization/virtual-machines/%s/)" % (vm.name, vm.id) )