summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
authorGiuseppe Scrivano <gscrivan@redhat.com>2018-04-26 17:21:48 +0200
committerAtomic Bot <atomic-devel@projectatomic.io>2018-06-15 14:53:18 +0000
commit7bdfb4f9b361aca4f4f3337907feb3ca414d36e4 (patch)
treeaff63093af49df79820e72a5a68f07e6fe70b863 /libpod
parent4b4de5dc21f034f5f678114dbf6d51f047c96a59 (diff)
downloadpodman-7bdfb4f9b361aca4f4f3337907feb3ca414d36e4.tar.gz
podman-7bdfb4f9b361aca4f4f3337907feb3ca414d36e4.tar.bz2
podman-7bdfb4f9b361aca4f4f3337907feb3ca414d36e4.zip
podman: accept option --rootfs to use exploded images
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com> Closes: #871 Approved by: mheon
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container.go2
-rw-r--r--libpod/container_commit.go4
-rw-r--r--libpod/container_inspect.go1
-rw-r--r--libpod/container_internal.go38
-rw-r--r--libpod/options.go21
-rw-r--r--libpod/storage.go64
6 files changed, 91 insertions, 39 deletions
diff --git a/libpod/container.go b/libpod/container.go
index 85b6fa3dd..26232e5c0 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -197,6 +197,8 @@ type ContainerConfig struct {
// Information on the image used for the root filesystem/
RootfsImageID string `json:"rootfsImageID,omitempty"`
RootfsImageName string `json:"rootfsImageName,omitempty"`
+ // Rootfs to use for the container, this conflicts with RootfsImageID
+ Rootfs string `json:"rootfs,omitempty"`
// Whether to mount volumes specified in the image.
ImageVolumes bool `json:"imageVolumes"`
// Src path to be mounted on /dev/shm in container.
diff --git a/libpod/container_commit.go b/libpod/container_commit.go
index 2872012b8..929850cbe 100644
--- a/libpod/container_commit.go
+++ b/libpod/container_commit.go
@@ -34,6 +34,10 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai
isEnvCleared, isLabelCleared, isExposeCleared, isVolumeCleared bool
)
+ if c.config.Rootfs != "" {
+ return nil, errors.Errorf("cannot commit a container that uses an exploded rootfs")
+ }
+
if !c.batched {
c.lock.Lock()
defer c.lock.Unlock()
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index c8bf1a8cd..0e37036ca 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -70,6 +70,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *inspect.Data)
},
ImageID: config.RootfsImageID,
ImageName: config.RootfsImageName,
+ Rootfs: config.Rootfs,
ResolvConfPath: resolvPath,
HostnamePath: hostnamePath,
HostsPath: hostsPath,
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index e25ffaa03..b3e474836 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -56,6 +56,10 @@ var (
// mutable layer, and the rest is the RootFS: the set of immutable layers
// that make up the image on which the container is based.
func (c *Container) rootFsSize() (int64, error) {
+ if c.config.Rootfs != "" {
+ return 0, nil
+ }
+
container, err := c.runtime.store.Container(c.ID())
if err != nil {
return 0, err
@@ -93,6 +97,18 @@ func (c *Container) rootFsSize() (int64, error) {
// rwSize Gets the size of the mutable top layer of the container.
func (c *Container) rwSize() (int64, error) {
+ if c.config.Rootfs != "" {
+ var size int64
+ err := filepath.Walk(c.config.Rootfs, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ size += info.Size()
+ return nil
+ })
+ return size, err
+ }
+
container, err := c.runtime.store.Container(c.ID())
if err != nil {
return 0, err
@@ -205,7 +221,7 @@ func (c *Container) setupStorage(ctx context.Context) error {
}
// Need both an image ID and image name, plus a bool telling us whether to use the image configuration
- if c.config.RootfsImageID == "" || c.config.RootfsImageName == "" {
+ if c.config.Rootfs == "" && (c.config.RootfsImageID == "" || c.config.RootfsImageName == "") {
return errors.Wrapf(ErrInvalidArg, "must provide image ID and image name to use an image")
}
@@ -691,9 +707,12 @@ func (c *Container) mountStorage() (err error) {
}
}
- mountPoint, err := c.runtime.storageService.MountContainerImage(c.ID())
- if err != nil {
- return errors.Wrapf(err, "error mounting storage for container %s", c.ID())
+ mountPoint := c.config.Rootfs
+ if mountPoint == "" {
+ mountPoint, err = c.runtime.storageService.MountContainerImage(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
@@ -796,6 +815,9 @@ func (c *Container) cleanupStorage() error {
}
}
}
+ if c.config.Rootfs != "" {
+ return nil
+ }
// Also unmount storage
if err := c.runtime.storageService.UnmountContainerImage(c.ID()); err != nil {
@@ -1154,7 +1176,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
return nil, errors.Wrapf(err, "error setting up OCI Hooks")
}
// Bind builtin image volumes
- if c.config.ImageVolumes {
+ if c.config.Rootfs == "" && c.config.ImageVolumes {
if err := c.addImageVolumes(ctx, &g); err != nil {
return nil, errors.Wrapf(err, "error mounting image volumes")
}
@@ -1235,8 +1257,10 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
}
}
- if err := idtools.MkdirAllAs(c.state.RealMountpoint, 0700, c.RootUID(), c.RootGID()); err != nil {
- return nil, err
+ if c.config.Rootfs == "" {
+ if err := idtools.MkdirAllAs(c.state.RealMountpoint, 0700, c.RootUID(), c.RootGID()); err != nil {
+ return nil, err
+ }
}
g.SetRootPath(c.state.RealMountpoint)
diff --git a/libpod/options.go b/libpod/options.go
index 34bde3211..02bcb8628 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -2,6 +2,7 @@ package libpod
import (
"net"
+ "os"
"path/filepath"
"regexp"
"syscall"
@@ -361,6 +362,9 @@ func WithRootFSFromImage(imageID string, imageName string, useImageVolumes bool)
if ctr.config.RootfsImageID != "" || ctr.config.RootfsImageName != "" {
return errors.Wrapf(ErrInvalidArg, "container already configured with root filesystem")
}
+ if ctr.config.Rootfs != "" {
+ return errors.Wrapf(ErrInvalidArg, "cannot set both an image ID and a rootfs for a container")
+ }
ctr.config.RootfsImageID = imageID
ctr.config.RootfsImageName = imageName
@@ -909,6 +913,23 @@ func WithCommand(command []string) CtrCreateOption {
}
}
+// WithRootFS sets the rootfs for the container
+func WithRootFS(rootfs string) CtrCreateOption {
+ return func(ctr *Container) error {
+ if ctr.valid {
+ return ErrCtrFinalized
+ }
+ if _, err := os.Stat(rootfs); err != nil {
+ return errors.Wrapf(err, "error checking path %q", rootfs)
+ }
+ if ctr.config.RootfsImageID != "" {
+ return errors.Wrapf(ErrInvalidArg, "cannot set both an image ID and a rootfs for a container")
+ }
+ ctr.config.Rootfs = rootfs
+ return nil
+ }
+}
+
// Pod Creation Options
// WithPodName sets the name of the pod.
diff --git a/libpod/storage.go b/libpod/storage.go
index c0391326c..c5581d53c 100644
--- a/libpod/storage.go
+++ b/libpod/storage.go
@@ -60,40 +60,40 @@ func (metadata *RuntimeContainerMetadata) SetMountLabel(mountLabel string) {
// CreateContainerStorage creates the storage end of things. We already have the container spec created
// TO-DO We should be passing in an Image object in the future.
func (r *storageService) CreateContainerStorage(ctx context.Context, systemContext *types.SystemContext, imageName, imageID, containerName, containerID, mountLabel string, options *storage.ContainerOptions) (ContainerInfo, error) {
- var ref types.ImageReference
- if imageName == "" && imageID == "" {
- return ContainerInfo{}, ErrEmptyID
- }
- if containerName == "" {
- return ContainerInfo{}, ErrEmptyID
- }
- // Check if we have the specified image.
- ref, err := istorage.Transport.ParseStoreReference(r.store, imageID)
- if err != nil {
- return ContainerInfo{}, err
- }
- img, err := istorage.Transport.GetStoreImage(r.store, ref)
- if err != nil {
- return ContainerInfo{}, err
- }
- // Pull out a copy of the image's configuration.
- image, err := ref.NewImage(ctx, systemContext)
- if err != nil {
- return ContainerInfo{}, err
- }
- defer image.Close()
+ var imageConfig *v1.Image
+ if imageName != "" {
+ var ref types.ImageReference
+ if containerName == "" {
+ return ContainerInfo{}, ErrEmptyID
+ }
+ // Check if we have the specified image.
+ ref, err := istorage.Transport.ParseStoreReference(r.store, imageID)
+ if err != nil {
+ return ContainerInfo{}, err
+ }
+ img, err := istorage.Transport.GetStoreImage(r.store, ref)
+ if err != nil {
+ return ContainerInfo{}, err
+ }
+ // Pull out a copy of the image's configuration.
+ image, err := ref.NewImage(ctx, systemContext)
+ if err != nil {
+ return ContainerInfo{}, err
+ }
+ defer image.Close()
- // Get OCI configuration of image
- imageConfig, err := image.OCIConfig(ctx)
- if err != nil {
- return ContainerInfo{}, err
- }
+ // Get OCI configuration of image
+ imageConfig, err = image.OCIConfig(ctx)
+ if err != nil {
+ return ContainerInfo{}, err
+ }
- // Update the image name and ID.
- if imageName == "" && len(img.Names) > 0 {
- imageName = img.Names[0]
+ // Update the image name and ID.
+ if imageName == "" && len(img.Names) > 0 {
+ imageName = img.Names[0]
+ }
+ imageID = img.ID
}
- imageID = img.ID
// Build metadata to store with the container.
metadata := RuntimeContainerMetadata{
@@ -119,7 +119,7 @@ func (r *storageService) CreateContainerStorage(ctx context.Context, systemConte
},
}
}
- container, err := r.store.CreateContainer(containerID, names, img.ID, "", string(mdata), options)
+ container, err := r.store.CreateContainer(containerID, names, imageID, "", string(mdata), options)
if err != nil {
logrus.Debugf("failed to create container %s(%s): %v", metadata.ContainerName, containerID, err)