trigger.cmds
— Command execution library¶
This module abstracts the asynchronous execution of commands on multiple network devices. It allows for integrated parsing and event-handling of return data for rapid integration to existing or newly-created tools.
The Commando
class is designed to be extended but can still be
used as-is to execute commands and return the results as-is.
-
class
trigger.cmds.
Commando
(devices=None, commands=None, creds=None, incremental=None, max_conns=10, verbose=False, timeout=30, production_only=True, allow_fallback=True, with_errors=True, force_cli=False, with_acls=False, command_interval=0, stop_reactor=True)¶ Execute commands asynchronously on multiple network devices.
This class is designed to be extended but can still be used as-is to execute commands and return the results as-is.
At the bare minimum you must specify a list of
devices
to interact with. You may optionally specify a list ofcommands
to execute on those devices, but doing so will execute the same commands on every device regardless of platform.If
commands
are not specified, they will be expected to be emitted by thegenerate
method for a given platform. Otherwise no commands will be executed.If you wish to customize the commands executed by device, you must define a
to_{vendor_name}
method containing your custom logic.If you wish to customize what is done with command results returned from a device, you must define a
from_{vendor_name}
method containing your custom logic.Parameters: - devices – A list of device hostnames or
NetDevice
objects - commands – (Optional) A list of commands to execute on the
devices
. - creds – (Optional) A 3-tuple of (username, password, realm). If only (username,
password) are provided, realm will be populated from
DEFAULT_REALM
. If unset it will fetch from.tacacsrc
. - incremental – (Optional) A callback that will be called with an empty sequence upon connection and then called every time a result comes back from the device, with the list of all results.
- max_conns – (Optional) The maximum number of simultaneous connections to keep open.
- verbose – (Optional) Whether or not to display informational messages to the console.
- timeout – (Optional) Time in seconds to wait for each command executed to return a
result. Set to
None
to disable timeout (not recommended). - production_only – (Optional) If set, includes all devices instead of excluding any devices
where
adminStatus
is not set toPRODUCTION
. - allow_fallback – If set (default), allow fallback to base parse/generate methods when they are not customized in a subclass, otherwise an exception is raised when a method is called that has not been explicitly defined.
- with_errors – (Optional) Return exceptions as results instead of raising them. The default is to always return them.
- force_cli – (Optional) Juniper only. If set, sends commands using CLI instead of Junoscript.
- with_acls – Whether to load ACL associations (requires Redis). Defaults to whatever is specified in settings.WITH_ACLS
- command_interval – (Optional) Amount of time in seconds to wait between sending commands.
- stop_reactor – Whether to stop the reactor loop when all results have returned.
(Default:
True
)
-
append_parsed_results
(device, results)¶ A simple method for appending results called by template parser method.
If you want to customize the default method for storing parsed results, overload this in your subclass.
Parameters: - device – A
NetDevice
object - results – The results to store. Anything you want really.
- device – A
-
errback
(failure, device)¶ The default errback. Overload for custom behavior but make sure it always decrements the connections.
Parameters: - failure – Usually a Twisted
Failure
instance. - device – A
NetDevice
object
- failure – Usually a Twisted
-
generate
(device, commands=None, extra=None)¶ Generate commands to be run on a device. If you don’t provide
commands
to the class constructor, this will return an empty list.Define a ‘to_{vendor_name}’ method to customize the behavior for each platform.
Parameters:
-
map_parsed_results
(command=None, fsm=None)¶ Return a dict of
{command: fsm, ...}
-
map_results
(commands=None, results=None)¶ Return a dict of
{command: result, ...}
-
parse
(results, device, commands=None)¶ Parse output from a device. Calls to
self._lookup_method
to find specificfrom
method.Define a ‘from_{vendor_name}’ method to customize the behavior for each platform.
Parameters:
-
parse_template
(results, device, commands=None)¶ Generator function that processes unstructured CLI data and yields either a TextFSM based object or generic raw output.
Parameters: - results (str) – The unstructured “raw” CLI data from device.
- device (
NetDevice
) – NetDevice object
-
reactor_running
¶ Return whether reactor event loop is running or not
-
run
()¶ Nothing happens until you execute this to perform the actual work.
-
select_next_device
(jobs=None)¶ Select another device for the active queue.
Currently only returns the next device in the job queue. This is abstracted out so that this behavior may be customized, such as for future support for incremental callbacks.
If a device is determined to be invalid, you must return
None
.Parameters: jobs – (Optional) The jobs queue. If not set, uses self.jobs
.Returns: A NetDevice
object orNone
.
-
store_error
(device, error)¶ A simple method for storing an error called by all default parse/generate methods.
If you want to customize the default method for storing results, overload this in your subclass.
Parameters: - device – A
NetDevice
object - error – The error to store. Anything you want really, but usually a Twisted
Failure
instance.
- device – A
-
store_results
(device, results)¶ A simple method for storing results called by all default parse/generate methods.
If you want to customize the default method for storing results, overload this in your subclass.
Parameters: - device – A
NetDevice
object - results – The results to store. Anything you want really.
- device – A
-
to_juniper
(device, commands=None, extra=None)¶ This just creates a series of
<command>foo</command>
elements to pass along to execute_junoscript()
- devices – A list of device hostnames or
-
class
trigger.cmds.
ReactorlessCommando
(devices=None, commands=None, creds=None, incremental=None, max_conns=10, verbose=False, timeout=30, production_only=True, allow_fallback=True, with_errors=True, force_cli=False, with_acls=False, command_interval=0, stop_reactor=True)¶ A reactor-less Commando subclass.
This allows multiple instances to coexist, with the side-effect that you have to manage the reactor start/stop manually.
An example of how this could be used:
from twisted.internet import defer, reactor devices = ['dev1', 'dev2'] # Our Commando instances. This is an example to show we have two instances # co-existing under the same reactor. c1 = ShowClock(devices) c2 = ShowUsers(devices) instances = [c1, c2] # Call the run method for each instance to get a list of Deferred task objects. deferreds = [] for i in instances: deferreds.append(i.run()) # Here we use a DeferredList to track a list of Deferred tasks that only # returns once they've all completed. d = defer.DeferredList(deferreds) # Once every task has returned a result, stop the reactor d.addBoth(lambda _: reactor.stop()) # And... finally, start the reactor to kick things off. reactor.run() # Inspect your results print d.result
-
monitor_result
(result, reactor)¶ Loop periodically or until the factory stops to check if we’re
all_done
and then return the results.
-
run
()¶ We’ve overloaded the run method to return a Deferred task object.
-
-
class
trigger.cmds.
NetACLInfo
(**args)¶ Class to fetch and parse interface information. Exposes a config attribute which is a dictionary of devices passed to the constructor and their interface information.
Each device is a dictionary of interfaces. Each interface field will default to an empty list if not populated after parsing. Below is a skeleton of the basic config, with expected fields:
config { 'device1': { 'interface1': { 'acl_in': [], 'acl_out': [], 'addr': [], 'description': [], 'subnets': [], } } }
Interface field descriptions:
addr: List of IPy.IP
objects of interface addressesacl_in: List of inbound ACL names acl_out: List of outbound ACL names description: List of interface description(s) subnets: List of IPy.IP
objects of interface networks/CIDRsExample:
>>> n = NetACLInfo(devices=['jm10-cc101-lab.lab.aol.net']) >>> n.run() Fetching jm10-cc101-lab.lab.aol.net >>> n.config.keys() [<NetDevice: jm10-cc101-lab.lab.aol.net>] >>> dev = n.config.keys()[0] >>> n.config[dev].keys() ['lo0.0', 'ge-0/0/0.0', 'ge-0/2/0.0', 'ge-0/1/0.0', 'fxp0.0'] >>> n.config[dev]['lo0.0'].keys() ['acl_in', 'subnets', 'addr', 'acl_out', 'description'] >>> lo0 = n.config[dev]['lo0.0'] >>> lo0['acl_in']; lo0['addr'] ['abc123'] [IP('66.185.128.160')]
This accepts all arguments from the
Commando
parent class, as well as this one extra:Parameters: skip_disabled – Whether to include interface names without any information. (Default: True
)-
IPhost
(addr)¶ Given ‘172.20.1.4/24’, return IP(‘172.20.1.4/32’).
-
IPsubnet
(addr)¶ Given ‘172.20.1.4/24’, return IP(‘172.20.1.0/24’).
-
from_arista
(data, device, commands=None)¶ Parse IOS config based on EBNF grammar
-
from_brocade
(data, device, commands=None)¶ Parse IOS config based on EBNF grammar
-
from_cisco
(data, device, commands=None)¶ Parse IOS config based on EBNF grammar
-
from_force10
(data, device, commands=None)¶ Parse IOS config based on EBNF grammar
-
from_foundry
(data, device, commands=None)¶ Parse IOS config based on EBNF grammar
-
from_juniper
(data, device, commands=None)¶ Do all the magic to parse Junos interfaces
-
to_arista
(dev, commands=None, extra=None)¶ Similar to IOS, but:
- Arista has no “show conf” so we have to do “show run”
- The regex used in the CLI for Arista is more “precise” so we have to change the pattern a little bit compared to the on in generate_ios_cmd
-
to_brocade
(dev, commands=None, extra=None)¶ This is the “show me all interface information” command we pass to IOS devices
-
to_cisco
(dev, commands=None, extra=None)¶ This is the “show me all interface information” command we pass to IOS devices
-
to_force10
(dev, commands=None, extra=None)¶ - Similar to IOS, but:
- You only get the “grep” (“include” equivalent) when using “show run”.
- The regex must be quoted.
-
to_foundry
(dev, commands=None, extra=None)¶ This is the “show me all interface information” command we pass to IOS devices
-
to_juniper
(dev, commands=None, extra=None)¶ Generates an etree.Element object suitable for use with JunoScript
-