From af643baa328ae3d4b7076054bba648c4b8bf8056 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Fri, 2 Jun 2017 20:09:00 +0200 Subject: vm: overhaul VM infrastructure currently has several problems: - Config struct is complete mess with a superset of params for all VM types - verification of Config is mess spread across several places - there is no place where VM code could do global initialization like creating GCE connection, uploading GCE image to GCS, matching adb devices with consoles, etc - it hard to add private VM implementations such impl would need to add code to config package which would lead to constant merge conflicts - interface for VM implementation is mixed with interface for VM users this does not allow to provide best interface for both of them - there is no way to add common code for all VM implementations This change solves these problems by: - splitting VM interface for users (vm package) and VM interface for VM implementations (vmimpl pacakge), this in turn allows to add common code - adding Pool concept that allows to do global initialization and config checking at the right time - decoupling manager config from VM-specific config each VM type now defines own config Note: manager configs need to be changed after this change: VM-specific parts are moved to own "vm" subobject. Note: this change also drops "local" VM type. Its story was long unclear and there is now syz-stress which solves the same problem. --- pkg/config/config.go | 6 +++--- pkg/config/config_test.go | 8 ++++---- pkg/osutil/osutil.go | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 7 deletions(-) (limited to 'pkg') diff --git a/pkg/config/config.go b/pkg/config/config.go index 461ebdabc..03d4b283e 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -11,7 +11,7 @@ import ( "strings" ) -func Load(filename string, cfg interface{}) error { +func LoadFile(filename string, cfg interface{}) error { if filename == "" { return fmt.Errorf("no config file specified") } @@ -19,10 +19,10 @@ func Load(filename string, cfg interface{}) error { if err != nil { return fmt.Errorf("failed to read config file: %v", err) } - return load(data, cfg) + return LoadData(data, cfg) } -func load(data []byte, cfg interface{}) error { +func LoadData(data []byte, cfg interface{}) error { if err := checkUnknownFields(data, reflect.ValueOf(cfg).Type()); err != nil { return err } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index e36dd9ee9..79836f39e 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -161,7 +161,7 @@ func TestLoad(t *testing.T) { for i, test := range tests { t.Run(fmt.Sprint(i), func(t *testing.T) { var cfg Config - err := load([]byte(test.input), &cfg) + err := LoadData([]byte(test.input), &cfg) errStr := "" if err != nil { errStr = err.Error() @@ -178,15 +178,15 @@ func TestLoad(t *testing.T) { func TestLoadBadType(t *testing.T) { want := "config type is not pointer to struct" - if err := load([]byte("{}"), 1); err == nil || err.Error() != want { + if err := LoadData([]byte("{}"), 1); err == nil || err.Error() != want { t.Fatalf("got '%v', want '%v'", err, want) } i := 0 - if err := load([]byte("{}"), &i); err == nil || err.Error() != want { + if err := LoadData([]byte("{}"), &i); err == nil || err.Error() != want { t.Fatalf("got '%v', want '%v'", err, want) } s := struct{}{} - if err := load([]byte("{}"), s); err == nil || err.Error() != want { + if err := LoadData([]byte("{}"), s); err == nil || err.Error() != want { t.Fatalf("got '%v', want '%v'", err, want) } } diff --git a/pkg/osutil/osutil.go b/pkg/osutil/osutil.go index 0bd4cdfac..3f42dbc12 100644 --- a/pkg/osutil/osutil.go +++ b/pkg/osutil/osutil.go @@ -6,7 +6,11 @@ package osutil import ( "bytes" "fmt" + "io" + "os" "os/exec" + "path/filepath" + "syscall" "time" ) @@ -34,3 +38,34 @@ func RunCmd(timeout time.Duration, dir, bin string, args ...string) ([]byte, err } return output.Bytes(), nil } + +func LongPipe() (io.ReadCloser, io.WriteCloser, error) { + r, w, err := os.Pipe() + if err != nil { + return nil, nil, fmt.Errorf("failed to create pipe: %v", err) + } + for sz := 128 << 10; sz <= 2<<20; sz *= 2 { + syscall.Syscall(syscall.SYS_FCNTL, w.Fd(), syscall.F_SETPIPE_SZ, uintptr(sz)) + } + return r, w, err +} + +var wd string + +func init() { + var err error + wd, err = os.Getwd() + if err != nil { + panic(fmt.Sprintf("failed to get wd: %v", err)) + } +} + +func Abs(path string) string { + if wd1, err := os.Getwd(); err == nil && wd1 != wd { + panic("don't mess with wd in a concurrent program") + } + if path == "" || filepath.IsAbs(path) { + return path + } + return filepath.Join(wd, path) +} -- cgit mrf-deployment