5353# - networks: Required networks (empty = network-agnostic, can run on any VM)
5454# - boot_image: Required boot image
5555# - fips: Whether FIPS mode is required
56- # - slow: Set to "true" for long-running tests (e.g., router, conformance )
56+ # - slow: Set to "true" for tests longer than VM boot time (~4 min )
5757# Slow tests get priority within their reusability tier to avoid
5858# becoming the critical path.
59+ # - fast: Set to "true" for tests shorter than VM boot time (~4 min)
60+ # Fast tests stay queued longer to maximize VM reuse opportunities
61+ # (reusing a VM saves more time than the test itself takes).
5962#
6063# ============================================================================
6164
@@ -685,14 +688,16 @@ sort_scenarios_for_reuse() {
685688 # 1. Reusability score (ascending): restrictive scenarios first
686689 # - They can't be reused anyway, so get them out of the way
687690 # - Their VMs are destroyed when done
688- # 2. Within same reusability: slow tests first (ascending 0=slow, 1=normal)
689- # - Long-running tests start early to avoid becoming critical path
691+ # 2. Within same reusability: duration priority (0=slow, 1=normal, 2=fast)
692+ # - Slow tests (longer than VM boot) start early to avoid critical path
693+ # - Fast tests (shorter than VM boot) stay queued for reuse opportunities
690694 # 3. Then boot_image descending (optionals before source)
691695 # 4. Then vcpus descending (larger VMs first)
692696 #
693697 # This ensures:
694698 # - Restrictive scenarios (special networks/boot_images) start first
695699 # - Slow tests start early within their reusability tier
700+ # - Fast tests act as "gap fillers", maximizing VM reuse
696701 # - Flexible scenarios stay queued longer, maximizing reuse opportunities
697702
698703 for scenario_script in " ${scenarios[@]} " ; do
@@ -701,20 +706,23 @@ sort_scenarios_for_reuse() {
701706 local req_file=" ${SCENARIO_STATUS} /${scenario_name} /requirements"
702707
703708 if [ -f " ${req_file} " ]; then
704- local boot_image networks vcpus reuse_score slow_flag slow_sort
709+ local boot_image networks vcpus reuse_score slow_flag fast_flag duration_sort
705710 boot_image=$( get_req_value " ${req_file} " " boot_image" " default" )
706711 networks=$( get_req_value " ${req_file} " " networks" " default" )
707712 vcpus=$( get_req_value " ${req_file} " " min_vcpus" " ${DEFAULT_VM_VCPUS} " )
708713 slow_flag=$( get_req_value " ${req_file} " " slow" " false" )
714+ fast_flag=$( get_req_value " ${req_file} " " fast" " false" )
709715 reuse_score=$( get_reusability_score " ${boot_image} " " ${networks} " )
710- # slow=true -> sort value 0 (first), slow=false -> sort value 1 (after )
711- slow_sort =1
716+ # Duration priority: slow= 0 (first), normal=1, fast=2 (last, best for reuse )
717+ duration_sort =1
712718 if [ " ${slow_flag} " = " true" ]; then
713- slow_sort=0
719+ duration_sort=0
720+ elif [ " ${fast_flag} " = " true" ]; then
721+ duration_sort=2
714722 fi
715- # Sort key: reuse_score (asc), slow_sort (asc), boot_image (desc), vcpus (desc)
723+ # Sort key: reuse_score (asc), duration_sort (asc), boot_image (desc), vcpus (desc)
716724 # Use inverse vcpus (100-vcpus) so ascending sort gives descending vcpus
717- printf " %d\t%d\t%s\t%02d\t%s\n" " ${reuse_score} " " ${slow_sort } " " ${boot_image} " " $(( 100 - vcpus)) " " ${scenario_script} "
725+ printf " %d\t%d\t%s\t%02d\t%s\n" " ${reuse_score} " " ${duration_sort } " " ${boot_image} " " $(( 100 - vcpus)) " " ${scenario_script} "
718726 else
719727 # Unknown requirements - treat as flexible, put last
720728 printf " 9\t1\taaa\t99\t%s\n" " ${scenario_script} "
@@ -848,9 +856,19 @@ run_scenario_on_vm() {
848856 # Create phase has its own retry logic with timeouts
849857 log " Creating VM ${vm_name} - logging to ${boot_log} "
850858
859+ # Track boot time for metrics
860+ local boot_start_time
861+ boot_start_time=$( date +%s)
862+
851863 local create_exit=0
852864 bash -x " ${SCRIPTDIR} /scenario.sh" create " ${scenario_script} " & > " ${boot_log} " || create_exit=$?
853865
866+ # Record boot time
867+ local boot_end_time boot_duration
868+ boot_end_time=$( date +%s)
869+ boot_duration=$(( boot_end_time - boot_start_time))
870+ echo " ${boot_duration} " > " ${vm_dir} /boot_time"
871+
854872 if [ ${create_exit} -ne 0 ]; then
855873 result=" FAILED"
856874 exit_code=1
@@ -1332,12 +1350,33 @@ show_status() {
13321350 echo " Dynamic scenarios: ${dynamic_scenario_count} (passed: ${passed_scenarios} , failed: ${failed_scenarios} )"
13331351 echo " "
13341352
1353+ # Calculate average boot time
1354+ local total_boot_time=0
1355+ local boot_time_count=0
1356+ for vm_dir in " ${VM_REGISTRY} " /* ; do
1357+ [ -d " ${vm_dir} " ] || continue
1358+ local boot_time_file=" ${vm_dir} /boot_time"
1359+ if [ -f " ${boot_time_file} " ]; then
1360+ local bt
1361+ bt=$( cat " ${boot_time_file} " )
1362+ total_boot_time=$(( total_boot_time + bt))
1363+ boot_time_count=$(( boot_time_count + 1 ))
1364+ fi
1365+ done
1366+ local avg_boot_time=0
1367+ local avg_boot_time_str=" N/A"
1368+ if [ ${boot_time_count} -gt 0 ]; then
1369+ avg_boot_time=$(( total_boot_time / boot_time_count))
1370+ avg_boot_time_str=" $( printf ' %d:%02d' $(( avg_boot_time / 60 )) $(( avg_boot_time % 60 )) ) "
1371+ fi
1372+
13351373 echo " === Dynamic VM Efficiency ==="
13361374 echo " VMs created: ${vms_created} "
13371375 echo " VM creation retries: ${vm_creation_retries} "
13381376 echo " VM reuses: ${vm_reuses} "
13391377 echo " Reuse rate: ${reuse_rate} %"
13401378 echo " Max scenarios per VM: ${max_runs_per_vm} "
1379+ echo " Avg VM boot time: ${avg_boot_time_str} (${boot_time_count} VMs)"
13411380 echo " "
13421381
13431382 echo " === Resource Configuration ==="
0 commit comments