github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/pkg/varlinkapi/volumes.go (about) 1 // +build varlink 2 3 package varlinkapi 4 5 import ( 6 "context" 7 "encoding/json" 8 9 "github.com/containers/podman/v2/libpod" 10 "github.com/containers/podman/v2/pkg/domain/infra/abi/parse" 11 iopodman "github.com/containers/podman/v2/pkg/varlink" 12 ) 13 14 // VolumeCreate creates a libpod volume based on input from a varlink connection 15 func (i *VarlinkAPI) VolumeCreate(call iopodman.VarlinkCall, options iopodman.VolumeCreateOpts) error { 16 var volumeOptions []libpod.VolumeCreateOption 17 18 if len(options.VolumeName) > 0 { 19 volumeOptions = append(volumeOptions, libpod.WithVolumeName(options.VolumeName)) 20 } 21 if len(options.Driver) > 0 { 22 volumeOptions = append(volumeOptions, libpod.WithVolumeDriver(options.Driver)) 23 } 24 if len(options.Labels) > 0 { 25 volumeOptions = append(volumeOptions, libpod.WithVolumeLabels(options.Labels)) 26 } 27 if len(options.Options) > 0 { 28 parsedOptions, err := parse.VolumeOptions(options.Options) 29 if err != nil { 30 return call.ReplyErrorOccurred(err.Error()) 31 } 32 volumeOptions = append(volumeOptions, parsedOptions...) 33 } 34 newVolume, err := i.Runtime.NewVolume(getContext(), volumeOptions...) 35 if err != nil { 36 return call.ReplyErrorOccurred(err.Error()) 37 } 38 return call.ReplyVolumeCreate(newVolume.Name()) 39 } 40 41 // VolumeRemove removes volumes by options.All or options.Volumes 42 func (i *VarlinkAPI) VolumeRemove(call iopodman.VarlinkCall, options iopodman.VolumeRemoveOpts) error { 43 success, failed, err := SharedRemoveVolumes(getContext(), i.Runtime, options.Volumes, options.All, options.Force) 44 if err != nil { 45 return call.ReplyErrorOccurred(err.Error()) 46 } 47 // Convert map[string]string to map[string]error 48 errStrings := make(map[string]string) 49 for k, v := range failed { 50 errStrings[k] = v.Error() 51 } 52 return call.ReplyVolumeRemove(success, errStrings) 53 } 54 55 // GetVolumes returns all the volumes known to the remote system 56 func (i *VarlinkAPI) GetVolumes(call iopodman.VarlinkCall, args []string, all bool) error { 57 var ( 58 err error 59 reply []*libpod.Volume 60 volumes []iopodman.Volume 61 ) 62 if all { 63 reply, err = i.Runtime.GetAllVolumes() 64 } else { 65 for _, v := range args { 66 vol, err := i.Runtime.GetVolume(v) 67 if err != nil { 68 return err 69 } 70 reply = append(reply, vol) 71 } 72 } 73 if err != nil { 74 return call.ReplyErrorOccurred(err.Error()) 75 } 76 // Build the iopodman.volume struct for the return 77 for _, v := range reply { 78 newVol := iopodman.Volume{ 79 Driver: v.Driver(), 80 Labels: v.Labels(), 81 MountPoint: v.MountPoint(), 82 Name: v.Name(), 83 Options: v.Options(), 84 } 85 volumes = append(volumes, newVol) 86 } 87 return call.ReplyGetVolumes(volumes) 88 } 89 90 // InspectVolume inspects a single volume, returning its JSON as a string. 91 func (i *VarlinkAPI) InspectVolume(call iopodman.VarlinkCall, name string) error { 92 vol, err := i.Runtime.LookupVolume(name) 93 if err != nil { 94 return call.ReplyErrorOccurred(err.Error()) 95 } 96 inspectOut, err := vol.Inspect() 97 if err != nil { 98 return call.ReplyErrorOccurred(err.Error()) 99 } 100 inspectJSON, err := json.Marshal(inspectOut) 101 if err != nil { 102 return call.ReplyErrorOccurred(err.Error()) 103 } 104 return call.ReplyInspectVolume(string(inspectJSON)) 105 } 106 107 // VolumesPrune removes unused images via a varlink call 108 func (i *VarlinkAPI) VolumesPrune(call iopodman.VarlinkCall) error { 109 var ( 110 prunedErrors []string 111 prunedNames []string 112 ) 113 responses, err := i.Runtime.PruneVolumes(getContext()) 114 if err != nil { 115 return call.ReplyVolumesPrune([]string{}, []string{err.Error()}) 116 } 117 for k, v := range responses { 118 if v == nil { 119 prunedNames = append(prunedNames, k) 120 } else { 121 prunedErrors = append(prunedErrors, v.Error()) 122 } 123 } 124 return call.ReplyVolumesPrune(prunedNames, prunedErrors) 125 } 126 127 // Remove given set of volumes 128 func SharedRemoveVolumes(ctx context.Context, runtime *libpod.Runtime, vols []string, all, force bool) ([]string, map[string]error, error) { 129 var ( 130 toRemove []*libpod.Volume 131 success []string 132 failed map[string]error 133 ) 134 135 failed = make(map[string]error) 136 137 if all { 138 vols, err := runtime.Volumes() 139 if err != nil { 140 return nil, nil, err 141 } 142 toRemove = vols 143 } else { 144 for _, v := range vols { 145 vol, err := runtime.LookupVolume(v) 146 if err != nil { 147 failed[v] = err 148 continue 149 } 150 toRemove = append(toRemove, vol) 151 } 152 } 153 154 // We could parallelize this, but I haven't heard anyone complain about 155 // performance here yet, so hold off. 156 for _, vol := range toRemove { 157 if err := runtime.RemoveVolume(ctx, vol, force); err != nil { 158 failed[vol.Name()] = err 159 continue 160 } 161 success = append(success, vol.Name()) 162 } 163 164 return success, failed, nil 165 }