Integration¶
The integration of connection module’s Connection Manager and topology Device object is based off a relatively simple & straight-forward concept:
When given a Device object, users should be able to directly interface (eg, connect, send/receive commands) with the actual device, without having to consciously involve anything else.
# Example
# -------
#
# device & connection integration
# when given a device object
device = testbed.devices['some-uut-device']
# users should be able to directly interface with it, eg:
# connect to it
device.connect()
# send commands
output = device.execute('show version')
device.configure('''
interface Ethernet1/1
ip address 192.5.10.1 255.255.255.0
no shutdown
''')
# and more ...
assert device.connected
device.ping('192.5.10.2')
device.reload()
device.disconnect()
Tip
For the sake of verbal simplicity, each connection (eg, telnet to console), shall be referred to as a connection instance here forward.
Single Instance¶
The most simplistic usage scenarios of connections is to just open a single
connection instance to a testbed device. To do so, simply invoke the
Device.connect()
method directly. From there on, all services associated
with that device should just show up directly as methods of that object
instance:
Syntax
------
# [] denotes optional arguments
# *args, **kwargs denotes all other possible arguments
# connect & disconnect
device.connect([via = "path"], [**kwargs])
device.disconnect()
# calling services
device.<services>([*args], [**kwargs])
# Example
# -------
#
# simplistic connection example
# using the topology module
from pyats import topology
# let's write an inline testbed file for simplicity
# (edit this to whatever your testbed looks like)
testbed = topology.loader.load('''
testbed:
name: my-inline-testbed
devices:
tplana-hath:
type: iosxe
os: iosxe
connections:
a:
protocol: telnet
ip: 10.1.1.1
port: 10000
''')
# pick the device to work with
device = testbed.devices['tplana-hath']
# we should be able to directly connect to it
device.connect()
assert device.connected
# run the various services associated with this connection
device.execute('show version')
device.configure('clock set 18:00:00 April 4 2063')
# disconnect from it
device.disconnect()
Tip
keep in mind that connection library is oblivious to what type of connection is being opened up or where it is connecting to. Eg, in single connection instances, the opened session could be either console or mgmt/vty.
Multiple Instance¶
When opening multiple connection instances, each connection must be provided with its own unique alias for identification purposes:
Syntax
------
# [] denotes optional arguments
# *args, **kwargs denotes all other possible arguments
# connect to alias and disconnect from alias
device.connect(alias = "alias", [via = "path"], [**kwargs])
device.<alias>.disconnect()
# calling services of an alias
device.<alias>.<services>([*args], [**kwargs])
# Example
# -------
#
# multiple connection instance example
# following the example above, let's make the testbed
# connection description slightly more complicated
# (edit this to whatever your testbed looks like)
testbed = topology.loader.load('''
testbed:
name: my-inline-testbed
devices:
tplana-hath:
type: iosxe
os: iosxe
connections:
a:
protocol: telnet
ip: 10.1.1.1
port: 10000
mgmt:
protocol: telnet
ip: 10.1.1.1
port: 20000
''')
# pick the device
device = testbed.devices['tplana-hath']
# make multiple connections to mgmt port (which accepts multi sessions)
# each should be provided a unique alias and the exact path eg:
device.connect(alias = 'vty_1', via = 'mgmt')
device.connect(alias = 'vty_2', via = 'mgmt')
device.connect(alias = 'vty_3', via = 'mgmt')
# now we can use each instance independent of the others
assert device.vty_1.connected
assert device.vty_2.connected
assert device.vty_3.connected
# each instance has its own services
# eg, configure different terminal width for each session
device.vty_1.configure('terminal width 100')
device.vty_2.configure('terminal width 200')
device.vty_2.configure('terminal width 300')
# disconnect each independently
device.vty_1.disconnect()
device.vty_2.disconnect()
device.vty_3.disconnect()
# or disconnect everything altogether
device.disconnect_all()
Warning
alias names may not contain characters such as -
, .
, \
etc. It
may only contain valid python attribute identifiers: [a-z], [A-Z], [0-9],
_
.
When device.connect()
is called without the alias
argument (eg,
Single Instance), a default alias is used:
# Example
# -------
#
# default alias is "default"
# in the case of single connections above
device.connect()
# you only get ONE connection, and
# this connection bears the alias "default", eg:
device.execute('show clock')
# is the exact same as:
device.default.execute('show clock')
When creating and handling multiple connections, always keep in mind that whilst you may establish multiple connections to the same device, the underlying router/device resources are still shared, and thus changes (eg, configs) may be applied globally (depending on what it was), and affect all your connection instances.
Tip
multiple connection instances start to make sense when you want to perform
many show
commands at the same time through asychronous means (eg,
multiprocessing, threading, etc).