#!/usr/bin/python
# Copyright 2012 Google Inc. All Rights Reserved.
#
"""Run the given shell command for each of the given hosts."""

import os
import re
import select
import subprocess
import sys
import config
from portsh import options

__author__ = 'Avery Pennarun (apenwarr@google.com)'


optspec = """
run [options...] <hosts> -- <command string...>
--
r,raw           Raw output (don't redirect stdin/stdout/stderr)
q,quiet         Quiet: don't print to stderr for nonzero exit codes
"""


def _FixNull(s):
  if s is None:
    return ''
  return str(s)


def _ArgSub(argv, host):
  for arg in argv:
    argout = []
    for part in re.split(r'(\$\w+)', arg):
      if part.startswith('$'):
        for var in config.Host.__slots__:
          if part[1:] == var:
            part = _FixNull(getattr(host, var))
            break
      argout.append(part)
    yield ''.join(argout)


class Handler(object):
  """When data is received from the given file, print it line by line."""

  def __init__(self, prefix, fileobj):
    self.prefix = prefix
    self.fileobj = fileobj
    self.buf = ''

  def __del__(self):
    if self.buf and not self.buf.endswith('\n'):
      self.buf += '\n'
    self.PrintBuf()

  def fileno(self):  #gpylint: disable-msg=C6409
    return self.fileobj.fileno()

  def PrintBuf(self):
    while '\n' in self.buf:
      line, self.buf = self.buf.split('\n', 1)
      print '%s: %s' % (self.prefix, line)

  def Run(self):
    """Read from this handler and write its results to stdout."""
    got = os.read(self.fileobj.fileno(), 65536)
    self.buf += got
    self.PrintBuf()
    return got


def main():
  o = options.Options(optspec)
  args = []
  cmd = []
  for i in range(1, len(sys.argv)):
    if sys.argv[i] == '--':
      args = sys.argv[1:i]
      cmd = sys.argv[i+1:]
      break
  opt, _, hostnames = o.parse(args)
  if not hostnames or not cmd:
    o.fatal('you must specify hosts, --, and a command string')

  try:
    hosts = [config.hosts.FindOne(name=i) for i in hostnames]
  except KeyError, e:
    o.fatal('host not configured: %s' % e)

  procs = []
  handlers = []
  for host in hosts:
    env = dict(os.environ)
    env.update(dict((key, _FixNull(getattr(host, key)))
                    for key in config.Host.__slots__))
    if len(cmd) > 1:
      argv = list(_ArgSub(cmd, host))
      shell = False
    else:
      argv = cmd[0]
      shell = True
    if opt.raw:
      p = subprocess.Popen(argv, env=env, shell=shell)
    else:
      p = subprocess.Popen(argv, env=env, shell=shell,
                           stdout=subprocess.PIPE, stderr=subprocess.PIPE)
      handlers.append(Handler(host.name, p.stdout))
      handlers.append(Handler(host.name, p.stderr))
    procs.append((host, p))

  while handlers:
    r, _, _ = select.select(handlers, [], [])
    for handler in r:
      if not handler.Run():
        handlers.remove(handler)

  final_rv = 0
  for host, p in procs:
    rv = p.wait()
    if rv != 0:
      if not opt.quiet:
        sys.stderr.write('-- %s: exited with error code %d\n'
                         % (host.name, rv))
      final_rv = 1
  return final_rv


if __name__ == '__main__':
  sys.exit(main())
