pythonfabric

Skip bad hosts and return good results on Fabric call


I would like to send a remote command to multiple hosts using the Python Fabric library. The following code works as long as all hosts are available

#!/usr/bin/python3
import fabric

group = fabric.ThreadingGroup('boss1', 'boss2')
results = group.run('uname -a', hide=True, timeout=5)

for _connection, _result in results.items():
    print(f'{_connection.host}: {_result.stdout.strip()}')

If one of the hosts is unavailable I get a timeout error such as the following

fabric.exceptions.GroupException: {<Connection host=boss1 user=ec2-user>: TimeoutError(60, 'Operation timed out'), <Connection host=boss2 user=ec2-user>: <Result cmd='uname -a' exited=0>}

I would (1) like to reduce the timeout to 5 seconds (as is specified in group.run()) and (2) isolate the error to only the bad host and return information from the successful one(s).

I have found documentation about connection_timeout, but only group.run() seems to accept a timeout keyword and it does not reduce from 60 seconds.

I have also found documentation about a skip_bad_hosts keyword but cannot insert it into my code without a runtime error.

What is the best way to skip over an error on one system and return results from the others?

Python 3, Fabric 3


Solution

  • The timeout needs to be specified in .ThreadingGroup() (with a different parameter name) and if you capture the exception you can reveal which commands were successful or not.

    #!/usr/bin/python3
    import fabric
    
    group = fabric.ThreadingGroup('boss1', 'boss2', connect_timeout=5)
    
    try:
        results = group.run('uname -nsr', hide=True)
    except fabric.exceptions.GroupException as err:
        results = err.result
    
    
    for _connection, _result in results.items():
        if hasattr(_result, 'stdout'):
            print(f'{_connection.host}: {_result.stdout.strip()}')
        else:
            print(f'{_connection.host}: {_result}')
    

    Sample output:

    boss1: timed out
    boss2: Linux boss2 4.14.355-275.582.amzn2.x86_64