nodenetwork sequels
[tests.git] / system / TestMain.py
index c576d25..e9c14e8 100755 (executable)
@@ -4,40 +4,23 @@
 import sys, os, os.path
 from optparse import OptionParser
 import traceback
 import sys, os, os.path
 from optparse import OptionParser
 import traceback
+from time import strftime
 
 import utils
 from TestPlc import TestPlc
 from TestSite import TestSite
 from TestNode import TestNode
 
 
 import utils
 from TestPlc import TestPlc
 from TestSite import TestSite
 from TestNode import TestNode
 
-SEP='<sep>'
-
 class TestMain:
 
     subversion_id = "$Id$"
 
 class TestMain:
 
     subversion_id = "$Id$"
 
-    default_config = [ 'main' , '1vnodes' , '1testbox64' ]
+    default_config = [ 'default' ] 
 
 
-    default_steps = ['uninstall','install','install_rpm', 
-                     'configure', 'start', SEP,
-                     'store_keys', 'initscripts', 
-                     'sites', 'nodes', 'slices', 'nodegroups', SEP,
-                     'init_node','bootcd', 'configure_qemu', SEP,
-                     'kill_all_qemus', 'start_nodes', SEP,
-                     'standby_20', SEP,
-                     'nodes_booted', 'nodes_ssh', 'check_slices',
-                     'check_initscripts', 'check_tcp',SEP,
-                     'force_kill_qemus', 'force_gather_logs' ]
-    other_steps = [ 'stop_all_vservers','fresh_install', 'cache_rpm', 'stop', SEP,
-                    'clean_sites', 'clean_nodes', 'clean_slices', 'clean_keys', SEP,
-                    'show_boxes', 'list_all_qemus', 'list_qemus', SEP,
-                    'db_dump' , 'db_restore',
-                    'standby_1 through 20', SEP,
-                    ]
     default_build_url = "http://svn.planet-lab.org/svn/build/trunk"
 
     def __init__ (self):
     default_build_url = "http://svn.planet-lab.org/svn/build/trunk"
 
     def __init__ (self):
-       self.path=os.path.dirname(sys.argv[0])
+       self.path=os.path.dirname(sys.argv[0]) or "."
         os.chdir(self.path)
 
     @staticmethod
         os.chdir(self.path)
 
     @staticmethod
@@ -52,31 +35,27 @@ class TestMain:
         except:
             setattr(parser.values,option.dest,value.split())
 
         except:
             setattr(parser.values,option.dest,value.split())
 
-    @staticmethod
-    def printable_steps (list):
-        return " ".join(list).replace(" "+SEP+" ","\n")
-
     def run (self):
     def run (self):
-        steps_message=20*'x'+" Defaut steps are\n"+TestMain.printable_steps(TestMain.default_steps)
-        steps_message += "\n"+20*'x'+" Other useful steps are\n"+TestMain.printable_steps(TestMain.other_steps)
+        steps_message=20*'x'+" Defaut steps are\n"+TestPlc.printable_steps(TestPlc.default_steps)
+        steps_message += "\n"+20*'x'+" Other useful steps are\n"+TestPlc.printable_steps(TestPlc.other_steps)
         usage = """usage: %%prog [options] steps
         usage = """usage: %%prog [options] steps
-myplc-url defaults to the last value used, as stored in arg-myplc-url,
+arch-rpms-url defaults to the last value used, as stored in arg-arch-rpms-url,
    no default
 build-url defaults to the last value used, as stored in arg-build-url, 
    or %s
 config defaults to the last value used, as stored in arg-config,
    or %r
    no default
 build-url defaults to the last value used, as stored in arg-build-url, 
    or %s
 config defaults to the last value used, as stored in arg-config,
    or %r
-ips defaults to the last value used, as stored in arg-ips,
+node-ips and plc-ips defaults to the last value used, as stored in arg-node-ips and arg-plc-ips,
    default is to use IP scanning
 steps refer to a method in TestPlc or to a step_* module
 ===
 """%(TestMain.default_build_url,TestMain.default_config)
         usage += steps_message
         parser=OptionParser(usage=usage,version=self.subversion_id)
    default is to use IP scanning
 steps refer to a method in TestPlc or to a step_* module
 ===
 """%(TestMain.default_build_url,TestMain.default_config)
         usage += steps_message
         parser=OptionParser(usage=usage,version=self.subversion_id)
-        parser.add_option("-u","--url",action="store", dest="myplc_url", 
-                          help="myplc URL - for locating build output")
+        parser.add_option("-u","--url",action="store", dest="arch_rpms_url", 
+                          help="URL of the arch-dependent RPMS area - for locating what to test")
         parser.add_option("-b","--build",action="store", dest="build_url", 
         parser.add_option("-b","--build",action="store", dest="build_url", 
-                          help="Build URL - for using vtest-init-vserver.sh in native mode")
+                          help="Build URL - for locating vtest-init-vserver.sh")
         parser.add_option("-c","--config",action="callback", callback=TestMain.optparse_list, dest="config",
                           nargs=1,type="string",
                           help="Config module - can be set multiple times, or use quotes")
         parser.add_option("-c","--config",action="callback", callback=TestMain.optparse_list, dest="config",
                           nargs=1,type="string",
                           help="Config module - can be set multiple times, or use quotes")
@@ -87,10 +66,13 @@ steps refer to a method in TestPlc or to a step_* module
                           help="Run all default steps")
         parser.add_option("-l","--list",action="store_true",dest="list_steps", default=False,
                           help="List known steps")
                           help="Run all default steps")
         parser.add_option("-l","--list",action="store_true",dest="list_steps", default=False,
                           help="List known steps")
-        parser.add_option("-i","--ip",action="callback", callback=TestMain.optparse_list, dest="ips",
+        parser.add_option("-N","--nodes",action="callback", callback=TestMain.optparse_list, dest="node_ips",
+                          nargs=1,type="string",
+                          help="Specify the set of IP addresses to use for nodes (scanning disabled)")
+        parser.add_option("-P","--plcs",action="callback", callback=TestMain.optparse_list, dest="plc_ips",
                           nargs=1,type="string",
                           nargs=1,type="string",
-                          help="Specify the set of IP addresses to use in vserver mode (disable scanning)")
-        parser.add_option("-s","--small",action="store_true",dest="small_test",default=False,
+                          help="Specify the set of IP addresses to use for plcs (scanning disabled)")
+        parser.add_option("-1","--small",action="store_true",dest="small_test",default=False,
                           help="run a small test -- typically only one node")
         parser.add_option("-d","--dbname",action="store",dest="dbname",default=None,
                            help="Used by db_dump and db_restore")
                           help="run a small test -- typically only one node")
         parser.add_option("-d","--dbname",action="store",dest="dbname",default=None,
                            help="Used by db_dump and db_restore")
@@ -102,17 +84,16 @@ steps refer to a method in TestPlc or to a step_* module
                           help="Show environment and exits")
         parser.add_option("-f","--forcenm", action="store_true", dest="forcenm", default=False, 
                           help="Force the NM to restart in check_slices step")
                           help="Show environment and exits")
         parser.add_option("-f","--forcenm", action="store_true", dest="forcenm", default=False, 
                           help="Force the NM to restart in check_slices step")
+        parser.add_option("-t","--trace", action="store", dest="trace_file", default=None,
+                          #default="logs/trace-@TIME@.txt",
+                          help="Trace file location")
         (self.options, self.args) = parser.parse_args()
 
         (self.options, self.args) = parser.parse_args()
 
-        # tmp : force small test 
-        utils.header("XXX WARNING : forcing small tests")
-        self.options.small_test = True
-
         if len(self.args) == 0:
             if self.options.all_steps:
         if len(self.args) == 0:
             if self.options.all_steps:
-                self.options.steps=TestMain.default_steps
+                self.options.steps=TestPlc.default_steps
             elif self.options.dry_run:
             elif self.options.dry_run:
-                self.options.steps=TestMain.default_steps
+                self.options.steps=TestPlc.default_steps
             elif self.options.list_steps:
                 print steps_message
                 sys.exit(1)
             elif self.options.list_steps:
                 print steps_message
                 sys.exit(1)
@@ -126,9 +107,10 @@ steps refer to a method in TestPlc or to a step_* module
         # handle defaults and option persistence
         for (recname,filename,default) in (
             ('build_url','arg-build-url',TestMain.default_build_url) ,
         # handle defaults and option persistence
         for (recname,filename,default) in (
             ('build_url','arg-build-url',TestMain.default_build_url) ,
-            ('ips','arg-ips',[]) , 
+            ('node_ips','arg-node-ips',[]) , 
+            ('plc_ips','arg-plc-ips',[]) , 
             ('config','arg-config',TestMain.default_config) , 
             ('config','arg-config',TestMain.default_config) , 
-            ('myplc_url','arg-myplc-url',"") , 
+            ('arch_rpms_url','arg-arch-rpms-url',"") , 
             ) :
 #            print 'handling',recname
             path=filename
             ) :
 #            print 'handling',recname
             path=filename
@@ -164,11 +146,14 @@ steps refer to a method in TestPlc or to a step_* module
             fsave.close()
 #            utils.header('Saved %s into %s'%(recname,filename))
 
             fsave.close()
 #            utils.header('Saved %s into %s'%(recname,filename))
 
+        self.options.arch = "i386"
+        if self.options.arch_rpms_url.find("x86_64") >= 0:
+            self.options.arch="x86_64"
         # steps
         if not self.options.steps:
             #default (all) steps
             #self.options.steps=['dump','clean','install','populate']
         # steps
         if not self.options.steps:
             #default (all) steps
             #self.options.steps=['dump','clean','install','populate']
-            self.options.steps=TestMain.default_steps
+            self.options.steps=TestPlc.default_steps
 
         # exclude
         selected=[]
 
         # exclude
         selected=[]
@@ -213,7 +198,7 @@ steps refer to a method in TestPlc or to a step_* module
         testplc_method_dict = __import__("TestPlc").__dict__['TestPlc'].__dict__
         all_step_infos=[]
         for step in self.options.steps:
         testplc_method_dict = __import__("TestPlc").__dict__['TestPlc'].__dict__
         all_step_infos=[]
         for step in self.options.steps:
-            if step == SEP:
+            if not TestPlc.valid_step(step):
                 continue
             force=False
             # is it a forcedstep
                 continue
             force=False
             # is it a forcedstep
@@ -235,19 +220,35 @@ steps refer to a method in TestPlc or to a step_* module
                     names.sort()
                     all_step_infos += [ ("%s.%s"%(step,name),module_dict[name],force) for name in names ]
                 except :
                     names.sort()
                     all_step_infos += [ ("%s.%s"%(step,name),module_dict[name],force) for name in names ]
                 except :
-                    print 'Step %s -- ignored'%(step)
+                    print '********** step %s NOT FOUND -- ignored'%(step)
                     traceback.print_exc()
                     overall_result = False
             
         if self.options.dry_run:
             self.show_env(self.options,"Dry run")
                     traceback.print_exc()
                     overall_result = False
             
         if self.options.dry_run:
             self.show_env(self.options,"Dry run")
-            
+        
+        # init & open trace file if provided
+        if self.options.trace_file and not self.options.dry_run:
+            time=strftime("%H-%M")
+            date=strftime("%Y-%m-%d")
+            trace_file=self.options.trace_file
+            trace_file=trace_file.replace("@TIME@",time)
+            trace_file=trace_file.replace("@DATE@",date)
+            self.options.trace_file=trace_file
+            # create dir if needed
+            trace_dir=os.path.dirname(trace_file)
+            if trace_dir and not os.path.isdir(trace_dir):
+                os.makedirs(trace_dir)
+            trace=open(trace_file,"w")
+
         # do all steps on all plcs
         # do all steps on all plcs
+        TRACE_FORMAT="TRACE: time=%(time)s plc=%(plcname)s step=%(stepname)s status=%(status)s force=%(force)s\n"
         for (stepname,method,force) in all_step_infos:
             for (spec,obj) in all_plcs:
                 plcname=spec['name']
 
                 # run the step
         for (stepname,method,force) in all_step_infos:
             for (spec,obj) in all_plcs:
                 plcname=spec['name']
 
                 # run the step
+                time=strftime("%Y-%m-%d-%H-%M")
                 if not spec['disabled'] or force:
                     try:
                         force_msg=""
                 if not spec['disabled'] or force:
                     try:
                         force_msg=""
@@ -256,19 +257,32 @@ steps refer to a method in TestPlc or to a step_* module
                         step_result = method(obj)
                         if step_result:
                             utils.header('********** SUCCESSFUL step %s on %s'%(stepname,plcname))
                         step_result = method(obj)
                         if step_result:
                             utils.header('********** SUCCESSFUL step %s on %s'%(stepname,plcname))
+                            status="OK"
                         else:
                             overall_result = False
                             spec['disabled'] = True
                             utils.header('********** FAILED Step %s on %s - discarding that plc from further steps'%(stepname,plcname))
                         else:
                             overall_result = False
                             spec['disabled'] = True
                             utils.header('********** FAILED Step %s on %s - discarding that plc from further steps'%(stepname,plcname))
+                            status="KO"
                     except:
                         overall_result=False
                         spec['disabled'] = True
                         traceback.print_exc()
                         utils.header ('********** FAILED (exception) Step %s on plc %s - discarding this plc from further steps'%(stepname,plcname))
                     except:
                         overall_result=False
                         spec['disabled'] = True
                         traceback.print_exc()
                         utils.header ('********** FAILED (exception) Step %s on plc %s - discarding this plc from further steps'%(stepname,plcname))
+                        status="KO"
 
                 # do not run, just display it's skipped
                 else:
                     utils.header("********** IGNORED Plc %s is disabled - skipping step %s"%(plcname,stepname))
 
                 # do not run, just display it's skipped
                 else:
                     utils.header("********** IGNORED Plc %s is disabled - skipping step %s"%(plcname,stepname))
+                    status="UNDEF"
+                if not self.options.dry_run:
+                    # alwas do this on stdout
+                    print TRACE_FORMAT%locals()
+                    # duplicate on trace_file if provided
+                    if self.options.trace_file:
+                        trace.write(TRACE_FORMAT%locals())
+
+        if self.options.trace_file and not self.options.dry_run:
+            trace.close()
 
         return overall_result
 
 
         return overall_result