6 from optparse import OptionParser
7 from random import Random
8 from time import localtime
9 from qa.sendmail import sendmail
10 from qa.utils import commands
11 from qa.logger import Logfile
13 from qa.Config import Config
14 from qa.Step import Step
15 from qa.tests.vserver_create import vserver_create
16 from qa.tests.vserver_delete import vserver_delete
17 from qa.tests.plc_configure import plc_configure
18 from qa.tests.plc_stop import plc_stop
19 from qa.tests.plc_start import plc_start
20 from qa.tests.add_test_data import add_test_data
21 from qa.tests.api_unit_test import api_unit_test
22 from qa.tests.sync_person_key import sync_person_key
23 from qa.tests.boot_node import boot_node
24 from qa.tests.node_run_tests import node_run_tests
26 def create_vserver(vserver_name, vserver_home, mailto):
27 # create vserver for this system test if it doesnt already exist
28 if not os.path.isdir('%(vserver_home)s/%(vserver_name)s' % locals()):
29 vserver_create(config)(vserver_name, distro, mailto)
31 def stop_vservers(prefix = 'plc', exempt = []):
33 # stop all running vservers
34 vserver_stat = "vserver-stat | grep %(prefix)s | awk '{print$8}'" % locals()
35 (stdin, stdout, stderr) = os.popen3(vserver_stat)
36 vservers = [line.strip() for line in stdout.readlines()]
37 vservers = filter(lambda x: x not in exempt, vservers)
38 for vserver in vservers:
40 utils.header("Stopping %(vserver)s " % locals())
41 stop_cmd = "vserver %(vserver)s stop" % locals()
42 (status, output) = commands("vserver %(vserver)s stop" % locals())
44 print "Failed to stop %(vserver)s" % locals()
45 utils.header("%s" % traceback.format_exc())
47 def cleanup_vservers(max_vservers, vserver_home, vserver_basename):
48 # only keep the newest MAX_VSERVERS
49 vservers = os.listdir("%(vserver_home)s" % locals())
50 valid_vservers = lambda vserver: vserver.startswith(vserver_basename) and os.path.isdir(vserver)
51 vservers = filter(valid_vservers, vservers)
54 expired_vservers = vservers[max_vservers:]
55 for vserver in expired_vservers:
56 utils.header("Deleting vserver: %(vserver)s" % locals(), logfile = config.logfile)
57 #vserver_delete()(vserver)
60 Usage: %prog [options]
62 parser = OptionParser(usage=usage,add_help_option = False)
63 parser.add_option("-v", "--vserver", help = "Vserver where tests should run")
64 parser.add_option("-d", "--distro", help = "Fedora distro to use")
65 parser.add_option("-p", "--plcname", help = "Which plc do we use (from config file)")
66 parser.add_option("-m", "--mailto", help = "Vserver build mailto address")
69 # Determine vserver name, distribution and mailto
70 # The distribution and current date will be part of of the vserver name
72 VSERVER_HOME = '/vservers/'
73 VSERVER_BASENAME = 'plc'
75 # use todays date and defaults to determine which vservers to run tests in
76 year, month, day = localtime()[:3]
77 YEAR, MONTH, DAY = [str(x) for x in [year,month,day]]
78 DATE = ".".join([YEAR, MONTH, DAY])
79 vserver_name = "%(VSERVER_BASENAME)s-%(distro)s-%(DATE)s" % locals()
81 (options, args) = parser.parse_args()
82 # choose which distros to use
83 if options.distro is not None: distros = [options.distro]
84 else: distros = ['f8']
86 # did the user specify a vserver or plc
88 if options.vserver is not None:
89 vserver_name = options.vserver
90 vserver_names.append(vserver_name)
92 if options.plcname is not None: plc_name = options.plcname
93 else: plc_name = 'TestPLC'
96 if options.mailto is not None: mailto = options.mailto
97 else: mailto = 'tmack@cs.princeton.edu'
99 if not options.vserver:
100 for distro in distros:
101 vserver_names.append("%(VSERVER_BASENAME)s-%(distro)s-%(DATE)s" % locals())
103 stop_vservers(exempt = vserver_names)
105 for vserver_name in vserver_names:
107 # Setup configuration
108 logfile_dir = "/var/log/qaapi/%(vserver_name)s" % locals()
109 config = Config(logdir = logfile_dir)
110 config.load("qa/qa_config.py")
112 config.plcs[plc_name]['vserver'] = vserver_name
113 config.plcs[plc_name]['host'] = config.hostname
114 config.plcs[plc_name]['ip'] = config.ip
115 config.plcs[plc_name].update_ip()
116 person_email = config.persons.values()[0]['email']
118 # Set plc configuration options
120 for service in ['API', 'WWW', 'BOOT',' DB']:
121 config_options['PLC_'+service+'_HOST'] = config.plcs[plc_name]['ip']
122 config_options['PLC_'+service+'_IP'] = config.plcs[plc_name]['ip']
123 config_options['PLC_ROOT_USER'] = 'root@localhost.localdomain'
124 config_options['PLC_ROOT_PASSWORD'] = 'root'
126 # Set node configuration options
127 nodelist = ['vm1.paris.cs.princeton.edu']
128 node_tests = ['node_cpu_sched.py', 'pf2test.pl' ]
129 slice = config.slices['ts_slice1']
132 steps[1] = Step("Create vserver %s" % vserver_name, create_vserver,
133 (vserver_name, VSERVER_HOME, mailto), config.logfile.filename)
134 steps[2] = Step("Mount plc %s " % plc_name, config.plcs[plc_name].commands,
135 ("/sbin/service plc mount",), config.logfile.filename)
136 steps[3] = Step("Configure plc %s" % plc_name, plc_configure(config), (plc_name, config_options,),
137 config.logfile.filename)
138 steps[4] = Step("Start plc %s " % plc_name, plc_start(config), (plc_name,),
139 config.logfile.filename)
140 steps[5] = Step("Add test data", add_test_data(config), (plc_name,), config.logfile.filename)
141 steps[6] = Step("Sync person public key", sync_person_key(config), (person_email,),
142 config.logfile.filename, False)
143 # XX fix logfile parameter
144 step_method = api_unit_test(config)
145 #steps[7] = Step("API unit test", step_method, (plc_name,), step_method.logfile.filename, False)
147 for node in nodelist:
148 if not node in config.nodes.keys(): continue
149 node = config.nodes[node]
150 node['vserver'] = vserver_name
151 step_num = max(steps.keys()) + 1
154 steps[step_num] = Step("Boot node %s" % node['hostname'], boot_node(config),
155 (plc_name, node['hostname']), node.logfile.filename)
157 # Check if node is fully booted
158 ready_step = Step("Check %s is ready" % node['hostname'], node.is_ready, (), node.logfile.filename)
159 steps[step_num].next_steps.append(ready_step)
161 # Download test scripts
162 download_scripts = Step("Download test scripts onto %s" % node['hostname'], node.download_testscripts,
163 (), config.logfile.filename)
164 steps[step_num].next_steps.append(download_scripts)
167 # XX fix logfile parameter
168 # XX node_run_tests should only run the test, download test on node before calling node_run_test
169 for test in node_tests:
170 # Create a separate logfile for this script
171 log_filename = "%s/%s-%s.log" % (config.logfile.dir, test, node['hostname'])
172 test_logfile = Logfile(log_filename)
173 step_method = node_run_tests(config, test_logfile)
174 test_step = Step("%s test on node %s" % (test, node['hostname']),
175 step_method, (node['hostname'], plc_name, test),
176 step_method.logfile.filename, False)
177 steps[step_num].next_steps.append(test_step)
180 step_num = step_num + 1
181 steps[step_num] = Step("Enter slice %s on %s" % (slice['name'], node['hostname']),
182 node.slice_commands, ("echo `whoami`@`hostname`", slice['name']),
183 node.logfile.filename, False)
185 # Copy contents of /var/log
186 step_num = step_num + 1
187 steps[step_num] = Step("Get %s logs" % node['hostname'], node.get_logs, (),
188 node.logfile.filename, False)
190 # Now that all the steps are defined, run them
196 steps[num].notify_contacts()
197 if steps[num].fatal and not steps[num].passed:
200 # Generate summary email
201 to = ["qa@planet-lab.org"]
202 subject = "PLC - %(distro)s - %(DATE)s QA summary" % locals()
204 The following are the results of QA tests for %(DATE)s %(distro)s MyPLC.\n\n""" % locals()
206 utils.header("Sending summary email")
207 # add results to summary body
210 body += step.get_results()
212 sendmail(to, subject, body)
213 sendmail(['tmack@cs.princeton.edu'], subject, body)
215 utils.header("ERROR %(vserver_name)s tests failed" % locals(), logfile = config.logfile)
216 utils.header("%s" % traceback.format_exc(), logfile = config.logfile)