By default SICS is launched with no environment variables and sudo doesn't allow 'None' on the ICS computers.
243 lines
9.3 KiB
Python
Executable File
243 lines
9.3 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_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)
|
|
# print "DEBUG: start_str:%s" % (start_str)
|
|
# 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)
|
|
|
|
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()
|