Mercurial for Tracking Cisco Configs

As I have been working with different routers I have squired a small repository of configuration files that I use for examples, backups, and ways of remembering the way the network was set up before a change. At the start I maintained each config as a separate file, usually containing the date (i.e. router1-071012.cfg). While that worked for a while it got cumbersome when I wanted to track more than one legacy version of a config file. After a while I found out how to use CVS to track a file and its history, but setting things up was a bit cumbersome especially when I wanted to move or organize files. Next I discovered SVN which let me rename files and organize them better among other things. However I would occasionally run into odd issue and commits would sometimes break in weird ways, however It worked much better than CVS. Not being totally content with SVN, I kept an eye on some of the other solutions out there. When I decided to pursue using another versioning system I did some research to figure out which drcs(distributed revision control system), I decided on Mercurial. I chose Mercurial over Git for various reasons, including that it was used natively for python and that bitbucket allowed users to have small private repositories with their free account. I have found this to be a very useful way to track router configurations. Note that all the examples I use are on an Ubuntu Linux based system using the CLI, there are other interfaces available but I will not detail them here.

I created an initial repository on a flash drive.
cd /media/flash/
hg init configs

Note that Mercurial tracks files and does not actually track folders so empty folders do not get tracked by the repository. In other words, if you need a folder to exist in the repository make sure it contains a file that is being tracked. In my repository I have folders named for the customer location, you may decided on a different convention. Since you can move files to different names/locations you can change your mind later, if you decide to use a different format. I used tftp/ftp/scp to copy the running configuration of a router to my box. I name the file after the device fqdn for simplicity. For example lets say I add the config for gw.customer1.net I would do the following in the /media/flash/configs folder

mkdir customer1
cat ~/gw.customer1.net > gw.customer1.net

now if I do an hg stat I see my file listed with a question mark in front of it.

braaen@brian:/media/keys/configs/customer1$ hg stat
? customer1/gw.customer1.net

This means that there is an unknown/untracked file in the repository, note that the path is part of the file identity relative to the root of the repository even though I am in the customer1 folder. To add the file to the repository I do the following hg add gw.customer1.net. Now if I do an hg stat I see an “A” in front of the file which means It will be added to the next commit.


braaen@brian:/media/keys/configs/customer1$ hg stat
A customer1/gw.customer1.net

To actually add the file to the reposity and “commit” the change I would use a hg commit. Lets add this file with hg commit -m "Added Initial verison of Customer1 gateway". Note that comments are required to make the commit (it really helps to use something descriptive for later reference). Now what if I want to make some changes to the router config and add a switch config.


braaen@brian:/media/keys/configs/customer1$ cat ~/gw.customer1.net > gw.customer1.net
braaen@brian:/media/keys/configs/customer1$ cat ~/sw.customer1.net > sw.customer1.net
braaen@brian:/media/keys/configs/customer1$ hg add sw.customer1.net
braaen@brian:/media/keys/configs/customer1$ hg stat
M customer1/gw.customer1.net
A customer1/sw.customer1.net

Now we see and “M” for modified on the stat for gw. What if we want to see the changes we can do a hg di gw.customer1 and get a diff of that changes.

braaen@brian:/media/keys/configs/customer1$ hg diff gw.customer1.net
diff -r e5168c46c61c customer1/gw.customer1.net
--- a/customer1/gw.customer1.net Tue Jul 10 10:46:38 2012 -0400
+++ b/customer1/gw.customer1.net Tue Jul 10 13:07:58 2012 -0400
@@ -8,7 +8,7 @@
no service pad
service timestamps debug datetime msec
service timestamps log datetime msec
-no service password-encryption
+service password-encryption
!
hostname gw.customer1.net
!

Again we commit the changes with a commit.

hg commit -m "Added Switch and modified Router"

Now what if we change both the router config and the switch config?

braaen@brian:/media/keys/configs/customer1$ cat ~/gw.customer1.net > gw.customer1.net
braaen@brian:/media/keys/configs/customer1$ cat ~/sw.customer1.net > sw.customer1.net
braaen@brian:/media/keys/configs/customer1$ hg stat
M customer1/gw.customer1.net
M customer1/sw.customer1.net

if we just for an hg di without specifying a file we see the diffs for both files.
braaen@brian:/media/keys/configs/customer1$ hg di
diff -r 1bc48f053ee9 customer1/gw.customer1.net
--- a/customer1/gw.customer1.net Tue Jul 10 13:08:47 2012 -0400
+++ b/customer1/gw.customer1.net Tue Jul 10 13:10:57 2012 -0400
@@ -8,7 +8,7 @@
no service pad
service timestamps debug datetime msec
service timestamps log datetime msec
-service password-encryption
+no service password-encryption
!
hostname gw.customer1.net
!
diff -r 1bc48f053ee9 customer1/sw.customer1.net
--- a/customer1/sw.customer1.net Tue Jul 10 13:08:47 2012 -0400
+++ b/customer1/sw.customer1.net Tue Jul 10 13:10:57 2012 -0400
@@ -7,7 +7,7 @@
no service pad
service timestamps debug datetime localtime
service timestamps log datetime localtime
-no service password-encryption
+service password-encryption
!
hostname sw.customer1.net
!

There are many other things that mercurial can be used for besides router configs, but this intoduction was just intended to demonstraigt a few advantages of using Mercurial to track configuration changes. For a more through introduction to Mercurial you can visit hginit.com or the Mercurial homepage. You can find Mercurial hosting plans at Bitbucket.