Trigger¶
“Keep your eyes on the prize, and your finger on the trigger.”
What is Trigger?¶
Trigger is a robust network automation toolkit written in Python that was designed for interfacing with network devices and managing network configuration and security policy. It increases the speed and efficiency of managing large-scale networks while reducing the risk of human error.
Key Features¶
Trigger is designed to work at scale and can support hundreds or thousands of network devices with ease. Here are some of things that make Trigger tick:
- Support for SSH, Telnet, and Juniper’s Junoscript XML API
- Easily get an interactive shell or execute commands asynchronously.
- Leverage advanced event-driven functionality to manage any number of jobs in parallel and handle output or errors as they return.
- Powerful metadata interface for performing complex queries to group and associate network devices by name, manufacturer, type, location, and more.
- Encrypted storage of login credentials so you can interact without constantly being prompted to enter your password.
- Flexible access-list & firewall policy parser that can test access if access is permitted, or easily convert ACLs from one format to another.
- Detailed support for timezones and maintenance windows.
- A suite of tools for simplifying many common tasks.
New in version 1.2.
- Import your metadata from an existing RANCID installation to get up-and-running quickly!
New in version 1.3.
- Import your metadata from a CSV file and get up-and-running even quicker!
Examples¶
To illustrate how Trigger works, here are some basic examples of leveraging the API.
For these examples to work you must have already installed and configured Trigger, so if you haven’t already please do that first!
Simple Examples¶
Working with metadata¶
Get a count of all your devices:
>>> from trigger.netdevices import NetDevices
>>> nd = NetDevices()
>>> len(nd)
5539
(Whoa! That’s a lot!) Let’s look up a device.
>>> dev = nd.find('edge1-abc')
>>> dev.vendor, dev.deviceType
(<Vendor: Juniper>, 'ROUTER')
>>> dev.has_ssh()
True
Get an interactive shell¶
Since this device has SSH, let’s connect to it:
>>> dev = nd.find('edge1-abc')
>>> dev.connect()
Connecting to edge1-abc.net.aol.com. Use ^X to exit.
Fetching credentials from /home/jathan/.tacacsrc
--- JUNOS 10.2S6.3 built 2011-01-22 20:06:27 UTC
jathan@edge1-abc>
Work with access-lists¶
Let’s start with a simple Cisco ACL:
>>> from trigger.acl import parse
>>> aclobj = parse("""access-list 123 permit tcp any host 10.20.30.40 eq 80""")
>>> aclobj.terms
[<Term: None>]
And convert it to Juniper format:
>>> aclobj.name_terms() # Juniper policy terms must have names
>>> aclobj.terms
[<Term: T1>]
>>> print '\n'.join(aclobj.output(format='junos'))
filter 123 {
term T1 {
from {
destination-address {
10.20.30.40/32;
}
protocol tcp;
destination-port 80;
}
then {
accept;
}
}
}
Cache your login credentials¶
Trigger will encrypt and store your credentials in a file called .tacacsrc
in your home directory. We already had them cached in the previous examples, so
I removed it and then:
>>> from trigger.tacacsrc import Tacacsrc
>>> tcrc = Tacacsrc()
/home/jathan/.tacacsrc not found, generating a new one!
Updating credentials for device/realm 'tacacsrc'
Username: jathan
Password:
Password (again):
>>> tcrc.creds['aol']
Credentials(username='jathan', password='boguspassword', realm='tacacsrc')
Passwords can be cached by realm. By default this realm is 'aol'
, but you
can change that in the settings. Your credentials are encrypted and decrypted
using a shared key. A more secure experimental GPG-encrypted method is in the
works.
Login to a device using the gong
script¶
Trigger includes a simple tool for end-users to connect to devices called
gong
. (It should be just go
but we’re in the future, so...):
$ gong foo1-cisco
Connecting to foo1-cisco.net.aol.com. Use ^X to exit.
Fetching credentials from /home/jathan/.tacacsrc
foo1-cisco#
foo1-cisco#show clock
20:52:05.777 UTC Sat Jun 23 2012
foo1-cisco#
Partial hostnames are supported, too:
$ gong foo1
2 possible matches found for 'foo1':
[ 1] foo1-abc.net.aol.com
[ 2] foo1-xyz.net.aol.com
[ 0] Exit
Enter a device number: 2
Connecting to foo1-xyz.net.aol.com. Use ^X to exit.
Fetching credentials from /home/jathan/.tacacsrc
foo1-xyz#
Slightly Advanced Examples¶
Execute commands asynchronously using Twisted¶
This is a little more advanced... so we saved it for last.
Trigger uses Twisted, which is a callback-based event loop. Wherever possible Twisted’s implementation details are abstracted away, but the power is there for those who choose to wield it. Here’s a super simplified example of how this might be accomplished:
from trigger.netdevices import NetDevices
from twisted.internet import reactor
nd = NetDevices()
dev = nd.find('foo1-abc')
def print_result(data):
"""Display results from a command"""
print 'Result:', data
def stop_reactor(data):
"""Stop the event loop"""
print 'Stopping reactor'
if reactor.running:
reactor.stop()
# Create an event chain that will execute a given list of commands on this
# device
async = dev.execute(['show clock'])
# When we get results from the commands executed, call this
async.addCallback(print_result)
# Once we're out of commands, or we an encounter an error, call this
async.addBoth(stop_reactor)
# Start the event loop
reactor.run()
Which outputs:
Result: ['21:27:46.435 UTC Sat Jun 23 2012\n']
Stopping reactor
Observe, however, that this only communicated with a single device.
Execute commands asynchronously using the Commando API¶
Commando
tries to hide Twisted’s implementation details so you
don’t have to deal with callbacks, while also implementing a worker pool so
that you may easily communicate with multiple devices in parallel.
This is a base class that is intended to be extended to perform the operations
you desire. Here is a basic example of how we might perform the same example
above using Commando
instead, but also communicating with a second device
in parallel:
from trigger.cmds import Commando
class ShowClock(Commando):
"""Execute 'show clock' on a list of Cisco devices."""
vendors = ['cisco']
commands = ['show clock']
if __name__ == '__main__':
device_list = ['foo1-abc.net.aol.com', 'foo2-xyz.net.aol.com']
showclock = ShowClock(devices=device_list)
showclock.run() # Commando exposes this to start the event loop
print '\nResults:'
print showclock.results
Which outputs:
Sending ['show clock'] to foo2-xyz.net.aol.com
Sending ['show clock'] to foo1-abc.net.aol.com
Received ['21:56:44.701 UTC Sat Jun 23 2012\n'] from foo2-xyz.net.aol.com
Received ['21:56:44.704 UTC Sat Jun 23 2012\n'] from foo1-abc.net.aol.com
Results:
{
'foo1-abc.net.aol.com': {
'show clock': '21:56:44.704 UTC Sat Jun 23 2012\n'
},
'foo2-xyz.net.aol.com': {
'show clock': '21:56:44.701 UTC Sat Jun 23 2012\n'
}
}
Supported Platforms¶
Trigger currently officially supports devices manufactured by the following vendors:
- A10 Networks
- All AX-series application delivery controllers and server load-balancers
- Arista Networks
- All 7000-family switch platforms
- Aruba Networks
- All Mobility Controller platforms
- Brocade Networks
- ADX application delivery switches
- MLX routers
- VDX switches
- Citrix Systems
- NetScaler application delivery controllers and server load-balancers
- Cisco Systems
- All router and switch platforms running IOS
- All switch platforms running NX-OS
- Dell
- PowerConnect switches
- F5 Networks
- All BIG-IP application delivery controllers and server load-balancers
- Force10
- All router and switch platforms running FTOS
- Foundry/Brocade
- All router and switch platforms (NetIron, ServerIron, et al.)
- Juniper Networks
- All router and switch platforms running Junos
- NetScreen firewalls running ScreenOS (Junos not yet supported)
- MRV Communications
- All LX-series console servers
It’s worth noting that other vendors may actually work with the current
libraries, but they have not been tested. The mapping of supported platforms is
specified in settings.py
as SUPPORTED_PLATFORMS
. Modify it at
your own risk!
Getting Started¶
Before you begin¶
You might be required to tinker with some Python code. Don’t worry, we’ll be gentle!
Important
Throughout this documentation you will see commands or code preceded by
a triple greater-than prompt (>>>
). This indicates that they are being
entered into a Python interpreter in interactive mode.
To start Python in interactive mode, it’s as simple as executing
python
from a command prompt:
% python
Python 2.7.2 (default, Jun 20 2012, 16:23:33)
Type "help", "copyright", "credits" or "license" for more information.
>>>
For more information, please see the official Python documentation on interactive mode.
Installation¶
Stable releases of Trigger are best installed using pip
or
easy_install
; or you may download compressed source archives from any of
the official locations. Detailed instructions and links may be found on the
Installation page.
Please keep in mind that before you can truly use Trigger, you must configure it. This is not overly difficult, but it is an important step.
Configuration¶
To configure Trigger please see Configuration and defaults. Initial configuration is relatively easy. If you have any doubts, just start by using the defaults that are provided in the instructions so you can start tinkering.
To take full advantage of all of the features, there are some hurdles you have to jump through, but we are working on greatly simplifying this! This is a work in progress, but it’s not a bad start. Please have a look and give us feedback on how we can improve!
Documentation¶
Please note that all documentation is written with users of Python 2.6 or higher in mind. It’s safe to assume that Trigger will not work properly on Python versions earlier than Python 2.6.
For now, most of our documentation is automatically generated form the source code documentation, which is usually very detailed. As we move along, this will change, especially with regards to some of the more creative ways in which we use Trigger’s major functionality.
Usage Documentation¶
Once you’ve properly installed Trigger, you might want to know how to use it. Please have a look at the usage documentation!
API Documentation¶
Trigger’s core API is made up of several components. For a more detailed explanation of these components, please see the Overview.
trigger.acl
— ACL parsing librarytrigger.changemgmt
— Change management librarytrigger.cmds
— Command execution librarytrigger.conf
— Configuration & Settings moduletrigger.contrib
— Extra, optional tools that solve common problems, extend, or modify core functionality.trigger.exceptions
— Trigger’s Exceptionstrigger.gorc
— Determine commands to run upon logintrigger.netdevices
— Network device metadata librarytrigger.netscreen
— Juniper NetScreen firewall parsertrigger.rancid
— RANCID Compatibility Librarytrigger.tacacsrc
— Network credentials librarytrigger.twister
— Asynchronous device interaction librarytrigger.utils
— CLI tools and utilities library
Road Map¶
We are using milestones to track Trigger’s development path 30 to 90 days out. This is where we map outstanding issues to upcoming releases and is the best way to see what’s coming!
Development¶
Any hackers interested in improving Trigger (or even users interested in how Trigger is put together or released) please see the Trigger Development page. It contains comprehensive info on contributing, repository layout, our release strategy, and more.
Getting Help¶
If you’ve scoured the Usage and API documentation and still can’t find an answer to your question, below are various support resources that should help. Please do at least skim the documentation before posting tickets or mailing list questions, however!
Mailing list¶
The best way to get help with using Trigger is via the trigger-users mailing list (Google Group). We’ll do our best to reply promptly!
Twitter¶
Trigger has an official Twitter account, @pytrigger, which is used for announcements and occasional related news tidbits (e.g. “Hey, check out this neat article on Trigger!”).
Email¶
If you don’t do Twitter or mailing lists, please feel free to drop us an email at pytrigger@aol.com.
Bugs/ticket tracker¶
To file new bugs or search existing ones, please use the GitHub issue tracker, located at https://github.com/trigger/trigger/issues.
IRC¶
Find us on IRC at #trigger
on Freenode (irc://irc.freenode.net/trigger).
Trigger is a Pacific coast operation, so your best chance of getting a real-time response is during the weekdays, Pacific time.
Wiki¶
We will use GitHub’s built-in wiki located at https://github.com/trigger/trigger/wiki.
OpenHatch¶
Find Trigger on Openhatch at http://openhatch.org/+projects/Trigger!
License¶
Trigger is licensed under the BSD 3-Clause License. For the explicit details, please see the License page.
About¶
Trigger was created by AOL’s Network Engineering team. With the high number of network devices on the AOL network this application is invaluable to performance and reliability. Hopefully you’ll find it useful for it on your network and consider participating!
To learn about Trigger’s background and history as well as an overview of the various components, please see the Overview.