Merge "veyron/services/wsprd: Broke up the monolithic lib package into many smaller packages."
diff --git a/services/mgmt/build/constants.go b/services/mgmt/build/constants.go
deleted file mode 100644
index d150780..0000000
--- a/services/mgmt/build/constants.go
+++ /dev/null
@@ -1,64 +0,0 @@
-package build
-
-type OperatingSystem uint8
-
-const (
- LINUX OperatingSystem = iota
- DARWIN
- WINDOWS
-)
-
-func (os OperatingSystem) String() string {
- switch os {
- case LINUX:
- return "linux"
- case DARWIN:
- return "darwin"
- case WINDOWS:
- return "windows"
- default:
- return "unknown"
- }
-}
-
-type Format uint8
-
-const (
- ELF Format = iota
- MACH
- PE
-)
-
-func (format Format) String() string {
- switch format {
- case ELF:
- return "elf"
- case MACH:
- return "mach-o"
- case PE:
- return "pe"
- default:
- return "unknown"
- }
-}
-
-type Architecture uint8
-
-const (
- AMD64 Architecture = iota
- ARM
- X86
-)
-
-func (arch Architecture) String() string {
- switch arch {
- case AMD64:
- return "amd64"
- case ARM:
- return "arm"
- case X86:
- return "x86"
- default:
- return "unknown"
- }
-}
diff --git a/services/mgmt/build/impl/impl_test.go b/services/mgmt/build/impl/impl_test.go
index 31b2d71..0404e7b 100644
--- a/services/mgmt/build/impl/impl_test.go
+++ b/services/mgmt/build/impl/impl_test.go
@@ -1,6 +1,7 @@
package impl
import (
+ "io"
"os"
"path/filepath"
"strings"
@@ -49,31 +50,43 @@
}
}
-func invokeBuild(t *testing.T, client build.Build, files []build.File) ([]byte, error) {
+func invokeBuild(t *testing.T, client build.Build, files []build.File) ([]byte, []build.File, error) {
stream, err := client.Build(rt.R().NewContext())
if err != nil {
t.Errorf("Build() failed: %v", err)
- return nil, err
+ return nil, nil, err
}
for _, file := range files {
if err := stream.Send(file); err != nil {
t.Logf("Send() failed: %v", err)
stream.Cancel()
- return nil, err
+ return nil, nil, err
}
}
if err := stream.CloseSend(); err != nil {
t.Logf("CloseSend() failed: %v", err)
stream.Cancel()
- return nil, err
+ return nil, nil, err
+ }
+ bins := make([]build.File, 0)
+ for {
+ bin, err := stream.Recv()
+ if err != nil && err != io.EOF {
+ t.Logf("Recv() failed: %v", err)
+ return nil, nil, err
+ }
+ if err == io.EOF {
+ break
+ }
+ bins = append(bins, bin)
}
output, err := stream.Finish()
if err != nil {
t.Logf("Finish() failed: %v", err)
stream.Cancel()
- return nil, err
+ return nil, nil, err
}
- return output, nil
+ return output, bins, nil
}
const mainSrc = `package main
@@ -97,13 +110,16 @@
Contents: []byte(mainSrc),
},
}
- output, err := invokeBuild(t, client, files)
+ output, bins, err := invokeBuild(t, client, files)
if err != nil {
t.FailNow()
}
if got, expected := strings.TrimSpace(string(output)), "test"; got != expected {
t.Fatalf("Unexpected output: got %v, expected %v", got, expected)
}
+ if got, expected := len(bins), 1; got != expected {
+ t.Fatalf("Unexpected number of binaries: got %v, expected %v", got, expected)
+ }
}
// TestFailure checks that the build server fails to build a package
@@ -118,7 +134,7 @@
Contents: []byte(""),
},
}
- if _, err := invokeBuild(t, client, files); err == nil {
+ if _, _, err := invokeBuild(t, client, files); err == nil {
t.FailNow()
}
}
diff --git a/services/mgmt/build/impl/invoker.go b/services/mgmt/build/impl/invoker.go
index b2b9c52..2ef2585 100644
--- a/services/mgmt/build/impl/invoker.go
+++ b/services/mgmt/build/impl/invoker.go
@@ -1,6 +1,7 @@
package impl
import (
+ "bytes"
"errors"
"io"
"io/ioutil"
@@ -15,7 +16,8 @@
)
var (
- errOperationFailed = errors.New("operation failed")
+ errBuildFailed = errors.New("build failed")
+ errInternalError = errors.New("internal error")
)
// invoker holds the state of a build server invocation.
@@ -33,25 +35,28 @@
// BUILD INTERFACE IMPLEMENTATION
+// TODO(jsimsa): Add support for building for a specific profile
+// specified as a suffix the Build().
func (i *invoker) Build(_ ipc.ServerContext, stream build.BuildServiceBuildStream) ([]byte, error) {
+ vlog.VI(1).Infof("Build() called.")
dir, prefix := "", ""
dirPerm, filePerm := os.FileMode(0700), os.FileMode(0600)
root, err := ioutil.TempDir(dir, prefix)
if err != nil {
vlog.Errorf("TempDir(%v, %v) failed: %v", dir, prefix, err)
- return nil, errOperationFailed
+ return nil, errInternalError
}
defer os.RemoveAll(root)
srcDir := filepath.Join(root, "go", "src")
if err := os.MkdirAll(srcDir, dirPerm); err != nil {
vlog.Errorf("MkdirAll(%v, %v) failed: %v", srcDir, dirPerm, err)
- return nil, errOperationFailed
+ return nil, errInternalError
}
for {
srcFile, err := stream.Recv()
if err != nil && err != io.EOF {
vlog.Errorf("Recv() failed: %v", err)
- return nil, errOperationFailed
+ return nil, errInternalError
}
if err == io.EOF {
break
@@ -60,21 +65,50 @@
dir := filepath.Dir(filePath)
if err := os.MkdirAll(dir, dirPerm); err != nil {
vlog.Errorf("MkdirAll(%v, %v) failed: %v", dir, dirPerm, err)
- return nil, errOperationFailed
+ return nil, errInternalError
}
if err := ioutil.WriteFile(filePath, srcFile.Contents, filePerm); err != nil {
vlog.Errorf("WriteFile(%v, %v) failed: %v", filePath, filePerm, err)
- return nil, errOperationFailed
+ return nil, errInternalError
}
}
- cmd := exec.Command(i.gobin, "build", "-v", "...")
+ cmd := exec.Command(i.gobin, "install", "-v", "...")
cmd.Env = append(cmd.Env, "GOPATH="+filepath.Dir(srcDir))
- bytes, err := cmd.CombinedOutput()
- if err != nil {
- vlog.Errorf("CombinedOutput() failed: %v", err)
- return nil, errOperationFailed
+ var output bytes.Buffer
+ cmd.Stdout = &output
+ cmd.Stderr = &output
+ if err := cmd.Run(); err != nil {
+ vlog.Errorf("Run() failed: %v", err)
+ if output.Len() != 0 {
+ vlog.Errorf("%v", output.String())
+ }
+ return output.Bytes(), errBuildFailed
}
- return bytes, nil
+ binDir := filepath.Join(root, "go", "bin")
+ files, err := ioutil.ReadDir(binDir)
+ if err != nil {
+ vlog.Errorf("ReadDir(%v) failed: %v", binDir, err)
+ return nil, errInternalError
+ }
+ // TODO(jsimsa): Analyze the binary files for non-standard shared
+ // library dependencies.
+ for _, file := range files {
+ binPath := filepath.Join(root, "go", "bin", file.Name())
+ bytes, err := ioutil.ReadFile(binPath)
+ if err != nil {
+ vlog.Errorf("ReadFile(%v) failed: %v", binPath, err)
+ return nil, errInternalError
+ }
+ result := build.File{
+ Name: "bin/" + file.Name(),
+ Contents: bytes,
+ }
+ if err := stream.Send(result); err != nil {
+ vlog.Errorf("Send() failed: %v", err)
+ return nil, errInternalError
+ }
+ }
+ return output.Bytes(), nil
}
func (i *invoker) Describe(_ ipc.ServerContext, name string) (binary.Description, error) {
diff --git a/services/mgmt/build/impl/util.go b/services/mgmt/build/impl/util.go
new file mode 100644
index 0000000..2710ae9
--- /dev/null
+++ b/services/mgmt/build/impl/util.go
@@ -0,0 +1,59 @@
+package impl
+
+import (
+ "runtime"
+
+ "veyron2/services/mgmt/build"
+)
+
+func getArch() build.Architecture {
+ switch runtime.GOARCH {
+ case "386":
+ return build.X86
+ case "amd64":
+ return build.AMD64
+ case "arm":
+ return build.ARM
+ default:
+ return build.UnsupportedArchitecture
+ }
+}
+
+func getOS() build.OperatingSystem {
+ switch runtime.GOOS {
+ case "darwin":
+ return build.Darwin
+ case "linux":
+ return build.Linux
+ case "windows":
+ return build.Windows
+ default:
+ return build.UnsupportedOperatingSystem
+ }
+}
+
+func archString(arch build.Architecture) string {
+ switch arch {
+ case build.X86:
+ return "x86"
+ case build.AMD64:
+ return "amd64"
+ case build.ARM:
+ return "arm"
+ default:
+ return "unsupported"
+ }
+}
+
+func osString(os build.OperatingSystem) string {
+ switch os {
+ case build.Darwin:
+ return "darwin"
+ case build.Linux:
+ return "linux"
+ case build.Windows:
+ return "windows"
+ default:
+ return "unsupported"
+ }
+}
diff --git a/services/mgmt/node/impl/invoker.go b/services/mgmt/node/impl/invoker.go
index 565d6d8..ed450c6 100644
--- a/services/mgmt/node/impl/invoker.go
+++ b/services/mgmt/node/impl/invoker.go
@@ -41,8 +41,7 @@
"time"
"veyron/lib/config"
- "veyron/services/mgmt/build"
- cbinary "veyron/services/mgmt/lib/binary"
+ blib "veyron/services/mgmt/lib/binary"
vexec "veyron/services/mgmt/lib/exec"
"veyron/services/mgmt/profile"
@@ -52,6 +51,7 @@
"veyron2/rt"
"veyron2/services/mgmt/application"
"veyron2/services/mgmt/binary"
+ "veyron2/services/mgmt/build"
"veyron2/services/mgmt/node"
"veyron2/services/mgmt/repository"
"veyron2/verror"
@@ -119,30 +119,30 @@
// TODO(jsimsa): Avoid computing the host node description from
// scratch if a recent cached copy exists.
func (i *invoker) computeNodeProfile() (*profile.Specification, error) {
- result := profile.Specification{Format: profile.Format{Attributes: make(map[string]string)}}
+ result := profile.Specification{}
// Find out what the supported file format, operating system, and
// architecture is.
switch runtime.GOOS {
- case "linux":
- result.Format.Name = build.ELF.String()
- result.Format.Attributes["os"] = build.LINUX.String()
case "darwin":
- result.Format.Name = build.MACH.String()
- result.Format.Attributes["os"] = build.DARWIN.String()
+ result.Format = build.MACH
+ result.OS = build.Darwin
+ case "linux":
+ result.Format = build.ELF
+ result.OS = build.Linux
case "windows":
- result.Format.Name = build.PE.String()
- result.Format.Attributes["os"] = build.WINDOWS.String()
+ result.Format = build.PE
+ result.OS = build.Windows
default:
return nil, errors.New("Unsupported operating system: " + runtime.GOOS)
}
switch runtime.GOARCH {
case "amd64":
- result.Format.Attributes["arch"] = build.AMD64.String()
+ result.Arch = build.AMD64
case "arm":
- result.Format.Attributes["arch"] = build.AMD64.String()
+ result.Arch = build.ARM
case "x86":
- result.Format.Attributes["arch"] = build.AMD64.String()
+ result.Arch = build.X86
default:
return nil, errors.New("Unsupported hardware architecture: " + runtime.GOARCH)
}
@@ -269,13 +269,13 @@
result := node.Description{Profiles: make(map[string]struct{})}
loop:
for _, profile := range known {
- if profile.Format.Name != p.Format.Name {
+ if profile.Format != p.Format {
continue
}
- if profile.Format.Attributes["os"] != p.Format.Attributes["os"] {
+ if profile.OS != p.OS {
continue
}
- if profile.Format.Attributes["arch"] != p.Format.Attributes["arch"] {
+ if profile.Arch != p.Arch {
continue
}
for library := range profile.Libraries {
@@ -331,7 +331,7 @@
// APPLICATION INTERFACE IMPLEMENTATION
func downloadBinary(workspace, name string) error {
- data, err := cbinary.Download(name)
+ data, err := blib.Download(name)
if err != nil {
vlog.Errorf("Download(%v) failed: %v", name, err)
return errOperationFailed
diff --git a/services/mgmt/profile/impl/impl_test.go b/services/mgmt/profile/impl/impl_test.go
index bb52ef9..ca9ff10 100644
--- a/services/mgmt/profile/impl/impl_test.go
+++ b/services/mgmt/profile/impl/impl_test.go
@@ -10,15 +10,18 @@
"veyron2/naming"
"veyron2/rt"
+ "veyron2/services/mgmt/build"
)
var (
// spec is an example profile specification used throughout the test.
spec = profile.Specification{
- Format: profile.Format{Name: "elf", Attributes: map[string]string{"os": "linux", "arch": "amd64"}},
+ Arch: build.AMD64,
+ Description: "Example profile to test the profile repository implementation.",
+ Format: build.ELF,
Libraries: map[profile.Library]struct{}{profile.Library{Name: "foo", MajorVersion: "1", MinorVersion: "0"}: struct{}{}},
Label: "example",
- Description: "Example profile to test the profile repository implementation.",
+ OS: build.Linux,
}
)
diff --git a/services/mgmt/profile/profile.vdl b/services/mgmt/profile/profile.vdl
index d37c59b..0f6338b 100644
--- a/services/mgmt/profile/profile.vdl
+++ b/services/mgmt/profile/profile.vdl
@@ -2,16 +2,7 @@
// types used by the implementation of Veyron profiles.
package profile
-// Format includes a type (e.g. ELF) and each instance of the format
-// has some specific attributes. The key attributes are the target
-// operating system (e.g. for ELF this could be one of System V,
-// HP-UX, NetBSD, Linux, Solaris, AIX, IRIX, FreeBSD, and OpenBSD) and
-// the target instruction set architecture (e.g. for ELF this could be
-// one of SPARC, x86, PowerPC, ARM, IA-64, x86-64, and AArch64).
-type Format struct {
- Name string
- Attributes map[string]string
-}
+import "veyron2/services/mgmt/build"
// Library describes a shared library that applications may use.
type Library struct {
@@ -26,12 +17,17 @@
// Specification is how we represent a profile internally. It should
// provide enough information to allow matching of binaries to nodes.
type Specification struct {
- // Format is the file format of the application binary.
- Format Format
- // Libraries is a set of libraries the application binary depends on.
- Libraries set[Library]
- // A human-friendly concise label for the profile, e.g. "linux-media"
- Label string
- // A human-friendly description of the profile.
+ // Arch is the target hardware architecture of the profile.
+ Arch build.Architecture
+ // Description is a human-friendly description of the profile.
Description string
+ // Format is the file format supported by the profile.
+ Format build.Format
+ // Libraries is a set of libraries the profile requires.
+ Libraries set[Library]
+ // Label is a human-friendly concise label for the profile,
+ // e.g. "linux-media".
+ Label string
+ // OS is the target operating system of the profile.
+ OS build.OperatingSystem
}
diff --git a/services/mgmt/profile/profile.vdl.go b/services/mgmt/profile/profile.vdl.go
index c219f26..8ece520 100644
--- a/services/mgmt/profile/profile.vdl.go
+++ b/services/mgmt/profile/profile.vdl.go
@@ -5,16 +5,9 @@
// types used by the implementation of Veyron profiles.
package profile
-// Format includes a type (e.g. ELF) and each instance of the format
-// has some specific attributes. The key attributes are the target
-// operating system (e.g. for ELF this could be one of System V,
-// HP-UX, NetBSD, Linux, Solaris, AIX, IRIX, FreeBSD, and OpenBSD) and
-// the target instruction set architecture (e.g. for ELF this could be
-// one of SPARC, x86, PowerPC, ARM, IA-64, x86-64, and AArch64).
-type Format struct {
- Name string
- Attributes map[string]string
-}
+import (
+ "veyron2/services/mgmt/build"
+)
// Library describes a shared library that applications may use.
type Library struct {
@@ -29,12 +22,17 @@
// Specification is how we represent a profile internally. It should
// provide enough information to allow matching of binaries to nodes.
type Specification struct {
- // Format is the file format of the application binary.
- Format Format
- // Libraries is a set of libraries the application binary depends on.
- Libraries map[Library]struct{}
- // A human-friendly concise label for the profile, e.g. "linux-media"
- Label string
- // A human-friendly description of the profile.
+ // Arch is the target hardware architecture of the profile.
+ Arch build.Architecture
+ // Description is a human-friendly description of the profile.
Description string
+ // Format is the file format supported by the profile.
+ Format build.Format
+ // Libraries is a set of libraries the profile requires.
+ Libraries map[Library]struct{}
+ // Label is a human-friendly concise label for the profile,
+ // e.g. "linux-media".
+ Label string
+ // OS is the target operating system of the profile.
+ OS build.OperatingSystem
}
diff --git a/services/mgmt/repository/repository.vdl.go b/services/mgmt/repository/repository.vdl.go
index f6bcc37..83bc841 100644
--- a/services/mgmt/repository/repository.vdl.go
+++ b/services/mgmt/repository/repository.vdl.go
@@ -523,46 +523,42 @@
result := _gen_ipc.ServiceSignature{Methods: make(map[string]_gen_ipc.MethodSignature)}
result.Methods["Put"] = _gen_ipc.MethodSignature{
InArgs: []_gen_ipc.MethodArgument{
- {Name: "Specification", Type: 69},
+ {Name: "Specification", Type: 70},
},
OutArgs: []_gen_ipc.MethodArgument{
- {Name: "", Type: 70},
+ {Name: "", Type: 71},
},
}
result.Methods["Remove"] = _gen_ipc.MethodSignature{
InArgs: []_gen_ipc.MethodArgument{},
OutArgs: []_gen_ipc.MethodArgument{
- {Name: "", Type: 70},
+ {Name: "", Type: 71},
},
}
result.Methods["Specification"] = _gen_ipc.MethodSignature{
InArgs: []_gen_ipc.MethodArgument{},
OutArgs: []_gen_ipc.MethodArgument{
- {Name: "", Type: 69},
{Name: "", Type: 70},
+ {Name: "", Type: 71},
},
}
result.TypeDefs = []_gen_vdlutil.Any{
- _gen_wiretype.MapType{Key: 0x3, Elem: 0x3, Name: "", Tags: []string(nil)}, _gen_wiretype.StructType{
- []_gen_wiretype.FieldType{
- _gen_wiretype.FieldType{Type: 0x3, Name: "Name"},
- _gen_wiretype.FieldType{Type: 0x41, Name: "Attributes"},
- },
- "veyron/services/mgmt/profile.Format", []string(nil)},
- _gen_wiretype.StructType{
+ _gen_wiretype.NamedPrimitiveType{Type: 0x32, Name: "veyron2/services/mgmt/build.Architecture", Tags: []string(nil)}, _gen_wiretype.NamedPrimitiveType{Type: 0x32, Name: "veyron2/services/mgmt/build.Format", Tags: []string(nil)}, _gen_wiretype.StructType{
[]_gen_wiretype.FieldType{
_gen_wiretype.FieldType{Type: 0x3, Name: "Name"},
_gen_wiretype.FieldType{Type: 0x3, Name: "MajorVersion"},
_gen_wiretype.FieldType{Type: 0x3, Name: "MinorVersion"},
},
"veyron/services/mgmt/profile.Library", []string(nil)},
- _gen_wiretype.MapType{Key: 0x43, Elem: 0x2, Name: "", Tags: []string(nil)}, _gen_wiretype.StructType{
+ _gen_wiretype.MapType{Key: 0x43, Elem: 0x2, Name: "", Tags: []string(nil)}, _gen_wiretype.NamedPrimitiveType{Type: 0x32, Name: "veyron2/services/mgmt/build.OperatingSystem", Tags: []string(nil)}, _gen_wiretype.StructType{
[]_gen_wiretype.FieldType{
+ _gen_wiretype.FieldType{Type: 0x41, Name: "Arch"},
+ _gen_wiretype.FieldType{Type: 0x3, Name: "Description"},
_gen_wiretype.FieldType{Type: 0x42, Name: "Format"},
_gen_wiretype.FieldType{Type: 0x44, Name: "Libraries"},
_gen_wiretype.FieldType{Type: 0x3, Name: "Label"},
- _gen_wiretype.FieldType{Type: 0x3, Name: "Description"},
+ _gen_wiretype.FieldType{Type: 0x45, Name: "OS"},
},
"veyron/services/mgmt/profile.Specification", []string(nil)},
_gen_wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
diff --git a/services/store/typeregistryhack/init.go b/services/store/typeregistryhack/init.go
index 84a8f00..72b5216 100644
--- a/services/store/typeregistryhack/init.go
+++ b/services/store/typeregistryhack/init.go
@@ -5,10 +5,7 @@
package typeregistryhack
import (
- "veyron/services/mgmt/profile"
- "veyron2/services/mgmt/application"
-
- // Register boxes types
+ // Register boxes types.
"veyron/examples/boxes"
// Register mdb types.
_ "veyron/examples/storage/mdb/schema"
@@ -18,6 +15,12 @@
_ "veyron/examples/bank/schema"
// Register stfortune types.
_ "veyron/examples/stfortune/schema"
+ // Register profile types.
+ "veyron/services/mgmt/profile"
+ // Register application types.
+ "veyron2/services/mgmt/application"
+ // Register build types.
+ _ "veyron2/services/mgmt/build"
"veyron2/vom"
)
diff --git a/tools/profile/impl/impl.go b/tools/profile/impl/impl.go
index cef78c8..b90e8a6 100644
--- a/tools/profile/impl/impl.go
+++ b/tools/profile/impl/impl.go
@@ -8,6 +8,7 @@
"veyron/services/mgmt/repository"
"veyron2/rt"
+ "veyron2/services/mgmt/build"
)
var cmdLabel = &cmdline.Command{
@@ -105,10 +106,12 @@
// TODO(rthellend): Read an actual specification from a file.
spec := profile.Specification{
- Format: profile.Format{Name: "elf", Attributes: map[string]string{"os": "linux", "arch": "amd64"}},
+ Arch: build.AMD64,
+ Description: "Example profile to test the profile manager implementation.",
+ Format: build.ELF,
Libraries: map[profile.Library]struct{}{profile.Library{Name: "foo", MajorVersion: "1", MinorVersion: "0"}: struct{}{}},
Label: "example",
- Description: "Example profile to test the profile manager implementation.",
+ OS: build.Linux,
}
if err := p.Put(rt.R().NewContext(), spec); err != nil {
return err
diff --git a/tools/profile/impl/impl_test.go b/tools/profile/impl/impl_test.go
index 8500787..45ccf14 100644
--- a/tools/profile/impl/impl_test.go
+++ b/tools/profile/impl/impl_test.go
@@ -15,16 +15,19 @@
"veyron2/naming"
"veyron2/rt"
"veyron2/security"
+ "veyron2/services/mgmt/build"
"veyron2/vlog"
)
var (
// spec is an example profile specification used throughout the test.
spec = profile.Specification{
- Format: profile.Format{Name: "elf", Attributes: map[string]string{"os": "linux"}},
+ Arch: build.AMD64,
+ Description: "Example profile to test the profile repository implementation.",
+ Format: build.ELF,
Libraries: map[profile.Library]struct{}{profile.Library{Name: "foo", MajorVersion: "1", MinorVersion: "0"}: struct{}{}},
Label: "example",
- Description: "Example profile to test the profile repository implementation.",
+ OS: build.Linux,
}
)