Recently my article is all about pyATS
A Python library for verification developed by Cisco. Please break the details ... For details ↓ Official Documents Introduction to me Something talked about in recent Qiita, especially in the automation area (I think)
What I created is that the prepared Config is correctly input to the target device, The input result is displayed as a difference in show running-config, and the structured output acquired by genie learn is diffed to display the difference in an easy-to-understand manner. This time, it is designed to return to the Config before the start.
├── check_acl.py ← body of script
├── testbed
│ └── devnet_always.yml ← testbed file
└── vars
├── csr1000v-1.yml ← Node Vars listed in testbed
├── iosxr1.yml
└── sbx-n9kv-ao.yml
testbed A file that collects connection destination information, this time prepare the following By the way, this explanation is previous article, so please omit it.
devnet_always.yml
---
testbed:
name: SandBox
devices:
sbx-n9kv-ao:
alias: uut
credentials:
default:
username: admin
password: Admin_1234!
connections:
vty:
protocol: ssh
ip: sbx-nxos-mgmt.cisco.com
port: 8181
os: nxos
type: nxos
iosxr1:
alias: rt
credentials:
default:
username: admin
password: C1sco12345
connections:
vty:
protocol: ssh
ip: sbx-iosxr-mgmt.cisco.com
port: 8181
os: iosxr
type: iosxr
csr1000v-1:
alias: xe1
credentials:
default:
username: developer
password: C1sco12345
connections:
vty:
protocol: ssh
ip: ios-xe-mgmt-latest.cisco.com
port: 8181
os: iosxe
type: iosxe
csr1000v:
alias: xe0
credentials:
default:
username: developer
password: C1sco12345
connections:
vty:
protocol: ssh
ip: ios-xe-mgmt.cisco.com
port: 8181
os: iosxe
type: iosxe
To explain the contents, command
is the Config required for inputting the settings, and clear
is the Config required for returning the settings.
Added Static Route and ACL to csr1000v-1 in IOS XE
csr1000v-1.yml
---
command: |
ip route 8.8.8.8 255.255.255.255 GigabitEthernet1 10.10.20.254
ip access-list extended TEST
permit ip any 8.8.8.8 0.0.0.0 log
remark ****TEST****
clear: |
no ip route 8.8.8.8 255.255.255.255 GigabitEthernet1 10.10.20.254
no ip access-list extended TEST
IOSXR iosxr1 prepares only files and the contents are empty.
iosxr1.yml
---
command: |
clear: |
Vars of csr1000v in Testbed is not prepared. Next, I will introduce my own Script. It is written in Python. Ugly, cool! Please let me know if you feel that, because I am not using it for business but using it for verification It may seem like a crappy code to crunchy programmers, but please forgive me. Script
check_acl.py
import logging
import yaml
#Import Genie module
from genie.conf import Genie
from genie.utils.diff import Diff
class setupDevices(object):
def __init__(self):
#For storing Device
self.listDevice = list()
#running-For storing config
self.beforeConfig = list()
self.afterConfig = list()
#Stores only Devices with vars files
self.targetDevice = list()
self.config = dict()
#For routing storage
self.beforeRouting = list()
self.afterRouting = list()
#for acl storage
self.beforeAcl = list()
self.afterAcl = list()
#Initialize testbed
try:
self.testbed = Genie.init('testbed/devnet_always.yml')
if self.testbed :
logging.info('testbed init:OK')
for keys in self.testbed.devices:
self.listDevice.append(keys)
except TypeError:
logging.warning("Testbed file is wrong")
#Check if there is a Var file
for device in self.listDevice:
try:
with open('vars/{}.yml'.format(device), 'r') as yml:
device_config = { device + "_config" :yaml.safe_load(yml)}
self.config.update(device_config)
self.targetDevice.append(device)
except FileNotFoundError:
logging.warning("{}File not".format(device))
continue
#Enter the login process
self.login()
#Login
def login(self):
logging.info("*"*32 + "Login" + "*"*32)
for device in self.targetDevice:
self.testbed.devices[device].connect(log_stdout=False)
if self.testbed.devices[device].is_connected():
logging.info("{}: connected".format(device))
else:
logging.info("{}: disconnected".format(device))
#Pre-log acquisition
def getBeforeAcl(self):
logging.info("*"*32 + "Pre-ACL confirmation" + "*"*32)
for device in self.targetDevice:
self.beforeAcl.append(self.testbed.devices[device].learn('acl'))
logging.info("{}: beforeAcl get".format(device))
def getBeforeConfig(self):
logging.info("*"*32 + "Pre-log acquisition"+ "*"*32)
for device in self.targetDevice:
self.beforeConfig.append(self.testbed.devices[device].learn('config'))
logging.info("{}: beforeConfig get".format(device))
def getBeforeRoute(self):
logging.info("*"*32 + "Prior Routing Tabel confirmation" + "*"*32)
for device in self.targetDevice:
self.beforeRouting.append(self.testbed.devices[device].learn('routing'))
logging.info("{}: beforeRouting get".format(device))
#Config input
def inputConfig(self):
logging.info("*"*32 + "Config input" + "*"*32)
for device in self.targetDevice:
self.testbed.devices[device].configure(self.config[device+"_config"]['command'])
logging.info("{}: input_config".format(device))
#Delete the input Config
def claerConfig(self):
logging.info("*"*32 + "Config back" + "*"*32)
for device in self.targetDevice:
self.testbed.devices[device].configure(self.config[device+"_config"]['clear'])
logging.info("{}: clear_config".format(device))
#Post Log acquisition
def getAfterConfig(self):
logging.info("*"*32 + "Post-log acquisition" + "*"*32)
for device in self.targetDevice:
self.afterConfig.append(self.testbed.devices[device].learn('config'))
logging.info("{}: afterConfig get".format(device))
def getAfterAcl(self):
logging.info("*"*32 + "Post-ACL confirmation" + "*"*32)
for device in self.targetDevice:
self.afterAcl.append(self.testbed.devices[device].learn('acl'))
logging.info("{}: afterAcl get".format(device))
def getAfterRoute(self):
logging.info("*"*32 + "Subsequent Routing Tabel confirmation" + "*"*32)
for device in self.targetDevice:
self.afterRouting.append(self.testbed.devices[device].learn('routing'))
logging.info("{}: afterRouting get".format(device))
#Log out
def logout(self):
logging.info("*"*32 + "Log out" + "*"*32)
for device in self.targetDevice:
self.testbed.devices[device].disconnect()
if self.testbed.devices[device].is_connected():
logging.info("{}: connected".format(device))
else:
logging.info("{}: disconnected".format(device))
#Diff Config
def diffConfig(self):
logging.info("*"*32 + "Diff" + "*"*32)
if self.beforeConfig and self.afterConfig:
for config_b,config_a,device in zip(self.beforeConfig,self.afterConfig,self.self.targetDevice):
config_diff = Diff(config_b,config_a)
config_diff.findDiff()
print("\n====={}_ConfigDiff=====".format(device))
print(config_diff)
if self.beforeRouting and self.afterRouting:
for config_b,config_a,device in zip(self.beforeRouting,self.afterRouting,self.self.targetDevice):
config_diff = Diff(config_b,config_a)
config_diff.findDiff()
print("\n====={}_RouteDiff=====".format(device))
print(config_diff)
if self.beforeAcl and self.afterAcl:
for config_b,config_a,device in zip(self.beforeAcl,self.afterAcl,self.self.targetDevice):
config_diff = Diff(config_b,config_a)
config_diff.findDiff()
print("\n====={}_AclDiff=====".format(device))
print(config_diff)
if __name__ == "__main__":
#Change log level to info
logging.basicConfig(level=logging.INFO)
logging.info("*"*32 + "Start processing" + "*"*32)
devnet = setupDevices()
devnet.getBeforeConfig()
devnet.getBeforeRoute()
devnet.getBeforeAcl()
devnet.inputConfig()
devnet.getAfterConfig()
devnet.getAfterRoute()
devnet.getAfterAcl()
devnet.claerConfig()
devnet.logout()
devnet.diffConfig()
logging.info("*"*32 + "End" + "*"*32)
If you paste it all at once, the Log will be boring, so I will explain it in small pieces.
Run the script with python check_acl.py
.
The testbed file is read as a process at startup. Next, read the Device name + _config.yml file in testbed. At this time, if the target yaml file does not exist, the message "There is no XX file" is displayed.
(nw_automate) 00:26:33 my Script $python check_acl.py
INFO : ********************************Start processing********************************
INFO : testbed init:OK
WARNING : sbx-n9kv-no ao file
WARNING :no csr1000v file
Next is the login process.
Log in with devices [device] .connect (log_stdout = False)
.
At this time, since log_stdout = False
is specified, the log at login is not displayed.
INFO : ********************************Login********************************
INFO : iosxr1: connected
INFO : csr1000v-1: connected
After logging in, you will get various pre-logs. After acquisition, various pre-states will be stored in List.
Items you want to check | Ops that can be obtained |
---|---|
RunningConfig | device['Device name'].learn('config') |
ACL | device['Device name'].learn('acl') |
Routing | device['Device name'].learn('routing') |
INFO : ********************************Pre-log acquisition********************************
INFO : iosxr1: beforeConfig get
INFO : csr1000v-1: beforeConfig get
INFO : ********************************Prior Routing Tabel confirmation********************************
INFO : Could not learn <class 'genie.libs.parser.iosxr.show_routing.ShowRouteIpv6Distributor'> 'genie.libs.parser.iosxr.show_routing.ShowRouteIpDistributor'> 'genie.libs.parser.iosxr.show_routing.ShowRouteIpv6Distributor'>
INFO : iosxr1: beforeRouting get
INFO : Could not learn <class 'genie.libs.parser.iosxe.show_routing.ShowIpv6RouteDistributor'>
'genie.libs.parser.iosxe.show_routing.ShowIpRouteDistributor'> 'genie.libs.parser.iosxe.show_routing.ShowIpv6RouteDistributor'>
INFO : csr1000v-1: beforeRouting get
INFO : ********************************Pre-ACL confirmation********************************
INFO : Could not learn <class 'genie.libs.parser.iosxr.show_acl.ShowAclAfiAll'>
Parser Output is empty
INFO : Could not learn <class'genie.libs.parser.iosxr.show_acl.ShowAclEthernetServices'>
INFO : | Commands for learning feature 'Acl'
INFO : | - Commands with empty output
INFO : | cmd: <class 'genie.libs.parser.iosxr.show_acl.ShowAclAfiAll'>
INFO : | cmd: <class 'genie.libs.parser.iosxr.show_acl.ShowAclEthernetServices'>
INFO : iosxr1: beforeAcl get
INFO : | Commands for learning feature 'Acl'
INFO : | cmd: <class 'genie.libs.parser.iosxe.show_acl.ShowAccessLists'>
INFO : csr1000v-1: beforeAcl get
Next, submit the Config described in [command]
of the Vars file.
After inputting, the post-log will be the same as the log taken in advance. (abridgement···)
INFO : ********************************Config input********************************
INFO : iosxr1: input_config
INFO : csr1000v-1: input_config
INFO : ********************************Post-log acquisition********************************
INFO : iosxr1: afterConfig get
INFO : csr1000v-1: afterConfig get
INFO : ********************************Subsequent Routing Tabel confirmation********************************
After getting the post-log, Config is also restored.
Return with the contents described in clear
of the vars file.
After that, log out. After logging out, the current connection status is checked and the status is displayed.
INFO : ********************************Config back********************************
INFO : iosxr1: clear_config
INFO : csr1000v-1: clear_config
INFO : ********************************Log out********************************
INFO : iosxr1: disconnected
INFO : csr1000v-1: disconnected
Finally, diff the obtained pre-Confgi and post-Config. There is a + or-sign at the beginning of the sentence,
For example, iosxr1's ConfigDiff displays the hierarchy nicely. Isn't this much easier to understand than simply comparing Texts?
INFO : ********************************Diff********************************
=====iosxr1_ConfigDiff=====
+Wed Dec 18 16:57:14.949 UTC:
-Wed Dec 18 16:56:58.216 UTC:
router static:
address-family ipv4 unicast:
+ 8.8.8.8/32 10.10.20.254:
=====csr1000v-1_ConfigDiff=====
+Current configuration : 7620 bytes:
+ip route 8.8.8.8 255.255.255.255 GigabitEthernet1 10.10.20.254:
-Current configuration : 7557 bytes:
=====iosxr1_RouteDiff=====
info:
vrf:
default:
address_family:
ipv4:
routes:
+ 8.8.8.8/32:
+ active: True
+ metric: 0
+ next_hop:
+ next_hop_list:
+ 1:
+ index: 1
+ next_hop: 10.10.20.254
+ updated: 00:00:08
+ route: 8.8.8.8/32
+ route_preference: 1
+ source_protocol: static
+ source_protocol_codes: S
=====csr1000v-1_RouteDiff=====
info:
vrf:
default:
address_family:
ipv4:
routes:
+ 8.8.8.8/32:
+ active: True
+ metric: 0
+ next_hop:
+ next_hop_list:
+ 1:
+ index: 1
+ next_hop: 10.10.20.254
+ outgoing_interface: GigabitEthernet1
+ route: 8.8.8.8/32
+ route_preference: 1
+ source_protocol: static
+ source_protocol_codes: S
=====iosxr1_AclDiff=====
=====csr1000v-1_AclDiff=====
INFO : ********************************End********************************
I'm sorry that the article was hard to read because it was just code. However, as you can see from the Diff results, it was easy to check.
I wrote Python very hard, but in fact I can do the same thing without writing any code. I will post a URL that will be helpful. PyATS | Create high-speed automation test using Genie's hidden special move Blitz [Easily check multi-vendor networks with pyATS / Genie and Robot Framework] (https://qiita.com/tahigash/items/ceb0809a4a9464c521b3)
I didn't write this code from scratch, but I managed to collect the information on the net and put it into shape. There is a lot of helpful code on Github called CiscoTestAutomation.
All Logs carried out this time
(nw_automate) 00:26:33 my Script $python check_acl.py
INFO : ********************************Start processing********************************
INFO : testbed init:OK
WARNING : sbx-n9kv-no ao file
WARNING :no csr1000v file
INFO : ********************************Login********************************
INFO : iosxr1: connected
INFO : csr1000v-1: connected
INFO : ********************************Pre-log acquisition********************************
INFO : iosxr1: beforeConfig get
INFO : csr1000v-1: beforeConfig get
INFO : ********************************Prior Routing Tabel confirmation********************************
INFO : Could not learn <class 'genie.libs.parser.iosxr.show_routing.ShowRouteIpv6Distributor'>
Parser Output is empty
INFO : +====================================================================================================================================================+
INFO : | Commands for learning feature 'Routing' |
INFO : +====================================================================================================================================================+
INFO : | - Parsed commands |
INFO : |----------------------------------------------------------------------------------------------------------------------------------------------------|
INFO : | cmd: <class 'genie.libs.parser.iosxr.show_routing.ShowRouteIpDistributor'> |
INFO : |====================================================================================================================================================|
INFO : | - Commands with empty output |
INFO : |----------------------------------------------------------------------------------------------------------------------------------------------------|
INFO : | cmd: <class 'genie.libs.parser.iosxr.show_routing.ShowRouteIpv6Distributor'> |
INFO : |====================================================================================================================================================|
INFO : iosxr1: beforeRouting get
INFO : Could not learn <class 'genie.libs.parser.iosxe.show_routing.ShowIpv6RouteDistributor'>
Parser Output is empty
INFO : +====================================================================================================================================================+
INFO : | Commands for learning feature 'Routing' |
INFO : +====================================================================================================================================================+
INFO : | - Parsed commands |
INFO : |----------------------------------------------------------------------------------------------------------------------------------------------------|
INFO : | cmd: <class 'genie.libs.parser.iosxe.show_routing.ShowIpRouteDistributor'> |
INFO : |====================================================================================================================================================|
INFO : | - Commands with empty output |
INFO : |----------------------------------------------------------------------------------------------------------------------------------------------------|
INFO : | cmd: <class 'genie.libs.parser.iosxe.show_routing.ShowIpv6RouteDistributor'> |
INFO : |====================================================================================================================================================|
INFO : csr1000v-1: beforeRouting get
INFO : ********************************Pre-ACL confirmation********************************
INFO : Could not learn <class 'genie.libs.parser.iosxr.show_acl.ShowAclAfiAll'>
Parser Output is empty
INFO : Could not learn <class 'genie.libs.parser.iosxr.show_acl.ShowAclEthernetServices'>
Parser Output is empty
INFO : +====================================================================================================================================================+
INFO : | Commands for learning feature 'Acl' |
INFO : +====================================================================================================================================================+
INFO : | - Commands with empty output |
INFO : |----------------------------------------------------------------------------------------------------------------------------------------------------|
INFO : | cmd: <class 'genie.libs.parser.iosxr.show_acl.ShowAclAfiAll'> |
INFO : | cmd: <class 'genie.libs.parser.iosxr.show_acl.ShowAclEthernetServices'> |
INFO : |====================================================================================================================================================|
INFO : iosxr1: beforeAcl get
INFO : +====================================================================================================================================================+
INFO : | Commands for learning feature 'Acl' |
INFO : +====================================================================================================================================================+
INFO : | - Parsed commands |
INFO : |----------------------------------------------------------------------------------------------------------------------------------------------------|
INFO : | cmd: <class 'genie.libs.parser.iosxe.show_acl.ShowAccessLists'> |
INFO : |====================================================================================================================================================|
INFO : csr1000v-1: beforeAcl get
INFO : ********************************Config input********************************
INFO : iosxr1: input_config
INFO : csr1000v-1: input_config
INFO : ********************************Post-log acquisition********************************
INFO : iosxr1: afterConfig get
INFO : csr1000v-1: afterConfig get
INFO : ********************************Subsequent Routing Tabel confirmation********************************
INFO : Could not learn <class 'genie.libs.parser.iosxr.show_routing.ShowRouteIpv6Distributor'>
Parser Output is empty
INFO : +====================================================================================================================================================+
INFO : | Commands for learning feature 'Routing' |
INFO : +====================================================================================================================================================+
INFO : | - Parsed commands |
INFO : |----------------------------------------------------------------------------------------------------------------------------------------------------|
INFO : | cmd: <class 'genie.libs.parser.iosxr.show_routing.ShowRouteIpDistributor'> |
INFO : |====================================================================================================================================================|
INFO : | - Commands with empty output |
INFO : |----------------------------------------------------------------------------------------------------------------------------------------------------|
INFO : | cmd: <class 'genie.libs.parser.iosxr.show_routing.ShowRouteIpv6Distributor'> |
INFO : |====================================================================================================================================================|
INFO : iosxr1: afterRouting get
INFO : Could not learn <class 'genie.libs.parser.iosxe.show_routing.ShowIpv6RouteDistributor'>
Parser Output is empty
INFO : +====================================================================================================================================================+
INFO : | Commands for learning feature 'Routing' |
INFO : +====================================================================================================================================================+
INFO : | - Parsed commands |
INFO : |----------------------------------------------------------------------------------------------------------------------------------------------------|
INFO : | cmd: <class 'genie.libs.parser.iosxe.show_routing.ShowIpRouteDistributor'> |
INFO : |====================================================================================================================================================|
INFO : | - Commands with empty output |
INFO : |----------------------------------------------------------------------------------------------------------------------------------------------------|
INFO : | cmd: <class 'genie.libs.parser.iosxe.show_routing.ShowIpv6RouteDistributor'> |
INFO : |====================================================================================================================================================|
INFO : csr1000v-1: afterRouting get
INFO : ********************************Post-ACL confirmation********************************
INFO : Could not learn <class 'genie.libs.parser.iosxr.show_acl.ShowAclAfiAll'>
Parser Output is empty
INFO : Could not learn <class 'genie.libs.parser.iosxr.show_acl.ShowAclEthernetServices'>
Parser Output is empty
INFO : +====================================================================================================================================================+
INFO : | Commands for learning feature 'Acl' |
INFO : +====================================================================================================================================================+
INFO : | - Commands with empty output |
INFO : |----------------------------------------------------------------------------------------------------------------------------------------------------|
INFO : | cmd: <class 'genie.libs.parser.iosxr.show_acl.ShowAclAfiAll'> |
INFO : | cmd: <class 'genie.libs.parser.iosxr.show_acl.ShowAclEthernetServices'> |
INFO : |====================================================================================================================================================|
INFO : iosxr1: afterAcl get
INFO : +====================================================================================================================================================+
INFO : | Commands for learning feature 'Acl' |
INFO : +====================================================================================================================================================+
INFO : | - Parsed commands |
INFO : |----------------------------------------------------------------------------------------------------------------------------------------------------|
INFO : | cmd: <class 'genie.libs.parser.iosxe.show_acl.ShowAccessLists'> |
INFO : |====================================================================================================================================================|
INFO : csr1000v-1: afterAcl get
INFO : ********************************Config back********************************
INFO : iosxr1: clear_config
INFO : csr1000v-1: clear_config
INFO : ********************************Log out********************************
INFO : iosxr1: disconnected
INFO : csr1000v-1: disconnected
INFO : ********************************Diff********************************
=====iosxr1_ConfigDiff=====
+Wed Dec 18 16:57:14.949 UTC:
-Wed Dec 18 16:56:58.216 UTC:
router static:
address-family ipv4 unicast:
+ 8.8.8.8/32 10.10.20.254:
=====csr1000v-1_ConfigDiff=====
+Current configuration : 7620 bytes:
+ip route 8.8.8.8 255.255.255.255 GigabitEthernet1 10.10.20.254:
-Current configuration : 7557 bytes:
=====iosxr1_RouteDiff=====
info:
vrf:
default:
address_family:
ipv4:
routes:
+ 8.8.8.8/32:
+ active: True
+ metric: 0
+ next_hop:
+ next_hop_list:
+ 1:
+ index: 1
+ next_hop: 10.10.20.254
+ updated: 00:00:08
+ route: 8.8.8.8/32
+ route_preference: 1
+ source_protocol: static
+ source_protocol_codes: S
=====csr1000v-1_RouteDiff=====
info:
vrf:
default:
address_family:
ipv4:
routes:
+ 8.8.8.8/32:
+ active: True
+ metric: 0
+ next_hop:
+ next_hop_list:
+ 1:
+ index: 1
+ next_hop: 10.10.20.254
+ outgoing_interface: GigabitEthernet1
+ route: 8.8.8.8/32
+ route_preference: 1
+ source_protocol: static
+ source_protocol_codes: S
=====iosxr1_AclDiff=====
=====csr1000v-1_AclDiff=====
INFO : ********************************End********************************
(nw_automate) 00:28:00 my Script $
Recommended Posts