github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/volume/volume.go (about) 1 package volume 2 3 import ( 4 "fmt" 5 "os" 6 "runtime" 7 "strings" 8 9 "github.com/Sirupsen/logrus" 10 "github.com/docker/docker/pkg/system" 11 ) 12 13 // DefaultDriverName is the driver name used for the driver 14 // implemented in the local package. 15 const DefaultDriverName string = "local" 16 17 // Driver is for creating and removing volumes. 18 type Driver interface { 19 // Name returns the name of the volume driver. 20 Name() string 21 // Create makes a new volume with the given id. 22 Create(name string, opts map[string]string) (Volume, error) 23 // Remove deletes the volume. 24 Remove(vol Volume) (err error) 25 // List lists all the volumes the driver has 26 List() ([]Volume, error) 27 // Get retrieves the volume with the requested name 28 Get(name string) (Volume, error) 29 } 30 31 // Volume is a place to store data. It is backed by a specific driver, and can be mounted. 32 type Volume interface { 33 // Name returns the name of the volume 34 Name() string 35 // DriverName returns the name of the driver which owns this volume. 36 DriverName() string 37 // Path returns the absolute path to the volume. 38 Path() string 39 // Mount mounts the volume and returns the absolute path to 40 // where it can be consumed. 41 Mount() (string, error) 42 // Unmount unmounts the volume when it is no longer in use. 43 Unmount() error 44 } 45 46 // MountPoint is the intersection point between a volume and a container. It 47 // specifies which volume is to be used and where inside a container it should 48 // be mounted. 49 type MountPoint struct { 50 Source string // Container host directory 51 Destination string // Inside the container 52 RW bool // True if writable 53 Name string // Name set by user 54 Driver string // Volume driver to use 55 Volume Volume `json:"-"` 56 57 // Note Mode is not used on Windows 58 Mode string `json:"Relabel"` // Originally field was `Relabel`" 59 60 // Note Propagation is not used on Windows 61 Propagation string // Mount propagation string 62 Named bool // specifies if the mountpoint was specified by name 63 64 // Specifies if data should be copied from the container before the first mount 65 // Use a pointer here so we can tell if the user set this value explicitly 66 // This allows us to error out when the user explicitly enabled copy but we can't copy due to the volume being populated 67 CopyData bool `json:"-"` 68 } 69 70 // Setup sets up a mount point by either mounting the volume if it is 71 // configured, or creating the source directory if supplied. 72 func (m *MountPoint) Setup() (string, error) { 73 if m.Volume != nil { 74 return m.Volume.Mount() 75 } 76 if len(m.Source) > 0 { 77 if _, err := os.Stat(m.Source); err != nil { 78 if !os.IsNotExist(err) { 79 return "", err 80 } 81 if runtime.GOOS != "windows" { // Windows does not have deprecation issues here 82 logrus.Warnf("Auto-creating non-existent volume host path %s, this is deprecated and will be removed soon", m.Source) 83 if err := system.MkdirAll(m.Source, 0755); err != nil { 84 return "", err 85 } 86 } 87 } 88 return m.Source, nil 89 } 90 return "", fmt.Errorf("Unable to setup mount point, neither source nor volume defined") 91 } 92 93 // Path returns the path of a volume in a mount point. 94 func (m *MountPoint) Path() string { 95 if m.Volume != nil { 96 return m.Volume.Path() 97 } 98 return m.Source 99 } 100 101 // ParseVolumesFrom ensures that the supplied volumes-from is valid. 102 func ParseVolumesFrom(spec string) (string, string, error) { 103 if len(spec) == 0 { 104 return "", "", fmt.Errorf("malformed volumes-from specification: %s", spec) 105 } 106 107 specParts := strings.SplitN(spec, ":", 2) 108 id := specParts[0] 109 mode := "rw" 110 111 if len(specParts) == 2 { 112 mode = specParts[1] 113 if !ValidMountMode(mode) { 114 return "", "", errInvalidMode(mode) 115 } 116 // For now don't allow propagation properties while importing 117 // volumes from data container. These volumes will inherit 118 // the same propagation property as of the original volume 119 // in data container. This probably can be relaxed in future. 120 if HasPropagation(mode) { 121 return "", "", errInvalidMode(mode) 122 } 123 // Do not allow copy modes on volumes-from 124 if _, isSet := getCopyMode(mode); isSet { 125 return "", "", errInvalidMode(mode) 126 } 127 } 128 return id, mode, nil 129 } 130 131 func errInvalidMode(mode string) error { 132 return fmt.Errorf("invalid mode: %v", mode) 133 } 134 135 func errInvalidSpec(spec string) error { 136 return fmt.Errorf("Invalid volume specification: '%s'", spec) 137 }