diff --git a/site_ansto/instrument/MANIFEST.TXT b/site_ansto/instrument/MANIFEST.TXT index 7521efaa..89c8a5e2 100644 --- a/site_ansto/instrument/MANIFEST.TXT +++ b/site_ansto/instrument/MANIFEST.TXT @@ -1,3 +1,4 @@ +runsics.py server_config.tcl barebones.tcl util diff --git a/site_ansto/instrument/dingo/MANIFEST.TXT b/site_ansto/instrument/dingo/MANIFEST.TXT index e8de9be2..6ca7ab23 100644 --- a/site_ansto/instrument/dingo/MANIFEST.TXT +++ b/site_ansto/instrument/dingo/MANIFEST.TXT @@ -1,3 +1,4 @@ +runsics_def.py dingo_configuration.tcl sics_ports.tcl script_validator_ports.tcl diff --git a/site_ansto/instrument/dingo/runsics_def.py b/site_ansto/instrument/dingo/runsics_def.py new file mode 100644 index 00000000..ced76c70 --- /dev/null +++ b/site_ansto/instrument/dingo/runsics_def.py @@ -0,0 +1,3 @@ +inst_user = 'dingo_sics' +inst_name = 'dingo' +inst_config = 'dingo_configuration.tcl' diff --git a/site_ansto/instrument/hipd/MANIFEST.TXT b/site_ansto/instrument/hipd/MANIFEST.TXT index c058f196..0ab31880 100644 --- a/site_ansto/instrument/hipd/MANIFEST.TXT +++ b/site_ansto/instrument/hipd/MANIFEST.TXT @@ -1,3 +1,4 @@ +runsics_def.py sics_ports.tcl script_validator_ports.tcl instrument_vars.tcl diff --git a/site_ansto/instrument/hipd/runsics_def.py b/site_ansto/instrument/hipd/runsics_def.py new file mode 100644 index 00000000..f2a6af78 --- /dev/null +++ b/site_ansto/instrument/hipd/runsics_def.py @@ -0,0 +1,3 @@ +inst_user = 'wombat_sics' +inst_name = 'wombat' +inst_config = 'wombat_configuration.tcl' diff --git a/site_ansto/instrument/hrpd/MANIFEST.TXT b/site_ansto/instrument/hrpd/MANIFEST.TXT index e770e1f6..de1b6bd1 100644 --- a/site_ansto/instrument/hrpd/MANIFEST.TXT +++ b/site_ansto/instrument/hrpd/MANIFEST.TXT @@ -1,3 +1,4 @@ +runsics_def.py sics_ports.tcl script_validator_ports.tcl instrument_vars.tcl diff --git a/site_ansto/instrument/hrpd/runsics_def.py b/site_ansto/instrument/hrpd/runsics_def.py new file mode 100644 index 00000000..321d54a2 --- /dev/null +++ b/site_ansto/instrument/hrpd/runsics_def.py @@ -0,0 +1,3 @@ +inst_user = 'echidna_sics' +inst_name = 'echidna' +inst_config = 'echidna_configuration.tcl' diff --git a/site_ansto/instrument/kookaburra/MANIFEST.TXT b/site_ansto/instrument/kookaburra/MANIFEST.TXT index 89fa2dfa..4e62d61e 100644 --- a/site_ansto/instrument/kookaburra/MANIFEST.TXT +++ b/site_ansto/instrument/kookaburra/MANIFEST.TXT @@ -1,3 +1,4 @@ +runsics_def.py kookaburra_configuration.tcl sics_ports.tcl script_validator_ports.tcl diff --git a/site_ansto/instrument/kookaburra/runsics_def.py b/site_ansto/instrument/kookaburra/runsics_def.py new file mode 100644 index 00000000..d976d11d --- /dev/null +++ b/site_ansto/instrument/kookaburra/runsics_def.py @@ -0,0 +1,3 @@ +inst_user = 'kookaburra_sics' +inst_name = 'kookaburra' +inst_config = 'kookaburra_configuration.tcl' diff --git a/site_ansto/instrument/lyrebird/MANIFEST.TXT b/site_ansto/instrument/lyrebird/MANIFEST.TXT index 75371c6c..1ddf45f1 100644 --- a/site_ansto/instrument/lyrebird/MANIFEST.TXT +++ b/site_ansto/instrument/lyrebird/MANIFEST.TXT @@ -1,3 +1,4 @@ +runsics_def.py lyrebird_configuration.tcl sics_ports.tcl script_validator_ports.tcl diff --git a/site_ansto/instrument/lyrebird/runsics_def.py b/site_ansto/instrument/lyrebird/runsics_def.py new file mode 100644 index 00000000..6ddd852f --- /dev/null +++ b/site_ansto/instrument/lyrebird/runsics_def.py @@ -0,0 +1,3 @@ +inst_user = 'lyrebird_sics' +inst_name = 'lyrebird' +inst_config = 'lyrebird_configuration.tcl' diff --git a/site_ansto/instrument/pelican/MANIFEST.TXT b/site_ansto/instrument/pelican/MANIFEST.TXT index bc3a006e..f5807a59 100644 --- a/site_ansto/instrument/pelican/MANIFEST.TXT +++ b/site_ansto/instrument/pelican/MANIFEST.TXT @@ -1,3 +1,4 @@ +runsics_def.py pelican_configuration.tcl sics_ports.tcl script_validator_ports.tcl diff --git a/site_ansto/instrument/pelican/runsics_def.py b/site_ansto/instrument/pelican/runsics_def.py new file mode 100644 index 00000000..d72c5850 --- /dev/null +++ b/site_ansto/instrument/pelican/runsics_def.py @@ -0,0 +1,3 @@ +inst_user = 'pelican_sics' +inst_name = 'pelican' +inst_config = 'pelican_configuration.tcl' diff --git a/site_ansto/instrument/reflectometer/MANIFEST.TXT b/site_ansto/instrument/reflectometer/MANIFEST.TXT index 15faf1c1..c48c7d9a 100644 --- a/site_ansto/instrument/reflectometer/MANIFEST.TXT +++ b/site_ansto/instrument/reflectometer/MANIFEST.TXT @@ -1,3 +1,4 @@ +runsics_def.py platypus_configuration.tcl sics_ports.tcl script_validator_ports.tcl diff --git a/site_ansto/instrument/reflectometer/runsics_def.py b/site_ansto/instrument/reflectometer/runsics_def.py new file mode 100644 index 00000000..6d44a3b9 --- /dev/null +++ b/site_ansto/instrument/reflectometer/runsics_def.py @@ -0,0 +1,3 @@ +inst_user = 'platypus_sics' +inst_name = 'platypus' +inst_config = 'platypus_configuration.tcl' diff --git a/site_ansto/instrument/rsd/MANIFEST.TXT b/site_ansto/instrument/rsd/MANIFEST.TXT index 3adb26a4..afc3c3c1 100644 --- a/site_ansto/instrument/rsd/MANIFEST.TXT +++ b/site_ansto/instrument/rsd/MANIFEST.TXT @@ -1,3 +1,4 @@ +runsics_def.py sics_ports.tcl script_validator_ports.tcl kowari_configuration.tcl diff --git a/site_ansto/instrument/rsd/runsics_def.py b/site_ansto/instrument/rsd/runsics_def.py new file mode 100644 index 00000000..6e5a95b0 --- /dev/null +++ b/site_ansto/instrument/rsd/runsics_def.py @@ -0,0 +1,3 @@ +inst_user = 'kowari_sics' +inst_name = 'kowari' +inst_config = 'kowari_configuration.tcl' diff --git a/site_ansto/instrument/runsics.py b/site_ansto/instrument/runsics.py new file mode 100755 index 00000000..82b940de --- /dev/null +++ b/site_ansto/instrument/runsics.py @@ -0,0 +1,162 @@ +#!/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 +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 = { + 'wombat': 0, + 'echidna': 100, + 'kowari': 200, + 'quokka': 300, + 'platypus': 400, + 'taipan': 500, + 'pelican': 600, + 'dingo': 700, + 'emu': 800, + 'kookaburra': 900, + 'bilby': 1000 +} + +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_cmd(server, args): + print '%s is already running. Cowardly refusing to launch it twice' % server + return + sicsenv = { + 'none': None, + 'fullsim': {'SICS_SIMULATION': 'full'}, + 'fakedev': {'SICS_SIMULATION': 'fakedev'}, + 'scriptval': {'SICS_SIMULATION': 'script_validator'} + } + execenv = os.environ + if (args.sockoffset != 'none'): + execenv['SOCKOFFSET'] = str(inst_test_sockoffset[args.sockoffset]) + # Set SICS_SIMULATION environment variable + if (server == 'scriptval'): + execenv.update(sicsenv['scriptval']) + else: + execenv.update(sicsenv[args.test]) + start_str = 'sudo -Eu %s %s/SICServer -d %s' % (args.user, 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, env=execenv, cwd=args.dir, stderr=fp, stdout=fp) + else: + subprocess.call(shlex.split(start_str), preexec_fn=sics_preexec, env=execenv, cwd=args.dir) + status_cmd(server, args) + +def stop_cmd(server, args): + INTMSG = 'SICSINT 6' + ret = status_cmd(server, args) + if ret: + (serv_port, pid) = ret + 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) listening on %d' % (server, pid, serv_port) + print "Sending '%s' to %d" % (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): + print 'Failed to stop %s' % server + print 'Try harder dammit!' + subprocess.call(shlex.split('sudo -Eu root killall SICServer')) + else: + return + if status_cmd(server, args): + print 'Failed again!' + print 'Die damn you! DIE!!' + subprocess.call(shlex.split('sudo -Eu root killall -s15 SICServer')) + else: + return + if status_cmd(server, args): + print 'Why wont you die!!??' + print 'I give up. Try calling a SICS programmer or sysadmin' + + +def status_cmd(server, args): + if (args.sockoffset == 'none'): + sock = server_port[server]['server'] + else: + sock = server_port[server]['server'] + inst_test_sockoffset[args.sockoffset] + status_cmd = 'sudo -Eu %s netstat -nltp' % args.user + with open(os.devnull) as fp: + netstat_str = subprocess.check_output(shlex.split(status_cmd), 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)) + print '%s listening on port %d, PID=%d' % (server, sock, pid) + return (sock, pid) + else: + print '%s not running' % server + return '' + +def main(**kwargs): + runsics_cmd = {'start': start_cmd, 'stop': stop_cmd, 'status': status_cmd} + # Setup defaults. Use nice defaults in test environments. + if os.environ.has_key('TEST_SICS'): + deflt_user = getpass.getuser() + deflt_test = os.environ['TEST_SICS'] + deflt_dir = './' + deflt_sockoffset = inst_name + else: + deflt_user = inst_user + deflt_test = 'none' + deflt_dir = '/usr/local/sics/server' + deflt_sockoffset = 'none' + # 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', '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.') + # Mandatory arguments + cmd_grp.add_argument('cmd', choices=['start', 'stop', 'status']) + # Advanced arguments + adv_grp.add_argument('-c', '--config', help='Run SICS with the given configuration file. Default=%s' % inst_config, default = inst_config ) + adv_grp.add_argument('-d', '--dir', help='Run SICS from the given directory. Default=%s' % deflt_dir, default = deflt_dir) + adv_grp.add_argument('-t', '--test', choices=['fullsim', 'fakedev', 'scriptval'], help='Run SICS in the given mode. Default=%s' % deflt_test, default=deflt_test) + adv_grp.add_argument('-u', '--user', help='Run SICS as the given user. Default=%s' % deflt_user, default = deflt_user ) + adv_grp.add_argument('--sockoffset', help='Offset the sockets to allow multiple SICS instances on a single host. Default=%s' % deflt_sockoffset, choices=inst_test_sockoffset.keys(), default = deflt_sockoffset ) + exc_grp = parser.add_mutually_exclusive_group() + exc_grp.add_argument('--sicsonly', help='Just run SICS without the script validator', action='store_true', default=False) + exc_grp.add_argument('--scriptval', help='Launch script validator as well as SICServer. Use this to override the default action when the TEST_SICS environmant variable is set.', action='store_true', default=False) + args = parser.parse_args() + # Don't launch script validator in development environments. + if args.scriptval: + deflt_sicsonly = False + elif os.environ.has_key('TEST_SICS'): + deflt_sicsonly = True + else: + deflt_sicsonly = args.sicsonly + # Launch SICS + if (deflt_sicsonly): + runsics_cmd[args.cmd]('sics', args) + else: + runsics_cmd[args.cmd]('sics', args) + runsics_cmd[args.cmd]('scriptval', args) + + +if __name__ == '__main__': + main() diff --git a/site_ansto/instrument/sans/MANIFEST.TXT b/site_ansto/instrument/sans/MANIFEST.TXT index 2a8bd319..92a3f6d5 100644 --- a/site_ansto/instrument/sans/MANIFEST.TXT +++ b/site_ansto/instrument/sans/MANIFEST.TXT @@ -1,3 +1,4 @@ +runsics_def.py quokka_configuration.tcl sics_ports.tcl script_validator_ports.tcl diff --git a/site_ansto/instrument/sans/runsics_def.py b/site_ansto/instrument/sans/runsics_def.py new file mode 100644 index 00000000..2a4a613f --- /dev/null +++ b/site_ansto/instrument/sans/runsics_def.py @@ -0,0 +1,3 @@ +inst_user = 'quokka_sics' +inst_name = 'quokka' +inst_config = 'quokka_configuration.tcl' diff --git a/site_ansto/instrument/server_config.tcl b/site_ansto/instrument/server_config.tcl index b708853a..aab91abe 100644 --- a/site_ansto/instrument/server_config.tcl +++ b/site_ansto/instrument/server_config.tcl @@ -5,6 +5,10 @@ #set sicsroot /usr/local/sics VarMake sicsdebug Int Mugger sicsdebug 0 +set telnetport 60001 +set interruptport 60002 +set serverport 60003 +set quieckport 60004 # Simulation flags, possible values = true or false # true: The simulated driver will be used. @@ -41,6 +45,12 @@ proc syncbackup {file} { backup motorSave } publish syncbackup Spy +if [info exists env(SOCKOFFSET)] { + set telnetport [expr {$telnetport + $env(SOCKOFFSET)}] + set interruptport [expr {$interruptport + $env(SOCKOFFSET)}] + set serverport [expr {$serverport + $env(SOCKOFFSET)}] + set quieckport [expr {$quieckport + $env(SOCKOFFSET)}] +} if {[info exists env(SICS_SIMULATION)] != 1} { set sicsroot ../ source sics_ports.tcl @@ -66,21 +76,22 @@ if {[info exists env(SICS_SIMULATION)] != 1} { switch $env(SICS_SIMULATION) { "full" { set sicsroot ../ - source sics_ports.tcl sics_simulation true } "fakedev" { set sicsroot ../ - source sics_ports.tcl sics_simulation fakedev } "script_validator" { VarMake sics_script_validator Text internal sics_script_validator true set sicsroot ../script_validator/ - source script_validator_ports.tcl + set telnetport [expr {$telnetport + 10}] + set interruptport [expr {$interruptport + 10}] + set serverport [expr {$serverport + 10}] + set quieckport [expr {$quieckport + 10}] sics_simulation true - MakeSync localhost [expr [get_portnum $serverport ]-10] spy 007 ../log/syncfile.tcl + MakeSync localhost $serverport spy 007 ../log/syncfile.tcl } default { error "ERROR: SICS_SIMULATION must be full, script_validator, or fakedev, not $env(SICS_SIMULATION)" diff --git a/site_ansto/instrument/tas/MANIFEST.TXT b/site_ansto/instrument/tas/MANIFEST.TXT index 2871a006..d223330f 100644 --- a/site_ansto/instrument/tas/MANIFEST.TXT +++ b/site_ansto/instrument/tas/MANIFEST.TXT @@ -1,3 +1,4 @@ +runsics_def.py sics_ports.tcl script_validator_ports.tcl taipan_configuration.tcl diff --git a/site_ansto/instrument/tas/runsics_def.py b/site_ansto/instrument/tas/runsics_def.py new file mode 100644 index 00000000..432a2caa --- /dev/null +++ b/site_ansto/instrument/tas/runsics_def.py @@ -0,0 +1,3 @@ +inst_user = 'taipan_sics' +inst_name = 'taipan' +inst_config = 'taipan_configuration.tcl'