aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-06-02 20:09:00 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-06-03 11:31:42 +0200
commitaf643baa328ae3d4b7076054bba648c4b8bf8056 (patch)
tree6e4687c745b63352dec21f6ac2a6a7d8fa1201c4 /pkg
parent96b8d4e99c7812f91633ea6cd1aee5867965e742 (diff)
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.
Diffstat (limited to 'pkg')
-rw-r--r--pkg/config/config.go6
-rw-r--r--pkg/config/config_test.go8
-rw-r--r--pkg/osutil/osutil.go35
3 files changed, 42 insertions, 7 deletions
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)
+}