github.com/fabiokung/docker@v0.11.2-0.20170222101415-4534dcd49497/volume/store/store.go (about) 1 package store 2 3 import ( 4 "net" 5 "os" 6 "path/filepath" 7 "sync" 8 "time" 9 10 "github.com/pkg/errors" 11 12 "github.com/Sirupsen/logrus" 13 "github.com/boltdb/bolt" 14 "github.com/docker/docker/pkg/locker" 15 "github.com/docker/docker/volume" 16 "github.com/docker/docker/volume/drivers" 17 ) 18 19 const ( 20 volumeDataDir = "volumes" 21 ) 22 23 type volumeWrapper struct { 24 volume.Volume 25 labels map[string]string 26 scope string 27 options map[string]string 28 } 29 30 func (v volumeWrapper) Options() map[string]string { 31 options := map[string]string{} 32 for key, value := range v.options { 33 options[key] = value 34 } 35 return options 36 } 37 38 func (v volumeWrapper) Labels() map[string]string { 39 return v.labels 40 } 41 42 func (v volumeWrapper) Scope() string { 43 return v.scope 44 } 45 46 func (v volumeWrapper) CachedPath() string { 47 if vv, ok := v.Volume.(interface { 48 CachedPath() string 49 }); ok { 50 return vv.CachedPath() 51 } 52 return v.Volume.Path() 53 } 54 55 // New initializes a VolumeStore to keep 56 // reference counting of volumes in the system. 57 func New(rootPath string) (*VolumeStore, error) { 58 vs := &VolumeStore{ 59 locks: &locker.Locker{}, 60 names: make(map[string]volume.Volume), 61 refs: make(map[string]map[string]struct{}), 62 labels: make(map[string]map[string]string), 63 options: make(map[string]map[string]string), 64 } 65 66 if rootPath != "" { 67 // initialize metadata store 68 volPath := filepath.Join(rootPath, volumeDataDir) 69 if err := os.MkdirAll(volPath, 750); err != nil { 70 return nil, err 71 } 72 73 dbPath := filepath.Join(volPath, "metadata.db") 74 75 var err error 76 vs.db, err = bolt.Open(dbPath, 0600, &bolt.Options{Timeout: 1 * time.Second}) 77 if err != nil { 78 return nil, errors.Wrap(err, "error while opening volume store metadata database") 79 } 80 81 // initialize volumes bucket 82 if err := vs.db.Update(func(tx *bolt.Tx) error { 83 if _, err := tx.CreateBucketIfNotExists(volumeBucketName); err != nil { 84 return errors.Wrap(err, "error while setting up volume store metadata database") 85 } 86 return nil 87 }); err != nil { 88 return nil, err 89 } 90 } 91 92 vs.restore() 93 94 return vs, nil 95 } 96 97 func (s *VolumeStore) getNamed(name string) (volume.Volume, bool) { 98 s.globalLock.RLock() 99 v, exists := s.names[name] 100 s.globalLock.RUnlock() 101 return v, exists 102 } 103 104 func (s *VolumeStore) setNamed(v volume.Volume, ref string) { 105 name := v.Name() 106 107 s.globalLock.Lock() 108 s.names[name] = v 109 if len(ref) > 0 { 110 if s.refs[name] == nil { 111 s.refs[name] = make(map[string]struct{}) 112 } 113 s.refs[name][ref] = struct{}{} 114 } 115 s.globalLock.Unlock() 116 } 117 118 // hasRef returns true if the given name has at least one ref. 119 // Callers of this function are expected to hold the name lock. 120 func (s *VolumeStore) hasRef(name string) bool { 121 s.globalLock.RLock() 122 l := len(s.refs[name]) 123 s.globalLock.RUnlock() 124 return l > 0 125 } 126 127 // getRefs gets the list of refs for a given name 128 // Callers of this function are expected to hold the name lock. 129 func (s *VolumeStore) getRefs(name string) []string { 130 s.globalLock.RLock() 131 defer s.globalLock.RUnlock() 132 133 refs := make([]string, 0, len(s.refs[name])) 134 for r := range s.refs[name] { 135 refs = append(refs, r) 136 } 137 138 return refs 139 } 140 141 // Purge allows the cleanup of internal data on docker in case 142 // the internal data is out of sync with volumes driver plugins. 143 func (s *VolumeStore) Purge(name string) { 144 s.globalLock.Lock() 145 v, exists := s.names[name] 146 if exists { 147 if _, err := volumedrivers.RemoveDriver(v.DriverName()); err != nil { 148 logrus.Errorf("Error dereferencing volume driver: %v", err) 149 } 150 } 151 if err := s.removeMeta(name); err != nil { 152 logrus.Errorf("Error removing volume metadata for volume %q: %v", name, err) 153 } 154 delete(s.names, name) 155 delete(s.refs, name) 156 delete(s.labels, name) 157 delete(s.options, name) 158 s.globalLock.Unlock() 159 } 160 161 // VolumeStore is a struct that stores the list of volumes available and keeps track of their usage counts 162 type VolumeStore struct { 163 // locks ensures that only one action is being performed on a particular volume at a time without locking the entire store 164 // since actions on volumes can be quite slow, this ensures the store is free to handle requests for other volumes. 165 locks *locker.Locker 166 // globalLock is used to protect access to mutable structures used by the store object 167 globalLock sync.RWMutex 168 // names stores the volume name -> volume relationship. 169 // This is used for making lookups faster so we don't have to probe all drivers 170 names map[string]volume.Volume 171 // refs stores the volume name and the list of things referencing it 172 refs map[string]map[string]struct{} 173 // labels stores volume labels for each volume 174 labels map[string]map[string]string 175 // options stores volume options for each volume 176 options map[string]map[string]string 177 db *bolt.DB 178 } 179 180 // List proxies to all registered volume drivers to get the full list of volumes 181 // If a driver returns a volume that has name which conflicts with another volume from a different driver, 182 // the first volume is chosen and the conflicting volume is dropped. 183 func (s *VolumeStore) List() ([]volume.Volume, []string, error) { 184 vols, warnings, err := s.list() 185 if err != nil { 186 return nil, nil, &OpErr{Err: err, Op: "list"} 187 } 188 var out []volume.Volume 189 190 for _, v := range vols { 191 name := normaliseVolumeName(v.Name()) 192 193 s.locks.Lock(name) 194 storedV, exists := s.getNamed(name) 195 // Note: it's not safe to populate the cache here because the volume may have been 196 // deleted before we acquire a lock on its name 197 if exists && storedV.DriverName() != v.DriverName() { 198 logrus.Warnf("Volume name %s already exists for driver %s, not including volume returned by %s", v.Name(), storedV.DriverName(), v.DriverName()) 199 s.locks.Unlock(v.Name()) 200 continue 201 } 202 203 out = append(out, v) 204 s.locks.Unlock(v.Name()) 205 } 206 return out, warnings, nil 207 } 208 209 // list goes through each volume driver and asks for its list of volumes. 210 func (s *VolumeStore) list() ([]volume.Volume, []string, error) { 211 var ( 212 ls []volume.Volume 213 warnings []string 214 ) 215 216 drivers, err := volumedrivers.GetAllDrivers() 217 if err != nil { 218 return nil, nil, err 219 } 220 221 type vols struct { 222 vols []volume.Volume 223 err error 224 driverName string 225 } 226 chVols := make(chan vols, len(drivers)) 227 228 for _, vd := range drivers { 229 go func(d volume.Driver) { 230 vs, err := d.List() 231 if err != nil { 232 chVols <- vols{driverName: d.Name(), err: &OpErr{Err: err, Name: d.Name(), Op: "list"}} 233 return 234 } 235 for i, v := range vs { 236 s.globalLock.RLock() 237 vs[i] = volumeWrapper{v, s.labels[v.Name()], d.Scope(), s.options[v.Name()]} 238 s.globalLock.RUnlock() 239 } 240 241 chVols <- vols{vols: vs} 242 }(vd) 243 } 244 245 badDrivers := make(map[string]struct{}) 246 for i := 0; i < len(drivers); i++ { 247 vs := <-chVols 248 249 if vs.err != nil { 250 warnings = append(warnings, vs.err.Error()) 251 badDrivers[vs.driverName] = struct{}{} 252 logrus.Warn(vs.err) 253 } 254 ls = append(ls, vs.vols...) 255 } 256 257 if len(badDrivers) > 0 { 258 s.globalLock.RLock() 259 for _, v := range s.names { 260 if _, exists := badDrivers[v.DriverName()]; exists { 261 ls = append(ls, v) 262 } 263 } 264 s.globalLock.RUnlock() 265 } 266 return ls, warnings, nil 267 } 268 269 // CreateWithRef creates a volume with the given name and driver and stores the ref 270 // This ensures there's no race between creating a volume and then storing a reference. 271 func (s *VolumeStore) CreateWithRef(name, driverName, ref string, opts, labels map[string]string) (volume.Volume, error) { 272 name = normaliseVolumeName(name) 273 s.locks.Lock(name) 274 defer s.locks.Unlock(name) 275 276 v, err := s.create(name, driverName, opts, labels) 277 if err != nil { 278 if _, ok := err.(*OpErr); ok { 279 return nil, err 280 } 281 return nil, &OpErr{Err: err, Name: name, Op: "create"} 282 } 283 284 s.setNamed(v, ref) 285 return v, nil 286 } 287 288 // Create creates a volume with the given name and driver. 289 // This is just like CreateWithRef() except we don't store a reference while holding the lock. 290 func (s *VolumeStore) Create(name, driverName string, opts, labels map[string]string) (volume.Volume, error) { 291 return s.CreateWithRef(name, driverName, "", opts, labels) 292 } 293 294 // checkConflict checks the local cache for name collisions with the passed in name, 295 // for existing volumes with the same name but in a different driver. 296 // This is used by `Create` as a best effort to prevent name collisions for volumes. 297 // If a matching volume is found that is not a conflict that is returned so the caller 298 // does not need to perform an additional lookup. 299 // When no matching volume is found, both returns will be nil 300 // 301 // Note: This does not probe all the drivers for name collisions because v1 plugins 302 // are very slow, particularly if the plugin is down, and cause other issues, 303 // particularly around locking the store. 304 // TODO(cpuguy83): With v2 plugins this shouldn't be a problem. Could also potentially 305 // use a connect timeout for this kind of check to ensure we aren't blocking for a 306 // long time. 307 func (s *VolumeStore) checkConflict(name, driverName string) (volume.Volume, error) { 308 // check the local cache 309 v, _ := s.getNamed(name) 310 if v == nil { 311 return nil, nil 312 } 313 314 vDriverName := v.DriverName() 315 var conflict bool 316 if driverName != "" { 317 // Retrieve canonical driver name to avoid inconsistencies (for example 318 // "plugin" vs. "plugin:latest") 319 vd, err := volumedrivers.GetDriver(driverName) 320 if err != nil { 321 return nil, err 322 } 323 324 if vDriverName != vd.Name() { 325 conflict = true 326 } 327 } 328 329 // let's check if the found volume ref 330 // is stale by checking with the driver if it still exists 331 exists, err := volumeExists(v) 332 if err != nil { 333 return nil, errors.Wrapf(errNameConflict, "found reference to volume '%s' in driver '%s', but got an error while checking the driver: %v", name, vDriverName, err) 334 } 335 336 if exists { 337 if conflict { 338 return nil, errors.Wrapf(errNameConflict, "driver '%s' already has volume '%s'", vDriverName, name) 339 } 340 return v, nil 341 } 342 343 if s.hasRef(v.Name()) { 344 // Containers are referencing this volume but it doesn't seem to exist anywhere. 345 // Return a conflict error here, the user can fix this with `docker volume rm -f` 346 return nil, errors.Wrapf(errNameConflict, "found references to volume '%s' in driver '%s' but the volume was not found in the driver -- you may need to remove containers referencing this volume or force remove the volume to re-create it", name, vDriverName) 347 } 348 349 // doesn't exist, so purge it from the cache 350 s.Purge(name) 351 return nil, nil 352 } 353 354 // volumeExists returns if the volume is still present in the driver. 355 // An error is returned if there was an issue communicating with the driver. 356 func volumeExists(v volume.Volume) (bool, error) { 357 exists, err := lookupVolume(v.DriverName(), v.Name()) 358 if err != nil { 359 return false, err 360 } 361 return exists != nil, nil 362 } 363 364 // create asks the given driver to create a volume with the name/opts. 365 // If a volume with the name is already known, it will ask the stored driver for the volume. 366 // If the passed in driver name does not match the driver name which is stored 367 // for the given volume name, an error is returned after checking if the reference is stale. 368 // If the reference is stale, it will be purged and this create can continue. 369 // It is expected that callers of this function hold any necessary locks. 370 func (s *VolumeStore) create(name, driverName string, opts, labels map[string]string) (volume.Volume, error) { 371 // Validate the name in a platform-specific manner 372 valid, err := volume.IsVolumeNameValid(name) 373 if err != nil { 374 return nil, err 375 } 376 if !valid { 377 return nil, &OpErr{Err: errInvalidName, Name: name, Op: "create"} 378 } 379 380 v, err := s.checkConflict(name, driverName) 381 if err != nil { 382 return nil, err 383 } 384 385 if v != nil { 386 return v, nil 387 } 388 389 // Since there isn't a specified driver name, let's see if any of the existing drivers have this volume name 390 if driverName == "" { 391 v, _ := s.getVolume(name) 392 if v != nil { 393 return v, nil 394 } 395 } 396 397 vd, err := volumedrivers.CreateDriver(driverName) 398 399 if err != nil { 400 return nil, &OpErr{Op: "create", Name: name, Err: err} 401 } 402 403 logrus.Debugf("Registering new volume reference: driver %q, name %q", vd.Name(), name) 404 405 if v, _ := vd.Get(name); v != nil { 406 return v, nil 407 } 408 v, err = vd.Create(name, opts) 409 if err != nil { 410 return nil, err 411 } 412 s.globalLock.Lock() 413 s.labels[name] = labels 414 s.options[name] = opts 415 s.refs[name] = make(map[string]struct{}) 416 s.globalLock.Unlock() 417 418 metadata := volumeMetadata{ 419 Name: name, 420 Driver: vd.Name(), 421 Labels: labels, 422 Options: opts, 423 } 424 425 if err := s.setMeta(name, metadata); err != nil { 426 return nil, err 427 } 428 return volumeWrapper{v, labels, vd.Scope(), opts}, nil 429 } 430 431 // GetWithRef gets a volume with the given name from the passed in driver and stores the ref 432 // This is just like Get(), but we store the reference while holding the lock. 433 // This makes sure there are no races between checking for the existence of a volume and adding a reference for it 434 func (s *VolumeStore) GetWithRef(name, driverName, ref string) (volume.Volume, error) { 435 name = normaliseVolumeName(name) 436 s.locks.Lock(name) 437 defer s.locks.Unlock(name) 438 439 vd, err := volumedrivers.GetDriver(driverName) 440 if err != nil { 441 return nil, &OpErr{Err: err, Name: name, Op: "get"} 442 } 443 444 v, err := vd.Get(name) 445 if err != nil { 446 return nil, &OpErr{Err: err, Name: name, Op: "get"} 447 } 448 449 s.setNamed(v, ref) 450 451 s.globalLock.RLock() 452 defer s.globalLock.RUnlock() 453 return volumeWrapper{v, s.labels[name], vd.Scope(), s.options[name]}, nil 454 } 455 456 // Get looks if a volume with the given name exists and returns it if so 457 func (s *VolumeStore) Get(name string) (volume.Volume, error) { 458 name = normaliseVolumeName(name) 459 s.locks.Lock(name) 460 defer s.locks.Unlock(name) 461 462 v, err := s.getVolume(name) 463 if err != nil { 464 return nil, &OpErr{Err: err, Name: name, Op: "get"} 465 } 466 s.setNamed(v, "") 467 return v, nil 468 } 469 470 // getVolume requests the volume, if the driver info is stored it just accesses that driver, 471 // if the driver is unknown it probes all drivers until it finds the first volume with that name. 472 // it is expected that callers of this function hold any necessary locks 473 func (s *VolumeStore) getVolume(name string) (volume.Volume, error) { 474 var meta volumeMetadata 475 meta, err := s.getMeta(name) 476 if err != nil { 477 return nil, err 478 } 479 480 driverName := meta.Driver 481 if driverName == "" { 482 s.globalLock.RLock() 483 v, exists := s.names[name] 484 s.globalLock.RUnlock() 485 if exists { 486 meta.Driver = v.DriverName() 487 if err := s.setMeta(name, meta); err != nil { 488 return nil, err 489 } 490 } 491 } 492 493 if meta.Driver != "" { 494 vol, err := lookupVolume(meta.Driver, name) 495 if err != nil { 496 return nil, err 497 } 498 if vol == nil { 499 s.Purge(name) 500 return nil, errNoSuchVolume 501 } 502 503 var scope string 504 vd, err := volumedrivers.GetDriver(meta.Driver) 505 if err == nil { 506 scope = vd.Scope() 507 } 508 return volumeWrapper{vol, meta.Labels, scope, meta.Options}, nil 509 } 510 511 logrus.Debugf("Probing all drivers for volume with name: %s", name) 512 drivers, err := volumedrivers.GetAllDrivers() 513 if err != nil { 514 return nil, err 515 } 516 517 for _, d := range drivers { 518 v, err := d.Get(name) 519 if err != nil || v == nil { 520 continue 521 } 522 meta.Driver = v.DriverName() 523 if err := s.setMeta(name, meta); err != nil { 524 return nil, err 525 } 526 return volumeWrapper{v, meta.Labels, d.Scope(), meta.Options}, nil 527 } 528 return nil, errNoSuchVolume 529 } 530 531 // lookupVolume gets the specified volume from the specified driver. 532 // This will only return errors related to communications with the driver. 533 // If the driver returns an error that is not communication related the 534 // error is logged but not returned. 535 // If the volume is not found it will return `nil, nil`` 536 func lookupVolume(driverName, volumeName string) (volume.Volume, error) { 537 vd, err := volumedrivers.GetDriver(driverName) 538 if err != nil { 539 return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", volumeName, driverName) 540 } 541 v, err := vd.Get(volumeName) 542 if err != nil { 543 err = errors.Cause(err) 544 if _, ok := err.(net.Error); ok { 545 return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", v.Name(), v.DriverName()) 546 } 547 548 // At this point, the error could be anything from the driver, such as "no such volume" 549 // Let's not check an error here, and instead check if the driver returned a volume 550 logrus.WithError(err).WithField("driver", driverName).WithField("volume", volumeName).Warnf("Error while looking up volume") 551 } 552 return v, nil 553 } 554 555 // Remove removes the requested volume. A volume is not removed if it has any refs 556 func (s *VolumeStore) Remove(v volume.Volume) error { 557 name := normaliseVolumeName(v.Name()) 558 s.locks.Lock(name) 559 defer s.locks.Unlock(name) 560 561 if s.hasRef(name) { 562 return &OpErr{Err: errVolumeInUse, Name: v.Name(), Op: "remove", Refs: s.getRefs(name)} 563 } 564 565 vd, err := volumedrivers.GetDriver(v.DriverName()) 566 if err != nil { 567 return &OpErr{Err: err, Name: vd.Name(), Op: "remove"} 568 } 569 570 logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name) 571 vol := unwrapVolume(v) 572 if err := vd.Remove(vol); err != nil { 573 return &OpErr{Err: err, Name: name, Op: "remove"} 574 } 575 576 s.Purge(name) 577 return nil 578 } 579 580 // Dereference removes the specified reference to the volume 581 func (s *VolumeStore) Dereference(v volume.Volume, ref string) { 582 name := v.Name() 583 584 s.locks.Lock(name) 585 defer s.locks.Unlock(name) 586 587 s.globalLock.Lock() 588 defer s.globalLock.Unlock() 589 590 if s.refs[name] != nil { 591 delete(s.refs[name], ref) 592 } 593 } 594 595 // Refs gets the current list of refs for the given volume 596 func (s *VolumeStore) Refs(v volume.Volume) []string { 597 name := v.Name() 598 599 s.locks.Lock(name) 600 defer s.locks.Unlock(name) 601 602 return s.getRefs(name) 603 } 604 605 // FilterByDriver returns the available volumes filtered by driver name 606 func (s *VolumeStore) FilterByDriver(name string) ([]volume.Volume, error) { 607 vd, err := volumedrivers.GetDriver(name) 608 if err != nil { 609 return nil, &OpErr{Err: err, Name: name, Op: "list"} 610 } 611 ls, err := vd.List() 612 if err != nil { 613 return nil, &OpErr{Err: err, Name: name, Op: "list"} 614 } 615 for i, v := range ls { 616 options := map[string]string{} 617 s.globalLock.RLock() 618 for key, value := range s.options[v.Name()] { 619 options[key] = value 620 } 621 ls[i] = volumeWrapper{v, s.labels[v.Name()], vd.Scope(), options} 622 s.globalLock.RUnlock() 623 } 624 return ls, nil 625 } 626 627 // FilterByUsed returns the available volumes filtered by if they are in use or not. 628 // `used=true` returns only volumes that are being used, while `used=false` returns 629 // only volumes that are not being used. 630 func (s *VolumeStore) FilterByUsed(vols []volume.Volume, used bool) []volume.Volume { 631 return s.filter(vols, func(v volume.Volume) bool { 632 s.locks.Lock(v.Name()) 633 hasRef := s.hasRef(v.Name()) 634 s.locks.Unlock(v.Name()) 635 return used == hasRef 636 }) 637 } 638 639 // filterFunc defines a function to allow filter volumes in the store 640 type filterFunc func(vol volume.Volume) bool 641 642 // filter returns the available volumes filtered by a filterFunc function 643 func (s *VolumeStore) filter(vols []volume.Volume, f filterFunc) []volume.Volume { 644 var ls []volume.Volume 645 for _, v := range vols { 646 if f(v) { 647 ls = append(ls, v) 648 } 649 } 650 return ls 651 } 652 653 func unwrapVolume(v volume.Volume) volume.Volume { 654 if vol, ok := v.(volumeWrapper); ok { 655 return vol.Volume 656 } 657 658 return v 659 } 660 661 // Shutdown releases all resources used by the volume store 662 // It does not make any changes to volumes, drivers, etc. 663 func (s *VolumeStore) Shutdown() error { 664 return s.db.Close() 665 }