class DemoScript(Script): name = "Script Demo" description = "A quick demonstration of the available field types" my_string1 = StringVar( description="Input a string between 3 and 10 characters", min_length=3, max_length=10) my_string2 = StringVar( description= "This field enforces a regex: three letters followed by three numbers", regex=r'[a-z]{3}\d{3}') my_number = IntegerVar( description="Pick a number between 1 and 255 (inclusive)", min_value=1, max_value=255) my_boolean = BooleanVar( description="Use the checkbox to toggle true/false") my_object = ObjectVar(description="Select a NetBox site", queryset=Site.objects.all()) def run(self, data): self.log_info("Your string was {}".format(data['my_string1'])) self.log_info("Your second string was {}".format(data['my_string2'])) self.log_info("Your number was {}".format(data['my_number'])) if data['my_boolean']: self.log_info("You ticked the checkbox") else: self.log_info("You did not tick the checkbox") self.log_info("You chose the sites {}".format(data['my_object'])) return "Here's some output"
class TestScript(Script): class Meta: name = "Test script" var1 = StringVar() var2 = IntegerVar() var3 = BooleanVar() def run(self, data, commit=True): self.log_info(data['var1']) self.log_success(data['var2']) self.log_failure(data['var3']) return 'Script complete'
class NewVM(Script): class Meta: name = "New VM" description = "Create a new VM" field_order = [ 'vm_name', 'dns_name', 'primary_ip4', 'primary_ip6', #'vrf', 'role', 'status', 'cluster', #'tenant', 'platform', 'interface_name', 'mac_address', 'vcpus', 'memory', 'disk', 'comments' ] vm_name = StringVar(label="VM name") dns_name = StringVar(label="DNS name", required=False) primary_ip4 = IPAddressWithMaskVar(label="IPv4 address") primary_ip6 = IPAddressWithMaskVar(label="IPv6 address", required=False) #vrf = ObjectVar(VRF.objects, 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) 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): if not addr: return if addr.version != expect_family: raise RuntimeError("Wrong family for %r" % a) 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 "")) setattr(vm, "primary_ip%d" % a.family, a) add_addr(data["primary_ip4"], 4) add_addr(data["primary_ip6"], 6) vm.save() self.log_success("Created VM %s" % vm.name)
class MultiConnect(Script): class Meta: name = "Multi Connect" description = "Add multiple connections from one device to another" device_a = ObjectVar(model=Device, label="Device A") termination_type_a = ChoiceVar(choices=TERM_CHOICES, label="Device A port type") termination_name_a = StringVar(label="Device A port name pattern", description="Example: ge-0/0/[5,7,12-23]") device_b = ObjectVar(model=Device, label="Device B") termination_type_b = ChoiceVar(choices=TERM_CHOICES, label="Device B port type") termination_name_b = StringVar(label="Device B port name pattern", description="Example: ge-0/0/[5,7,12-23]") cable_status = ChoiceVar(choices=LinkStatusChoices.CHOICES, default=LinkStatusChoices.STATUS_CONNECTED, label="Cable Status") cable_type = ChoiceVar(choices=NO_CHOICE + CableTypeChoices.CHOICES, required=False, label="Cable Type") cable_tenant = ObjectVar(model=Tenant, required=False, label="Cable Tenant") cable_label = StringVar(label="Cable Label pattern", required=False) cable_color = ChoiceVar(choices=NO_CHOICE + ColorChoices.CHOICES, required=False, label="Cable Color") cable_length = IntegerVar( required=False, label="Cable Length") # unfortunately there is no DecimalVar cable_length_unit = ChoiceVar(choices=NO_CHOICE + CableLengthUnitChoices.CHOICES, required=False, label="Cable Length Unit") cable_tags = MultiObjectVar(model=Tag, required=False, label="Cable Tags") def run(self, data, commit): device_a = data["device_a"] device_b = data["device_b"] ports_a = getattr(device_a, data["termination_type_a"]).all() ports_b = getattr(device_b, data["termination_type_b"]).all() terms_a = expand_pattern(data["termination_name_a"]) terms_b = expand_pattern(data["termination_name_b"]) if len(terms_a) != len(terms_b): return self.log_failure( f'Mismatched number of ports: {len(terms_a)} (A) versus {len(terms_b)} (B)' ) labels = expand_pattern(data["cable_label"]) if len(labels) == 1: labels = [labels[0] for i in range(len(terms_a))] elif len(labels) != len(terms_a): return self.log_failure( f'Mismatched number of labels: {len(labels)} labels versus {len(terms_a)} ports' ) for i in range(len(terms_a)): term_a = [x for x in ports_a if x.name == terms_a[i]] if len(term_a) != 1: self.log_failure( f'Unable to find "{terms_a[i]}" in {data["termination_type_a"]} on device A ({device_a.name})' ) continue term_b = [x for x in ports_b if x.name == terms_b[i]] if len(term_b) != 1: self.log_failure( f'Unable to find "{terms_b[i]}" in {data["termination_type_b"]} on device B ({device_b.name})' ) continue cable = Cable( termination_a=term_a[0], termination_b=term_b[0], type=data["cable_type"], status=data["cable_status"], tenant=data["cable_tenant"], label=labels[i], color=data["cable_color"], length=data["cable_length"], length_unit=data["cable_length_unit"], ) try: with transaction.atomic(): cable.full_clean() cable.save() cable.tags.set(data["cable_tags"]) except Exception as e: self.log_failure( f'Unable to connect {device_a.name}:{terms_a[i]} to {device_b.name}:{terms_b[i]}: {e}' ) continue self.log_success( f'Created cable from {device_a.name}:{terms_a[i]} to {device_b.name}:{terms_b[i]}' )
class NewVM(Script): class Meta: name = "New VM" description = "Create a new VM" field_order = [ 'vm_name', 'dns_name', 'primary_ip4', 'primary_ip6', #'vrf', 'role', 'status', 'cluster', #'tenant', 'platform', 'interface_name', 'mac_address', 'vcpus', 'memory', 'disk', 'comments', 'pve_host' ] vm_name = StringVar(label="VM name") dns_name = StringVar(label="DNS name", required=False) primary_ip4 = IPAddressWithMaskVar(label="IPv4 address") # primary_ip6 = IPAddressWithMaskVar(label="IPv6 address", required=False) # vrf = ObjectVar(VRF.objects, required=False) role = ObjectVar(DeviceRole.objects.filter(vm_role=True), required=False, default=8) 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=True) memory = IntegerVar(label="Memory (MB)", required=True) disk = IntegerVar(label="Disk (GB)", required=True) comments = TextVar(label="Comments", required=False) # pve_host = ObjectVar(Device.objects.filter(cluster__name='Newtelco Cluster'), label="Proxmox Host", required=True) PVE_DEVICES = (('nt-pve', 'nt-pve'), ('nt-pve2', 'nt-pve2'), ('nt-pve5', 'nt-pve5'), ('nt-pve6', 'nt-pve6')) pve_host = ChoiceVar(choices=PVE_DEVICES) # pve_host_ip=Device.objects.filter(name=pve_host) def run(self, data, commit): pve_host = Device.objects.filter(name=data["pve_host"]) vm = VirtualMachine( name=data["vm_name"], role=data["role"], status=data["status"], vcpus=data["vcpus"], memory=data["memory"], disk=data["disk"], comments=data["comments"], ) if commit: vm.save() interface = Interface( name=data["interface_name"], type=InterfaceTypeChoices.TYPE_VIRTUAL, virtual_machine=vm, ) if commit: interface.save() def add_addr(addr, expect_family): if not addr: return if addr.version != expect_family: raise RuntimeError("Wrong family for %r" % a) try: a = IPAddress.objects.get( address=addr, family=addr.version, vrf=data.get("vrf"), ) result = "Assigned" except ObjectDoesNotExist: a = IPAddress( address=addr, family=addr.version, 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 "")) setattr(vm, "primary_ip%d" % a.family, a) def connect_pve(addr): self.log_info(addr) proxmox = ProxmoxAPI( addr, user='******', token_name='nb1', token_value='0cf6ab07-ff7e-41a3-80e4-e09e7fea6c7d', verify_ssl=False) self.log_success(proxmox.nodes.get()) # self.log_info(data["pve_host"]) pve_ip = str(pve_host.get().primary_ip4)[:-3] self.log_info(pve_ip) connect_pve(pve_ip) if commit: add_addr(data["primary_ip4"], 4) # add_addr(data["primary_ip6"], 6) vm.save() self.log_success("Created VM %s" % vm.name) else: self.log_success("Dry-run Success - Created VM %s" % vm.name)
class NewVM(Script): class Meta: name = "New VM" description = "Create a new VM" vm_name = StringVar(label="VM name") dns_name = StringVar(label="DNS name", required=False) vm_tags = MultiObjectVar(model=Tag, label="VM tags", required=False) primary_ip4 = IPAddressWithMaskVar(label="IPv4 address") #primary_ip4_tags = MultiObjectVar(model=Tag, label="IPv4 tags", required=False) primary_ip6 = IPAddressWithMaskVar(label="IPv6 address", required=False) #primary_ip6_tags = MultiObjectVar(model=Tag, label="IPv6 tags", required=False) #vrf = ObjectVar(model=VRF, required=False) role = ObjectVar(model=DeviceRole, query_params=dict(vm_role=True), required=False) status = ChoiceVar(VirtualMachineStatusChoices, default=VirtualMachineStatusChoices.STATUS_ACTIVE) cluster = ObjectVar(model=Cluster) tenant = ObjectVar(model=Tenant, required=False) platform = ObjectVar(model=Platform, 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) def run(self, data, commit): 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.full_clean() vm.save() vm.tags.set(data["vm_tags"]) vminterface = VMInterface( name=data["interface_name"], mac_address=data["mac_address"], virtual_machine=vm, ) vminterface.full_clean() vminterface.save() def add_addr(addr, family): if not addr: return if addr.version != family: raise RuntimeError(f"Wrong family for {a}") 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.assigned_object: raise RuntimeError(f"Address {addr} is already assigned") a.assigned_object = vminterface a.tenant = data.get("tenant") a.full_clean() a.save() #a.tags.set(data[f"primary_ip{family}_tags"]) self.log_info(f"{result} IP address {a.address} {a.vrf or ''}") setattr(vm, f"primary_ip{family}", a) add_addr(data["primary_ip4"], 4) add_addr(data["primary_ip6"], 6) vm.full_clean() vm.save() self.log_success( f"Created VM [{vm.name}](/virtualization/virtual-machines/{vm.id}/)" )