Fabric: ¿Cómo leer los resultados en ThreadingGroup durante fallas parciales?

Creado en 14 may. 2018  ·  5Comentarios  ·  Fuente: fabric/fabric

Será bueno incluir un ejemplo de eso en los documentos también. Supongamos que tengo este código.

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. 

Supongamos que web1 y web3 tuvieron éxito mientras que web2 no pudo conectarse o el comando regresó con un código de salida distinto de cero.

  • ¿Cómo obtengo esos detalles después de que se genera la excepción?
  • ¿Está garantizado que la excepción se generará solo después de que se hayan realizado todas las operaciones?

Cualquier ayuda es apreciada.

Comentario más útil

Hola,

Además del comentario de shadyabhi, aquí hay una forma que uso para tratar con GroupException.
Espero que esto sea de ayuda !!

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



(lo obtuve del soporte de ActivCloud )

Todos 5 comentarios

Hola @shadyabhi ,

No estoy seguro si está tratando de detectar una excepción específica o si solo desea detectar todas las excepciones que ocurren en subprocesos separados. Creo que el objeto ThreadingGroup ya pasa alrededor de objetos de excepción usando colas y subidas si se encuentra alguna durante la ejecución. Pude ver los rastros de la pila usando el siguiente fragmento de código:

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)}

En la línea de comandos ejecuté: fab thread-exception-example

Hola @bossjones ,

Gracias por responder. Sin embargo, no estoy usando el comando fab sino ejecutando todo esto usando fabric como una biblioteca. Entonces, una respuesta aún está pendiente y sería apreciada.

En otras palabras, fab está manejando lo que yo mismo quiero manejar en mi código. Hay razones por las que no quiero usar el comando fab directamente, ya que me gustaría tener más flexibilidad en la forma en que invoco las tareas.

Gracias

Hola a todos,

Lo siento, pasé por alto los detalles. Revisé el código de la tela y obtuve detalles.

El argumento con GroupException es un diccionario con la clave como objeto fabric.connection.Connection y el valor como objeto fabric.runners.Result .

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

Hola,

Además del comentario de shadyabhi, aquí hay una forma que uso para tratar con GroupException.
Espero que esto sea de ayuda !!

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



(lo obtuve del soporte de ActivCloud )

¡Gracias @akiuni por tu ejemplo! Soy nuevo en Python/Fabric y eso me ayudó a comprender cómo realizar solicitudes usando ThreadedGroup y recopilar los resultados cuando hubo una excepción. Aquí está mi versión ampliada de su ejemplo. ¡Muy apreciado! Por lo que vale, también publiqué esto en 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()

¿Fue útil esta página
0 / 5 - 0 calificaciones