Files
runc/integration/utils_test.go
T
Andrey Vagin 94fb37f557 process: add Wait(), Signal() and Pid() methods
Currently we have a problem when buffers are used for std file
descriptors.  These buffers are filled from goroutines (Cmd.goroutine),
and we need to wait them to be sure that all data have been copied.

Signed-off-by: Andrew Vagin <avagin@openvz.org>
2015-02-23 23:40:41 +03:00

118 lines
2.6 KiB
Go

package integration
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"os/exec"
"strings"
"syscall"
"github.com/docker/libcontainer"
"github.com/docker/libcontainer/configs"
)
func newStdBuffers() *stdBuffers {
return &stdBuffers{
Stdin: bytes.NewBuffer(nil),
Stdout: bytes.NewBuffer(nil),
Stderr: bytes.NewBuffer(nil),
}
}
type stdBuffers struct {
Stdin *bytes.Buffer
Stdout *bytes.Buffer
Stderr *bytes.Buffer
}
func (b *stdBuffers) String() string {
s := []string{}
if b.Stderr != nil {
s = append(s, b.Stderr.String())
}
if b.Stdout != nil {
s = append(s, b.Stdout.String())
}
return strings.Join(s, "|")
}
// newRootfs creates a new tmp directory and copies the busybox root filesystem
func newRootfs() (string, error) {
dir, err := ioutil.TempDir("", "")
if err != nil {
return "", err
}
if err := os.MkdirAll(dir, 0700); err != nil {
return "", err
}
if err := copyBusybox(dir); err != nil {
return "", nil
}
return dir, nil
}
func remove(dir string) {
os.RemoveAll(dir)
}
// copyBusybox copies the rootfs for a busybox container created for the test image
// into the new directory for the specific test
func copyBusybox(dest string) error {
out, err := exec.Command("sh", "-c", fmt.Sprintf("cp -R /busybox/* %s/", dest)).CombinedOutput()
if err != nil {
return fmt.Errorf("copy error %q: %q", err, out)
}
return nil
}
func newContainer(config *configs.Config) (libcontainer.Container, error) {
factory, err := libcontainer.New(".",
libcontainer.InitArgs(os.Args[0], "init", "--"),
libcontainer.Cgroupfs,
)
if err != nil {
return nil, err
}
return factory.Create("testCT", config)
}
// runContainer runs the container with the specific config and arguments
//
// buffers are returned containing the STDOUT and STDERR output for the run
// along with the exit code and any go error
func runContainer(config *configs.Config, console string, args ...string) (buffers *stdBuffers, exitCode int, err error) {
container, err := newContainer(config)
if err != nil {
return nil, -1, err
}
defer container.Destroy()
buffers = newStdBuffers()
process := &libcontainer.Process{
Args: args,
Env: standardEnvironment,
Stdin: buffers.Stdin,
Stdout: buffers.Stdout,
Stderr: buffers.Stderr,
}
err = container.Start(process)
if err != nil {
return nil, -1, err
}
ps, err := process.Wait()
if err != nil {
return nil, -1, err
}
status := ps.Sys().(syscall.WaitStatus)
if status.Exited() {
exitCode = status.ExitStatus()
} else if status.Signaled() {
exitCode = -int(status.Signal())
} else {
return nil, -1, err
}
return
}