"""
This script allows you to create a VM, an interface and primary IP address
all in one screen.
Workaround for issues:
"""
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_type_id=80,
# field_id=1,
# serialized_value=data["cf_last_updated"],
# )
# cf_env.update_or_create(
# obj_type_id=80,
# field_id=5,
# serialized_value=data["cf_environment"],
# )
vm.save()
self.log_success(
"Created VM [%s](https://<redacted>/virtualization/virtual-machines/%s/)"
% (vm.name, vm.id)
)