netbox icon indicating copy to clipboard operation
netbox copied to clipboard

Custom Scripts - Module & Script Attributes

Open Arshnika opened this issue 1 year ago • 4 comments
trafficstars

Deployment Type

Self-hosted

NetBox Version

v4.0.0

Python Version

3.10

Steps to Reproduce

  1. Create a custom script module including multiple scripts
  2. Define a "name" for the module
  3. Define a "name" and "description" for the scripts.
  4. Add the script module to NetBox

Expected Behavior

When the script module is added, NetBox should reflect all configured attributes on the GUI interface.

image

Observed Behavior

  • NetBox uses the script module file name as the name instead of the defined "name" attribute
  • NetBox uses the script class name as the name of the script instead of the defined "name" attribute
  • NetBox does not show the defined "description" attribute.

Custom_Scripts

Arshnika avatar May 09 '24 02:05 Arshnika

Please share a sample script code for us to reproduce this.

abhi1693 avatar May 09 '24 07:05 abhi1693

@abhi1693,

#!/usr/bin/env python3
from typing import Protocol
from extras.scripts import *
from extras.models import Tag
from dcim.choices import DeviceStatusChoices, SiteStatusChoices
from ipam.choices import PrefixStatusChoices, VLANStatusChoices
from ipam.models import IPAddress, Prefix, VLAN
from circuits.choices import CircuitStatusChoices
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site, Region, Interface, SiteGroup
from dcim.utils import ContentType
from tenancy.models import Tenant, Contact, ContactAssignment
from timezone_field import TimeZoneField, TimeZoneFormField
from django.utils.text import slugify
from django.forms import PasswordInput
from utilities import querysets
from extras.models import Tag
from circuits.models import Provider, CircuitType, Circuit, CircuitTermination
from meraki.exceptions import APIError

class Meraki_Get_CDP_LLDP_Neighbors(Script):

    class Meta:
            name = 'Get CDP/LLDP Neighbors'
            description = 'Get CDP/LLDP neighbors from Meraki Dashboard API'
            commit_default = False
            #field_order = ['site_name', 'switch_count', 'switch_model']

    #-----------------------------------------------------------
    #--- Get Values from HTML Form -----------------------------
    #-----------------------------------------------------------

    Store_Name = ObjectVar(model=Site, label='Store Name:')
    Protocols = (
        ('lldp', 'LLDP'),
        ('cdp', 'CDP'),
    )
    Protocol = ChoiceVar(choices=Protocols)

    def run(self, data, commit):
        
        import pynetbox
        import meraki
        import requests
        import os
        from dotenv import load_dotenv
        requests.packages.urllib3.disable_warnings()

        directory = os.path.dirname(os.path.abspath(__file__))
        dotenv_path = directory + '/.env'
        load_dotenv(dotenv_path)
        API_KEY_Meraki = os.environ.get("meraki_api", "default")
        API_KEY_NetBox = os.environ.get("netbox_api", "default")

        def printNei(m, serial, name, protocol):

            #----------------------------------------------------------
            #---- Print device neighbors. -----------------------------
            #---- Filters per protocol if protocol is provided. -------
            #----------------------------------------------------------
            
            CDP_Neighbors = ''
            LLDP_Neighbors = ''

            dp = m.devices.getDeviceLldpCdp(serial)
            for port in dp.get("ports", []):
                for proto in dp.get("ports").get(port):
                    nei = dp.get("ports").get(port).get(proto)
                    ip = nei.get("address", nei.get("managementAddress"))
                    if proto == "cdp" and protocol != "lldp":
                        systemName = nei.get("deviceId", "noname")
                        CDP_Neighbors += f'{proto.upper():4} LOCAL {name[:35]:35} SOURCE-PORT {nei.get("sourcePort"):8} REMOTE DEVICE {systemName.split(".")[0][:45]:45} REMOTE PORT {nei.get("portId"):24} REMOTE IP {ip}'
                        CDP_Neighbors += '\n'
                    elif proto == "lldp" and protocol != "cdp":
                        systemName = nei.get("systemName", "noname")
                        LLDP_Neighbors += f'{proto.upper():4} LOCAL {name[:35]:35} SOURCE-PORT {nei.get("sourcePort"):8} REMOTE DEVICE {systemName.split(".")[0][:45]:45} REMOTE PORT {nei.get("portId"):24} REMOTE IP {ip}'
                        LLDP_Neighbors += '\n'
            
            if protocol == 'cdp':
                return CDP_Neighbors
            else:
                return LLDP_Neighbors

        def main():

            org_id = '602356450160806405'
            protocol = data['Protocol']
            store_name = str(data['Store_Name'])

            nb = pynetbox.api (
                'https://netbox.sul.local',
                token=API_KEY_NetBox,
                threading = True,
            )
            nb.http_session.verify = False

            m = meraki.DashboardAPI(API_KEY_Meraki,suppress_logging=True)
            org_networks = m.organizations.getOrganizationNetworks(org_id)

            nb_site = nb.dcim.sites.get(name=store_name)
            nb_mer_sitename = nb_site.custom_fields['meraki_sitename']

            Neighbors = ''
            for net in org_networks:
                mer_netid = net['id']
                mer_sitename = net['name'][+9:]
                
                if mer_sitename == nb_mer_sitename:
                    mer_devices = m.networks.getNetworkDevices(mer_netid)
                    for mer_device in mer_devices:
                        serial, name = mer_device.get("serial"), mer_device.get(
                            "name", mer_device.get("serial", "MISSING")
                        )
                        Neighbors += printNei(m, serial, name, protocol)
                    break
            
            if Neighbors == '':
                Neighbors = 'Operation was not completed.\nEither the Meraki sitename is not the same as the Meraki sitename in NetBox or the Meraki site has not been created in NetBox.'
            return Neighbors
            
        return main()

Arshnika avatar May 10 '24 04:05 Arshnika

Hi @abhi1693,

BTW, we have also upgraded NetBox to version 4.0.1 but to no avail.

Arshnika avatar May 10 '24 04:05 Arshnika

Hi @abhi1693,

Just wondering whether you have been able to find the root cause of the issue?

Thanks.

Arshnika avatar May 13 '24 01:05 Arshnika

We just updated to v4.0.2 and are facing the same issue. Neither the modules name attribute nor the scripts Meta name and description value are used.

hendrikbl avatar May 15 '24 09:05 hendrikbl

@arthanson please update the status & severity for this bug report.

jeremystretch avatar May 22 '24 13:05 jeremystretch