nornir-collection 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nornir_collection/__init__.py +0 -0
- nornir_collection/batfish/__init__.py +0 -0
- nornir_collection/batfish/assert_config.py +358 -0
- nornir_collection/batfish/utils.py +129 -0
- nornir_collection/cisco/__init__.py +0 -0
- nornir_collection/cisco/configuration_management/__init__.py +0 -0
- nornir_collection/cisco/configuration_management/cli/__init__.py +0 -0
- nornir_collection/cisco/configuration_management/cli/config_tasks.py +569 -0
- nornir_collection/cisco/configuration_management/cli/config_workflow.py +107 -0
- nornir_collection/cisco/configuration_management/cli/show_tasks.py +677 -0
- nornir_collection/cisco/configuration_management/netconf/__init__.py +0 -0
- nornir_collection/cisco/configuration_management/netconf/config_tasks.py +564 -0
- nornir_collection/cisco/configuration_management/netconf/config_workflow.py +298 -0
- nornir_collection/cisco/configuration_management/netconf/nr_cfg_iosxe_netconf.py +186 -0
- nornir_collection/cisco/configuration_management/netconf/ops_tasks.py +307 -0
- nornir_collection/cisco/configuration_management/processor.py +151 -0
- nornir_collection/cisco/configuration_management/pyats.py +236 -0
- nornir_collection/cisco/configuration_management/restconf/__init__.py +0 -0
- nornir_collection/cisco/configuration_management/restconf/cisco_rpc.py +514 -0
- nornir_collection/cisco/configuration_management/restconf/config_workflow.py +95 -0
- nornir_collection/cisco/configuration_management/restconf/tasks.py +325 -0
- nornir_collection/cisco/configuration_management/utils.py +511 -0
- nornir_collection/cisco/software_upgrade/__init__.py +0 -0
- nornir_collection/cisco/software_upgrade/cisco_software_upgrade.py +283 -0
- nornir_collection/cisco/software_upgrade/utils.py +794 -0
- nornir_collection/cisco/support_api/__init__.py +0 -0
- nornir_collection/cisco/support_api/api_calls.py +1173 -0
- nornir_collection/cisco/support_api/cisco_maintenance_report.py +221 -0
- nornir_collection/cisco/support_api/cisco_support.py +727 -0
- nornir_collection/cisco/support_api/reports.py +747 -0
- nornir_collection/cisco/support_api/utils.py +316 -0
- nornir_collection/fortinet/__init__.py +0 -0
- nornir_collection/fortinet/utils.py +36 -0
- nornir_collection/git.py +224 -0
- nornir_collection/netbox/__init__.py +0 -0
- nornir_collection/netbox/custom_script.py +107 -0
- nornir_collection/netbox/inventory.py +360 -0
- nornir_collection/netbox/scan_prefixes_and_update_ip_addresses.py +989 -0
- nornir_collection/netbox/set_device_status.py +67 -0
- nornir_collection/netbox/sync_datasource.py +111 -0
- nornir_collection/netbox/update_cisco_inventory_data.py +158 -0
- nornir_collection/netbox/update_cisco_support_plugin_data.py +339 -0
- nornir_collection/netbox/update_fortinet_inventory_data.py +161 -0
- nornir_collection/netbox/update_purestorage_inventory_data.py +144 -0
- nornir_collection/netbox/utils.py +261 -0
- nornir_collection/netbox/verify_device_primary_ip.py +202 -0
- nornir_collection/nornir_plugins/__init__.py +0 -0
- nornir_collection/nornir_plugins/inventory/__init__.py +0 -0
- nornir_collection/nornir_plugins/inventory/netbox.py +250 -0
- nornir_collection/nornir_plugins/inventory/staggered_yaml.py +143 -0
- nornir_collection/nornir_plugins/inventory/utils.py +277 -0
- nornir_collection/purestorage/__init__.py +0 -0
- nornir_collection/purestorage/utils.py +53 -0
- nornir_collection/utils.py +741 -0
- nornir_collection-0.0.1.dist-info/LICENSE +21 -0
- nornir_collection-0.0.1.dist-info/METADATA +136 -0
- nornir_collection-0.0.1.dist-info/RECORD +59 -0
- nornir_collection-0.0.1.dist-info/WHEEL +5 -0
- nornir_collection-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,107 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
This module contains functions related to NetBox custom scripts.
|
4
|
+
|
5
|
+
The functions are ordered as followed:
|
6
|
+
- Regular functions
|
7
|
+
"""
|
8
|
+
|
9
|
+
|
10
|
+
import os
|
11
|
+
import time
|
12
|
+
import json
|
13
|
+
import requests
|
14
|
+
from nornir_collection.utils import task_name, task_error, task_info, exit_error
|
15
|
+
|
16
|
+
|
17
|
+
#### Regular functions ######################################################################################
|
18
|
+
|
19
|
+
|
20
|
+
def run_nb_custom_script( # pylint: disable=dangerous-default-value
|
21
|
+
name: str, url: str, payload: dict = {}, verbose: bool = False
|
22
|
+
) -> bool:
|
23
|
+
"""
|
24
|
+
Runs a custom script in NetBox.
|
25
|
+
Args:
|
26
|
+
name (str): The name of the custom script to run.
|
27
|
+
url (str): The URL of the custom script to run.
|
28
|
+
payload (dict, optional): The payload to send with the request. Defaults to {}.
|
29
|
+
verbose (bool, optional): Whether to print verbose output. Defaults to False.
|
30
|
+
Returns:
|
31
|
+
bool: True if the custom script failed, False otherwise.
|
32
|
+
"""
|
33
|
+
task_text = f"Run NetBox Custom Script {name}"
|
34
|
+
print(task_name(text=task_text))
|
35
|
+
|
36
|
+
# Set the NetBox token, timeout, header
|
37
|
+
timeout = (3.05, 27)
|
38
|
+
headers = {
|
39
|
+
"Accept": "application/json",
|
40
|
+
"Content-Type": "application/json",
|
41
|
+
"Authorization": f"Token {os.environ.get('NB_TOKEN')}",
|
42
|
+
}
|
43
|
+
|
44
|
+
# Do the http post request to run the NetBox custom script
|
45
|
+
response = requests.post( # nosec
|
46
|
+
url=url, headers=headers, data=json.dumps(payload), verify=False, timeout=timeout
|
47
|
+
)
|
48
|
+
# Verify the response code
|
49
|
+
if not response.status_code == 200:
|
50
|
+
msg = [
|
51
|
+
f"Failed to run NetBox custom script {url}",
|
52
|
+
f"Status code: {response.status_code}",
|
53
|
+
f"Response Text: {response.text}",
|
54
|
+
]
|
55
|
+
# Print the error message and exit the script
|
56
|
+
exit_error(task_text=task_text, msg=msg)
|
57
|
+
|
58
|
+
# Print the start of the custom script
|
59
|
+
print(task_info(text="Started NetBox Custom Script", changed=False))
|
60
|
+
print(f"Started NetBox Custom Script {name}")
|
61
|
+
if verbose:
|
62
|
+
print(json.dumps(response.json(), indent=4))
|
63
|
+
|
64
|
+
# Create a result dict from the first API response to track the progress of the status
|
65
|
+
result = response.json()["result"]
|
66
|
+
# Do the http get request to verify the status of the running NetBox custom script
|
67
|
+
# Terminate the while loop with a timeout of max 300s (5min)
|
68
|
+
timeout_start = time.time()
|
69
|
+
while time.time() < timeout_start + 300:
|
70
|
+
if result["status"]["value"] not in ("pending", "running"):
|
71
|
+
break
|
72
|
+
result = requests.get(url=result["url"], headers=headers, verify=False, timeout=timeout) # nosec
|
73
|
+
result = result.json()
|
74
|
+
time.sleep(1)
|
75
|
+
|
76
|
+
# Print the end result after the custom script has finished or the timeout exeeded
|
77
|
+
if result["status"]["value"] not in ("completed", "failed"):
|
78
|
+
print(task_error(text="Failed NetBox Custom Script", changed=False))
|
79
|
+
print(f"Failed NetBox Custom Script {name}")
|
80
|
+
print(json.dumps(result, indent=4))
|
81
|
+
|
82
|
+
# Return True because the custom script failed
|
83
|
+
return True
|
84
|
+
|
85
|
+
# Create a list of the log messages
|
86
|
+
result_list = []
|
87
|
+
result_list.append(f"Completed NetBox Custom Script {name}\n")
|
88
|
+
for item in result["data"]["log"]:
|
89
|
+
# Space after the info emoji needed to align the text
|
90
|
+
symbol_lookup = {"debug": "🚧", "info": "ℹ️", "success": "✅", "warning": "🚨", "failure": "❌"}
|
91
|
+
symbol = symbol_lookup.get(item["status"], "❓")
|
92
|
+
result_list.append(f"{symbol} [{item['status'].capitalize()}] - {item['message']}")
|
93
|
+
if verbose:
|
94
|
+
result_list.append(json.dumps(result, indent=4))
|
95
|
+
|
96
|
+
if "failed" in result["status"]["value"]:
|
97
|
+
print(task_error(text="Completed NetBox Custom Script", changed=False))
|
98
|
+
print("\n".join(result_list))
|
99
|
+
|
100
|
+
# Return True because the custom script failed
|
101
|
+
return True
|
102
|
+
|
103
|
+
print(task_info(text="Completed NetBox Custom Script", changed=False))
|
104
|
+
print("\n".join(result_list))
|
105
|
+
|
106
|
+
# Return False because the custom script was successful
|
107
|
+
return False
|
@@ -0,0 +1,360 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
This module contains general functions and tasks related to NetBox and Nornir.
|
4
|
+
|
5
|
+
The functions are ordered as followed:
|
6
|
+
- Task Helper Functions
|
7
|
+
- Single Nornir Tasks
|
8
|
+
- Nornir Tasks in regular Function
|
9
|
+
"""
|
10
|
+
|
11
|
+
|
12
|
+
from typing import Dict, List
|
13
|
+
from nornir.core import Nornir
|
14
|
+
from nornir.core.task import Task, Result
|
15
|
+
from nornir_collection.netbox.utils import get_nb_resources
|
16
|
+
from nornir_collection.utils import task_info, print_task_name, print_result, exit_error
|
17
|
+
|
18
|
+
|
19
|
+
#### Task Helper Functions ##################################################################################
|
20
|
+
|
21
|
+
|
22
|
+
#### Nornir Tasks ###########################################################################################
|
23
|
+
|
24
|
+
|
25
|
+
def _load_virtual_chassis_data(task: Task, all_devices: List[Dict]) -> Result:
|
26
|
+
"""
|
27
|
+
Load NetBox virtual chassis member data.
|
28
|
+
Args:
|
29
|
+
task (Task): Nornir task object.
|
30
|
+
all_devices: (List[Dict]): List of all devices from NetBox.
|
31
|
+
Returns:
|
32
|
+
Result: Nornir result object.
|
33
|
+
"""
|
34
|
+
# Set the failed flag to False
|
35
|
+
failed = False
|
36
|
+
|
37
|
+
# If the device is not part of a virtual chassis
|
38
|
+
if not task.host.get("virtual_chassis"):
|
39
|
+
# Return the Nornir object
|
40
|
+
result = (
|
41
|
+
f"'Load Virtual-Chassis data' -> NetBoxResponse <Success: {not failed}>\n"
|
42
|
+
+ "-> Device is not part of a virtual-chassis in NetBox"
|
43
|
+
)
|
44
|
+
return Result(host=task.host, result=result, changed=False, failed=failed)
|
45
|
+
|
46
|
+
# Dict comprehension to include only some key-value pairs
|
47
|
+
include_keys = ["id", "url", "display", "name", "serial"]
|
48
|
+
# Add an empty list for the members of the virtual chassis
|
49
|
+
task.host["virtual_chassis"]["members"] = []
|
50
|
+
# Add the data of all members to the master
|
51
|
+
# Start with 2 as the master is number 1 and already in the lists
|
52
|
+
for i in range(2, task.host["virtual_chassis"]["member_count"] + 1):
|
53
|
+
# Get the member data
|
54
|
+
member = [x for x in all_devices if x["name"] == f"{task.host['virtual_chassis']['name']}_{i}"]
|
55
|
+
# Dict comprehension to include only some key-value pairs
|
56
|
+
member = {k: v for (k, v) in member[0].items() if k in include_keys}
|
57
|
+
member["serial"] = member["serial"] if member["serial"] else None
|
58
|
+
# Add the member data to the virtual chassis master
|
59
|
+
task.host["virtual_chassis"]["members"].append(member)
|
60
|
+
|
61
|
+
# Return the Nornir object
|
62
|
+
return Result(host=task.host)
|
63
|
+
|
64
|
+
|
65
|
+
def _load_interface_data(task: Task, all_interfaces: List[Dict], enrich_vlan_data: True) -> Result:
|
66
|
+
"""
|
67
|
+
Load NetBox interface data.
|
68
|
+
Args:
|
69
|
+
task (Task): The Nornir task object.
|
70
|
+
all_interfaces: (List[Dict]): List of all interfaces from NetBox.
|
71
|
+
Returns:
|
72
|
+
Result: Nornir result object.
|
73
|
+
"""
|
74
|
+
# pylint: disable=too-many-locals
|
75
|
+
|
76
|
+
# Set the failed flag to False
|
77
|
+
failed = False
|
78
|
+
|
79
|
+
# Get all interfaces from the master device
|
80
|
+
interfaces = [x for x in all_interfaces if x["device"]["id"] == task.host["id"]]
|
81
|
+
# Add all interfaces from the virtual chassis members
|
82
|
+
if task.host.get("virtual_chassis") and task.host["virtual_chassis"].get("members"):
|
83
|
+
for member in task.host["virtual_chassis"]["members"]:
|
84
|
+
interfaces.extend([x for x in all_interfaces if x["device"]["id"] == member["id"]])
|
85
|
+
# Return if the interfaces list is empty
|
86
|
+
if not interfaces:
|
87
|
+
# Return the Nornir object
|
88
|
+
result = (
|
89
|
+
f"'Load interface data' -> NetBoxResponse <Success: {not failed}>\n"
|
90
|
+
+ "-> No interface data found in NetBox"
|
91
|
+
)
|
92
|
+
return Result(host=task.host, result=result, changed=False, failed=failed)
|
93
|
+
|
94
|
+
# Dict keys for comprehension to include only some key-value pairs
|
95
|
+
# fmt: off
|
96
|
+
include_keys = [
|
97
|
+
"name", "int_template", "description", "type", "lag", "count_ipaddresses",
|
98
|
+
"count_fhrp_groups", "int_peer_device", "int_config_context", "enabled",
|
99
|
+
]
|
100
|
+
# fmt: on
|
101
|
+
# Make some normalization to the device interfaces data with the interface_filter list and others
|
102
|
+
for interface in interfaces:
|
103
|
+
# Remove the custom_fields key and make the custom_field native to Nornir
|
104
|
+
for custom_field, value in interface["custom_fields"].items():
|
105
|
+
interface[custom_field] = value
|
106
|
+
interface.pop("custom_fields")
|
107
|
+
# Dict comprehension to include only some key-value pairs
|
108
|
+
interface = {k: v for (k, v) in interface.items() if k in include_keys}
|
109
|
+
# If the interface has a peer device, add the peer device data to the interface
|
110
|
+
if enrich_vlan_data and interface.get("int_peer_device"):
|
111
|
+
# Get the interface peer device name
|
112
|
+
peer_name = interface["int_peer_device"]["name"]
|
113
|
+
# Slice the last two characters from the name to get the peer name of the virtual chassis
|
114
|
+
peer_name = peer_name if task.nornir.inventory.hosts.get(peer_name) else peer_name[:-2]
|
115
|
+
# Add the peer device data (VLAN name & VLAN ID) to the interface if 'cfg_vlans' exists
|
116
|
+
if task.nornir.inventory.hosts[peer_name].data.get("cfg_vlans"):
|
117
|
+
interface["int_peer_device"]["vlans"] = [
|
118
|
+
{k: v for (k, v) in vlan.items() if k in ["vid", "name"]}
|
119
|
+
for vlan in task.nornir.inventory.hosts[peer_name].data["cfg_vlans"]
|
120
|
+
]
|
121
|
+
# Add an empty list if 'cfg_vlans' does not exist
|
122
|
+
else:
|
123
|
+
interface["int_peer_device"]["vlans"] = []
|
124
|
+
|
125
|
+
# Reorder the list to have all LAG interfaces first and all virtual interfaces last
|
126
|
+
lag_int = [i for i in interfaces if i["type"]["value"] == "lag"]
|
127
|
+
virt_int = [i for i in interfaces if i["type"]["value"] == "virtual"]
|
128
|
+
other_int = [i for i in interfaces if i["type"]["value"] not in ("lag", "virtual")]
|
129
|
+
# Assign the interfaces list to the device
|
130
|
+
interfaces = lag_int + other_int + virt_int
|
131
|
+
|
132
|
+
# Create an empty interfaces list in the device data
|
133
|
+
task.host["interfaces"] = []
|
134
|
+
# Dict comprehension to include only some key-value pairs
|
135
|
+
for interface in interfaces:
|
136
|
+
data = {k: v for (k, v) in interface.items() if k in include_keys}
|
137
|
+
task.host["interfaces"].append(data)
|
138
|
+
|
139
|
+
# Return the Nornir object
|
140
|
+
return Result(host=task.host)
|
141
|
+
|
142
|
+
|
143
|
+
def _load_vlan_data(task: Task, all_vlans: List[Dict]) -> Result:
|
144
|
+
"""
|
145
|
+
Load NetBox VLAN data.
|
146
|
+
Args:
|
147
|
+
task (Task): The Nornir task object.
|
148
|
+
all_interfaces: (List[Dict]): List of all VLANs from NetBox.
|
149
|
+
Returns:
|
150
|
+
Result: Nornir result object.
|
151
|
+
"""
|
152
|
+
# Set the failed flag to False
|
153
|
+
failed = False
|
154
|
+
|
155
|
+
# Return if the device has no VLAN groups
|
156
|
+
if not task.host.get("vlan_groups"):
|
157
|
+
# Return the Nornir object
|
158
|
+
result = (
|
159
|
+
f"'Load VLAN data' -> NetBoxResponse <Success: {not failed}>\n"
|
160
|
+
+ "-> No 'vlan_groups' key found in NetBox"
|
161
|
+
)
|
162
|
+
return Result(host=task.host, result=result, changed=False, failed=failed)
|
163
|
+
|
164
|
+
# Dict keys for comprehension to include only some key-value pairs
|
165
|
+
include_keys = ["display", "name", "vid", "status", "description", "group", "role", "prefix_count"]
|
166
|
+
# Create an empty cfg_vlans dict in the device data
|
167
|
+
task.host["cfg_vlans"] = []
|
168
|
+
|
169
|
+
# Loop through the 'vlan_groups' and find VLANs that match the group and role
|
170
|
+
for group, roles in task.host["vlan_groups"].items():
|
171
|
+
# If the group_roles list is not empty, filter the VLANs to match only the role
|
172
|
+
if roles:
|
173
|
+
vlans = []
|
174
|
+
for role in roles:
|
175
|
+
# Update the VLANs to match all VLANs that match also the role
|
176
|
+
data = [x for x in all_vlans if (x["group"]["name"] == group and x["role"]["name"] == role)]
|
177
|
+
vlans.extend(data)
|
178
|
+
# Return if the data list is empty
|
179
|
+
if not data:
|
180
|
+
failed = True
|
181
|
+
break
|
182
|
+
else:
|
183
|
+
# Get all VLANs that match the group name
|
184
|
+
vlans = [x for x in all_vlans if x["group"]["name"] == group]
|
185
|
+
# Return if the vlans list is empty
|
186
|
+
if not vlans:
|
187
|
+
failed = True
|
188
|
+
break
|
189
|
+
|
190
|
+
# Add the VLANs to the cfg_vlans dict
|
191
|
+
for item in vlans:
|
192
|
+
# Dict comprehension to include only some key-value pairs
|
193
|
+
vlan = {k: v for (k, v) in item.items() if k in include_keys}
|
194
|
+
task.host["cfg_vlans"].append(vlan)
|
195
|
+
|
196
|
+
# Set the result based on the failed boolian
|
197
|
+
result = f"'Load VLAN data' -> NetBoxResponse <Success: {not failed}>\n"
|
198
|
+
if failed:
|
199
|
+
result += "-> One or more 'groups' and/or 'roles' under the 'vlan_groups' key not found in NetBox"
|
200
|
+
else:
|
201
|
+
result += "-> All 'groups' and 'roles' under the 'vlan_groups' key found in NetBox"
|
202
|
+
|
203
|
+
# Return the Nornir object
|
204
|
+
return Result(host=task.host, result=result, changed=False, failed=failed)
|
205
|
+
|
206
|
+
|
207
|
+
def _load_cisco_support_data(task: Task, all_csupp: List[Dict]) -> Result:
|
208
|
+
"""
|
209
|
+
Load NetBox Cisco support data.
|
210
|
+
Args:
|
211
|
+
task (Task): The Nornir task object.
|
212
|
+
all_interfaces: (List[Dict]): List of all interfaces from NetBox.
|
213
|
+
Returns:
|
214
|
+
Result: Nornir result object.
|
215
|
+
"""
|
216
|
+
# Set the failed flag to False
|
217
|
+
failed = False
|
218
|
+
|
219
|
+
# Get the Cisco Support data for the master
|
220
|
+
data = [x for x in all_csupp if x["device"]["id"] == task.host["id"]]
|
221
|
+
# Return if the data list is empty
|
222
|
+
if not data:
|
223
|
+
# Return the Nornir object
|
224
|
+
result = (
|
225
|
+
f"'Load Cisco-Support data' -> NetBoxResponse <Success: {not failed}>\n"
|
226
|
+
+ "-> No Cisco-Support data found in NetBox"
|
227
|
+
)
|
228
|
+
return Result(host=task.host, result=result, changed=False, failed=failed)
|
229
|
+
|
230
|
+
# Dict keys for comprehension to exclude some key-value pairs from the response
|
231
|
+
exclude_keys = ["device"]
|
232
|
+
# Dict comprehension to exclude some key-value pairs
|
233
|
+
data = {k: v for (k, v) in data[0].items() if k not in exclude_keys}
|
234
|
+
task.host["cisco_support"] = {}
|
235
|
+
task.host["cisco_support"]["master"] = data
|
236
|
+
|
237
|
+
# Add all interfaces from the virtual chassis members
|
238
|
+
if task.host.get("virtual_chassis") and task.host["virtual_chassis"].get("members"):
|
239
|
+
task.host["cisco_support"]["members"] = []
|
240
|
+
for member in task.host["virtual_chassis"]["members"]:
|
241
|
+
data = [x for x in all_csupp if x["device"]["id"] == member["id"]]
|
242
|
+
# Dict comprehension to exclude some key-value pairs
|
243
|
+
data = {k: v for (k, v) in data[0].items() if k not in exclude_keys}
|
244
|
+
task.host["cisco_support"]["members"].append(data)
|
245
|
+
|
246
|
+
# Return the Nornir
|
247
|
+
return Result(host=task.host)
|
248
|
+
|
249
|
+
|
250
|
+
#### Nornir Tasks in regular Function #######################################################################
|
251
|
+
|
252
|
+
|
253
|
+
def load_additional_netbox_data(nr: Nornir, add_netbox_data: dict[str:bool]) -> Nornir:
|
254
|
+
"""
|
255
|
+
Load additional data from NetBox into Nornir inventory based on 'add_netbox_data' options.
|
256
|
+
"""
|
257
|
+
# pylint: disable=invalid-name
|
258
|
+
result_msg = []
|
259
|
+
task_text = "NORNIR load NetBox additional inventory data"
|
260
|
+
|
261
|
+
# Get the NetBox url from the inventory options
|
262
|
+
nb_url = nr.config.inventory.options["nb_url"]
|
263
|
+
|
264
|
+
# Add the virtual chassis data to the devices
|
265
|
+
if add_netbox_data.get("load_virtual_chassis_data"):
|
266
|
+
# Get all devices from NetBox
|
267
|
+
all_devices = get_nb_resources(url=f"{nb_url}/api/dcim/devices/?limit=1000")
|
268
|
+
# Run the custom Nornir task _load_virtual_chassis_data
|
269
|
+
result = nr.run(
|
270
|
+
name=task_text,
|
271
|
+
task=_load_virtual_chassis_data,
|
272
|
+
all_devices=all_devices,
|
273
|
+
on_failed=True,
|
274
|
+
)
|
275
|
+
# Exit the script if the task failed
|
276
|
+
if result.failed:
|
277
|
+
print_result(result)
|
278
|
+
exit_error(
|
279
|
+
task_text=task_text,
|
280
|
+
text="ALERT: LOAD VIRTUAL-CHASSIS DATA FAILED!",
|
281
|
+
msg="-> Analyse the Nornir Init Python function and NetBox API response",
|
282
|
+
)
|
283
|
+
# Append the result message
|
284
|
+
result_msg.append(" - Load Virtual-Chassis")
|
285
|
+
|
286
|
+
# Add the Cisco support data to the devices
|
287
|
+
if add_netbox_data.get("load_cisco_support_data"):
|
288
|
+
# Get all Cisco-Support data from NetBox
|
289
|
+
all_csupp = get_nb_resources(url=f"{nb_url}/api/plugins/device-support/cisco-device/?limit=1000")
|
290
|
+
# Run the custom Nornir task _load_cisco_support_data
|
291
|
+
result = nr.run(
|
292
|
+
name=task_text,
|
293
|
+
task=_load_cisco_support_data,
|
294
|
+
all_csupp=all_csupp,
|
295
|
+
on_failed=True,
|
296
|
+
)
|
297
|
+
# Exit the script if the task failed
|
298
|
+
if result.failed:
|
299
|
+
print_result(result)
|
300
|
+
exit_error(
|
301
|
+
task_text=task_text,
|
302
|
+
text="ALERT: LOAD CISCO-SUPPORT FAILED!",
|
303
|
+
msg="-> Analyse the Nornir Init Python function and NetBox API response",
|
304
|
+
)
|
305
|
+
# Append the result message
|
306
|
+
result_msg.append(" - Load Cisco-Support")
|
307
|
+
|
308
|
+
# Add the vlan data to the devices
|
309
|
+
if add_netbox_data.get("load_vlan_data"):
|
310
|
+
# Get all vlans from NetBox
|
311
|
+
all_vlans = get_nb_resources(url=f"{nb_url}/api/ipam/vlans/?limit=1000?")
|
312
|
+
# Run the custom Nornir task _load_vlan_data
|
313
|
+
result = nr.run(
|
314
|
+
name=task_text,
|
315
|
+
task=_load_vlan_data,
|
316
|
+
all_vlans=all_vlans,
|
317
|
+
on_failed=True,
|
318
|
+
)
|
319
|
+
# Exit the script if the task failed
|
320
|
+
if result.failed:
|
321
|
+
print_result(result)
|
322
|
+
exit_error(
|
323
|
+
task_text=task_text,
|
324
|
+
text="ALERT: LOAD VLAN DATA FAILED!",
|
325
|
+
msg="-> Analyse the Nornir Init Python function and NetBox API response",
|
326
|
+
)
|
327
|
+
# Append the result message
|
328
|
+
result_msg.append(" - Load VLANs")
|
329
|
+
|
330
|
+
# Add the interfaces data to the devices
|
331
|
+
if add_netbox_data.get("load_interface_data"):
|
332
|
+
# Get all interfaces from NetBox
|
333
|
+
all_interfaces = get_nb_resources(url=f"{nb_url}/api/dcim/interfaces/?limit=1000")
|
334
|
+
# Run the custom Nornir task _load_interface_data
|
335
|
+
# Enrich the interface data with VLAN data if the 'load_vlan_data' option is set
|
336
|
+
result = nr.run(
|
337
|
+
name=task_text,
|
338
|
+
task=_load_interface_data,
|
339
|
+
all_interfaces=all_interfaces,
|
340
|
+
enrich_vlan_data=add_netbox_data.get("load_vlan_data", False),
|
341
|
+
on_failed=True,
|
342
|
+
)
|
343
|
+
# Exit the script if the task failed
|
344
|
+
if result.failed:
|
345
|
+
print_result(result)
|
346
|
+
exit_error(
|
347
|
+
task_text=task_text,
|
348
|
+
text="ALERT: LOAD INTERFACE DATA FAILED!",
|
349
|
+
msg="-> Analyse the Nornir Init Python function and NetBox API response",
|
350
|
+
)
|
351
|
+
# Append the result message
|
352
|
+
result_msg.append(" - Load Interfaces")
|
353
|
+
|
354
|
+
# Print the result of the additional loaded data
|
355
|
+
print_task_name(text=task_text)
|
356
|
+
print(task_info(text=task_text, changed=False))
|
357
|
+
print("'Load NetBox additional inventory data' -> NornirResponse <Success: True>")
|
358
|
+
print("-> Additional loaded data:")
|
359
|
+
for msg in result_msg:
|
360
|
+
print(msg)
|