NETBOX - NetBox VLAN Device List Discovery.sh
From IT-Arts.net
NetBox_VLAN_Device_List_Discovery.sh
#!/usr/bin/env bash
#
# THIS SCRIPT EXTRACT ALL HOST/INTERFACES CONFIGURED WITH GIVEN VLAN
#
# THIS SCRIPT NEED BASH 4+ AND JQ
# NETBOX VERSION 4.6.x
#
########################################################################
set -euo pipefail
# =========================
# USAGE FUNCTION
# =========================
usage() {
echo "USAGE: $0 -h <FQDN> -t <TOKEN> -v <VLAN_VID1> <VLAN_VID2>... [-d]"
echo "-h : FQDN OF NETBOX INSTANCE"
echo "-t : API TOKEN FOR AUTHENTICATION"
echo "-v : LIST OF VLAN VIDS TO SEARCH (NOT VLAN IDs)"
echo "-d : ENABLE DEBUG OUTPUT"
exit 1
}
# =========================
# INPUT VARIABLES
# =========================
HOST="" # NETBOX FQDN (WITHOUT HTTPS PREFIX)
TOKEN="" # NETBOX API TOKEN
DEBUG=0 # DEBUG MODE FLAG (0=OFF, 1=ON)
VIDS=() # LIST OF VLAN VIDS PASSED BY USER
# =========================
# ARGUMENT PARSING
# =========================
while [[ $# -gt 0 ]]; do
case "$1" in
-h) HOST="${2:-}"; shift 2 ;; # SET NETBOX HOST
-t) TOKEN="${2:-}"; shift 2 ;; # SET API TOKEN
-v)
shift
# COLLECT MULTIPLE VLAN VIDS UNTIL NEXT OPTION
while [[ $# -gt 0 && "$1" != -* ]]; do
VIDS+=("$1")
shift
done
;;
-d) DEBUG=1; shift ;; # ENABLE DEBUG MODE
*) usage ;; # INVALID OPTION
esac
done
# ENSURE REQUIRED PARAMETERS ARE PRESENT
[[ -z "$HOST" || -z "$TOKEN" || ${#VIDS[@]} -eq 0 ]] && usage
# =========================
# API CONFIGURATION
# =========================
API="https://${HOST}/api"
AUTH="Authorization: Token ${TOKEN}"
# =========================
# API CALL WRAPPER FUNCTION
# =========================
api() {
local url="$1"
# DEBUG OUTPUT FOR API CALLS
[[ $DEBUG -eq 1 ]] && echo "[DEBUG] GET $url" >&2
# PERFORM REQUEST
resp=$(curl -sS -H "$AUTH" -H "Accept: application/json" "$url")
# VALIDATE JSON RESPONSE
echo "$resp" | jq -e . >/dev/null 2>&1 || {
echo "[ERROR] INVALID JSON RESPONSE: $url" >&2
echo "$resp" | head -n 10 >&2
return 1
}
echo "$resp"
}
# =========================
# OUTPUT HEADER
# =========================
echo "DEVICE, VLAN VID, VLAN NAME, INTERFACE, MODE, INTERFACE DESCRIPTION"
# PRELOAD ALL INTERFACES ONCE (PERFORMANCE OPTIMIZATION)
interfaces=$(api "${API}/dcim/interfaces/?limit=1000")
# =========================
# MAIN PROCESS LOOP
# =========================
for vid in "${VIDS[@]}"; do
# FETCH VLAN OBJECTS MATCHING GIVEN VID
vlan_json=$(api "${API}/ipam/vlans/?vid=${vid}&limit=1000")
# COUNT HOW MANY VLAN OBJECTS MATCH THIS VID
vlan_count=$(echo "$vlan_json" | jq '.results | length')
# IF NO VLAN FOUND, REPORT IT
if [[ "$vlan_count" -eq 0 ]]; then
echo "VLAN ${vid} IS NOT PRESENT"
continue
fi
# LOOP THROUGH ALL VLAN OBJECTS (IMPORTANT: SAME VID CAN HAVE MULTIPLE VLANS)
echo "$vlan_json" | jq -c '.results[]' | while read -r vlan; do
# EXTRACT VLAN INTERNAL ID (NETBOX OBJECT ID)
vlan_id=$(echo "$vlan" | jq -r '.id')
# EXTRACT VLAN NAME
vlan_name=$(echo "$vlan" | jq -r '.name')
# DEBUG INFO PER VLAN OBJECT
[[ $DEBUG -eq 1 ]] && echo "[DEBUG] VID=$vid VLAN_ID=$vlan_id NAME=$vlan_name" >&2
# PROCESS ALL INTERFACES AGAINST THIS VLAN OBJECT
echo "$interfaces" | jq -r \
--arg vid "$vid" \
--arg vlan_id "$vlan_id" \
--arg name "$vlan_name" '
.results[] |
# DEVICE NAME
.device.name as $device |
# INTERFACE NAME
.name as $iface |
# INTERFACE DESCRIPTION (DEFAULT IF EMPTY)
(.description // "—") as $desc |
# LIST OF TAGGED VLANS ON INTERFACE
(.tagged_vlans // []) as $tagged_list |
# CHECK IF CURRENT VLAN IS TAGGED
($tagged_list | map(.id | tostring) | index($vlan_id)) as $is_tagged |
# CHECK IF CURRENT VLAN IS UNTAGGED
(.untagged_vlan?.id | tostring == $vlan_id) as $is_untagged |
# OUTPUT FORMATTING
if $is_tagged then
"\($device), \($vid), \($name), \($iface), TAGGED, \($desc)"
elif $is_untagged then
"\($device), \($vid), \($name), \($iface), UNTAGGED, \($desc)"
else
empty
end
'
done
done | sort -u
