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