summaryrefslogtreecommitdiff
path: root/libpod/boltdb_state_internal.go
diff options
context:
space:
mode:
authorMarco Vedovati <mvedovati@suse.com>2019-07-05 12:54:07 +0200
committerMarco Vedovati <mvedovati@suse.com>2019-09-25 19:44:38 +0200
commitdacbc5beb2a8841e52cf8ea7f544b4d302469c1d (patch)
tree59789993d8dafec7b96ca1eb7a31b3959c50e7b0 /libpod/boltdb_state_internal.go
parent83b2348313c52cc3e20d72285a9d81d3d72c2d5d (diff)
downloadpodman-dacbc5beb2a8841e52cf8ea7f544b4d302469c1d.tar.gz
podman-dacbc5beb2a8841e52cf8ea7f544b4d302469c1d.tar.bz2
podman-dacbc5beb2a8841e52cf8ea7f544b4d302469c1d.zip
rm: add containers eviction with `rm --force`
Add ability to evict a container when it becomes unusable. This may happen when the host setup changes after a container creation, making it impossible for that container to be used or removed. Evicting a container is done using the `rm --force` command. Signed-off-by: Marco Vedovati <mvedovati@suse.com>
Diffstat (limited to 'libpod/boltdb_state_internal.go')
-rw-r--r--libpod/boltdb_state_internal.go83
1 files changed, 80 insertions, 3 deletions
diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go
index a50fce31e..ed87373e9 100644
--- a/libpod/boltdb_state_internal.go
+++ b/libpod/boltdb_state_internal.go
@@ -347,7 +347,7 @@ func getRuntimeConfigBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
return bkt, nil
}
-func (s *BoltState) getContainerFromDB(id []byte, ctr *Container, ctrsBkt *bolt.Bucket) error {
+func (s *BoltState) getContainerConfigFromDB(id []byte, config *ContainerConfig, ctrsBkt *bolt.Bucket) error {
ctrBkt := ctrsBkt.Bucket(id)
if ctrBkt == nil {
return errors.Wrapf(define.ErrNoSuchCtr, "container %s not found in DB", string(id))
@@ -365,10 +365,18 @@ func (s *BoltState) getContainerFromDB(id []byte, ctr *Container, ctrsBkt *bolt.
return errors.Wrapf(define.ErrInternal, "container %s missing config key in DB", string(id))
}
- if err := json.Unmarshal(configBytes, ctr.config); err != nil {
+ if err := json.Unmarshal(configBytes, config); err != nil {
return errors.Wrapf(err, "error unmarshalling container %s config", string(id))
}
+ return nil
+}
+
+func (s *BoltState) getContainerFromDB(id []byte, ctr *Container, ctrsBkt *bolt.Bucket) error {
+ if err := s.getContainerConfigFromDB(id, ctr.config, ctrsBkt); err != nil {
+ return err
+ }
+
// Get the lock
lock, err := s.runtime.lockManager.RetrieveLock(ctr.config.LockID)
if err != nil {
@@ -388,7 +396,7 @@ func (s *BoltState) getContainerFromDB(id []byte, ctr *Container, ctrsBkt *bolt.
ociRuntime, ok := s.runtime.ociRuntimes[runtimeName]
if !ok {
- return errors.Wrapf(define.ErrInternal, "container %s was created with OCI runtime %s, but that runtime is not available in the current configuration", ctr.ID(), ctr.config.OCIRuntime)
+ return errors.Wrapf(define.ErrOCIRuntimeUnavailable, "cannot find OCI runtime %q for container %s", ctr.config.OCIRuntime, ctr.ID())
}
ctr.ociRuntime = ociRuntime
}
@@ -862,3 +870,72 @@ func (s *BoltState) removeContainer(ctr *Container, pod *Pod, tx *bolt.Tx) error
return nil
}
+
+// lookupContainerID retrieves a container ID from the state by full or unique
+// partial ID or name.
+// NOTE: the retrieved container ID namespace may not match the state namespace.
+func (s *BoltState) lookupContainerID(idOrName string, ctrBucket, namesBucket, nsBucket *bolt.Bucket) ([]byte, error) {
+ // First, check if the ID given was the actual container ID
+ ctrExists := ctrBucket.Bucket([]byte(idOrName))
+ if ctrExists != nil {
+ // A full container ID was given.
+ // It might not be in our namespace, but this will be handled
+ // the callers.
+ return []byte(idOrName), nil
+ }
+
+ // Next, check if the full name was given
+ isPod := false
+ fullID := namesBucket.Get([]byte(idOrName))
+ if fullID != nil {
+ // The name exists and maps to an ID.
+ // However, we are not yet certain the ID is a
+ // container.
+ ctrExists = ctrBucket.Bucket(fullID)
+ if ctrExists != nil {
+ // A container bucket matching the full ID was
+ // found.
+ return fullID, nil
+ }
+ // Don't error if we have a name match but it's not a
+ // container - there's a chance we have a container with
+ // an ID starting with those characters.
+ // However, so we can return a good error, note whether
+ // this is a pod.
+ isPod = true
+ }
+
+ var id []byte
+ // We were not given a full container ID or name.
+ // Search for partial ID matches.
+ exists := false
+ err := ctrBucket.ForEach(func(checkID, checkName []byte) error {
+ // If the container isn't in our namespace, we
+ // can't match it
+ if s.namespaceBytes != nil {
+ ns := nsBucket.Get(checkID)
+ if !bytes.Equal(ns, s.namespaceBytes) {
+ return nil
+ }
+ }
+ if strings.HasPrefix(string(checkID), idOrName) {
+ if exists {
+ return errors.Wrapf(define.ErrCtrExists, "more than one result for container ID %s", idOrName)
+ }
+ id = checkID
+ exists = true
+ }
+
+ return nil
+ })
+
+ if err != nil {
+ return nil, err
+ } else if !exists {
+ if isPod {
+ return nil, errors.Wrapf(define.ErrNoSuchCtr, "%s is a pod, not a container", idOrName)
+ }
+ return nil, errors.Wrapf(define.ErrNoSuchCtr, "no container with name or ID %s found", idOrName)
+ }
+ return id, nil
+}