diff options
author | Giuseppe Scrivano <gscrivan@redhat.com> | 2018-04-26 17:21:48 +0200 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2018-06-15 14:53:18 +0000 |
commit | 7bdfb4f9b361aca4f4f3337907feb3ca414d36e4 (patch) | |
tree | aff63093af49df79820e72a5a68f07e6fe70b863 /libpod | |
parent | 4b4de5dc21f034f5f678114dbf6d51f047c96a59 (diff) | |
download | podman-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.go | 2 | ||||
-rw-r--r-- | libpod/container_commit.go | 4 | ||||
-rw-r--r-- | libpod/container_inspect.go | 1 | ||||
-rw-r--r-- | libpod/container_internal.go | 38 | ||||
-rw-r--r-- | libpod/options.go | 21 | ||||
-rw-r--r-- | libpod/storage.go | 64 |
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) |