#!/bin/env python
#
#  kill_daq - kills CODA components for a specified configuration
#
#  DL, 10-Mar-2014
#
#
#
# This is the complment to the start_daq script. It will
# try and kill processes related to a given CODA configuration.
# These processes may be running on remote computers.
#
#  Running this wih no arguments will print a list of 
# CODA configurations based on the current COOL_HOME
# and EXPID environment variable settings. One of those
# configuration names should be given on the command line
# as a single argument to this script so it knows which
# components to try and kill.
#
#  contact:
#  davidl@jlab.org  x5567
#
import sys,os
import subprocess
import string
import time
import math
import re

COOL_HOME  = os.getenv("COOL_HOME")
EXPID      = os.getenv("EXPID")
CONFIG     = ""
if len(sys.argv) > 1 : CONFIG = sys.argv[1]


rocs = []  # will be filled by GetComponents
pebs = []  # will be filled by GetComponents
ers  = []  # will be filled by GetComponents
fcss = []  # will be filled by GetComponents


#------------------
# FindExecutable
#------------------
def FindExecutable(exename, args=[]):
	try:
		proc = subprocess.Popen(["which", exename], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
		result = proc.communicate()[0].strip()
		if proc.returncode == 0:
			for arg in args: result += " " + arg
			return result
	except:
		print sys.exc_info()[0]
	return "<not found>"


#------------------
# KillROC
#------------------
def KillROC(roc):
	global coda_roc
	# By convention, we use the dns name as the roc name in jcedit
	host = roc
	roccmd = '%s' % (coda_roc)
	cmd = "kill_remote_processes -q -n %s %s" % (host, roccmd)
	print cmd
	subprocess.Popen(string.split(cmd))

#------------------
# KillPEB
#------------------
def KillPEB(peb):
	global coda_eb
	# By convention, name of the peb in jcedit is just
	# "peb" with the dns name appended
	host = peb[3:]
	pebcmd = '%s' % (coda_eb)
	cmd = "kill_remote_processes -p -q -n %s %s" % (host, pebcmd)
	print cmd
	subprocess.Popen(string.split(cmd))
	# Try removing the ET system file (if it exists)
	cmd = "ssh %s rm -f /tmp/et_%s_%s" % (host, EXPID, peb)
	print cmd
	subprocess.Popen(string.split(cmd))

#------------------
# KillER
#------------------
def KillER(er):
	global coda_er
	# By convention, name of the ER in jcedit is just
	# "ER" with the dns name appended
	host = er[2:]
	ercmd = '%s' % (coda_er)
	cmd = "kill_remote_processes -p -q -n %s %s" % (host, ercmd)
	print cmd
	subprocess.Popen(string.split(cmd))
	# Try removing the ET system file (if it exists)
	cmd = "ssh %s rm -f /tmp/et_%s_%s" % (host, EXPID, er)
	print cmd
	subprocess.Popen(string.split(cmd))

#------------------
# KillFCS
#------------------
def KillFCS(fcs):
	global coda_fcs
	# By convention, name of the FCS in jcedit is just
	# "fcs" with the dns name appended
	host = fcs[3:]
	fcscmd = '%s' % (coda_fcs)
	cmd = "kill_remote_processes -p -q -n %s %s" % (host, fcscmd)
	print cmd
	subprocess.Popen(string.split(cmd))

#------------------
# GetConfigurations
#------------------
def GetConfigurations():
	confdir = "%s/%s/config/Control" % (COOL_HOME, EXPID)
	if os.path.exists(confdir):
		return os.listdir(confdir)
	else:
		print "Directory doesn't exist: %s" % confdir
		print "Check your COOL_HOME and EXPID environment variables!"
		sys.exit(-1)

#------------------
# GetComponents
#------------------
def GetComponents():
	global rocs, pebs, ers
	fname = "%s/%s/config/Control/%s/%s.rdf" % (COOL_HOME, EXPID, CONFIG, CONFIG)
	with open(fname) as f:
		lines = f.readlines()
		for line in lines:
			idx_end   = string.rfind(line, '.rdf"/>')
			if idx_end   < 2: continue
			idx_start = string.rfind(line[0:idx_end], '/')
			if idx_start < 2: continue
			cname = line[idx_start+1:idx_end]
			if string.find(cname, "roc") == 0: rocs.append(cname)
			if string.find(cname, "ts" ) == 0: rocs.append(cname)
			if string.find(cname, "localhost" ) == 0: rocs.append(cname)  # for running sandbox test
			if string.find(cname, "peb") == 0: pebs.append(cname)
			if string.find(cname, "fcs") == 0: fcss.append(cname)
			if string.find(cname, "ER" ) == 0: ers.append(cname)


#-----------------------------------------

# Check that COOL_HOME and EXPID are set
if COOL_HOME == None:
	print "COOL_HOME environment variable not set!"
	sys.exit(-1)
if EXPID == None:
	print "EXPID environment variable not set!"
	sys.exit(-1)

# Get configuration list
configs = GetConfigurations()
if not CONFIG in configs:
	print "\nYou must specify one of the following configurations:\n"
	for config in configs: sys.stdout.write("%s " % config)
	print "\n"
	sys.exit(0)


# Get the list of ROCs, PEBs, and ERs
GetComponents()
sys.stdout.write("ROCs: ")
print rocs
sys.stdout.write("PEBs: ")
print pebs
sys.stdout.write(" ERs: ")
print ers


print "\n--- Kill all DAQ components ---\n"

# Find executables in current PATH
platform = FindExecutable('platform')
rcgui    = FindExecutable('rcgui')
coda_eb  = FindExecutable('coda_emu_peb64') 
coda_er  = FindExecutable('coda_emu_er64') 
coda_fcs = FindExecutable('coda_emu_fcs64') 
coda_roc = FindExecutable('coda_roc_test') 

print "CODA executable locations:"
print "  platform: %s" % platform
print "     rcgui: %s" % rcgui
print "   coda_eb: %s" % coda_eb
print "   coda_er: %s" % coda_er
print "  coda_fcs: %s" % coda_fcs
print "  coda_roc: %s" % coda_roc
print ""


#--------------------------------------------------------

# Kill platform
cmd = 'pkill -f %s' % (platform)
print cmd
subprocess.Popen(string.split(cmd))


# Kill all PEBs
for peb in pebs: KillPEB(peb)

# Kill all ERs
for er in ers: KillER(er)

# Kill all FCSs
for fcs in fcss: KillFCS(fcs)

# Kill rcgui window (Run Control)
cmd = 'pkill -f %s' % (rcgui)
print cmd
subprocess.Popen(string.split(cmd))

# Kill all ROCs
for roc in rocs: KillROC(roc)

time.sleep(2) # wait for background processes to print thier messages
print "Done"