Files
sics/site_ansto/instrument/runsics.py
Douglas Clowes 30c23b1e0a Merge branch 'RELEASE-3_1'
Conflicts:
	sics/site_ansto/instrument/bilby/config/chopper/sct_astrium_chopper.tcl
	sics/site_ansto/instrument/config/beamline/sct_he3_polanal.tcl
	sics/site_ansto/instrument/config/environment/isotech_ps.sct
	sics/site_ansto/instrument/config/environment/isotech_ps_sct.tcl
	sics/site_ansto/instrument/config/environment/temperature/julabo_lh45.sct
	sics/site_ansto/instrument/config/environment/temperature/julabo_lh45_gen_sct.tcl
	sics/site_ansto/instrument/config/environment/temperature/ls340_sct.tcl
	sics/site_ansto/instrument/util/gen_sct.py
2014-11-13 13:52:46 +11:00

243 lines
9.2 KiB
Python
Executable File

#!/usr/bin/env python
# vim: ts=8 sts=4 sw=4 expandtab
import sys
import os
import getpass
import resource
import subprocess
import shlex
import argparse
import re
import socket
import time
from runsics_def import *
# Re-open stdout unbuffered because we want to see feedback live as it happens.
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w',0)
# TODO These numbers should be available on the system to any application
server_port = {
'sics': {'telnet': 60001, 'interrupt': 60002, 'server': 60003,
'quieck': 60004},
'scriptval': {'telnet': 60011, 'interrupt': 60012, 'server': 60013,
'quieck': 60014}
}
inst_test_sockoffset = {
'echidna' : 0,
'wombat' : 100,
'kowari' : 200,
'dingo' : 300,
'quokka' : 400,
'platypus' : 500,
'pelican' : 600,
'taipan' : 700,
'lyrebird' : 800,
'kookaburra' : 900,
'bilby' : 1000,
'emu' : 1100
}
deflt_dir = '/usr/local/sics/server'
deflt_sockoffset = 'none'
deflt_user = inst_user
sics_killer = inst_user
sics_checker = 'root'
if os.environ.has_key('TEST_SICS'):
deflt_test = os.environ['TEST_SICS']
else:
deflt_test = 'none'
def sics_preexec():
resource.setrlimit(resource.RLIMIT_CORE, (resource.RLIM_INFINITY, resource.RLIM_INFINITY))
os.umask(0022)
# TODO Launch simulated devices if TEST_SICS=fakedev. Must write launch script first.
def start_cmd(server, args):
if status_fn(server, args) != (0,0):
print '%s is already running. Cowardly refusing to launch it twice' % server
return
if (args.sockoffset != 'none'):
soffset = ':' + str(inst_test_sockoffset[args.sockoffset])
else:
soffset = ''
sicsenv = {
'none': '',
'fullsim': 'SICS_SIMULATION=full%s' % soffset,
'fakedev': 'SICS_SIMULATION=fakedev%s' % soffset,
'scriptval': 'SICS_INIT_LOGPATH="../script_validator/log" SICS_SIMULATION=script_validator%s' % soffset
}
# Set SICS_SIMULATION environment variable
if (server == 'scriptval'):
SIMENV = sicsenv['scriptval']
else:
SIMENV = sicsenv[args.test]
start_str = 'sudo -u %s %s %s/SICServer -d %s' % (args.user, SIMENV,
args.dir, args.config)
# Suppress output if launching the script validator
if (server == 'scriptval'):
with open(os.devnull) as fp:
subprocess.call(shlex.split(start_str), preexec_fn=sics_preexec,
cwd=args.dir, stderr=fp, stdout=fp)
else:
subprocess.call(shlex.split(start_str), preexec_fn=sics_preexec,
cwd=args.dir)
status_cmd(server, args)
# print "DEBUG: start_str:%s" % (start_str)
def stop_cmd(server, args):
INTMSG = 'SICSINT 6'
(serv_port, pid) = status_cmd(server, args)
if pid:
if (args.sockoffset == 'none'):
int_port = server_port[server]['interrupt']
else:
int_port = server_port[server]['interrupt'] + inst_test_sockoffset[args.sockoffset]
print "STOP %s(%d) by sending '%s' to socket %d" % (server, pid,
INTMSG, int_port)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto( INTMSG + '\n\r', ('localhost', int_port) )
sock.close()
if status_cmd(server, args) != (0,0):
sys.stdout.write('Waiting ')
for n in range(3):
sys.stdout.write('.')
time.sleep(1)
if status_fn(server, args) != (0,0):
continue
else:
break
print ''
else:
return
if status_fn(server, args) != (0,0):
print 'Failed to stop %s' % server
print "Fragging PID %d with default KILL" % (pid)
subprocess.call(shlex.split('sudo -u %s /bin/kill %d' %
(sics_killer, pid)))
else:
return
if status_fn(server, args) != (0,0):
print 'Failed again!'
print "Terminating PID %d with EXTREME PREJUDICE (-15)" % (pid)
subprocess.call(shlex.split('sudo -u %s /bin/kill -15 %d' %
(sics_killer, pid)))
else:
return
if status_cmd(server, args) != (0,0):
print 'Why wont you die, Powers!!??'
print 'I give up. Try calling a SICS programmer or sysadmin'
def status_fn(server, args):
if (args.sockoffset == 'none'):
sock = server_port[server]['server']
else:
sock = server_port[server]['server'] + inst_test_sockoffset[args.sockoffset]
status_str = 'sudo -u %s netstat -nltp' % sics_checker
netstat_str, err = subprocess.Popen(shlex.split(status_str),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).communicate()
# ffr: We can replace the previous Popen().communicate() line with the following two lines if Python is upgraded to V2.7
# with open(os.devnull) as fp:
# netstat_str = subprocess.check_output(shlex.split(status_str), stderr=fp)
#
#Find PID of SICServer listening on server port
m = re.search(':%d .* (\d+)\/SICServer' % sock, netstat_str)
if m:
pid = int(m.group(1))
return (sock, pid)
else:
return (0,0)
def status_cmd(server, args):
(sock,pid) = status_fn(server, args)
if pid:
print '%s listening on port %d, PID=%d' % (server, sock, pid)
else:
print '%s not running' % server
return (sock, pid)
args_adv_grp_help = """
Options providing more control. Usually only useful for SICS
developers and testers. If you are running multiple instances
of SICS on a single host you can set the TEST_SICS environment
variable to one of the --test values to get nice defaults.
"""
args_config_help = 'Run SICS with the given configuration file. Default=%s'
args_dir_help = 'Run SICS from the given directory. Default=%s'
args_test_help = 'Run SICS in the given mode. Default=%s'
args_user_help = 'Run SICS as the given user. Default=%s'
args_sockoffset_help = """
Offset the sockets to allow multiple SICS instances on a single
host. Default=%s
"""
args_sicsonly_help = 'Just run SICS without the script validator'
args_scriptval_help = """
Launch script validator as well as SICServer. Use this to
override the default action when the TEST_SICS environmant
variable is set.
"""
args_dev_help = """
Launch SICS only in current directory listening on socket %s
and with simulation = fullsim
"""
def main(**kwargs):
global sics_killer, sics_checker
runsics_cmd = {'start': start_cmd, 'stop': stop_cmd, 'status': status_cmd}
# Setup defaults. Use nice defaults in test environments.
# Parse arguments
parser = argparse.ArgumentParser( description='SICS Server startup script.')
cmd_grp = parser.add_argument_group('Commands', 'Runsics commands')
adv_grp = parser.add_argument_group('Advanced', args_adv_grp_help)
# Mandatory arguments
cmd_grp.add_argument('cmd', choices=['start', 'stop', 'status'])
# Advanced arguments
adv_grp.add_argument('-c', '--config', help= args_config_help % inst_config,
default = inst_config )
adv_grp.add_argument('-d', '--dir', help=args_dir_help % deflt_dir,
default = deflt_dir)
adv_grp.add_argument('-t', '--test',
choices=['fullsim', 'fakedev', 'scriptval'],
help=args_dir_help % deflt_test, default=deflt_test)
adv_grp.add_argument('-u', '--user', help= args_user_help % deflt_user,
default = deflt_user )
adv_grp.add_argument('--sockoffset',
help= args_sockoffset_help % deflt_sockoffset,
choices=inst_test_sockoffset.keys(),
default = deflt_sockoffset )
exc_grp = parser.add_mutually_exclusive_group()
exc_grp.add_argument('--sicsonly', help= args_sicsonly_help,
action='store_true', default=False)
exc_grp.add_argument('--scriptval', help= args_scriptval_help,
action='store_true', default=False)
exc_grp.add_argument('--dev',
help= args_dir_help % (server_port['sics']['server'] +
inst_test_sockoffset[inst_name]),
action='store_true')
args = parser.parse_args()
# By default don't launch script validator in development environments.
if args.dev:
if args.scriptval:
args.sicsonly = False
else:
args.sicsonly = True
args.sockoffset = inst_name
args.user = getpass.getuser()
sics_killer = getpass.getuser()
sics_checker = getpass.getuser()
if (args.test == 'none'):
args.test = 'fullsim'
if (args.dir == deflt_dir):
args.dir = './'
# Launch SICS
if (args.sicsonly):
runsics_cmd[args.cmd]('sics', args)
else:
runsics_cmd[args.cmd]('sics', args)
runsics_cmd[args.cmd]('scriptval', args)
if __name__ == '__main__':
main()