.



git-svn-id: http://test.kernel.org/svn/autotest/trunk@541 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/conmux/drivers/reboot-apc b/conmux/drivers/reboot-apc
index 6a5d36f..e66dc39 100755
--- a/conmux/drivers/reboot-apc
+++ b/conmux/drivers/reboot-apc
@@ -3,32 +3,89 @@
 # Reboot a machine connected to an APC power strip
 #
 # Copyright 2007 Google Inc., Martin J. Bligh <mbligh@google.com>
+set P "reboot-apc"
 
-set ip_addr [lindex $argv 0]
-set port [lindex $argv 1]
+#
+# OPTIONS: options parser.
+#
+proc shift {_list} {
+        upvar $_list list
+        set res [lindex $list 0]
+        set list [lreplace $list 0 0]
+        return $res
+}
 
-spawn telnet $ip_addr
+proc arg {_list arg} {
+        upvar $_list list
+        if {[llength $list] < 1} {
+               puts stderr "$arg: required argument missing"
+               exit 1
+        }
+        return [shift list]
+}
 
 set timeout 10
+set user {apc}
+set pass {apc}
+set host [lindex $argv 0]
+set outlet [lindex $argv 1]
+shift argv
+shift argv
 
+while {[llength $argv] > 0} {
+puts "length [llength $argv]"
+   switch -- [shift argv] {
+      -p  { set pass [arg argv p]}
+      -u  { set user [arg argv u]}
+   }
+}
+
+if {[llength $argv] > 0} {
+   puts stderr "Usage: $P <host> <outlet> [-u <user>] [-p <pass>]"
+   exit 1
+}
+
+if {[string compare $host ""] == 0 ||
+   [string compare $outlet ""] == 0} \
+   {
+      puts stderr "host and outlet required"
+      exit 1
+   }
+
+spawn telnet $host
 expect "User Name :"
-send "apc\r"
+send $user
+send "\r"
 expect "Password  :"
-send "apc\r"
+send $pass
+send "\r"
 expect "1- Device Manager"
 expect "> "
 send "1\r"
-expect "3- Outlet Control/Configuration"
-expect "> "
-send "3\r"
-expect "Press <ENTER> to continue..."
+# We get a different prompt if we're just an outlet controller
+# decide which response we need to enter
+set timeout 2
+expect {
+   "3- Outlet Control/Configuration" {
+      send "3\r"
+      exp_continue
+   }
+   "2- Outlet Control" {
+      send "2\r"
+      exp_continue
+   }
+}
 send "\r"
 expect "> "
-send $port
+send $outlet
 send "\r"
-expect "1- Control Outlet"
-expect "> "
-send "1\r"
+# Here too, if we're just an outlet controller we don't get the option
+# to modify configuration
+expect {
+   "1- Control Outlet" {
+      send "1\r"
+   }
+}
 expect "3- Immediate Reboot"
 expect "> "
 send "3\r"
diff --git a/server.old/monitor_queue b/server.old/monitor_queue
new file mode 100755
index 0000000..75428cc
--- /dev/null
+++ b/server.old/monitor_queue
@@ -0,0 +1,70 @@
+#!/usr/bin/python -u
+# monitor_queue <client> <spool_directory> <resultsdir> [<conmux_console>]
+import os, time, sys
+from subprocess import *
+
+if (len(sys.argv) < 4):
+	print "Usage: monitor_queue <client> <spool_directory> <resultsdir> [<conmux_console>]"
+	sys.exit(1)
+(client, spooldir, resultsdir) = sys.argv[1:4]
+if len(sys.argv) == 5:
+	console = sys.argv[4]
+else:
+	console = None
+if not os.path.exists(spooldir):
+	print "spooldir %s does not exist" % spooldir
+	sys.exit(1)
+if not os.path.exists(resultsdir):
+	print "resultsdir %s does not exist" % resultsdir
+	sys.exit(1)
+
+
+def pick_job(jobs):
+	# Pick the next job to run. Currently we just pick the oldest job
+	# However, this would be the place to put prioritizations.
+	if not jobs:
+		return None
+	return sorted(jobs, key=lambda x:os.stat(x).st_mtime, reverse=True)[0]
+
+
+def run_job(control):
+	print "Executing job: " + next_job
+
+	# First set up some paths.
+	results = os.path.join(resultsdir, next_job)
+	if os.path.exists(results):
+		print "Resultsdir %s already present, " % results,
+		results = "%s.%d" % (results, int(time.time()))
+		print "changing to %s" % results
+	os.mkdir(results)
+	debug = os.path.join(results, 'debug')
+	os.mkdir(debug)
+
+	# Now run the job
+	runjob_cmd = ' '.join([runjob, client, next_job, results])
+	if console:
+		runjob_cmd += ' ' + console
+	server_log = open(os.path.join(debug, 'server.log'), 'w');
+	p = Popen(runjob_cmd, shell=True, stdout=server_log, stderr=STDOUT)
+	(pid, ret) = os.waitpid(p.pid, 0)
+	file.close(server_log)
+	print "Completed job: %s (%d) " % (next_job, ret)
+	return ret
+
+
+dir = os.path.abspath(os.path.dirname(sys.argv[0]))
+runjob = os.path.join(dir, 'runjob')
+os.chdir(spooldir)
+print "monitoring spool directory: " + spooldir
+while True:
+	jobs = [j for j in os.listdir(spooldir) if not j.startswith('.')]
+	next_job = pick_job(jobs)
+	if not next_job:
+		time.sleep(10)
+		continue
+	ret = run_job(next_job)
+	if ret == 1:          # Ooops. the machine is stuffed.
+		print "WARNING: client %s failed verify_machine" % client
+		sleep(600)
+		continue
+	os.remove(next_job)
diff --git a/server.old/runjob b/server.old/runjob
new file mode 100755
index 0000000..1a0c25f
--- /dev/null
+++ b/server.old/runjob
@@ -0,0 +1,156 @@
+#!/usr/bin/python
+import sys, os, re, commands, time, signal
+from subprocess import *
+
+# Execute a job on a remote client. We use ssh to connect.
+#
+# autotest-client is run on the other end. It will connect us with
+# stdout and stderr outputs:
+#
+# stdout: standard output of autotest binary (job spew)
+# stderr: Control stream (read from named pipe on client
+#
+# We want to just log stdout to a server-side file.
+# Stderr is what we're monitoring closely for status.
+# If the stderr stream gives us an EOF, the autotest-client exited
+
+# Return codes:
+# 0 - success
+# 1 - verify machine failed
+# 2 - execute job failed
+
+autodir = '/usr/local/autotest'            # default. changed by retrieve_config
+
+def parse_arguments():
+	# First parse arguments, do setup, etc.
+	if len(sys.argv) < 4:
+		sys.stderr.write("Usage: runjob <client> <control_file> <results> [<conmux_console>]\n")
+		sys.exit(1)
+	(client, control, results) = sys.argv[1:4]
+	if len(sys.argv) == 5:
+		console = sys.argv[4]
+	else:
+		console = None
+	if not os.path.exists(control):
+		sys.stderr.write("Control file %s does not exist\n" % control)
+		sys.exit(1)
+	return (client, control, results, console)
+
+
+def retrieve_config(client):
+	# Grab the autotest.conf file from the client, 
+	# so we can use config information
+	print "Retrieving autotest.conf from %s" % client
+	local_conf = "/tmp/autotest.conf.%d" % os.getpid()
+	if os.path.exists(local_conf):
+		os.remove(local_conf)
+	os.system("scp -q root@%s:/etc/autotest.conf %s" % (client, local_conf))
+
+	# Now to find out what $AUTODIR is on the client
+	# This is disgusting, but will have to do for now. 
+	# We can't source it (security nightmare)
+	global autodir
+	if os.path.exists(local_conf):
+		for line in open(local_conf, 'r').readlines():
+			dir = re.search(r'autodir=(\S+)', line).group(1)
+			if dir:
+				autodir = re.sub('[\'\"]', '', dir)
+	print "autodir set to " + autodir
+
+
+def verify_machine(client):
+	autotest_bin = os.path.join(autodir, 'bin/autotest')
+	ret = os.system("ssh -q root@%s ls %s > /dev/null" % (client, autotest_bin))
+	if ret != 0:
+		return False
+	return True
+
+
+def clean_house(client):
+	path = os.path.join(autodir, 'control')
+	ret = os.system("ssh -q root@%s rm -f %s" % (client, path))
+	path = os.path.join(autodir, 'control.state')
+	ret = os.system("ssh -q root@%s rm -f %s" % (client, path))
+
+
+def push_control(remote_control):
+	# Push the control file we want to sue to the client
+	print "Pushing control file %s to %s" % (control, client)
+	ret = os.system("scp -q %s root@%s:%s" % \
+					(control, client, remote_control))
+	if ret != 0:
+		raise "pushing control file failed"
+
+
+def execute_section(client, autodir, remote_control, section):
+	print "Executing %s/bin/autotest %s/control phase %d" % \
+						(autodir, autodir, section)
+	client_log = open("%s/debug/client.log.%d" % (results, section), 'w')
+	if section > 0:
+		remote_control = '-c ' + remote_control
+	cmd = "ssh -q root@%s %s/bin/autotest_client %s" % \
+					(client, autodir, remote_control)
+	f = Popen(cmd, shell=True, stdout=client_log, stderr=PIPE).stderr
+	line = None
+	for line in iter(f.readline, ''): 
+		print line,
+		sys.stdout.flush()
+	return line
+
+
+def execute_control(client, autodir, remote_control):
+	section = 0
+	while True:
+		last = execute_section(client, autodir, remote_control, section)
+		section += 1
+		if re.match('DONE', last):
+			print "Client complete"
+			return True
+		elif re.match('REBOOT', last):
+			print "Client is rebooting"
+			time.sleep(300)
+		else:
+			sys.stderr.write("Aborting - unknown return code: %s\n"\
+									 % last)
+			return False
+
+
+def retrieve_results(client, autodir, results):
+	ret = os.system("scp -rq root@%s:%s/results/default/* %s" % \
+						(client,autodir,results))
+	if ret != 0:
+		raise "retrieve results failed"
+
+
+# MAIN PROGRAM
+
+ret = 0
+(client, control, results, console) = parse_arguments()
+debug = os.path.join(results, 'debug')
+if not os.path.exists(debug):
+	os.makedirs(debug)
+
+if console:
+	console_log = open(os.path.join(debug, "console.log"), 'w')
+	conmux_path = os.path.join(os.path.dirname(sys.argv[0]), \
+							'../conmux/console')
+	cmd = os.path.abspath(conmux_path) + ' ' + console
+	# For some incomprehensible reason, conmux won't redirect to a file.
+	con = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT)
+	Popen(['cat'], stdin=con.stdout, stdout=console_log)
+	con_pid = con.pid
+else:
+	con_pid = None
+
+retrieve_config(client)
+if not verify_machine(client):
+	sys.exit(1)
+clean_house(client)
+remote_control = "%s/control" % autodir
+push_control(remote_control)
+if not execute_control(client, autodir, remote_control):
+	ret = 2
+retrieve_results(client, autodir, results)
+if con_pid:
+	os.kill(con_pid, signal.SIGTERM)
+sys.exit(ret)
diff --git a/server.old/start_all_queues b/server.old/start_all_queues
new file mode 100755
index 0000000..3978ce4
--- /dev/null
+++ b/server.old/start_all_queues
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+
+import os, os.path, sys
+
+dir = os.path.abspath(os.path.dirname(sys.argv[0]))
+monitor_queue = os.path.join(dir, 'monitor_queue')
+
+if len(sys.argv) < 2:
+	print "Usage: start_all_queues <top_level_dir>"
+	sys.exit(1)
+
+top_dir = os.path.abspath(sys.argv[1])
+queue_dir = os.path.join(top_dir, 'queue')
+results_dir = os.path.join(top_dir, 'results')
+
+for machine in os.listdir(queue_dir):
+	queue = os.path.join(queue_dir, machine)
+	results = os.path.join(results_dir, machine)
+
+	if not os.path.exists(results):
+		print "No results directory: %s" % results
+		sys.exit(1)
+
+	console_path = "/usr/local/conmux/etc/%s.cf" % machine
+	if os.path.exists(console_path):
+		console = machine
+	else:
+		console = ''
+
+	cmd = ' '.join([monitor_queue, machine, queue, results, console])
+	print cmd
+	os.system("nohup %s > %s/.log 2>&1 &" % (cmd,queue))
+
diff --git a/server.old/testkernel b/server.old/testkernel
new file mode 100755
index 0000000..c680403
--- /dev/null
+++ b/server.old/testkernel
@@ -0,0 +1,46 @@
+#!/usr/bin/python
+# testkernel <client> <control> <kernel> <config> <patches ...>
+#
+# Create a config that builds the kernel+patches specified, 
+# then runs the tests specified in the control file supplied.
+#
+# Run that control file on the comma-separated list of machines supplied
+# by dumping a control file in $AUTOTEST_DIR/queue/machine. 
+import os, sys, time
+
+if len(sys.argv) < 5:
+	print "Usage: testkernel <client> <control> <kernel> <config> <patches ...>"
+	sys.exit(1)
+(client, control, kernel, config) = sys.argv[1:5]
+if len(sys.argv) > 5:
+	patches = sys.argv[5:]
+else:
+	patches = []
+
+
+# Need to be careful to create the control file atomically, so don't end up
+# executing half of it. Try to create it in the same filesystem, then move it.
+queuedir = os.path.join(os.environ['AUTOTEST_DIR'], 'queue')
+tmpfile = os.path.join(queuedir, 'tmp_control.%d' % os.getpid())
+c = open(tmpfile, 'w')
+print >> c, "def step_init():"
+print >> c, "\t" + "job.next_step([step_test])"
+print >> c, "\t" + "testkernel = job.kernel('%s')" % kernel
+if patches:
+	patch_list = ', '.join(["'%s'" % x for x in patches])
+	print >> c, "\t" + "testkernel.patch(%s)" % patch_list
+print >> c, "\t" + "testkernel.config('%s')" % config
+print >> c, "\t" + "testkernel.build()"
+print >> c, "\t" + "testkernel.boot()"
+print >> c, ""
+print >> c, "def step_test():"
+
+for line in open(control, 'r'):
+	print >> c, "\t" + line,
+c.close()
+# This is pretty revolting, but will do as a hack for testing
+jobname = os.path.basename(control) + '.' + os.path.basename(kernel)
+output = os.path.join(queuedir, client, jobname)
+if os.path.exists(output):
+	output += ".%d" % int(time.time())
+os.rename(tmpfile, output)