vm/gce: allow non-preemptible VMs

We are seeing some flakes during bisection and image testing.
Hard to tell what's the root cause because they are episodic.
But using non-preemptible VMs for bisection and image testing
looks good on all fronts.

Update #501
This commit is contained in:
Dmitry Vyukov 2019-03-28 13:20:58 +01:00
parent f94f56fe6b
commit 742f448304
4 changed files with 29 additions and 32 deletions

View File

@ -92,7 +92,7 @@ func NewContext() (*Context, error) {
return ctx, nil
}
func (ctx *Context) CreateInstance(name, machineType, image, sshkey string) (string, error) {
func (ctx *Context) CreateInstance(name, machineType, image, sshkey string, preemptible bool) (string, error) {
prefix := "https://www.googleapis.com/compute/v1/projects/" + ctx.ProjectID
sshkeyAttr := "syzkaller:" + sshkey
oneAttr := "1"
@ -132,7 +132,7 @@ func (ctx *Context) CreateInstance(name, machineType, image, sshkey string) (str
},
Scheduling: &compute.Scheduling{
AutomaticRestart: &falseAttr,
Preemptible: true,
Preemptible: preemptible,
OnHostMaintenance: "TERMINATE",
},
}

View File

@ -90,42 +90,36 @@ func (env *Env) BuildKernel(compilerBin, userspaceDir, cmdlineFile, sysctlFile s
cmdlineFile, sysctlFile, kernelConfig); err != nil {
return err
}
return SetConfigImage(cfg, imageDir)
return SetConfigImage(cfg, imageDir, true)
}
func SetConfigImage(cfg *mgrconfig.Config, imageDir string) error {
func SetConfigImage(cfg *mgrconfig.Config, imageDir string, reliable bool) error {
cfg.KernelObj = filepath.Join(imageDir, "obj")
cfg.Image = filepath.Join(imageDir, "image")
if keyFile := filepath.Join(imageDir, "key"); osutil.IsExist(keyFile) {
cfg.SSHKey = keyFile
}
vmConfig := make(map[string]interface{})
if err := json.Unmarshal(cfg.VM, &vmConfig); err != nil {
return fmt.Errorf("failed to parse VM config: %v", err)
}
if cfg.Type == "qemu" || cfg.Type == "vmm" {
kernel := filepath.Join(imageDir, "kernel")
if !osutil.IsExist(kernel) {
kernel = ""
if kernel := filepath.Join(imageDir, "kernel"); osutil.IsExist(kernel) {
vmConfig["kernel"] = kernel
}
initrd := filepath.Join(imageDir, "initrd")
if !osutil.IsExist(initrd) {
initrd = ""
}
if kernel != "" || initrd != "" {
vmConfig := make(map[string]interface{})
if err := json.Unmarshal(cfg.VM, &vmConfig); err != nil {
return fmt.Errorf("failed to parse VM config: %v", err)
}
if kernel != "" {
vmConfig["kernel"] = kernel
}
if initrd != "" {
vmConfig["initrd"] = initrd
}
vmCfg, err := json.Marshal(vmConfig)
if err != nil {
return fmt.Errorf("failed to serialize VM config: %v", err)
}
cfg.VM = vmCfg
if initrd := filepath.Join(imageDir, "initrd"); osutil.IsExist(initrd) {
vmConfig["initrd"] = initrd
}
}
if cfg.Type == "gce" {
// Don't use preemptible VMs for image testing, patch testing and bisection.
vmConfig["preemptible"] = !reliable
}
vmCfg, err := json.Marshal(vmConfig)
if err != nil {
return fmt.Errorf("failed to serialize VM config: %v", err)
}
cfg.VM = vmCfg
return nil
}

View File

@ -435,7 +435,7 @@ func (mgr *Manager) createTestConfig(imageDir string, info *BuildInfo) (*mgrconf
mgrcfg.Name += "-test"
mgrcfg.Tag = info.KernelCommit
mgrcfg.Workdir = filepath.Join(imageDir, "workdir")
if err := instance.SetConfigImage(mgrcfg, imageDir); err != nil {
if err := instance.SetConfigImage(mgrcfg, imageDir, true); err != nil {
return nil, err
}
mgrcfg.KernelSrc = mgr.kernelDir
@ -461,7 +461,7 @@ func (mgr *Manager) writeConfig(buildTag string) (string, error) {
}
mgrcfg.Tag = buildTag
mgrcfg.Workdir = mgr.workDir
if err := instance.SetConfigImage(mgrcfg, mgr.currentDir); err != nil {
if err := instance.SetConfigImage(mgrcfg, mgr.currentDir, false); err != nil {
return "", err
}
// Strictly saying this is somewhat racy as builder can concurrently

View File

@ -39,7 +39,8 @@ type Config struct {
Count int `json:"count"` // number of VMs to use
MachineType string `json:"machine_type"` // GCE machine type (e.g. "n1-highcpu-2")
GCSPath string `json:"gcs_path"` // GCS path to upload image
GCEImage string `json:"gce_image"` // Pre-created GCE image to use
GCEImage string `json:"gce_image"` // pre-created GCE image to use
Preemptible bool `json:"preemptible"` // use preemptible VMs if available (defaults to true)
}
type Pool struct {
@ -67,7 +68,8 @@ func ctor(env *vmimpl.Env) (vmimpl.Pool, error) {
return nil, fmt.Errorf("config param name is empty (required for GCE)")
}
cfg := &Config{
Count: 1,
Count: 1,
Preemptible: true,
}
if err := config.LoadData(env.Config, cfg); err != nil {
return nil, fmt.Errorf("failed to parse gce vm config: %v", err)
@ -144,7 +146,8 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) {
return nil, err
}
log.Logf(0, "creating instance: %v", name)
ip, err := pool.GCE.CreateInstance(name, pool.cfg.MachineType, pool.cfg.GCEImage, string(gceKeyPub))
ip, err := pool.GCE.CreateInstance(name, pool.cfg.MachineType, pool.cfg.GCEImage,
string(gceKeyPub), pool.cfg.Preemptible)
if err != nil {
return nil, err
}