summaryrefslogtreecommitdiff
path: root/libpod/container.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/container.go')
-rw-r--r--libpod/container.go113
1 files changed, 105 insertions, 8 deletions
diff --git a/libpod/container.go b/libpod/container.go
index f1dd34131..fce64b0dd 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -13,6 +13,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"
@@ -49,6 +50,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
@@ -397,6 +400,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
}
@@ -410,6 +418,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())
}
@@ -421,6 +434,30 @@ func (c *Container) teardownStorage() error {
return nil
}
+// Refresh refreshes the container's state after a restart
+func (c *Container) refresh() error {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ if !c.valid {
+ return errors.Wrapf(ErrCtrRemoved, "container %s is not valid - may have been removed", c.ID())
+ }
+
+ // We need to get the container's temporary directory from c/storage
+ // It was lost in the reboot and must be recreated
+ dir, err := c.runtime.storageService.GetRunDir(c.ID())
+ if err != nil {
+ return errors.Wrapf(err, "error retrieving temporary directory for container %s", c.ID())
+ }
+ c.state.RunDir = dir
+
+ if err := c.runtime.state.SaveContainer(c); err != nil {
+ return errors.Wrapf(err, "error refreshing state for container %s", c.ID())
+ }
+
+ return nil
+}
+
// Init creates a container in the OCI runtime
func (c *Container) Init() (err error) {
c.lock.Lock()
@@ -434,12 +471,27 @@ func (c *Container) Init() (err error) {
return errors.Wrapf(ErrCtrExists, "container %s has already been created in runtime", c.ID())
}
- // Mount storage for the container
if err := c.mountStorage(); err != nil {
return err
}
- // Make the OCI runtime spec we will use
+ // If the OCI spec already exists, we need to replace it
+ // Cannot guarantee some things, e.g. network namespaces, have the same
+ // paths
+ jsonPath := filepath.Join(c.bundlePath(), "config.json")
+ if _, err := os.Stat(jsonPath); err != nil {
+ if !os.IsNotExist(err) {
+ return errors.Wrapf(err, "error doing stat on container %s spec", c.ID())
+ }
+ // The spec does not exist, we're fine
+ } else {
+ // The spec exists, need to remove it
+ if err := os.Remove(jsonPath); err != nil {
+ return errors.Wrapf(err, "error replacing runtime spec for container %s", c.ID())
+ }
+ }
+
+ // Save OCI spec to disk
g := generate.NewFromSpec(c.config.Spec)
// Mount ShmDir from host into container
g.AddBindMount(c.config.ShmDir, "/dev/shm", []string{"rw"})
@@ -448,8 +500,6 @@ func (c *Container) Init() (err error) {
c.runningSpec.Annotations[crioAnnotations.Created] = c.config.CreatedTime.Format(time.RFC3339Nano)
c.runningSpec.Annotations["org.opencontainers.image.stopSignal"] = fmt.Sprintf("%d", c.config.StopSignal)
- // Save the OCI spec to disk
- jsonPath := filepath.Join(c.bundlePath(), "config.json")
fileJSON, err := json.Marshal(c.runningSpec)
if err != nil {
return errors.Wrapf(err, "error exporting runtime spec for container %s to JSON", c.ID())
@@ -457,10 +507,11 @@ func (c *Container) Init() (err error) {
if err := ioutil.WriteFile(jsonPath, fileJSON, 0644); err != nil {
return errors.Wrapf(err, "error writing runtime spec JSON to file for container %s", c.ID())
}
- c.state.ConfigPath = jsonPath
logrus.Debugf("Created OCI spec for container %s at %s", c.ID(), jsonPath)
+ c.state.ConfigPath = jsonPath
+
// With the spec complete, do an OCI create
// TODO set cgroup parent in a sane fashion
if err := c.runtime.ociRuntime.createContainer(c, "/libpod_parent"); err != nil {
@@ -554,9 +605,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
@@ -732,6 +810,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) {