Scrapli stands for scrape cli very cleverly joined together in one word. Althought he source documentation of this network devices interaction library is really wonderful and can be found here, this is my journal on my path to learning various libraries for device interactions and understand how they differ from each other and which one suits best for my task at hand. Let’s see how to use Scrapli for Network Automation
from scrapli import Scrapli
device = {
"host": "sandbox-iosxe-latest-1.cisco.com",
"auth_username": "developer",
"auth_password": "C1sco12345",
"auth_strict_key": False,
"platform": "cisco_iosxe"
}
conn = Scrapli(**device)
conn.open()
print(conn.get_prompt())
conn.close()
It’s similar to Netmiko and so we can use Context Manager here as well to let python handle the open and close of connection for you and shorten the code too.
with Scrapli(**device) as device:
print(device.get_prompt())
╰─ python3 02.py ─╯
csr1000v-1#
Scrapli basically needs to know the Driver it needs to use to connect to the device. There are two ways you can control that.
- Either specify the platform like above and Scrapli( ) will automatically return the Driver corresponding to that driver and use it connections.
- Or, directly import the connection driver you want for the device in question. Screenshot below has list of supported Drivers and platform types
The core drivers and associated platforms are outlined below:
Platform/OS | Scrapli Driver | Scrapli Async Driver | Platform Name |
---|---|---|---|
Cisco IOS-XE | IOSXEDriver | AsyncIOSXEDriver | cisco_iosxe |
Cisco NX-OS | NXOSDriver | AsyncNXOSDriver | cisco_nxos |
Cisco IOS-XR | IOSXRDriver | AsyncIOSXRDriver | cisco_iosxr |
Arista EOS | EOSDriver | AsyncEOSDriver | arista_eos |
Juniper JunOS | JunosDriver | AsyncJunosDriver | juniper_junos |
Which brings us to the point, What Async is ?
Asynchronous or async for short, allows a program to juggle multiple operations without waiting or getting hung up on any one of them. It’s a smart way to efficiently handle tasks like network or file I/O, where most of the program’s time is spent waiting for a task to finish.
Assume you need to open hundreds of network connections. You could open one connection, wait for the results, then open the next and wait for the results, and so on. Most of the time the program runs is spent waiting on a network response, not doing actual work.
Async gives you a more efficient method: Open all the connections at once, then switch among each active connection as they return results. If one connection isn’t returning results, switch to the next one, and so on, until all connections have returned their data.
Which again begs the question why not use threading ?
Well, threading is a technique to achieve concurrency for a general purpose application but when you are dealing with codes that need to wait on I/O operations, then asyncIO is the choice for achieve concurrent task execution. There may be a lot more behind the scenes as to why async is better than threading. I will update this column as i understand more about the differences but this should be sufficient to make a start.
Now that we know some basic terms, lets see another method of connecting to the devices using Scrapli.
from scrapli.driver.core import IOSXEDriver
from rich import print
device = {
"host": 'sandbox-iosxe-latest-1.cisco.com',
"auth_username": "developer",
"auth_password": "C1sco12345",
# "auth_secondary" : "C1sco12345", >> when you need to specify the enable password
"auth_strict_key": False,
# "transport": "system" >> when you need to specify the transport method. We will talk about this later.
}
with IOSXEDriver(**device) as conn:
print(conn)
╰─ python3 03.py ─╯
Scrapli Driver sandbox-iosxe-latest-1.cisco.com:22
Let’s send commands to devices and fetch outputs.
SINGLE COMMAND
with IOSXEDriver(**device) as conn:
response = conn.send_command("show ip int brief")
print(response.result)
the response object received as a result of send_command has multiple methods you can call on it. Execute dir(response) to see what all you can execute and get more information. However, the most important out of those
with IOSXEDriver(**device) as conn:
response = conn.send_command("show ip int brief")
print(response.channel_input) ## What was sent to the device as input
print(response.result) ## .result contains the text format of the output from device.
If you would like to parse the response object containing output into structured data, you can leverage either textfsm or genie parsers like with Netmiko and its super easy to leverage them ofcourse as a pre requisite both textfsm and genie should be installed already via pip/pip3
with IOSXEDriver(**device) as conn:
response = conn.send_command("show ip int brief")
print(response.channel_input)
print(response.result)
print(response.textfsm_parse_output()) # if you want to use textfsm
print(response.genie_parse_output()) #if you wannt to use genie parsers
╰─ python3 03.py ─╯
show ip int brief
Interface IP-Address OK? Method Status Protocol
GigabitEthernet1 10.10.20.48 YES NVRAM up up
GigabitEthernet2 192.168.38.67 YES manual administratively down down
GigabitEthernet3 192.168.1.2 YES manual administratively down down
Loopback0 10.1.1.1 YES manual up up
Loopback1001 1.1.1.10 YES manual up up
Loopback1002 2.2.2.2 YES manual up up
Loopback10000 192.0.2.60 YES other administratively down down
[
{'intf': 'GigabitEthernet1', 'ipaddr': '10.10.20.48', 'status': 'up', 'proto': 'up'},
{'intf': 'GigabitEthernet2', 'ipaddr': '192.168.38.67', 'status': 'administratively down', 'proto': 'down'},
{'intf': 'GigabitEthernet3', 'ipaddr': '192.168.1.2', 'status': 'administratively down', 'proto': 'down'},
{'intf': 'Loopback0', 'ipaddr': '10.1.1.1', 'status': 'up', 'proto': 'up'},
{'intf': 'Loopback1001', 'ipaddr': '1.1.1.10', 'status': 'up', 'proto': 'up'},
{'intf': 'Loopback1002', 'ipaddr': '2.2.2.2', 'status': 'up', 'proto': 'up'},
{'intf': 'Loopback10000', 'ipaddr': '192.0.2.60', 'status': 'administratively down', 'proto': 'down'}
]
{
'interface': {
'GigabitEthernet1': {'ip_address': '10.10.20.48', 'interface_is_ok': 'YES', 'method': 'NVRAM', 'status': 'up', 'protocol': 'up'},
'GigabitEthernet2': {'ip_address': '192.168.38.67', 'interface_is_ok': 'YES', 'method': 'manual', 'status': 'administratively down', 'protocol': 'down'},
'GigabitEthernet3': {'ip_address': '192.168.1.2', 'interface_is_ok': 'YES', 'method': 'manual', 'status': 'administratively down', 'protocol': 'down'},
'Loopback0': {'ip_address': '10.1.1.1', 'interface_is_ok': 'YES', 'method': 'manual', 'status': 'up', 'protocol': 'up'},
'Loopback1001': {'ip_address': '1.1.1.10', 'interface_is_ok': 'YES', 'method': 'manual', 'status': 'up', 'protocol': 'up'},
'Loopback1002': {'ip_address': '2.2.2.2', 'interface_is_ok': 'YES', 'method': 'manual', 'status': 'up', 'protocol': 'up'},
'Loopback10000': {'ip_address': '192.0.2.60', 'interface_is_ok': 'YES', 'method': 'other', 'status': 'administratively down', 'protocol': 'down'}
}
}
In case you want to execute multiple commands, you can do that using send_commands( ) instead of send_command( ) method. The response object in this case case will return a list of responses for each command that you can iterate through to get the desired result.
MULTIPLE COMMANDS
with IOSXEDriver(**device) as conn:
responses = conn.send_commands(["show ip int brief", "show version"])
for response in responses:
print(conn.get_prompt() + response.channel_input)
print(response.result)
print(response.textfsm_parse_output())
print(response.genie_parse_output())
You could leverage TTP parser just like textfsm and genie and you can also leverage a custom textfsm parser too. More details about which you can get here.
https://carlmontanari.github.io/scrapli/user_guide/basic_usage/#ttp-integration
This was the simplified view of how to get started with SCRAPLI but there is a lot more to it. Features like
- Configuration push
- Async
- Dealing with a non standard device that core drivers don’t support
- Modifying the transport options
- More scrapli utilities like:-
- Netconf
- Community
- Cfg
- Replay
- Nornir
All these advanced features we will talk about in the next posts in this series. Thanks for reading, if you have any comments, suggestions, questions, please feel free to drop them in the suggestion box on the right navigation bar or comment below.
Let’s first try to see basic difference between multi-threading, multi-processing, asynchronous code execution before we see how to use Async version of Scrapli
2 thoughts on “How to use Scrapli for Network Automation”