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