Example #1
0
// applyLayerHandler parses a diff in the standard layer format from `layer`, and
// applies it to the directory `dest`. Returns the size in bytes of the
// contents of the layer.
func applyLayerHandler(dest string, layer archive.ArchiveReader, decompress bool) (size int64, err error) {
	dest = filepath.Clean(dest)
	if decompress {
		decompressed, err := archive.DecompressStream(layer)
		if err != nil {
			return 0, err
		}
		defer decompressed.Close()

		layer = decompressed
	}

	cmd := reexec.Command("docker-applyLayer", dest)
	cmd.Stdin = layer

	outBuf, errBuf := new(bytes.Buffer), new(bytes.Buffer)
	cmd.Stdout, cmd.Stderr = outBuf, errBuf

	if err = cmd.Run(); err != nil {
		return 0, fmt.Errorf("ApplyLayer %s stdout: %s stderr: %s", err, outBuf, errBuf)
	}

	// Stdout should be a valid JSON struct representing an applyLayerResponse.
	response := applyLayerResponse{}
	decoder := json.NewDecoder(outBuf)
	if err = decoder.Decode(&response); err != nil {
		return 0, fmt.Errorf("unable to decode ApplyLayer JSON response: %s", err)
	}

	return response.LayerSize, nil
}
Example #2
0
func mountFrom(dir, device, target, mType string, flags uintptr, label string) error {
	options := &mountOptions{
		Device: device,
		Target: target,
		Type:   mType,
		Flag:   uint32(flags),
		Label:  label,
	}

	cmd := reexec.Command("docker-mountfrom", dir)
	w, err := cmd.StdinPipe()
	if err != nil {
		return fmt.Errorf("mountfrom error on pipe creation: %v", err)
	}

	output := bytes.NewBuffer(nil)
	cmd.Stdout = output
	cmd.Stderr = output

	if err := cmd.Start(); err != nil {
		return fmt.Errorf("mountfrom error on re-exec cmd: %v", err)
	}
	//write the options to the pipe for the untar exec to read
	if err := json.NewEncoder(w).Encode(options); err != nil {
		return fmt.Errorf("mountfrom json encode to pipe failed: %v", err)
	}
	w.Close()

	if err := cmd.Wait(); err != nil {
		return fmt.Errorf("mountfrom re-exec error: %v: output: %s", err, output)
	}
	return nil
}
Example #3
0
func (r *RootfsWriter) WriteFile(log lager.Logger, filePath string, contents []byte, rootfsPath string, rootUid, rootGid int) error {
	cmd := reexec.Command("chrootwrite",
		"-rootfs", rootfsPath,
		"-path", filePath,
		"-uid", strconv.Itoa(rootUid),
		"-gid", strconv.Itoa(rootGid),
	)

	stdin, err := cmd.StdinPipe()
	if err != nil {
		return err
	}

	if err = cmd.Start(); err != nil {
		return err
	}

	if _, err = stdin.Write(contents); err != nil {
		return err
	}

	if err = stdin.Close(); err != nil {
		return err
	}

	return cmd.Wait()
}
Example #4
0
func invokeUnpack(decompressedArchive io.ReadCloser, dest string, options *archive.TarOptions) error {

	// We can't pass a potentially large exclude list directly via cmd line
	// because we easily overrun the kernel's max argument/environment size
	// when the full image list is passed (e.g. when this is used by
	// `docker load`). We will marshall the options via a pipe to the
	// child
	r, w, err := os.Pipe()
	if err != nil {
		return fmt.Errorf("Untar pipe failure: %v", err)
	}

	cmd := reexec.Command("docker-untar", dest)
	cmd.Stdin = decompressedArchive

	cmd.ExtraFiles = append(cmd.ExtraFiles, r)
	output := bytes.NewBuffer(nil)
	cmd.Stdout = output
	cmd.Stderr = output

	if err := cmd.Start(); err != nil {
		return fmt.Errorf("Untar error on re-exec cmd: %v", err)
	}
	//write the options to the pipe for the untar exec to read
	if err := json.NewEncoder(w).Encode(options); err != nil {
		return fmt.Errorf("Untar json encode to pipe failed: %v", err)
	}
	w.Close()

	if err := cmd.Wait(); err != nil {
		return fmt.Errorf("Untar re-exec error: %v: output: %s", err, output)
	}
	return nil
}
Example #5
0
File: diff.go Project: NERSC/docker
func ApplyLayer(dest string, layer archive.ArchiveReader) error {
	cmd := reexec.Command("docker-applyLayer", dest)
	cmd.Stdin = layer
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("ApplyLayer %s %s", err, out)
	}
	return nil
}
Example #6
0
func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error {
	if tarArchive == nil {
		return fmt.Errorf("Empty archive")
	}
	if options == nil {
		options = &archive.TarOptions{}
	}
	if options.ExcludePatterns == nil {
		options.ExcludePatterns = []string{}
	}

	dest = filepath.Clean(dest)
	if _, err := os.Stat(dest); os.IsNotExist(err) {
		if err := os.MkdirAll(dest, 0777); err != nil {
			return err
		}
	}

	decompressedArchive, err := archive.DecompressStream(tarArchive)
	if err != nil {
		return err
	}
	defer decompressedArchive.Close()

	// We can't pass a potentially large exclude list directly via cmd line
	// because we easily overrun the kernel's max argument/environment size
	// when the full image list is passed (e.g. when this is used by
	// `docker load`). We will marshall the options via a pipe to the
	// child
	r, w, err := os.Pipe()
	if err != nil {
		return fmt.Errorf("Untar pipe failure: %v", err)
	}
	cmd := reexec.Command("docker-untar", dest)
	cmd.Stdin = decompressedArchive
	cmd.ExtraFiles = append(cmd.ExtraFiles, r)
	var output bytes.Buffer
	cmd.Stdout = &output
	cmd.Stderr = &output

	if err := cmd.Start(); err != nil {
		return fmt.Errorf("Untar error on re-exec cmd: %v", err)
	}
	//write the options to the pipe for the untar exec to read
	if err := json.NewEncoder(w).Encode(options); err != nil {
		return fmt.Errorf("Untar json encode to pipe failed: %v", err)
	}
	w.Close()

	if err := cmd.Wait(); err != nil {
		return fmt.Errorf("Untar re-exec error: %v: output: %s", err, output)
	}
	return nil
}
Example #7
0
func reexecInNamespace(args ...string) {
	reexecArgs := append([]string{"namespaced"}, args...)
	cmd := reexec.Command(reexecArgs...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Cloneflags: syscall.CLONE_NEWNS,
	}

	if err := cmd.Run(); err != nil {
		fmt.Printf("secret garden exec failed: %s\n", err)
		os.Exit(1)
	}
}
Example #8
0
func Command(rootfsPath string, uid, gid int, mode os.FileMode, recreate bool, paths ...string) *exec.Cmd {
	flags := []string{
		name,
		"-rootfsPath", rootfsPath,
		"-uid", strconv.Itoa(uid),
		"-gid", strconv.Itoa(gid),
		"-perm", strconv.Itoa(int(mode.Perm())),
	}

	if recreate {
		flags = append(flags, "-recreate=true")
	}

	return reexec.Command(append(flags, paths...)...)
}
Example #9
0
func runEnqueue(t *testing.T, filename, from, to string) {
	cmd := reexec.Command("enqueue", filename, from, to)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Start(); err != nil {
		t.Fatal(err)
	}
	go func() {
		if err := cmd.Wait(); err != nil {
			t.Fatal(err)
		}
	}()

}
Example #10
0
func runAllocate(t *testing.T, wg *sync.WaitGroup, memoryRegion, size, qty string) {
	cmd := reexec.Command("allocate", memoryRegion, size, qty)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Start(); err != nil {
		t.Fatal(err)
	}
	go func() {
		defer wg.Done()
		if err := cmd.Wait(); err != nil {
			t.Fatal(err)
		}
	}()
}
Example #11
0
// importLayer adds a new layer to the tag and graph store based on the given data.
func (d *Driver) importLayer(id string, layerData archive.Reader, parentLayerPaths []string) (size int64, err error) {
	cmd := reexec.Command(append([]string{"docker-windows-write-layer", d.info.HomeDir, id}, parentLayerPaths...)...)
	output := bytes.NewBuffer(nil)
	cmd.Stdin = layerData
	cmd.Stdout = output
	cmd.Stderr = output

	if err = cmd.Start(); err != nil {
		return
	}

	if err = cmd.Wait(); err != nil {
		return 0, fmt.Errorf("re-exec error: %v: output: %s", err, output)
	}

	return strconv.ParseInt(output.String(), 10, 64)
}
Example #12
0
func (c *Container) Apply(log lager.Logger, cfg kawasaki.NetworkConfig, pid int) error {
	netns, err := c.FileOpener.Open(fmt.Sprintf("/proc/%d/ns/net", pid))
	if err != nil {
		return err
	}
	defer netns.Close()

	log = log.Session("configure-container-netns", lager.Data{
		"networkConfig": cfg,
		"netNsPath":     netns.Name(),
	})

	cmd := reexec.Command("configure-container-netns",
		"-netNsPath", netns.Name(),
		"-containerIntf", cfg.ContainerIntf,
		"-containerIP", cfg.ContainerIP.String(),
		"-bridgeIP", cfg.BridgeIP.String(),
		"-subnet", cfg.Subnet.String(),
		"-mtu", strconv.FormatInt(int64(cfg.Mtu), 10),
	)

	errBuf := bytes.NewBuffer([]byte{})
	cmd.Stderr = errBuf

	if err := cmd.Start(); err != nil {
		log.Error("starting-command", errors.New(errBuf.String()))
		return err
	}

	if err := cmd.Wait(); err != nil {
		status, err := exitStatus(err)
		if err != nil {
			log.Error("waiting-for-command", errors.New(errBuf.String()))
			return err
		}

		if status == 1 {
			return errors.New(errBuf.String())
		}

		log.Error("unexpected-error", errors.New(errBuf.String()))
		return errors.New("unexpected error")
	}

	return nil
}
Example #13
0
// applyLayerHandler parses a diff in the standard layer format from `layer`, and
// applies it to the directory `dest`. Returns the size in bytes of the
// contents of the layer.
func applyLayerHandler(dest string, layer io.Reader, options *archive.TarOptions, decompress bool) (size int64, err error) {
	dest = filepath.Clean(dest)
	if decompress {
		decompressed, err := archive.DecompressStream(layer)
		if err != nil {
			return 0, err
		}
		defer decompressed.Close()

		layer = decompressed
	}
	if options == nil {
		options = &archive.TarOptions{}
		if rsystem.RunningInUserNS() {
			options.InUserNS = true
		}
	}
	if options.ExcludePatterns == nil {
		options.ExcludePatterns = []string{}
	}

	data, err := json.Marshal(options)
	if err != nil {
		return 0, fmt.Errorf("ApplyLayer json encode: %v", err)
	}

	cmd := reexec.Command("docker-applyLayer", dest)
	cmd.Stdin = layer
	cmd.Env = append(cmd.Env, fmt.Sprintf("OPT=%s", data))

	outBuf, errBuf := new(bytes.Buffer), new(bytes.Buffer)
	cmd.Stdout, cmd.Stderr = outBuf, errBuf

	if err = cmd.Run(); err != nil {
		return 0, fmt.Errorf("ApplyLayer %s stdout: %s stderr: %s", err, outBuf, errBuf)
	}

	// Stdout should be a valid JSON struct representing an applyLayerResponse.
	response := applyLayerResponse{}
	decoder := json.NewDecoder(outBuf)
	if err = decoder.Decode(&response); err != nil {
		return 0, fmt.Errorf("unable to decode ApplyLayer JSON response: %s", err)
	}

	return response.LayerSize, nil
}
Example #14
0
func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error {
	if tarArchive == nil {
		return fmt.Errorf("Empty archive")
	}
	if options == nil {
		options = &archive.TarOptions{}
	}
	if options.ExcludePatterns == nil {
		options.ExcludePatterns = []string{}
	}

	dest = filepath.Clean(dest)
	if _, err := os.Stat(dest); os.IsNotExist(err) {
		if err := os.MkdirAll(dest, 0777); err != nil {
			return err
		}
	}

	// We can't pass the exclude list directly via cmd line
	// because we easily overrun the shell max argument list length
	// when the full image list is passed (e.g. when this is used
	// by `docker load`). Instead we will add the JSON marshalled
	// and placed in the env, which has significantly larger
	// max size
	data, err := json.Marshal(options)
	if err != nil {
		return fmt.Errorf("Untar json encode: %v", err)
	}
	decompressedArchive, err := archive.DecompressStream(tarArchive)
	if err != nil {
		return err
	}
	defer decompressedArchive.Close()

	cmd := reexec.Command("docker-untar", dest)
	cmd.Stdin = decompressedArchive
	cmd.Env = append(cmd.Env, fmt.Sprintf("OPT=%s", data))
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("Untar %s %s", err, out)
	}
	return nil
}
Example #15
0
func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error {
	if tarArchive == nil {
		return fmt.Errorf("Empty archive")
	}
	if options == nil {
		options = &archive.TarOptions{}
	}
	if options.ExcludePatterns == nil {
		options.ExcludePatterns = []string{}
	}

	var (
		buf bytes.Buffer
		enc = json.NewEncoder(&buf)
	)
	if err := enc.Encode(options); err != nil {
		return fmt.Errorf("Untar json encode: %v", err)
	}
	if _, err := os.Stat(dest); os.IsNotExist(err) {
		if err := os.MkdirAll(dest, 0777); err != nil {
			return err
		}
	}
	dest = filepath.Clean(dest)
	decompressedArchive, err := archive.DecompressStream(tarArchive)
	if err != nil {
		return err
	}
	defer decompressedArchive.Close()

	cmd := reexec.Command("docker-untar", dest, buf.String())
	cmd.Stdin = decompressedArchive
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("Untar %s %s", err, out)
	}
	return nil
}
	"io"

	_ "github.com/cloudfoundry-incubator/garden-linux/container_daemon/proc_starter"
	"github.com/docker/docker/pkg/reexec"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
)

var _ = Describe("proc_starter", func() {
	It("runs the process in the specified working directory", func() {
		testWorkDir, err := ioutil.TempDir("", "")
		Expect(err).ToNot(HaveOccurred())

		cmd := reexec.Command("proc_starter", "-uid=0", "-gid=0", fmt.Sprintf("-workDir=%s", testWorkDir), "--", "/bin/sh", "-c", "echo $PWD")
		op, err := cmd.CombinedOutput()
		Expect(err).ToNot(HaveOccurred())
		Expect(string(op)).To(Equal(testWorkDir + "\n"))
	})

	It("runs a program from the PATH", func() {
		cmd := reexec.Command("proc_starter", "-uid=0", "-gid=0", "-workDir=/tmp", "--", "ls", "/")
		Expect(cmd.Run()).To(Succeed())
	})

	It("sets rlimits", func() {
		cmd := reexec.Command("proc_starter", "-uid=0", "-gid=0", "-workDir=/tmp", "-rlimits=RLIMIT_NOFILE=2099,RLIMIT_CPU=3", "--", "sh", "-c", "ulimit -a")
		out := gbytes.NewBuffer()
		cmd.Stdout = io.MultiWriter(GinkgoWriter, out)
		cmd.Stderr = GinkgoWriter
Example #17
0
func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error {
	if tarArchive == nil {
		return fmt.Errorf("Empty archive")
	}
	if options == nil {
		options = &archive.TarOptions{}
	}
	if options.ExcludePatterns == nil {
		options.ExcludePatterns = []string{}
	}

	dest = filepath.Clean(dest)
	if _, err := os.Stat(dest); os.IsNotExist(err) {
		if err := system.MkdirAll(dest, 0777); err != nil {
			return err
		}
	}

	decompressedArchive, err := archive.DecompressStream(tarArchive)
	if err != nil {
		return err
	}

	var data []byte
	var r, w *os.File
	defer decompressedArchive.Close()

	if runtime.GOOS != "windows" {
		// We can't pass a potentially large exclude list directly via cmd line
		// because we easily overrun the kernel's max argument/environment size
		// when the full image list is passed (e.g. when this is used by
		// `docker load`). We will marshall the options via a pipe to the
		// child

		// This solution won't work on Windows as it will fail in golang
		// exec_windows.go as at the lowest layer because attr.Files > 3
		r, w, err = os.Pipe()
		if err != nil {
			return fmt.Errorf("Untar pipe failure: %v", err)
		}
	} else {
		// We can't pass the exclude list directly via cmd line
		// because we easily overrun the shell max argument list length
		// when the full image list is passed (e.g. when this is used
		// by `docker load`). Instead we will add the JSON marshalled
		// and placed in the env, which has significantly larger
		// max size
		data, err = json.Marshal(options)
		if err != nil {
			return fmt.Errorf("Untar json encode: %v", err)
		}
	}

	cmd := reexec.Command("docker-untar", dest)
	cmd.Stdin = decompressedArchive

	if runtime.GOOS != "windows" {
		cmd.ExtraFiles = append(cmd.ExtraFiles, r)
		output := bytes.NewBuffer(nil)
		cmd.Stdout = output
		cmd.Stderr = output

		if err := cmd.Start(); err != nil {
			return fmt.Errorf("Untar error on re-exec cmd: %v", err)
		}
		//write the options to the pipe for the untar exec to read
		if err := json.NewEncoder(w).Encode(options); err != nil {
			return fmt.Errorf("Untar json encode to pipe failed: %v", err)
		}
		w.Close()

		if err := cmd.Wait(); err != nil {
			return fmt.Errorf("Untar re-exec error: %v: output: %s", err, output)
		}
		return nil
	} else {
		cmd.Env = append(cmd.Env, fmt.Sprintf("OPT=%s", data))
		out, err := cmd.CombinedOutput()
		if err != nil {
			return fmt.Errorf("Untar %s %s", err, out)
		}
		return nil
	}

}