I had this use case where I needed to retrieve the output of a command on multiple servers as part of a python library.

At first, I did it with paramiko and it worked well but as the amount of servers grew, it took too much time to run.
I knew about fabric and read the docs in hope of finding a solution - which I did: the @parallel decorator.

I didn’t want to deal with a fabfile and the fab binary, I wanted to include this in my library - fabric can be used as a library but it’s not extremely well documented.

Here’s how I ended up doing it:

from fabric.api import *

class ParallelCommands():
    def __init__(self, **args):
        self.hosts = args['hosts']
        self.command = args['command']

    @parallel(pool_size=10) # Run on as many as 10 hosts at once
    def parallel_exec(self):
        return run(self.command)

    def capture(self):
        with settings(hide('running', 'commands', 'stdout', 'stderr')):
            stdout = execute(self.parallel_exec, hosts=self.hosts)
        return stdout

hosts = ['root@server1', 'root@server2']
command = 'uname -a'

instance = ParallelCommands(hosts=hosts, command=command)
output = instance.capture()

"""
The output of each server is inside a dictionary:
{ 'root@server1': 'output', 'root@server2': 'output' }
"""

print output['root@server1']  

Comments

comments powered by Disqus