September 24, 2013 - 10:49 am. Posted by Viktor Petersson
When you’re working with a cloud infrastructure, it’s pretty common that you need to perform the same task on all your servers. Perhaps you need deploy a hotfix, or simply just check what kernel version your servers are running.
The traditional sysadmin way of doing this was to simply write a for-loop in shell-script which fires off the execution of the desired command via SSH on each server. There’s nothing wrong with this approach, but when you are dealing with a large pool of dynamic IPs, it becomes somewhat challenging (not to mention that it is slow and hard to manage on a larger sets of nodes).
A popular tool in the DevOps toolbox is fabric. It is much like the traditional approach, but written in Python and far more dynamic. In this article, we will explore to use fabric in conjunction with our own Python-module to automate tasks.
We’re going to assume that you have already configured pycloudsigma, so let’s dive in. The task we will run is a simple
echo on each server that is online. We’re also going to assume that you have SSH enabled and that you have the same username on all servers.
First, we need to create the file
fabfile.py with the following content:
import cloudsigma from fabric.api import run, env server = cloudsigma.resource.Server() # Set variables for Fabric env.disable_known_hosts = True env.user = 'cloudsigma' env.colorize_errors = True env.hosts =  def build_host_list(): """ Add all running servers' public IP to the hosts pool """ for s in server.list(): # Try to get IP of all running servers. # Will throw an exception on non-running servers. try: env.hosts.append(s['runtime']['nics']['ip_v4']['uuid']) except: pass return None def say_hello(): run("echo <code>hostname</code> at your service!") build_host_list()
With the file created, let’s run fabric (from the folder you created the above file):
$ fab say_hello [u'aaa.aaa.aaa.aaa', u'bbb.bbb.bbb.bbb', u'ccc.ccc.ccc.ccc', u'ddd.ddd.ddd.ddd'] [aaa.aaa.aaa.aaa] Executing task 'say_hello' [aaa.aaa.aaa.aaa] run: echo <code>hostname</code> at your service! [aaa.aaa.aaa.aaa] out: test3.local at your service! [aaa.aaa.aaa.aaa] out: [bbb.bbb.bbb.bbb] Executing task 'say_hello' [bbb.bbb.bbb.bbb] run: echo <code>hostname</code> at your service! [bbb.bbb.bbb.bbb] out: test2.local at your service! [bbb.bbb.bbb.bbb] out: [ccc.ccc.ccc.ccc] Executing task 'say_hello' [ccc.ccc.ccc.ccc] run: echo <code>hostname</code> at your service! [ccc.ccc.ccc.ccc] out: test0.local at your service! [ccc.ccc.ccc.ccc] out: [ddd.ddd.ddd.ddd] Executing task 'say_hello' [ddd.ddd.ddd.ddd] run: echo <code>hostname</code> at your service! [ddd.ddd.ddd.ddd] out: test1.local at your service! [ddd.ddd.ddd.ddd] out: Done. Disconnecting from aaa.aaa.aaa.aaa... done. Disconnecting from ccc.ccc.ccc.ccc... done. Disconnecting from bbb.bbb.bbb.bbb... done. Disconnecting from ddd.ddd.ddd.ddd... done.
Success! As you can see, we ran the command on all servers and got a very readable result back.
This a super simple example to illustrate the concept. We’re really just scraping the surface of fabric’s functionaries.
One concrete example that this could be used for is if you have tagged all your web servers, you could leverage that tag and run a deploy on just those servers.
If you have any questions, feel free to post a comment below.