2016-05-27 17:35:42 +00:00
|
|
|
package runtime
|
|
|
|
|
|
|
|
import (
|
2016-07-15 18:49:43 +00:00
|
|
|
"flag"
|
2016-05-27 17:35:42 +00:00
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"path/filepath"
|
|
|
|
"syscall"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
utils "github.com/docker/containerd/testutils"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2016-07-15 18:49:43 +00:00
|
|
|
devNull = "/dev/null"
|
|
|
|
stdin io.WriteCloser
|
2016-06-16 21:39:19 +00:00
|
|
|
runtimeTool = flag.String("runtime", "runc", "Runtime to use for this test")
|
2016-05-27 17:35:42 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Create containerd state and oci bundles directory
|
|
|
|
func setup() error {
|
|
|
|
if err := os.MkdirAll(utils.StateDir, 0755); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.MkdirAll(utils.BundlesRoot, 0755); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creates the bundleDir with rootfs, io fifo dir and a default spec.
|
|
|
|
// On success, returns the bundlePath
|
|
|
|
func setupBundle(bundleName string) (string, error) {
|
|
|
|
bundlePath := filepath.Join(utils.BundlesRoot, bundleName)
|
|
|
|
if err := os.MkdirAll(bundlePath, 0755); err != nil {
|
|
|
|
fmt.Println("Unable to create bundlePath due to ", err)
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
io := filepath.Join(bundlePath, "io")
|
|
|
|
if err := os.MkdirAll(io, 0755); err != nil {
|
|
|
|
fmt.Println("Unable to create io dir due to ", err)
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := utils.GenerateReferenceSpecs(bundlePath); err != nil {
|
|
|
|
fmt.Println("Unable to generate OCI reference spec: ", err)
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := utils.CreateBusyboxBundle(bundleName); err != nil {
|
|
|
|
fmt.Println("CreateBusyboxBundle error: ", err)
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return bundlePath, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func setupStdio(cwd string, bundlePath string, bundleName string) (Stdio, error) {
|
|
|
|
s := NewStdio(devNull, devNull, devNull)
|
|
|
|
|
|
|
|
pid := "init"
|
|
|
|
for stdName, stdPath := range map[string]*string{
|
|
|
|
"stdin": &s.Stdin,
|
|
|
|
"stdout": &s.Stdout,
|
|
|
|
"stderr": &s.Stderr,
|
|
|
|
} {
|
|
|
|
*stdPath = filepath.Join(cwd, bundlePath, "io", bundleName+"-"+pid+"-"+stdName)
|
|
|
|
if err := syscall.Mkfifo(*stdPath, 0755); err != nil && !os.IsExist(err) {
|
|
|
|
fmt.Println("Mkfifo error: ", err)
|
|
|
|
return s, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err := attachStdio(s)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println("attachStdio error: ", err)
|
|
|
|
return s, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return s, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func attachStdio(s Stdio) error {
|
|
|
|
stdinf, err := os.OpenFile(s.Stdin, syscall.O_RDWR, 0)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
stdin = stdinf
|
|
|
|
stdoutf, err := os.OpenFile(s.Stdout, syscall.O_RDWR, 0)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
go io.Copy(os.Stdout, stdoutf)
|
|
|
|
stderrf, err := os.OpenFile(s.Stderr, syscall.O_RDWR, 0)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
go io.Copy(os.Stderr, stderrf)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func teardownBundle(bundleName string) {
|
|
|
|
containerRoot := filepath.Join(utils.StateDir, bundleName)
|
|
|
|
os.RemoveAll(containerRoot)
|
|
|
|
|
|
|
|
bundlePath := filepath.Join(utils.BundlesRoot, bundleName)
|
|
|
|
os.RemoveAll(bundlePath)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove containerd state and oci bundles directory
|
|
|
|
func teardown() {
|
|
|
|
os.RemoveAll(utils.StateDir)
|
|
|
|
os.RemoveAll(utils.BundlesRoot)
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkBusyboxSh(b *testing.B) {
|
|
|
|
bundleName := "busybox-sh"
|
|
|
|
|
|
|
|
wd := utils.GetTestOutDir()
|
|
|
|
if err := os.Chdir(wd); err != nil {
|
|
|
|
b.Fatalf("Could not change working directory: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := setup(); err != nil {
|
|
|
|
b.Fatalf("Error setting up test: %v", err)
|
|
|
|
}
|
|
|
|
defer teardown()
|
|
|
|
|
|
|
|
for n := 0; n < b.N; n++ {
|
|
|
|
bundlePath, err := setupBundle(bundleName)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
s, err := setupStdio(wd, bundlePath, bundleName)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
c, err := New(ContainerOpts{
|
|
|
|
Root: utils.StateDir,
|
|
|
|
ID: bundleName,
|
|
|
|
Bundle: filepath.Join(wd, bundlePath),
|
2016-06-16 21:39:19 +00:00
|
|
|
Runtime: *runtimeTool,
|
2016-05-27 17:35:42 +00:00
|
|
|
Shim: "containerd-shim",
|
|
|
|
Timeout: 15 * time.Second,
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
b.Fatalf("Error creating a New container: ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
benchmarkStartContainer(b, c, s, bundleName)
|
|
|
|
|
|
|
|
teardownBundle(bundleName)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func benchmarkStartContainer(b *testing.B, c Container, s Stdio, bundleName string) {
|
2016-07-15 18:49:43 +00:00
|
|
|
p, err := c.Start("", s)
|
|
|
|
if err != nil {
|
2016-05-27 17:35:42 +00:00
|
|
|
b.Fatalf("Error starting container %v", err)
|
|
|
|
}
|
|
|
|
|
2016-06-16 21:39:19 +00:00
|
|
|
kill := exec.Command(c.Runtime(), "kill", bundleName, "KILL")
|
2016-05-27 17:35:42 +00:00
|
|
|
kill.Run()
|
|
|
|
|
2016-07-15 18:49:43 +00:00
|
|
|
p.Wait()
|
|
|
|
c.Delete()
|
|
|
|
|
2016-05-27 17:35:42 +00:00
|
|
|
// wait for kill to finish. selected wait time is arbitrary
|
|
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
|
|
|
|
}
|