Multi Change and Netlib Updates

I’ve implemented some new changes to pyMultiChange and netlib. The biggest change affects both netlib and pyMultiChange. In netlib, I ripped out both the ‘simple_creds’ and ‘simple_yaml’ methods, as both stored user credentials in plain text on the computer that you used them on.

Instead, utilizing the ‘keyring’ python module, I created a new class called ‘KeyRing’. Using ‘KeyRing’ is simple. It implements three methods. These methods are ‘get_creds’, ‘set_creds’, and ‘del_creds’.

‘get_creds’ will attempt to retrieve the credentials for a username, if the credentials exist. If they do not exist, ‘get_creds’ will automatically call the ‘set_creds’ method.

‘set_creds’ does exactly what it sounds like. It allows you to set your credentials. If no user credentials exist, it creates a new keyring. However, if user credentials do exist, it over-writes the credentials.

Finally, ‘del_creds’ deletes a user’s credentials from an existing keyring.

The ‘keyring‘ python library utilizes your operating systems native methods for storing passwords. For Example, in Mac OS X, it will utilize the KeyChain functionality, In Linux, it will use dbus, and in Microsoft Windows, it utilizes the Credential Vault. There are also methods available for you to create your own backend. Much more secure than the ~/.tacacslogin or ~/.tacacs.yml files that used to be created from the old methods.

As expected, this change was implemented into pyMultiChange. Doing so, required that new command line arguments needed to be implemented. There are actually several new command line arguments, since the last time that I wrote about pyMultiChange. I’ll go over them here.

The first, is that now requires that you specify a username for all actions. This allows to interact with the keyring to set, extract, and delete credentials.

When you specify a username, immediately attempts to extract the credentials for the user. If they don’t exist, will prompt you to set the credentials.

You can also utilize the ‘–set-creds’ command line argument to either set credentials for a new user or over-write the credentials for an existing user.

Like wise, you can use the ‘–delete-creds’ to delete existing creds.

Beyond that, the option to utilize threading was created. With the threading ability, you also get the ability to specify the number of threads and the delay factor between command execution.

For example, the below series of command line arguments enable threading, utilizing 50 threads, create a delay factor of 5 seconds, and will display the command output.

This is very handy for running a common command set across a large number of devices very quickly.

Beyond that, there are a few under the hood enhancements.

  1. Protocol failover will no longer happen. Meaning that if a device fails to login via SSH, it will no longer failover to attempt to login via telnet and vise versa.
  2. Login failures are logged in a file called ‘failure.log’. This file is created in the local folder that you’re running ‘’ in.
  3. will now only read the commands file once, rather than reading it for every device that it attempts to make changes on.
  4. pyMultiChange and netlib are now python installable packages. Meaning that you can run their ‘’ files and they will be installed as native python packages, allowing them to be called from anywhere on the OS.

Both packages are available on

Share on FacebookTweet about this on TwitterShare on LinkedInShare on RedditEmail this to someone

June 22, 2016

Posted In: Cisco Administration Python Scripting, DevOps, Network DevOps, Network Programmability, Python Tips

Kicking the tires on the new Ansible Network Modules, Part 2

In the previous blog, I kicked the tires on the ios_command and ios_config Ansible modules. I still had my development environment set up from then, so I decided that I wanted to kick the tires on the ios_template module.

The online documentation currently has several errors, with the module documentation in the same state, which is undesirable. However, after some experimentation, I feel that I can adequately describe what the module does.

You feed the module a candidate configuration for a device, the module will then reach out to the device, pull its current running configuration, compare the running configuration to the candidate configuration, determine what configuration needs to be added to the device based upon the comparison, then add the configuration to the device.

I’ve noted two caveats with this module. First, it will not negate any commands, so if you update your configuration template to remove a swath of configuration, the module will not make those changes. Second, the module isn’t intelligent enough to determine the risk associated with a command, thus it’s unable to take preemptive actions, such as bleeding traffic from a link or device.

With that in mind, let’s get to the playbook.

Here is what my playbook looks like:

In this playbook, the src file – “{{ inventory_hostname }}.candidate_config.txt“, which are referenced, contain the running configuration of each of my devices in inventory, with the exception that I’ve added an access-list called TEST. Given what we know of the module, it will compare the running config to the candidate config, determine that the access-list called TEST is missing from the running config, and attempt to add the access-list to the device.

You can see below that there is an access-list at the tail end of both of the configurations.

Now, if we run the playbook, you can see the results.

That is definitely cool! Though, it’s also definitely lacking from a configuration intent perspective. I’m sure that it will improve with time.

Some colleagues and I have been attempting to solve this configuration intent problem. It’s a difficult problem to solve for, but we have a working code base. Soon, I’ll try to write about configuration intent and how we are approaching the problem.

Share on FacebookTweet about this on TwitterShare on LinkedInShare on RedditEmail this to someone

March 2, 2016

Posted In: Ansible, DevOps, Network DevOps, Network Programmability, Python Tips