diff options
author | Matthew Heon <matthew.heon@pm.me> | 2019-06-13 16:51:31 -0400 |
---|---|---|
committer | Matthew Heon <matthew.heon@pm.me> | 2019-06-13 17:02:20 -0400 |
commit | 49e696642d4d2d08bb89d6968f50ef9d6f17361a (patch) | |
tree | 6f90e20212f2cc9c5d3d31ea64c91702ba5c2144 /libpod/runtime_cstorage.go | |
parent | 2784cf3ca3c635b1383823dd9bc47d26274e60e3 (diff) | |
download | podman-49e696642d4d2d08bb89d6968f50ef9d6f17361a.tar.gz podman-49e696642d4d2d08bb89d6968f50ef9d6f17361a.tar.bz2 podman-49e696642d4d2d08bb89d6968f50ef9d6f17361a.zip |
Add --storage flag to 'podman rm' (local only)
This flag switches to removing containers directly from c/storage
and is mostly used to remove orphan containers.
It's a superior solution to our former one, which attempted
removal from storage under certain circumstances and could, under
some conditions, not trigger.
Also contains the beginning of support for storage in `ps` but
wiring that in is going to be a much bigger pain.
Fixes #3329.
Signed-off-by: Matthew Heon <matthew.heon@pm.me>
Diffstat (limited to 'libpod/runtime_cstorage.go')
-rw-r--r-- | libpod/runtime_cstorage.go | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/libpod/runtime_cstorage.go b/libpod/runtime_cstorage.go new file mode 100644 index 000000000..569f63322 --- /dev/null +++ b/libpod/runtime_cstorage.go @@ -0,0 +1,118 @@ +package libpod + +import ( + "github.com/containers/storage" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +// StorageContainer represents a container present in c/storage but not in +// libpod. +type StorageContainer struct { + ID string + Names []string + PresentInLibpod bool +} + +// ListStorageContainers lists all containers visible to c/storage. +func (r *Runtime) ListStorageContainers() ([]*StorageContainer, error) { + r.lock.RLock() + defer r.lock.RUnlock() + + finalCtrs := []*StorageContainer{} + + ctrs, err := r.store.Containers() + if err != nil { + return nil, err + } + + for _, ctr := range ctrs { + storageCtr := new(StorageContainer) + storageCtr.ID = ctr.ID + storageCtr.Names = ctr.Names + + // Look up if container is in state + hasCtr, err := r.state.HasContainer(ctr.ID) + if err != nil { + return nil, errors.Wrapf(err, "error looking up container %s in state", ctr.ID) + } + + storageCtr.PresentInLibpod = hasCtr + + finalCtrs = append(finalCtrs, storageCtr) + } + + return finalCtrs, nil +} + +// RemoveStorageContainer removes a container from c/storage. +// The container WILL NOT be removed if it exists in libpod. +// Accepts ID or full name of container. +// If force is set, the container will be unmounted first to ensure removal. +func (r *Runtime) RemoveStorageContainer(idOrName string, force bool) error { + r.lock.Lock() + defer r.lock.Unlock() + + targetID, err := r.store.Lookup(idOrName) + if err != nil { + if err == storage.ErrLayerUnknown { + return errors.Wrapf(ErrNoSuchCtr, "no container with ID or name %q found", idOrName) + } + return errors.Wrapf(err, "error looking up container %q", idOrName) + } + + // Lookup returns an ID but it's not guaranteed to be a container ID. + // So we can still error here. + ctr, err := r.store.Container(targetID) + if err != nil { + if err == storage.ErrContainerUnknown { + return errors.Wrapf(ErrNoSuchCtr, "%q does not refer to a container", idOrName) + } + return errors.Wrapf(err, "error retrieving container %q", idOrName) + } + + // Error out if the container exists in libpod + exists, err := r.state.HasContainer(ctr.ID) + if err != nil { + return err + } + if exists { + return errors.Wrapf(ErrCtrExists, "refusing to remove %q as it exists in libpod as container %s", idOrName, ctr.ID) + } + + if !force { + timesMounted, err := r.store.Mounted(ctr.ID) + if err != nil { + if err == storage.ErrContainerUnknown { + // Container was removed from under us. + // It's gone, so don't bother erroring. + logrus.Warnf("Storage for container %s already removed", ctr.ID) + return nil + } + return errors.Wrapf(err, "error looking up container %q mounts", idOrName) + } + if timesMounted > 0 { + return errors.Wrapf(ErrCtrStateInvalid, "container %q is mounted and cannot be removed without using force", idOrName) + } + } else { + if _, err := r.store.Unmount(ctr.ID, true); err != nil { + if err == storage.ErrContainerUnknown { + // Container again gone, no error + logrus.Warnf("Storage for container %s already removed", ctr.ID) + return nil + } + return errors.Wrapf(err, "error unmounting container %q", idOrName) + } + } + + if err := r.store.DeleteContainer(ctr.ID); err != nil { + if err == storage.ErrContainerUnknown { + // Container again gone, no error + logrus.Warnf("Storage for container %s already removed", ctr.ID) + return nil + } + return errors.Wrapf(err, "error removing storage for container %q", idOrName) + } + + return nil +} |