Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pillar: netbox: create "connected_devices" function #62666

Merged
merged 9 commits into from
Sep 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/62761.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added "connected_devices" feature to netbox pillar module. It contains extra information about devices connected to the minion
205 changes: 205 additions & 0 deletions salt/pillar/netbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@
An integer specifying how many results should be returned for each query
to the NetBox API. Leaving this unset will use NetBox's default value.

connected_devices: ``False``
.. versionadded:: 3006

Whether connected_devices key should be populated with device objects.
If set to True it will force `interfaces` to also be true as a dependency

Note that each option you enable can have a detrimental impact on pillar
performance, so use them with caution.

Expand Down Expand Up @@ -520,6 +526,160 @@
tags:
custom_fields:
config_context:
connected_devices:
----------
512:
----------
airflow:
None
asset_tag:
001
cluster:
None
comments:
config_context:
created:
2022-03-10T00:00:00Z
custom_fields:
device_role:
----------
display:
Network switch
id:
512
name:
Network switch
slug:
network_switch
url:
https://netbox.example.com/api/dcim/device-roles/5/
device_type:
----------
display:
Nexus 3048
id:
40
manufacturer:
----------
display:
Cisco
id:
1
name:
Cisco
slug:
cisco
url:
https://netbox.example.com/api/dcim/manufacturers/1/
model:
Nexus 3048
slug:
n3k-c3048tp-1ge
url:
https://netbox.example.com/api/dcim/device-types/40/
display:
another device (001)
face:
----------
label:
Front
value:
front
id:
1533
last_updated:
2022-08-22T13:50:15.923868Z
local_context_data:
None
location:
----------
_depth:
2
display:
Location Name
id:
2
name:
Location Name
slug:
location-name
url:
https://netbox.example.com/api/dcim/locations/2
name:
another device
parent_device:
None
platform:
None
position:
18.0
primary_ip:
----------
address:
192.168.1.1/24
display:
192.168.1.1/24
family:
4
id:
1234
url:
https://netbox.example.com/api/ipam/ip-addresses/1234/
primary_ip4:
----------
address:
192.168.1.1/24
display:
192.168.1.1/24
family:
4
id:
1234
url:
https://netbox.example.com/api/ipam/ip-addresses/1234/
primary_ip6:
None
rack:
----------
display:
RackName
id:
139
name:
RackName
url:
https://netbox.example.com/api/dcim/racks/139/
serial:
ABCD12345
site:
----------
display:
SiteName
id:
2
name:
SiteName
slug:
sitename
url:
https://netbox.example.com/api/dcim/sites/2/
status:
----------
label:
Active
value:
active
tags:
tenant:
None
url:
https://netbox.example.com/api/dcim/devices/1533/
vc_position:
None
vc_priority:
None
virtual_chassis:
None
created:
2021-02-19
last_updated:
Expand Down Expand Up @@ -777,6 +937,40 @@ def _get_site_details(api_url, minion_id, site_name, site_id, headers):
return site_details_ret["dict"]


def _get_connected_devices(api_url, minion_id, interfaces, headers):
log.debug('Retrieving connected devices for "%s"', minion_id)
connected_devices_result = {}
connected_devices_ids = []
for int_short in interfaces:
if "connected_endpoints" in int_short.keys():
if int_short["connected_endpoints"]:
for device_short in int_short["connected_endpoints"]:
if (
"device" in device_short.keys()
and not device_short["device"]["id"] in connected_devices_ids
):
connected_devices_ids.append(device_short["device"]["id"])
log.debug("connected_devices_ids: %s", connected_devices_ids)

for dev_id in connected_devices_ids:
device_url = "{api_url}/{app}/{endpoint}/{dev_id}".format(
api_url=api_url, app="dcim", endpoint="devices", dev_id=dev_id
)
device_results = []
device_ret = salt.utils.http.query(device_url, header_dict=headers, decode=True)
if "error" in device_ret:
log.error(
'API query failed for "%s", status code: %d, error %s',
minion_id,
device_ret["status"],
device_ret["error"],
)
else:
connected_devices_result[dev_id] = dict(device_ret["dict"])

return connected_devices_result


def _get_site_prefixes(
api_url, minion_id, site_name, site_id, headers, api_query_result_limit
):
Expand Down Expand Up @@ -876,6 +1070,13 @@ def ext_pillar(minion_id, pillar, *args, **kwargs):
site_prefixes = kwargs.get("site_prefixes", True)
proxy_username = kwargs.get("proxy_username", None)
proxy_return = kwargs.get("proxy_return", True)
connected_devices = kwargs.get("connected_devices", False)
if connected_devices and not interfaces:
# connected_devices logic requires interfaces to be populated
interfaces = True
log.debug(
"netbox pillar interfaces set to 'True' as connected_devices is 'True'"
)
api_query_result_limit = kwargs.get("api_query_result_limit")

ret = {}
Expand Down Expand Up @@ -951,6 +1152,10 @@ def ext_pillar(minion_id, pillar, *args, **kwargs):
ret["netbox"]["site"]["prefixes"] = _get_site_prefixes(
api_url, minion_id, site_name, site_id, headers, api_query_result_limit
)
if connected_devices:
ret["netbox"]["connected_devices"] = _get_connected_devices(
api_url, minion_id, ret["netbox"]["interfaces"], headers
)
if proxy_return:
if ret["netbox"]["platform"]:
platform_id = ret["netbox"]["platform"]["id"]
Expand Down
Loading