nornir-collection 0.0.24__py3-none-any.whl → 0.0.26__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/cisco/configuration_management/netconf/config_tasks.py +66 -1
- nornir_collection/cisco/configuration_management/utils.py +0 -2
- nornir_collection/netbox/inventory.py +1 -1
- nornir_collection/netbox/update_prefixes_ip_addresses.py +31 -28
- {nornir_collection-0.0.24.dist-info → nornir_collection-0.0.26.dist-info}/METADATA +3 -2
- {nornir_collection-0.0.24.dist-info → nornir_collection-0.0.26.dist-info}/RECORD +9 -9
- {nornir_collection-0.0.24.dist-info → nornir_collection-0.0.26.dist-info}/WHEEL +1 -1
- {nornir_collection-0.0.24.dist-info → nornir_collection-0.0.26.dist-info/licenses}/LICENSE +0 -0
- {nornir_collection-0.0.24.dist-info → nornir_collection-0.0.26.dist-info}/top_level.txt +0 -0
@@ -360,6 +360,71 @@ def nc_edit_cleanup_svi(task: Task, verbose: bool = False) -> Result:
|
|
360
360
|
return Result(host=task.host, custom_result=custom_result, failed=task_failed)
|
361
361
|
|
362
362
|
|
363
|
+
def nc_edit_cleanup_vlan(task: Task, verbose: bool = False) -> Result:
|
364
|
+
"""
|
365
|
+
TBD
|
366
|
+
"""
|
367
|
+
# The custom_result list will be filled with the results
|
368
|
+
custom_result = []
|
369
|
+
|
370
|
+
#### Get all current configured VLANs with RESTCONF #####################################################
|
371
|
+
|
372
|
+
task_text = "RESTCONF GET VLANs"
|
373
|
+
|
374
|
+
# Set the RESTCONF port, yang query and url to get all configured SVIs
|
375
|
+
yang_query = "Cisco-IOS-XE-native:native/vlan/Cisco-IOS-XE-vlan:vlan-list"
|
376
|
+
url = f"https://{task.host.hostname}:443/restconf/data/{yang_query}"
|
377
|
+
|
378
|
+
# RESTCONF HTTP Get for all SVIs
|
379
|
+
response = rc_cisco_get(url=url, auth=(task.host.username, task.host.password), verify=False)
|
380
|
+
|
381
|
+
# Set the RESTCONF result and return the Nornir result if the RESTCONF response status_code is not 200
|
382
|
+
custom_result = set_restconf_result(
|
383
|
+
task=Task,
|
384
|
+
task_text=task_text,
|
385
|
+
yang_query=yang_query,
|
386
|
+
response=response,
|
387
|
+
custom_result=custom_result,
|
388
|
+
verbose=verbose,
|
389
|
+
)
|
390
|
+
|
391
|
+
# Create a list with all current configured VLANs except the default VLAN 1
|
392
|
+
current_vlans = [x for x in response["json"]["Cisco-IOS-XE-vlan:vlan-list"] if x["id"] != 1]
|
393
|
+
|
394
|
+
#### Render NETCONF payload to remove VLANs with Jinja2 #################################################
|
395
|
+
|
396
|
+
task_text = "Render Jinja2 NETCONF payload"
|
397
|
+
# Create a list with all configured VLANs which are not part of the inventory
|
398
|
+
remove_vlans = [x for x in current_vlans if x["id"] not in [x["vid"] for x in task.host["cfg_vlans"]]]
|
399
|
+
|
400
|
+
# If there are no VLANs to remove, return the Nornir result
|
401
|
+
if not remove_vlans:
|
402
|
+
custom_result.append(
|
403
|
+
f"{task_result(text=task_text, changed=False, level_name='INFO', failed=False)}\n"
|
404
|
+
+ f"'{task_text}' -> NornirResponse <Success: True>\n"
|
405
|
+
+ "-> No VLANs to remove"
|
406
|
+
)
|
407
|
+
return Result(host=task.host, custom_result=custom_result, failed=False)
|
408
|
+
|
409
|
+
# Set the info message for the Nornir result
|
410
|
+
info_msg = f"VLANs to remove: {len(remove_vlans)}"
|
411
|
+
|
412
|
+
# Render the Jinja2 payload template and configure the NETCONF candidate datastore
|
413
|
+
custom_result, task_failed = netconf_configure_jinja2_rendered_payload_template(
|
414
|
+
task=task,
|
415
|
+
j2_task_text=task_text,
|
416
|
+
j2_tpl_path="iosxe_netconf/tpl_sys/cleanup/cleanup_vlan.j2",
|
417
|
+
custom_result=custom_result,
|
418
|
+
task_failed=False,
|
419
|
+
info_msg=info_msg,
|
420
|
+
verbose=verbose,
|
421
|
+
j2_kwargs={"remove_vlans": remove_vlans},
|
422
|
+
)
|
423
|
+
|
424
|
+
# Return the Nornir NETCONF result
|
425
|
+
return Result(host=task.host, custom_result=custom_result, failed=task_failed)
|
426
|
+
|
427
|
+
|
363
428
|
def nc_edit_tpl_config(task: Task, tpl_startswith: str, verbose: bool = False) -> Result:
|
364
429
|
"""
|
365
430
|
TBD
|
@@ -477,7 +542,6 @@ def nc_cfg_cleanup(nr: Nornir, cfg_status: bool = True, verbose: bool = False) -
|
|
477
542
|
"""
|
478
543
|
TBD
|
479
544
|
"""
|
480
|
-
|
481
545
|
# Return False if cfg_status argument is False
|
482
546
|
if not cfg_status:
|
483
547
|
return False
|
@@ -485,6 +549,7 @@ def nc_cfg_cleanup(nr: Nornir, cfg_status: bool = True, verbose: bool = False) -
|
|
485
549
|
tasks = {
|
486
550
|
nc_edit_cleanup_portchannel: "NETCONF portchannel cleanup",
|
487
551
|
nc_edit_cleanup_svi: "NETCONF vlan interface cleanup",
|
552
|
+
nc_edit_cleanup_vlan: "NETCONF vlan cleanup",
|
488
553
|
}
|
489
554
|
|
490
555
|
# Run each task from the Nornir tasks list
|
@@ -234,9 +234,7 @@ def add_interface_data(task: Task, interface: dict) -> dict:
|
|
234
234
|
"""
|
235
235
|
# If the interface is part of a Port-channel
|
236
236
|
if "lag" in interface and interface["lag"] is not None:
|
237
|
-
# Set the int_config_context of the Port-channel to the int_config_context of the interface
|
238
237
|
po_interface = [i for i in task.host["interfaces"] if i["name"] == interface["lag"]["name"]]
|
239
|
-
interface["int_config_context"] = po_interface[0]["int_config_context"]
|
240
238
|
interface["description"] = po_interface[0]["description"]
|
241
239
|
interface["portchannel_number"] = extract_interface_number(interface["lag"]["name"])
|
242
240
|
|
@@ -92,7 +92,7 @@ def _load_interface_data(task: Task, all_interfaces: List[Dict], enrich_vlan_dat
|
|
92
92
|
# fmt: off
|
93
93
|
include_keys = [
|
94
94
|
"name", "int_template", "description", "type", "lag", "mode", "untagged_vlan", "tagged_vlans",
|
95
|
-
"count_ipaddresses", "count_fhrp_groups", "int_peer_device", "
|
95
|
+
"count_ipaddresses", "count_fhrp_groups", "int_peer_device", "enabled",
|
96
96
|
]
|
97
97
|
# fmt: on
|
98
98
|
# Make some normalization to the device interfaces data with the interface_filter list and others
|
@@ -306,6 +306,24 @@ def nmap_scan_host_ip_or_subnet(hosts: str) -> list:
|
|
306
306
|
return nmap_scan_result
|
307
307
|
|
308
308
|
|
309
|
+
def nmap_double_check_ips(ip_list: dict) -> list:
|
310
|
+
"""
|
311
|
+
TBD
|
312
|
+
"""
|
313
|
+
verified_ips = []
|
314
|
+
# Nmap scan ip-addresses of the maybe_delete_ips list
|
315
|
+
for ip in ip_list:
|
316
|
+
# Scan the prefix with nmap
|
317
|
+
scan_result = nmap_scan_host_ip_or_subnet(hosts=ip["address"])
|
318
|
+
# Add the nmap scan result to the inactive_ips list with the ID of the ip-address
|
319
|
+
if scan_result:
|
320
|
+
# As a single ip-address is scanned the scan_result can have only one list item
|
321
|
+
verified_ips.append({"id": ip["id"], **scan_result[0]})
|
322
|
+
|
323
|
+
# Return the verified ip-addresses list
|
324
|
+
return verified_ips
|
325
|
+
|
326
|
+
|
309
327
|
def get_ipfabric_data_for_prefix(prefix: dict) -> tuple:
|
310
328
|
"""
|
311
329
|
TBD
|
@@ -571,15 +589,8 @@ def delete_inactive_auto_discovered_ip_addresses(
|
|
571
589
|
maybe_delete_ips = create_ip_list(
|
572
590
|
loop_list=prefix["discovered_ips"], check_list=prefix["datasource_ips"], is_in_both=False
|
573
591
|
)
|
574
|
-
|
575
|
-
|
576
|
-
# Nmap scan ip-addresses of the maybe_delete_ips list
|
577
|
-
for ip in maybe_delete_ips:
|
578
|
-
# Scan the prefix with nmap
|
579
|
-
scan_result = nmap_scan_host_ip_or_subnet(hosts=ip["address"])
|
580
|
-
# Add the nmal scan result to the inactive_ips list
|
581
|
-
if scan_result:
|
582
|
-
delete_ips.extend(scan_result)
|
592
|
+
# Nmap scan ip-addresses of the maybe_delete_ips list
|
593
|
+
delete_ips = nmap_double_check_ips(ip_list=maybe_delete_ips)
|
583
594
|
|
584
595
|
# If ip-addresses have been found
|
585
596
|
if delete_ips:
|
@@ -659,14 +670,8 @@ def update_inactive_ip_addresses(nb_url: str, prefix: dict, ds: Literal["nmap",
|
|
659
670
|
maybe_active_ips = create_ip_list(
|
660
671
|
loop_list=prefix["inactive_ips"], check_list=prefix["datasource_ips"], is_in_both=False
|
661
672
|
)
|
662
|
-
|
663
|
-
|
664
|
-
for ip in maybe_active_ips:
|
665
|
-
# Scan the prefix with nmap
|
666
|
-
scan_result = nmap_scan_host_ip_or_subnet(hosts=ip["address"])
|
667
|
-
# Add the nmal scan result to the inactive_ips list
|
668
|
-
if scan_result:
|
669
|
-
active_ips.extend(scan_result)
|
673
|
+
# Nmap scan ip-addresses of the maybe_active_ips list
|
674
|
+
active_ips = nmap_double_check_ips(ip_list=maybe_active_ips)
|
670
675
|
|
671
676
|
# If ip-addresses have been found
|
672
677
|
if active_ips:
|
@@ -722,21 +727,16 @@ def update_active_ip_addresses(
|
|
722
727
|
resp=resp, nb_type="ip", data=active_ips, ds=ds, task_text=task_text, text=text
|
723
728
|
)
|
724
729
|
result.extend(sub_result)
|
725
|
-
|
730
|
+
if sub_failed:
|
731
|
+
failed = True
|
732
|
+
result.append(f"-> Payload:\n{payload}")
|
726
733
|
|
727
734
|
# Update the ip-addresses with the status 'active' that are not part of the datacenter list
|
728
735
|
maybe_inactive_ips = create_ip_list(
|
729
736
|
loop_list=prefix["active_ips"], check_list=prefix["datasource_ips"], is_in_both=False
|
730
737
|
)
|
731
|
-
|
732
|
-
|
733
|
-
# Nmap scan ip-addresses of the maybe_inactive_ips list
|
734
|
-
for ip in maybe_inactive_ips:
|
735
|
-
# Scan the prefix with nmap
|
736
|
-
scan_result = nmap_scan_host_ip_or_subnet(hosts=ip["address"])
|
737
|
-
# Add the nmal scan result to the inactive_ips list
|
738
|
-
if scan_result:
|
739
|
-
inactive_ips.extend(scan_result)
|
738
|
+
# Nmap scan ip-addresses of the maybe_inactive_ips list
|
739
|
+
inactive_ips = nmap_double_check_ips(ip_list=maybe_inactive_ips)
|
740
740
|
# Create a new list to exclude the overwrite_active ip-addresses
|
741
741
|
inactive_ips = [ip for ip in inactive_ips if ip["address"] not in overwrite_active]
|
742
742
|
|
@@ -756,7 +756,10 @@ def update_active_ip_addresses(
|
|
756
756
|
resp=resp, nb_type="ip", data=inactive_ips, ds=ds, task_text=task_text, text=text
|
757
757
|
)
|
758
758
|
result.extend(sub_result)
|
759
|
-
|
759
|
+
if sub_failed:
|
760
|
+
failed = True
|
761
|
+
result.append(f"-> Data for Payload:\n{inactive_ips}")
|
762
|
+
result.append(f"-> Payload:\n{payload}")
|
760
763
|
|
761
764
|
return result, failed
|
762
765
|
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: nornir-collection
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.26
|
4
4
|
Summary: Nornir-Collection contains network automation functions and complete IaC workflows with Nornir and other python libraries. It contains Nornir tasks and general functions in Nornir style.
|
5
5
|
Author: Willi Kubny
|
6
6
|
Author-email: willi.kubny@gmail.ch
|
@@ -47,6 +47,7 @@ Dynamic: author-email
|
|
47
47
|
Dynamic: classifier
|
48
48
|
Dynamic: description
|
49
49
|
Dynamic: description-content-type
|
50
|
+
Dynamic: license-file
|
50
51
|
Dynamic: requires-dist
|
51
52
|
Dynamic: requires-python
|
52
53
|
Dynamic: summary
|
@@ -8,13 +8,13 @@ nornir_collection/cisco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
|
|
8
8
|
nornir_collection/cisco/configuration_management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
9
|
nornir_collection/cisco/configuration_management/processor.py,sha256=KjhilyyDDiYL7wFemGEWSP16OLeM4dENmrtb20LRssY,6443
|
10
10
|
nornir_collection/cisco/configuration_management/pyats.py,sha256=j9XzG3ttURR0wtu2Se9QQEpG5o2kq9mqDkReNCdWKpk,8932
|
11
|
-
nornir_collection/cisco/configuration_management/utils.py,sha256=
|
11
|
+
nornir_collection/cisco/configuration_management/utils.py,sha256=YZE3pgaA4kKnIQkkLenUhxLoYLi1sd0sa4jNfSulC34,18452
|
12
12
|
nornir_collection/cisco/configuration_management/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
13
|
nornir_collection/cisco/configuration_management/cli/config_tasks.py,sha256=mWXysgUm6ymNLQjomB1T05QT9A-fdV1aEKFzzDrfCUw,22147
|
14
14
|
nornir_collection/cisco/configuration_management/cli/config_workflow.py,sha256=GIka5SPLZ7M2zCFv8Jadl73QC-InnGopzI8xQt36MfM,3459
|
15
15
|
nornir_collection/cisco/configuration_management/cli/show_tasks.py,sha256=w9p2Iks33-pE4-YztH6vj-eI0MuPI7YD6gZhRcpQF7M,27971
|
16
16
|
nornir_collection/cisco/configuration_management/netconf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
|
-
nornir_collection/cisco/configuration_management/netconf/config_tasks.py,sha256=
|
17
|
+
nornir_collection/cisco/configuration_management/netconf/config_tasks.py,sha256=V1goW79OWxA7kNle4M2NzK47TZLw7TGji-2QaTiviSI,25696
|
18
18
|
nornir_collection/cisco/configuration_management/netconf/config_workflow.py,sha256=qxB4DolQL2WJO9JRATzANhIwYPNuKyuN0hI9-ABzJq8,14557
|
19
19
|
nornir_collection/cisco/configuration_management/netconf/nr_cfg_iosxe_netconf.py,sha256=qKb1EeiYbCO96AE6ETaNxRrM2nCfsbX00nwcPK9ZSkc,8629
|
20
20
|
nornir_collection/cisco/configuration_management/netconf/ops_tasks.py,sha256=cj7cpJNvY2bytv9VOqwg_7qOekL-cIL0EjML2KT4TQM,10659
|
@@ -35,13 +35,13 @@ nornir_collection/fortinet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
35
35
|
nornir_collection/fortinet/utils.py,sha256=xkvxdJy3-aD39WK_9Gc0rY9r-OxfHnPVNMspy3KZbcE,1174
|
36
36
|
nornir_collection/netbox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
37
37
|
nornir_collection/netbox/custom_script.py,sha256=yU1lbv_25b3qAWA6GRsVYpEuh0KUPTVo47U5s_lksjo,4050
|
38
|
-
nornir_collection/netbox/inventory.py,sha256=
|
38
|
+
nornir_collection/netbox/inventory.py,sha256=4KrmvHrY29PH9prs7D_oTfraUDg1svDbXEamaAxev1M,15507
|
39
39
|
nornir_collection/netbox/set_device_status.py,sha256=vtn0KcR-91Z2aLjbEpZRef1Jip8eM9GWbKRiAJuEjLY,2437
|
40
40
|
nornir_collection/netbox/sync_datasource.py,sha256=eEsgwy_arIPbA-ObqqzTNdU9aiP80s7LCzAKA6hCXYQ,4703
|
41
41
|
nornir_collection/netbox/update_cisco_inventory_data.py,sha256=Aq4VGvAIiBhOCsSOF-wBUrpYtBXR8HwR3NCWEeM4d0g,6426
|
42
42
|
nornir_collection/netbox/update_cisco_support_plugin_data.py,sha256=H8SfqESad64LrZrsWOaICHKj122sgu96dK9RcbvtzGM,13896
|
43
43
|
nornir_collection/netbox/update_fortinet_inventory_data.py,sha256=ltwkE_bFljRUR4aeOxorChCsHdZciD1TqvoPnWTUIUg,6367
|
44
|
-
nornir_collection/netbox/update_prefixes_ip_addresses.py,sha256=
|
44
|
+
nornir_collection/netbox/update_prefixes_ip_addresses.py,sha256=tPdFkjv84OU9yOwyAWiI9ZV1JdtwUWy08NGgnN0uZhk,49692
|
45
45
|
nornir_collection/netbox/update_purestorage_inventory_data.py,sha256=cGZNMTZWJ0wu1BYdE92EVN-C-oLMJHxaKi_-1cMg0Ow,5368
|
46
46
|
nornir_collection/netbox/utils.py,sha256=mCV7QfLeR6kKurZVpMrHucIoru759RiwzE4NGEx91kI,12140
|
47
47
|
nornir_collection/netbox/verify_device_primary_ip.py,sha256=6UCdZaZxhV4v8KqpjSpE9c7jaxIAF2krrknrrRj1AvM,8690
|
@@ -52,8 +52,8 @@ nornir_collection/nornir_plugins/inventory/staggered_yaml.py,sha256=nBvUFq7U5zVT
|
|
52
52
|
nornir_collection/nornir_plugins/inventory/utils.py,sha256=mxIlKK-4PHqCnFKn7Oozu1RW_JB5z1TgEYc-ave70nE,11822
|
53
53
|
nornir_collection/purestorage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
54
54
|
nornir_collection/purestorage/utils.py,sha256=TqU2sKz0ENnmSDEBcSvXPnVkI1DVHOogI68D7l32g7I,1730
|
55
|
-
nornir_collection-0.0.
|
56
|
-
nornir_collection-0.0.
|
57
|
-
nornir_collection-0.0.
|
58
|
-
nornir_collection-0.0.
|
59
|
-
nornir_collection-0.0.
|
55
|
+
nornir_collection-0.0.26.dist-info/licenses/LICENSE,sha256=bOPVh1OVNwz2tCjkLaChWT6AoXdtqye3aua5l0tgYJo,1068
|
56
|
+
nornir_collection-0.0.26.dist-info/METADATA,sha256=b27m0rRe6UVYls_c-iZCGNeHlcDquUvM79naa8c5k8k,7191
|
57
|
+
nornir_collection-0.0.26.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
58
|
+
nornir_collection-0.0.26.dist-info/top_level.txt,sha256=OyCzPWABf-D0AOHm9ihrwdk5eq200BnKna6gIDspwsE,18
|
59
|
+
nornir_collection-0.0.26.dist-info/RECORD,,
|
File without changes
|
File without changes
|