Index: Makefile
==================================================================
--- Makefile
+++ Makefile
@@ -268,11 +268,11 @@
$(PREFIX)/bin/nbfind : utils/nbfind
$(INSTALL) $< $@
chmod a+x $@
-$(PREFIX)/bin/loadrunner : utils/loadrunner
+$(PREFIX)/bin/mtrunner : utils/mtrunner
$(INSTALL) $< $@
chmod a+x $@
# $(PREFIX)/bin/refdb : refdb
# $(INSTALL) $< $@
@@ -302,11 +302,11 @@
$(INSTALL) dboard $(PREFIX)/bin/.$(ARCHSTR)/dboard
install : $(PREFIX)/bin/.$(ARCHSTR) $(PREFIX)/bin/.$(ARCHSTR)/mtest $(PREFIX)/bin/megatest \
$(PREFIX)/bin/.$(ARCHSTR)/dboard $(PREFIX)/bin/dashboard $(HELPERS) $(PREFIX)/bin/nbfake \
$(PREFIX)/bin/.$(ARCHSTR)/mtexec $(PREFIX)/bin/mtexec $(PREFIX)/bin/serialize-env \
- $(PREFIX)/bin/nbfind $(PREFIX)/bin/loadrunner $(PREFIX)/bin/viewscreen $(PREFIX)/bin/mt_xterm \
+ $(PREFIX)/bin/nbfind $(PREFIX)/bin/mtrunner $(PREFIX)/bin/viewscreen $(PREFIX)/bin/mt_xterm \
$(PREFIX)/share/docs/megatest_manual.html $(PREFIX)/bin/remrun \
$(PREFIX)/share/docs/megatest_manual.html $(PREFIX)/bin/remrun $(PREFIX)/bin/mtutil \
$(PREFIX)/bin/tcmt $(PREFIX)/share/db/mt-pg.sql \
$(PREFIX)/share/js/jquery-3.1.0.slim.min.js
# $(PREFIX)/bin/.$(ARCHSTR)/ndboard
Index: NOTES
==================================================================
--- NOTES
+++ NOTES
@@ -158,5 +158,9 @@
INFO: (0) Server shutdown complete. Exiting
Start: 0 at Sun Apr 28 22:18:25 MST 2013
Max: 52 at Sun Apr 28 23:06:59 MST 2013
End: 6 at Sun Apr 28 23:47:51 MST 2013
+
+========================================================================
+
+
Index: archive.scm
==================================================================
--- archive.scm
+++ archive.scm
@@ -90,11 +90,11 @@
(pscript-cmd (conc pscript " " testsuite-name " " target " " run-name " " test-name))
(apath (if pscript
(handle-exceptions
exn
(begin
- (debug:print 0 "ERROR: script \"" pscript-cmd "\" failed to run properly.")
+ (debug:print 0 *default-log-port* "ERROR: script \"" pscript-cmd "\" failed to run properly.")
(exit 1))
(with-input-from-pipe
pscript-cmd
read-line))
#f)) ;; this is the user-calculated archive path
@@ -116,13 +116,16 @@
;; (allocation-id (rmt:archive-allocate-testsuite/area-to-block block-id testsuite-name area-key)))
(if block-id ;; (and block-id allocation-id)
(let ((res (cons block-id archive-path)))
(hash-table-set! blockid-cache key res)
res)
- #f))
- #f)) ;; no best disk found
- )))
+ (begin
+ (debug:print 0 *default-log-port* "WARNING: no disk found for " target ", " run-name ", " test-name ", archive-path=" archive-path)
+ #f)))
+ (begin
+ (debug:print 0 *default-log-port* "WARNING: no disk found for " target ", " run-name ", " test-name ", block-id=" block-id)
+ #f)))))) ;; no best disk found
;; archive - run bup
;;
;; 1. create the bup dir if not exists
;; 2. start the du of each directory
@@ -182,13 +185,11 @@
partial-path-index)
#f))
;; we need our archive dir checked for every test to enable folks who want to store other ways.
(archive-info (archive:allocate-new-archive-block blockid-cache *toppath* tsname min-space target run-name test-name))
(archive-dir (if archive-info (cdr archive-info) #f))
- (archive-id (if archive-info (car archive-info) -1))
-
- )
+ (archive-id (if archive-info (car archive-info) -1)))
(if (not archive-dir) ;; no archive disk found, this is fatal
(begin
(debug:print 0 *default-log-port* "FATAL: No archive disks found. Please add disks with at least "
min-space " MB space to the [archive-disks] section of megatest.config")
@@ -246,11 +247,20 @@
(arch-group (hash-table-ref arch-groups test-base))
(arch-info (car arch-group)) ;; don't know yet how this will work, can I get more than one possibility?
(archive-id (car arch-info))
(archive-dir (cdr arch-info)))
(debug:print 0 *default-log-port* "Processing disk-group " test-base)
- (let* ((test-paths (hash-table-ref disk-groups test-base)))
+ (let* ((test-paths-in (hash-table-ref disk-groups test-base))
+ (test-paths (if (args:get-arg "-include")
+ (let ((subpaths (string-split (args:get-arg "-include") ",")))
+ (apply append
+ (map (lambda (p)
+ (map (lambda (subp)
+ (conc p "/" subp))
+ subpaths))
+ test-paths-in)))
+ test-paths-in)))
(if (not (common:file-exists? archive-dir))
(create-directory archive-dir #t))
(case archiver
((bup) ;; Archive using bup
(let* ((bup-init-params (list "-d" archive-dir "init"))
@@ -300,12 +310,14 @@
(for-each
(lambda (test-dat)
(let ((test-id (db:test-get-id test-dat))
(run-id (db:test-get-run_id test-dat)))
(rmt:test-set-archive-block-id run-id test-id archive-id)
- (if (member archive-command '("save-remove"))
- (runs:remove-test-directory test-dat 'archive-remove))))
+ (if (member (symbol->string archive-command) '("save-remove"))
+ (begin
+ (debug:print-info 0 *default-log-port* "remove testdat")
+ (runs:remove-test-directory test-dat 'archive-remove)))))
(hash-table-ref test-groups test-base)))))
(hash-table-keys disk-groups))
#t))
(define (archive:bup-restore archive-command run-id run-name tests rp-mutex bup-mutex) ;; move the getting of archive space down into the below block so that a single run can
@@ -343,11 +355,14 @@
(archive-block-id (db:test-get-archived test-dat))
(archive-block-info (rmt:test-get-archive-block-info archive-block-id))
(archive-path (if (vector? archive-block-info)
(vector-ref archive-block-info 2) ;; look in db.scm for test-get-archive-block-info for the vector record info
#f)) ;; no archive found?
- (archive-internal-path (conc (common:get-testsuite-name) "-" run-id "/latest/" test-partial-path)))
+ (archive-internal-path (conc (common:get-testsuite-name) "-" run-id "/latest/" test-partial-path))
+ (include-paths (args:get-arg "-include"))
+ (exclude-pattern (args:get-arg "-exclude-rx"))
+ (exclude-file (args:get-arg "-exclude-rx-from")))
;; some sanity checks, move an existing path out of the way - iif it is not a toplevel with children
;;
(if (and (not toplevel/children) ;; special handling needed for toplevel with children
prev-test-physical-path
@@ -386,6 +401,90 @@
(run-n-wait bup-exe params: bup-restore-params print-cmd: #f)
;; (mutex-unlock! bup-mutex)
(mt:test-set-state-status-by-id run-id test-id "COMPLETED" #f #f)))
(debug:print-error 0 *default-log-port* "No archive path in the record for run-id=" run-id " test-id=" test-id))))
(filter vector? tests))))
-
+
+(define (common:get-youngest-test tests)
+ (if (null? tests)
+ #f
+ (let ((res #f))
+ (for-each
+ (lambda (test-dat)
+ (let ((event-time (db:test-get-event_time test-dat)))
+ (if (or (not res)
+ (> event-time (db:test-get-event_time res)))
+ (set! res test-dat))))
+ tests)
+ res)))
+
+;; from an archive get a specific path - works ONLY with bup for now
+;;
+(define (archive:bup-get-data archive-command run-id-in run-name-in tests rp-mutex bup-mutex)
+ (if (null? tests)
+ (debug:print-info 0 *default-log-port* "get-data called with no matching tests to operate on.")
+
+ (let* ((bup-exe (or (configf:lookup *configdat* "archive" "bup") "bup"))
+ (linktree (common:get-linktree)) ;; (configf:lookup *configdat* "setup" "linktree")))
+ ;; (test-dat (common:get-youngest-test tests))
+ (destpath (args:get-arg "-dest")))
+ (cond
+ ((null? tests)
+ (debug:print-error 0 *default-log-port*
+ "No test matching provided target, runname pattern and test pattern found."))
+ ((file-exists? destpath)
+ (debug:print-error 0 *default-log-port*
+ "Destination path alread exists! Please remove it before running get."))
+ (else
+ (let loop ((rem-tests tests))
+ (let* ((test-dat (common:get-youngest-test rem-tests))
+ (item-path (db:test-get-item-path test-dat))
+ (test-name (db:test-get-testname test-dat))
+ (test-id (db:test-get-id test-dat))
+ (run-id (db:test-get-run_id test-dat))
+ (run-name (rmt:get-run-name-from-id run-id))
+ (keyvals (rmt:get-key-val-pairs run-id))
+ (target (string-intersperse (map cadr keyvals) "/"))
+
+ (toplevel/children (and (db:test-get-is-toplevel test-dat)
+ (> (rmt:test-toplevel-num-items run-id test-name) 0)))
+ (test-partial-path (conc target "/" run-name "/"
+ (db:test-make-full-name test-name item-path)))
+ ;; note the trailing slash to get the dir inspite of it being a link
+ (test-path (conc linktree "/" test-partial-path))
+ (archive-block-id (db:test-get-archived test-dat))
+ (archive-block-info (rmt:test-get-archive-block-info archive-block-id))
+ (archive-path (if (vector? archive-block-info)
+ (vector-ref archive-block-info 2)
+ #f))
+ (archive-internal-path (conc (common:get-testsuite-name) "-" run-id
+ "/latest/" test-partial-path))
+ (include-paths (args:get-arg "-include"))
+ (exclude-pattern (args:get-arg "-exclude-rx"))
+ (exclude-file (args:get-arg "-exclude-rx-from")))
+
+ (if (and archive-path ;; no point in proceeding if there is no actual archive
+ (not toplevel/children))
+ (begin
+ (let* ((bup-restore-params (append (list "-d" archive-path "restore" "-C" (or destpath "data"))
+ ;; " " ;; What is the empty string for?
+ (if include-paths
+ (map (lambda (p)
+ (conc archive-internal-path "/" p))
+ (string-split include-paths ","))
+ (list archive-internal-path)))))
+ (debug:print-info 0 *default-log-port* "Restoring archived data to " (or destpath "data")
+ " from archive in " archive-path " ... " archive-internal-path)
+ (run-n-wait bup-exe params: bup-restore-params print-cmd: #t)))
+ (let ((new-rem-tests (filter (lambda (tdat)
+ (or (not (eq? (db:test-get-id tdat) test-id))
+ (not (eq? (db:test-get-run_id tdat) run-id))))
+ rem-tests) ))
+ (debug:print-info 0 *default-log-port*
+ "No archive path in the record for run-id=" run-id
+ " test-id=" test-id ", skipping.")
+ (if (null? new-rem-tests)
+ (begin
+ (debug:print-info 0 *default-log-port* "No archives found for " target "/" run-name "...")
+ #f)
+ (loop new-rem-tests)))))))))))
+
ADDED autostuff/.mtutil.scm
Index: autostuff/.mtutil.scm
==================================================================
--- /dev/null
+++ autostuff/.mtutil.scm
@@ -0,0 +1,88 @@
+;; Copyright 2006-2017, Matthew Welland.
+;;
+;; This file is part of Megatest.
+;;
+;; Megatest is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Megatest is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Megatest. If not, see .
+
+(use json)
+(use ducttape-lib)
+
+(define (get-last-runname area-path target)
+ (let* ((run-data (with-input-from-pipe (conc "megatest -list-runs % -target " target " -fields runs:runname,event_time -dumpmode sexpr -start-dir " area-path)
+ read)))
+ (if (or (not run-data)
+ (null? run-data))
+ #f
+ (let* ((name-time (let ((dat (map cdadr (alist-ref target run-data equal?)))) ;; (("runname" . "2017w07.0-0047") ("event_time" . "1487490424"))
+ ;; (print "dat=" dat)
+ (map (lambda (item)
+ (cons (alist-ref "runname" item equal?)
+ (string->number (alist-ref "event_time" item equal?))))
+ dat)))
+ (sorted (sort name-time (lambda (a b)(> (cdr a)(cdr b)))))
+ (last-name (if (null? sorted)
+ #f
+ (caar sorted))))
+ last-name))))
+
+(define (str-first-char->number str)
+ (char->integer (string-ref str 0)))
+
+;; example of how to set up and write target mappers
+;; NOTE: maps a *list* of targets!
+;;
+;; (? target run-name area area-path reason contour mode-patt)
+;;
+(add-target-mapper 'prefix-contour
+ (lambda (runkey area contour)
+ (print "target: " runkey)
+ (list (conc contour "/" runkey))))
+#;(add-target-mapper 'prefix-area-contour
+ (lambda (target run-name area area-path reason contour mode-patt)
+ (conc area "/" contour "/" target)))
+
+(add-runname-mapper 'corporate-ww
+ (lambda (target run-name area area-path reason contour mode-patt)
+ (print "corporate-ww called with: target=" target " run-name=" run-name " area=" area " area-path=" area-path " reason=" reason " contour=" contour " mode-patt=" mode-patt)
+ (let* ((last-name (get-last-runname area-path target))
+ (last-letter (let* ((ch (if (string? last-name)
+ (let ((len (string-length last-name)))
+ (substring last-name (- len 1) len))
+ "a"))
+ (chnum (str-first-char->number ch))
+ (a (str-first-char->number "a"))
+ (z (str-first-char->number "z")))
+ (if (and (>= chnum a)(<= chnum z))
+ chnum
+ #f)))
+ (next-letter (if last-letter
+ (list->string
+ (list
+ (integer->char
+ (+ last-letter 1)))) ;; surely there is an easier way?
+ "a")))
+ ;; (print "last-name: " last-name " last-letter: " last-letter " next-letter: " next-letter)
+ (conc (seconds->wwdate (current-seconds)) next-letter))))
+
+(add-runname-mapper 'auto
+ (lambda (target run-name area area-path reason contour mode-patt)
+ "auto-eh"))
+
+;; run only areas where first letter of area name is "a"
+;;
+(add-area-checker 'first-letter-a
+ (lambda (area target contour)
+ (string-match "^a.*$" area)))
+
+
ADDED autostuff/megatest.config
Index: autostuff/megatest.config
==================================================================
--- /dev/null
+++ autostuff/megatest.config
@@ -0,0 +1,85 @@
+# Copyright 2006-2017, Matthew Welland.
+#
+# This file is part of Megatest.
+#
+# Megatest is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Megatest is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Megatest. If not, see .
+
+## commented out due to a bug in v1.6501 in mtutil
+[fields]
+a text
+b text
+c text
+
+[default]
+# usercode .mtutil.scm
+# areafilter area-to-run
+# targtrans generic-target-translator
+# runtrans generic-runname-translator
+usercode .mtutil.scm
+# areafilter area-to-run
+targtrans prefix-contour-broken
+# runtrans generic-runname-translator
+
+[setup]
+pktsdirs /mfs/home/matt/orion_automation/pkts
+
+[areas]
+
+# path-to-area map-target-script(future, optional)
+# someqa path=../megatestqa/someqa; targtrans=somefunc; areafilter=area-to-run
+# targtrans is name of scheme proc stored in .mtutil.scm, which lives in PWD where mtutil is run
+# the target translator can return: a/target OR (list/of targets/to apply/run)
+# OR #f i.e. run nothing
+
+# ext-tests path=ext-tests; targtrans=prefix-contour;
+
+
+ext path=/mfs/home/matt/automation_areas/megatest/ext-tests; targtrans=prefix-contour
+
+[contours]
+# selector=tag-expr/mode-patt
+quick areas=ext; selector=/QUICKPATT
+# quick2 areafn=check-area; selector=/QUICKPATT
+full areas=ext
+# quick areas=fullrun,ext-tests; selector=QUICKPATT/quick
+# full areas=fullrun,ext-tests; selector=MAXPATT/
+# short areas=fullrun,ext-tests; selector=MAXPATT/
+# all areas=fullrun,ext-tests
+# snazy selector=QUICKPATT/
+
+[nopurpose]
+
+[access]
+ext matt:admin mattw:owner
+
+[accesstypes]
+admin run rerun resume remove set-ss rerun-clean
+owner run rerun resume remove rerun-all
+badguy set-ss
+
+[setup]
+maxload 1.2
+
+[listeners]
+localhost:12345 contact=matt@kiatoa.com
+localhost:54321 contact=matt@kiatoa.com
+
+[listener]
+script nbfake echo
+
+
+[server]
+timeout 1
+
+[include local.config]
ADDED autostuff/runconfigs.config
Index: autostuff/runconfigs.config
==================================================================
--- /dev/null
+++ autostuff/runconfigs.config
@@ -0,0 +1,112 @@
+# Copyright 2006-2017, Matthew Welland.
+#
+# This file is part of Megatest.
+#
+# Megatest is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Megatest is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Megatest. If not, see .
+
+# To get emacs font highlighing in the various megatest configs do this:
+#
+# Install emacs-goodies-el:
+# sudo apt install emacs-goodies-el
+# Add to your ~/.emacs file:
+# (add-to-list 'auto-mode-alist '("config\\'" . conf-space-mode))
+#
+
+# example of a cron entry to run sync using db spec pgdb, with pgdb setting in file local.config
+#
+[a/b/c]
+# all:scheduled:sync cron= 0/5 * * * *;dbdest=pgdb;appendconf=/nfs/phoebe/disk1/home/mfs/matt/.sysmaint/local.config
+# quick:scheduled:sync cron= 0/5 * * * *;dbdest=pgdb;appendconf=/nfs/phoebe/disk1/home/mfs/matt/.sysmaint/local.config
+# fast:scheduled:sync-prepend cron= 0/1 * * * *;dbdest=pgdb;appendconf=/mfs/matt/.sysmaint/local.config
+
+# [scriptinc ./gentargets.sh #{getenv USER}]
+# [v1.23/45/67]
+
+# tip will be replaced with hashkey?
+
+# [%/%/%] doesn't work
+
+[/.*/]
+
+[v1.65/tip/dev]
+# file: files changes since last run trigger new run
+# script: script is called with unix seconds as last parameter (other parameters are preserved)
+#
+# contour:sensetype:action params data
+# commented out for debug
+
+quick:file:run runtrans=auto; glob=/nfs/orion/disk1/mfs_home/home/matt/automation_areas/megatest/*.scm foo.touchme
+# snazy:file:run runtrans=corporate-ww; glob=/home/matt/data/megatest/*.scm
+# short:file:run runtrans=short; glob=/home/matt/data/megatest/*.scm
+
+# script returns change-time (unix epoch), new-target-name, run-name
+#
+# quick:script:run checkfossil = http://www.kiatoa.com/fossils/megatest v1.63;\
+# checkfossil = http://www.kiatoa.com/fossils/megatest_qa trunk
+
+# # fossil based trigger
+# #
+quick:fossil:run http://www.kiatoa.com/fossils/megatest=v1.65;\
+ http://www.kiatoa.com/fossils/megatest_qa=trunk
+
+# field allowed values
+# ----- --------------
+# minute 0-59
+# hour 0-23
+# day of month 1-31
+# month 1-12 (or names, future development)
+# day of week 0-7 (0 or 7 is Sun, or, future development, use names)
+
+# actions:
+# run - run a testsuite
+# clean - clear out runs
+# archive - archive runs
+
+# quick:scheduled:run cron=47 * * * * ;run-name=auto
+# quick:scheduled:archive cron=15 20 * * * ;run-name=%;target=%/%/%
+
+# [%]
+# # every friday at midnight clean "all" tests over 7d
+# all:scheduled:clean cron= 0 0 0 0 5;run-name=%;age=7d
+
+[v1.65/tip/dev]
+# # file: files changes since last run trigger new run
+# # script: script is called with unix seconds as last parameter (other parameters are preserved)
+# #
+# # contour:sensetype:action params data
+# quick:file:run run-name=auto;glob=*.scm
+# quick:file:clean run-name=auto;
+# quick:script:run run-name=auto;script=checkfossil.sh v1.63
+#
+# # field allowed values
+# # ----- --------------
+# # minute 0-59
+# # hour 0-23
+# # day of month 1-31
+# # month 1-12 (or names, future development)
+# # day of week 0-7 (0 or 7 is Sun, or, future development, use names)
+#
+# # actions:
+# # run - run a testsuite
+# # clean - clear out runs
+# # archive - archive runs
+#
+quick:scheduled:run cron=47 * * * * ;run-name=auto
+# quick:scheduled:archive cron=15 20 * * * ;run-name=% ;
+#
+
+[%/%/%]
+# # every friday at midnight clean "all" tests over 7d
+all:scheduled:clean cron= 0 0 0 0 5;run-name=%;age=7d
+#
ADDED autostuff/setup.sh
Index: autostuff/setup.sh
==================================================================
--- /dev/null
+++ autostuff/setup.sh
@@ -0,0 +1,2 @@
+source /opt/chicken/4.13.0_18.04_WW45/setup-chicken4x.sh
+export PATH=/mfs/home/matt/orion_automation/bin:$PATH
Index: common.scm
==================================================================
--- common.scm
+++ common.scm
@@ -484,13 +484,14 @@
(directory-fold
(lambda (file rem)
(handle-exceptions
exn
(begin
- (debug:print-info 0 *default-log-port* "unable to rotate log " file ", probably handled by another process.")
- (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
- (print-call-chain (current-error-port)))
+ (debug:print-info 2 *default-log-port* "unable to rotate log " file ", probably handled by another process, this is safe to ignore.")
+ (debug:print 2 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
+ ;; (print-call-chain (current-error-port)) ;;
+ )
(let* ((fullname (conc "logs/" file))
(mod-time (file-modification-time fullname))
(file-age (- (current-seconds) mod-time)))
(hash-table-set! all-files file mod-time)
(if (or (and (string-match "^.*.log" file)
@@ -691,14 +692,18 @@
;; dot-locking egg seems not to work, using this for now
;; if lock is older than expire-time then remove it and try again
;; to get the lock
;;
(define (common:simple-file-lock fname #!key (expire-time 300))
+ (let ((fmod-time (handle-exceptions
+ ext
+ (current-seconds)
+ (file-modification-time fname))))
(if (common:file-exists? fname)
- (if (> (- (current-seconds)(file-modification-time fname)) expire-time)
+ (if (> (- (current-seconds) fmod-time) expire-time)
(begin
- (handle-exceptions exn #f (delete-file* fname))
+ (handle-exceptions exn #f (delete-file* fname))
(common:simple-file-lock fname expire-time: expire-time))
#f)
(let ((key-string (conc (get-host-name) "-" (current-process-id))))
(with-output-to-file fname
(lambda ()
@@ -708,11 +713,11 @@
(handle-exceptions exn
#f
(with-input-from-file fname
(lambda ()
(equal? key-string (read-line)))))
- #f))))
+ #f)))))
(define (common:simple-file-lock-and-wait fname #!key (expire-time 300))
(let ((end-time (+ expire-time (current-seconds))))
(let loop ((got-lock (common:simple-file-lock fname expire-time: expire-time)))
(if got-lock
@@ -879,10 +884,35 @@
(configf:lookup *configdat* "setup" "testsuite" )
(getenv "MT_TESTSUITE_NAME")
(if (string? *toppath* )
(pathname-file *toppath*)
#f))) ;; (pathname-file (current-directory)))))
+
+;; safe getting of toppath
+(define (common:get-toppath areapath)
+ (or *toppath*
+ (if areapath
+ (begin
+ (set! *toppath* areapath)
+ (setenv "MT_RUN_AREA_HOME" areapath)
+ areapath)
+ #f)
+ (if (getenv "MT_RUN_AREA_HOME")
+ (begin
+ (set! *toppath* (getenv "MT_RUN_AREA_HOME"))
+ *toppath*)
+ #f)
+ ;; last resort, look for megatest.config
+ (let loop ((thepath (realpath ".")))
+ (if (file-exists? (conc thepath "/megatest.config"))
+ thepath
+ (if (equal? thepath "/")
+ (begin
+ (debug:print-error 0 *default-log-port* "Unable to find megatest home directory.")
+ #f)
+ (loop (pathname-directory thepath)))))
+ ))
(define common:get-area-name common:get-testsuite-name)
(define (common:get-db-tmp-area . junk)
(if *db-cache-path*
@@ -1172,11 +1202,23 @@
;;
(define (common:bash-glob instr)
(string-split
(with-input-from-pipe
(conc "/bin/bash -c \"echo " instr "\"")
- read-line)))
+ read-line)))
+
+;;======================================================================
+;; Some safety net stuff
+;;======================================================================
+
+;; return input if it is a list or return null
+(define (common:list-or-null inlst #!key (ovrd #f)(message #f))
+ (if (list? inlst)
+ inlst
+ (begin
+ (if message (debug:print-error 0 *default-log-port* message))
+ (or ovrd '()))))
;;======================================================================
;; T A R G E T S , S T A T E , S T A T U S ,
;; R U N N A M E A N D T E S T P A T T
;;======================================================================
@@ -1277,13 +1319,18 @@
(define (common:get-linktree)
(or (getenv "MT_LINKTREE")
(if *configdat*
(configf:lookup *configdat* "setup" "linktree")
- (if *toppath*
- (conc *toppath* "/lt")
- #f))))
+ #f)
+ (if (or *toppath* (getenv "MT_RUN_AREA_HOME"))
+ (conc (or *toppath* (getenv "MT_RUN_AREA_HOME")) "/lt")
+ #f)
+ (let* ((tp (common:get-toppath #f))
+ (lt (conc tp "/lt")))
+ (if (not tp)(debug:print 0 *default-log-port* "WARNING: cannot calculate best path for linktree, using " lt))
+ lt)))
(define (common:args-get-runname)
(let ((res (or (args:get-arg "-runname")
(args:get-arg ":runname")
(getenv "MT_RUNNAME"))))
@@ -1672,37 +1719,47 @@
;; cpu-load))
;; get values from cached info from dropping file in logs dir
;; e.g. key is host and dtype is normalized-load
;;
-(define (common:get-cached-info key dtype #!key (age 5))
- (let* ((fullpath (conc *toppath* "/.sysdata/" key "-" dtype ".log")))
- (if (and (file-exists? fullpath)
- (file-read-access? fullpath))
- (handle-exceptions
- exn
- #f
- (debug:print 2 *default-log-port* "reading file " fullpath)
- (let ((real-age (- (current-seconds)(file-change-time fullpath))))
- (if (< real-age age)
- (with-input-from-file fullpath read)
- (begin
- (debug:print 1 *default-log-port* "file " fullpath " is too old (" real-age" seconds) to trust, skipping reading it")
- #f))))
- (begin
- (debug:print 2 *default-log-port* "not reading file " fullpath)
- #f))))
-
-(define (common:write-cached-info key dtype dat)
- (let* ((fulldir (conc *toppath* "/.sysdata"))
- (fullpath (conc fulldir "/" key "-" dtype ".log")))
- (if (not (file-exists? fulldir))(create-directory fulldir #t))
- (handle-exceptions
- exn
- #f
- (with-output-to-file fullpath (lambda ()(pp dat))))))
-
+(define (common:get-cached-info key dtype #!key (age 10))
+ (if *toppath*
+ (let* ((fullpath (conc *toppath* "/.sysdata/" key "-" dtype ".log")))
+ (if (and (file-exists? fullpath)
+ (file-read-access? fullpath))
+ (handle-exceptions
+ exn
+ #f
+ (debug:print 2 *default-log-port* "reading file " fullpath)
+ (let ((real-age (- (current-seconds)(file-change-time fullpath))))
+ (if (< real-age age)
+ (handle-exceptions
+ exn
+ (begin
+ (debug:print-info 1 *default-log-port* " removing bad file " fullpath)
+ (delete-file* fullpath)
+ #f)
+ (with-input-from-file fullpath read))
+ (begin
+ (debug:print-info 2 *default-log-port* "file " fullpath " is too old (" real-age" seconds) to trust, skipping reading it")
+ #f))))
+ (begin
+ (debug:print 2 *default-log-port* "not reading file " fullpath)
+ #f)))
+ #f))
+
+(define (common:write-cached-info key dtype dat)
+ (if *toppath*
+ (let* ((fulldir (conc *toppath* "/.sysdata"))
+ (fullpath (conc fulldir "/" key "-" dtype ".log")))
+ (if (not (file-exists? fulldir))(create-directory fulldir #t))
+ (handle-exceptions
+ exn
+ #f
+ (with-output-to-file fullpath (lambda ()(pp dat)))))
+ #f))
+
;; get cpu load by reading from /proc/loadavg, return all three values
;;
(define (common:get-cpu-load remote-host)
(handle-exceptions
exn
@@ -1935,30 +1992,38 @@
(or (common:get-cached-info actual-host "num-cpus" age: (+ 2592000 (random 3600))) ;; hosts had better not be changing the number of cpus too often!
(let* ((proc (lambda ()
(let loop ((numcpu 0)
(inl (read-line)))
(if (eof-object? inl)
- (begin
- (common:write-cached-info actual-host "num-cpus" numcpu)
- numcpu)
+ (if (> numcpu 0)
+ numcpu
+ #f) ;; if zero return #f so caller knows that things are not working
(loop (if (string-match "^processor\\s+:\\s+\\d+$" inl)
(+ numcpu 1)
numcpu)
(read-line))))))
(result (if remote-host
(with-input-from-pipe
(conc "ssh " remote-host " cat /proc/cpuinfo")
proc)
(with-input-from-file "/proc/cpuinfo" proc))))
- (common:write-cached-info actual-host "num-cpus" result)
+ (if (and (number? result)
+ (> result 0))
+ (common:write-cached-info actual-host "num-cpus" result))
result))))
;; wait for normalized cpu load to drop below maxload
;;
-(define (common:wait-for-normalized-load maxload msg remote-host)
+(define (common:wait-for-normalized-load maxload msg remote-host #!optional (rem-tries 5))
(let ((num-cpus (common:get-num-cpus remote-host)))
- (common:wait-for-cpuload maxload num-cpus 15 msg: msg remote-host: remote-host)))
+ (if num-cpus
+ (common:wait-for-cpuload maxload num-cpus 15 msg: msg remote-host: remote-host)
+ (begin
+ (thread-sleep! (random 60)) ;; we failed to get num cpus. wait a bit and try again
+ (if (> rem-tries 0)
+ (common:wait-for-normalized-load maxload msg remote-host (- rem-tries 1))
+ #f)))))
;; DO NOT CALL THIS DIRECTLY. It is called from common:wait-for-normalized-load
;;
(define (common:wait-for-cpuload maxload-in numcpus-in waitdelay #!key (count 1000) (msg #f)(remote-host #f)(force-maxload #f))
(let* ((loadavg (common:get-cpu-load remote-host))
@@ -1965,18 +2030,22 @@
(numcpus (if (<= 1 numcpus-in) ;; not possible to have zero. If we get 1, it's possible that we got the previous default, and we should check again
(common:get-num-cpus remote-host)
numcpus-in))
(maxload (if force-maxload
maxload-in
- (max maxload-in 0.5))) ;; so maxload must be greater than 0.5 for now BUG - FIXME?
+ (if (number? maxload-in)
+ (max maxload-in 0.5)
+ 0.5))) ;; so maxload must be greater than 0.5 for now BUG - FIXME?
(first (car loadavg))
(next (cadr loadavg))
(adjload (* maxload (max 1 numcpus))) ;; possible bug where numcpus (or could be maxload) is zero, crude fallback is to at least use 1
(loadjmp (- first next))
(adjwait (min (+ 300 (random 10)) (abs (* (+ (random 10)(/ (- 1000 count) 10) waitdelay) (- first adjload) )) )));; add some randomness to the time to break any alignment where netbatch dumps many jobs to machines simultaneously
- (debug:print-info 1 *default-log-port* "Checking cpuload on " (or remote-host "localhost") ", maxload: " maxload
- ", load: " first ", adjload: " adjload ", loadjmp: " loadjmp)
+ ;; let's let the user know once in a long while that load checking is happening but not constantly report it
+ (if (> (random 100) 75) ;; about 25% of the time
+ (debug:print-info 1 *default-log-port* "Checking cpuload on " (or remote-host "localhost") ", maxload: " maxload
+ ", load: " first ", adjload: " adjload ", loadjmp: " loadjmp))
(cond
((and (> first adjload)
(> count 0))
(debug:print-info 0 *default-log-port* "server start delayed " adjwait " seconds due to load " first " exceeding max of " adjload " on server " (or remote-host (get-host-name)) " (normalized load-limit: " maxload ") " (if msg msg ""))
(thread-sleep! adjwait)
@@ -2084,12 +2153,13 @@
;; check space in dbdir and in megatest dir
;; returns: ok/not dbspace required-space
;;
(define (common:check-db-dir-space)
(let* ((required (string->number
+ ;; default is 1GB (or actually a billion bytes) This is the number of 1 kB blocks.
(or (configf:lookup *configdat* "setup" "dbdir-space-required")
- "100000")))
+ "1000000")))
(dbdir (common:get-db-tmp-area)) ;; (db:get-dbdir))
(tdbspace (common:check-space-in-dir dbdir required))
(mdbspace (common:check-space-in-dir *toppath* required)))
(sort (list tdbspace mdbspace) (lambda (a b)
(< (cadr a)(cadr b))))))
@@ -2108,13 +2178,16 @@
(exit 1)))))
;; paths is list of lists ((name path) ... )
;;
(define (common:get-disk-with-most-free-space disks minsize)
- (let ((best #f)
+ (let* ((best #f)
(bestsize 0)
- (min-inodes (or (string->number (if (configf:lookup *configdat* "setup" "min_inodes") (configf:lookup *configdat* "setup" "min_inodes") "0")) 0)))
+ (default-min-inodes-string "1000000")
+ (default-min-inodes (string->number default-min-inodes-string))
+ (min-inodes (or (string->number (if (configf:lookup *configdat* "setup" "min_inodes") (configf:lookup *configdat* "setup" "min_inodes") default-min-inodes-string)) default-min-inodes)))
+
(for-each
(lambda (disk-num)
(let* ((dirpath (cadr (assoc disk-num disks)))
(freespc (cond
((not (directory? dirpath))
@@ -2146,10 +2219,11 @@
-1)
(else
(get-free-inodes dirpath))))
;;(free-inodes (get-free-inodes dirpath))
)
+ (debug:print 2 *default-log-port* "INFO: disk " disk-num " path " dirpath " free space " freespc " free inodes " free-inodes)
(if (and (> freespc bestsize)(> free-inodes min-inodes ))
(begin
(set! best (cons disk-num dirpath))
(set! bestsize freespc)))
;;(print "Processing: " disk-num " bestsize: " bestsize " best: " best " freespc: " freespc " min-inodes: " min-inodes " free-inodes: " free-inodes)
Index: configf.scm
==================================================================
--- configf.scm
+++ configf.scm
@@ -20,11 +20,11 @@
;;======================================================================
;; Config file handling
;;======================================================================
-(use regex regex-case) ;; directory-utils)
+(use regex regex-case matchable) ;; directory-utils)
(declare (unit configf))
(declare (uses process))
(declare (uses env))
(declare (uses keys))
@@ -118,14 +118,15 @@
" (let ((extra \"" cmd "\"))"
" (conc (or *toppath* (get-environment-variable \"MT_RUN_AREA_HOME\"))"
" (if (string-null? extra) \"\" \"/\")"
" extra)))"))
((get g)
- (let* ((parts (string-split cmd))
- (sect (car parts))
- (var (cadr parts)))
- (conc "(lambda (ht)(configf:lookup ht \"" sect "\" \"" var "\"))")))
+ (match (string-split cmd)
+ ((sect var)(conc "(lambda (ht)(configf:lookup ht \"" sect "\" \"" var "\"))"))
+ (else
+ (debug:print-error 0 *default-log-port* "#{get ...} used with only one parameter, \"" cmd "\", two needed.")
+ "(lambda (ht) #f)")))
((runconfigs-get rget) (conc "(lambda (ht)(runconfigs-get ht \"" cmd "\"))"))
;; ((rget) (conc "(lambda (ht)(runconfigs-get ht \"" cmd "\"))"))
(else "(lambda (ht)(print \"ERROR\") \"ERROR\")"))))
;; (print "fullcmd=" fullcmd)
(handle-exceptions
Index: db.scm
==================================================================
--- db.scm
+++ db.scm
@@ -1464,20 +1464,18 @@
(set! res id))
db
"SELECT id FROM archive_blocks WHERE archive_disk_id=? AND disk_path=?;"
bdisk-id archive-path)
(if res ;; record exists, update du if applicable and return res
- (begin
- (if du (sqlite3:execute db "UPDATE archive_blocks SET last_du=?,last_du_time=(strftime('%s','now'))
+ (if du (sqlite3:execute db "UPDATE archive_blocks SET last_du=?,last_du_time=(strftime('%s','now'))
WHERE archive_disk_id=? AND disk_path=?;"
- bdisk-id archive-path du))
- res)
+ bdisk-id archive-path du))
(begin
(sqlite3:execute db "INSERT OR REPLACE INTO archive_blocks (archive_disk_id,disk_path,last_du)
VALUES (?,?,?);"
bdisk-id archive-path (or du 0))
- (db:archive-register-block-name dbstruct bdisk-id archive-path du: du)))
+ (set! res (db:archive-register-block-name dbstruct bdisk-id archive-path du: du))))
(stack-push! (dbr:dbstruct-dbstack dbstruct) dbdat)
res))
;; The "archived" field in tests is overloaded; 0 = not archived, > 0 archived in block with given id
@@ -1614,10 +1612,30 @@
;; given a launch delay (minimum time from last launch) return amount of time to wait
;;
;; (define (db:launch-delay-left dbstruct run-id launch-delay)
+
+
+(define (db:get-status-from-final-status-file run-dir)
+ (let (
+ (infile (conc run-dir "/.final-status")))
+
+ ;; first verify we are able to write the output file
+ (if (not (file-read-access? infile))
+ (begin
+ (debug:print 0 *default-log-port* "ERROR: cannot read " infile)
+ (debug:print 0 *default-log-port* "ERROR: run-dir is " run-dir)
+ #f
+ )
+ (with-input-from-file infile read-lines)
+ )
+ )
+)
+
+
+
;; select end_time-now from
;; (select testname,item_path,event_time+run_duration as
;; end_time,strftime('%s','now') as now from tests where state in
;; ('RUNNING','REMOTEHOSTSTART','LAUNCHED'));
@@ -1624,10 +1642,12 @@
(define (db:find-and-mark-incomplete dbstruct run-id ovr-deadtime)
(let* ((incompleted '())
(oldlaunched '())
(toplevels '())
+ ;; The default running-deadtime is 720 seconds = 12 minutes.
+ ;; "(running-deadtime-default (+ server-start-allowance (* 2 launch-monitor-period)))" = 200 + (2 * (200 + 30 + 30))
(deadtime-trim (or ovr-deadtime (configf:lookup-number *configdat* "setup" "deadtime")))
(server-start-allowance 200)
(server-overloaded-budget 200)
(launch-monitor-off-time (or (configf:lookup-number *configdat* "setup" "test-stats-update-period") 30))
(launch-monitor-on-time-budget 30)
@@ -1635,10 +1655,13 @@
(remotehoststart-deadtime-default (+ server-start-allowance server-overloaded-budget 30))
(remotehoststart-deadtime (or deadtime-trim remotehoststart-deadtime-default))
(running-deadtime-default (+ server-start-allowance (* 2 launch-monitor-period)))
(running-deadtime (or deadtime-trim running-deadtime-default)) ;; two minutes (30 seconds between updates, this leaves 3x grace period)
)
+ (debug:print-info 4 *default-log-port* "running-deadtime = " running-deadtime)
+ (debug:print-info 4 *default-log-port* "deadtime-trim = " deadtime-trim)
+
(db:with-db
dbstruct #f #f
(lambda (db)
;; in RUNNING or REMOTEHOSTSTART for more than 10 minutes
;;
@@ -1657,12 +1680,13 @@
(debug:print-info 0 *default-log-port* "Found old toplevel test in RUNNING state, test-id=" test-id))
(begin
(set! incompleted (cons (list test-id run-dir uname testname item-path run-id) incompleted))
(debug:print-info 0 *default-log-port* "Found old test in RUNNING state, test-id=" test-id" exceeded running-deadtime "running-deadtime" now="(current-seconds)" event-time="event-time" run-duration="run-duration))))
db
+
"SELECT id,rundir,uname,testname,item_path,event_time,run_duration FROM tests WHERE run_id=? AND (strftime('%s','now') - event_time) > (run_duration + ?) AND state IN ('RUNNING');"
- run-id running-deadtime)
+ run-id running-deadtime) ;; default time 720 seconds
(sqlite3:for-each-row
(lambda (test-id run-dir uname testname item-path event-time run-duration)
(if (and (equal? uname "n/a")
@@ -1674,11 +1698,11 @@
(begin
(debug:print-info 0 *default-log-port* "Found old test in REMOTEHOSTSTART state, test-id=" test-id" exceeded running-deadtime "running-deadtime" now="(current-seconds)" event-time="event-time" run-duration="run-duration)
(set! incompleted (cons (list test-id run-dir uname testname item-path run-id) incompleted)))))
db
"SELECT id,rundir,uname,testname,item_path,event_time,run_duration FROM tests WHERE run_id=? AND (strftime('%s','now') - event_time) > (run_duration + ?) AND state IN ('REMOTEHOSTSTART');"
- run-id remotehoststart-deadtime)
+ run-id remotehoststart-deadtime) ;; default time 230 seconds
;; in LAUNCHED for more than one day. Could be long due to job queues TODO/BUG: Need override for this in config
;;
;; (db:delay-if-busy dbdat)
(sqlite3:for-each-row
@@ -1708,16 +1732,37 @@
;; incompleted))
(min-incompleted-ids (map car incompleted)) ;; do 'em all
(all-ids (append min-incompleted-ids (map car oldlaunched))))
(if (> (length all-ids) 0)
(begin
+ ;; (launch:is-test-alive "localhost" 435)
(debug:print 0 *default-log-port* "WARNING: Marking test(s); " (string-intersperse (map conc all-ids) ", ") " as DEAD")
(for-each
- (lambda (test-id)
- (db:set-state-status-and-roll-up-items dbstruct run-id test-id 'foo "COMPLETED" "DEAD" "Test stopped responding while in RUNNING or REMOTEHOSTSTART; presumed dead."))
- ;;(db:test-set-state-status dbstruct run-id test-id "COMPLETED" "DEAD" "Test stopped responding while in RUNNING or REMOTEHOSTSTART; presumed dead.")) ;; fix for one aspect of Randy's ticket 1405717332 ;; TODO - fix problem where test goes to COMPLETED/DEAD while in progress, only later to go to COMPLETED/PASS. ref ticket 220546828
- all-ids))))))))
+ (lambda (test-id)
+ (let* (;; (run-dir (db:test-get-rundir-from-test-id dbstruct run-id test-id))
+ (tinfo (db:get-test-info-by-id dbstruct run-id test-id))
+ (run-dir (db:test-get-rundir tinfo))
+ (host (db:test-get-host tinfo))
+ (pid (db:test-get-process_id tinfo))
+ (result (db:get-status-from-final-status-file run-dir)))
+ (if (and (list? result) (> (length result) 1) (equal? "PASS" (cadr result)) (equal? "COMPLETED" (car result)))
+ (begin
+ (debug:print 0 *default-log-port* "INFO: test " test-id " actually passed, so marking PASS not DEAD")
+ (db:set-state-status-and-roll-up-items dbstruct run-id test-id 'foo "COMPLETED" "PASS"
+ "Test stopped responding but it has PASSED; marking it PASS in the DB."))
+ (let ((is-alive (launch:is-test-alive host pid)))
+ (if is-alive
+ (debug:print 0 *default-log-port* "INFO: test " test-id " on host " host " has a process on pid " pid ", NOT setting to DEAD.")
+ (begin
+ (debug:print 0 *default-log-port* "INFO: test " test-id " final state/status is not COMPLETED/PASS. It is " result)
+ (db:set-state-status-and-roll-up-items dbstruct run-id test-id 'foo "COMPLETED" "DEAD"
+ "Test stopped responding while in RUNNING or REMOTEHOSTSTART; presumed dead.")))))))
+ all-ids)
+ ;;call end of eud of run detection for posthook
+ (launch:end-of-run-check run-id)
+ )))))))
+
;; ALL REPLACED BY THE BLOCK ABOVE
;;
;; (sqlite3:execute
;; db
Index: docs/manual/howto.txt
==================================================================
--- docs/manual/howto.txt
+++ docs/manual/howto.txt
@@ -13,196 +13,213 @@
// You should have received a copy of the GNU General Public License
// along with Megatest. If not, see .
//
// Copyright 2006-2012, Matthew Welland.
-How To Do Things
-----------------
-
-Process Runs
-~~~~~~~~~~~~
-
-Remove Runs
-^^^^^^^^^^^
-
-From the dashboard click on the button (PASS/FAIL...) for one of the tests. From the test control panel that
-comes up push the clean test button. The command field will be prefilled with a template command for removing
-that test. You can edit the command, for example change the argument to -testpatt to "%" to remove all tests.
-
-.Remove the test diskperf and all it's items
-----------------
-megatest -remove-runs -target ubuntu/nfs/none -runname ww28.1a -testpatt diskperf/% -v
-----------------
-
-.Remove all tests for all runs and all targets
-----------------
-megatest -remove-runs -target %/%/% -runname % -testpatt % -v
-----------------
-
-Archive Runs
-^^^^^^^^^^^^
-
-Megatest supports using the bup backup tool (https://bup.github.io/) to archive your tests for efficient storage
-and retrieval. Archived data can be rapidly retrieved if needed. The metadata for the run (PASS/FAIL status, run
-durations, time stamps etc.) are all preserved in the megatest database.
-
-For setup information see the Archiving topic in the reference section of this manual.
-
-To Archive
-++++++++++
-
-Hint: use the test control panel to create a template command by pushing the "Archive Tests" button.
-
-.Archive a full run
-----------------
-megatest -target ubuntu/nfs/none -runname ww28.1a -archive save-remove -testpatt %
-----------------
-
-To Restore
-++++++++++
-
-.Retrieve a single test
-----------------
-megatest -target ubuntu/nfs/none -runname ww28.1a -archive restore -testpatt diskperf/%
-----------------
-
-Hint: You can browse the archive using bup commands directly.
-
-----------------
-bup -d /path/to/bup/archive ftp
-----------------
-
-Submit jobs to Host Types based on Test Name
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.In megatest.config
-------------------------
-[host-types]
-general ssh #{getbgesthost general}
-nbgeneral nbjob run JOBCOMMAND -log $MT_LINKTREE/$MT_TARGET/$MT_RUNNAME.$MT_TESTNAME-$MT_ITEM_PATH.lgo
-
-[hosts]
-general cubian xena
-
-[launchers]
-envsetup general
-xor/%/n 4C16G
-% nbgeneral
-
-[jobtools]
-launcher bsub
-# if defined and not "no" flexi-launcher will bypass launcher unless there is no
-# match.
-flexi-launcher yes
-------------------------
-
-Tricks
-------
-
-This section is a compendium of a various useful tricks for debugging,
-configuring and generally getting the most out of Megatest.
-
-Limiting your running jobs
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The following example will limit a test in the jobgroup "group1" to no more than 10 tests simultaneously.
-
-In your testconfig:
-
-----------------
-[test_meta]
-jobgroup group1
-----------------
-
-In your megatest.config:
-
----------------
-[jobgroups]
-group1 10
-custdes 4
----------------
-
-Debugging Tricks
-----------------
-
-Examining The Environment
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Test Control Panel - xterm
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-From the dashboard click on a test PASS/FAIL button. This brings up a test control panel. Aproximately near the center left of the
-window there is a button "Start Xterm". Push this to get an xterm with the full context and environment loaded for that test. You can run
-scripts or ezsteps by copying from the testconfig (hint, load up the testconfig in a separate gvim or emacs window). This is the easiest way
-to debug your tests.
-
-During Config File Processing
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-It is often helpful to know the content of variables in various
-contexts as Megatest does the actions needed to run your tests. A handy technique is to force the startup of an xterm in the context being examined.
-
-For example, if an item list is not being generated as expected you
-can inject the startup of an xterm as if it were an item:
-
-.Original items table
------------------
-[items]
-CELLNAME [system getcellname.sh]
------------------
-
-.Items table modified for debug
------------------
-[items]
-DEBUG [system xterm]
-CELLNAME [system getcellnames.sh]
------------------
-
-When this test is run an xterm will pop up. In that xterm the
-environment is exactly that in which the script "getcellnames.sh"
-would run. You can now debug the script to find out why it isn't
-working as expected.
-
-Organising Your Tests and Tasks
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The default location "tests" for storing tests can be extended by
-adding to your tests-paths section.
-
-----------------------------
-[misc]
-parent #{shell dirname $(readlink -f .)}
-
-[tests-paths]
-1 #{get misc parent}/simplerun/tests
-----------------------------
-
-The above example shows how you can use addition sections in your
-config file to do complex processing. By putting results of relatively
-slow operations into variables the processing of your configs can be
-kept fast.
-
-Alternative Method for Running your Job Script
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-.Directly running job in testconfig
--------------------
-[setup]
-runscript main.csh
--------------------
-
-The runscript method is essentially a brute force way to run scripts where the
-user is responsible for setting STATE and STATUS and managing the details of running a test.
-
-Debugging Server Problems
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Some handy Unix commands to track down issues with servers not
-communicating with your test manager processes. Please put in tickets
-at https://www.kiatoa.com/fossils/megatest if you have problems with
-servers getting stuck.
-
-----------------
-sudo lsof -i
-sudo netstat -lptu
-sudo netstat -tulpn
+How To Do Things
+----------------
+
+Process Runs
+~~~~~~~~~~~~
+
+Remove Runs
+^^^^^^^^^^^
+
+From the dashboard click on the button (PASS/FAIL...) for one of the tests. From the test control panel that
+comes up push the clean test button. The command field will be prefilled with a template command for removing
+that test. You can edit the command, for example change the argument to -testpatt to "%" to remove all tests.
+
+.Remove the test diskperf and all it's items
+----------------
+megatest -remove-runs -target ubuntu/nfs/none -runname ww28.1a -testpatt diskperf/% -v
+----------------
+
+.Remove all tests for all runs and all targets
+----------------
+megatest -remove-runs -target %/%/% -runname % -testpatt % -v
+----------------
+
+Archive Runs
+^^^^^^^^^^^^
+
+Megatest supports using the bup backup tool (https://bup.github.io/) to archive your tests for efficient storage
+and retrieval. Archived data can be rapidly retrieved if needed. The metadata for the run (PASS/FAIL status, run
+durations, time stamps etc.) are all preserved in the megatest database.
+
+For setup information see the Archiving topic in the reference section of this manual.
+
+To Archive
+++++++++++
+
+Hint: use the test control panel to create a template command by pushing the "Archive Tests" button.
+
+.Archive a full run
+----------------
+megatest -target ubuntu/nfs/none -runname ww28.1a -archive save-remove -testpatt %
+----------------
+
+To Restore
+++++++++++
+
+.Retrieve a single test
+----------------
+megatest -target ubuntu/nfs/none -runname ww28.1a -archive restore -testpatt diskperf/%
+----------------
+
+Hint: You can browse the archive using bup commands directly.
+
+----------------
+bup -d /path/to/bup/archive ftp
+----------------
+
+Pass Data from Test to Test
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.To save the data call archive save within your test:
+----------------
+megatest -archive save
+----------------
+
+.To retrieve the data call archive get using patterns as needed
+----------------
+# Put the retrieved data into /tmp
+DESTPATH=/tmp/$USER/$MT_TARGET/$MT_RUN_NAME/$MT_TESTNAME/$MT_ITEMPATH/my_data
+mkdir -p $DESTPATH
+megatest -archive get -runname % -dest $DESTPATH
+----------------
+
+
+Submit jobs to Host Types based on Test Name
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.In megatest.config
+------------------------
+[host-types]
+general ssh #{getbgesthost general}
+nbgeneral nbjob run JOBCOMMAND -log $MT_LINKTREE/$MT_TARGET/$MT_RUNNAME.$MT_TESTNAME-$MT_ITEM_PATH.lgo
+
+[hosts]
+general cubian xena
+
+[launchers]
+envsetup general
+xor/%/n 4C16G
+% nbgeneral
+
+[jobtools]
+launcher bsub
+# if defined and not "no" flexi-launcher will bypass launcher unless there is no
+# match.
+flexi-launcher yes
+------------------------
+
+Tricks
+------
+
+This section is a compendium of a various useful tricks for debugging,
+configuring and generally getting the most out of Megatest.
+
+Limiting your running jobs
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following example will limit a test in the jobgroup "group1" to no more than 10 tests simultaneously.
+
+In your testconfig:
+
+----------------
+[test_meta]
+jobgroup group1
+----------------
+
+In your megatest.config:
+
+---------------
+[jobgroups]
+group1 10
+custdes 4
+---------------
+
+Debugging Tricks
+----------------
+
+Examining The Environment
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Test Control Panel - xterm
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+From the dashboard click on a test PASS/FAIL button. This brings up a test control panel. Aproximately near the center left of the
+window there is a button "Start Xterm". Push this to get an xterm with the full context and environment loaded for that test. You can run
+scripts or ezsteps by copying from the testconfig (hint, load up the testconfig in a separate gvim or emacs window). This is the easiest way
+to debug your tests.
+
+During Config File Processing
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+It is often helpful to know the content of variables in various
+contexts as Megatest does the actions needed to run your tests. A handy technique is to force the startup of an xterm in the context being examined.
+
+For example, if an item list is not being generated as expected you
+can inject the startup of an xterm as if it were an item:
+
+.Original items table
+-----------------
+[items]
+CELLNAME [system getcellname.sh]
+-----------------
+
+.Items table modified for debug
+-----------------
+[items]
+DEBUG [system xterm]
+CELLNAME [system getcellnames.sh]
+-----------------
+
+When this test is run an xterm will pop up. In that xterm the
+environment is exactly that in which the script "getcellnames.sh"
+would run. You can now debug the script to find out why it isn't
+working as expected.
+
+Organising Your Tests and Tasks
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The default location "tests" for storing tests can be extended by
+adding to your tests-paths section.
+
+----------------------------
+[misc]
+parent #{shell dirname $(readlink -f .)}
+
+[tests-paths]
+1 #{get misc parent}/simplerun/tests
+----------------------------
+
+The above example shows how you can use addition sections in your
+config file to do complex processing. By putting results of relatively
+slow operations into variables the processing of your configs can be
+kept fast.
+
+Alternative Method for Running your Job Script
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.Directly running job in testconfig
+-------------------
+[setup]
+runscript main.csh
+-------------------
+
+The runscript method is essentially a brute force way to run scripts where the
+user is responsible for setting STATE and STATUS and managing the details of running a test.
+
+Debugging Server Problems
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Some handy Unix commands to track down issues with servers not
+communicating with your test manager processes. Please put in tickets
+at https://www.kiatoa.com/fossils/megatest if you have problems with
+servers getting stuck.
+
+----------------
+sudo lsof -i
+sudo netstat -lptu
+sudo netstat -tulpn
----------------
Index: docs/manual/megatest_manual.html
==================================================================
--- docs/manual/megatest_manual.html
+++ docs/manual/megatest_manual.html
@@ -900,10 +900,69 @@
sqlite3 database. Megatest has been used with the Intel Netbatch and
lsf (also known as openlava) batch systems and it should be
straightforward to use it with other similar systems.
+
+
+
Overview
+
+
+
Stand-alone Megatest Area
+
A single, stand-alone, Megatest based testsuite or "area" is
+sufficient for most validation, automation and build problems.
+
+
+
+
+
+
Megatest is designed as a distributed or decoupled system. This means
+you can run the areas stand-alone with no additional
+infrastructure. I.e. there are no databases, web servers or other
+centralized resources needed. However as your needs grow you can
+integrate multiple areas into a bigger system.
+
+
Component Descriptions
+
+-
+
+Multi-area dashboard and xterm. A gui (the dashboard) is usually the
+ best option for controlling and launching runs but all operations
+ can also be done from the commandline. Note: The not yet released
+ multi-area dashboard replaces the old dashboard for browsing and
+ controlling runs but for managing a single area the old dashboard
+ works very well.
+
+
+-
+
+Area/testsuite. This is your testsuite or automation definition and
+ consists of the information in megatest.config, runconfigs.config
+ and your testconfigs along with any custom scripting that can’t be
+ done with the native Megatest features.
+
+
+-
+
+If your testsuite or build automation is too large to run on a
+ single instance you can distribute your jobs into a compute server
+ pool. The only current requirements are password-less ssh access and
+ a network filesystem.
+
+
+
+
+
+
+
Full System Architecture
+
+
+
+
+
+
+
Installation
@@ -1393,10 +1452,26 @@
bup -d /path/to/bup/archive ftp
+
+
+
Pass Data from Test to Test
+
+
To save the data call archive save within your test:
+
+
megatest -archive save
+
+
+
To retrieve the data call archive get using patterns as needed
+
+
# Put the retrieved data into /tmp
+DESTPATH=/tmp/$USER/$MT_TARGET/$MT_RUN_NAME/$MT_TESTNAME/$MT_ITEMPATH/my_data
+mkdir -p $DESTPATH
+megatest -archive get -runname % -dest $DESTPATH
+
Submit jobs to Host Types based on Test Name
In megatest.config
@@ -1973,10 +2048,32 @@
A x y
B 1 2
# Yields x/1 y/2
+
+
Or use files
+
+
[itemopts]
+slash path/to/file/with/items
+# or
+space path/to/file/with/items
+
+
+
File format for / delimited
+
+
key1/key2/key3
+val1/val2/val2
+...
+
+
+
File format for space delimited
+
+
key1 key2 key3
+val1 val2 val2
+...
+
Requirements section
Header
@@ -2307,10 +2404,114 @@
Propagate environment to next step
$MT_MEGATEST -env2file .ezsteps/${stepname}
+
+
+
Scripts
+
+
Specifying scripts inline (best used for only simple scripts)
+
+
[scripts]
+loaddb #!/bin/bash
+ sqlite3 $1 <<EOF
+ .mode tabs
+ .import $2 data
+ .q
+ EOF
+
+
The above snippet results in the creation of an executable script
+called "loaddb" in the test directory. NOTE: every line in the script
+must be prefixed with the exact same number of spaces. Lines beginning
+with a # will not work as expected. Currently you cannot indent
+intermediate lines.
+
+
Full example with ezsteps, logpro rules, scripts etc.
+
+
# You can include a common file
+#
+[include #{getenv MT_RUN_AREA_HOME}/global-testconfig.inc]
+
+# Use "var" for a scratch pad
+#
+[var]
+dumpsql select * from data;
+sepstr .....................................
+
+# NOT IMPLEMENTED YET!
+#
+[ezsteps-addendum]
+prescript something.sh
+postscript something2.sh
+
+# Add additional steps here. Format is "stepname script"
+[ezsteps]
+importdb loaddb prod.db prod.sql
+dumpprod dumpdata prod.db "#{get var dumpsql}"
+diff (echo "prod#{get var sepstr}test";diff --side-by-side \
+ dumpprod.log reference.log ;echo DIFFDONE)
+
+[scripts]
+loaddb #!/bin/bash
+ sqlite3 $1 <<EOF
+ .mode tabs
+ .import $2 data
+ .q
+ EOF
+
+dumpdata #!/bin/bash
+ sqlite3 $1 <<EOF
+ .separator ,
+ $2
+ .q
+ EOF
+
+# Test requirements are specified here
+[requirements]
+waiton setup
+priority 0
+
+# Iteration for your test is controlled by the items section
+# The complicated if is needed to allow processing of the config for the dashboard when there are no actual runs.
+[items]
+THINGNAME [system generatethings.sh | sort -u]
+
+# Logpro rules for each step can be captured here in the testconfig
+# note: The ;; after the stepname and the leading whitespace are required
+#
+[logpro]
+inputdb ;;
+ (expect:ignore in "LogFileBody" < 99 "Ignore error in comments" #/^\/\/.*error/)
+ (expect:warning in "LogFileBody" = 0 "Any warning" #/warn/)
+ (expect:required in "LogFileBody" > 0 "Some data found" #/^[a-z]{3,4}[0-9]+_r.*/)
+
+diff ;;
+ (expect:ignore in "LogFileBody" < 99 "Ignore error in comments" #/^\/\/.*error/)
+ (expect:warning in "LogFileBody" = 0 "Any warning" #/warn/)
+ (expect:error in "LogFileBody" = 0 "< or > indicate missing entry" (list #/(<|>)/ #/error/i))
+ (expect:error in "LogFileBody" = 0 "Difference in data" (list #/\s+\|\s+/ #/error/i))
+ (expect:required in "LogFileBody" > 0 "DIFFDONE Marker found" #/DIFFDONE/)
+ (expect:required in "LogFileBody" > 0 "Some things found" #/^[a-z]{3,4}[0-9]+_r.*/)
+
+# NOT IMPLEMENTED YET!
+#
+## Also: enhance logpro to take list of command files: file1,file2...
+[waivers]
+createprod{target=%78/%/%/%} ;;
+ (disable:required "DIFFDONE Marker found")
+ (disable:error "Some error")
+ (expect:waive in "LogFileBody" < 99 "Waive if failed due to version" #/\w+3\.6.*/)
+
+# test_meta is a section for storing additional data on your test
+[test_meta]
+author matt
+owner matt
+description Compare things
+tags tagone,tagtwo
+reviewed never
+
Triggers
In your testconfig or megatest.config triggers can be specified
@@ -2990,10 +3191,10 @@