| [2495] | 1 | from subprocess import PIPE, Popen | 
|---|
 | 2 | from invirt.config import structs as config | 
|---|
 | 3 | import random | 
|---|
 | 4 |  | 
|---|
 | 5 | hostnames = [ h.hostname for h in config.hosts ] | 
|---|
 | 6 |  | 
|---|
 | 7 | def monocast(args, hosts = hostnames, randomize = True): | 
|---|
 | 8 |     """ | 
|---|
 | 9 |     Given a command and a list of hostnames or IPs, issue the command to each | 
|---|
 | 10 |     node until it connects to one of the nodes. | 
|---|
 | 11 |  | 
|---|
 | 12 |     Returns: | 
|---|
 | 13 |         host the command ran on | 
|---|
 | 14 |         hosts that could not be contacted | 
|---|
 | 15 |         returncode of remctl | 
|---|
 | 16 |         stdout of remctl | 
|---|
 | 17 |         stderr of remctl | 
|---|
 | 18 |     """ | 
|---|
 | 19 |     if(randomize): | 
|---|
 | 20 |         hosts = random.sample(hosts, len(hosts)) | 
|---|
 | 21 |     hostsdown = [] | 
|---|
 | 22 |     for host in hosts: | 
|---|
 | 23 |         pipe = Popen(['remctl', host, 'remote', 'web'] + args, stdout=PIPE, stderr=PIPE) | 
|---|
 | 24 |         output = pipe.communicate() | 
|---|
 | 25 |         if pipe.returncode != 0: | 
|---|
 | 26 |             if output[1].startswith('remctl: cannot connect to %s' % host): | 
|---|
 | 27 |                 hostsdown.append(host) | 
|---|
 | 28 |             else: | 
|---|
 | 29 |                 #raise RuntimeError("remctl to host %s returned non-zero exit status %d; stderr:\n%s" | 
|---|
 | 30 |                 #                   % (host, pipe.returncode, output[1])) | 
|---|
 | 31 |                 return (host, hostsdown, pipe.returncode,) + output | 
|---|
 | 32 |         else: | 
|---|
 | 33 |             return (host, hostsdown, pipe.returncode,) + output | 
|---|
 | 34 |     raise RuntimeError("Failed to contact any hosts: tried %s" % (hostsdown, )) | 
|---|