github.com/AbhinandanKurakure/podman/v3@v3.4.10/libpod/volume.go (about) 1 package libpod 2 3 import ( 4 "os" 5 "path/filepath" 6 "time" 7 8 "github.com/containers/podman/v3/libpod/define" 9 "github.com/containers/podman/v3/libpod/lock" 10 "github.com/containers/podman/v3/libpod/plugin" 11 ) 12 13 // Volume is a libpod named volume. 14 // Named volumes may be shared by multiple containers, and may be created using 15 // more complex options than normal bind mounts. They may be backed by a mounted 16 // filesystem on the host. 17 type Volume struct { 18 config *VolumeConfig 19 state *VolumeState 20 21 valid bool 22 plugin *plugin.VolumePlugin 23 runtime *Runtime 24 lock lock.Locker 25 } 26 27 // VolumeConfig holds the volume's immutable configuration. 28 type VolumeConfig struct { 29 // Name of the volume. 30 Name string `json:"name"` 31 // ID of the volume's lock. 32 LockID uint32 `json:"lockID"` 33 // Labels for the volume. 34 Labels map[string]string `json:"labels"` 35 // The volume driver. Empty string or local does not activate a volume 36 // driver, all other values will. 37 Driver string `json:"volumeDriver"` 38 // The location the volume is mounted at. 39 MountPoint string `json:"mountPoint"` 40 // Time the volume was created. 41 CreatedTime time.Time `json:"createdAt,omitempty"` 42 // Options to pass to the volume driver. For the local driver, this is 43 // a list of mount options. For other drivers, they are passed to the 44 // volume driver handling the volume. 45 Options map[string]string `json:"volumeOptions,omitempty"` 46 // Whether this volume is anonymous (will be removed on container exit) 47 IsAnon bool `json:"isAnon"` 48 // UID the volume will be created as. 49 UID int `json:"uid"` 50 // GID the volume will be created as. 51 GID int `json:"gid"` 52 // Size maximum of the volume. 53 Size uint64 `json:"size"` 54 // Inodes maximum of the volume. 55 Inodes uint64 `json:"inodes"` 56 } 57 58 // VolumeState holds the volume's mutable state. 59 // Volumes are not guaranteed to have a state. Only volumes using the Local 60 // driver that have mount options set will create a state. 61 type VolumeState struct { 62 // Mountpoint is the location where the volume was mounted. 63 // This is only used for volumes using a volume plugin, which will mount 64 // at non-standard locations. 65 MountPoint string `json:"mountPoint,omitempty"` 66 // MountCount is the number of times this volume has been requested to 67 // be mounted. 68 // It is incremented on mount() and decremented on unmount(). 69 // On incrementing from 0, the volume will be mounted on the host. 70 // On decrementing to 0, the volume will be unmounted on the host. 71 MountCount uint `json:"mountCount"` 72 // NeedsCopyUp indicates that the next time the volume is mounted into 73 // a container, the container will "copy up" the contents of the 74 // mountpoint into the volume. 75 // This should only be done once. As such, this is set at container 76 // create time, then cleared after the copy up is done and never set 77 // again. 78 NeedsCopyUp bool `json:"notYetMounted,omitempty"` 79 // NeedsChown indicates that the next time the volume is mounted into 80 // a container, the container will chown the volume to the container process 81 // UID/GID. 82 NeedsChown bool `json:"notYetChowned,omitempty"` 83 // UIDChowned is the UID the volume was chowned to. 84 UIDChowned int `json:"uidChowned,omitempty"` 85 // GIDChowned is the GID the volume was chowned to. 86 GIDChowned int `json:"gidChowned,omitempty"` 87 } 88 89 // Name retrieves the volume's name 90 func (v *Volume) Name() string { 91 return v.config.Name 92 } 93 94 // Returns the size on disk of volume 95 func (v *Volume) Size() (uint64, error) { 96 var size uint64 97 err := filepath.Walk(v.config.MountPoint, func(path string, info os.FileInfo, err error) error { 98 if err == nil && !info.IsDir() { 99 size += (uint64)(info.Size()) 100 } 101 return err 102 }) 103 return size, err 104 } 105 106 // Driver retrieves the volume's driver. 107 func (v *Volume) Driver() string { 108 return v.config.Driver 109 } 110 111 // Scope retrieves the volume's scope. 112 // Libpod does not implement volume scoping, and this is provided solely for 113 // Docker compatibility. It returns only "local". 114 func (v *Volume) Scope() string { 115 return "local" 116 } 117 118 // Labels returns the volume's labels 119 func (v *Volume) Labels() map[string]string { 120 labels := make(map[string]string) 121 for key, value := range v.config.Labels { 122 labels[key] = value 123 } 124 return labels 125 } 126 127 // MountPoint returns the volume's mountpoint on the host 128 func (v *Volume) MountPoint() (string, error) { 129 // For the sake of performance, avoid locking unless we have to. 130 if v.UsesVolumeDriver() { 131 v.lock.Lock() 132 defer v.lock.Unlock() 133 134 if err := v.update(); err != nil { 135 return "", err 136 } 137 } 138 139 return v.mountPoint(), nil 140 } 141 142 // MountCount returns the volume's mountcount on the host from state 143 // Useful in determining if volume is using plugin or a filesystem mount and its mount 144 func (v *Volume) MountCount() (uint, error) { 145 v.lock.Lock() 146 defer v.lock.Unlock() 147 if err := v.update(); err != nil { 148 return 0, err 149 } 150 return v.state.MountCount, nil 151 } 152 153 // Internal-only helper for volume mountpoint 154 func (v *Volume) mountPoint() string { 155 if v.UsesVolumeDriver() { 156 return v.state.MountPoint 157 } 158 159 return v.config.MountPoint 160 } 161 162 // Options return the volume's options 163 func (v *Volume) Options() map[string]string { 164 options := make(map[string]string) 165 for k, v := range v.config.Options { 166 options[k] = v 167 } 168 return options 169 } 170 171 // Anonymous returns whether this volume is anonymous. Anonymous volumes were 172 // created with a container, and will be removed when that container is removed. 173 func (v *Volume) Anonymous() bool { 174 return v.config.IsAnon 175 } 176 177 // UID returns the UID the volume will be created as. 178 func (v *Volume) UID() (int, error) { 179 v.lock.Lock() 180 defer v.lock.Unlock() 181 182 if err := v.update(); err != nil { 183 return -1, err 184 } 185 186 return v.uid(), nil 187 } 188 189 // Internal, unlocked accessor for UID. 190 func (v *Volume) uid() int { 191 if v.state.UIDChowned > 0 { 192 return v.state.UIDChowned 193 } 194 return v.config.UID 195 } 196 197 // GID returns the GID the volume will be created as. 198 func (v *Volume) GID() (int, error) { 199 v.lock.Lock() 200 defer v.lock.Unlock() 201 202 if err := v.update(); err != nil { 203 return -1, err 204 } 205 206 return v.gid(), nil 207 } 208 209 // Internal, unlocked accessor for GID. 210 func (v *Volume) gid() int { 211 if v.state.GIDChowned > 0 { 212 return v.state.GIDChowned 213 } 214 return v.config.GID 215 } 216 217 // CreatedTime returns the time the volume was created at. It was not tracked 218 // for some time, so older volumes may not contain one. 219 func (v *Volume) CreatedTime() time.Time { 220 return v.config.CreatedTime 221 } 222 223 // Config returns the volume's configuration. 224 func (v *Volume) Config() (*VolumeConfig, error) { 225 config := VolumeConfig{} 226 err := JSONDeepCopy(v.config, &config) 227 return &config, err 228 } 229 230 // VolumeInUse goes through the container dependencies of a volume 231 // and checks if the volume is being used by any container. 232 func (v *Volume) VolumeInUse() ([]string, error) { 233 v.lock.Lock() 234 defer v.lock.Unlock() 235 236 if !v.valid { 237 return nil, define.ErrVolumeRemoved 238 } 239 return v.runtime.state.VolumeInUse(v) 240 } 241 242 // IsDangling returns whether this volume is dangling (unused by any 243 // containers). 244 func (v *Volume) IsDangling() (bool, error) { 245 ctrs, err := v.VolumeInUse() 246 if err != nil { 247 return false, err 248 } 249 return len(ctrs) == 0, nil 250 } 251 252 // UsesVolumeDriver determines whether the volume uses a volume driver. Volume 253 // drivers are pluggable backends for volumes that will manage the storage and 254 // mounting. 255 func (v *Volume) UsesVolumeDriver() bool { 256 return !(v.config.Driver == define.VolumeDriverLocal || v.config.Driver == "") 257 }