diff --git a/plugins/NetBox/v1/configValidation.json b/plugins/NetBox/v1/configValidation.json new file mode 100644 index 00000000..9371c98c --- /dev/null +++ b/plugins/NetBox/v1/configValidation.json @@ -0,0 +1,18 @@ +{ + "steps": [ + { + "displayName": "Authenticate", + "dataStream": { "name": "status" }, + "required": true, + "error": "Could not connect to NetBox. Check the NetBox URL is reachable, the API token is valid and enabled, and that any allowed IP restriction on the token permits SquaredUp.", + "success": "Connected to NetBox successfully." + }, + { + "displayName": "Check data access", + "dataStream": { "name": "sites" }, + "required": false, + "error": "Connected, but no sites were returned. Check the token's user has view permission on DCIM objects.", + "success": "Sites are accessible." + } + ] +} diff --git a/plugins/NetBox/v1/custom_types.json b/plugins/NetBox/v1/custom_types.json new file mode 100644 index 00000000..7c3da58f --- /dev/null +++ b/plugins/NetBox/v1/custom_types.json @@ -0,0 +1,44 @@ +[ + { + "name": "Site", + "sourceType": "Site", + "icon": "building", + "singular": "Site", + "plural": "Sites" + }, + { + "name": "Rack", + "sourceType": "Rack", + "icon": "server", + "singular": "Rack", + "plural": "Racks" + }, + { + "name": "Device", + "sourceType": "Device", + "icon": "network-wired", + "singular": "Device", + "plural": "Devices" + }, + { + "name": "Virtual Machine", + "sourceType": "Virtual Machine", + "icon": "cube", + "singular": "Virtual Machine", + "plural": "Virtual Machines" + }, + { + "name": "Prefix", + "sourceType": "Prefix", + "icon": "sitemap", + "singular": "Prefix", + "plural": "Prefixes" + }, + { + "name": "Circuit", + "sourceType": "Circuit", + "icon": "route", + "singular": "Circuit", + "plural": "Circuits" + } +] diff --git a/plugins/NetBox/v1/dataStreams/circuits.json b/plugins/NetBox/v1/dataStreams/circuits.json new file mode 100644 index 00000000..5e4cce84 --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/circuits.json @@ -0,0 +1,150 @@ +{ + "name": "circuits", + "displayName": "Circuits", + "description": "All circuits with provider, type, status, commit rate and contract dates", + "tags": [ + "Network", + "Inventory" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/circuits/circuits/", + "getArgs": [ + { + "key": "fields", + "value": "id,cid,display,display_url,provider,provider_account,type,status,tenant,install_date,termination_date,commit_rate,description,termination_a,termination_z,created,last_updated,custom_fields" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "limit", + "value": "250" + }, + "offset": { + "mode": "row", + "rowCountIn": { + "realm": "payloadArraySize", + "path": "results" + }, + "base": 0 + }, + "out": { + "realm": "queryArg", + "path": "offset" + } + }, + "pathToData": "results", + "expandInnerObjects": true + }, + "matches": "none", + "metadata": [ + { + "name": "id", + "visible": false + }, + { + "name": "cid", + "displayName": "Circuit ID", + "shape": "string", + "role": "label" + }, + { + "name": "provider.name", + "displayName": "Provider", + "shape": "string" + }, + { + "name": "provider_account.name", + "displayName": "Provider Account", + "shape": "string" + }, + { + "name": "type.name", + "displayName": "Type", + "shape": "string" + }, + { + "name": "status.label", + "displayName": "Status", + "shape": "string" + }, + { + "name": "status.value", + "visible": false + }, + { + "name": "tenant.name", + "displayName": "Tenant", + "shape": "string" + }, + { + "name": "commit_rate", + "displayName": "Commit Rate", + "shape": "kilobitspersecond" + }, + { + "name": "termination_a.termination.display", + "displayName": "Termination A", + "shape": "string" + }, + { + "name": "termination_z.termination.display", + "displayName": "Termination Z", + "shape": "string" + }, + { + "name": "install_date", + "displayName": "Install Date", + "shape": "date" + }, + { + "name": "termination_date", + "displayName": "Termination Date", + "shape": "date" + }, + { + "name": "daysUntilTermination", + "displayName": "Days Until Termination", + "shape": "number", + "computed": true, + "valueExpression": "{{ typeof $['termination_date'] === 'string' && $['termination_date'] ? Math.ceil((new Date($['termination_date']).getTime() - Date.now()) / 86400000) : null }}" + }, + { + "name": "description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "created", + "displayName": "Created", + "shape": "date" + }, + { + "name": "last_updated", + "displayName": "Last Updated", + "shape": "date" + }, + { + "name": "display_url", + "displayName": "Link", + "shape": [ + "url", + { + "label": "Open in NetBox" + } + ] + }, + { + "sourceId": "id", + "sourceType": "Circuit", + "name": "cid" + }, + { + "pattern": "^custom_fields[.].*" + } + ], + "timeframes": false +} diff --git a/plugins/NetBox/v1/dataStreams/deviceInterfaces.json b/plugins/NetBox/v1/dataStreams/deviceInterfaces.json new file mode 100644 index 00000000..2b89e30c --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/deviceInterfaces.json @@ -0,0 +1,205 @@ +{ + "name": "deviceInterfaces", + "displayName": "Device Interfaces", + "description": "Interfaces on a device with type, state, speed, VLAN mode, cabling and connection", + "tags": [ + "Network", + "Inventory" + ], + "baseDataSourceName": "httpRequestScoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/dcim/interfaces/", + "getArgs": [ + { + "key": "device_id", + "value": "{{ objects.map(o => o.rawId) }}" + }, + { + "key": "fields", + "value": "id,display,display_url,device,name,label,type,enabled,mgmt_only,mtu,speed,duplex,mode,mac_address,primary_mac_address,lag,parent,untagged_vlan,tagged_vlans,vrf,cable,mark_connected,link_peers,connected_endpoints,connected_endpoints_reachable,count_ipaddresses,description,last_updated" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "limit", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "results" + } + }, + "out": { + "realm": "queryArg", + "path": "offset" + } + }, + "pathToData": "results", + "expandInnerObjects": true + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Device" + ] + } + }, + "metadata": [ + { + "name": "id", + "visible": false + }, + { + "pattern": "^(link_peers|connected_endpoints|tagged_vlans)[.].*", + "visible": false + }, + { + "name": "display", + "visible": false + }, + { + "name": "device.name", + "displayName": "Device", + "shape": "string" + }, + { + "name": "name", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "label", + "displayName": "Label", + "shape": "string" + }, + { + "name": "type.label", + "displayName": "Type", + "shape": "string" + }, + { + "name": "enabled", + "displayName": "Enabled", + "shape": "boolean" + }, + { + "name": "mgmt_only", + "displayName": "Management Only", + "shape": "boolean" + }, + { + "name": "speed", + "displayName": "Speed", + "shape": "kilobitspersecond" + }, + { + "name": "mtu", + "displayName": "MTU", + "shape": "number" + }, + { + "name": "duplex.label", + "displayName": "Duplex", + "shape": "string" + }, + { + "name": "mode.label", + "displayName": "VLAN Mode", + "shape": "string" + }, + { + "name": "primary_mac_address.mac_address", + "visible": false + }, + { + "name": "mac_address", + "displayName": "MAC Address", + "shape": "string", + "valueExpression": "{{ typeof $['primary_mac_address.mac_address'] === 'string' && $['primary_mac_address.mac_address'] ? $['primary_mac_address.mac_address'] : (typeof $['mac_address'] === 'string' && $['mac_address'] ? $['mac_address'] : null) }}" + }, + { + "name": "lag.name", + "displayName": "LAG", + "shape": "string" + }, + { + "name": "parent.name", + "displayName": "Parent Interface", + "shape": "string" + }, + { + "name": "untagged_vlan.display", + "displayName": "Untagged VLAN", + "shape": "string" + }, + { + "name": "taggedVlanCount", + "displayName": "Tagged VLANs", + "shape": "number", + "computed": true, + "valueExpression": "{{ Object.keys($).filter(k => k.startsWith('tagged_vlans.') && k.endsWith('.id') && k.split('.').length === 3 && typeof $[k] === 'number').length }}" + }, + { + "name": "vrf.name", + "displayName": "VRF", + "shape": "string" + }, + { + "name": "cable.id", + "visible": false + }, + { + "name": "cabled", + "displayName": "Cabled", + "shape": "boolean", + "computed": true, + "valueExpression": "{{ typeof $['cable.id'] === 'number' }}" + }, + { + "name": "connectedTo", + "displayName": "Connected To", + "shape": "string", + "computed": true, + "valueExpression": "{{ (() => { for (const p of ['connected_endpoints', 'link_peers']) { const out = []; for (let i = 0; i < 20; i++) { const n = $[p + '.' + i + '.name']; const d = $[p + '.' + i + '.display']; const label = typeof n === 'string' && n ? n : (typeof d === 'string' && d ? d : null); if (!label) continue; const dev = $[p + '.' + i + '.device.name']; out.push(typeof dev === 'string' && dev ? dev + ' ' + label : label); } if (out.length) return out.join(', '); } return null; })() }}" + }, + { + "name": "connected_endpoints_reachable", + "displayName": "Reachable", + "shape": "boolean" + }, + { + "name": "count_ipaddresses", + "displayName": "IP Addresses", + "shape": "number" + }, + { + "name": "description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "last_updated", + "displayName": "Last Updated", + "shape": "date" + }, + { + "name": "display_url", + "displayName": "Link", + "shape": [ + "url", + { + "label": "Open in NetBox" + } + ] + } + ], + "timeframes": false +} diff --git a/plugins/NetBox/v1/dataStreams/deviceRoles.json b/plugins/NetBox/v1/dataStreams/deviceRoles.json new file mode 100644 index 00000000..85a51781 --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/deviceRoles.json @@ -0,0 +1,63 @@ +{ + "name": "deviceRoles", + "displayName": "Device Roles", + "description": "Device roles as label and slug pairs", + "tags": [ + "Inventory" + ], + "visibility": { + "type": "hidden" + }, + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/dcim/device-roles/", + "getArgs": [ + { + "key": "fields", + "value": "id,name,slug" + }, + { + "key": "ordering", + "value": "name" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "limit", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "results" + } + }, + "out": { + "realm": "queryArg", + "path": "offset" + } + }, + "postRequestScript": "deviceRoles.js" + }, + "matches": "none", + "metadata": [ + { + "name": "label", + "displayName": "Label", + "shape": "string", + "role": "label" + }, + { + "name": "value", + "displayName": "Value", + "shape": "string", + "role": "value" + } + ], + "timeframes": false +} diff --git a/plugins/NetBox/v1/dataStreams/devices.json b/plugins/NetBox/v1/dataStreams/devices.json new file mode 100644 index 00000000..b51378cb --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/devices.json @@ -0,0 +1,283 @@ +{ + "name": "devices", + "displayName": "Devices", + "description": "All devices with status, role, hardware, location, ownership and data quality flags", + "tags": [ + "Inventory", + "Network" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/dcim/devices/", + "getArgs": [ + { + "key": "fields", + "value": "id,display,display_url,status,role,device_type,platform,site,location,rack,position,face,serial,asset_tag,tenant,primary_ip,oob_ip,cluster,parent_device,description,created,last_updated,custom_fields" + }, + { + "key": "site_id", + "value": "{{ (typeof site !== 'undefined' && site && site.length) ? site.map(s => [].concat(s.rawId)[0]) : null }}" + }, + { + "key": "rack_id", + "value": "{{ (typeof rack !== 'undefined' && rack && rack.length) ? rack.map(o => [].concat(o.rawId)[0]) : null }}" + }, + { + "key": "role", + "value": "{{ (typeof role !== 'undefined' && role && role.length) ? [].concat(role).flatMap(r => (r && typeof r === 'object') ? [r.value] : String(r).split(',')).map(r => String(r).trim()).filter(Boolean) : null }}" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "limit", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "results" + } + }, + "out": { + "realm": "queryArg", + "path": "offset" + } + }, + "pathToData": "results", + "expandInnerObjects": true + }, + "matches": "none", + "ui": [ + { + "type": "objects", + "name": "site", + "label": "Site (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Site" + ] + } + } + }, + { + "type": "objects", + "name": "rack", + "label": "Rack (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Rack" + ] + } + } + }, + { + "type": "autocomplete", + "name": "role", + "label": "Role(s) (optional)", + "isMulti": true, + "allowCustomValues": true, + "data": { + "source": "dataStream", + "dataStreamName": "deviceRoles", + "dataSourceConfig": {} + } + } + ], + "metadata": [ + { + "name": "id", + "visible": false + }, + { + "name": "display", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "status.label", + "displayName": "Status", + "shape": "string" + }, + { + "name": "status.value", + "visible": false + }, + { + "name": "role.name", + "displayName": "Role", + "shape": "string" + }, + { + "name": "device_type.manufacturer.name", + "displayName": "Manufacturer", + "shape": "string" + }, + { + "name": "device_type.model", + "displayName": "Device Type", + "shape": "string" + }, + { + "name": "platform.name", + "displayName": "Platform", + "shape": "string" + }, + { + "name": "site.name", + "displayName": "Site", + "shape": "string" + }, + { + "name": "site.id", + "visible": false + }, + { + "name": "site.url", + "visible": false, + "valueExpression": "{{ typeof $['site.id'] === 'number' ? String($['site.id']) : null }}" + }, + { + "name": "location.name", + "displayName": "Location", + "shape": "string" + }, + { + "name": "rack.name", + "displayName": "Rack", + "shape": "string" + }, + { + "name": "rack.id", + "visible": false + }, + { + "name": "rack.url", + "visible": false, + "valueExpression": "{{ typeof $['rack.id'] === 'number' ? String($['rack.id']) : null }}" + }, + { + "name": "position", + "displayName": "Position (U)", + "shape": "number" + }, + { + "name": "tenant.name", + "displayName": "Tenant", + "shape": "string" + }, + { + "name": "serial", + "displayName": "Serial Number", + "shape": "string" + }, + { + "name": "asset_tag", + "displayName": "Asset Tag", + "shape": "string" + }, + { + "name": "primary_ip.address", + "visible": false + }, + { + "name": "primary_ip.display", + "displayName": "Primary IP", + "shape": "string", + "valueExpression": "{{ typeof $['primary_ip.address'] === 'string' && $['primary_ip.address'] ? $['primary_ip.address'].split('/')[0] : null }}" + }, + { + "name": "oob_ip.address", + "displayName": "OOB IP", + "shape": "string" + }, + { + "name": "cluster.name", + "displayName": "Cluster", + "shape": "string" + }, + { + "name": "parent_device.name", + "displayName": "Parent Device", + "shape": "string" + }, + { + "name": "description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "created", + "displayName": "Created", + "shape": "date" + }, + { + "name": "last_updated", + "displayName": "Last Updated", + "shape": "date" + }, + { + "name": "missingSerial", + "displayName": "Missing Serial", + "shape": "boolean", + "computed": true, + "valueExpression": "{{ !(typeof $['serial'] === 'string' && $['serial']) }}" + }, + { + "name": "missingPrimaryIp", + "displayName": "Missing Primary IP", + "shape": "boolean", + "computed": true, + "valueExpression": "{{ !(typeof $['primary_ip.address'] === 'string' && $['primary_ip.address']) }}" + }, + { + "name": "missingTenant", + "displayName": "Missing Tenant", + "shape": "boolean", + "computed": true, + "valueExpression": "{{ !(typeof $['tenant.name'] === 'string' && $['tenant.name']) }}" + }, + { + "name": "missingPlatform", + "displayName": "Missing Platform", + "shape": "boolean", + "computed": true, + "valueExpression": "{{ !(typeof $['platform.name'] === 'string' && $['platform.name']) }}" + }, + { + "name": "daysSinceUpdate", + "displayName": "Days Since Update", + "shape": "number", + "computed": true, + "valueExpression": "{{ typeof $['last_updated'] === 'string' && $['last_updated'] ? Math.floor((Date.now() - new Date($['last_updated']).getTime()) / 86400000) : null }}" + }, + { + "name": "display_url", + "displayName": "Link", + "shape": [ + "url", + { + "label": "Open in NetBox" + } + ] + }, + { + "sourceId": "id", + "sourceType": "Device", + "name": "display" + }, + { + "pattern": "^custom_fields[.].*" + } + ], + "timeframes": false +} diff --git a/plugins/NetBox/v1/dataStreams/graphqlQuery.json b/plugins/NetBox/v1/dataStreams/graphqlQuery.json new file mode 100644 index 00000000..39cbbe31 --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/graphqlQuery.json @@ -0,0 +1,46 @@ +{ + "name": "graphqlQuery", + "displayName": "GraphQL Query", + "description": "Results of a NetBox GraphQL query, one row per item in the first list returned", + "tags": ["Query"], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "post", + "endpointPath": "graphql/", + "headers": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "postBody": { + "query": "{{query}}" + }, + "postRequestScript": "graphqlQuery.js", + "errorHandling": { + "type": "script", + "script": "errorHandling/graphqlQuery.js" + } + }, + "matches": "none", + "manualConfigApply": true, + "ui": [ + { + "type": "code", + "name": "query", + "label": "GraphQL query", + "language": "graphql", + "defaultValue": "{\n power_feed_list {\n name\n status\n rack {\n name\n site {\n name\n }\n }\n custom_field_data\n }\n}", + "validation": { + "required": true + }, + "help": "A NetBox GraphQL query. One row is returned per item in the first list in the response, with nested fields flattened into columns such as `rack.site.name`. Use the GraphiQL explorer at `/graphql/` on your NetBox instance to build and test queries." + } + ], + "metadata": [ + { + "pattern": ".*" + } + ], + "timeframes": false +} diff --git a/plugins/NetBox/v1/dataStreams/ipAddresses.json b/plugins/NetBox/v1/dataStreams/ipAddresses.json new file mode 100644 index 00000000..58e6779f --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/ipAddresses.json @@ -0,0 +1,276 @@ +{ + "name": "ipAddresses", + "displayName": "IP Addresses", + "description": "IP addresses with VRF, status, role, DNS name and assignment", + "tags": [ + "IPAM", + "Network" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/ipam/ip-addresses/", + "getArgs": [ + { + "key": "fields", + "value": "id,address,display,display_url,family,vrf,tenant,status,role,assigned_object_id,assigned_object,dns_name,description,created,last_updated,custom_fields" + }, + { + "key": "assigned", + "value": "{{assignment || null}}" + }, + { + "key": "status", + "value": "{{status || null}}" + }, + { + "key": "parent", + "value": "{{ (typeof prefix !== 'undefined' && prefix && prefix.length) ? [].concat(prefix[0].name)[0] : null }}" + }, + { + "key": "vrf_id", + "value": "{{ (typeof prefix !== 'undefined' && prefix && prefix.length) ? (typeof [].concat(prefix[0].vrfId)[0] !== 'undefined' && [].concat(prefix[0].vrfId)[0] !== null ? [].concat(prefix[0].vrfId)[0] : ([].concat(prefix[0].status)[0] === 'container' ? null : 'null')) : null }}" + }, + { + "key": "device_id", + "value": "{{ (typeof device !== 'undefined' && device && device.length) ? device.map(o => [].concat(o.rawId)[0]) : null }}" + }, + { + "key": "virtual_machine_id", + "value": "{{ (typeof virtualMachine !== 'undefined' && virtualMachine && virtualMachine.length) ? virtualMachine.map(o => [].concat(o.rawId)[0]) : null }}" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "limit", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "results" + } + }, + "out": { + "realm": "queryArg", + "path": "offset" + } + }, + "pathToData": "results", + "expandInnerObjects": true + }, + "matches": "none", + "ui": [ + { + "type": "objects", + "name": "prefix", + "label": "Prefix (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Prefix" + ] + } + } + }, + { + "type": "objects", + "name": "device", + "label": "Device (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Device" + ] + } + } + }, + { + "type": "objects", + "name": "virtualMachine", + "label": "Virtual machine (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Virtual Machine" + ] + } + } + }, + { + "type": "choiceChips", + "name": "assignment", + "label": "Assignment", + "options": [ + { + "value": "true", + "label": "Assigned" + }, + { + "value": "false", + "label": "Unassigned" + } + ] + }, + { + "type": "choiceChips", + "name": "status", + "label": "Status", + "isMulti": true, + "options": [ + { + "value": "active", + "label": "Active" + }, + { + "value": "reserved", + "label": "Reserved" + }, + { + "value": "deprecated", + "label": "Deprecated" + }, + { + "value": "dhcp", + "label": "DHCP" + }, + { + "value": "slaac", + "label": "SLAAC" + } + ] + } + ], + "metadata": [ + { + "name": "id", + "visible": false + }, + { + "name": "address", + "displayName": "Address", + "shape": "string", + "role": "label" + }, + { + "name": "display", + "displayName": "IP", + "shape": "string", + "valueExpression": "{{ typeof $[\"address\"] === \"string\" ? $[\"address\"].split(\"/\")[0] : null }}" + }, + { + "name": "family.label", + "displayName": "Family", + "shape": "string" + }, + { + "name": "family.value", + "visible": false + }, + { + "name": "vrf.name", + "visible": false + }, + { + "name": "vrfName", + "displayName": "VRF", + "shape": "string", + "computed": true, + "valueExpression": "{{ typeof $[\"vrf.name\"] === \"string\" && $[\"vrf.name\"] ? $[\"vrf.name\"] : \"Global\" }}" + }, + { + "name": "status.label", + "displayName": "Status", + "shape": "string" + }, + { + "name": "status.value", + "visible": false + }, + { + "name": "role.label", + "displayName": "Role", + "shape": "string" + }, + { + "name": "tenant.name", + "displayName": "Tenant", + "shape": "string" + }, + { + "name": "dns_name", + "displayName": "DNS Name", + "shape": "string" + }, + { + "name": "assigned_object_id", + "visible": false + }, + { + "name": "assigned_object.name", + "visible": false + }, + { + "name": "assigned_object.display", + "visible": false + }, + { + "name": "assigned_object.device.name", + "visible": false + }, + { + "name": "assigned_object.virtual_machine.name", + "visible": false + }, + { + "name": "assignedTo", + "displayName": "Assigned To", + "shape": "string", + "computed": true, + "valueExpression": "{{ (() => { const s = (v) => typeof v === \"string\" && v ? v : null; const parent = s($[\"assigned_object.device.name\"]) || s($[\"assigned_object.virtual_machine.name\"]); const iface = s($[\"assigned_object.name\"]) || s($[\"assigned_object.display\"]); return parent && iface ? parent + \" / \" + iface : (parent || iface); })() }}" + }, + { + "name": "assigned", + "displayName": "Assigned", + "shape": "boolean", + "computed": true, + "valueExpression": "{{ typeof $[\"assigned_object_id\"] === \"number\" }}" + }, + { + "name": "description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "created", + "displayName": "Created", + "shape": "date" + }, + { + "name": "last_updated", + "displayName": "Last Updated", + "shape": "date" + }, + { + "name": "display_url", + "displayName": "Link", + "shape": [ + "url", + { + "label": "Open in NetBox" + } + ] + }, + { + "pattern": "^custom_fields[.].*" + } + ], + "timeframes": false +} diff --git a/plugins/NetBox/v1/dataStreams/objectChanges.json b/plugins/NetBox/v1/dataStreams/objectChanges.json new file mode 100644 index 00000000..f86446eb --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/objectChanges.json @@ -0,0 +1,209 @@ +{ + "name": "objectChanges", + "displayName": "Change Log", + "description": "Changes recorded in the NetBox change log with user, action and object", + "tags": [ + "Audit", + "Changes" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/core/object-changes/", + "getArgs": [ + { + "key": "fields", + "value": "id,time,user_name,request_id,action,changed_object_type,changed_object_id,object_repr,message" + }, + { + "key": "time_after", + "value": "{{timeframe.start}}" + }, + { + "key": "time_before", + "value": "{{timeframe.end}}" + }, + { + "key": "action", + "value": "{{typeof action !== 'undefined' && action ? action : null}}" + }, + { + "key": "changed_object_type", + "value": "{{(typeof object !== 'undefined' && object && object[0]) ? ({ 'Site': 'dcim.site', 'Rack': 'dcim.rack', 'Device': 'dcim.device', 'Virtual Machine': 'virtualization.virtualmachine', 'Prefix': 'ipam.prefix', 'Circuit': 'circuits.circuit' })[[].concat(object[0].sourceType)[0]] || null : (typeof objectType !== 'undefined' && objectType ? objectType : null)}}" + }, + { + "key": "changed_object_id", + "value": "{{(typeof object !== 'undefined' && object && object[0]) ? [].concat(object[0].rawId)[0] : null}}" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "limit", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "results" + } + }, + "out": { + "realm": "queryArg", + "path": "offset" + } + }, + "pathToData": "results", + "expandInnerObjects": true + }, + "matches": "none", + "ui": [ + { + "type": "objects", + "name": "object", + "label": "Object (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Site", + "Rack", + "Device", + "Virtual Machine", + "Prefix", + "Circuit" + ] + } + } + }, + { + "type": "choiceChips", + "name": "action", + "label": "Action", + "options": [ + { + "value": "create", + "label": "Created" + }, + { + "value": "update", + "label": "Updated" + }, + { + "value": "delete", + "label": "Deleted" + } + ] + }, + { + "type": "choiceChips", + "name": "objectType", + "label": "Object type", + "options": [ + { + "value": "dcim.site", + "label": "Site" + }, + { + "value": "dcim.rack", + "label": "Rack" + }, + { + "value": "dcim.device", + "label": "Device" + }, + { + "value": "virtualization.virtualmachine", + "label": "Virtual Machine" + }, + { + "value": "ipam.prefix", + "label": "Prefix" + }, + { + "value": "circuits.circuit", + "label": "Circuit" + } + ] + } + ], + "metadata": [ + { + "name": "id", + "visible": false + }, + { + "name": "time", + "displayName": "Time", + "shape": "date", + "role": "timestamp" + }, + { + "name": "user_name", + "displayName": "User", + "shape": "string" + }, + { + "name": "action.label", + "displayName": "Action", + "shape": "string" + }, + { + "name": "action.value", + "visible": false + }, + { + "name": "changed_object_type", + "displayName": "Object Type", + "shape": "string", + "formatExpression": "{{ ({ 'dcim.site': 'Site', 'dcim.rack': 'Rack', 'dcim.device': 'Device', 'virtualization.virtualmachine': 'Virtual Machine', 'ipam.prefix': 'Prefix', 'circuits.circuit': 'Circuit' })[$['changed_object_type']] || $['changed_object_type'] }}" + }, + { + "name": "objectTypeName", + "displayName": "Object Type Name", + "shape": "string", + "computed": true, + "visible": false, + "valueExpression": "{{ (() => { const t = $['changed_object_type']; if (typeof t !== 'string') { return null; } const known = { 'dcim.site': 'Site', 'dcim.rack': 'Rack', 'dcim.device': 'Device', 'virtualization.virtualmachine': 'Virtual Machine', 'ipam.prefix': 'Prefix', 'circuits.circuit': 'Circuit' }; return known[t] || t.split('.').pop().replace(/^./, (c) => c.toUpperCase()); })() }}" + }, + { + "name": "object_repr", + "displayName": "Object", + "shape": "string", + "role": "label" + }, + { + "name": "message", + "displayName": "Message", + "shape": "string" + }, + { + "name": "changed_object_id", + "visible": false + }, + { + "name": "request_id", + "visible": false + } + ], + "defaultShaping": { + "sort": { + "by": [ + [ + "time", + "desc" + ] + ] + } + }, + "timeframes": [ + "last1hour", + "last12hours", + "last24hours", + "last7days", + "last30days" + ] +} diff --git a/plugins/NetBox/v1/dataStreams/powerFeeds.json b/plugins/NetBox/v1/dataStreams/powerFeeds.json new file mode 100644 index 00000000..6f3bf107 --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/powerFeeds.json @@ -0,0 +1,222 @@ +{ + "name": "powerFeeds", + "displayName": "Power Feeds", + "description": "Power feeds with their rack, site, panel, electrical rating and available power", + "tags": [ + "Power", + "Capacity" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "post", + "endpointPath": "graphql/", + "headers": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "postBody": { + "query": "query PowerFeeds($offset: Int = 0) { power_feed_list(pagination: { offset: $offset, limit: 500 }{{ (typeof site !== 'undefined' && site && site.length) ? ', filters: { power_panel: { site: { id: { in_list: [' + site.map(s => Number([].concat(s.rawId)[0])).join(', ') + '] } } } }' : '' }}) { id name description status type supply phase voltage amperage max_utilization available_power mark_connected cable { id } tenant { name } rack { id name } power_panel { id name site { id name } } created last_updated custom_field_data } }" + }, + "paging": { + "mode": "offset", + "pageSize": { + "realm": "none" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "data.power_feed_list" + } + }, + "out": { + "realm": "body", + "path": "variables.offset" + } + }, + "postRequestScript": "powerFeeds.js", + "expandInnerObjects": true + }, + "matches": "none", + "ui": [ + { + "type": "objects", + "name": "site", + "label": "Site (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Site" + ] + } + } + } + ], + "metadata": [ + { + "name": "id", + "visible": false + }, + { + "name": "name", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "power_panel.site.name", + "displayName": "Site", + "shape": "string" + }, + { + "name": "rack.name", + "displayName": "Rack", + "shape": "string" + }, + { + "name": "power_panel.name", + "displayName": "Power Panel", + "shape": "string" + }, + { + "name": "status", + "visible": false + }, + { + "name": "statusLabel", + "displayName": "Status", + "shape": "string", + "computed": true, + "valueExpression": "{{ typeof $['status'] === 'string' ? $['status'].charAt(0).toUpperCase() + $['status'].slice(1).replace(/-/g, ' ') : null }}" + }, + { + "name": "type", + "visible": false + }, + { + "name": "typeLabel", + "displayName": "Type", + "shape": "string", + "computed": true, + "valueExpression": "{{ typeof $['type'] === 'string' ? $['type'].charAt(0).toUpperCase() + $['type'].slice(1).replace(/-/g, ' ') : null }}" + }, + { + "name": "supply", + "visible": false + }, + { + "name": "supplyLabel", + "displayName": "Supply", + "shape": "string", + "computed": true, + "valueExpression": "{{ typeof $['supply'] === 'string' ? $['supply'].toUpperCase() : null }}" + }, + { + "name": "phase", + "visible": false + }, + { + "name": "phaseLabel", + "displayName": "Phase", + "shape": "string", + "computed": true, + "valueExpression": "{{ typeof $['phase'] === 'string' ? $['phase'].charAt(0).toUpperCase() + $['phase'].slice(1).replace(/-/g, ' ') : null }}" + }, + { + "name": "voltage", + "displayName": "Voltage (V)", + "shape": "number" + }, + { + "name": "amperage", + "displayName": "Amperage (A)", + "shape": "number" + }, + { + "name": "max_utilization", + "displayName": "Max Utilization", + "shape": "percent" + }, + { + "name": "available_power", + "visible": false + }, + { + "name": "availableKva", + "displayName": "Available Power (kVA)", + "shape": [ + "number", + { + "decimalPlaces": 2 + } + ], + "computed": true, + "valueExpression": "{{ typeof $['available_power'] === 'number' ? Math.round($['available_power'] / 10) / 100 : null }}" + }, + { + "name": "mark_connected", + "visible": false + }, + { + "name": "cable.id", + "visible": false + }, + { + "name": "connected", + "displayName": "Connected", + "shape": "boolean", + "computed": true, + "valueExpression": "{{ $['mark_connected'] === true || typeof $['cable.id'] === 'string' }}" + }, + { + "name": "tenant.name", + "displayName": "Tenant", + "shape": "string" + }, + { + "name": "description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "created", + "displayName": "Created", + "shape": "date" + }, + { + "name": "last_updated", + "displayName": "Last Updated", + "shape": "date" + }, + { + "name": "rack.id", + "visible": false + }, + { + "name": "power_panel.id", + "visible": false + }, + { + "name": "power_panel.site.id", + "visible": false + }, + { + "sourceId": "rack.id", + "sourceType": "Rack", + "name": "rack.name" + }, + { + "sourceId": "power_panel.site.id", + "sourceType": "Site", + "name": "power_panel.site.name" + }, + { + "pattern": "^custom_field_data[.].*" + } + ], + "timeframes": false +} diff --git a/plugins/NetBox/v1/dataStreams/prefixUtilization.json b/plugins/NetBox/v1/dataStreams/prefixUtilization.json new file mode 100644 index 00000000..90687a97 --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/prefixUtilization.json @@ -0,0 +1,133 @@ +{ + "name": "prefixUtilization", + "displayName": "Prefix Utilization", + "description": "IP space utilization per prefix, calculated the same way as NetBox", + "tags": [ + "IPAM", + "Capacity" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "{{ object.status === 'container' ? 'api/ipam/prefixes/' : 'api/ipam/ip-addresses/' }}", + "getArgs": [ + { + "key": "within", + "value": "{{ object.status === 'container' ? object.name : null }}" + }, + { + "key": "parent", + "value": "{{ object.status === 'container' ? null : object.name }}" + }, + { + "key": "vrf_id", + "value": "{{ object.status === 'container' ? (typeof object.vrfId === 'undefined' ? null : object.vrfId) : (typeof object.vrfId === 'undefined' ? 'null' : object.vrfId) }}" + }, + { + "key": "fields", + "value": "{{ object.status === 'container' ? 'prefix' : null }}" + }, + { + "key": "brief", + "value": "{{ object.status === 'container' ? null : 'true' }}" + }, + { + "key": "limit", + "value": "{{ object.status === 'container' ? '1000' : '1' }}" + } + ], + "paging": { + "mode": "none" + }, + "postRequestScript": "prefixUtilization.js" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Prefix" + ] + } + }, + "metadata": [ + { + "name": "prefix", + "displayName": "Prefix", + "shape": "string", + "role": "label" + }, + { + "name": "vrf", + "displayName": "VRF", + "shape": "string" + }, + { + "name": "status", + "displayName": "Status", + "shape": "string" + }, + { + "name": "size", + "displayName": "Size", + "shape": [ + "number", + { + "decimalPlaces": 0, + "thousandsSeparator": true + } + ] + }, + { + "name": "used", + "displayName": "Used", + "shape": [ + "number", + { + "decimalPlaces": 0, + "thousandsSeparator": true + } + ] + }, + { + "name": "utilization", + "displayName": "Utilization", + "shape": [ + "percent", + { + "decimalPlaces": 1 + } + ], + "role": "value" + }, + { + "name": "prefixId", + "visible": false + }, + { + "name": "netboxUrl", + "displayName": "Link", + "shape": [ + "url", + { + "label": "Open in NetBox" + } + ] + }, + { + "sourceId": "prefixId", + "sourceType": "Prefix", + "name": "prefix" + } + ], + "defaultShaping": { + "sort": { + "by": [ + [ + "utilization", + "desc" + ] + ] + } + }, + "timeframes": false +} diff --git a/plugins/NetBox/v1/dataStreams/prefixes.json b/plugins/NetBox/v1/dataStreams/prefixes.json new file mode 100644 index 00000000..ef588814 --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/prefixes.json @@ -0,0 +1,175 @@ +{ + "name": "prefixes", + "displayName": "Prefixes", + "description": "All IP prefixes with VRF, scope, status, role and pool settings", + "tags": [ + "IPAM", + "Network" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/ipam/prefixes/", + "getArgs": [ + { + "key": "fields", + "value": "id,display,display_url,prefix,family,vrf,scope_type,scope,status,role,tenant,vlan,is_pool,mark_utilized,_depth,children,description,created,last_updated,custom_fields" + }, + { + "key": "site_id", + "value": "{{ (typeof site !== 'undefined' && site && site.length) ? site.map(s => [].concat(s.rawId)[0]) : null }}" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "limit", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "results" + } + }, + "out": { + "realm": "queryArg", + "path": "offset" + } + }, + "pathToData": "results", + "expandInnerObjects": true + }, + "matches": "none", + "ui": [ + { + "type": "objects", + "name": "site", + "label": "Site (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Site" + ] + } + } + } + ], + "metadata": [ + { + "name": "id", + "visible": false + }, + { + "name": "prefix", + "displayName": "Prefix", + "shape": "string", + "role": "label" + }, + { + "name": "family.label", + "displayName": "Family", + "shape": "string" + }, + { + "name": "vrf.name", + "displayName": "VRF", + "shape": "string" + }, + { + "name": "vrf.id", + "visible": false + }, + { + "name": "status.label", + "displayName": "Status", + "shape": "string" + }, + { + "name": "status.value", + "visible": false + }, + { + "name": "role.name", + "displayName": "Role", + "shape": "string" + }, + { + "name": "tenant.name", + "displayName": "Tenant", + "shape": "string" + }, + { + "name": "scope.name", + "displayName": "Scope", + "shape": "string" + }, + { + "name": "scope_type", + "visible": false + }, + { + "name": "vlan.display", + "displayName": "VLAN", + "shape": "string" + }, + { + "name": "is_pool", + "displayName": "Pool", + "shape": "boolean" + }, + { + "name": "mark_utilized", + "displayName": "Marked Utilized", + "shape": "boolean" + }, + { + "name": "_depth", + "displayName": "Depth", + "shape": "number" + }, + { + "name": "children", + "displayName": "Child Prefixes", + "shape": "number" + }, + { + "name": "description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "created", + "displayName": "Created", + "shape": "date" + }, + { + "name": "last_updated", + "displayName": "Last Updated", + "shape": "date" + }, + { + "name": "display_url", + "displayName": "Link", + "shape": [ + "url", + { + "label": "Open in NetBox" + } + ] + }, + { + "sourceId": "id", + "sourceType": "Prefix", + "name": "prefix" + }, + { + "pattern": "^custom_fields[.].*" + } + ], + "timeframes": false +} diff --git a/plugins/NetBox/v1/dataStreams/rackElevation.json b/plugins/NetBox/v1/dataStreams/rackElevation.json new file mode 100644 index 00000000..6b70acf0 --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/rackElevation.json @@ -0,0 +1,171 @@ +{ + "name": "rackElevation", + "displayName": "Rack Elevation", + "description": "Rack units from top to bottom with the device, role, type and manufacturer at each unit", + "tags": [ + "Inventory", + "Capacity" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "post", + "endpointPath": "graphql/", + "headers": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "postBody": { + "query": "query($offset: Int) { rack_list(pagination: { limit: 100, offset: $offset }{{ (() => { const ids = (v) => ((typeof v !== 'undefined' && v) || []).map((o) => String([].concat(o.rawId)[0]).replace(/[^0-9]/g, '')).filter(Boolean); const s = ids(typeof site !== 'undefined' ? site : null); const r = ids(typeof rack !== 'undefined' ? rack : null); const f = []; if (s.length) f.push('site: { id: { in_list: [' + s.join(', ') + '] } }'); if (r.length) f.push('id: { in_list: [' + r.join(', ') + '] }'); return f.length ? ', filters: { ' + f.join(', ') + ' }' : ''; })() }}) { id name u_height starting_unit desc_units site { name } devices { id name position face role { name slug } device_type { model u_height is_full_depth manufacturer { name } } parent_bay { id } } } }", + "variables": { + "offset": 0 + } + }, + "postRequestScript": "rackElevation.js", + "paging": { + "mode": "offset", + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "data.rack_list" + } + }, + "out": { + "realm": "body", + "path": "variables.offset" + } + } + }, + "matches": "none", + "ui": [ + { + "type": "objects", + "name": "site", + "label": "Site (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Site" + ] + } + } + }, + { + "type": "objects", + "name": "rack", + "label": "Rack (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Rack" + ] + } + } + }, + { + "type": "autocomplete", + "name": "role", + "label": "Role (optional)", + "isMulti": true, + "allowCustomValues": true, + "data": { + "source": "dataStream", + "dataStreamName": "deviceRoles", + "dataSourceConfig": {} + } + } + ], + "metadata": [ + { + "name": "rack", + "displayName": "Rack", + "shape": "string", + "role": "label" + }, + { + "name": "site", + "displayName": "Site", + "shape": "string" + }, + { + "name": "unit", + "displayName": "Unit", + "shape": "number" + }, + { + "name": "unitsLabel", + "displayName": "Device Units", + "shape": "string" + }, + { + "name": "device", + "displayName": "Device", + "shape": "string" + }, + { + "name": "role", + "displayName": "Role", + "shape": "string" + }, + { + "name": "deviceType", + "displayName": "Device Type", + "shape": "string" + }, + { + "name": "manufacturer", + "displayName": "Manufacturer", + "shape": "string" + }, + { + "name": "face", + "displayName": "Face", + "shape": "string" + }, + { + "name": "deviceHeight", + "displayName": "Height (U)", + "shape": "number" + }, + { + "name": "isTopUnit", + "displayName": "Top Unit", + "shape": "boolean" + }, + { + "name": "occupied", + "displayName": "Occupied", + "shape": "boolean" + }, + { + "name": "order", + "displayName": "Row Order", + "shape": "number", + "visible": false + }, + { + "name": "rackId", + "visible": false + }, + { + "name": "deviceId", + "visible": false + }, + { + "sourceId": "rackId", + "sourceType": "Rack", + "name": "rack" + }, + { + "sourceId": "deviceId", + "sourceType": "Device", + "name": "device" + } + ], + "timeframes": false +} diff --git a/plugins/NetBox/v1/dataStreams/rackUtilization.json b/plugins/NetBox/v1/dataStreams/rackUtilization.json new file mode 100644 index 00000000..bf407a3a --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/rackUtilization.json @@ -0,0 +1,150 @@ +{ + "name": "rackUtilization", + "displayName": "Rack Utilization", + "description": "Rack unit space used and available per rack, counting both faces", + "tags": [ + "Capacity", + "Inventory" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "post", + "endpointPath": "graphql/", + "headers": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "postBody": { + "query": "query($offset: Int) { rack_list(pagination: { limit: 500, offset: $offset }{{ (() => { const ids = (v) => ((typeof v !== 'undefined' && v) || []).map((o) => String([].concat(o.rawId)[0]).replace(/[^0-9]/g, '')).filter(Boolean); const s = ids(typeof site !== 'undefined' ? site : null); const r = ids(typeof rack !== 'undefined' ? rack : null); const f = []; if (s.length) f.push('site: { id: { in_list: [' + s.join(', ') + '] } }'); if (r.length) f.push('id: { in_list: [' + r.join(', ') + '] }'); return f.length ? ', filters: { ' + f.join(', ') + ' }' : ''; })() }}) { id name u_height starting_unit site { id name } location { name } devices { id position face device_type { u_height is_full_depth } } } }", + "variables": { + "offset": 0 + } + }, + "paging": { + "mode": "offset", + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "data.rack_list" + } + }, + "out": { + "realm": "body", + "path": "variables.offset" + } + }, + "postRequestScript": "rackUtilization.js" + }, + "matches": "none", + "ui": [ + { + "type": "objects", + "name": "site", + "label": "Site (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Site" + ] + } + } + }, + { + "type": "objects", + "name": "rack", + "label": "Rack (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Rack" + ] + } + } + } + ], + "metadata": [ + { + "name": "rack", + "displayName": "Rack", + "shape": "string", + "role": "label" + }, + { + "name": "site", + "displayName": "Site", + "shape": "string" + }, + { + "name": "location", + "displayName": "Location", + "shape": "string" + }, + { + "name": "uHeight", + "displayName": "Height (U)", + "shape": "number" + }, + { + "name": "usedUnits", + "displayName": "Used (U)", + "shape": "number" + }, + { + "name": "availableUnits", + "displayName": "Available (U)", + "shape": "number" + }, + { + "name": "utilization", + "displayName": "Utilization", + "shape": [ + "percent", + { + "decimalPlaces": 1 + } + ], + "role": "value" + }, + { + "name": "frontUsed", + "displayName": "Front Used (U)", + "shape": "number" + }, + { + "name": "rearUsed", + "displayName": "Rear Used (U)", + "shape": "number" + }, + { + "name": "deviceCount", + "displayName": "Devices", + "shape": "number" + }, + { + "name": "rackId", + "visible": false + }, + { + "sourceId": "rackId", + "sourceType": "Rack", + "name": "rack" + } + ], + "defaultShaping": { + "sort": { + "by": [ + [ + "utilization", + "desc" + ] + ] + } + }, + "timeframes": false +} diff --git a/plugins/NetBox/v1/dataStreams/racks.json b/plugins/NetBox/v1/dataStreams/racks.json new file mode 100644 index 00000000..35556efd --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/racks.json @@ -0,0 +1,181 @@ +{ + "name": "racks", + "displayName": "Racks", + "description": "All racks with site, location, status, height and device count", + "tags": [ + "Inventory", + "Network" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/dcim/racks/", + "getArgs": [ + { + "key": "fields", + "value": "id,display,display_url,site,location,status,role,tenant,facility_id,serial,asset_tag,u_height,starting_unit,form_factor,device_count,powerfeed_count,description,created,last_updated,custom_fields" + }, + { + "key": "site_id", + "value": "{{ (typeof site !== 'undefined' && site && site.length) ? site.map(s => [].concat(s.rawId)[0]) : null }}" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "limit", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "results" + } + }, + "out": { + "realm": "queryArg", + "path": "offset" + } + }, + "pathToData": "results", + "expandInnerObjects": true + }, + "matches": "none", + "ui": [ + { + "type": "objects", + "name": "site", + "label": "Site (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Site" + ] + } + } + } + ], + "metadata": [ + { + "name": "id", + "visible": false + }, + { + "name": "display", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "status.label", + "displayName": "Status", + "shape": "string" + }, + { + "name": "status.value", + "visible": false + }, + { + "name": "site.name", + "displayName": "Site", + "shape": "string" + }, + { + "name": "site.id", + "visible": false + }, + { + "name": "site.url", + "visible": false, + "valueExpression": "{{ typeof $['site.id'] === 'number' ? String($['site.id']) : null }}" + }, + { + "name": "location.name", + "displayName": "Location", + "shape": "string" + }, + { + "name": "role.name", + "displayName": "Role", + "shape": "string" + }, + { + "name": "tenant.name", + "displayName": "Tenant", + "shape": "string" + }, + { + "name": "facility_id", + "displayName": "Facility ID", + "shape": "string" + }, + { + "name": "form_factor.label", + "displayName": "Form Factor", + "shape": "string" + }, + { + "name": "u_height", + "displayName": "Height (U)", + "shape": "number" + }, + { + "name": "device_count", + "displayName": "Devices", + "shape": "number" + }, + { + "name": "powerfeed_count", + "displayName": "Power Feeds", + "shape": "number" + }, + { + "name": "serial", + "displayName": "Serial Number", + "shape": "string" + }, + { + "name": "asset_tag", + "displayName": "Asset Tag", + "shape": "string" + }, + { + "name": "description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "created", + "displayName": "Created", + "shape": "date" + }, + { + "name": "last_updated", + "displayName": "Last Updated", + "shape": "date" + }, + { + "name": "display_url", + "displayName": "Link", + "shape": [ + "url", + { + "label": "Open in NetBox" + } + ] + }, + { + "sourceId": "id", + "sourceType": "Rack", + "name": "display" + }, + { + "pattern": "^custom_fields[.].*" + } + ], + "timeframes": false +} diff --git a/plugins/NetBox/v1/dataStreams/scripts/deviceRoles.js b/plugins/NetBox/v1/dataStreams/scripts/deviceRoles.js new file mode 100644 index 00000000..73dec329 --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/scripts/deviceRoles.js @@ -0,0 +1,4 @@ +result = ((data && data.results) || []).map((r) => ({ + label: r.name, + value: r.slug, +})); diff --git a/plugins/NetBox/v1/dataStreams/scripts/errorHandling/graphqlQuery.js b/plugins/NetBox/v1/dataStreams/scripts/errorHandling/graphqlQuery.js new file mode 100644 index 00000000..84d45c8b --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/scripts/errorHandling/graphqlQuery.js @@ -0,0 +1,5 @@ +// GraphQL errors in a 200 response are raised by the post-request script; this covers failed HTTP requests (bad auth, malformed request) +const body = typeof response.body === "string" ? response.body.slice(0, 300) : ""; +const apiMsg = (data && (data.detail || data.message)) || body; + +result = apiMsg ? `HTTP ${response.status}: ${apiMsg}` : `Request failed with HTTP ${response.status}`; diff --git a/plugins/NetBox/v1/dataStreams/scripts/graphqlQuery.js b/plugins/NetBox/v1/dataStreams/scripts/graphqlQuery.js new file mode 100644 index 00000000..97534aef --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/scripts/graphqlQuery.js @@ -0,0 +1,81 @@ +// NetBox GraphQL returns { data: { : [ ...items ] } } for list queries +// (e.g. site_list) or { data: { : { ... } } } for single-object queries. +// The query is user-supplied, so the columns are unknown in advance and must be built dynamically here. +// +// Row source: the first array found in `data.data` (in key order). If a top-level value is an object +// that wraps a list under a well-known name (results, items, nodes, edges, entries), that list is used. +// If there is no list at all, the single object returned becomes one row. +// +// Flattening: nested objects become dot-notation columns (rack.site.name). +// - arrays of primitives are joined with ", " +// - arrays of objects become ".count" plus "", the joined display/name of each item (if any have one) +const WRAPPER_KEYS = ["results", "items", "nodes", "edges", "entries"]; +const isObject =(v) => v !== null && typeof v === "object" && !Array.isArray(v); +const isPrimitive = (v) => v === null || typeof v !== "object"; + +const flatten = (value, path, out) => { + if (isObject(value)) { + Object.keys(value).forEach((key) => { + flatten(value[key], path ? `${path}.${key}` : key, out); + }); + } else if (Array.isArray(value)) { + if (value.every(isPrimitive)) { + out[path] = value.join(", "); + } else { + out[`${path}.count`] = value.length; + out[path] = value + .map((item) => isObject(item) && (item.display || item.name)) + .filter(Boolean) + .join(", "); + } + } else { + out[path] = value; + } + return out; +}; + +// GraphQL reports query errors with HTTP 200 and an `errors` array, which errorHandling never sees (it only runs on failed HTTP requests) +if (data && Array.isArray(data.errors) && data.errors.length) { + throw new Error(data.errors.map((e) => e.message).join("; ")); +} + +const root = (data && data.data) || {}; + +let items = null; +for (const key of Object.keys(root)) { + const value = root[key]; + if (Array.isArray(value)) { + items = value; + break; + } + if (isObject(value)) { + // Only well-known wrapper names are unwrapped, otherwise a single object with an array field + // (e.g. site(id: 1) { name tags { name } }) would be mistaken for a list of its tags + const inner = Object.keys(value).find((k) => WRAPPER_KEYS.includes(k) && Array.isArray(value[k])); + if (inner) { + items = value[inner]; + break; + } + } +} + +if (items) { + const rows = items.map((item) => (isObject(item) ? flatten(item, "", {}) : { value: item })); + // An empty array can't be told apart from an empty primitive list, so it emits no ".count" column. + // Default that column to 0 on rows that lack it, otherwise the count is blank rather than 0 for empty lists. + const countCols = new Set(); + rows.forEach((row) => Object.keys(row).forEach((k) => k.endsWith(".count") && countCols.add(k))); + rows.forEach((row) => countCols.forEach((k) => row[k] === undefined && (row[k] = 0))); + // A null nested object (e.g. region: null) is emitted as a "region" column, which would sit beside "region.name" + // from the rows where it is populated. Drop it so only the dotted columns remain (blank where the object is null). + const allKeys = new Set(); + rows.forEach((row) => Object.keys(row).forEach((k) => allKeys.add(k))); + const parents = [...allKeys].filter((k) => [...allKeys].some((o) => o.startsWith(`${k}.`))); + rows.forEach((row) => parents.forEach((k) => row[k] === null && delete row[k])); + result = rows; +} else { + const keys = Object.keys(root); + // A single object field (e.g. site(id: 1) { ... }) is flattened without its field name as a prefix + const single = keys.length === 1 && isObject(root[keys[0]]) ? root[keys[0]] : root; + result = keys.length ? [flatten(single, "", {})] : []; +} diff --git a/plugins/NetBox/v1/dataStreams/scripts/powerFeeds.js b/plugins/NetBox/v1/dataStreams/scripts/powerFeeds.js new file mode 100644 index 00000000..8edb8b77 --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/scripts/powerFeeds.js @@ -0,0 +1,6 @@ +// GraphQL reports errors as HTTP 200 with an `errors` array, so errorHandling never fires; throw to surface the message. +if (data && data.errors && data.errors.length) { + throw new Error(data.errors.map((e) => e.message).join("; ")); +} + +result = (data && data.data && data.data.power_feed_list) || []; diff --git a/plugins/NetBox/v1/dataStreams/scripts/prefixUtilization.js b/plugins/NetBox/v1/dataStreams/scripts/prefixUtilization.js new file mode 100644 index 00000000..27e7dd59 --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/scripts/prefixUtilization.js @@ -0,0 +1,95 @@ +// Mirrors NetBox Prefix.get_utilization() (ipam/models/ip.py), minus IP ranges marked populated. +const unwrap = (v) => (Array.isArray(v) ? v[0] : v); +const obj = (context.objects && context.objects[0]) || {}; +const cidr = String(unwrap(obj.name)); +const status = unwrap(obj.status); +const isPool = unwrap(obj.isPool) === true || unwrap(obj.isPool) === 'true'; +const markUtilized = unwrap(obj.markUtilized) === true || unwrap(obj.markUtilized) === 'true'; +const vrfId = unwrap(obj.vrfId); +const vrfName = unwrap(obj.vrf); + +const [addr, lenStr] = cidr.split('/'); +const prefixLen = parseInt(lenStr, 10); +const isV6 = addr.includes(':'); +const totalBits = isV6 ? 128 : 32; + +// Parse an address into a BigInt (IPv4 dotted quad or IPv6, including '::' compression and embedded IPv4). +const toBigInt = (a) => { + if (!a.includes(':')) { + return a.split('.').reduce((acc, o) => (acc << 8n) + BigInt(parseInt(o, 10)), 0n); + } + let s = a; + if (s.includes('.')) { + const idx = s.lastIndexOf(':'); + const v4 = s.slice(idx + 1).split('.').map((o) => parseInt(o, 10)); + s = s.slice(0, idx + 1) + ((v4[0] << 8) | v4[1]).toString(16) + ':' + ((v4[2] << 8) | v4[3]).toString(16); + } + const [head, tail] = s.split('::'); + const h = head ? head.split(':') : []; + const t = tail !== undefined && tail ? tail.split(':') : []; + const missing = tail === undefined ? 0 : 8 - h.length - t.length; + const groups = [...h, ...Array(missing).fill('0'), ...t]; + return groups.reduce((acc, g) => (acc << 16n) + BigInt(parseInt(g || '0', 16)), 0n); +}; + +const parseCidr = (c) => { + const [a, l] = c.split('/'); + const len = parseInt(l, 10); + const bits = a.includes(':') ? 128 : 32; + const size = 1n << BigInt(bits - len); + const start = (toBigInt(a) >> BigInt(bits - len)) << BigInt(bits - len); + return { start, end: start + size - 1n, size }; +}; + +const prefixSize = 1n << BigInt(totalBits - prefixLen); +let size = prefixSize; +let used = 0n; +let utilization; + +if (markUtilized) { + utilization = 100; + if (status === 'container') { + used = prefixSize; + } +} else if (status === 'container') { + // Union of child ranges: sort by start and merge overlaps, so nested children aren't double counted. + const children = ((data && data.results) || []) + .filter((r) => r && typeof r.prefix === 'string') + .map((r) => parseCidr(r.prefix)) + .sort((a, b) => (a.start < b.start ? -1 : a.start > b.start ? 1 : 0)); + let curEnd = -1n; + for (const c of children) { + if (c.start > curEnd) { + used += c.size; + curEnd = c.end; + } else if (c.end > curEnd) { + used += c.end - curEnd; + curEnd = c.end; + } + } +} else { + used = BigInt((data && data.count) || 0); + // IPv4 non-pool prefixes shorter than /31 exclude the network and broadcast addresses + if (!isV6 && prefixLen < 31 && !isPool) { + size = prefixSize - 2n; + } +} + +if (utilization === undefined) { + // Scale by 10000 in BigInt to keep precision for huge IPv6 sizes, then cap at 100 + const scaled = size > 0n ? (used * 10000n) / size : 0n; + utilization = Math.min(Number(scaled) / 100, 100); +} + +result = [ + { + prefix: cidr, + vrf: typeof vrfName === 'string' && vrfName ? vrfName : 'Global', + status: status, + size: Number(size), + used: Number(used), + utilization: utilization, + prefixId: unwrap(obj.rawId), + netboxUrl: unwrap(obj.netboxUrl), + }, +]; diff --git a/plugins/NetBox/v1/dataStreams/scripts/rackElevation.js b/plugins/NetBox/v1/dataStreams/scripts/rackElevation.js new file mode 100644 index 00000000..020a9548 --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/scripts/rackElevation.js @@ -0,0 +1,123 @@ +// Builds one row per rack unit (and per device covering it) from the GraphQL rack_list response. +// The GraphQL API returns Decimal fields (position, u_height) as strings such as "32.0". +// GraphQL reports errors as HTTP 200 with an `errors` array, so errorHandling never fires; throw to surface the message. +if (data && data.errors && data.errors.length) { + throw new Error(data.errors.map((e) => e.message).join("; ")); +} +const racks = (data && data.data && data.data.rack_list) || []; + +// Optional role filter: autocomplete values arrive as [{ value }] (slug, or a custom typed name). +const roleFilter = new Set( + ((context.config && context.config.role) || []) + .map((r) => String(r && typeof r === "object" ? r.value : r).toLowerCase()) + .filter((r) => r && r !== "undefined"), +); +const hasRoleFilter = roleFilter.size > 0; +const matchesRole = (role) => + !hasRoleFilter || + (role && (roleFilter.has(String(role.slug).toLowerCase()) || roleFilter.has(String(role.name).toLowerCase()))); + +const unitRange = (lo, hi) => (lo === hi ? `${lo}` : `${lo}–${hi}`); + +const rows = []; +let order = 0; + +// Keep racks together, ordered by site then rack name. +const bySiteAndName = (a, b) => + ((a.site && a.site.name) || "").localeCompare((b.site && b.site.name) || "") || + String(a.name).localeCompare(String(b.name)) || + Number(a.id) - Number(b.id); + +for (const rack of [...racks].sort(bySiteAndName)) { + const startUnit = Number(rack.starting_unit) || 1; + const height = Number(rack.u_height) || 0; + const topUnit = startUnit + height - 1; + const base = { + rack: rack.name, + site: (rack.site && rack.site.name) || "", + rackId: String(rack.id), + }; + + // Split the rack's devices into those mounted at a position and the rest (0U, child devices, unracked). + const mounted = []; + const other = []; + for (const dev of rack.devices || []) { + if (!matchesRole(dev.role)) continue; + const dt = dev.device_type || {}; + const info = { + deviceId: String(dev.id), + device: dev.name || "(unnamed)", + role: (dev.role && dev.role.name) || "", + deviceType: dt.model || "", + manufacturer: (dt.manufacturer && dt.manufacturer.name) || "", + deviceHeight: Number(dt.u_height) || 0, + fullDepth: !!dt.is_full_depth, + face: dev.face === "rear" ? "Rear" : "Front", + }; + const pos = dev.position === null || dev.position === undefined ? null : Number(dev.position); + if (pos !== null && !Number.isNaN(pos) && info.deviceHeight > 0) { + // Whole units the device touches: a 0.5U device at 5.5 still occupies unit 5. + info.lo = Math.floor(pos); + info.hi = Math.max(Math.ceil(pos + info.deviceHeight) - 1, info.lo); + mounted.push(info); + } else { + info.kind = dev.parent_bay ? "Child" : info.deviceHeight === 0 ? "0U" : "Unracked"; + other.push(info); + } + } + + // NetBox renders a descending rack (desc_units) with the starting unit at the top. + const units = []; + for (let i = 0; i < height; i++) units.push(rack.desc_units ? startUnit + i : topUnit - i); + + for (const unit of units) { + const covering = mounted + .filter((d) => d.lo <= unit && d.hi >= unit) + .sort((a, b) => (a.fullDepth === b.fullDepth ? 0 : a.fullDepth ? -1 : 1) || (a.face === "Front" ? -1 : 1)); + if (!covering.length) { + // An empty slot is only meaningful when not filtering by role. + if (!hasRoleFilter) { + rows.push({ ...base, order: order++, unit, unitsLabel: `${unit}`, device: "", deviceId: "", role: "", deviceType: "", manufacturer: "", face: "", deviceHeight: null, isTopUnit: false, occupied: false }); + } + continue; + } + for (const d of covering) { + rows.push({ + ...base, + order: order++, + unit, + unitsLabel: unitRange(d.lo, d.hi), + device: d.device, + deviceId: d.deviceId, + role: d.role, + deviceType: d.deviceType, + manufacturer: d.manufacturer, + face: d.fullDepth ? "Both" : d.face, + deviceHeight: d.deviceHeight, + isTopUnit: unit === (rack.desc_units ? d.lo : d.hi), + occupied: true, + }); + } + } + + // 0U, child and unracked devices follow the units; they have no unit number. + for (const d of other) { + rows.push({ + ...base, + order: order++, + unit: null, + unitsLabel: d.kind, + device: d.device, + deviceId: d.deviceId, + role: d.role, + deviceType: d.deviceType, + manufacturer: d.manufacturer, + face: "", + deviceHeight: d.deviceHeight, + isTopUnit: false, + occupied: true, + }); + } +} + +result = rows; diff --git a/plugins/NetBox/v1/dataStreams/scripts/rackUtilization.js b/plugins/NetBox/v1/dataStreams/scripts/rackUtilization.js new file mode 100644 index 00000000..b8effe2f --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/scripts/rackUtilization.js @@ -0,0 +1,60 @@ +// GraphQL returns { data: { rack_list: [ { id, name, u_height, starting_unit, site, location, devices: [...] } ] } }. +// Occupancy is computed per rack from every positioned device, in half-unit steps (position and height can be .5). +// A device occupies the slots [position, position + height). Slots are unioned across both faces, so a half-depth +// device on the front and another on the rear at the same U count once, and a full-depth device counts once. +// GraphQL reports query errors with HTTP 200 and an `errors` array (errorHandling does not fire on a 200), so surface them here. +if (data && Array.isArray(data.errors) && data.errors.length) { + throw new Error(data.errors.map((e) => e.message).filter(Boolean).join("; ")); +} +const racks = (data && data.data && data.data.rack_list) || []; + +const num = (v) => (v === null || typeof v === "undefined" || v === "" ? null : Number(v)); +const round = (v, dp) => Math.round(v * 10 ** dp) / 10 ** dp; +const faceOf = (d) => String(d.face || "").toLowerCase(); + +result = racks.map((rack) => { + const uHeight = num(rack.u_height) || 0; + const startingUnit = num(rack.starting_unit) || 1; + // Slots are half-units, so unit U maps to slot index U * 2. The rack spans [lo, hi). + const lo = startingUnit * 2; + const hi = lo + uHeight * 2; + + const both = new Set(); + const front = new Set(); + const rear = new Set(); + let deviceCount = 0; + + (rack.devices || []).forEach((d) => { + const position = num(d.position); + if (position === null) return; // child devices (in bays) and unracked devices have no position + deviceCount++; + + const type = d.device_type || {}; + const height = num(type.u_height) || 0; // 0U devices occupy no space + const start = Math.round(position * 2); + const end = start + Math.round(height * 2); + const fullDepth = type.is_full_depth !== false; + const face = faceOf(d); + + for (let s = Math.max(start, lo); s < Math.min(end, hi); s++) { + both.add(s); + if (fullDepth || face === "front") front.add(s); + if (fullDepth || face === "rear") rear.add(s); + } + }); + + const usedUnits = both.size / 2; + return { + rack: rack.name, + site: rack.site && rack.site.name, + location: (rack.location && rack.location.name) || "", + uHeight, + usedUnits, + availableUnits: Math.max(uHeight - usedUnits, 0), + utilization: uHeight ? round((usedUnits / uHeight) * 100, 1) : 0, + frontUsed: front.size / 2, + rearUsed: rear.size / 2, + deviceCount, + rackId: rack.id, + }; +}); diff --git a/plugins/NetBox/v1/dataStreams/sites.json b/plugins/NetBox/v1/dataStreams/sites.json new file mode 100644 index 00000000..a4afc14f --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/sites.json @@ -0,0 +1,168 @@ +{ + "name": "sites", + "displayName": "Sites", + "description": "All sites with status, region, tenant and object counts", + "tags": [ + "Inventory", + "Network" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/dcim/sites/", + "getArgs": [ + { + "key": "fields", + "value": "id,display,display_url,status,region,group,tenant,facility,time_zone,description,physical_address,latitude,longitude,device_count,rack_count,prefix_count,vlan_count,circuit_count,virtualmachine_count,created,last_updated,custom_fields" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "limit", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "results" + } + }, + "out": { + "realm": "queryArg", + "path": "offset" + } + }, + "pathToData": "results", + "expandInnerObjects": true + }, + "matches": "none", + "metadata": [ + { + "name": "id", + "visible": false + }, + { + "name": "display", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "status.label", + "displayName": "Status", + "shape": "string" + }, + { + "name": "status.value", + "visible": false + }, + { + "name": "region.name", + "displayName": "Region", + "shape": "string" + }, + { + "name": "group.name", + "displayName": "Site Group", + "shape": "string" + }, + { + "name": "tenant.name", + "displayName": "Tenant", + "shape": "string" + }, + { + "name": "facility", + "displayName": "Facility", + "shape": "string" + }, + { + "name": "time_zone", + "displayName": "Time Zone", + "shape": "string" + }, + { + "name": "physical_address", + "displayName": "Address", + "shape": "string" + }, + { + "name": "latitude", + "displayName": "Latitude", + "shape": "number" + }, + { + "name": "longitude", + "displayName": "Longitude", + "shape": "number" + }, + { + "name": "device_count", + "displayName": "Devices", + "shape": "number" + }, + { + "name": "rack_count", + "displayName": "Racks", + "shape": "number" + }, + { + "name": "prefix_count", + "displayName": "Prefixes", + "shape": "number" + }, + { + "name": "vlan_count", + "displayName": "VLANs", + "shape": "number" + }, + { + "name": "circuit_count", + "displayName": "Circuits", + "shape": "number" + }, + { + "name": "virtualmachine_count", + "displayName": "Virtual Machines", + "shape": "number" + }, + { + "name": "description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "created", + "displayName": "Created", + "shape": "date" + }, + { + "name": "last_updated", + "displayName": "Last Updated", + "shape": "date" + }, + { + "name": "display_url", + "displayName": "Link", + "shape": [ + "url", + { + "label": "Open in NetBox" + } + ] + }, + { + "sourceId": "id", + "sourceType": "Site", + "name": "display" + }, + { + "pattern": "^custom_fields[.].*" + } + ], + "timeframes": false +} diff --git a/plugins/NetBox/v1/dataStreams/status.json b/plugins/NetBox/v1/dataStreams/status.json new file mode 100644 index 00000000..54345e07 --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/status.json @@ -0,0 +1,60 @@ +{ + "name": "status", + "displayName": "Instance Status", + "description": "NetBox version, installed plugins and background worker count for the connected instance", + "tags": [ + "Status" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/status/" + }, + "matches": "none", + "metadata": [ + { + "name": "netbox-version", + "displayName": "NetBox Version", + "shape": "string", + "role": "label" + }, + { + "name": "netbox-full-version", + "displayName": "Full Version", + "shape": "string" + }, + { + "name": "django-version", + "displayName": "Django Version", + "shape": "string" + }, + { + "name": "python-version", + "displayName": "Python Version", + "shape": "string" + }, + { + "name": "rq-workers-running", + "displayName": "Workers Running", + "shape": "number", + "role": "value" + }, + { + "name": "hostname", + "displayName": "Hostname", + "shape": "string" + }, + { + "name": "plugins", + "visible": false + }, + { + "name": "pluginCount", + "displayName": "Plugins Installed", + "computed": true, + "valueExpression": "{{ Object.keys($['plugins'] || {}).length }}", + "shape": "number" + } + ], + "timeframes": false +} diff --git a/plugins/NetBox/v1/dataStreams/virtualMachines.json b/plugins/NetBox/v1/dataStreams/virtualMachines.json new file mode 100644 index 00000000..e95e7540 --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/virtualMachines.json @@ -0,0 +1,181 @@ +{ + "name": "virtualMachines", + "displayName": "Virtual Machines", + "description": "All virtual machines with status, cluster, site, resources and primary IP", + "tags": [ + "Inventory", + "Virtualization" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/virtualization/virtual-machines/", + "getArgs": [ + { + "key": "fields", + "value": "id,display,display_url,status,site,cluster,device,role,tenant,platform,primary_ip,vcpus,memory,disk,description,created,last_updated,custom_fields" + }, + { + "key": "site_id", + "value": "{{ (typeof site !== 'undefined' && site && site.length) ? site.map(s => [].concat(s.rawId)[0]) : null }}" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "limit", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "results" + } + }, + "out": { + "realm": "queryArg", + "path": "offset" + } + }, + "pathToData": "results", + "expandInnerObjects": true + }, + "matches": "none", + "ui": [ + { + "type": "objects", + "name": "site", + "label": "Site (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Site" + ] + } + } + } + ], + "metadata": [ + { + "name": "id", + "visible": false + }, + { + "name": "display", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "status.label", + "displayName": "Status", + "shape": "string" + }, + { + "name": "status.value", + "visible": false + }, + { + "name": "cluster.name", + "displayName": "Cluster", + "shape": "string" + }, + { + "name": "site.name", + "displayName": "Site", + "shape": "string" + }, + { + "name": "site.id", + "visible": false + }, + { + "name": "site.url", + "visible": false, + "valueExpression": "{{ typeof $['site.id'] === 'number' ? String($['site.id']) : null }}" + }, + { + "name": "device.name", + "displayName": "Host Device", + "shape": "string" + }, + { + "name": "role.name", + "displayName": "Role", + "shape": "string" + }, + { + "name": "tenant.name", + "displayName": "Tenant", + "shape": "string" + }, + { + "name": "platform.name", + "displayName": "Platform", + "shape": "string" + }, + { + "name": "primary_ip.address", + "visible": false + }, + { + "name": "primary_ip.display", + "displayName": "Primary IP", + "shape": "string", + "valueExpression": "{{ typeof $['primary_ip.address'] === 'string' && $['primary_ip.address'] ? $['primary_ip.address'].split('/')[0] : null }}" + }, + { + "name": "vcpus", + "displayName": "vCPUs", + "shape": "number" + }, + { + "name": "memory", + "displayName": "Memory", + "shape": "megabytes" + }, + { + "name": "disk", + "displayName": "Disk", + "shape": "megabytes" + }, + { + "name": "description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "created", + "displayName": "Created", + "shape": "date" + }, + { + "name": "last_updated", + "displayName": "Last Updated", + "shape": "date" + }, + { + "name": "display_url", + "displayName": "Link", + "shape": [ + "url", + { + "label": "Open in NetBox" + } + ] + }, + { + "sourceId": "id", + "sourceType": "Virtual Machine", + "name": "display" + }, + { + "pattern": "^custom_fields[.].*" + } + ], + "timeframes": false +} diff --git a/plugins/NetBox/v1/dataStreams/vlanGroups.json b/plugins/NetBox/v1/dataStreams/vlanGroups.json new file mode 100644 index 00000000..00bb96f4 --- /dev/null +++ b/plugins/NetBox/v1/dataStreams/vlanGroups.json @@ -0,0 +1,147 @@ +{ + "name": "vlanGroups", + "displayName": "VLAN Groups", + "description": "VLAN groups with scope, VLAN ID ranges and utilization", + "tags": [ + "IPAM", + "Capacity" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/ipam/vlan-groups/", + "getArgs": [ + { + "key": "fields", + "value": "id,display,display_url,name,slug,scope_type,scope,tenant,vid_ranges,total_vlan_ids,vlan_count,utilization,description,last_updated,custom_fields" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "limit", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "results" + } + }, + "out": { + "realm": "queryArg", + "path": "offset" + } + }, + "pathToData": "results", + "expandInnerObjects": true + }, + "matches": "none", + "defaultShaping": { + "sort": { + "by": [ + [ + "utilizationPct", + "desc" + ] + ] + } + }, + "metadata": [ + { + "name": "id", + "visible": false + }, + { + "name": "display", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "scope_type", + "visible": false + }, + { + "name": "scopeType", + "displayName": "Scope Type", + "shape": "string", + "computed": true, + "valueExpression": "{{ typeof $['scope_type'] === 'string' && $['scope_type'] ? (({ site: 'Site', sitegroup: 'Site Group', region: 'Region', location: 'Location', rack: 'Rack', cluster: 'Cluster', clustergroup: 'Cluster Group' })[$['scope_type'].split('.').pop()] || $['scope_type']) : null }}" + }, + { + "name": "scope.name", + "displayName": "Scope", + "shape": "string" + }, + { + "name": "tenant.name", + "displayName": "Tenant", + "shape": "string" + }, + { + "name": "vid_ranges", + "visible": false + }, + { + "name": "vidRanges", + "displayName": "VLAN ID Ranges", + "shape": "string", + "computed": true, + "valueExpression": "{{ (() => { let r = $['vid_ranges']; if (typeof r === 'string') { try { r = JSON.parse(r); } catch (e) { return null; } } return Array.isArray(r) ? r.map(x => x[0] === x[1] ? String(x[0]) : x[0] + '-' + x[1]).join(', ') : null; })() }}" + }, + { + "name": "total_vlan_ids", + "displayName": "Total VLAN IDs", + "shape": "number" + }, + { + "name": "vlan_count", + "displayName": "VLANs", + "shape": "number" + }, + { + "name": "utilization", + "visible": false + }, + { + "name": "utilizationPct", + "displayName": "Utilization", + "shape": [ + "percent", + { + "decimalPlaces": 1 + } + ], + "computed": true, + "valueExpression": "{{ Number.isFinite(parseFloat($['utilization'])) ? parseFloat($['utilization']) : null }}" + }, + { + "name": "description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "last_updated", + "displayName": "Last Updated", + "shape": "date" + }, + { + "name": "display_url", + "displayName": "Link", + "shape": [ + "url", + { + "label": "Open in NetBox" + } + ] + }, + { + "pattern": "^custom_fields[.].*" + } + ], + "timeframes": false +} diff --git a/plugins/NetBox/v1/defaultContent/Capacity/dataCenters.dash.json b/plugins/NetBox/v1/defaultContent/Capacity/dataCenters.dash.json new file mode 100644 index 00000000..88568317 --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Capacity/dataCenters.dash.json @@ -0,0 +1,771 @@ +{ + "name": "Data Centers", + "schemaVersion": "1.5", + "timeframe": "none", + "variables": [], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "eb418e62-e67c-4beb-8029-2582854cacb9", + "x": 0, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Sites", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[sites]}}", + "name": "sites", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Sites" + } + } + } + } + }, + { + "i": "fb8d1ef6-967b-4998-80e1-a1ba58040461", + "x": 1, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Racks", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[sites]}}", + "name": "sites", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "sum", + "names": [ + "rack_count" + ] + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "rack_count_sum", + "comparisonColumn": "none", + "label": "Racks" + } + } + } + } + }, + { + "i": "5e3dc2fe-2b5d-430c-bda1-4f36b895bb4a", + "x": 2, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[sites]}}", + "name": "sites", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "sum", + "names": [ + "device_count" + ] + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "device_count_sum", + "comparisonColumn": "none", + "label": "Devices" + } + } + } + } + }, + { + "i": "aeedc5c8-9dea-4aca-a76f-4ee8fde44d88", + "x": 3, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Circuits", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[sites]}}", + "name": "sites", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "sum", + "names": [ + "circuit_count" + ] + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "circuit_count_sum", + "comparisonColumn": "none", + "label": "Circuits" + } + } + } + } + }, + { + "i": "20ece744-d1e4-4e78-9f92-072d09f28766", + "x": 0, + "y": 2, + "w": 4, + "h": 6, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Site Map", + "description": "Sites plotted by latitude and longitude, coloured by status. Sites without coordinates are not shown.", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[sites]}}", + "name": "sites", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "display", + "asc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "display", + "status.label", + "region.name", + "facility", + "physical_address", + "latitude", + "longitude", + "display_url" + ], + "hiddenColumns": [ + "group.name", + "tenant.name", + "time_zone", + "device_count", + "rack_count", + "prefix_count", + "vlan_count", + "circuit_count", + "virtualmachine_count", + "description", + "created", + "last_updated" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "geoMap", + "encoding": { + "latitude": { + "field": "latitude", + "type": "quantitative", + "title": "Latitude" + }, + "longitude": { + "field": "longitude", + "type": "quantitative", + "title": "Longitude" + }, + "label": { + "field": "display", + "type": "nominal", + "title": "Site" + }, + "status": { + "field": "status.value", + "type": "nominal", + "title": "Status" + }, + "details": [ + { + "field": "status.label", + "type": "nominal", + "title": "Status" + }, + { + "field": "region.name", + "type": "nominal", + "title": "Region" + }, + { + "field": "facility", + "type": "nominal", + "title": "Facility" + }, + { + "field": "tenant.name", + "type": "nominal", + "title": "Tenant" + }, + { + "field": "rack_count", + "type": "quantitative", + "title": "Racks" + }, + { + "field": "device_count", + "type": "quantitative", + "title": "Devices" + } + ] + }, + "style": { + "geoMapBase": "auto", + "geoMapStatusMap": { + "active": "success", + "planned": "unknown", + "staging": "warning", + "decommissioning": "warning", + "retired": "unknown" + }, + "geoMapSymbol": "circle", + "geoMapPointSize": 10, + "geoMapZoomControls": true, + "geoMapWheelZoom": false, + "showLabels": true + } + } + } + } + }, + { + "i": "f9376cdd-325b-4c51-9b0f-283078283909", + "x": 0, + "y": 8, + "w": 2, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Sites by Region", + "description": "Sites with a region assigned", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[sites]}}", + "name": "sites", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "region.name", + "operation": "notempty" + } + ] + }, + "group": { + "by": [ + [ + "region.name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ], + "top": 15 + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "region.name_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "region.name_uniqueValues", + "type": "nominal", + "title": "Region" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Sites" + } + }, + "style": { + "cartesianHorizontal": true + } + } + } + } + }, + { + "i": "d175afab-8891-478a-bfe2-5e307faebb90", + "x": 2, + "y": 8, + "w": 2, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Sites by Status", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[sites]}}", + "name": "sites", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "status.label", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "labelColumn": "status.label_uniqueValues", + "hideCenterValue": false, + "showValuesAsPercentage": false, + "legendPosition": "auto", + "legendMode": "table" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "pie", + "encoding": { + "label": { + "field": "status.label_uniqueValues", + "type": "nominal", + "title": "Status" + }, + "value": { + "field": "count", + "type": "quantitative", + "title": "Count" + } + }, + "style": { + "pieInnerRadius": 60, + "pieDonutCenterValue": "total", + "labelFontSize": 16, + "pieLegendStyle": "table", + "mappedColors": { + "Active": "#2fb344", + "Planned": "#17a2b8", + "Staging": "#206bc4", + "Decommissioning": "#f59f00", + "Retired": "#d63939" + } + } + } + } + } + }, + { + "i": "ac6a9f18-a7f3-4a7c-944d-c9375f44d8e9", + "x": 0, + "y": 12, + "w": 2, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Sites by Tenant", + "description": "Sites with a tenant assigned", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[sites]}}", + "name": "sites", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "tenant.name", + "operation": "notempty" + } + ] + }, + "group": { + "by": [ + [ + "tenant.name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ], + "top": 15 + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "tenant.name_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "tenant.name_uniqueValues", + "type": "nominal", + "title": "Tenant" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Sites" + } + }, + "style": { + "cartesianHorizontal": true + } + } + } + } + }, + { + "i": "b75e7915-fec0-4f5d-af13-24f50c493f40", + "x": 2, + "y": 12, + "w": 2, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Top 10 Sites by Racks", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[sites]}}", + "name": "sites", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "rack_count", + "operation": "greaterthan", + "value": "0" + } + ] + }, + "sort": { + "by": [ + [ + "rack_count", + "desc" + ] + ], + "top": 10 + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "display", + "yAxisData": [ + "rack_count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "display", + "type": "nominal", + "title": "Site" + }, + "y": { + "field": "rack_count", + "type": "quantitative", + "title": "Racks" + } + }, + "style": { + "cartesianHorizontal": true + } + } + } + } + }, + { + "i": "df74f570-61c6-4c94-98fa-c1e0692ed2db", + "x": 0, + "y": 16, + "w": 4, + "h": 6, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Data Center Sites", + "description": "All sites, including any site custom fields", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[sites]}}", + "name": "sites", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "display", + "asc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "display", + "status.label", + "region.name", + "group.name", + "facility", + "tenant.name", + "time_zone", + "physical_address", + "rack_count", + "device_count", + "circuit_count", + "display_url" + ], + "hiddenColumns": [ + "latitude", + "longitude", + "prefix_count", + "vlan_count", + "virtualmachine_count", + "description", + "created", + "last_updated" + ] + } + } + } + } + } + ] + } +} diff --git a/plugins/NetBox/v1/defaultContent/Capacity/ipamCapacity.dash.json b/plugins/NetBox/v1/defaultContent/Capacity/ipamCapacity.dash.json new file mode 100644 index 00000000..e465096c --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Capacity/ipamCapacity.dash.json @@ -0,0 +1,680 @@ +{ + "name": "IPAM Capacity", + "schemaVersion": "1.5", + "timeframe": "none", + "variables": [], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "7174e594-da58-424a-b245-8efe6288f9f1", + "x": 0, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Prefixes", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[prefixes]}}", + "name": "prefixes", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Prefixes" + } + } + } + } + }, + { + "i": "9feebca5-2aff-47d7-bf06-2814dcf59d50", + "x": 1, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Total VLAN Groups", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[vlanGroups]}}", + "name": "vlanGroups", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "VLAN Groups" + } + } + } + } + }, + { + "i": "514fafdb-2127-4b6f-9212-6b1e544fe4ee", + "x": 2, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "IP Addresses", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[ipAddresses]}}", + "name": "ipAddresses", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "IP Addresses" + } + } + } + } + }, + { + "i": "82f0d193-92a6-4a41-8254-d6d40dbf261a", + "x": 3, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Unassigned IP Addresses", + "description": "IP addresses not assigned to an interface", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[ipAddresses]}}", + "name": "ipAddresses", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "assignment": "false" + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Unassigned" + } + } + } + } + }, + { + "i": "93952ffc-c959-44a8-a508-b51a50f438e8", + "x": 0, + "y": 2, + "w": 2, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Prefixes by Status", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[prefixes]}}", + "name": "prefixes", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "status.label", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "labelColumn": "status.label_uniqueValues", + "hideCenterValue": false, + "showValuesAsPercentage": false, + "legendPosition": "auto", + "legendMode": "table" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "pie", + "encoding": { + "label": { + "field": "status.label_uniqueValues", + "type": "nominal", + "title": "Status" + }, + "value": { + "field": "count", + "type": "quantitative", + "title": "Count" + } + }, + "style": { + "pieInnerRadius": 60, + "pieDonutCenterValue": "total", + "labelFontSize": 16, + "pieLegendStyle": "table" + } + } + } + } + }, + { + "i": "2a160721-415c-4a26-b903-171a04808541", + "x": 2, + "y": 2, + "w": 2, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "IP Addresses by Status", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[ipAddresses]}}", + "name": "ipAddresses", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "status.label", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "labelColumn": "status.label_uniqueValues", + "hideCenterValue": false, + "showValuesAsPercentage": false, + "legendPosition": "auto", + "legendMode": "table" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "pie", + "encoding": { + "label": { + "field": "status.label_uniqueValues", + "type": "nominal", + "title": "Status" + }, + "value": { + "field": "count", + "type": "quantitative", + "title": "Count" + } + }, + "style": { + "pieInnerRadius": 60, + "pieDonutCenterValue": "total", + "labelFontSize": 16, + "pieLegendStyle": "table", + "mappedColors": { + "Active": "#2fb344", + "Reserved": "#17a2b8", + "Deprecated": "#d63939", + "DHCP": "#2fb344", + "SLAAC": "#2fb344" + } + } + } + } + } + }, + { + "i": "673097ce-d716-4f78-b719-5e066d186648", + "x": 0, + "y": 6, + "w": 4, + "h": 6, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Prefix Utilization", + "description": "Rows over 80% are highlighted amber, over 90% red", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[prefixUtilization]}}", + "name": "prefixUtilization", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "utilization", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[NetBox Prefixes]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "prefix", + "vrf", + "status", + "size", + "used", + "utilization", + "netboxUrl" + ], + "hiddenColumns": [] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "netboxUrl", + "title": "Prefix", + "renderer": { + "type": "link", + "labelField": "prefix" + } + }, + { + "field": "vrf", + "title": "VRF", + "renderer": { + "type": "text" + } + }, + { + "field": "status", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#2fb344", + "Container": "#9ba3af", + "Reserved": "#17a2b8", + "Deprecated": "#d63939" + } + } + }, + { + "field": "size", + "title": "Size", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "used", + "title": "Used", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "utilization", + "title": "Utilization", + "renderer": { + "type": "progress", + "max": 100 + } + } + ] + }, + "style": { + "richTableRowHighlight": { + "field": "utilization", + "thresholds": [ + { + "to": 79.99, + "color": "rgba(0,0,0,0)" + }, + { + "to": 89.99, + "color": "rgba(245,158,11,0.12)" + }, + { + "to": 100, + "color": "rgba(239,68,68,0.15)" + } + ] + } + } + } + } + } + }, + { + "i": "3fdffd7d-fbdc-4163-bc53-308b73385b5b", + "x": 0, + "y": 12, + "w": 2, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "VLAN Group Utilization", + "description": "Top 10 VLAN groups by VLAN IDs used", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[vlanGroups]}}", + "name": "vlanGroups", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "utilizationPct", + "desc" + ] + ], + "top": 10 + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "display", + "yAxisData": [ + "utilizationPct" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "Utilization (%)", + "showXAxisLabel": false, + "showYAxisLabel": true, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "ringGrid", + "encoding": { + "value": { + "field": "utilizationPct", + "type": "quantitative", + "title": "Utilization" + }, + "label": { + "field": "display", + "type": "nominal", + "title": "VLAN Group" + } + }, + "style": { + "ringGridColumnsPerRow": 5, + "ringGridThresholds": [ + { + "to": 0.8, + "color": "#2fb344" + }, + { + "to": 0.9, + "color": "#f59f00" + }, + { + "to": 1, + "color": "#d63939" + } + ] + } + } + } + } + }, + { + "i": "e89e45dc-9e12-4911-b8ed-20f3dbc9dc5d", + "x": 2, + "y": 12, + "w": 2, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "VLAN Groups", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[vlanGroups]}}", + "name": "vlanGroups", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "utilizationPct", + "desc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "display", + "scopeType", + "scope.name", + "vidRanges", + "total_vlan_ids", + "vlan_count", + "utilizationPct", + "tenant.name", + "display_url" + ], + "hiddenColumns": [ + "last_updated" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "display_url", + "title": "VLAN Group", + "renderer": { + "type": "link", + "labelField": "display" + } + }, + { + "field": "scope.name", + "title": "Scope", + "renderer": { + "type": "text" + } + }, + { + "field": "vlan_count", + "title": "VLANs", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "total_vlan_ids", + "title": "VLAN IDs", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "utilizationPct", + "title": "Utilization", + "renderer": { + "type": "progress", + "max": 100 + } + } + ] + } + } + } + } + } + ] + } +} diff --git a/plugins/NetBox/v1/defaultContent/Capacity/manifest.json b/plugins/NetBox/v1/defaultContent/Capacity/manifest.json new file mode 100644 index 00000000..9f7b2029 --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Capacity/manifest.json @@ -0,0 +1,20 @@ +{ + "items": [ + { + "name": "ipamCapacity", + "type": "dashboard" + }, + { + "name": "rackCapacity", + "type": "dashboard" + }, + { + "name": "power", + "type": "dashboard" + }, + { + "name": "dataCenters", + "type": "dashboard" + } + ] +} diff --git a/plugins/NetBox/v1/defaultContent/Capacity/power.dash.json b/plugins/NetBox/v1/defaultContent/Capacity/power.dash.json new file mode 100644 index 00000000..e2dc3d35 --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Capacity/power.dash.json @@ -0,0 +1,606 @@ +{ + "name": "Power", + "schemaVersion": "1.5", + "timeframe": "none", + "variables": [], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "cbf41122-ff57-4c66-9944-5788eb0abd4f", + "x": 0, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Total Power Feeds", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[powerFeeds]}}", + "name": "powerFeeds", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Power Feeds" + } + } + } + } + }, + { + "i": "4188eeeb-4b47-4de2-99a5-be96ceb65615", + "x": 1, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Available Power", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[powerFeeds]}}", + "name": "powerFeeds", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "sum", + "names": [ + "availableKva" + ] + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "availableKva_sum", + "comparisonColumn": "none", + "label": "kVA" + } + } + } + } + }, + { + "i": "41e2a680-1cf8-4e07-9651-8516af5c09d3", + "x": 2, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Power Panels", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[powerFeeds]}}", + "name": "powerFeeds", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "distinctCount", + "names": [ + "power_panel.name" + ] + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "power_panel.name_distinctCount", + "comparisonColumn": "none", + "label": "Power Panels" + } + } + } + } + }, + { + "i": "b94a970e-eae1-441b-a0c6-0bae9c905e6c", + "x": 3, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Sites with Power Feeds", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[powerFeeds]}}", + "name": "powerFeeds", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "distinctCount", + "names": [ + "power_panel.site.name" + ] + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "power_panel.site.name_distinctCount", + "comparisonColumn": "none", + "label": "Sites" + } + } + } + } + }, + { + "i": "1b28f95c-02f6-4ab9-aa29-3f01b1438824", + "x": 0, + "y": 2, + "w": 2, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Available Power by Site", + "description": "Top 15 sites by available power (kVA)", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[powerFeeds]}}", + "name": "powerFeeds", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "power_panel.site.name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "sum", + "names": [ + "availableKva" + ] + } + ] + }, + "sort": { + "by": [ + [ + "availableKva_sum", + "desc" + ] + ], + "top": 15 + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "power_panel.site.name_uniqueValues", + "yAxisData": [ + "availableKva_sum" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "kVA", + "showXAxisLabel": false, + "showYAxisLabel": true, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "power_panel.site.name_uniqueValues", + "type": "nominal", + "title": "Site" + }, + "y": { + "field": "availableKva_sum", + "type": "quantitative", + "title": "Available Power (kVA)" + } + }, + "style": { + "cartesianHorizontal": true + } + } + } + } + }, + { + "i": "52b9fc68-40c6-444e-8c4c-ac5dca54e3d2", + "x": 2, + "y": 2, + "w": 2, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Power Feeds by Status", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[powerFeeds]}}", + "name": "powerFeeds", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "statusLabel", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "labelColumn": "statusLabel_uniqueValues", + "hideCenterValue": false, + "showValuesAsPercentage": false, + "legendPosition": "auto", + "legendMode": "table" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "pie", + "encoding": { + "label": { + "field": "statusLabel_uniqueValues", + "type": "nominal", + "title": "Status" + }, + "value": { + "field": "count", + "type": "quantitative", + "title": "Count" + } + }, + "style": { + "pieInnerRadius": 60, + "pieDonutCenterValue": "total", + "labelFontSize": 16, + "pieLegendStyle": "table", + "mappedColors": { + "Active": "#2fb344", + "Planned": "#17a2b8", + "Offline": "#9ba3af", + "Failed": "#d63939" + } + } + } + } + } + }, + { + "i": "0aace71b-f7db-4a1f-ab07-da3424841520", + "x": 0, + "y": 6, + "w": 4, + "h": 7, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Power Feeds", + "description": "Power feeds by site and rack, with available power and maximum utilization", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[powerFeeds]}}", + "name": "powerFeeds", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "power_panel.site.name", + "asc" + ], + [ + "rack.name", + "asc" + ], + [ + "name", + "asc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "power_panel.site.name", + "rack.name", + "name", + "power_panel.name", + "phaseLabel", + "voltage", + "amperage", + "availableKva", + "max_utilization", + "statusLabel", + "connected" + ], + "hiddenColumns": [ + "typeLabel", + "supplyLabel", + "tenant.name", + "description", + "created", + "last_updated" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "power_panel.site.name", + "title": "Site", + "renderer": { + "type": "text" + } + }, + { + "field": "rack.name", + "title": "Rack", + "renderer": { + "type": "text" + } + }, + { + "field": "name", + "title": "Power Feed", + "renderer": { + "type": "text" + } + }, + { + "field": "power_panel.name", + "title": "Power Panel", + "renderer": { + "type": "text" + } + }, + { + "field": "phaseLabel", + "title": "Phase", + "renderer": { + "type": "text" + } + }, + { + "field": "voltage", + "title": "Voltage (V)", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "amperage", + "title": "Amperage (A)", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "availableKva", + "title": "Available Power (kVA)", + "renderer": { + "type": "number", + "decimals": 2 + }, + "align": "right" + }, + { + "field": "max_utilization", + "title": "Max Utilization", + "renderer": { + "type": "progress", + "max": 100 + } + }, + { + "field": "statusLabel", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#2fb344", + "Planned": "#17a2b8", + "Offline": "#9ba3af", + "Failed": "#d63939" + } + } + }, + { + "field": "connected", + "title": "Connected", + "renderer": { + "type": "boolean", + "trueLabel": "Yes", + "falseLabel": "No" + }, + "align": "center" + } + ] + } + } + } + } + }, + { + "i": "5ed849da-0f2b-454a-88dc-bb37e8c73285", + "x": 0, + "y": 13, + "w": 4, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Power Feed Details", + "description": "All power feeds, including any power feed custom fields", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[powerFeeds]}}", + "name": "powerFeeds", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "power_panel.site.name", + "asc" + ], + [ + "rack.name", + "asc" + ], + [ + "name", + "asc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "name", + "power_panel.site.name", + "rack.name", + "power_panel.name", + "statusLabel", + "typeLabel", + "supplyLabel", + "phaseLabel", + "tenant.name", + "description" + ], + "hiddenColumns": [ + "voltage", + "amperage", + "availableKva", + "max_utilization", + "connected", + "created", + "last_updated" + ] + } + } + } + } + } + ] + } +} diff --git a/plugins/NetBox/v1/defaultContent/Capacity/rackCapacity.dash.json b/plugins/NetBox/v1/defaultContent/Capacity/rackCapacity.dash.json new file mode 100644 index 00000000..3321948a --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Capacity/rackCapacity.dash.json @@ -0,0 +1,569 @@ +{ + "name": "Rack Capacity", + "schemaVersion": "1.5", + "timeframe": "none", + "variables": [], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "d15771ec-0ca0-4434-b854-4709532f339a", + "x": 0, + "y": 0, + "w": 4, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Rack Space Summary", + "description": "Rack units used on either face, across all racks", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[rackUtilization]}}", + "name": "rackUtilization", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + }, + { + "type": "sum", + "names": [ + "uHeight" + ] + }, + { + "type": "sum", + "names": [ + "usedUnits" + ] + }, + { + "type": "sum", + "names": [ + "availableUnits" + ] + }, + { + "type": "mean", + "names": [ + "utilization" + ] + }, + { + "type": "sum", + "names": [ + "deviceCount" + ] + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Racks" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Racks" + }, + { + "field": "uHeight_sum", + "type": "quantitative", + "title": "Rack Units" + }, + { + "field": "usedUnits_sum", + "type": "quantitative", + "title": "Used Units" + }, + { + "field": "availableUnits_sum", + "type": "quantitative", + "title": "Available Units" + }, + { + "field": "utilization_mean", + "type": "quantitative", + "title": "Average Utilization" + }, + { + "field": "deviceCount_sum", + "type": "quantitative", + "title": "Racked Devices" + } + ] + }, + "style": { + "scalarBoxWidth": 310, + "scalarBoxHeight": 140, + "scalarFontSize": 48 + } + } + } + } + }, + { + "i": "8f9df73b-a543-409b-a217-3f3e5778f12f", + "x": 0, + "y": 2, + "w": 2, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Top 15 Racks by Utilization", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[rackUtilization]}}", + "name": "rackUtilization", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "utilization", + "desc" + ] + ], + "top": 15 + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "rack", + "yAxisData": [ + "utilization" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "Utilization (%)", + "showXAxisLabel": false, + "showYAxisLabel": true, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "rack", + "type": "nominal", + "title": "Rack" + }, + "y": { + "field": "utilization", + "type": "quantitative", + "title": "Utilization" + } + }, + "style": { + "cartesianHorizontal": true, + "cartesianYAxisRangeMode": "percentage" + } + } + } + } + }, + { + "i": "7b57f4a0-6736-4f2e-b104-529f7449f052", + "x": 2, + "y": 2, + "w": 2, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Racks per Site", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[rackUtilization]}}", + "name": "rackUtilization", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "site", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + }, + { + "type": "sum", + "names": [ + "deviceCount" + ] + }, + { + "type": "sum", + "names": [ + "usedUnits" + ] + }, + { + "type": "sum", + "names": [ + "availableUnits" + ] + }, + { + "type": "mean", + "names": [ + "utilization" + ] + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ], + [ + "site_uniqueValues", + "asc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "site_uniqueValues", + "count", + "deviceCount_sum", + "usedUnits_sum", + "availableUnits_sum", + "utilization_mean" + ], + "hiddenColumns": [], + "columnDisplayNames": { + "site_uniqueValues": "Site", + "count": "Racks", + "deviceCount_sum": "Devices", + "usedUnits_sum": "Used Units", + "availableUnits_sum": "Available Units", + "utilization_mean": "Average Utilization" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "site_uniqueValues", + "title": "Site", + "renderer": { + "type": "text" + } + }, + { + "field": "count", + "title": "Racks", + "renderer": { + "type": "bar" + } + }, + { + "field": "deviceCount_sum", + "title": "Devices", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "usedUnits_sum", + "title": "Used Units", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "availableUnits_sum", + "title": "Available Units", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "utilization_mean", + "title": "Average Utilization", + "renderer": { + "type": "progress", + "max": 100 + } + } + ] + } + } + } + } + }, + { + "i": "df7f4b44-8a16-4b73-bdc5-c3608f110f5d", + "x": 0, + "y": 7, + "w": 4, + "h": 6, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Rack Utilization", + "description": "Rack units used on either face of each rack", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[rackUtilization]}}", + "name": "rackUtilization", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "utilization", + "desc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "rack", + "site", + "location", + "uHeight", + "deviceCount", + "usedUnits", + "availableUnits", + "frontUsed", + "rearUsed", + "utilization" + ], + "hiddenColumns": [] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "rack", + "title": "Rack", + "renderer": { + "type": "text" + } + }, + { + "field": "site", + "title": "Site", + "renderer": { + "type": "text" + } + }, + { + "field": "location", + "title": "Location", + "renderer": { + "type": "text" + } + }, + { + "field": "uHeight", + "title": "U Height", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "deviceCount", + "title": "Devices", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "usedUnits", + "title": "Used Units", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "availableUnits", + "title": "Available Units", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "frontUsed", + "title": "Front Used", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "rearUsed", + "title": "Rear Used", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "utilization", + "title": "Utilization", + "renderer": { + "type": "progress", + "max": 100 + } + } + ] + } + } + } + } + }, + { + "i": "c4e4ec98-facd-4e81-8875-b5956c6a9bc4", + "x": 0, + "y": 13, + "w": 4, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Rack Details", + "description": "Includes any rack custom fields", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[racks]}}", + "name": "racks", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "site.name", + "asc" + ], + [ + "display", + "asc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "display", + "status.label", + "site.name", + "location.name", + "role.name", + "u_height", + "device_count", + "powerfeed_count", + "tenant.name", + "facility_id", + "display_url" + ], + "hiddenColumns": [ + "created", + "serial", + "asset_tag", + "form_factor.label" + ] + } + } + } + } + } + ] + } +} diff --git a/plugins/NetBox/v1/defaultContent/Inventory/changeActivity.dash.json b/plugins/NetBox/v1/defaultContent/Inventory/changeActivity.dash.json new file mode 100644 index 00000000..d0594551 --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Inventory/changeActivity.dash.json @@ -0,0 +1,677 @@ +{ + "name": "Change Activity", + "schemaVersion": "1.5", + "timeframe": "last7days", + "variables": [], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "56fb80c3-dfd7-415f-9aba-59a3b3c27dc5", + "x": 0, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Total Changes", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[objectChanges]}}", + "name": "objectChanges", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Changes" + } + } + } + } + }, + { + "i": "bf1df4dc-5ec0-486d-9ee3-8c458a20f5c1", + "x": 1, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Active Users", + "description": "Users who made at least one change", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[objectChanges]}}", + "name": "objectChanges", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "distinctCount", + "names": [ + "user_name" + ] + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "user_name_distinctCount", + "comparisonColumn": "none", + "label": "Users" + } + } + } + } + }, + { + "i": "423fe515-ea86-41c6-a167-80c400bba75a", + "x": 2, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Objects Created", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[objectChanges]}}", + "name": "objectChanges", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "action.value", + "operation": "equals", + "value": "create" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Created" + } + } + } + } + }, + { + "i": "0ca0fc13-e4a1-445a-a398-0bceb6d8d5aa", + "x": 3, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Objects Deleted", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[objectChanges]}}", + "name": "objectChanges", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "action.value", + "operation": "equals", + "value": "delete" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Deleted" + } + } + } + } + }, + { + "i": "04eacbc6-1e99-4fe7-a7ce-fdec18ef8aa0", + "x": 0, + "y": 2, + "w": 3, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Changes Over Time", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[objectChanges]}}", + "name": "objectChanges", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "time", + "byDay" + ], + [ + "action.label", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "time_byDay", + "asc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "time_byDay", + "yAxisData": [ + "count" + ], + "xAxisGroup": "action.label_uniqueValues", + "xAxisLabel": "", + "yAxisLabel": "Changes", + "showXAxisLabel": false, + "showYAxisLabel": true, + "showLegend": true, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "time_byDay", + "type": "temporal", + "title": "Day" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Changes" + }, + "series": { + "field": "action.label_uniqueValues", + "type": "nominal", + "title": "Action" + } + }, + "style": { + "cartesianStack": "on", + "legendPosition": "bottom", + "mappedColors": { + "Created": "#2fb344", + "Updated": "#206bc4", + "Deleted": "#d63939" + } + } + } + } + } + }, + { + "i": "b9d25f0e-f8ba-4fc2-b7f2-ae9d7a6eca32", + "x": 3, + "y": 2, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Changes by Action", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[objectChanges]}}", + "name": "objectChanges", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "action.label", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "labelColumn": "action.label_uniqueValues", + "hideCenterValue": false, + "showValuesAsPercentage": false, + "legendPosition": "auto", + "legendMode": "table" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "pie", + "encoding": { + "label": { + "field": "action.label_uniqueValues", + "type": "nominal", + "title": "Action" + }, + "value": { + "field": "count", + "type": "quantitative", + "title": "Count" + } + }, + "style": { + "pieInnerRadius": 60, + "pieDonutCenterValue": "total", + "labelFontSize": 16, + "pieLegendStyle": "table", + "mappedColors": { + "Created": "#2fb344", + "Updated": "#206bc4", + "Deleted": "#d63939" + } + } + } + } + } + }, + { + "i": "7e03f124-829d-4ebb-a459-66e5ad1a39b4", + "x": 0, + "y": 5, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Top 10 Users by Changes", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[objectChanges]}}", + "name": "objectChanges", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "user_name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ], + "top": 10 + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "user_name_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "user_name_uniqueValues", + "type": "nominal", + "title": "User" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Changes" + } + }, + "style": { + "cartesianHorizontal": true + } + } + } + } + }, + { + "i": "67c086f7-8b28-4e84-9e99-3b0095630bd5", + "x": 2, + "y": 5, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Top 10 Object Types by Changes", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[objectChanges]}}", + "name": "objectChanges", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "changed_object_type", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ], + "top": 10 + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "changed_object_type_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "changed_object_type_uniqueValues", + "type": "nominal", + "title": "Object Type" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Changes" + } + }, + "style": { + "cartesianHorizontal": true + } + } + } + } + }, + { + "i": "deaf1b8a-00db-4774-8b7f-db8771fc3930", + "x": 0, + "y": 8, + "w": 4, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Recent Changes", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[objectChanges]}}", + "name": "objectChanges", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "time", + "desc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "time", + "user_name", + "action.label", + "changed_object_type", + "object_repr", + "message" + ], + "hiddenColumns": [] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "time", + "title": "Time", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "user_name", + "title": "User", + "renderer": { + "type": "text" + } + }, + { + "field": "action.label", + "title": "Action", + "renderer": { + "type": "badge", + "colors": { + "Created": "#2fb344", + "Updated": "#206bc4", + "Deleted": "#d63939" + } + } + }, + { + "field": "changed_object_type", + "title": "Object Type", + "renderer": { + "type": "text" + } + }, + { + "field": "object_repr", + "title": "Object", + "renderer": { + "type": "text" + } + }, + { + "field": "message", + "title": "Message", + "renderer": { + "type": "text" + } + } + ] + } + } + } + } + } + ] + } +} diff --git a/plugins/NetBox/v1/defaultContent/Inventory/dataQuality.dash.json b/plugins/NetBox/v1/defaultContent/Inventory/dataQuality.dash.json new file mode 100644 index 00000000..5b549c7e --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Inventory/dataQuality.dash.json @@ -0,0 +1,1101 @@ +{ + "name": "Data Quality", + "schemaVersion": "1.5", + "timeframe": "none", + "variables": [], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "aa5f7ca1-7d27-4e8a-9eae-3027afe37ba9", + "x": 0, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices Missing Serial", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "missingSerial", + "operation": "equals", + "value": "true" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Devices" + } + } + } + } + }, + { + "i": "081f5de9-5ec8-492d-92da-d528d02eed0c", + "x": 1, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices Missing Primary IP", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "missingPrimaryIp", + "operation": "equals", + "value": "true" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Devices" + } + } + } + } + }, + { + "i": "1fc7ffac-15b2-49e1-8a3a-79f1e725b9b6", + "x": 2, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices Missing Tenant", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "missingTenant", + "operation": "equals", + "value": "true" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Devices" + } + } + } + } + }, + { + "i": "e5954e24-f656-43fb-b9fe-b6dfb3349c62", + "x": 3, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices Missing Platform", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "missingPlatform", + "operation": "equals", + "value": "true" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Devices" + } + } + } + } + }, + { + "i": "5489be6a-e524-4279-bda5-9f7071de194f", + "x": 0, + "y": 2, + "w": 2, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Incomplete Devices", + "description": "Devices missing a serial, primary IP, tenant or platform", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "or", + "filters": [ + { + "column": "missingSerial", + "operation": "equals", + "value": "true" + }, + { + "column": "missingPrimaryIp", + "operation": "equals", + "value": "true" + }, + { + "column": "missingTenant", + "operation": "equals", + "value": "true" + }, + { + "column": "missingPlatform", + "operation": "equals", + "value": "true" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Devices" + } + } + } + } + }, + { + "i": "8565907d-84a9-4f6e-96b8-2ac23dc24719", + "x": 2, + "y": 2, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Stale Devices", + "description": "Devices not updated in over a year", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "daysSinceUpdate", + "operation": "greaterthan", + "value": "365" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Devices" + } + } + } + } + }, + { + "i": "5bf30f9d-0db8-4360-b52c-d192a5e72d1c", + "x": 3, + "y": 2, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Unassigned IP Addresses", + "description": "IP addresses not assigned to an interface", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[ipAddresses]}}", + "name": "ipAddresses", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "assignment": "false" + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "IP Addresses" + } + } + } + } + }, + { + "i": "5dfd6fa5-d7eb-48ad-b374-ee1c4a7422fe", + "x": 0, + "y": 4, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Incomplete Devices by Site", + "description": "Top 10 sites by devices missing a serial, primary IP, tenant or platform", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "or", + "filters": [ + { + "column": "missingSerial", + "operation": "equals", + "value": "true" + }, + { + "column": "missingPrimaryIp", + "operation": "equals", + "value": "true" + }, + { + "column": "missingTenant", + "operation": "equals", + "value": "true" + }, + { + "column": "missingPlatform", + "operation": "equals", + "value": "true" + } + ] + }, + "group": { + "by": [ + [ + "site.name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ], + "top": 10 + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "site.name_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "site.name_uniqueValues", + "type": "nominal", + "title": "Site" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Devices" + } + }, + "style": { + "cartesianHorizontal": true + } + } + } + } + }, + { + "i": "d2c41a8e-79ce-47d0-a779-588d421ed4ac", + "x": 2, + "y": 4, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Incomplete Devices by Role", + "description": "Top 10 roles by devices missing a serial, primary IP, tenant or platform", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "or", + "filters": [ + { + "column": "missingSerial", + "operation": "equals", + "value": "true" + }, + { + "column": "missingPrimaryIp", + "operation": "equals", + "value": "true" + }, + { + "column": "missingTenant", + "operation": "equals", + "value": "true" + }, + { + "column": "missingPlatform", + "operation": "equals", + "value": "true" + } + ] + }, + "group": { + "by": [ + [ + "role.name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ], + "top": 10 + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "role.name_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "role.name_uniqueValues", + "type": "nominal", + "title": "Role" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Devices" + } + }, + "style": { + "cartesianHorizontal": true + } + } + } + } + }, + { + "i": "6bb34eec-6762-4ff0-b057-ba4e2ec61159", + "x": 0, + "y": 7, + "w": 4, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices with Data Gaps", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "or", + "filters": [ + { + "column": "missingSerial", + "operation": "equals", + "value": "true" + }, + { + "column": "missingPrimaryIp", + "operation": "equals", + "value": "true" + }, + { + "column": "missingTenant", + "operation": "equals", + "value": "true" + }, + { + "column": "missingPlatform", + "operation": "equals", + "value": "true" + } + ] + }, + "sort": { + "by": [ + [ + "site.name", + "asc" + ], + [ + "display", + "asc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "display", + "status.label", + "role.name", + "site.name", + "missingSerial", + "missingPrimaryIp", + "missingTenant", + "missingPlatform", + "serial", + "primary_ip.display", + "tenant.name", + "platform.name", + "display_url" + ], + "hiddenColumns": [ + "daysSinceUpdate", + "created", + "description", + "oob_ip.address", + "asset_tag", + "device_type.manufacturer.name", + "device_type.model", + "rack.name", + "position", + "location.name" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "display_url", + "title": "Device", + "renderer": { + "type": "link", + "labelField": "display" + } + }, + { + "field": "status.label", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#2fb344", + "Planned": "#17a2b8", + "Staged": "#206bc4", + "Failed": "#d63939", + "Offline": "#9ba3af", + "Inventory": "#ae3ec9", + "Decommissioning": "#f59f00" + } + } + }, + { + "field": "role.name", + "title": "Role", + "renderer": { + "type": "text" + } + }, + { + "field": "site.name", + "title": "Site", + "renderer": { + "type": "text" + } + }, + { + "field": "missingSerial", + "title": "Serial", + "renderer": { + "type": "boolean", + "trueLabel": "Missing", + "falseLabel": "—", + "trueColor": "#f59f00", + "falseColor": "#9ba3af" + }, + "align": "center" + }, + { + "field": "missingPrimaryIp", + "title": "Primary IP", + "renderer": { + "type": "boolean", + "trueLabel": "Missing", + "falseLabel": "—", + "trueColor": "#f59f00", + "falseColor": "#9ba3af" + }, + "align": "center" + }, + { + "field": "missingTenant", + "title": "Tenant", + "renderer": { + "type": "boolean", + "trueLabel": "Missing", + "falseLabel": "—", + "trueColor": "#f59f00", + "falseColor": "#9ba3af" + }, + "align": "center" + }, + { + "field": "missingPlatform", + "title": "Platform", + "renderer": { + "type": "boolean", + "trueLabel": "Missing", + "falseLabel": "—", + "trueColor": "#f59f00", + "falseColor": "#9ba3af" + }, + "align": "center" + }, + { + "field": "last_updated", + "title": "Last Updated", + "renderer": { + "type": "date", + "relative": true + } + } + ] + } + } + } + } + }, + { + "i": "517507f4-2275-4b77-925d-b99dac353728", + "x": 0, + "y": 12, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Stale Device Details", + "description": "Devices not updated in over a year", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "daysSinceUpdate", + "operation": "greaterthan", + "value": "365" + } + ] + }, + "sort": { + "by": [ + [ + "daysSinceUpdate", + "desc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "display", + "daysSinceUpdate", + "last_updated", + "status.label", + "role.name", + "site.name", + "device_type.manufacturer.name", + "device_type.model", + "display_url" + ], + "hiddenColumns": [ + "missingSerial", + "missingPrimaryIp", + "missingTenant", + "missingPlatform", + "created", + "description", + "oob_ip.address", + "asset_tag" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "display_url", + "title": "Device", + "renderer": { + "type": "link", + "labelField": "display" + } + }, + { + "field": "daysSinceUpdate", + "title": "Days Since Update", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "last_updated", + "title": "Last Updated", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "status.label", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#2fb344", + "Planned": "#17a2b8", + "Staged": "#206bc4", + "Failed": "#d63939", + "Offline": "#9ba3af", + "Inventory": "#ae3ec9", + "Decommissioning": "#f59f00" + } + } + }, + { + "field": "role.name", + "title": "Role", + "renderer": { + "type": "text" + } + }, + { + "field": "site.name", + "title": "Site", + "renderer": { + "type": "text" + } + }, + { + "field": "device_type.manufacturer.name", + "title": "Manufacturer", + "renderer": { + "type": "text" + } + }, + { + "field": "device_type.model", + "title": "Model", + "renderer": { + "type": "text" + } + } + ] + } + } + } + } + }, + { + "i": "edf1a364-5f9b-41d1-99da-d9a487e3ad2d", + "x": 0, + "y": 16, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Unassigned IP Address Details", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[ipAddresses]}}", + "name": "ipAddresses", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "assignment": "false" + }, + "sort": { + "by": [ + [ + "address", + "asc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "address", + "status.label", + "vrfName", + "dns_name", + "tenant.name", + "description", + "last_updated", + "display_url" + ], + "hiddenColumns": [ + "display", + "created", + "family.label", + "assigned", + "assignedTo", + "role.label" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "display_url", + "title": "Address", + "renderer": { + "type": "link", + "labelField": "address" + } + }, + { + "field": "status.label", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#2fb344", + "Reserved": "#17a2b8", + "Deprecated": "#d63939", + "DHCP": "#2fb344", + "SLAAC": "#2fb344" + } + } + }, + { + "field": "vrfName", + "title": "VRF", + "renderer": { + "type": "text" + } + }, + { + "field": "dns_name", + "title": "DNS Name", + "renderer": { + "type": "text" + } + }, + { + "field": "tenant.name", + "title": "Tenant", + "renderer": { + "type": "text" + } + }, + { + "field": "description", + "title": "Description", + "renderer": { + "type": "text" + } + }, + { + "field": "last_updated", + "title": "Last Updated", + "renderer": { + "type": "date", + "relative": true + } + } + ] + } + } + } + } + } + ] + } +} diff --git a/plugins/NetBox/v1/defaultContent/Inventory/deviceInventory.dash.json b/plugins/NetBox/v1/defaultContent/Inventory/deviceInventory.dash.json new file mode 100644 index 00000000..d99d67fb --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Inventory/deviceInventory.dash.json @@ -0,0 +1,457 @@ +{ + "name": "Device Inventory", + "schemaVersion": "1.5", + "timeframe": "none", + "variables": [], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "5ae1af6e-dc82-4cc0-a057-e778c99fe57a", + "x": 0, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Devices" + } + } + } + } + }, + { + "i": "545a65fe-5988-4294-9d6e-39af3f39bfae", + "x": 1, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Device Models", + "description": "Distinct device types in use", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "distinctCount", + "names": [ + "device_type.model" + ] + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "device_type.model_distinctCount", + "comparisonColumn": "none", + "label": "Models" + } + } + } + } + }, + { + "i": "5b330995-da8d-4232-942d-ca0f24a0b657", + "x": 2, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Manufacturers", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "distinctCount", + "names": [ + "device_type.manufacturer.name" + ] + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "device_type.manufacturer.name_distinctCount", + "comparisonColumn": "none", + "label": "Manufacturers" + } + } + } + } + }, + { + "i": "66dac578-577a-441e-bb91-56978ed02a5f", + "x": 3, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Sites with Devices", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "distinctCount", + "names": [ + "site.name" + ] + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "site.name_distinctCount", + "comparisonColumn": "none", + "label": "Sites" + } + } + } + } + }, + { + "i": "23087dfa-b635-48ed-8f78-44e8cf87c627", + "x": 0, + "y": 2, + "w": 2, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices per Model", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "device_type.model", + "uniqueValues" + ], + [ + "device_type.manufacturer.name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ], + [ + "device_type.model_uniqueValues", + "asc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "device_type.model_uniqueValues", + "device_type.manufacturer.name_uniqueValues", + "count" + ], + "hiddenColumns": [], + "columnDisplayNames": { + "device_type.model_uniqueValues": "Model", + "device_type.manufacturer.name_uniqueValues": "Manufacturer", + "count": "Devices" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "device_type.model_uniqueValues", + "title": "Model", + "renderer": { + "type": "text" + } + }, + { + "field": "device_type.manufacturer.name_uniqueValues", + "title": "Manufacturer", + "renderer": { + "type": "text" + } + }, + { + "field": "count", + "title": "Devices", + "renderer": { + "type": "bar" + } + } + ] + } + } + } + } + }, + { + "i": "7d8520f2-af66-4b68-900a-660398009166", + "x": 2, + "y": 2, + "w": 2, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices per Site", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "site.name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ], + [ + "site.name_uniqueValues", + "asc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "site.name_uniqueValues", + "count" + ], + "hiddenColumns": [], + "columnDisplayNames": { + "site.name_uniqueValues": "Site", + "count": "Devices" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "site.name_uniqueValues", + "title": "Site", + "renderer": { + "type": "text" + } + }, + { + "field": "count", + "title": "Devices", + "renderer": { + "type": "bar" + } + } + ] + } + } + } + } + }, + { + "i": "f6d6f11a-1e66-49b7-9d25-bc0814fde71f", + "x": 0, + "y": 7, + "w": 4, + "h": 7, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Device Details", + "description": "All devices, including any device custom fields", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "site.name", + "asc" + ], + [ + "display", + "asc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "display", + "device_type.model", + "device_type.manufacturer.name", + "site.name", + "role.name", + "rack.name", + "position", + "status.label", + "serial", + "primary_ip.display", + "tenant.name", + "display_url" + ], + "hiddenColumns": [ + "missingSerial", + "missingPrimaryIp", + "missingTenant", + "missingPlatform", + "daysSinceUpdate", + "created", + "description", + "oob_ip.address", + "asset_tag", + "platform.name", + "location.name", + "cluster.name", + "parent_device.name", + "last_updated" + ] + } + } + } + } + } + ] + } +} diff --git a/plugins/NetBox/v1/defaultContent/Inventory/lifecycleAndCircuits.dash.json b/plugins/NetBox/v1/defaultContent/Inventory/lifecycleAndCircuits.dash.json new file mode 100644 index 00000000..c558dfa4 --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Inventory/lifecycleAndCircuits.dash.json @@ -0,0 +1,972 @@ +{ + "name": "Lifecycle and Circuits", + "schemaVersion": "1.5", + "timeframe": "none", + "variables": [], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "ecc23965-115b-46bf-a5c2-6a0ea2f4401a", + "x": 0, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Inactive Devices", + "description": "Planned, staged, offline, failed, inventory or decommissioning", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "status.value", + "operation": "notequals", + "value": "active" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Devices" + } + } + } + } + }, + { + "i": "0832f840-dadd-4e2f-903e-8079a731425a", + "x": 1, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Inactive Virtual Machines", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[virtualMachines]}}", + "name": "virtualMachines", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "status.value", + "operation": "notequals", + "value": "active" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Virtual Machines" + } + } + } + } + }, + { + "i": "50ab53f2-c668-4c41-98ac-d1dea71fcc26", + "x": 2, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Circuits", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[circuits]}}", + "name": "circuits", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Circuits" + } + } + } + } + }, + { + "i": "773fabb5-5e49-4517-aa0c-9b59a87b958a", + "x": 3, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Circuits Terminating Within 90 Days", + "description": "Includes circuits already past their termination date", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[circuits]}}", + "name": "circuits", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "termination_date", + "operation": "notempty" + }, + { + "column": "daysUntilTermination", + "operation": "lessthan", + "value": "91" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Circuits" + } + } + } + } + }, + { + "i": "07a04792-9e47-4ad6-971a-1c837ed1655c", + "x": 0, + "y": 2, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices by Status", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "status.label", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "status.label_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "status.label_uniqueValues", + "type": "nominal", + "title": "Status" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Devices" + } + }, + "style": { + "cartesianColorRules": [ + { + "label": "Active", + "color": "#2fb344" + }, + { + "label": "Planned", + "color": "#17a2b8" + }, + { + "label": "Staged", + "color": "#206bc4" + }, + { + "label": "Failed", + "color": "#d63939" + }, + { + "label": "Offline", + "color": "#9ba3af" + }, + { + "label": "Inventory", + "color": "#ae3ec9" + }, + { + "label": "Decommissioning", + "color": "#f59f00" + } + ] + } + } + } + } + }, + { + "i": "5296e27c-3e1d-42bc-a1a8-22102351efab", + "x": 2, + "y": 2, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Virtual Machines by Status", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[virtualMachines]}}", + "name": "virtualMachines", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "status.label", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "status.label_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "status.label_uniqueValues", + "type": "nominal", + "title": "Status" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Virtual Machines" + } + }, + "style": { + "cartesianColorRules": [ + { + "label": "Active", + "color": "#2fb344" + }, + { + "label": "Planned", + "color": "#17a2b8" + }, + { + "label": "Staged", + "color": "#206bc4" + }, + { + "label": "Failed", + "color": "#d63939" + }, + { + "label": "Offline", + "color": "#9ba3af" + }, + { + "label": "Paused", + "color": "#f76707" + }, + { + "label": "Decommissioning", + "color": "#f59f00" + } + ] + } + } + } + } + }, + { + "i": "9a3d6f17-01d5-41ae-9714-c27e86892d57", + "x": 0, + "y": 5, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices Not Active", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "status.value", + "operation": "notequals", + "value": "active" + } + ] + }, + "sort": { + "by": [ + [ + "status.label", + "asc" + ], + [ + "display", + "asc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "display", + "status.label", + "role.name", + "device_type.manufacturer.name", + "device_type.model", + "platform.name", + "site.name", + "rack.name", + "position", + "primary_ip.display", + "tenant.name", + "serial", + "display_url" + ], + "hiddenColumns": [ + "missingSerial", + "missingPrimaryIp", + "missingTenant", + "missingPlatform", + "daysSinceUpdate", + "created", + "description", + "oob_ip.address", + "asset_tag" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "display_url", + "title": "Device", + "renderer": { + "type": "link", + "labelField": "display" + } + }, + { + "field": "status.label", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#2fb344", + "Planned": "#17a2b8", + "Staged": "#206bc4", + "Failed": "#d63939", + "Offline": "#9ba3af", + "Inventory": "#ae3ec9", + "Decommissioning": "#f59f00" + } + } + }, + { + "field": "role.name", + "title": "Role", + "renderer": { + "type": "text" + } + }, + { + "field": "device_type.manufacturer.name", + "title": "Manufacturer", + "renderer": { + "type": "text" + } + }, + { + "field": "device_type.model", + "title": "Model", + "renderer": { + "type": "text" + } + }, + { + "field": "site.name", + "title": "Site", + "renderer": { + "type": "text" + } + }, + { + "field": "rack.name", + "title": "Rack", + "renderer": { + "type": "text" + } + }, + { + "field": "tenant.name", + "title": "Tenant", + "renderer": { + "type": "text" + } + }, + { + "field": "last_updated", + "title": "Last Updated", + "renderer": { + "type": "date", + "relative": true + } + } + ] + } + } + } + } + }, + { + "i": "0b9c0aca-8326-4ac4-90a7-0f2a16cdc7d8", + "x": 0, + "y": 9, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Circuits by Provider", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[circuits]}}", + "name": "circuits", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "provider.name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ], + "top": 10 + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "provider.name_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "provider.name_uniqueValues", + "type": "nominal", + "title": "Provider" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Circuits" + } + }, + "style": { + "cartesianHorizontal": true + } + } + } + } + }, + { + "i": "01161a70-8ee3-4af4-92a9-eb3ba327fa7a", + "x": 2, + "y": 9, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Circuits by Status", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[circuits]}}", + "name": "circuits", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "status.label", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "labelColumn": "status.label_uniqueValues", + "hideCenterValue": false, + "showValuesAsPercentage": false, + "legendPosition": "auto", + "legendMode": "table" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "pie", + "encoding": { + "label": { + "field": "status.label_uniqueValues", + "type": "nominal", + "title": "Status" + }, + "value": { + "field": "count", + "type": "quantitative", + "title": "Count" + } + }, + "style": { + "pieInnerRadius": 60, + "pieDonutCenterValue": "total", + "labelFontSize": 16, + "pieLegendStyle": "table", + "mappedColors": { + "Active": "#2fb344", + "Planned": "#17a2b8", + "Provisioning": "#206bc4", + "Offline": "#d63939", + "Deprovisioning": "#f59f00", + "Decommissioned": "#9ba3af" + } + } + } + } + } + }, + { + "i": "60ac6be0-e3a7-4eab-8ebe-25f7f08dec97", + "x": 0, + "y": 12, + "w": 4, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Circuit Terminations", + "description": "Circuits ordered by days until termination", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[circuits]}}", + "name": "circuits", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "daysUntilTermination", + "asc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "cid", + "provider.name", + "type.name", + "status.label", + "termination_date", + "daysUntilTermination", + "commit_rate", + "install_date", + "termination_a.termination.display", + "termination_z.termination.display", + "tenant.name", + "display_url" + ], + "hiddenColumns": [ + "created", + "last_updated", + "description" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "display_url", + "title": "Circuit ID", + "renderer": { + "type": "link", + "labelField": "cid" + } + }, + { + "field": "provider.name", + "title": "Provider", + "renderer": { + "type": "text" + } + }, + { + "field": "type.name", + "title": "Type", + "renderer": { + "type": "text" + } + }, + { + "field": "status.label", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#2fb344", + "Planned": "#17a2b8", + "Provisioning": "#206bc4", + "Offline": "#d63939", + "Deprovisioning": "#f59f00", + "Decommissioned": "#9ba3af" + } + } + }, + { + "field": "termination_date", + "title": "Termination Date", + "renderer": { + "type": "date" + } + }, + { + "field": "daysUntilTermination", + "title": "Days Until Termination", + "renderer": { + "type": "number", + "thresholds": [ + { + "to": 0, + "color": "#d63939" + }, + { + "to": 90, + "color": "#f59f00" + }, + { + "to": 1000000, + "color": "#2fb344" + } + ] + }, + "align": "right" + }, + { + "field": "commit_rate", + "title": "Commit Rate", + "renderer": { + "type": "number", + "compact": true, + "suffix": " Kbps" + }, + "align": "right" + }, + { + "field": "install_date", + "title": "Install Date", + "renderer": { + "type": "date" + } + }, + { + "field": "termination_a.termination.display", + "title": "Side A", + "renderer": { + "type": "text" + } + }, + { + "field": "termination_z.termination.display", + "title": "Side Z", + "renderer": { + "type": "text" + } + }, + { + "field": "tenant.name", + "title": "Tenant", + "renderer": { + "type": "text" + } + } + ] + } + } + } + } + } + ] + } +} diff --git a/plugins/NetBox/v1/defaultContent/Inventory/manifest.json b/plugins/NetBox/v1/defaultContent/Inventory/manifest.json new file mode 100644 index 00000000..c3813a5d --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Inventory/manifest.json @@ -0,0 +1,20 @@ +{ + "items": [ + { + "name": "deviceInventory", + "type": "dashboard" + }, + { + "name": "dataQuality", + "type": "dashboard" + }, + { + "name": "lifecycleAndCircuits", + "type": "dashboard" + }, + { + "name": "changeActivity", + "type": "dashboard" + } + ] +} diff --git a/plugins/NetBox/v1/defaultContent/Perspectives/circuit.dash.json b/plugins/NetBox/v1/defaultContent/Perspectives/circuit.dash.json new file mode 100644 index 00000000..54214db2 --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Perspectives/circuit.dash.json @@ -0,0 +1,179 @@ +{ + "name": "Circuit", + "schemaVersion": "1.5", + "timeframe": "last30days", + "variables": [ + "{{variables.[NetBox Circuit]}}" + ], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "783841cf-dd6e-4715-9a54-7b8479b8c2a3", + "x": 0, + "y": 0, + "w": 1, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Circuit Properties", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "datastream-properties", + "name": "properties", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[NetBox Circuits]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[NetBox Circuit]}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": [ + "name" + ], + "hiddenColumns": [ + "id", + "links", + "type", + "label", + "sourceId", + "sourceType", + "siteId", + "rackId", + "vrfId" + ] + } + } + }, + "variables": [ + "{{variables.[NetBox Circuit]}}" + ] + } + }, + { + "i": "af52a83e-2c86-4c5b-a474-42ac34a20a27", + "x": 1, + "y": 0, + "w": 3, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Change Log", + "description": "Changes recorded against this circuit", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[objectChanges]}}", + "name": "objectChanges", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "object": { + "variable": "{{variables.[NetBox Circuit]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Circuits]}}" + } + }, + "sort": { + "by": [ + [ + "time", + "desc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Circuit]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "time", + "user_name", + "action.label", + "object_repr", + "message" + ], + "hiddenColumns": [ + "changed_object_type" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "time", + "title": "Time", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "user_name", + "title": "User", + "renderer": { + "type": "text" + } + }, + { + "field": "action.label", + "title": "Action", + "renderer": { + "type": "badge", + "colors": { + "Created": "#2fb344", + "Updated": "#206bc4", + "Deleted": "#d63939" + } + } + }, + { + "field": "object_repr", + "title": "Object", + "renderer": { + "type": "text" + } + }, + { + "field": "message", + "title": "Message", + "renderer": { + "type": "text" + } + } + ] + } + } + } + } + } + ] + } +} diff --git a/plugins/NetBox/v1/defaultContent/Perspectives/device.dash.json b/plugins/NetBox/v1/defaultContent/Perspectives/device.dash.json new file mode 100644 index 00000000..7ba64544 --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Perspectives/device.dash.json @@ -0,0 +1,486 @@ +{ + "name": "Device", + "schemaVersion": "1.5", + "timeframe": "last30days", + "variables": [ + "{{variables.[NetBox Device]}}" + ], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "5d69700a-0cfb-401a-a8f1-a384fe86db5f", + "x": 0, + "y": 0, + "w": 1, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Device Properties", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "datastream-properties", + "name": "properties", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[NetBox Devices]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[NetBox Device]}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": [ + "name" + ], + "hiddenColumns": [ + "id", + "links", + "type", + "label", + "sourceId", + "sourceType", + "siteId", + "rackId", + "vrfId" + ] + } + } + }, + "variables": [ + "{{variables.[NetBox Device]}}" + ] + } + }, + { + "i": "586308e3-ef01-4c2b-8937-ce3081b02164", + "x": 1, + "y": 0, + "w": 3, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Interfaces", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deviceInterfaces]}}", + "name": "deviceInterfaces", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "name", + "asc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[NetBox Devices]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[NetBox Device]}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "name", + "type.label", + "enabled", + "speed", + "mode.label", + "untagged_vlan.display", + "connectedTo", + "cabled", + "mac_address", + "count_ipaddresses", + "description", + "display_url" + ], + "hiddenColumns": [ + "device.name", + "label", + "mgmt_only", + "mtu", + "duplex.label", + "lag.name", + "parent.name", + "taggedVlanCount", + "vrf.name", + "connected_endpoints_reachable", + "last_updated" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "display_url", + "title": "Interface", + "renderer": { + "type": "link", + "labelField": "name" + } + }, + { + "field": "type.label", + "title": "Type", + "renderer": { + "type": "text" + } + }, + { + "field": "enabled", + "title": "Enabled", + "renderer": { + "type": "boolean", + "trueLabel": "Yes", + "falseLabel": "No" + }, + "align": "center" + }, + { + "field": "speed", + "title": "Speed", + "renderer": { + "type": "number", + "compact": true, + "suffix": " Kbps" + }, + "align": "right" + }, + { + "field": "mode.label", + "title": "Mode", + "renderer": { + "type": "text" + } + }, + { + "field": "untagged_vlan.display", + "title": "Untagged VLAN", + "renderer": { + "type": "text" + } + }, + { + "field": "connectedTo", + "title": "Connected To", + "renderer": { + "type": "text" + } + }, + { + "field": "cabled", + "title": "Cabled", + "renderer": { + "type": "boolean", + "trueLabel": "Yes", + "falseLabel": "No" + }, + "align": "center" + }, + { + "field": "mac_address", + "title": "MAC Address", + "renderer": { + "type": "text" + } + }, + { + "field": "count_ipaddresses", + "title": "IPs", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "description", + "title": "Description", + "renderer": { + "type": "text" + } + } + ] + } + } + }, + "variables": [ + "{{variables.[NetBox Device]}}" + ] + } + }, + { + "i": "522b3b38-1fcd-455a-ab00-78544c606f98", + "x": 0, + "y": 5, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "IP Addresses", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[ipAddresses]}}", + "name": "ipAddresses", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "device": { + "variable": "{{variables.[NetBox Device]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Devices]}}" + } + }, + "sort": { + "by": [ + [ + "address", + "asc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Device]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "address", + "status.label", + "vrfName", + "dns_name", + "assignedTo", + "tenant.name", + "description", + "display_url" + ], + "hiddenColumns": [ + "display", + "created", + "family.label", + "assigned", + "role.label" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "display_url", + "title": "Address", + "renderer": { + "type": "link", + "labelField": "address" + } + }, + { + "field": "status.label", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#2fb344", + "Reserved": "#17a2b8", + "Deprecated": "#d63939", + "DHCP": "#2fb344", + "SLAAC": "#2fb344" + } + } + }, + { + "field": "vrfName", + "title": "VRF", + "renderer": { + "type": "text" + } + }, + { + "field": "dns_name", + "title": "DNS Name", + "renderer": { + "type": "text" + } + }, + { + "field": "assignedTo", + "title": "Assigned To", + "renderer": { + "type": "text" + } + }, + { + "field": "tenant.name", + "title": "Tenant", + "renderer": { + "type": "text" + } + }, + { + "field": "description", + "title": "Description", + "renderer": { + "type": "text" + } + } + ] + } + } + } + } + }, + { + "i": "20a1a299-769e-464d-8731-20eec0a996b7", + "x": 0, + "y": 8, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Change Log", + "description": "Changes recorded against this device", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[objectChanges]}}", + "name": "objectChanges", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "object": { + "variable": "{{variables.[NetBox Device]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Devices]}}" + } + }, + "sort": { + "by": [ + [ + "time", + "desc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Device]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "time", + "user_name", + "action.label", + "object_repr", + "message" + ], + "hiddenColumns": [ + "changed_object_type" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "time", + "title": "Time", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "user_name", + "title": "User", + "renderer": { + "type": "text" + } + }, + { + "field": "action.label", + "title": "Action", + "renderer": { + "type": "badge", + "colors": { + "Created": "#2fb344", + "Updated": "#206bc4", + "Deleted": "#d63939" + } + } + }, + { + "field": "object_repr", + "title": "Object", + "renderer": { + "type": "text" + } + }, + { + "field": "message", + "title": "Message", + "renderer": { + "type": "text" + } + } + ] + } + } + } + } + } + ] + } +} diff --git a/plugins/NetBox/v1/defaultContent/Perspectives/manifest.json b/plugins/NetBox/v1/defaultContent/Perspectives/manifest.json new file mode 100644 index 00000000..d31966c6 --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Perspectives/manifest.json @@ -0,0 +1,28 @@ +{ + "items": [ + { + "name": "site", + "type": "dashboard" + }, + { + "name": "rack", + "type": "dashboard" + }, + { + "name": "device", + "type": "dashboard" + }, + { + "name": "virtualMachine", + "type": "dashboard" + }, + { + "name": "prefix", + "type": "dashboard" + }, + { + "name": "circuit", + "type": "dashboard" + } + ] +} diff --git a/plugins/NetBox/v1/defaultContent/Perspectives/prefix.dash.json b/plugins/NetBox/v1/defaultContent/Perspectives/prefix.dash.json new file mode 100644 index 00000000..0605d7e8 --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Perspectives/prefix.dash.json @@ -0,0 +1,471 @@ +{ + "name": "Prefix", + "schemaVersion": "1.5", + "timeframe": "last30days", + "variables": [ + "{{variables.[NetBox Prefix]}}" + ], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "9881a921-a9e3-4856-be7b-7f26ef11ec5c", + "x": 0, + "y": 0, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Prefix Properties", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "datastream-properties", + "name": "properties", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[NetBox Prefixes]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[NetBox Prefix]}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": [ + "name" + ], + "hiddenColumns": [ + "id", + "links", + "type", + "label", + "sourceId", + "sourceType", + "siteId", + "rackId", + "vrfId" + ] + } + } + }, + "variables": [ + "{{variables.[NetBox Prefix]}}" + ] + } + }, + { + "i": "bf430aa6-68da-4fd3-90db-d202d90cbab1", + "x": 1, + "y": 0, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Prefix Utilization", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[prefixUtilization]}}", + "name": "prefixUtilization", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[NetBox Prefixes]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[NetBox Prefix]}}" + }, + "visualisation": { + "type": "data-stream-gauge", + "config": { + "data-stream-gauge": { + "value": { + "type": "mean", + "columns": [ + "utilization" + ] + }, + "label": "Utilization (%)", + "minimum": 0, + "maximum": 100 + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "gauge", + "encoding": { + "value": { + "field": "utilization", + "type": "quantitative", + "title": "Utilization" + } + }, + "style": { + "gaugeLabelText": "Utilization", + "gaugeBands": [ + { + "to": 0.8, + "color": "#2fb344" + }, + { + "to": 0.9, + "color": "#f59f00" + }, + { + "to": 1, + "color": "#d63939" + } + ] + } + } + }, + "variables": [ + "{{variables.[NetBox Prefix]}}" + ] + } + }, + { + "i": "b2b3dfa7-52c7-4065-8198-23466cb00eb0", + "x": 2, + "y": 0, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Address Space", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[prefixUtilization]}}", + "name": "prefixUtilization", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[NetBox Prefixes]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[NetBox Prefix]}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": [ + "prefix", + "vrf", + "status", + "size", + "used", + "utilization", + "netboxUrl" + ], + "hiddenColumns": [] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "size", + "type": "quantitative", + "title": "Addresses" + }, + { + "field": "used", + "type": "quantitative", + "title": "Used" + }, + { + "field": "utilization", + "type": "quantitative", + "title": "Utilization" + } + ] + }, + "style": { + "scalarBoxWidth": 300, + "scalarBoxHeight": 220, + "scalarFontSize": 56 + } + } + }, + "variables": [ + "{{variables.[NetBox Prefix]}}" + ] + } + }, + { + "i": "17000eb1-6f73-4ba6-981f-b9bacd2d6ff4", + "x": 0, + "y": 3, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "IP Addresses in Prefix", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[ipAddresses]}}", + "name": "ipAddresses", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "prefix": { + "variable": "{{variables.[NetBox Prefix]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Prefixes]}}" + } + }, + "sort": { + "by": [ + [ + "address", + "asc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Prefix]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "address", + "status.label", + "vrfName", + "dns_name", + "assignedTo", + "tenant.name", + "description", + "display_url" + ], + "hiddenColumns": [ + "display", + "created", + "family.label", + "assigned", + "role.label" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "display_url", + "title": "Address", + "renderer": { + "type": "link", + "labelField": "address" + } + }, + { + "field": "status.label", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#2fb344", + "Reserved": "#17a2b8", + "Deprecated": "#d63939", + "DHCP": "#2fb344", + "SLAAC": "#2fb344" + } + } + }, + { + "field": "vrfName", + "title": "VRF", + "renderer": { + "type": "text" + } + }, + { + "field": "dns_name", + "title": "DNS Name", + "renderer": { + "type": "text" + } + }, + { + "field": "assignedTo", + "title": "Assigned To", + "renderer": { + "type": "text" + } + }, + { + "field": "tenant.name", + "title": "Tenant", + "renderer": { + "type": "text" + } + }, + { + "field": "description", + "title": "Description", + "renderer": { + "type": "text" + } + } + ] + } + } + } + } + }, + { + "i": "892f873a-2e86-400d-9414-d1d02025fe83", + "x": 0, + "y": 7, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Change Log", + "description": "Changes recorded against this prefix", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[objectChanges]}}", + "name": "objectChanges", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "object": { + "variable": "{{variables.[NetBox Prefix]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Prefixes]}}" + } + }, + "sort": { + "by": [ + [ + "time", + "desc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Prefix]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "time", + "user_name", + "action.label", + "object_repr", + "message" + ], + "hiddenColumns": [ + "changed_object_type" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "time", + "title": "Time", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "user_name", + "title": "User", + "renderer": { + "type": "text" + } + }, + { + "field": "action.label", + "title": "Action", + "renderer": { + "type": "badge", + "colors": { + "Created": "#2fb344", + "Updated": "#206bc4", + "Deleted": "#d63939" + } + } + }, + { + "field": "object_repr", + "title": "Object", + "renderer": { + "type": "text" + } + }, + { + "field": "message", + "title": "Message", + "renderer": { + "type": "text" + } + } + ] + } + } + } + } + } + ] + } +} diff --git a/plugins/NetBox/v1/defaultContent/Perspectives/rack.dash.json b/plugins/NetBox/v1/defaultContent/Perspectives/rack.dash.json new file mode 100644 index 00000000..58134f0b --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Perspectives/rack.dash.json @@ -0,0 +1,652 @@ +{ + "name": "Rack", + "schemaVersion": "1.5", + "timeframe": "last30days", + "variables": [ + "{{variables.[NetBox Rack]}}" + ], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "43988400-b66b-4bb7-83aa-f0338c85412e", + "x": 0, + "y": 0, + "w": 1, + "h": 6, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Rack Properties", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "datastream-properties", + "name": "properties", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[NetBox Racks]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[NetBox Rack]}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": [ + "name" + ], + "hiddenColumns": [ + "id", + "links", + "type", + "label", + "sourceId", + "sourceType", + "siteId", + "rackId", + "vrfId" + ] + } + } + }, + "variables": [ + "{{variables.[NetBox Rack]}}" + ] + } + }, + { + "i": "f17e7c09-9f36-4406-9595-d7312fa32c58", + "x": 1, + "y": 0, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Rack Utilization", + "description": "Rack units used on either face", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[rackUtilization]}}", + "name": "rackUtilization", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "rack": { + "variable": "{{variables.[NetBox Rack]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Racks]}}" + } + } + }, + "variables": [ + "{{variables.[NetBox Rack]}}" + ], + "visualisation": { + "type": "data-stream-gauge", + "config": { + "data-stream-gauge": { + "value": { + "type": "mean", + "columns": [ + "utilization" + ] + }, + "label": "Utilization (%)", + "minimum": 0, + "maximum": 100 + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "gauge", + "encoding": { + "value": { + "field": "utilization", + "type": "quantitative", + "title": "Utilization" + } + }, + "style": { + "gaugeLabelText": "Utilization" + } + } + } + } + }, + { + "i": "82367003-5ed9-4d70-ae6d-9e0102289fbe", + "x": 2, + "y": 0, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Rack Space", + "description": "Rack units used on either face", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[rackUtilization]}}", + "name": "rackUtilization", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "rack": { + "variable": "{{variables.[NetBox Rack]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Racks]}}" + } + } + }, + "variables": [ + "{{variables.[NetBox Rack]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": [ + "uHeight", + "usedUnits", + "availableUnits", + "frontUsed", + "rearUsed", + "utilization", + "deviceCount" + ], + "hiddenColumns": [ + "rack", + "site", + "location" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "uHeight", + "type": "quantitative", + "title": "Rack Units" + }, + { + "field": "usedUnits", + "type": "quantitative", + "title": "Used Units" + }, + { + "field": "availableUnits", + "type": "quantitative", + "title": "Available Units" + }, + { + "field": "deviceCount", + "type": "quantitative", + "title": "Devices" + } + ] + }, + "style": { + "scalarBoxWidth": 440, + "scalarBoxHeight": 130, + "scalarFontSize": 48 + } + } + } + } + }, + { + "i": "d1a3e0f6-e23f-424a-bac4-808ff6494e06", + "x": 1, + "y": 3, + "w": 3, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices by Role in Rack", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "rack": { + "variable": "{{variables.[NetBox Rack]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Racks]}}" + } + }, + "group": { + "by": [ + [ + "role.name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Rack]}}" + ], + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "role.name_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "role.name_uniqueValues", + "type": "nominal", + "title": "Role" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Devices" + } + }, + "style": { + "cartesianHorizontal": true + } + } + } + } + }, + { + "i": "16624438-7872-4cf0-a871-44954036cc69", + "x": 0, + "y": 6, + "w": 4, + "h": 9, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Rack Elevation", + "description": "Each rack unit from the top down, with the device mounted at it. Empty units are listed; 0U, child and unracked devices follow the units.", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[rackElevation]}}", + "name": "rackElevation", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "rack": { + "variable": "{{variables.[NetBox Rack]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Racks]}}" + } + }, + "sort": { + "by": [ + [ + "order", + "asc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Rack]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "unit", + "device", + "role", + "deviceType", + "manufacturer", + "face", + "deviceHeight", + "unitsLabel" + ], + "hiddenColumns": [ + "rack", + "site", + "isTopUnit", + "occupied" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "unit", + "title": "Unit", + "renderer": { + "type": "number" + }, + "align": "right", + "width": 70 + }, + { + "field": "device", + "title": "Device", + "renderer": { + "type": "text" + } + }, + { + "field": "role", + "title": "Role", + "renderer": { + "type": "text" + } + }, + { + "field": "deviceType", + "title": "Device Type", + "renderer": { + "type": "text" + } + }, + { + "field": "manufacturer", + "title": "Manufacturer", + "renderer": { + "type": "text" + } + }, + { + "field": "face", + "title": "Face", + "renderer": { + "type": "text" + } + }, + { + "field": "deviceHeight", + "title": "Height (U)", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "unitsLabel", + "title": "Device Units", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 4 + } + } + } + } + }, + { + "i": "16d97f67-d02d-464e-a737-974718bcc13c", + "x": 0, + "y": 15, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices in Rack", + "description": "Includes any device custom fields", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "rack": { + "variable": "{{variables.[NetBox Rack]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Racks]}}" + } + }, + "sort": { + "by": [ + [ + "position", + "desc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Rack]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "display", + "position", + "status.label", + "role.name", + "device_type.manufacturer.name", + "device_type.model", + "primary_ip.display", + "serial", + "display_url" + ], + "hiddenColumns": [ + "missingSerial", + "missingPrimaryIp", + "missingTenant", + "missingPlatform", + "daysSinceUpdate", + "created", + "description", + "oob_ip.address", + "asset_tag", + "site.name", + "rack.name", + "location.name" + ] + } + } + } + } + }, + { + "i": "e6ac60cc-259e-4381-8a5e-54fef71f4543", + "x": 0, + "y": 19, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Change Log", + "description": "Changes recorded against this rack", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[objectChanges]}}", + "name": "objectChanges", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "object": { + "variable": "{{variables.[NetBox Rack]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Racks]}}" + } + }, + "sort": { + "by": [ + [ + "time", + "desc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Rack]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "time", + "user_name", + "action.label", + "object_repr", + "message" + ], + "hiddenColumns": [ + "changed_object_type" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "time", + "title": "Time", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "user_name", + "title": "User", + "renderer": { + "type": "text" + } + }, + { + "field": "action.label", + "title": "Action", + "renderer": { + "type": "badge", + "colors": { + "Created": "#2fb344", + "Updated": "#206bc4", + "Deleted": "#d63939" + } + } + }, + { + "field": "object_repr", + "title": "Object", + "renderer": { + "type": "text" + } + }, + { + "field": "message", + "title": "Message", + "renderer": { + "type": "text" + } + } + ] + } + } + } + } + } + ] + } +} diff --git a/plugins/NetBox/v1/defaultContent/Perspectives/site.dash.json b/plugins/NetBox/v1/defaultContent/Perspectives/site.dash.json new file mode 100644 index 00000000..237b14b5 --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Perspectives/site.dash.json @@ -0,0 +1,1135 @@ +{ + "name": "Site", + "schemaVersion": "1.5", + "timeframe": "last30days", + "variables": [ + "{{variables.[NetBox Site]}}" + ], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "f3d9fd21-2157-4e09-862d-39ba62eb31fe", + "x": 0, + "y": 0, + "w": 1, + "h": 6, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Site Properties", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "datastream-properties", + "name": "properties", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[NetBox Sites]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[NetBox Site]}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": [ + "name" + ], + "hiddenColumns": [ + "id", + "links", + "type", + "label", + "sourceId", + "sourceType", + "siteId", + "rackId", + "vrfId" + ] + } + } + }, + "variables": [ + "{{variables.[NetBox Site]}}" + ] + } + }, + { + "i": "e73db72a-e2b9-456c-8b27-62a5dfc8275f", + "x": 1, + "y": 0, + "w": 3, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Rack Space at Site", + "description": "Rack units used on either face, across the racks at this site", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[rackUtilization]}}", + "name": "rackUtilization", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "site": { + "variable": "{{variables.[NetBox Site]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Sites]}}" + } + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + }, + { + "type": "sum", + "names": [ + "usedUnits" + ] + }, + { + "type": "sum", + "names": [ + "availableUnits" + ] + }, + { + "type": "mean", + "names": [ + "utilization" + ] + }, + { + "type": "sum", + "names": [ + "deviceCount" + ] + } + ] + } + }, + "variables": [ + "{{variables.[NetBox Site]}}" + ], + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "usedUnits_sum", + "comparisonColumn": "none", + "label": "Used Units" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Racks" + }, + { + "field": "usedUnits_sum", + "type": "quantitative", + "title": "Used Units" + }, + { + "field": "availableUnits_sum", + "type": "quantitative", + "title": "Available Units" + }, + { + "field": "utilization_mean", + "type": "quantitative", + "title": "Average Utilization" + }, + { + "field": "deviceCount_sum", + "type": "quantitative", + "title": "Racked Devices" + } + ] + }, + "style": { + "scalarBoxWidth": 285, + "scalarBoxHeight": 140, + "scalarFontSize": 44 + } + } + } + } + }, + { + "i": "8bbdf85a-bf67-4415-963c-dbcdb8bd60cd", + "x": 1, + "y": 2, + "w": 3, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices by Role at Site", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "site": { + "variable": "{{variables.[NetBox Site]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Sites]}}" + } + }, + "group": { + "by": [ + [ + "role.name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Site]}}" + ], + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "role.name_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "role.name_uniqueValues", + "type": "nominal", + "title": "Role" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Devices" + } + }, + "style": { + "cartesianHorizontal": true + } + } + } + } + }, + { + "i": "8065eedd-aaed-440d-b064-f47ebccb4d18", + "x": 0, + "y": 6, + "w": 2, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Rack Utilization at Site", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[rackUtilization]}}", + "name": "rackUtilization", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "site": { + "variable": "{{variables.[NetBox Site]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Sites]}}" + } + }, + "sort": { + "by": [ + [ + "rack", + "asc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Site]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "rack", + "location", + "uHeight", + "deviceCount", + "usedUnits", + "availableUnits", + "utilization" + ], + "hiddenColumns": [ + "site", + "frontUsed", + "rearUsed" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "rack", + "title": "Rack", + "renderer": { + "type": "text" + } + }, + { + "field": "location", + "title": "Location", + "renderer": { + "type": "text" + } + }, + { + "field": "uHeight", + "title": "U Height", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "deviceCount", + "title": "Devices", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "usedUnits", + "title": "Used Units", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "availableUnits", + "title": "Available Units", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "utilization", + "title": "Utilization", + "renderer": { + "type": "progress", + "max": 100 + } + } + ] + } + } + } + } + }, + { + "i": "a37be3cb-d8ef-4d54-8c4e-86978bda496f", + "x": 2, + "y": 6, + "w": 2, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Power Feeds at Site", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[powerFeeds]}}", + "name": "powerFeeds", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "site": { + "variable": "{{variables.[NetBox Site]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Sites]}}" + } + }, + "sort": { + "by": [ + [ + "rack.name", + "asc" + ], + [ + "name", + "asc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Site]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "rack.name", + "name", + "power_panel.name", + "phaseLabel", + "availableKva", + "max_utilization", + "statusLabel" + ], + "hiddenColumns": [ + "power_panel.site.name", + "typeLabel", + "supplyLabel", + "voltage", + "amperage", + "connected", + "tenant.name", + "description", + "created", + "last_updated" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "rack.name", + "title": "Rack", + "renderer": { + "type": "text" + } + }, + { + "field": "name", + "title": "Power Feed", + "renderer": { + "type": "text" + } + }, + { + "field": "power_panel.name", + "title": "Power Panel", + "renderer": { + "type": "text" + } + }, + { + "field": "phaseLabel", + "title": "Phase", + "renderer": { + "type": "text" + } + }, + { + "field": "availableKva", + "title": "Available Power (kVA)", + "renderer": { + "type": "number", + "decimals": 2 + }, + "align": "right" + }, + { + "field": "max_utilization", + "title": "Max Utilization", + "renderer": { + "type": "progress", + "max": 100 + } + }, + { + "field": "statusLabel", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#2fb344", + "Planned": "#17a2b8", + "Offline": "#9ba3af", + "Failed": "#d63939" + } + } + } + ] + } + } + } + } + }, + { + "i": "e513f662-5c76-468d-91e9-d4e784800020", + "x": 0, + "y": 11, + "w": 4, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices", + "description": "Includes any device custom fields", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "site": { + "variable": "{{variables.[NetBox Site]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Sites]}}" + } + }, + "sort": { + "by": [ + [ + "display", + "asc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Site]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "display", + "status.label", + "role.name", + "device_type.manufacturer.name", + "device_type.model", + "platform.name", + "rack.name", + "position", + "primary_ip.display", + "tenant.name", + "serial", + "display_url" + ], + "hiddenColumns": [ + "missingSerial", + "missingPrimaryIp", + "missingTenant", + "missingPlatform", + "daysSinceUpdate", + "created", + "description", + "oob_ip.address", + "asset_tag", + "site.name" + ] + } + } + } + } + }, + { + "i": "e8c86afa-32d8-4de3-9c17-baed5cad9862", + "x": 0, + "y": 16, + "w": 2, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Prefixes", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[prefixes]}}", + "name": "prefixes", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "site": { + "variable": "{{variables.[NetBox Site]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Sites]}}" + } + }, + "sort": { + "by": [ + [ + "prefix", + "asc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Site]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "prefix", + "status.label", + "vrf.name", + "role.name", + "vlan.display", + "display_url" + ], + "hiddenColumns": [ + "created", + "_depth", + "mark_utilized", + "family.label", + "scope.name", + "tenant.name", + "is_pool", + "children", + "description" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "display_url", + "title": "Prefix", + "renderer": { + "type": "link", + "labelField": "prefix" + } + }, + { + "field": "status.label", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#2fb344", + "Container": "#9ba3af", + "Reserved": "#17a2b8", + "Deprecated": "#d63939" + } + } + }, + { + "field": "vrf.name", + "title": "VRF", + "renderer": { + "type": "text" + } + }, + { + "field": "role.name", + "title": "Role", + "renderer": { + "type": "text" + } + }, + { + "field": "vlan.display", + "title": "VLAN", + "renderer": { + "type": "text" + } + } + ] + } + } + } + } + }, + { + "i": "8ece4343-0a2d-4620-971f-921b9e6764ab", + "x": 2, + "y": 16, + "w": 2, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Virtual Machines", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[virtualMachines]}}", + "name": "virtualMachines", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "site": { + "variable": "{{variables.[NetBox Site]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Sites]}}" + } + }, + "sort": { + "by": [ + [ + "display", + "asc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Site]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "display", + "status.label", + "cluster.name", + "device.name", + "role.name", + "platform.name", + "primary_ip.display", + "vcpus", + "memory", + "disk", + "tenant.name", + "display_url" + ], + "hiddenColumns": [ + "created", + "description", + "site.name" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "display_url", + "title": "Virtual Machine", + "renderer": { + "type": "link", + "labelField": "display" + } + }, + { + "field": "status.label", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#2fb344", + "Planned": "#17a2b8", + "Staged": "#206bc4", + "Failed": "#d63939", + "Offline": "#9ba3af", + "Paused": "#f76707", + "Decommissioning": "#f59f00" + } + } + }, + { + "field": "cluster.name", + "title": "Cluster", + "renderer": { + "type": "text" + } + }, + { + "field": "role.name", + "title": "Role", + "renderer": { + "type": "text" + } + }, + { + "field": "primary_ip.display", + "title": "Primary IP", + "renderer": { + "type": "text" + } + } + ] + } + } + } + } + }, + { + "i": "12c71db6-1863-480a-b4b9-8a9cc9ee2af9", + "x": 0, + "y": 20, + "w": 4, + "h": 9, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Rack Elevation at Site", + "description": "Every rack at the site, each unit from the top down with the device mounted at it. Empty units are listed.", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[rackElevation]}}", + "name": "rackElevation", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "site": { + "variable": "{{variables.[NetBox Site]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Sites]}}" + } + }, + "sort": { + "by": [ + [ + "order", + "asc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Site]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "rack", + "unit", + "device", + "role", + "deviceType", + "manufacturer", + "face", + "deviceHeight", + "unitsLabel" + ], + "hiddenColumns": [ + "site", + "isTopUnit", + "occupied" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "rack", + "title": "Rack", + "renderer": { + "type": "text" + } + }, + { + "field": "unit", + "title": "Unit", + "renderer": { + "type": "number" + }, + "align": "right", + "width": 70 + }, + { + "field": "device", + "title": "Device", + "renderer": { + "type": "text" + } + }, + { + "field": "role", + "title": "Role", + "renderer": { + "type": "text" + } + }, + { + "field": "deviceType", + "title": "Device Type", + "renderer": { + "type": "text" + } + }, + { + "field": "manufacturer", + "title": "Manufacturer", + "renderer": { + "type": "text" + } + }, + { + "field": "face", + "title": "Face", + "renderer": { + "type": "text" + } + }, + { + "field": "deviceHeight", + "title": "Height (U)", + "renderer": { + "type": "number" + }, + "align": "right" + }, + { + "field": "unitsLabel", + "title": "Device Units", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 4 + } + } + } + } + }, + { + "i": "ca968a13-efcd-44a5-80b2-f604773022be", + "x": 0, + "y": 29, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Change Log", + "description": "Changes recorded against this site", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[objectChanges]}}", + "name": "objectChanges", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "object": { + "variable": "{{variables.[NetBox Site]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Sites]}}" + } + }, + "sort": { + "by": [ + [ + "time", + "desc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Site]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "time", + "user_name", + "action.label", + "object_repr", + "message" + ], + "hiddenColumns": [ + "changed_object_type" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "time", + "title": "Time", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "user_name", + "title": "User", + "renderer": { + "type": "text" + } + }, + { + "field": "action.label", + "title": "Action", + "renderer": { + "type": "badge", + "colors": { + "Created": "#2fb344", + "Updated": "#206bc4", + "Deleted": "#d63939" + } + } + }, + { + "field": "object_repr", + "title": "Object", + "renderer": { + "type": "text" + } + }, + { + "field": "message", + "title": "Message", + "renderer": { + "type": "text" + } + } + ] + } + } + } + } + } + ] + } +} diff --git a/plugins/NetBox/v1/defaultContent/Perspectives/virtualMachine.dash.json b/plugins/NetBox/v1/defaultContent/Perspectives/virtualMachine.dash.json new file mode 100644 index 00000000..a34f5a19 --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/Perspectives/virtualMachine.dash.json @@ -0,0 +1,313 @@ +{ + "name": "Virtual Machine", + "schemaVersion": "1.5", + "timeframe": "last30days", + "variables": [ + "{{variables.[NetBox Virtual Machine]}}" + ], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "c503a756-16b7-42c7-9984-7c51b9348e52", + "x": 0, + "y": 0, + "w": 1, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Virtual Machine Properties", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "datastream-properties", + "name": "properties", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[NetBox Virtual Machines]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[NetBox Virtual Machine]}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": [ + "name" + ], + "hiddenColumns": [ + "id", + "links", + "type", + "label", + "sourceId", + "sourceType", + "siteId", + "rackId", + "vrfId" + ] + } + } + }, + "variables": [ + "{{variables.[NetBox Virtual Machine]}}" + ] + } + }, + { + "i": "e2d657f2-5dcb-492a-bee7-dd1673bdcdca", + "x": 1, + "y": 0, + "w": 3, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "IP Addresses", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[ipAddresses]}}", + "name": "ipAddresses", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "virtualMachine": { + "variable": "{{variables.[NetBox Virtual Machine]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Virtual Machines]}}" + } + }, + "sort": { + "by": [ + [ + "address", + "asc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Virtual Machine]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "address", + "status.label", + "vrfName", + "dns_name", + "assignedTo", + "tenant.name", + "description", + "display_url" + ], + "hiddenColumns": [ + "display", + "created", + "family.label", + "assigned", + "role.label" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "display_url", + "title": "Address", + "renderer": { + "type": "link", + "labelField": "address" + } + }, + { + "field": "status.label", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#2fb344", + "Reserved": "#17a2b8", + "Deprecated": "#d63939", + "DHCP": "#2fb344", + "SLAAC": "#2fb344" + } + } + }, + { + "field": "vrfName", + "title": "VRF", + "renderer": { + "type": "text" + } + }, + { + "field": "dns_name", + "title": "DNS Name", + "renderer": { + "type": "text" + } + }, + { + "field": "assignedTo", + "title": "Assigned To", + "renderer": { + "type": "text" + } + }, + { + "field": "tenant.name", + "title": "Tenant", + "renderer": { + "type": "text" + } + }, + { + "field": "description", + "title": "Description", + "renderer": { + "type": "text" + } + } + ] + } + } + } + } + }, + { + "i": "26dcc49b-a0e9-4fee-8ce1-87892ec65583", + "x": 0, + "y": 4, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Change Log", + "description": "Changes recorded against this virtual machine", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[objectChanges]}}", + "name": "objectChanges", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "object": { + "variable": "{{variables.[NetBox Virtual Machine]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[NetBox Virtual Machines]}}" + } + }, + "sort": { + "by": [ + [ + "time", + "desc" + ] + ] + } + }, + "variables": [ + "{{variables.[NetBox Virtual Machine]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "time", + "user_name", + "action.label", + "object_repr", + "message" + ], + "hiddenColumns": [ + "changed_object_type" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "time", + "title": "Time", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "user_name", + "title": "User", + "renderer": { + "type": "text" + } + }, + { + "field": "action.label", + "title": "Action", + "renderer": { + "type": "badge", + "colors": { + "Created": "#2fb344", + "Updated": "#206bc4", + "Deleted": "#d63939" + } + } + }, + { + "field": "object_repr", + "title": "Object", + "renderer": { + "type": "text" + } + }, + { + "field": "message", + "title": "Message", + "renderer": { + "type": "text" + } + } + ] + } + } + } + } + } + ] + } +} diff --git a/plugins/NetBox/v1/defaultContent/manifest.json b/plugins/NetBox/v1/defaultContent/manifest.json new file mode 100644 index 00000000..d44e1625 --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/manifest.json @@ -0,0 +1,20 @@ +{ + "items": [ + { + "name": "overview", + "type": "dashboard" + }, + { + "name": "Capacity", + "type": "folder" + }, + { + "name": "Inventory", + "type": "folder" + }, + { + "name": "Perspectives", + "type": "folder" + } + ] +} diff --git a/plugins/NetBox/v1/defaultContent/overview.dash.json b/plugins/NetBox/v1/defaultContent/overview.dash.json new file mode 100644 index 00000000..36a5c8a8 --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/overview.dash.json @@ -0,0 +1,897 @@ +{ + "name": "Overview", + "schemaVersion": "1.5", + "timeframe": "none", + "variables": [], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "bf31d423-f2fb-4740-a715-fcb629c90f2e", + "x": 0, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Sites", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[sites]}}", + "name": "sites", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Sites" + } + } + } + } + }, + { + "i": "a87f696a-ed47-4998-b3bf-7f8bfa0a08d0", + "x": 1, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Racks", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[racks]}}", + "name": "racks", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Racks" + } + } + } + } + }, + { + "i": "e7506eb4-a411-4ffa-97ed-b748c354acc2", + "x": 2, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Devices" + } + } + } + } + }, + { + "i": "33e2dc4d-b335-4e42-9c0e-760a5d0e3205", + "x": 3, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Virtual Machines", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[virtualMachines]}}", + "name": "virtualMachines", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Virtual Machines" + } + } + } + } + }, + { + "i": "5fd8b80c-c6fd-4b29-850d-948feff122c4", + "x": 0, + "y": 2, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Prefixes", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[prefixes]}}", + "name": "prefixes", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Prefixes" + } + } + } + } + }, + { + "i": "e9f93dc9-4fcd-49b9-9177-8c86d0967fa2", + "x": 1, + "y": 2, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "IP Addresses", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[ipAddresses]}}", + "name": "ipAddresses", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "IP Addresses" + } + } + } + } + }, + { + "i": "13d8a594-20e9-458c-8899-0ea9c23ba51e", + "x": 2, + "y": 2, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Circuits", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[circuits]}}", + "name": "circuits", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Circuits" + } + } + } + } + }, + { + "i": "627b9b5d-7448-47a1-acad-6443a46cdf16", + "x": 3, + "y": 2, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "NetBox Version", + "description": "Version of the connected NetBox instance", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[status]}}", + "name": "status", + "pluginConfigId": "{{configId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "netbox-version", + "comparisonColumn": "none", + "label": "Version" + } + } + } + } + }, + { + "i": "2940b5ba-6b25-4153-a688-ee1c16e4973b", + "x": 0, + "y": 4, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices by Status", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "status.label", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "labelColumn": "status.label_uniqueValues", + "hideCenterValue": false, + "showValuesAsPercentage": false, + "legendPosition": "auto", + "legendMode": "table" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "pie", + "encoding": { + "label": { + "field": "status.label_uniqueValues", + "type": "nominal", + "title": "Status" + }, + "value": { + "field": "count", + "type": "quantitative", + "title": "Count" + } + }, + "style": { + "pieInnerRadius": 60, + "pieDonutCenterValue": "total", + "labelFontSize": 16, + "pieLegendStyle": "table", + "mappedColors": { + "Active": "#2fb344", + "Planned": "#17a2b8", + "Staged": "#206bc4", + "Failed": "#d63939", + "Offline": "#9ba3af", + "Inventory": "#ae3ec9", + "Decommissioning": "#f59f00" + } + } + } + } + } + }, + { + "i": "2fb65d1f-6d0e-47c7-83fb-15904fded3cf", + "x": 2, + "y": 4, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices by Role", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "role.name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ], + "top": 10 + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "role.name_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "role.name_uniqueValues", + "type": "nominal", + "title": "Role" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Devices" + } + }, + "style": { + "cartesianHorizontal": true + } + } + } + } + }, + { + "i": "128aeab0-ec18-4447-a5e1-7c28ee6f3fcf", + "x": 0, + "y": 7, + "w": 4, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices by Manufacturer and Model", + "description": "Device count per model, grouped by manufacturer", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "device_type.manufacturer.name", + "uniqueValues" + ], + [ + "device_type.model", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ] + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "device_type.manufacturer.name_uniqueValues", + "device_type.model_uniqueValues", + "count" + ], + "hiddenColumns": [] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "treemap", + "encoding": { + "label": { + "field": "device_type.model_uniqueValues", + "type": "nominal", + "title": "Model" + }, + "value": { + "field": "count", + "type": "quantitative", + "title": "Devices" + }, + "parent": { + "field": "device_type.manufacturer.name_uniqueValues", + "type": "nominal", + "title": "Manufacturer" + } + }, + "style": { + "showLabels": true, + "treemapGap": 2 + } + } + } + } + }, + { + "i": "31357f86-697b-42fa-a962-bacd3cd8b80f", + "x": 0, + "y": 12, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Devices by Platform", + "description": "Devices with a platform assigned", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "platform.name", + "operation": "notempty" + } + ] + }, + "group": { + "by": [ + [ + "platform.name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ], + "top": 10 + } + }, + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "labelColumn": "platform.name_uniqueValues", + "hideCenterValue": false, + "showValuesAsPercentage": false, + "legendPosition": "auto", + "legendMode": "table" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "pie", + "encoding": { + "label": { + "field": "platform.name_uniqueValues", + "type": "nominal", + "title": "Platform" + }, + "value": { + "field": "count", + "type": "quantitative", + "title": "Count" + } + }, + "style": { + "pieInnerRadius": 60, + "pieDonutCenterValue": "total", + "labelFontSize": 16, + "pieLegendStyle": "table" + } + } + } + } + }, + { + "i": "f2ed10ba-4845-4fc0-bb28-78184d0fb915", + "x": 2, + "y": 12, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Top 10 Sites by Devices", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[devices]}}", + "name": "devices", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "site.name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ], + "top": 10 + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "site.name_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "site.name_uniqueValues", + "type": "nominal", + "title": "Site" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Devices" + } + }, + "style": { + "cartesianHorizontal": true + } + } + } + } + }, + { + "i": "82078e48-0542-4ad8-acdc-9f56151824e0", + "x": 0, + "y": 15, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Virtual Machines by Cluster", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[virtualMachines]}}", + "name": "virtualMachines", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "cluster.name", + "operation": "notempty" + } + ] + }, + "group": { + "by": [ + [ + "cluster.name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ], + "top": 10 + } + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "cluster.name_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "horizontal", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "cluster.name_uniqueValues", + "type": "nominal", + "title": "Cluster" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Virtual Machines" + } + }, + "style": { + "cartesianHorizontal": true + } + } + } + } + } + ] + } +} diff --git a/plugins/NetBox/v1/defaultContent/scopes.json b/plugins/NetBox/v1/defaultContent/scopes.json new file mode 100644 index 00000000..f9ad16b3 --- /dev/null +++ b/plugins/NetBox/v1/defaultContent/scopes.json @@ -0,0 +1,104 @@ +[ + { + "name": "NetBox Sites", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Site" + ] + } + }, + "variable": { + "name": "NetBox Site", + "allowMultipleSelection": false, + "default": "none", + "type": "object" + } + }, + { + "name": "NetBox Racks", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Rack" + ] + } + }, + "variable": { + "name": "NetBox Rack", + "allowMultipleSelection": false, + "default": "none", + "type": "object" + } + }, + { + "name": "NetBox Devices", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Device" + ] + } + }, + "variable": { + "name": "NetBox Device", + "allowMultipleSelection": false, + "default": "none", + "type": "object" + } + }, + { + "name": "NetBox Virtual Machines", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Virtual Machine" + ] + } + }, + "variable": { + "name": "NetBox Virtual Machine", + "allowMultipleSelection": false, + "default": "none", + "type": "object" + } + }, + { + "name": "NetBox Prefixes", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Prefix" + ] + } + }, + "variable": { + "name": "NetBox Prefix", + "allowMultipleSelection": false, + "default": "none", + "type": "object" + } + }, + { + "name": "NetBox Circuits", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Circuit" + ] + } + }, + "variable": { + "name": "NetBox Circuit", + "allowMultipleSelection": false, + "default": "none", + "type": "object" + } + } +] diff --git a/plugins/NetBox/v1/docs/README.md b/plugins/NetBox/v1/docs/README.md new file mode 100644 index 00000000..1b52d67e --- /dev/null +++ b/plugins/NetBox/v1/docs/README.md @@ -0,0 +1,118 @@ +Visualize your [NetBox](https://netboxlabs.com/oss/netbox/) source of truth in SquaredUp: device and site inventory, IP prefix capacity, rack space and elevations, power feeds, data quality gaps, circuits, and the change log. Data comes from the [NetBox REST API](https://netboxlabs.com/docs/netbox/integrations/rest-api/) and the [NetBox GraphQL API](https://netboxlabs.com/docs/netbox/integrations/graphql-api/). + +## Setup + +You need the address of your NetBox instance and an **API token** for a user that can view the objects you want in SquaredUp. + +1. Sign in to NetBox in a browser and note the address. Examples: `https://netbox.example.com` for a self-managed instance, or `https://.cloud.netboxapp.com` for NetBox Cloud. +2. Open the user menu (top right) and choose **API Tokens**, then click **Add a token**. + - On NetBox 4.5 and later, create a **v2** token. NetBox shows the full token as `Bearer nbt_.`. v1 tokens still work, but they are deprecated and will be removed in a future NetBox release. + - Leave **Write enabled** unticked. The plugin only reads data. + - If you set **Allowed IPs**, include the addresses SquaredUp connects from, or the on-premises agent's address. +3. Copy the values immediately. NetBox shows the secret only once. +4. In SquaredUp, enter the address in **NetBox URL**, choose the **Token version**, and paste the token into **Token** exactly as NetBox shows it. Including the leading `Bearer` is fine. + +The token inherits the permissions of the user that owns it. Objects the user cannot view are not imported. + +## Configuration fields + +| Field | What it is | Where to find it | Required | +| ----- | ---------- | ---------------- | -------- | +| **NetBox URL** | The address of the NetBox instance. Do not include `/api`. If you do, it is removed automatically. | The address bar when NetBox is open in a browser. | Yes | +| **Token version** | The NetBox API token format. **v2** sends `Authorization: Bearer nbt_.`. **v1** sends `Authorization: Token `. | v2 tokens require NetBox 4.5 or later. | Yes | +| **Token** | The API token. For v2, paste the full value NetBox shows (`Bearer nbt_.`). The `Bearer` prefix is optional. For v1, paste the 40-character token. | NetBox → user menu → **API Tokens**. | Yes | +| **Key** | The public key of a v2 token. Only needed if **Token** contains just the secret, without the `nbt_.` prefix. Shown only when **Token version** is v2. | NetBox → user menu → **API Tokens**. | No | +| **Ignore certificate errors** | Skips TLS certificate validation. Only tick this for self-managed instances that use a self-signed or private CA certificate (common on new NetBox Enterprise installs). | n/a | No | + +When you save, the plugin checks two things: +1. It calls the NetBox status endpoint. A failure here means the address is unreachable, the token is invalid, expired or disabled, or the token's **Allowed IPs** blocks SquaredUp. +2. It reads the list of sites. A warning here means the token's user can't view DCIM objects. + +## What this plugin monitors + +The plugin works with **NetBox Community**, **NetBox Enterprise**, and **NetBox Cloud**. All three expose the same APIs, so no edition-specific setup is needed. NetBox records the intended state of your network, not live health, so the dashboards show inventory, capacity and lifecycle rather than up/down status. + +- **Inventory**: sites, racks, devices, virtual machines, circuits and IP addresses. This covers status, role, manufacturer, model, platform, tenant and location. +- **IP capacity**: prefix utilization, calculated the same way as NetBox. Containers count their child prefixes, pools count their full size, and prefixes marked as utilized count as full. VLAN group utilization is also shown. +- **Rack capacity**: + - Rack space used and available per rack and per site, counting both faces. + - A unit-by-unit rack elevation listing for one rack or every rack at a site, including empty units, multi-unit devices and a role filter. +- **Power**: power feeds by site, rack and panel, with voltage, amperage, phase and available power in kVA. +- **Data quality**: + - Devices missing a serial number, primary IP, tenant or platform. + - Devices not updated in over a year. + - Unassigned IP addresses. +- **Lifecycle**: devices and virtual machines that aren't active (planned, staged, offline, decommissioning), and circuit termination dates. +- **Change activity**: the NetBox change log by user, action and object type over time. +- **Custom fields**: every custom field on sites, racks, devices, virtual machines, prefixes, circuits, IP addresses and power feeds appears as an extra column. + +**Dashboards.** The out-of-the-box dashboards are **Overview**, **IPAM Capacity**, **Rack Capacity**, **Data Quality**, **Lifecycle and Circuits**, **Change Activity**, **Data Centers** (including a map of sites), **Power**, and **Device Inventory**. There is also a perspective dashboard for each **Site**, **Rack**, **Device**, **Virtual Machine**, **Prefix** and **Circuit**. + +**Comparing NetBox with monitoring data.** Device and virtual machine objects carry their name and primary IP address (without the mask). You can use them to compare NetBox's intended inventory with what other SquaredUp data sources actually monitor, for example by joining the **Devices** stream with a monitoring stream on name or IP in a dashboard tile. + +## Data streams + +- **Sites**: every site with status, region, site group, tenant, facility, coordinates, object counts and custom fields. Account-wide. +- **Racks**: every rack with site, location, status, role, height and device count. Account-wide, with an optional **Site** filter. +- **Devices**: every device with status, role, manufacturer, model, platform, site, rack and position, serial, tenant, primary IP and data-quality flags. Account-wide, with optional **Site**, **Rack** and **Role(s)** filters. +- **Virtual Machines**: every virtual machine with status, cluster, site, role, platform, vCPUs, memory, disk and primary IP. Account-wide, with an optional **Site** filter. +- **Prefixes**: every IP prefix with VRF, scope, status, role, VLAN and pool settings. Account-wide, with an optional **Site** filter. +- **Prefix Utilization**: used and total addresses and utilization % for each selected prefix. Per prefix. +- **IP Addresses**: IP addresses with VRF, status, role, DNS name and the device or virtual machine they're assigned to. + - Account-wide. + - Optional filters: **Prefix**, **Device**, **Virtual machine**, **Assignment** (assigned or unassigned) and **Status**. +- **VLAN Groups**: VLAN groups with scope, VLAN ID ranges and utilization. Account-wide. +- **Circuits**: circuits with provider, type, status, commit rate, terminations, and install and termination dates. Account-wide. +- **Device Interfaces**: interfaces on the selected devices, with type, enabled state, speed, MTU, VLAN mode, cabling and what each is connected to. Per device. +- **Rack Utilization**: rack units used and available per rack, counting both faces. Account-wide, with optional **Site** and **Rack** filters. +- **Rack Elevation**: one row per rack unit from the top down, with the device, role, type, manufacturer, face and height at that unit, including empty units. Account-wide, with optional **Site**, **Rack** and **Role** filters. +- **Power Feeds**: power feeds with site, rack, panel, status, type, supply, phase, voltage, amperage, maximum utilization and available power in kVA. Account-wide, with an optional **Site** filter. +- **Change Log**: changes recorded in NetBox, with time, user, action and object. + - Account-wide, for timeframes up to 30 days. + - Optional filters: an **Object**, **Action** or **Object type**. +- **Instance Status**: the NetBox version, number of installed plugins and number of background workers. +- **GraphQL Query**: runs a NetBox GraphQL query you write and returns one row per item in the first list in the result, with nested fields flattened into columns. + - Use it for views the other streams don't cover. + - Build and test queries in NetBox's GraphiQL explorer at `https:///graphql/`. + - Add `pagination: { limit: 1000, offset: 0 }` to lists that may be longer than 1,000 items. + +## What gets indexed + +| Object type | API source | Represents | +| ----------- | ---------- | ---------- | +| **Site** | `GET /api/dcim/sites/` | A NetBox site (data centre, office or campus). | +| **Rack** | `GET /api/dcim/racks/` | An equipment rack. | +| **Device** | `GET /api/dcim/devices/` | A physical device, such as a switch, router, server or PDU. | +| **Virtual Machine** | `GET /api/virtualization/virtual-machines/` | A virtual machine. | +| **Prefix** | `GET /api/ipam/prefixes/` | An IPv4 or IPv6 prefix, in a VRF or the global table. | +| **Circuit** | `GET /api/circuits/circuits/` | A carrier circuit. | + +Each object is identified by its NetBox ID and keeps key properties such as status, site, role and tenant. Each also keeps a link back to the object in NetBox. + +Imports run every 12 hours by default. Dashboard tiles query NetBox live, but SquaredUp caches results briefly, so use the dashboard's refresh button to see a change straight away. + +## Known limitations + +- **Read-only.** The plugin never creates, changes or deletes anything in NetBox. +- **Prefix utilization makes one request per prefix.** + - NetBox's API has no utilization or IP-count field, so each prefix is calculated with its own request. + - Tiles that show many prefixes take longer on large NetBox instances. The IPAM Capacity dashboard keeps this to a single tile. + - IP ranges marked as populated aren't counted, so such prefixes can read lower than in NetBox. + - A container prefix with more than 1,000 child prefixes is under-counted. +- **Large lists.** List streams return every matching object. On very large instances (many thousands of devices or IP addresses), use the Site, Prefix, Status or Assignment filters to keep tiles within SquaredUp's response size limit. +- **GraphQL lists stop at 1,000 items.** NetBox returns at most 1,000 items per GraphQL list, even when a higher limit is requested. + - The plugin's own GraphQL streams (Rack Utilization, Rack Elevation and Power Feeds) page through results automatically. + - Queries in the **GraphQL Query** stream must add `pagination` themselves. +- **Rack space.** + - Utilization counts a unit as used if a device occupies it on either face. + - 0U devices and devices in device bays don't use rack units. Rack Elevation lists them after the units. +- **Power.** Available power is the feed's rated capacity (voltage × amperage × maximum utilization, adjusted for three-phase). NetBox doesn't record live power draw. If you track actual load in a custom field, it appears as a column. +- **Site map.** + - Sites appear on the Data Centers map only if their latitude and longitude are set in NetBox. NetBox doesn't convert addresses into coordinates. + - The map uses SmartViz Geo Map. Until it's available in your SquaredUp region, the tile shows a table of sites instead. +- **Change log.** Available for up to 30 days at a time. On busy instances, filter by object, action or object type. +- **Reconnecting after plugin updates.** If a plugin update changes how SquaredUp connects to NetBox, open the data source and save it again. +- **NetBox version.** + - Built for NetBox 4.x and tested with NetBox 4.7. + - v2 tokens need NetBox 4.5 or later. + - On older 4.x releases, check the Change Log stream and the GraphQL-based streams (Rack Utilization, Rack Elevation, Power Feeds). They depend on the current change log API location and GraphQL filter syntax. diff --git a/plugins/NetBox/v1/icon.svg b/plugins/NetBox/v1/icon.svg new file mode 100644 index 00000000..0d756a7a --- /dev/null +++ b/plugins/NetBox/v1/icon.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/NetBox/v1/indexDefinitions/default.json b/plugins/NetBox/v1/indexDefinitions/default.json new file mode 100644 index 00000000..2f5fd2b2 --- /dev/null +++ b/plugins/NetBox/v1/indexDefinitions/default.json @@ -0,0 +1,265 @@ +{ + "steps": [ + { + "name": "sites", + "dataStream": { + "name": "sites" + }, + "timeframe": "none", + "objectMapping": { + "id": "id", + "name": "display", + "type": { + "value": "Site" + }, + "properties": [ + { + "status": "status.value" + }, + { + "region": "region.name" + }, + { + "siteGroup": "group.name" + }, + { + "tenant": "tenant.name" + }, + { + "facility": "facility" + }, + { + "timeZone": "time_zone" + }, + { + "netboxUrl": "display_url" + } + ] + } + }, + { + "name": "racks", + "dataStream": { + "name": "racks" + }, + "timeframe": "none", + "objectMapping": { + "id": "id", + "name": "display", + "type": { + "value": "Rack" + }, + "properties": [ + { + "status": "status.value" + }, + { + "siteId": "site.url" + }, + { + "site": "site.name" + }, + { + "location": "location.name" + }, + { + "role": "role.name" + }, + { + "tenant": "tenant.name" + }, + { + "uHeight": "u_height" + }, + { + "netboxUrl": "display_url" + } + ] + } + }, + { + "name": "devices", + "dataStream": { + "name": "devices" + }, + "timeframe": "none", + "objectMapping": { + "id": "id", + "name": "display", + "type": { + "value": "Device" + }, + "properties": [ + { + "status": "status.value" + }, + { + "role": "role.name" + }, + { + "manufacturer": "device_type.manufacturer.name" + }, + { + "deviceType": "device_type.model" + }, + { + "platform": "platform.name" + }, + { + "siteId": "site.url" + }, + { + "site": "site.name" + }, + { + "rackId": "rack.url" + }, + { + "rack": "rack.name" + }, + { + "serial": "serial" + }, + { + "assetTag": "asset_tag" + }, + { + "tenant": "tenant.name" + }, + { + "primaryIp": "primary_ip.display" + }, + { + "cluster": "cluster.name" + }, + { + "netboxUrl": "display_url" + } + ] + } + }, + { + "name": "virtualMachines", + "dataStream": { + "name": "virtualMachines" + }, + "timeframe": "none", + "objectMapping": { + "id": "id", + "name": "display", + "type": { + "value": "Virtual Machine" + }, + "properties": [ + { + "status": "status.value" + }, + { + "cluster": "cluster.name" + }, + { + "siteId": "site.url" + }, + { + "site": "site.name" + }, + { + "role": "role.name" + }, + { + "platform": "platform.name" + }, + { + "tenant": "tenant.name" + }, + { + "primaryIp": "primary_ip.display" + }, + { + "netboxUrl": "display_url" + } + ] + } + }, + { + "name": "prefixes", + "dataStream": { + "name": "prefixes" + }, + "timeframe": "none", + "objectMapping": { + "id": "id", + "name": "prefix", + "type": { + "value": "Prefix" + }, + "properties": [ + { + "vrfId": "vrf.id" + }, + { + "vrf": "vrf.name" + }, + { + "status": "status.value" + }, + { + "role": "role.name" + }, + { + "tenant": "tenant.name" + }, + { + "scope": "scope.name" + }, + { + "isPool": "is_pool" + }, + { + "markUtilized": "mark_utilized" + }, + { + "netboxUrl": "display_url" + } + ] + } + }, + { + "name": "circuits", + "dataStream": { + "name": "circuits" + }, + "timeframe": "none", + "objectMapping": { + "id": "id", + "name": "cid", + "type": { + "value": "Circuit" + }, + "properties": [ + { + "provider": "provider.name" + }, + { + "circuitType": "type.name" + }, + { + "status": "status.value" + }, + { + "tenant": "tenant.name" + }, + { + "commitRate": "commit_rate" + }, + { + "terminationDate": "termination_date" + }, + { + "netboxUrl": "display_url" + } + ] + } + } + ] +} diff --git a/plugins/NetBox/v1/metadata.json b/plugins/NetBox/v1/metadata.json new file mode 100644 index 00000000..921888b8 --- /dev/null +++ b/plugins/NetBox/v1/metadata.json @@ -0,0 +1,69 @@ +{ + "name": "netbox", + "displayName": "NetBox", + "version": "1.0.0", + "author": { + "name": "@shawn149", + "type": "community" + }, + "description": "Visualize your NetBox inventory, IP address capacity, data quality, circuits and change activity.", + "category": "Network", + "type": "hybrid", + "schemaVersion": "2.1", + "importNotSupported": false, + "restrictedToPlatforms": [], + "keywords": [ + "netbox", + "netbox labs", + "source of truth", + "dcim", + "ipam", + "network", + "inventory", + "data center", + "racks", + "prefixes", + "circuits", + "cmdb" + ], + "objectTypes": [ + "Site", + "Rack", + "Device", + "Virtual Machine", + "Prefix", + "Circuit" + ], + "links": [ + { + "category": "documentation", + "url": "https://github.com/squaredup/plugins/blob/main/plugins/NetBox/v1/docs/README.md", + "label": "Help adding this plugin" + }, + { + "category": "source", + "url": "https://github.com/squaredup/plugins/tree/main/plugins/NetBox/v1", + "label": "Repository" + } + ], + "base": { + "plugin": "WebAPI", + "majorVersion": "1", + "config": { + "baseUrl": "{{ netboxUrl.trim().replace(/[/]+$/, '').replace(/[/]api$/i, '') }}", + "authMode": "none", + "headers": [ + { + "key": "Authorization", + "value": "{{ (typeof tokenVersion === 'string' && tokenVersion.trim() === 'v1') ? ((typeof v1Token === 'string' ? v1Token.trim().replace(/^token( +|$)/i, '') : '') ? 'Token ' + (typeof v1Token === 'string' ? v1Token.trim().replace(/^token( +|$)/i, '') : '') : null) : ((typeof v2Token === 'string' ? v2Token.trim().replace(/^bearer( +|$)/i, '') : '') ? ((typeof v2Token === 'string' ? v2Token.trim().replace(/^bearer( +|$)/i, '') : '').indexOf('nbt_') === 0 ? 'Bearer ' + (typeof v2Token === 'string' ? v2Token.trim().replace(/^bearer( +|$)/i, '') : '') : ((typeof v2Key === 'string' ? v2Key.trim().replace(/^nbt_/i, '') : '') ? 'Bearer nbt_' + (typeof v2Key === 'string' ? v2Key.trim().replace(/^nbt_/i, '') : '') + '.' + (typeof v2Token === 'string' ? v2Token.trim().replace(/^bearer( +|$)/i, '') : '') : null)) : null) }}" + }, + { + "key": "Accept", + "value": "application/json" + } + ], + "queryArgs": [], + "ignoreCertificateErrors": "{{ignoreCertificateErrors}}" + } + } +} diff --git a/plugins/NetBox/v1/ui.json b/plugins/NetBox/v1/ui.json new file mode 100644 index 00000000..1cda6ecd --- /dev/null +++ b/plugins/NetBox/v1/ui.json @@ -0,0 +1,72 @@ +[ + { + "type": "text", + "name": "netboxUrl", + "label": "NetBox URL", + "placeholder": "https://netbox.example.com", + "help": "The address used to open NetBox in a browser. For NetBox Cloud this is `https://.cloud.netboxapp.com`.", + "validation": { + "required": true, + "pattern": { + "value": "^https?://[^ ]+$", + "message": "Enter the full address of the NetBox instance, e.g. https://netbox.example.com" + } + } + }, + { + "type": "radio", + "name": "tokenVersion", + "label": "Token version", + "defaultValue": "v2", + "options": [ + { "value": "v2", "label": "v2 (NetBox 4.5 and later)" }, + { "value": "v1", "label": "v1 (legacy)" } + ], + "validation": { "required": true } + }, + { + "type": "fieldGroup", + "visible": { "tokenVersion": "v2" }, + "fields": [ + { + "type": "password", + "name": "v2Token", + "label": "Token", + "placeholder": "Bearer nbt_xxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "help": "Paste the value exactly as NetBox shows it, with or without the leading `Bearer`.", + "validation": { "required": true } + }, + { + "type": "text", + "name": "v2Key", + "label": "Key", + "placeholder": "Enter the NetBox token key", + "help": "Only needed if **Token** contains just the secret, without the `nbt_.` prefix." + } + ] + }, + { + "type": "fieldGroup", + "visible": { "tokenVersion": "v1" }, + "fields": [ + { + "type": "markdown", + "name": "v1Deprecation", + "content": "⚠️ v1 API tokens are deprecated and will be removed in a future NetBox release. Please use v2 tokens instead." + }, + { + "type": "password", + "name": "v1Token", + "label": "Token", + "placeholder": "Enter the 40-character NetBox token", + "validation": { "required": true } + } + ] + }, + { + "type": "checkbox", + "name": "ignoreCertificateErrors", + "label": "Ignore certificate errors", + "help": "Enable when connecting to a self-managed NetBox instance that uses a self-signed or private CA certificate." + } +]