moving to multi-plcs daily tests
[tests.git] / system / TestMain.py
index 9dbe219..75c79ff 100755 (executable)
@@ -1,10 +1,11 @@
-#!/usr/bin/env python
+#!/usr/bin/env python -u
 # $Id$
 
 import sys, os, os.path
 from optparse import OptionParser
 import traceback
 from time import strftime
+import readline
 
 import utils
 from TestPlc import TestPlc
@@ -45,7 +46,7 @@ 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
-node-ips and plc-ips defaults to the last value used, as stored in arg-node-ips and arg-plc-ips,
+node-ips and plc-ips defaults to the last value used, as stored in arg-ips-node and arg-ips-plc,
    default is to use IP scanning
 steps refer to a method in TestPlc or to a step_* module
 ===
@@ -72,20 +73,22 @@ 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")
-        parser.add_option("-N","--nodes",action="callback", callback=TestMain.optparse_list, dest="node_ips",
+        parser.add_option("-N","--nodes",action="callback", callback=TestMain.optparse_list, dest="ips_node",
                           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",
+        parser.add_option("-P","--plcs",action="callback", callback=TestMain.optparse_list, dest="ips_plc",
                           nargs=1,type="string",
                           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("-s","--size",action="store",type="int",dest="size",default=1,
+                          help="sets test size in # of plcs - default is 1")
         parser.add_option("-D","--dbname",action="store",dest="dbname",default=None,
                            help="Used by db_dump and db_restore")
         parser.add_option("-v","--verbose", action="store_true", dest="verbose", default=False, 
                           help="Run in verbose mode")
         parser.add_option("-q","--quiet", action="store_true", dest="quiet", default=False, 
                           help="Run in quiet mode")
+        parser.add_option("-i","--interactive",action="store_true",dest="interactive",default=False,
+                          help="prompts before each step")
         parser.add_option("-n","--dry-run", action="store_true", dest="dry_run", default=False,
                           help="Show environment and exits")
         parser.add_option("-r","--restart-nm", action="store_true", dest="forcenm", default=False, 
@@ -94,6 +97,8 @@ steps refer to a method in TestPlc or to a step_* module
                           #default="logs/trace-@TIME@.txt",
                           help="Trace file location")
         (self.options, self.args) = parser.parse_args()
+        if self.options.quiet:
+            self.options.verbose=False
 
         if len(self.args) == 0:
             if self.options.all_steps:
@@ -113,13 +118,13 @@ 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) ,
-            ('node_ips','arg-node-ips',[]) , 
-            ('plc_ips','arg-plc-ips',[]) , 
+            ('ips_node','arg-ips-node',[]) , 
+            ('ips_plc','arg-ips-plc',[]) , 
             ('config','arg-config',TestMain.default_config) , 
             ('arch_rpms_url','arg-arch-rpms-url',"") , 
             ('personality','arg-personality',"linux32"),
             ('pldistro','arg-pldistro',"planetlab"),
-            ('fcdistro','arg-fcdistro','f8'),
+            ('fcdistro','arg-fcdistro','centos5'),
             ) :
 #            print 'handling',recname
             path=filename
@@ -142,8 +147,6 @@ steps refer to a method in TestPlc or to a step_* module
                         print "Cannot determine",recname
                         print "Run %s --help for help"%sys.argv[0]                        
                         sys.exit(1)
-            if not self.options.quiet:
-                utils.header('* Using %s = %s'%(recname,getattr(self.options,recname)))
 
             # save for next run
             fsave=open(path,"w")
@@ -155,6 +158,14 @@ steps refer to a method in TestPlc or to a step_* module
             fsave.close()
 #            utils.header('Saved %s into %s'%(recname,filename))
 
+            # lists need be reversed
+            if isinstance(getattr(self.options,recname),list):
+                getattr(self.options,recname).reverse()
+
+            if not self.options.quiet:
+                utils.header('* Using %s = %s'%(recname,getattr(self.options,recname)))
+
+
         if self.options.personality == "linux32":
             self.options.arch = "i386"
         elif self.options.personality == "linux64":
@@ -195,9 +206,18 @@ steps refer to a method in TestPlc or to a step_* module
                 traceback.print_exc()
                 print 'Cannot load config %s -- ignored'%modulename
                 raise
-        # show config
-        if not self.options.quiet:
-            utils.show_test_spec("Test specifications",all_plc_specs)
+        # remember plc IP address(es) if not specified
+        ips_plc_file=open('arg-ips-plc','w')
+        for plc_spec in all_plc_specs:
+            ips_plc_file.write("%s\n"%plc_spec['PLC_API_HOST'])
+        ips_plc_file.close()
+        # ditto for nodes
+        ips_node_file=open('arg-ips-node','w')
+        for plc_spec in all_plc_specs:
+            for site_spec in plc_spec['sites']:
+                for node_spec in site_spec['nodes']:
+                    ips_node_file.write("%s\n"%node_spec['node_fields']['hostname'])
+        ips_node_file.close()
         # build a TestPlc object from the result, passing options
         for spec in all_plc_specs:
             spec['disabled'] = False
@@ -213,7 +233,7 @@ steps refer to a method in TestPlc or to a step_* module
             if not TestPlc.valid_step(step):
                 continue
             force=False
-            # is it a forcedstep
+            # is it a forced step
             if step.find("force_") == 0:
                 step=step.replace("force_","")
                 force=True
@@ -261,7 +281,35 @@ steps refer to a method in TestPlc or to a step_* module
 
                 # run the step
                 time=strftime("%Y-%m-%d-%H-%M")
-                if not spec['disabled'] or force:
+                if not spec['disabled'] or force or self.options.interactive:
+                    skip_step=False
+                    if self.options.interactive:
+                        prompting=True
+                        while prompting:
+                            msg="Run step %s on %s [r](un)/d(ry_run)/s(kip)/q(uit) ? "%(stepname,plcname)
+                            answer=raw_input(msg).strip().lower() or "r"
+                            answer=answer[0]
+                            if answer in ['s','n']:     # skip/no/next
+                                print '%s on %s skipped'%(stepname,plcname)
+                                prompting=False
+                                skip_step=True
+                            elif answer in ['q','b']:   # quit/bye
+                                print 'Exiting'
+                                return
+                            elif answer in ['d']:       # dry_run
+                                dry_run=self.options.dry_run
+                                self.options.dry_run=True
+                                obj.options.dry_run=True
+                                obj.apiserver.set_dry_run(True)
+                                step_result=method(obj)
+                                print 'dry_run step ->',step_result
+                                self.options.dry_run=dry_run
+                                obj.options.dry_run=dry_run
+                                obj.apiserver.set_dry_run(dry_run)
+                            elif answer in ['r','y']:   # run/yes
+                                prompting=False
+                    if skip_step:
+                        continue
                     try:
                         force_msg=""
                         if force: force_msg=" (forced)"