github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/libpod/runtime_cstorage.go (about)

     1  package libpod
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/containers/libpod/libpod/define"
     7  	"github.com/containers/storage"
     8  	"github.com/pkg/errors"
     9  	"github.com/sirupsen/logrus"
    10  )
    11  
    12  // StorageContainer represents a container present in c/storage but not in
    13  // libpod.
    14  type StorageContainer struct {
    15  	ID              string
    16  	Names           []string
    17  	Image           string
    18  	CreateTime      time.Time
    19  	PresentInLibpod bool
    20  }
    21  
    22  // ListStorageContainers lists all containers visible to c/storage.
    23  func (r *Runtime) ListStorageContainers() ([]*StorageContainer, error) {
    24  	r.lock.RLock()
    25  	defer r.lock.RUnlock()
    26  
    27  	finalCtrs := []*StorageContainer{}
    28  
    29  	ctrs, err := r.store.Containers()
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  
    34  	for _, ctr := range ctrs {
    35  		storageCtr := new(StorageContainer)
    36  		storageCtr.ID = ctr.ID
    37  		storageCtr.Names = ctr.Names
    38  		storageCtr.Image = ctr.ImageID
    39  		storageCtr.CreateTime = ctr.Created
    40  
    41  		// Look up if container is in state
    42  		hasCtr, err := r.state.HasContainer(ctr.ID)
    43  		if err != nil {
    44  			return nil, errors.Wrapf(err, "error looking up container %s in state", ctr.ID)
    45  		}
    46  
    47  		storageCtr.PresentInLibpod = hasCtr
    48  
    49  		finalCtrs = append(finalCtrs, storageCtr)
    50  	}
    51  
    52  	return finalCtrs, nil
    53  }
    54  
    55  // RemoveStorageContainer removes a container from c/storage.
    56  // The container WILL NOT be removed if it exists in libpod.
    57  // Accepts ID or full name of container.
    58  // If force is set, the container will be unmounted first to ensure removal.
    59  func (r *Runtime) RemoveStorageContainer(idOrName string, force bool) error {
    60  	r.lock.Lock()
    61  	defer r.lock.Unlock()
    62  
    63  	return r.removeStorageContainer(idOrName, force)
    64  }
    65  
    66  // Internal function to remove the container storage without
    67  // locking the runtime.
    68  func (r *Runtime) removeStorageContainer(idOrName string, force bool) error {
    69  	targetID, err := r.store.Lookup(idOrName)
    70  	if err != nil {
    71  		if errors.Cause(err) == storage.ErrLayerUnknown {
    72  			return errors.Wrapf(define.ErrNoSuchCtr, "no container with ID or name %q found", idOrName)
    73  		}
    74  		return errors.Wrapf(err, "error looking up container %q", idOrName)
    75  	}
    76  
    77  	// Lookup returns an ID but it's not guaranteed to be a container ID.
    78  	// So we can still error here.
    79  	ctr, err := r.store.Container(targetID)
    80  	if err != nil {
    81  		if errors.Cause(err) == storage.ErrContainerUnknown {
    82  			return errors.Wrapf(define.ErrNoSuchCtr, "%q does not refer to a container", idOrName)
    83  		}
    84  		return errors.Wrapf(err, "error retrieving container %q", idOrName)
    85  	}
    86  
    87  	// Error out if the container exists in libpod
    88  	exists, err := r.state.HasContainer(ctr.ID)
    89  	if err != nil {
    90  		return err
    91  	}
    92  	if exists {
    93  		return errors.Wrapf(define.ErrCtrExists, "refusing to remove %q as it exists in libpod as container %s", idOrName, ctr.ID)
    94  	}
    95  
    96  	if !force {
    97  		timesMounted, err := r.store.Mounted(ctr.ID)
    98  		if err != nil {
    99  			if errors.Cause(err) == storage.ErrContainerUnknown {
   100  				// Container was removed from under us.
   101  				// It's gone, so don't bother erroring.
   102  				logrus.Warnf("Storage for container %s already removed", ctr.ID)
   103  				return nil
   104  			}
   105  			return errors.Wrapf(err, "error looking up container %q mounts", idOrName)
   106  		}
   107  		if timesMounted > 0 {
   108  			return errors.Wrapf(define.ErrCtrStateInvalid, "container %q is mounted and cannot be removed without using force", idOrName)
   109  		}
   110  	} else if _, err := r.store.Unmount(ctr.ID, true); err != nil {
   111  		if errors.Cause(err) == storage.ErrContainerUnknown {
   112  			// Container again gone, no error
   113  			logrus.Warnf("Storage for container %s already removed", ctr.ID)
   114  			return nil
   115  		}
   116  		return errors.Wrapf(err, "error unmounting container %q", idOrName)
   117  	}
   118  
   119  	if err := r.store.DeleteContainer(ctr.ID); err != nil {
   120  		if errors.Cause(err) == storage.ErrContainerUnknown {
   121  			// Container again gone, no error
   122  			logrus.Warnf("Storage for container %s already removed", ctr.ID)
   123  			return nil
   124  		}
   125  		return errors.Wrapf(err, "error removing storage for container %q", idOrName)
   126  	}
   127  
   128  	return nil
   129  }