#!/usr/bin/env python

# Copyright (C) 2014 SignalFuse, Inc.

# Maestro extension that can be used for wrapping the execution of a
# long-running service with log management scaffolding, potentially sending the
# log output to a file, or through Pipestash, or both, depending on the use
# case and parameters.

import os
import random
import signal
import subprocess

from ...guestutils import *

def run_service(cmd, logbase=None, logtarget=None):
    """Wrap the execution of a service with the necessary logging nets.

    If logbase is provided (it is by default), log output will be redirected
    (or teed) to a file named after the container executing the service inside
    the logbase directory.

    If Redis nodes are available in the environment as referenced by the given
    logtarget, log output will be streamed via pipestash to one of the
    available node containers, chosen at random when the service starts.

    The way this is accomplished varied on whether logbase is provided or not,
    and whether Redis nodes are available:

        - if neither, log output flows to stdout and will be captured by Docker;
        - if logbase is provided, but no Redis nodes are available, the
          output of the service is directly redirected to the log file;
        - if logbase is not provided, but Redis nodes are available, the
          output of the service is piped to pipestash;
        - if logbase is provided and Redis nodes are available, the output
          of the service is piped to a tee that will write the log file, and
          the output of the tee is piped to pipestash.

    The whole pipeline, whatever its construct is, waits for the service to
    terminate. SIGTERM is also redirected from the parent to the service.
    """
    if type(cmd) == str:
        cmd = cmd.split(' ')

    log = logbase and os.path.join(logbase, '{}.log'.format(get_container_name())) or None
    if logbase and not os.path.exists(logbase):
        os.makedirs(logbase)

    redis = logtarget and get_node_list(logtarget, ports=['redis'], minimum=0) or None
    stdout = redis and subprocess.PIPE or (log and open(log, 'w+') or None)

    # Start the service with the provided command.
    service = subprocess.Popen(cmd, stdout=stdout,
                               stderr=subprocess.STDOUT)
    last = service

    # Connect SIGTERM to the service process.
    signal.signal(signal.SIGTERM, lambda signum, frame: service.terminate())

    if redis:
        if log:
            # Tee to a local log file.
            tee = subprocess.Popen(['tee', log], stdin=last.stdout,
                                   stdout=subprocess.PIPE)
            last.stdout.close()
            last = tee

        pipestash = subprocess.Popen(['pipestash', '-t', 'log',
            '-r', 'redis://{}/0'.format(random.choice(redis)),
            '-R', 'logstash',
            '-f', 'service={}'.format(get_service_name()),
            '-S', get_container_name()],
            stdin=last.stdout)
        last.stdout.close()
        last = pipestash

    # Wait for the service to exit and return its return code.
    last.communicate()
    return service.wait()

@@ -391,9 +391,60 @@
 ort 
-*
+get_container_name, get_service_name, get_node_list%0A
 %0A%0Ade
@@ -1169,16 +1169,26 @@
 tured by
+%0A         
  Docker;
@@ -1895,24 +1895,34 @@
 g = logbase 
+%5C%0A        
 and os.path.
@@ -1973,16 +1973,26 @@
 name()))
+ %5C%0A       
  or None
@@ -2092,16 +2092,26 @@
 gtarget 
+%5C%0A        
 and get_
@@ -2158,16 +2158,26 @@
 nimum=0)
+ %5C%0A       
  or None
@@ -2846,16 +2846,29 @@
 s.Popen(
+%0A            
 %5B'pipest
@@ -2898,16 +2898,17 @@
         
+ 
 '-r', 'r
@@ -2946,24 +2946,25 @@
 ce(redis)),%0A
+ 
             
@@ -2993,16 +2993,17 @@
         
+ 
 '-f', 's
@@ -3037,24 +3037,25 @@
 ce_name()),%0A
+ 
             

Fix styling issues