106 lines
4.0 KiB
Python
Executable File
106 lines
4.0 KiB
Python
Executable File
# -----------------------------------------------------------------------------
|
|
# Swissmakers GmbH - NetBox Custom Script
|
|
# © 2025 Swissmakers GmbH. All rights reserved.
|
|
# https://swissmakers.ch
|
|
# -----------------------------------------------------------------------------
|
|
|
|
from dcim.models import DeviceRole, Platform, Device, DeviceType, Site, Interface, Rack, Location
|
|
from django.core.exceptions import ObjectDoesNotExist
|
|
from ipam.choices import IPAddressStatusChoices
|
|
from ipam.models import IPAddress, VRF
|
|
from extras.scripts import Script, StringVar, IPAddressWithMaskVar, ObjectVar, ChoiceVar
|
|
from dcim.choices import DeviceStatusChoices, InterfaceTypeChoices
|
|
|
|
class NewDevice(Script):
|
|
class Meta:
|
|
name = "New Device"
|
|
description = "Create a new Device"
|
|
scheduling_enabled = False
|
|
|
|
device_name = StringVar(label="Device name (FQDN)")
|
|
access_description = StringVar(
|
|
label="Description",
|
|
required=False,
|
|
max_length=200,
|
|
)
|
|
primary_ip4 = IPAddressWithMaskVar(label="IPv4 address in CIDR (/24)", required=False)
|
|
interface_name = StringVar(default="ens18", required=False)
|
|
role = ObjectVar(model=DeviceRole, required=False)
|
|
status = ChoiceVar(choices=DeviceStatusChoices, default=DeviceStatusChoices.STATUS_ACTIVE)
|
|
device_type = ObjectVar(model=DeviceType)
|
|
site = ObjectVar(model=Site)
|
|
rack = ObjectVar(model=Rack, required=False)
|
|
location = ObjectVar(model=Location, required=False)
|
|
serial = StringVar(label="Serial Number", required=False)
|
|
|
|
def run(self, data, commit):
|
|
device = Device(
|
|
name=data["device_name"],
|
|
role=data["role"],
|
|
status=data["status"],
|
|
device_type=data["device_type"],
|
|
site=data["site"],
|
|
rack=data.get("rack"),
|
|
location=data.get("location"),
|
|
description=data.get("access_description"),
|
|
serial=data.get("serial"),
|
|
)
|
|
device.full_clean()
|
|
device.save()
|
|
|
|
if data["interface_name"]:
|
|
try:
|
|
interface = Interface.objects.get(
|
|
name=data["interface_name"],
|
|
device=device
|
|
)
|
|
self.log_info(f"Interface {data['interface_name']} already exists for device {device.name}")
|
|
except ObjectDoesNotExist:
|
|
interface = Interface(
|
|
name=data["interface_name"],
|
|
device=device,
|
|
type=InterfaceTypeChoices.TYPE_1GE_FIXED,
|
|
)
|
|
interface.full_clean()
|
|
interface.save()
|
|
|
|
def add_addr(addr, family):
|
|
if not addr:
|
|
return
|
|
if addr.version != family:
|
|
raise RuntimeError(f"Wrong family for {addr}")
|
|
try:
|
|
a = IPAddress.objects.get(
|
|
address=addr,
|
|
vrf=data.get("vrf"),
|
|
)
|
|
a.snapshot()
|
|
result = "Assigned"
|
|
except ObjectDoesNotExist:
|
|
a = IPAddress(
|
|
address=addr,
|
|
vrf=data.get("vrf"),
|
|
)
|
|
result = "Created"
|
|
a.status = IPAddressStatusChoices.STATUS_ACTIVE
|
|
if a.assigned_object:
|
|
raise RuntimeError(f"Address {addr} is already assigned")
|
|
a.assigned_object = interface
|
|
# set DNS-name to fqdn of the device
|
|
a.dns_name = device.name
|
|
# validate and save
|
|
a.full_clean()
|
|
a.save()
|
|
self.log_info(f"{result} IP address {a.address} {a.vrf or ''} with DNS name {a.dns_name}")
|
|
setattr(device, f"primary_ip{family}", a)
|
|
|
|
device.snapshot()
|
|
if data["primary_ip4"]:
|
|
add_addr(data["primary_ip4"], 4)
|
|
|
|
device.full_clean()
|
|
device.save()
|
|
|
|
self.log_success(f"Created Device {device.name}")
|
|
self.log_info(f"Device details: <a href='{device.get_absolute_url()}'>{device.name}</a>")
|