Fabric: Comment lire les résultats dans ThreadingGroup lors d'échecs partiels ?

Créé le 14 mai 2018  ·  5Commentaires  ·  Source: fabric/fabric

Il sera bon d'inclure un exemple de cela dans les docs aussi. Supposons que j'ai ce code.

from fabric import ThreadingGroup as Group
from fabric.exceptions import GroupException

hosts = ['web1', 'web2', 'web3']
g = Group(*hosts)

try:
    results = g.run('date', hide='both')
except GroupException as e:
    print e.args # I read from code that arguments are passed to exception but I'm unable to use that. `args` argument in my case is an empty tuple. 

Supposons que web1 et web3 ont réussi alors que web2 n'a pas réussi à se connecter ou que la commande a renvoyé un code de sortie différent de zéro.

  • Comment puis-je obtenir ces détails après la levée de l'exception ?
  • Est-il garanti que l'exception ne sera déclenchée qu'une fois toutes les opérations effectuées ?

Toute aide est appréciée.

Commentaire le plus utile

Bonjour,

En plus du commentaire de shadyabhi, voici une façon que j'utilise pour gérer GroupException.
J'espère que cela aidera !!

import logging, socket, paramiko.ssh_exception
from fabric import Connection, Config, ThreadingGroup, exceptions, runners

...

g = ThreadingGroup.from_connections(c)
try:
    result = g.run('hostname' )  # (just a basic command)
except exceptions.GroupException as e:
    i = 0
    for c, r in e.result.items():
        print("Host[{}] = [{}]".format(i,c.host) )
        if isinstance(r,runners.Result) :
            print("ok, fine")
        elif isinstance(r,socket.gaierror) :
            print("Network error")
        elif isinstance(r,paramiko.ssh_exception.AuthenticationException) :
            print("Auth failed")
        else:
            print("something else")
        i+=1



(obtenu si du support ActivCloud )

Tous les 5 commentaires

Salut @shadyabhi ,

Vous ne savez pas si vous essayez d'attraper une exception spécifique ou si vous voulez simplement attraper toutes les exceptions qui se produisent dans des threads séparés. Je pense que l'objet ThreadingGroup passe déjà autour des objets d'exception à l'aide de files d'attente et déclenche le cas échéant lors de l'exécution. J'ai pu voir les traces de la pile en utilisant l'extrait de code suivant :

def run_data(c):
    c.run('date', hide='both')

<strong i="8">@task</strong>
def thread_exception_example(c):
    hosts = ['localhost', 'fakehost', 'localhost']

    # python list comprehension
    {c: run_data(c) for c in Group(*hosts)}

Sur la ligne de commande, j'ai exécuté : fab thread-exception-example

Salut @bossjones ,

Merci d'avoir répondu. Cependant, je n'utilise pas la commande fab mais j'exécute plutôt tout cela en utilisant fabric comme bibliothèque. Donc, une réponse est toujours en attente et serait appréciée.

En d'autres termes, fab gère moi-même ce que je veux gérer dans mon code. Il y a des raisons pour lesquelles je ne veux pas utiliser directement la commande fab car j'aimerais avoir plus de flexibilité dans la façon dont j'appelle les tâches.

Merci

Salut tout le monde,

Je suis désolé, j'ai oublié les détails. J'ai vérifié le code du tissu et j'ai obtenu des détails.

L'argument avec GroupException est un dictionnaire avec la clé comme objet fabric.connection.Connection et la valeur comme objet fabric.runners.Result .

except GroupException as e:
         for c, r in e.result.items():
             print "Connection: {}, Result: {}".format(c, r)

Bonjour,

En plus du commentaire de shadyabhi, voici une façon que j'utilise pour gérer GroupException.
J'espère que cela aidera !!

import logging, socket, paramiko.ssh_exception
from fabric import Connection, Config, ThreadingGroup, exceptions, runners

...

g = ThreadingGroup.from_connections(c)
try:
    result = g.run('hostname' )  # (just a basic command)
except exceptions.GroupException as e:
    i = 0
    for c, r in e.result.items():
        print("Host[{}] = [{}]".format(i,c.host) )
        if isinstance(r,runners.Result) :
            print("ok, fine")
        elif isinstance(r,socket.gaierror) :
            print("Network error")
        elif isinstance(r,paramiko.ssh_exception.AuthenticationException) :
            print("Auth failed")
        else:
            print("something else")
        i+=1



(obtenu si du support ActivCloud )

Merci @akiuni pour votre exemple ! Je suis nouveau sur Python/Fabric et cela m'a aidé à comprendre comment faire des requêtes à l'aide de ThreadedGroup et collecter les résultats en cas d'exception. Voici ma version étendue de votre exemple. Très appréciée! Pour ce que ça vaut, j'ai également posté ceci sur Stackoverflow .

# requires fabric 2.x - run 'pip install fabric' to install it
import logging, socket, paramiko.ssh_exception
from fabric import Connection, Config, SerialGroup, ThreadingGroup, exceptions, runners
from fabric.exceptions import GroupException


# Note: You need to supply your own valid servers here to ssh to of course!
def main():
    testHosts("All should succeed", "validServer1,validServer2,validServer3")
    testHosts("Some should fail", "validServer1,validServer2,BADSERVER1,validServer3,BADSERVER2")

def testHosts(message, hostsAsString):
    print("")
    print(message)

    # Get list of hosts from somewhere, and convert them to connections
    hosts = hostsAsString.split(",")
    servers = [Connection(host=host) for host in hosts]

    # Create a thread group to run requests in parallel
    g = ThreadingGroup.from_connections(servers)
    try:
        command = "df -h / | tail -n1 | awk '{print $5}'"
        results = g.run(command, hide=True)
        for r in results:
            connection = results[r]
            print("{}".format(r.host) )
            print("  SUCCESS, " + connection.stdout.strip())
    except GroupException as e:
        # If an exception occurred, at least one request failed. 
        # Iterate through results here
        for c, r in e.result.items():
            print("{}".format(c.host) )
            if isinstance(r,runners.Result) :
                print("  SUCCESS, " + r.stdout.strip())
            elif isinstance(r,socket.gaierror) :
                print("  FAILED,  Network error")
            elif isinstance(r,paramiko.ssh_exception.AuthenticationException) :
                print("  FAILED,  Auth failed")
            else:
                print("  FAILED,  Something other reason")

main()

Cette page vous a été utile?
0 / 5 - 0 notes