diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container.go | 65 | ||||
-rw-r--r-- | libpod/images/image_data.go | 1 | ||||
-rw-r--r-- | libpod/oci.go | 8 | ||||
-rw-r--r-- | libpod/runc.go | 117 | ||||
-rw-r--r-- | libpod/runtime_img.go | 5 |
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) } |