Consolidate mount logic

There are still two places that don't use the new function,
export and mount, but both can probably be converted to it
in the future.

Signed-off-by: Matthew Heon <matthew.heon@gmail.com>

Closes: #99
Approved by: rhatdan
This commit is contained in:
Matthew Heon 2017-12-03 12:17:44 -05:00 committed by Atomic Bot
parent 1f482c9f1f
commit 750fc239b5
1 changed files with 72 additions and 76 deletions

View File

@ -420,25 +420,10 @@ func (c *Container) Init() (err error) {
return errors.Wrapf(ErrCtrExists, "container %s has already been created in runtime", c.ID())
}
mountPoint, err := c.runtime.storageService.StartContainer(c.ID())
if err != nil {
return errors.Wrapf(err, "error mounting storage for container %s", c.ID())
// Mount storage for the container
if err := c.mountStorage(); err != nil {
return err
}
c.state.Mounted = true
c.state.Mountpoint = mountPoint
logrus.Debugf("Created root filesystem for container %s at %s", c.ID(), c.state.Mountpoint)
defer func() {
if err != nil {
if err2 := c.runtime.storageService.StopContainer(c.ID()); err2 != nil {
logrus.Errorf("Error unmounting storage for container %s: %v", c.ID(), err2)
}
c.state.Mounted = false
c.state.Mountpoint = ""
}
}()
// Make the OCI runtime spec we will use
g := generate.NewFromSpec(c.config.Spec)
@ -484,45 +469,14 @@ func (c *Container) Start() error {
return err
}
mounted, err := mount.Mounted(c.config.ShmDir)
if err != nil {
return errors.Wrapf(err, "unable to determine if %q is mounted", c.config.ShmDir)
}
if !mounted {
shmOptions := "mode=1777,size=" + strconv.Itoa(DefaultShmSize)
if err := unix.Mount("shm", c.config.ShmDir, "tmpfs", unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV,
label.FormatMountLabel(shmOptions, c.config.MountLabel)); err != nil {
return errors.Wrapf(err, "failed to mount shm tmpfs %q", c.config.ShmDir)
}
}
// Container must be created or stopped to be started
if !(c.state.State == ContainerStateCreated || c.state.State == ContainerStateStopped) {
return errors.Wrapf(ErrCtrStateInvalid, "container %s must be in Created or Stopped state to be started", c.ID())
}
// If the container isn't mounted, mount it
if !c.state.Mounted {
mountPoint, err := c.runtime.storageService.StartContainer(c.ID())
if err != nil {
return errors.Wrapf(err, "error mounting storage for container %s", c.ID())
}
c.state.Mounted = true
c.state.Mountpoint = mountPoint
logrus.Debugf("Created root filesystem for container %s at %s", c.ID(), c.state.Mountpoint)
defer func() {
if err != nil {
if err2 := c.runtime.storageService.StopContainer(c.ID()); err2 != nil {
logrus.Errorf("Error unmounting storage for container %s: %v", c.ID(), err2)
}
c.state.Mounted = false
c.state.Mountpoint = ""
}
}()
// Mount storage for the container
if err := c.mountStorage(); err != nil {
return err
}
if err := c.runtime.ociRuntime.startContainer(c); err != nil {
@ -667,18 +621,7 @@ func (c *Container) Unmount() error {
return errors.Wrapf(ErrCtrStateInvalid, "cannot remove storage for container %s as it is running or paused", c.ID())
}
if !c.state.Mounted {
return nil
}
err := c.runtime.store.Unmount(c.ID())
if err != nil {
return errors.Wrapf(err, "error unmounting container %q", c.ID())
}
c.state.Mountpoint = ""
c.state.Mounted = false
return c.save()
return c.cleanupStorage()
}
// Pause pauses a container
@ -813,7 +756,7 @@ func (c *Container) isStopped() (bool, error) {
return c.state.State == ContainerStateStopped, nil
}
// nil container state to the database
// save container state to the database
func (c *Container) save() error {
if err := c.runtime.state.SaveContainer(c); err != nil {
return errors.Wrapf(err, "error saving container %s state", c.ID())
@ -821,6 +764,56 @@ func (c *Container) save() error {
return nil
}
// mountStorage sets up the container's root filesystem
// It mounts the image and any other requested mounts
// TODO: Add ability to override mount label so we can use this for Mount() too
// TODO: Can we use this for export? Copying SHM into the export might not be
// good
func (c *Container) mountStorage() (err error) {
// Container already mounted, nothing to do
if c.state.Mounted {
return nil
}
// TODO: generalize this mount code so it will mount every mount in ctr.config.Mounts
mounted, err := mount.Mounted(c.config.ShmDir)
if err != nil {
return errors.Wrapf(err, "unable to determine if %q is mounted", c.config.ShmDir)
}
if !mounted {
shmOptions := "mode=1777,size=" + strconv.Itoa(DefaultShmSize)
if err := unix.Mount("shm", c.config.ShmDir, "tmpfs", unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV,
label.FormatMountLabel(shmOptions, c.config.MountLabel)); err != nil {
return errors.Wrapf(err, "failed to mount shm tmpfs %q", c.config.ShmDir)
}
}
mountPoint, err := c.runtime.storageService.StartContainer(c.ID())
if err != nil {
return errors.Wrapf(err, "error mounting storage for container %s", c.ID())
}
c.state.Mounted = true
c.state.Mountpoint = mountPoint
logrus.Debugf("Created root filesystem for container %s at %s", c.ID(), c.state.Mountpoint)
defer func() {
if err != nil {
if err2 := c.cleanupStorage(); err2 != nil {
logrus.Errorf("Error unmounting storage for container %s: %v", c.ID(), err)
}
}
}()
if err := c.runtime.state.SaveContainer(c); err != nil {
return errors.Wrapf(err, "error saving container %s state", c.ID())
}
return nil
}
// CleanupStorage unmounts all mount points in container and cleans up container storage
func (c *Container) CleanupStorage() error {
c.lock.Lock()
@ -831,22 +824,24 @@ func (c *Container) CleanupStorage() error {
return c.cleanupStorage()
}
// cleanupStorage unmounts and cleans up the container's root filesystem
func (c *Container) cleanupStorage() error {
if !c.state.Mounted {
// Already unmounted, do nothing
return nil
}
if c.state.Mounted {
for _, mount := range c.config.Mounts {
if err := unix.Unmount(mount, unix.MNT_DETACH); err != nil {
if err != syscall.EINVAL {
logrus.Warnf("container %s failed to unmount %s : %v", c.ID(), mount, err)
}
for _, mount := range c.config.Mounts {
if err := unix.Unmount(mount, unix.MNT_DETACH); err != nil {
if err != syscall.EINVAL {
logrus.Warnf("container %s failed to unmount %s : %v", c.ID(), mount, err)
}
}
c.config.Mounts = []string{}
}
// Also unmount storage
if err := c.runtime.storageService.StopContainer(c.ID()); err != nil {
return errors.Wrapf(err, "error unmounting container %s root filesystem", c.ID())
}
// Also unmount storage
if err := c.runtime.storageService.StopContainer(c.ID()); err != nil {
return errors.Wrapf(err, "error unmounting container %s root filesystem", c.ID())
}
c.state.Mountpoint = ""
@ -855,5 +850,6 @@ func (c *Container) cleanupStorage() error {
if err := c.runtime.state.SaveContainer(c); err != nil {
return errors.Wrapf(err, "error saving container %s state", c.ID())
}
return nil
}