aboutsummaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container.go65
-rw-r--r--libpod/images/image_data.go1
-rw-r--r--libpod/oci.go8
-rw-r--r--libpod/runc.go117
-rw-r--r--libpod/runtime_img.go5
5 files changed, 188 insertions, 8 deletions
diff --git a/libpod/container.go b/libpod/container.go
index ce4d6ea84..70011963d 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -14,6 +14,7 @@ import (
"github.com/containers/storage"
"github.com/containers/storage/pkg/archive"
+ "github.com/docker/docker/daemon/caps"
"github.com/docker/docker/pkg/mount"
"github.com/docker/docker/pkg/namesgenerator"
"github.com/docker/docker/pkg/stringid"
@@ -50,6 +51,8 @@ const (
ContainerStateStopped ContainerState = iota
// ContainerStatePaused indicates that the container has been paused
ContainerStatePaused ContainerState = iota
+ // name of the directory holding the artifacts
+ artifactsDir = "artifacts"
)
// Container is a single OCI container
@@ -383,6 +386,11 @@ func (c *Container) setupStorage() error {
c.config.StaticDir = containerInfo.Dir
c.state.RunDir = containerInfo.RunDir
+ artifacts := filepath.Join(c.config.StaticDir, artifactsDir)
+ if err := os.MkdirAll(artifacts, 0755); err != nil {
+ return errors.Wrapf(err, "error creating artifacts directory %q", artifacts)
+ }
+
return nil
}
@@ -396,6 +404,11 @@ func (c *Container) teardownStorage() error {
return errors.Wrapf(ErrCtrStateInvalid, "cannot remove storage for container %s as it is running or paused", c.ID())
}
+ artifacts := filepath.Join(c.config.StaticDir, artifactsDir)
+ if err := os.RemoveAll(artifacts); err != nil {
+ return errors.Wrapf(err, "error removing artifacts %q", artifacts)
+ }
+
if err := c.cleanupStorage(); err != nil {
return errors.Wrapf(err, "failed to cleanup container %s storage", c.ID())
}
@@ -578,9 +591,36 @@ func (c *Container) Kill(signal uint) error {
}
// Exec starts a new process inside the container
-// Returns fully qualified URL of streaming server for executed process
-func (c *Container) Exec(cmd []string, tty bool, stdin bool) (string, error) {
- return "", ErrNotImplemented
+func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) error {
+ var capList []string
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ if err := c.syncContainer(); err != nil {
+ return err
+ }
+
+ conState := c.state.State
+
+ if conState != ContainerStateRunning {
+ return errors.Errorf("cannot attach to container that is not running")
+ }
+ if privileged {
+ capList = caps.GetAllCapabilities()
+ }
+ globalOpts := runcGlobalOptions{
+ log: c.LogPath(),
+ }
+ execOpts := runcExecOptions{
+ capAdd: capList,
+ pidFile: filepath.Join(c.state.RunDir, fmt.Sprintf("%s-execpid", stringid.GenerateNonCryptoID()[:12])),
+ env: env,
+ user: user,
+ cwd: c.config.Spec.Process.Cwd,
+ tty: tty,
+ }
+
+ return c.runtime.ociRuntime.execContainer(c, cmd, globalOpts, execOpts)
}
// Attach attaches to a container
@@ -756,6 +796,25 @@ func (c *Container) Export(path string) error {
return err
}
+// AddArtifact creates and writes to an artifact file for the container
+func (c *Container) AddArtifact(name string, data []byte) error {
+ return ioutil.WriteFile(c.getArtifactPath(name), data, 0740)
+}
+
+// GetArtifact reads the specified artifact file from the container
+func (c *Container) GetArtifact(name string) ([]byte, error) {
+ return ioutil.ReadFile(c.getArtifactPath(name))
+}
+
+// RemoveArtifact deletes the specified artifacts file
+func (c *Container) RemoveArtifact(name string) error {
+ return os.Remove(c.getArtifactPath(name))
+}
+
+func (c *Container) getArtifactPath(name string) string {
+ return filepath.Join(c.config.StaticDir, artifactsDir, name)
+}
+
// Commit commits the changes between a container and its image, creating a new
// image
func (c *Container) Commit() (*storage.Image, error) {
diff --git a/libpod/images/image_data.go b/libpod/images/image_data.go
index b64ac557f..1fa63f6cb 100644
--- a/libpod/images/image_data.go
+++ b/libpod/images/image_data.go
@@ -88,7 +88,6 @@ func GetData(store storage.Store, name string) (*Data, error) {
if err != nil {
return nil, errors.Wrapf(err, "error reading image %q", img.ID)
}
- defer imgRef.Close()
tags, digests, err := ParseImageNames(img.Names)
if err != nil {
diff --git a/libpod/oci.go b/libpod/oci.go
index 6ea6bb64f..49bf95bc5 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -302,7 +302,7 @@ func (r *OCIRuntime) createContainer(ctr *Container, cgroupParent string) (err e
func (r *OCIRuntime) updateContainerStatus(ctr *Container) error {
state := new(spec.State)
- out, err := exec.Command(r.path, "state", ctr.ID()).CombinedOutput()
+ out, err := exec.Command(r.path, "state", ctr.ID()).Output()
if err != nil {
return errors.Wrapf(err, "error getting container %s state. stderr/out: %s", ctr.ID(), out)
}
@@ -454,3 +454,9 @@ func (r *OCIRuntime) pauseContainer(ctr *Container) error {
func (r *OCIRuntime) unpauseContainer(ctr *Container) error {
return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "resume", ctr.ID())
}
+
+//execContiner executes a command in a running container
+func (r *OCIRuntime) execContainer(c *Container, cmd []string, globalOpts runcGlobalOptions, commandOpts runcExecOptions) error {
+ r.RuncExec(c, cmd, globalOpts, commandOpts)
+ return nil
+}
diff --git a/libpod/runc.go b/libpod/runc.go
new file mode 100644
index 000000000..efbb51b24
--- /dev/null
+++ b/libpod/runc.go
@@ -0,0 +1,117 @@
+package libpod
+
+import (
+ "os"
+ "os/exec"
+ "strings"
+
+ "github.com/sirupsen/logrus"
+)
+
+type runcGlobalOptions struct {
+ log string
+ logFormat string
+ root string
+ criu string
+ systemdCgroup bool
+}
+type runcExecOptions struct {
+ consoleSocket string
+ cwd string
+ env []string
+ tty bool
+ user string
+ processPath string
+ detach bool
+ pidFile string
+ processLabel string
+ apparmor string
+ noNewPrivs bool
+ capAdd []string
+}
+
+func parseGlobalOptionsToArgs(opts runcGlobalOptions) []string {
+ args := []string{}
+ if opts.log != "" {
+ args = append(args, "--log", opts.log)
+ }
+ if opts.logFormat != "" {
+ args = append(args, "--log-format", opts.logFormat)
+ }
+ if opts.root != "" {
+ args = append(args, "--root", opts.root)
+ }
+ if opts.criu != "" {
+ args = append(args, "--criu", opts.criu)
+ }
+ if opts.systemdCgroup {
+ args = append(args, "--systemd-cgroup")
+ }
+ return args
+}
+
+// RuncExec executes 'runc --options exec --options cmd'
+func (r *OCIRuntime) RuncExec(container *Container, command []string, globalOpts runcGlobalOptions, execOpts runcExecOptions) error {
+ args := []string{}
+ args = append(args, parseGlobalOptionsToArgs(globalOpts)...)
+ // Add subcommand
+ args = append(args, "exec")
+ // Now add subcommand args
+
+ if execOpts.consoleSocket != "" {
+ args = append(args, "--console-socket", execOpts.consoleSocket)
+ }
+ if execOpts.cwd != "" {
+ args = append(args, "--cwd", execOpts.cwd)
+ }
+
+ if len(execOpts.env) > 0 {
+ for _, envInput := range execOpts.env {
+ args = append(args, "--env", envInput)
+ }
+ }
+ if execOpts.tty {
+ args = append(args, "--tty")
+ }
+ if execOpts.user != "" {
+ args = append(args, "--user", execOpts.user)
+
+ }
+ if execOpts.processPath != "" {
+ args = append(args, "--process", execOpts.processPath)
+ }
+ if execOpts.detach {
+ args = append(args, "--detach")
+ }
+ if execOpts.pidFile != "" {
+ args = append(args, "--pid-file", execOpts.pidFile)
+ }
+ if execOpts.processLabel != "" {
+ args = append(args, "--process-label", execOpts.processLabel)
+ }
+ if execOpts.apparmor != "" {
+ args = append(args, "--apparmor", execOpts.apparmor)
+ }
+ if execOpts.noNewPrivs {
+ args = append(args, "--no-new-privs")
+ }
+ if len(execOpts.capAdd) > 0 {
+ for _, capAddValue := range execOpts.capAdd {
+ args = append(args, "--cap", capAddValue)
+ }
+ }
+
+ // Append Cid
+ args = append(args, container.ID())
+ // Append Cmd
+ args = append(args, command...)
+
+ logrus.Debug("Executing runc command: %s %s", r.path, strings.Join(args, " "))
+ cmd := exec.Command(r.path, args...)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ cmd.Stdin = os.Stdin
+ cmd.Start()
+ err := cmd.Wait()
+ return err
+}
diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go
index ba1cec96f..598bfaf0f 100644
--- a/libpod/runtime_img.go
+++ b/libpod/runtime_img.go
@@ -228,7 +228,7 @@ func (k *Image) GetManifest() error {
if err != nil {
return errors.Wrapf(err, "unable to create new image source")
}
- _, _, err = imageSource.GetManifest()
+ _, _, err = imageSource.GetManifest(nil)
if err == nil {
return nil
}
@@ -383,7 +383,7 @@ func (k *Image) HasLatest() (bool, error) {
if err != nil {
return false, err
}
- _, _, err = pullRef.(types.ImageSource).GetManifest()
+ _, _, err = pullRef.(types.ImageSource).GetManifest(nil)
return false, err
}
@@ -1124,7 +1124,6 @@ func (r *Runtime) InfoAndDigestAndSize(img storage.Image) (*types.ImageInspectIn
if err != nil {
return nil, "", -1, errors.Wrapf(err, "error reading image %q", img.ID)
}
- defer imgRef.Close()
return infoAndDigestAndSize(imgRef)
}