blob: 6d08ec206ca610c80f7ca7a08d2a13cb61fa8cc5 [file] [log] [blame] [edit]
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package main
import (
"fmt"
"log"
"os"
server "go.chromium.org/chromiumos/test/ctpv2/common/server_template"
"go.chromium.org/chromiumos/config/go/test/api"
testapi "go.chromium.org/chromiumos/config/go/test/lab/api"
)
const (
binName = "autovm_test_shifter_filter"
installPath = "installPath"
hwAgnostic = "hw_agnostic"
release = "release/"
gsBucketPath = "gs://chromeos-image-archive/"
buildReportJSON = "build_report.json"
success = "SUCCESS"
)
var vmBoards = []string{"betty", "reven-vmtest", "amd64-generic"}
// isTestVMCompatible returns true if the test can be safely executed on a VM.
func isTestVMCompatible(testCase *api.CTPTestCase) bool {
compatibilityCriteria := []func(*api.CTPTestCase) bool{
isHwAgnostic,
// Add more criteria functions here in the future
}
for _, criterion := range compatibilityCriteria {
if criterion(testCase) {
return true
}
}
return false
}
// isHwAgnostic checks if the test case has the hwAgnostic tag.
func isHwAgnostic(testCase *api.CTPTestCase) bool {
for _, testCaseTag := range testCase.GetMetadata().GetTestCase().GetTags() {
if testCaseTag.GetValue() == hwAgnostic {
return true
}
}
return false
}
func generateVMSchedulingUnit(board string, version string) *api.SchedulingUnit {
return &api.SchedulingUnit{
PrimaryTarget: &api.Target{
SwarmingDef: &api.SwarmingDefinition{
DutInfo: &testapi.Dut{
DutType: &testapi.Dut_Chromeos{
Chromeos: &testapi.Dut_ChromeOS{
DutModel: &testapi.DutModel{BuildTarget: board},
},
},
},
}},
DynamicUpdateLookupTable: map[string]string{
"board": board,
"installPath": "gs://chromeos-image-archive/" + board + "-" + release + version,
},
}
}
// updateSchedulingUnitOption updates the list of Scheduling units. Returns nil if no VMlab Scheduling unit found.
func updateSchedulingUnitOption(schedulingUnitOption *api.SchedulingUnitOptions, board string, version string) *api.SchedulingUnitOptions {
var filteredSchedulingUnits []*api.SchedulingUnit
for _, schedulingUnit := range schedulingUnitOption.GetSchedulingUnits() {
// if VM board in scheduling unit then do not remove. This will trigger VMlab flow
if checkBoardInVMBoardsList(getBoard(schedulingUnit)) {
filteredSchedulingUnits = append(filteredSchedulingUnits, schedulingUnit)
}
}
if len(filteredSchedulingUnits) == 0 {
return nil
}
schedulingUnitOption.SchedulingUnits = filteredSchedulingUnits
return schedulingUnitOption
}
// updateSchedulingUnitOptions updates the schedulingUnitOptions for each test case in internal test plan request.
func updateSchedulingUnitOptions(req *api.InternalTestplan, board string, version string, log *log.Logger) error {
for _, testCase := range req.GetTestCases() {
if isTestVMCompatible(testCase) {
var updatedSchedulingUnitOptions []*api.SchedulingUnitOptions
for _, schedulingUnitOption := range testCase.GetSchedulingUnitOptions() {
updatedSchedulingUnitOption := updateSchedulingUnitOption(schedulingUnitOption, board, version)
if updatedSchedulingUnitOption == nil {
continue
}
updatedSchedulingUnitOptions = append(updatedSchedulingUnitOptions, updatedSchedulingUnitOption)
}
// if no schedulign unit found from intended scheduling units, then create a VM schedulign unit with available board/version
if len(updatedSchedulingUnitOptions) == 0 {
testCase.SchedulingUnitOptions = []*api.SchedulingUnitOptions{
{
SchedulingUnits: []*api.SchedulingUnit{
generateVMSchedulingUnit(board, version),
},
},
}
} else {
testCase.SchedulingUnitOptions = updatedSchedulingUnitOptions
}
} else {
log.Printf("Skippping as test : %s, isn't VM compatible", testCase.GetName())
}
}
return nil
}
func executor(req *api.InternalTestplan, log *log.Logger) (*api.InternalTestplan, error) {
available, board, version := isAnyVMImageAvailable(req, log)
if available {
// iterates each test case and updates the scheduling units based on if test is hw agnostic.
err := updateSchedulingUnitOptions(req, board, version, log)
if err != nil {
return nil, fmt.Errorf("Error during AutoVM test shifter filter execution: %s", err)
}
log.Printf("Image is available: %t", available)
} else {
log.Printf("Skipping AutoVM test shifter filter execution. VM Image is not available.")
}
return req, nil
}
func main() {
err := server.Server(executor, binName)
if err != nil {
os.Exit(2)
}
os.Exit(0)
}