2009-12-24 5 views
11

Questo è relativo al mio previous question, ma uno diverso.Come fare in modo che Fabric ignori gli host offline nell'elenco env.hosts?

Ho il seguente fabfile:

from fabric.api import * 

host1 = '192.168.200.181' 
offline_host2 = '192.168.200.199' 
host3 = '192.168.200.183' 

env.hosts = [host1, offline_host2, host3] 
env.warn_only = True 

def df_h(): 
    with settings(warn_only=True): 
     run("df -h | grep sda3") 

e l'uscita è:

[192.168.200.199] run: df -h | grep sda3 

Fatal error: Low level socket error connecting to host 192.168.200.199: No route to host 

Aborting. 

Dopo l'esecuzione colpisce il server non in linea, si interrompe immediatamente, a prescindere degli altri server del env. lista degli ospiti.

Ho usato l'impostazione env "warn_only = True", ma forse lo sto usando in modo improprio.

Come posso modificare questo comportamento in modo che stampi solo l'errore e continui a eseguirlo?

risposta

15

Secondo il Fabric documentation on warn_only,

env.warn_only "stabilisce se per avvertire, invece di abortire, quando le condizioni di errore run/sudo/local incontro.

questo non aiuterà a il caso di un server inattivo, poiché l'errore si verifica durante il tentativo SSH prima di eseguire run/sudo/local.

Una soluzione potrebbe essere quella di creare una funzione per verificare se ciascun server è attivo prima dell'esecuzione delle attività. Di seguito è riportato il codice che ho usato.

from __future__ import print_function 
from fabric.api import run, sudo, local, env 
import paramiko 
import socket 

host1 = '192.168.200.181' 
offline_host2 = '192.168.200.199' 
host3 = '192.168.200.183' 

env.hosts = [host1, offline_host2, host3] 

def df_h(): 
    if _is_host_up(env.host, int(env.port)) is True: 
     run("df -h | grep sda1") 


def _is_host_up(host, port): 
    # Set the timeout 
    original_timeout = socket.getdefaulttimeout() 
    new_timeout = 3 
    socket.setdefaulttimeout(new_timeout) 
    host_status = False 
    try: 
     transport = paramiko.Transport((host, port)) 
     host_status = True 
    except: 
     print('***Warning*** Host {host} on port {port} is down.'.format(
      host=host, port=port) 
     ) 
    socket.setdefaulttimeout(original_timeout) 
    return host_status 
+1

Ho usato un modo simile per farlo, ma molto ingenuo - Ho spostato il comando ping con il sottoprocesso modulo -_- " Dovrei assolutamente dare un'occhiata ai moduli che hai usato. Grazie, amico –

+0

@ jevonearth's answer suggerisce il metodo fabric = = v1.4 usando il flag --skip-bad-hosts o env.skip_bad_hosts = True nella funzione – sreenivas

1

Non lo stai usando in modo improprio. Puoi anche solo fornire --warn-only=true sulla riga di comando. It's the documented method suggested by the development team.

+1

Il parametro deve essere "--warn-only". Tuttavia, esegui "fab -warn-only df_h" restituisce lo stesso messaggio di errore. Sembra che l'errore di connessione non sia coperto dall'impostazione "warn_only". –

1

in base alla risposta di Matteo, mi si avvicinò con un decoratore che compie proprio questo:

from __future__ import with_statement 
from paramiko import Transport 
from socket import getdefaulttimeout, setdefaulttimeout 
from fabric.api import run, cd, env, roles 


roledefs = { 
    'greece': [ 
     'alpha', 
     'beta' 
    ], 
    'arabia': [ 
     'kha', 
     'saad' 
    ] 
} 

env.roledefs = roledefs 


def if_host_offline_ignore(fn): 
    def wrapped(): 
     original_timeout = getdefaulttimeout() 
     setdefaulttimeout(3) 
     try: 
      Transport((env.host, int(env.port))) 
      return fn() 
     except: 
      print "The following host appears to be offline: " + env.host 
     setdefaulttimeout(original_timeout) 
    return wrapped 


@roles('greece') 
@if_host_offline_ignore 
def hello_greece(): 
    with cd("/tmp"): 
     run("touch hello_greece") 


@roles('arabia') 
@if_host_offline_ignore 
def hello_arabia(): 
    with cd("/tmp"): 
     run("touch hello_arabia") 

E 'particolarmente utile quando si hanno più host e ruoli.

19

A partire dalla versione 1.4 Fabric ha un'opzione --skip-bad-hosts che può essere impostata dalla riga di comando o impostando la variabile nel file fab.

env.skip_bad_hosts = True 

documentazione per l'opzione è qui: http://docs.fabfile.org/en/latest/usage/fab.html#cmdoption--skip-bad-hosts

Non dimenticare di impostare in modo esplicito il valore di timeout anche.

+1

Questa risposta è quella corretta per fabric> = v1.4 e deve essere upvoted –