diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2016-10-07 18:56:45 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2016-10-07 18:56:45 +0200 |
| commit | d21c3c878c8965786d39a5d73bbe22792b0a6ccd (patch) | |
| tree | 5c72441d9a36e0f7e2ed91e1c3e6243966757acc /gce | |
| parent | 2da6f4a8e133a3b35321b9cc7d87022cc4b91723 (diff) | |
syz-gce: add autonomous GCE runner
It is meant to download new kernel images from GCS,
update and rebuild syzkaller and restart syz-manager.
Work in progress...
Diffstat (limited to 'gce')
| -rw-r--r-- | gce/gce.go | 95 |
1 files changed, 71 insertions, 24 deletions
diff --git a/gce/gce.go b/gce/gce.go index 2ae3aae37..a6cf7a5e0 100644 --- a/gce/gce.go +++ b/gce/gce.go @@ -3,6 +3,12 @@ // Package gce provides wrappers around Google Compute Engine (GCE) APIs. // It is assumed that the program itself also runs on GCE as APIs operate on the current project/zone. +// +// See https://cloud.google.com/compute/docs for details. +// In particular, API reference: +// https://cloud.google.com/compute/docs/reference/latest +// and Go API wrappers: +// https://godoc.org/google.golang.org/api/compute/v0.beta package gce import ( @@ -84,24 +90,6 @@ func NewContext() (*Context, error) { return ctx, nil } -func (ctx *Context) getMeta(path string) (string, error) { - req, err := http.NewRequest("GET", "http://metadata.google.internal/computeMetadata/v1/"+path, nil) - if err != nil { - return "", err - } - req.Header.Add("Metadata-Flavor", "Google") - resp, err := http.DefaultClient.Do(req) - if err != nil { - return "", err - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return "", err - } - return string(body), nil -} - func (ctx *Context) CreateInstance(name, machineType, image, sshkey string) (string, error) { prefix := "https://www.googleapis.com/compute/v1/projects/" + ctx.ProjectID instance := &compute.Instance{ @@ -148,7 +136,7 @@ func (ctx *Context) CreateInstance(name, machineType, image, sshkey string) (str if err != nil { return "", fmt.Errorf("failed to create instance: %v", err) } - if err := ctx.waitForCompletion("create", op.Name, false); err != nil { + if err := ctx.waitForCompletion("zone", "create image", op.Name, false); err != nil { return "", err } @@ -175,24 +163,65 @@ func (ctx *Context) CreateInstance(name, machineType, image, sshkey string) (str func (ctx *Context) DeleteInstance(name string) error { <-ctx.apiRateGate op, err := ctx.computeService.Instances.Delete(ctx.ProjectID, ctx.ZoneID, name).Do() - apiErr, ok := err.(*googleapi.Error) - if ok && apiErr.Code == 404 { + if apiErr, ok := err.(*googleapi.Error); ok && apiErr.Code == 404 { return nil } if err != nil { return fmt.Errorf("failed to delete instance: %v", err) } - if err := ctx.waitForCompletion("delete", op.Name, true); err != nil { + if err := ctx.waitForCompletion("zone", "delete image", op.Name, true); err != nil { + return err + } + return nil +} + +func (ctx *Context) CreateImage(imageName, gcsFile string) error { + image := &compute.Image{ + Name: imageName, + RawDisk: &compute.ImageRawDisk{ + Source: "https://storage.googleapis.com/" + gcsFile, + }, + } + <-ctx.apiRateGate + op, err := ctx.computeService.Images.Insert(ctx.ProjectID, image).Do() + if err != nil { + return fmt.Errorf("failed to create image: %v", err) + } + if err := ctx.waitForCompletion("global", "create image", op.Name, false); err != nil { + return err + } + return nil +} + +func (ctx *Context) DeleteImage(imageName string) error { + <-ctx.apiRateGate + op, err := ctx.computeService.Images.Delete(ctx.ProjectID, imageName).Do() + if apiErr, ok := err.(*googleapi.Error); ok && apiErr.Code == 404 { + return nil + } + if err != nil { + return fmt.Errorf("failed to delete image: %v", err) + } + if err := ctx.waitForCompletion("global", "delete image", op.Name, true); err != nil { return err } return nil } -func (ctx *Context) waitForCompletion(desc, opName string, ignoreNotFound bool) error { +func (ctx *Context) waitForCompletion(typ, desc, opName string, ignoreNotFound bool) error { for { time.Sleep(2 * time.Second) <-ctx.apiRateGate - op, err := ctx.computeService.ZoneOperations.Get(ctx.ProjectID, ctx.ZoneID, opName).Do() + var err error + var op *compute.Operation + switch typ { + case "global": + op, err = ctx.computeService.GlobalOperations.Get(ctx.ProjectID, opName).Do() + case "zone": + op, err = ctx.computeService.ZoneOperations.Get(ctx.ProjectID, ctx.ZoneID, opName).Do() + default: + panic("unknown operation type: " + typ) + } if err != nil { return fmt.Errorf("failed to get %v operation %v: %v", desc, opName, err) } @@ -216,3 +245,21 @@ func (ctx *Context) waitForCompletion(desc, opName string, ignoreNotFound bool) } } } + +func (ctx *Context) getMeta(path string) (string, error) { + req, err := http.NewRequest("GET", "http://metadata.google.internal/computeMetadata/v1/"+path, nil) + if err != nil { + return "", err + } + req.Header.Add("Metadata-Flavor", "Google") + resp, err := http.DefaultClient.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", err + } + return string(body), nil +} |
