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

     1  package libpod
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/containers/libpod/libpod/define"
     7  	"github.com/containers/libpod/libpod/events"
     8  	"github.com/pkg/errors"
     9  )
    10  
    11  // Contains the public Runtime API for volumes
    12  
    13  // A VolumeCreateOption is a functional option which alters the Volume created by
    14  // NewVolume
    15  type VolumeCreateOption func(*Volume) error
    16  
    17  // VolumeFilter is a function to determine whether a volume is included in command
    18  // output. Volumes to be outputted are tested using the function. a true return will
    19  // include the volume, a false return will exclude it.
    20  type VolumeFilter func(*Volume) bool
    21  
    22  // RemoveVolume removes a volumes
    23  func (r *Runtime) RemoveVolume(ctx context.Context, v *Volume, force bool) error {
    24  	r.lock.Lock()
    25  	defer r.lock.Unlock()
    26  
    27  	if !r.valid {
    28  		return define.ErrRuntimeStopped
    29  	}
    30  
    31  	if !v.valid {
    32  		if ok, _ := r.state.HasVolume(v.Name()); !ok {
    33  			// Volume probably already removed
    34  			// Or was never in the runtime to begin with
    35  			return nil
    36  		}
    37  	}
    38  	return r.removeVolume(ctx, v, force)
    39  }
    40  
    41  // GetVolume retrieves a volume given its full name.
    42  func (r *Runtime) GetVolume(name string) (*Volume, error) {
    43  	r.lock.RLock()
    44  	defer r.lock.RUnlock()
    45  
    46  	if !r.valid {
    47  		return nil, define.ErrRuntimeStopped
    48  	}
    49  
    50  	vol, err := r.state.Volume(name)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	return vol, nil
    56  }
    57  
    58  // LookupVolume retrieves a volume by unambiguous partial name.
    59  func (r *Runtime) LookupVolume(name string) (*Volume, error) {
    60  	r.lock.RLock()
    61  	defer r.lock.RUnlock()
    62  
    63  	if !r.valid {
    64  		return nil, define.ErrRuntimeStopped
    65  	}
    66  
    67  	vol, err := r.state.LookupVolume(name)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	return vol, nil
    73  }
    74  
    75  // HasVolume checks to see if a volume with the given name exists
    76  func (r *Runtime) HasVolume(name string) (bool, error) {
    77  	r.lock.RLock()
    78  	defer r.lock.RUnlock()
    79  
    80  	if !r.valid {
    81  		return false, define.ErrRuntimeStopped
    82  	}
    83  
    84  	return r.state.HasVolume(name)
    85  }
    86  
    87  // Volumes retrieves all volumes
    88  // Filters can be provided which will determine which volumes are included in the
    89  // output. Multiple filters are handled by ANDing their output, so only volumes
    90  // matching all filters are returned
    91  func (r *Runtime) Volumes(filters ...VolumeFilter) ([]*Volume, error) {
    92  	r.lock.RLock()
    93  	defer r.lock.RUnlock()
    94  
    95  	if !r.valid {
    96  		return nil, define.ErrRuntimeStopped
    97  	}
    98  
    99  	vols, err := r.state.AllVolumes()
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  
   104  	volsFiltered := make([]*Volume, 0, len(vols))
   105  	for _, vol := range vols {
   106  		include := true
   107  		for _, filter := range filters {
   108  			include = include && filter(vol)
   109  		}
   110  
   111  		if include {
   112  			volsFiltered = append(volsFiltered, vol)
   113  		}
   114  	}
   115  
   116  	return volsFiltered, nil
   117  }
   118  
   119  // GetAllVolumes retrieves all the volumes
   120  func (r *Runtime) GetAllVolumes() ([]*Volume, error) {
   121  	r.lock.RLock()
   122  	defer r.lock.RUnlock()
   123  
   124  	if !r.valid {
   125  		return nil, define.ErrRuntimeStopped
   126  	}
   127  
   128  	return r.state.AllVolumes()
   129  }
   130  
   131  // PruneVolumes removes unused volumes from the system
   132  func (r *Runtime) PruneVolumes(ctx context.Context) (map[string]error, error) {
   133  	reports := make(map[string]error)
   134  	vols, err := r.GetAllVolumes()
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  
   139  	for _, vol := range vols {
   140  		if err := r.RemoveVolume(ctx, vol, false); err != nil {
   141  			if errors.Cause(err) != define.ErrVolumeBeingUsed && errors.Cause(err) != define.ErrVolumeRemoved {
   142  				reports[vol.Name()] = err
   143  			}
   144  			continue
   145  		}
   146  		vol.newVolumeEvent(events.Prune)
   147  		reports[vol.Name()] = nil
   148  	}
   149  	return reports, nil
   150  }