blob: 37112575ef8be0013ce3b34a01c7ace767a795fa [file] [log] [blame]
package instance_types
import (
"context"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"strings"
"go.skia.org/infra/go/auth"
"go.skia.org/infra/go/exec"
"go.skia.org/infra/go/gce"
"go.skia.org/infra/go/util"
)
const (
DEV_NAME_PREFIX = "skia-d-"
INTERNAL_NAME_PREFIX = "skia-i-"
USER_CHROME_BOT = gce.USER_CHROME_BOT
DEBIAN_SOURCE_IMAGE_EXTERNAL = "skia-swarming-base-v2020-03-31-000"
DEBIAN_SOURCE_IMAGE_INTERNAL = "skia-swarming-base-v2020-03-31-000"
WIN_SOURCE_IMAGE = "projects/windows-cloud/global/images/windows-server-2019-dc-v20200114"
INSTANCE_TYPE_CT = "ct"
INSTANCE_TYPE_LINUX_MICRO = "linux-micro"
INSTANCE_TYPE_LINUX_SMALL = "linux-small"
INSTANCE_TYPE_LINUX_MEDIUM = "linux-medium"
INSTANCE_TYPE_LINUX_LARGE = "linux-large"
INSTANCE_TYPE_LINUX_GPU = "linux-gpu"
INSTANCE_TYPE_LINUX_AMD = "linux-amd"
INSTANCE_TYPE_LINUX_SKYLAKE = "linux-skylake"
INSTANCE_TYPE_WIN_MEDIUM = "win-medium"
INSTANCE_TYPE_WIN_LARGE = "win-large"
)
var (
// "Constants"
SETUP_SCRIPT_LINUX_PATH = filepath.Join("go", "gce", "swarming", "setup-script-linux.sh")
SETUP_SCRIPT_WIN_PATH = filepath.Join("scripts", "win_setup.ps1")
STARTUP_SCRIPT_WIN_PATH = filepath.Join("scripts", "win_startup.ps1")
CHROME_BOT_SCRIPT_WIN_PATH = filepath.Join("scripts", "chromebot-schtask.ps1")
NODE_SETUP_PATH = filepath.Join("third_party", "node", "setup_6.x")
externalNamePrefixRegexp = regexp.MustCompile("^skia-e-")
)
// Base configs for Swarming GCE instances.
func Swarming20180406(name string, machineType, serviceAccount, setupScriptPath, nodeSetupScript, sourceImage string) *gce.Instance {
vm := &gce.Instance{
BootDisk: &gce.Disk{
Name: name,
SizeGb: 15,
SourceImage: sourceImage,
Type: gce.DISK_TYPE_PERSISTENT_STANDARD,
},
DataDisks: []*gce.Disk{{
Name: fmt.Sprintf("%s-data", name),
SizeGb: 300,
Type: gce.DISK_TYPE_PERSISTENT_STANDARD,
MountPath: gce.DISK_MOUNT_PATH_DEFAULT,
}},
GSDownloads: []*gce.GSDownload{},
MachineType: machineType,
Metadata: map[string]string{},
MetadataDownloads: map[string]string{},
Name: name,
Os: gce.OS_LINUX,
ServiceAccount: serviceAccount,
SetupScript: setupScriptPath,
Scopes: []string{auth.ScopeAllCloudAPIs},
Tags: []string{"use-swarming-auth"},
User: USER_CHROME_BOT,
}
if nodeSetupScript != "" {
vm.Metadata["node-setup-script"] = nodeSetupScript
}
return vm
}
// Linux GCE instances.
func linuxSwarmingBot(num int, machineType, setupScriptPath, nodeSetupScript string) *gce.Instance {
return Swarming20180406(fmt.Sprintf("skia-e-gce-%03d", num), machineType, gce.SERVICE_ACCOUNT_CHROMIUM_SWARM, setupScriptPath, nodeSetupScript, DEBIAN_SOURCE_IMAGE_EXTERNAL)
}
// Micro Linux GCE instances.
func LinuxMicro(num int, setupScriptPath, nodeSetupScript string) *gce.Instance {
vm := linuxSwarmingBot(num, gce.MACHINE_TYPE_F1_MICRO, setupScriptPath, nodeSetupScript)
vm.DataDisks[0].SizeGb = 10
return vm
}
// Small Linux GCE instances.
func LinuxSmall(num int, setupScriptPath, nodeSetupScript string) *gce.Instance {
return linuxSwarmingBot(num, gce.MACHINE_TYPE_HIGHMEM_2, setupScriptPath, nodeSetupScript)
}
// Medium Linux GCE instances.
func LinuxMedium(num int, setupScriptPath, nodeSetupScript string) *gce.Instance {
return linuxSwarmingBot(num, gce.MACHINE_TYPE_STANDARD_16, setupScriptPath, nodeSetupScript)
}
// Large Linux GCE instances.
func LinuxLarge(num int, setupScriptPath, nodeSetupScript string) *gce.Instance {
return linuxSwarmingBot(num, gce.MACHINE_TYPE_HIGHCPU_64, setupScriptPath, nodeSetupScript)
}
// Linux GCE instances with GPUs.
func LinuxGpu(num int, setupScriptPath, nodeSetupScript string) *gce.Instance {
// Max 8 CPUs when using a GPU.
vm := linuxSwarmingBot(num, gce.MACHINE_TYPE_STANDARD_8, setupScriptPath, nodeSetupScript)
vm.Gpu = true
vm.MaintenancePolicy = gce.MAINTENANCE_POLICY_TERMINATE // Required for GPUs.
return vm
}
// Linux GCE instances with AMD CPUs (skbug.com/10269).
func LinuxAmd(num int, setupScriptPath, nodeSetupScript string) *gce.Instance {
vm := linuxSwarmingBot(num, gce.MACHINE_TYPE_N2D_STANDARD_16, setupScriptPath, nodeSetupScript)
vm.MinCpuPlatform = gce.CPU_PLATFORM_AMD
return vm
}
// Linux GCE instances with Skylake CPUs.
func LinuxSkylake(num int, setupScriptPath, nodeSetupScript string) *gce.Instance {
vm := LinuxMedium(num, setupScriptPath, nodeSetupScript)
vm.MinCpuPlatform = gce.CPU_PLATFORM_SKYLAKE
return vm
}
// Internal instances.
func Internal(vm *gce.Instance) *gce.Instance {
vm.Name = externalNamePrefixRegexp.ReplaceAllString(vm.Name, INTERNAL_NAME_PREFIX)
for _, d := range append(vm.DataDisks, vm.BootDisk) {
d.Name = externalNamePrefixRegexp.ReplaceAllString(d.Name, INTERNAL_NAME_PREFIX)
}
vm.ServiceAccount = gce.SERVICE_ACCOUNT_CHROME_SWARMING
if vm.BootDisk.SourceImage == DEBIAN_SOURCE_IMAGE_EXTERNAL {
vm.BootDisk.SourceImage = DEBIAN_SOURCE_IMAGE_INTERNAL
}
return vm
}
// Dev instances.
func Dev(vm *gce.Instance) *gce.Instance {
vm.Name = externalNamePrefixRegexp.ReplaceAllString(vm.Name, DEV_NAME_PREFIX)
for _, d := range append(vm.DataDisks, vm.BootDisk) {
d.Name = externalNamePrefixRegexp.ReplaceAllString(d.Name, DEV_NAME_PREFIX)
}
return vm
}
// Skia CT bots.
func SkiaCT(num int, setupScriptPath, nodeSetupScript string) *gce.Instance {
vm := Swarming20180406(fmt.Sprintf("skia-ct-gce-%03d", num), gce.MACHINE_TYPE_STANDARD_16, gce.SERVICE_ACCOUNT_CHROMIUM_SWARM, setupScriptPath, nodeSetupScript, DEBIAN_SOURCE_IMAGE_EXTERNAL)
vm.DataDisks[0].SizeGb = 3000
// SkiaCT bots use a datadisk with a snapshot that is prepopulated with 1M SKPS.
vm.DataDisks[0].SourceSnapshot = "skia-ct-skps-snapshot-3"
return vm
}
// Configs for Windows GCE instances.
func AddWinConfigs(vm *gce.Instance, startupScriptPath, chromebotScript, bootDiskType string) *gce.Instance {
vm.BootDisk.SizeGb = 300
vm.BootDisk.Type = bootDiskType
vm.DataDisks = nil
// Most of the Windows setup, including the gitconfig/netrc, occurs in
// the setup and startup scripts, which also install and schedule the
// chrome-bot scheduled task script.
vm.Metadata["chromebot-schtask-ps1"] = chromebotScript
vm.Os = gce.OS_WINDOWS
vm.StartupScript = startupScriptPath
return vm
}
// Windows GCE instances.
func WinSwarmingBot(name, machineType, setupScriptPath, startupScriptPath, chromebotScript, bootDiskType string) *gce.Instance {
vm := Swarming20180406(name, machineType, gce.SERVICE_ACCOUNT_CHROMIUM_SWARM, setupScriptPath, "", WIN_SOURCE_IMAGE)
return AddWinConfigs(vm, startupScriptPath, chromebotScript, bootDiskType)
}
// Medium Windows GCE instances.
func WinMedium(num int, setupScriptPath, startupScriptPath, chromebotScript string) *gce.Instance {
return WinSwarmingBot(fmt.Sprintf("skia-e-gce-%03d", num), gce.MACHINE_TYPE_STANDARD_16, setupScriptPath, startupScriptPath, chromebotScript, gce.DISK_TYPE_PERSISTENT_SSD)
}
// Large Windows GCE instances.
func WinLarge(num int, setupScriptPath, startupScriptPath, chromebotScript string) *gce.Instance {
return WinSwarmingBot(fmt.Sprintf("skia-e-gce-%03d", num), gce.MACHINE_TYPE_HIGHCPU_64, setupScriptPath, startupScriptPath, chromebotScript, gce.DISK_TYPE_PERSISTENT_SSD)
}
// Returns the path to the setup script, given a local checkout.
func GetLinuxScripts(ctx context.Context, checkoutRoot, workdir string) (string, string, error) {
nodeSetupBytes, err := ioutil.ReadFile(filepath.Join(checkoutRoot, NODE_SETUP_PATH))
if err != nil {
return "", "", err
}
return filepath.Join(checkoutRoot, SETUP_SCRIPT_LINUX_PATH), string(nodeSetupBytes), nil
}
// Returns the setup, startup, and chrome-bot scripts, given a local checkout.
// Writes the scripts into the given workdir.
func GetWindowsScripts(ctx context.Context, checkoutRoot, workdir string) (string, string, string, error) {
pw, err := exec.RunCwd(ctx, ".", "gsutil", "cat", "gs://skia-buildbots/artifacts/bots/win-chrome-bot.txt")
if err != nil {
return "", "", "", err
}
pw = strings.TrimSpace(pw)
setupBytes, err := ioutil.ReadFile(filepath.Join(checkoutRoot, SETUP_SCRIPT_WIN_PATH))
if err != nil {
return "", "", "", err
}
setupScript := strings.Replace(string(setupBytes), "CHROME_BOT_PASSWORD", pw, -1)
setupPath := filepath.Join(workdir, "setup-script.ps1")
if err := ioutil.WriteFile(setupPath, []byte(setupScript), os.ModePerm); err != nil {
return "", "", "", err
}
startupBytes, err := ioutil.ReadFile(filepath.Join(checkoutRoot, STARTUP_SCRIPT_WIN_PATH))
if err != nil {
return "", "", "", err
}
startupScript := strings.Replace(string(startupBytes), "CHROME_BOT_PASSWORD", pw, -1)
startupPath := filepath.Join(workdir, "startup-script.ps1")
if err := ioutil.WriteFile(startupPath, []byte(startupScript), os.ModePerm); err != nil {
return "", "", "", err
}
// Return the chrome-bot script itself, not its path.
chromebotBytes, err := ioutil.ReadFile(filepath.Join(checkoutRoot, CHROME_BOT_SCRIPT_WIN_PATH))
if err != nil {
return "", "", "", err
}
chromebotScript := util.ToDos(string(chromebotBytes))
return setupPath, startupPath, chromebotScript, nil
}