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