summaryrefslogtreecommitdiff
path: root/libpod/container_internal.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/container_internal.go')
-rw-r--r--libpod/container_internal.go107
1 files changed, 101 insertions, 6 deletions
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 3c7637717..ba11dd2c6 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -313,16 +313,111 @@ func (c *Container) save() error {
return nil
}
+// Initialize a container, creating it in the runtime
+func (c *Container) init() error {
+ if err := c.makeBindMounts(); err != nil {
+ return err
+ }
+
+ // Generate the OCI spec
+ spec, err := c.generateSpec()
+ if err != nil {
+ return err
+ }
+
+ // Save the OCI spec to disk
+ if err := c.saveSpec(spec); err != nil {
+ return err
+ }
+
+ // With the spec complete, do an OCI create
+ if err := c.runtime.ociRuntime.createContainer(c, c.config.CgroupParent); err != nil {
+ return err
+ }
+
+ logrus.Debugf("Created container %s in OCI runtime", c.ID())
+
+ c.state.State = ContainerStateCreated
+
+ return c.save()
+}
+
+// Initialize (if necessary) and start a container
+// Performs all necessary steps to start a container that is not running
+// Does not lock or check validity
+func (c *Container) initAndStart() (err error) {
+ // If we are ContainerStateUnknown, throw an error
+ if c.state.State == ContainerStateUnknown {
+ return errors.Wrapf(ErrCtrStateInvalid, "container %s is in an unknown state", c.ID())
+ }
+
+ // If we are running, do nothing
+ if c.state.State == ContainerStateRunning {
+ return nil
+ }
+ // If we are paused, throw an error
+ if c.state.State == ContainerStatePaused {
+ return errors.Wrapf(ErrCtrStateInvalid, "cannot start paused container %s", c.ID())
+ }
+ // TODO remove this once we can restart containers
+ if c.state.State == ContainerStateStopped {
+ return errors.Wrapf(ErrNotImplemented, "restarting containers is not yet implemented")
+ }
+
+ // Mount if necessary
+ if err := c.mountStorage(); err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ if err2 := c.cleanupStorage(); err2 != nil {
+ logrus.Errorf("Error cleaning up storage for container %s: %v", c.ID(), err2)
+ }
+ }
+ }()
+
+ // Create a network namespace if necessary
+ if c.config.CreateNetNS && c.state.NetNS == nil {
+ if err := c.runtime.createNetNS(c); err != nil {
+ return err
+ }
+ }
+ defer func() {
+ if err != nil {
+ if err2 := c.runtime.teardownNetNS(c); err2 != nil {
+ logrus.Errorf("Error tearing down network namespace for container %s: %v", c.ID(), err2)
+ }
+ }
+ }()
+
+ // If we are ContainerStateConfigured we need to init()
+ if c.state.State == ContainerStateConfigured {
+ if err := c.init(); err != nil {
+ return err
+ }
+ }
+
+ // Now start the container
+ return c.start()
+}
+
+// Internal, non-locking function to start a container
+func (c *Container) start() error {
+ if err := c.runtime.ociRuntime.startContainer(c); err != nil {
+ return err
+ }
+
+ logrus.Debugf("Started container %s", c.ID())
+
+ c.state.State = ContainerStateRunning
+
+ return c.save()
+}
+
// Internal, non-locking function to stop container
func (c *Container) stop(timeout uint) error {
logrus.Debugf("Stopping ctr %s with timeout %d", c.ID(), timeout)
- if c.state.State == ContainerStateConfigured ||
- c.state.State == ContainerStateUnknown ||
- c.state.State == ContainerStatePaused {
- return errors.Wrapf(ErrCtrStateInvalid, "can only stop created, running, or stopped containers")
- }
-
if err := c.runtime.ociRuntime.stopContainer(c, timeout); err != nil {
return err
}