.. Trigger documentation master file, created by sphinx-quickstart on Wed Jul 6 15:17:22 2011. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. To illustrate how Trigger works, here are some basic examples of leveraging the API. For these examples to work you must have already :ref:`installed ` and :ref:`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 (, '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 [] And convert it to Juniper format:: >>> aclobj.name_terms() # Juniper policy terms must have names >>> aclobj.terms [] >>> 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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `~trigger.cmds.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' } }