github.com/45cali/docker@v1.11.1/volume/store/store.go (about) 1 package store 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "os" 7 "path/filepath" 8 "sync" 9 "time" 10 11 "github.com/Sirupsen/logrus" 12 "github.com/boltdb/bolt" 13 "github.com/docker/docker/pkg/locker" 14 "github.com/docker/docker/volume" 15 "github.com/docker/docker/volume/drivers" 16 ) 17 18 const ( 19 volumeDataDir = "volumes" 20 volumeBucketName = "volumes" 21 ) 22 23 type volumeMetadata struct { 24 Name string 25 Labels map[string]string 26 } 27 28 type volumeWithLabels struct { 29 volume.Volume 30 labels map[string]string 31 } 32 33 func (v volumeWithLabels) Labels() map[string]string { 34 return v.labels 35 } 36 37 // New initializes a VolumeStore to keep 38 // reference counting of volumes in the system. 39 func New(rootPath string) (*VolumeStore, error) { 40 vs := &VolumeStore{ 41 locks: &locker.Locker{}, 42 names: make(map[string]volume.Volume), 43 refs: make(map[string][]string), 44 labels: make(map[string]map[string]string), 45 } 46 47 if rootPath != "" { 48 // initialize metadata store 49 volPath := filepath.Join(rootPath, volumeDataDir) 50 if err := os.MkdirAll(volPath, 750); err != nil { 51 return nil, err 52 } 53 54 dbPath := filepath.Join(volPath, "metadata.db") 55 56 var err error 57 vs.db, err = bolt.Open(dbPath, 0600, &bolt.Options{Timeout: 1 * time.Second}) 58 if err != nil { 59 return nil, err 60 } 61 62 // initialize volumes bucket 63 if err := vs.db.Update(func(tx *bolt.Tx) error { 64 if _, err := tx.CreateBucketIfNotExists([]byte(volumeBucketName)); err != nil { 65 return err 66 } 67 68 return nil 69 }); err != nil { 70 return nil, err 71 } 72 } 73 74 return vs, nil 75 } 76 77 func (s *VolumeStore) getNamed(name string) (volume.Volume, bool) { 78 s.globalLock.Lock() 79 v, exists := s.names[name] 80 s.globalLock.Unlock() 81 return v, exists 82 } 83 84 func (s *VolumeStore) setNamed(v volume.Volume, ref string) { 85 s.globalLock.Lock() 86 s.names[v.Name()] = v 87 if len(ref) > 0 { 88 s.refs[v.Name()] = append(s.refs[v.Name()], ref) 89 } 90 s.globalLock.Unlock() 91 } 92 93 func (s *VolumeStore) purge(name string) { 94 s.globalLock.Lock() 95 delete(s.names, name) 96 delete(s.refs, name) 97 delete(s.labels, name) 98 s.globalLock.Unlock() 99 } 100 101 // VolumeStore is a struct that stores the list of volumes available and keeps track of their usage counts 102 type VolumeStore struct { 103 locks *locker.Locker 104 globalLock sync.Mutex 105 // names stores the volume name -> driver name relationship. 106 // This is used for making lookups faster so we don't have to probe all drivers 107 names map[string]volume.Volume 108 // refs stores the volume name and the list of things referencing it 109 refs map[string][]string 110 // labels stores volume labels for each volume 111 labels map[string]map[string]string 112 db *bolt.DB 113 } 114 115 // List proxies to all registered volume drivers to get the full list of volumes 116 // If a driver returns a volume that has name which conflicts with another volume from a different driver, 117 // the first volume is chosen and the conflicting volume is dropped. 118 func (s *VolumeStore) List() ([]volume.Volume, []string, error) { 119 vols, warnings, err := s.list() 120 if err != nil { 121 return nil, nil, &OpErr{Err: err, Op: "list"} 122 } 123 var out []volume.Volume 124 125 for _, v := range vols { 126 name := normaliseVolumeName(v.Name()) 127 128 s.locks.Lock(name) 129 storedV, exists := s.getNamed(name) 130 // Note: it's not safe to populate the cache here because the volume may have been 131 // deleted before we acquire a lock on its name 132 if exists && storedV.DriverName() != v.DriverName() { 133 logrus.Warnf("Volume name %s already exists for driver %s, not including volume returned by %s", v.Name(), storedV.DriverName(), v.DriverName()) 134 s.locks.Unlock(v.Name()) 135 continue 136 } 137 138 out = append(out, v) 139 s.locks.Unlock(v.Name()) 140 } 141 return out, warnings, nil 142 } 143 144 // list goes through each volume driver and asks for its list of volumes. 145 func (s *VolumeStore) list() ([]volume.Volume, []string, error) { 146 drivers, err := volumedrivers.GetAllDrivers() 147 if err != nil { 148 return nil, nil, err 149 } 150 var ( 151 ls []volume.Volume 152 warnings []string 153 ) 154 155 type vols struct { 156 vols []volume.Volume 157 err error 158 driverName string 159 } 160 chVols := make(chan vols, len(drivers)) 161 162 for _, vd := range drivers { 163 go func(d volume.Driver) { 164 vs, err := d.List() 165 if err != nil { 166 chVols <- vols{driverName: d.Name(), err: &OpErr{Err: err, Name: d.Name(), Op: "list"}} 167 return 168 } 169 chVols <- vols{vols: vs} 170 }(vd) 171 } 172 173 badDrivers := make(map[string]struct{}) 174 for i := 0; i < len(drivers); i++ { 175 vs := <-chVols 176 177 if vs.err != nil { 178 warnings = append(warnings, vs.err.Error()) 179 badDrivers[vs.driverName] = struct{}{} 180 logrus.Warn(vs.err) 181 } 182 ls = append(ls, vs.vols...) 183 } 184 185 if len(badDrivers) > 0 { 186 for _, v := range s.names { 187 if _, exists := badDrivers[v.DriverName()]; exists { 188 ls = append(ls, v) 189 } 190 } 191 } 192 return ls, warnings, nil 193 } 194 195 // CreateWithRef creates a volume with the given name and driver and stores the ref 196 // This is just like Create() except we store the reference while holding the lock. 197 // This ensures there's no race between creating a volume and then storing a reference. 198 func (s *VolumeStore) CreateWithRef(name, driverName, ref string, opts, labels map[string]string) (volume.Volume, error) { 199 name = normaliseVolumeName(name) 200 s.locks.Lock(name) 201 defer s.locks.Unlock(name) 202 203 v, err := s.create(name, driverName, opts, labels) 204 if err != nil { 205 return nil, &OpErr{Err: err, Name: name, Op: "create"} 206 } 207 208 s.setNamed(v, ref) 209 return v, nil 210 } 211 212 // Create creates a volume with the given name and driver. 213 func (s *VolumeStore) Create(name, driverName string, opts, labels map[string]string) (volume.Volume, error) { 214 name = normaliseVolumeName(name) 215 s.locks.Lock(name) 216 defer s.locks.Unlock(name) 217 218 v, err := s.create(name, driverName, opts, labels) 219 if err != nil { 220 return nil, &OpErr{Err: err, Name: name, Op: "create"} 221 } 222 s.setNamed(v, "") 223 return v, nil 224 } 225 226 // create asks the given driver to create a volume with the name/opts. 227 // If a volume with the name is already known, it will ask the stored driver for the volume. 228 // If the passed in driver name does not match the driver name which is stored for the given volume name, an error is returned. 229 // It is expected that callers of this function hold any necessary locks. 230 func (s *VolumeStore) create(name, driverName string, opts, labels map[string]string) (volume.Volume, error) { 231 // Validate the name in a platform-specific manner 232 valid, err := volume.IsVolumeNameValid(name) 233 if err != nil { 234 return nil, err 235 } 236 if !valid { 237 return nil, &OpErr{Err: errInvalidName, Name: name, Op: "create"} 238 } 239 240 if v, exists := s.getNamed(name); exists { 241 if v.DriverName() != driverName && driverName != "" && driverName != volume.DefaultDriverName { 242 return nil, errNameConflict 243 } 244 return v, nil 245 } 246 247 // Since there isn't a specified driver name, let's see if any of the existing drivers have this volume name 248 if driverName == "" { 249 v, _ := s.getVolume(name) 250 if v != nil { 251 return v, nil 252 } 253 } 254 255 vd, err := volumedrivers.GetDriver(driverName) 256 257 if err != nil { 258 return nil, &OpErr{Op: "create", Name: name, Err: err} 259 } 260 261 logrus.Debugf("Registering new volume reference: driver %q, name %q", vd.Name(), name) 262 263 if v, _ := vd.Get(name); v != nil { 264 return v, nil 265 } 266 v, err := vd.Create(name, opts) 267 if err != nil { 268 return nil, err 269 } 270 s.globalLock.Lock() 271 s.labels[name] = labels 272 s.globalLock.Unlock() 273 274 if s.db != nil { 275 metadata := &volumeMetadata{ 276 Name: name, 277 Labels: labels, 278 } 279 280 volData, err := json.Marshal(metadata) 281 if err != nil { 282 return nil, err 283 } 284 285 if err := s.db.Update(func(tx *bolt.Tx) error { 286 b := tx.Bucket([]byte(volumeBucketName)) 287 err := b.Put([]byte(name), volData) 288 return err 289 }); err != nil { 290 return nil, err 291 } 292 } 293 294 return volumeWithLabels{v, labels}, nil 295 } 296 297 // GetWithRef gets a volume with the given name from the passed in driver and stores the ref 298 // This is just like Get(), but we store the reference while holding the lock. 299 // This makes sure there are no races between checking for the existence of a volume and adding a reference for it 300 func (s *VolumeStore) GetWithRef(name, driverName, ref string) (volume.Volume, error) { 301 name = normaliseVolumeName(name) 302 s.locks.Lock(name) 303 defer s.locks.Unlock(name) 304 305 vd, err := volumedrivers.GetDriver(driverName) 306 if err != nil { 307 return nil, &OpErr{Err: err, Name: name, Op: "get"} 308 } 309 310 v, err := vd.Get(name) 311 if err != nil { 312 return nil, &OpErr{Err: err, Name: name, Op: "get"} 313 } 314 315 s.setNamed(v, ref) 316 if labels, ok := s.labels[name]; ok { 317 return volumeWithLabels{v, labels}, nil 318 } 319 return v, nil 320 } 321 322 // Get looks if a volume with the given name exists and returns it if so 323 func (s *VolumeStore) Get(name string) (volume.Volume, error) { 324 name = normaliseVolumeName(name) 325 s.locks.Lock(name) 326 defer s.locks.Unlock(name) 327 328 v, err := s.getVolume(name) 329 if err != nil { 330 return nil, &OpErr{Err: err, Name: name, Op: "get"} 331 } 332 s.setNamed(v, "") 333 return v, nil 334 } 335 336 // getVolume requests the volume, if the driver info is stored it just accesses that driver, 337 // if the driver is unknown it probes all drivers until it finds the first volume with that name. 338 // it is expected that callers of this function hold any necessary locks 339 func (s *VolumeStore) getVolume(name string) (volume.Volume, error) { 340 labels := map[string]string{} 341 342 if s.db != nil { 343 // get meta 344 if err := s.db.Update(func(tx *bolt.Tx) error { 345 b := tx.Bucket([]byte(volumeBucketName)) 346 data := b.Get([]byte(name)) 347 348 if string(data) == "" { 349 return nil 350 } 351 352 var meta volumeMetadata 353 buf := bytes.NewBuffer(data) 354 355 if err := json.NewDecoder(buf).Decode(&meta); err != nil { 356 return err 357 } 358 labels = meta.Labels 359 360 return nil 361 }); err != nil { 362 return nil, err 363 } 364 } 365 366 logrus.Debugf("Getting volume reference for name: %s", name) 367 s.globalLock.Lock() 368 v, exists := s.names[name] 369 s.globalLock.Unlock() 370 if exists { 371 vd, err := volumedrivers.GetDriver(v.DriverName()) 372 if err != nil { 373 return nil, err 374 } 375 vol, err := vd.Get(name) 376 if err != nil { 377 return nil, err 378 } 379 return volumeWithLabels{vol, labels}, nil 380 } 381 382 logrus.Debugf("Probing all drivers for volume with name: %s", name) 383 drivers, err := volumedrivers.GetAllDrivers() 384 if err != nil { 385 return nil, err 386 } 387 388 for _, d := range drivers { 389 v, err := d.Get(name) 390 if err != nil { 391 continue 392 } 393 394 return volumeWithLabels{v, labels}, nil 395 } 396 return nil, errNoSuchVolume 397 } 398 399 // Remove removes the requested volume. A volume is not removed if it has any refs 400 func (s *VolumeStore) Remove(v volume.Volume) error { 401 name := normaliseVolumeName(v.Name()) 402 s.locks.Lock(name) 403 defer s.locks.Unlock(name) 404 405 if refs, exists := s.refs[name]; exists && len(refs) > 0 { 406 return &OpErr{Err: errVolumeInUse, Name: v.Name(), Op: "remove", Refs: refs} 407 } 408 409 vd, err := volumedrivers.GetDriver(v.DriverName()) 410 if err != nil { 411 return &OpErr{Err: err, Name: vd.Name(), Op: "remove"} 412 } 413 414 logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name) 415 vol := withoutLabels(v) 416 if err := vd.Remove(vol); err != nil { 417 return &OpErr{Err: err, Name: name, Op: "remove"} 418 } 419 420 s.purge(name) 421 return nil 422 } 423 424 // Dereference removes the specified reference to the volume 425 func (s *VolumeStore) Dereference(v volume.Volume, ref string) { 426 s.locks.Lock(v.Name()) 427 defer s.locks.Unlock(v.Name()) 428 429 s.globalLock.Lock() 430 defer s.globalLock.Unlock() 431 var refs []string 432 433 for _, r := range s.refs[v.Name()] { 434 if r != ref { 435 refs = append(refs, r) 436 } 437 } 438 s.refs[v.Name()] = refs 439 } 440 441 // Refs gets the current list of refs for the given volume 442 func (s *VolumeStore) Refs(v volume.Volume) []string { 443 s.locks.Lock(v.Name()) 444 defer s.locks.Unlock(v.Name()) 445 446 s.globalLock.Lock() 447 defer s.globalLock.Unlock() 448 refs, exists := s.refs[v.Name()] 449 if !exists { 450 return nil 451 } 452 453 refsOut := make([]string, len(refs)) 454 copy(refsOut, refs) 455 return refsOut 456 } 457 458 // FilterByDriver returns the available volumes filtered by driver name 459 func (s *VolumeStore) FilterByDriver(name string) ([]volume.Volume, error) { 460 vd, err := volumedrivers.GetDriver(name) 461 if err != nil { 462 return nil, &OpErr{Err: err, Name: name, Op: "list"} 463 } 464 ls, err := vd.List() 465 if err != nil { 466 return nil, &OpErr{Err: err, Name: name, Op: "list"} 467 } 468 return ls, nil 469 } 470 471 // FilterByUsed returns the available volumes filtered by if they are in use or not. 472 // `used=true` returns only volumes that are being used, while `used=false` returns 473 // only volumes that are not being used. 474 func (s *VolumeStore) FilterByUsed(vols []volume.Volume, used bool) []volume.Volume { 475 return s.filter(vols, func(v volume.Volume) bool { 476 s.locks.Lock(v.Name()) 477 l := len(s.refs[v.Name()]) 478 s.locks.Unlock(v.Name()) 479 if (used && l > 0) || (!used && l == 0) { 480 return true 481 } 482 return false 483 }) 484 } 485 486 // filterFunc defines a function to allow filter volumes in the store 487 type filterFunc func(vol volume.Volume) bool 488 489 // filter returns the available volumes filtered by a filterFunc function 490 func (s *VolumeStore) filter(vols []volume.Volume, f filterFunc) []volume.Volume { 491 var ls []volume.Volume 492 for _, v := range vols { 493 if f(v) { 494 ls = append(ls, v) 495 } 496 } 497 return ls 498 } 499 500 func withoutLabels(v volume.Volume) volume.Volume { 501 if vol, ok := v.(volumeWithLabels); ok { 502 return vol.Volume 503 } 504 505 return v 506 }