update logfile name
[tests.git] / qaapi / system-test.py
1 #!/usr/bin/python
2 import commands
3 import os
4 import sys
5 import traceback
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
12 from qa import utils 
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
25
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)
30
31 def stop_vservers(prefix = 'plc', exempt = []):
32         
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:
39         try: 
40             utils.header("Stopping %(vserver)s " % locals())
41             stop_cmd = "vserver %(vserver)s stop" % locals()
42             (status, output) = commands("vserver %(vserver)s stop" % locals())          
43         except: 
44             print "Failed to stop %(vserver)s" % locals()
45             utils.header("%s" % traceback.format_exc())
46
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)
52     vservers.sort()
53     vservers.reverse()
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)
58
59 usage="""
60 Usage: %prog [options]   
61 """
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")
67
68 # Define globals
69 # Determine vserver name, distribution and mailto
70 # The distribution and current date will be part of of the vserver name  
71 MAX_VSERVERS =  3
72 VSERVER_HOME = '/vservers/'
73 VSERVER_BASENAME = 'plc'
74 distro = 'f8' 
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()
80
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']
85
86 # did the user specify a vserver or plc
87 if options.vserver is not None: vserver_name = options.vserver
88
89 if options.plcname is not None: plc_name = options.plcname
90 else: plc_name = 'TestPLC' 
91
92 # who gets emailed
93 if options.mailto is not None: mailto = options.mailto
94 else: mailto = 'tmack@cs.princeton.edu'     
95
96 # Setup configuration 
97 logfile_dir = "/var/log/qaapi/%(vserver_name)s" % locals()
98 config = Config(logdir = logfile_dir)
99 config.load("qa/qa_config.py")  
100
101 vserver_names = []
102 for distro in distros:
103         vserver_names.append("%(VSERVER_BASENAME)s-%(distro)s-%(DATE)s" % locals())
104         
105 stop_vservers(exempt = vserver_names)
106
107 for distro in distros:
108     try:        
109         vserver_name = "%(VSERVER_BASENAME)s-%(distro)s-%(DATE)s" % locals()
110         config.plcs[plc_name]['vserver'] = vserver_name
111         config.plcs[plc_name]['host'] = config.hostname
112         config.plcs[plc_name]['ip'] = config.ip
113         config.plcs[plc_name].update_ip()
114         person_email = config.persons.values()[0]['email']
115
116         # Set plc configuration options
117         config_options = {}
118         for service in ['API', 'WWW', 'BOOT',' DB']:
119             config_options['PLC_'+service+'_HOST'] = config.plcs[plc_name]['ip']
120             config_options['PLC_'+service+'_IP'] = config.plcs[plc_name]['ip']  
121         config_options['PLC_ROOT_USER'] = 'root@localhost.localdomain'
122         config_options['PLC_ROOT_PASSWORD'] = 'root'
123         
124         # Set node configuration options
125         nodelist = ['vm1.paris.cs.princeton.edu']
126         node_tests = ['node_cpu_sched.py', 'pf2test.pl' ]
127         slice = config.slices['ts_slice1']
128         
129         steps = {}
130         steps[1] = Step("Create vserver %s" % vserver_name, create_vserver, 
131                         (vserver_name, VSERVER_HOME, mailto), config.logfile.filename)
132         steps[2] = Step("Mount plc %s " % plc_name,  config.plcs[plc_name].commands, 
133                         ("/sbin/service plc mount",), config.logfile.filename)
134         steps[3] = Step("Configure plc %s" % plc_name, plc_configure(config), (plc_name, config_options,),
135                         config.logfile.filename)
136         steps[4] = Step("Start plc %s " % plc_name, plc_start(config), (plc_name,),
137                         config.logfile.filename)
138         steps[5] = Step("Add test data", add_test_data(config), (plc_name,), config.logfile.filename)
139         steps[6] = Step("Sync person public key", sync_person_key(config), (person_email,),
140                         config.logfile.filename, False)
141         # XX fix logfile parameter
142         step_method = api_unit_test(config) 
143         steps[7] = Step("API unit test", step_method, (plc_name,), step_method.logfile.filename, False)
144
145         for node in nodelist:
146             if not node in config.nodes.keys(): continue
147             node = config.nodes[node]   
148             step_num = max(steps.keys()) + 1
149             steps[step_num] = Step("Boot node %s" % node['hostname'], boot_node(config),
150                                    (plc_name, node['hostname']), node.logfile.filename)
151             ready_step = Step("Check %s is ready" % node['hostname'], node.is_ready, (), node.logfile.filename)
152             steps[step_num].next_steps.append(ready_step)
153
154             download_scripts = Step("Download test scripts onto %s" % node['hostname'], node.download_testscripts,
155                                     (), config.logfile.filename)
156             steps[step_num].next_steps.append(download_scripts)
157
158                  
159             # XX fix logfile parameter
160             # XX node_run_tests should only run the test, download test on node before calling node_run_test
161             for test in node_tests:
162                 # Create a separate logfile for this script
163                 log_filename = "%s/%s-%s.log" % (config.logfile.dir, test, node['hostname'])
164                 test_logfile = Logfile(log_filename)
165                 step_method = node_run_tests(config, test_logfile) 
166                 test_step = Step("%s test on node %s" % (test, node['hostname']), 
167                                  step_method, (node['hostname'], plc_name, test), 
168                                  step_method.logfile.filename, False)
169                 steps[step_num].next_steps.append(test_step)    
170     
171         # Now that all the steps are defined, run them
172         order = steps.keys()
173         order.sort()
174         results = {}
175         for num in order:
176             steps[num].run()
177             steps[num].notify_contacts()
178             if steps[num].fatal and not steps[num].passed:
179                 break   
180         
181         # Generate summary email
182         to = ["tmack@cs.princeton.edu"]
183         subject = "[QA Results] PLC - %(distro)s - %(DATE)s" % locals()
184         body = """
185         MyPLC %(distro)s results
186         Build: %(DATE)s \n\n""" % locals()
187         
188         utils.header("Sending summary email")
189         # add results to summary body
190         for num in order:
191             step = steps[num]
192             body += step.get_results()
193          
194         sendmail(to, subject, body)     
195  
196     except:
197         utils.header("ERROR %(vserver_name)s tests failed" % locals(), logfile = config.logfile)        
198         utils.header("%s" % traceback.format_exc(), logfile = config.logfile)
199