github.com/brahmaroutu/docker@v1.2.1-0.20160809185609-eb28dde01f16/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 ensures there's no race between creating a volume and then storing a reference. 216 func (s *VolumeStore) CreateWithRef(name, driverName, ref string, opts, labels map[string]string) (volume.Volume, error) { 217 name = normaliseVolumeName(name) 218 s.locks.Lock(name) 219 defer s.locks.Unlock(name) 220 221 v, err := s.create(name, driverName, opts, labels) 222 if err != nil { 223 return nil, &OpErr{Err: err, Name: name, Op: "create"} 224 } 225 226 s.setNamed(v, ref) 227 return v, nil 228 } 229 230 // Create creates a volume with the given name and driver. 231 // This is just like CreateWithRef() except we don't store a reference while holding the lock. 232 func (s *VolumeStore) Create(name, driverName string, opts, labels map[string]string) (volume.Volume, error) { 233 return s.CreateWithRef(name, driverName, "", opts, labels) 234 } 235 236 // create asks the given driver to create a volume with the name/opts. 237 // If a volume with the name is already known, it will ask the stored driver for the volume. 238 // If the passed in driver name does not match the driver name which is stored for the given volume name, an error is returned. 239 // It is expected that callers of this function hold any necessary locks. 240 func (s *VolumeStore) create(name, driverName string, opts, labels map[string]string) (volume.Volume, error) { 241 // Validate the name in a platform-specific manner 242 valid, err := volume.IsVolumeNameValid(name) 243 if err != nil { 244 return nil, err 245 } 246 if !valid { 247 return nil, &OpErr{Err: errInvalidName, Name: name, Op: "create"} 248 } 249 250 if v, exists := s.getNamed(name); exists { 251 if v.DriverName() != driverName && driverName != "" && driverName != volume.DefaultDriverName { 252 return nil, errNameConflict 253 } 254 return v, nil 255 } 256 257 // Since there isn't a specified driver name, let's see if any of the existing drivers have this volume name 258 if driverName == "" { 259 v, _ := s.getVolume(name) 260 if v != nil { 261 return v, nil 262 } 263 } 264 265 vd, err := volumedrivers.GetDriver(driverName) 266 267 if err != nil { 268 return nil, &OpErr{Op: "create", Name: name, Err: err} 269 } 270 271 logrus.Debugf("Registering new volume reference: driver %q, name %q", vd.Name(), name) 272 273 if v, _ := vd.Get(name); v != nil { 274 return v, nil 275 } 276 v, err := vd.Create(name, opts) 277 if err != nil { 278 return nil, err 279 } 280 s.globalLock.Lock() 281 s.labels[name] = labels 282 s.globalLock.Unlock() 283 284 if s.db != nil { 285 metadata := &volumeMetadata{ 286 Name: name, 287 Labels: labels, 288 } 289 290 volData, err := json.Marshal(metadata) 291 if err != nil { 292 return nil, err 293 } 294 295 if err := s.db.Update(func(tx *bolt.Tx) error { 296 b := tx.Bucket([]byte(volumeBucketName)) 297 err := b.Put([]byte(name), volData) 298 return err 299 }); err != nil { 300 return nil, err 301 } 302 } 303 304 return volumeWrapper{v, labels, vd.Scope()}, nil 305 } 306 307 // GetWithRef gets a volume with the given name from the passed in driver and stores the ref 308 // This is just like Get(), but we store the reference while holding the lock. 309 // This makes sure there are no races between checking for the existence of a volume and adding a reference for it 310 func (s *VolumeStore) GetWithRef(name, driverName, ref string) (volume.Volume, error) { 311 name = normaliseVolumeName(name) 312 s.locks.Lock(name) 313 defer s.locks.Unlock(name) 314 315 vd, err := volumedrivers.GetDriver(driverName) 316 if err != nil { 317 return nil, &OpErr{Err: err, Name: name, Op: "get"} 318 } 319 320 v, err := vd.Get(name) 321 if err != nil { 322 return nil, &OpErr{Err: err, Name: name, Op: "get"} 323 } 324 325 s.setNamed(v, ref) 326 327 return volumeWrapper{v, s.labels[name], vd.Scope()}, nil 328 } 329 330 // Get looks if a volume with the given name exists and returns it if so 331 func (s *VolumeStore) Get(name string) (volume.Volume, error) { 332 name = normaliseVolumeName(name) 333 s.locks.Lock(name) 334 defer s.locks.Unlock(name) 335 336 v, err := s.getVolume(name) 337 if err != nil { 338 return nil, &OpErr{Err: err, Name: name, Op: "get"} 339 } 340 s.setNamed(v, "") 341 return v, nil 342 } 343 344 // getVolume requests the volume, if the driver info is stored it just accesses that driver, 345 // if the driver is unknown it probes all drivers until it finds the first volume with that name. 346 // it is expected that callers of this function hold any necessary locks 347 func (s *VolumeStore) getVolume(name string) (volume.Volume, error) { 348 labels := map[string]string{} 349 350 if s.db != nil { 351 // get meta 352 if err := s.db.Update(func(tx *bolt.Tx) error { 353 b := tx.Bucket([]byte(volumeBucketName)) 354 data := b.Get([]byte(name)) 355 356 if string(data) == "" { 357 return nil 358 } 359 360 var meta volumeMetadata 361 buf := bytes.NewBuffer(data) 362 363 if err := json.NewDecoder(buf).Decode(&meta); err != nil { 364 return err 365 } 366 labels = meta.Labels 367 368 return nil 369 }); err != nil { 370 return nil, err 371 } 372 } 373 374 logrus.Debugf("Getting volume reference for name: %s", name) 375 s.globalLock.Lock() 376 v, exists := s.names[name] 377 s.globalLock.Unlock() 378 if exists { 379 vd, err := volumedrivers.GetDriver(v.DriverName()) 380 if err != nil { 381 return nil, err 382 } 383 vol, err := vd.Get(name) 384 if err != nil { 385 return nil, err 386 } 387 return volumeWrapper{vol, labels, vd.Scope()}, nil 388 } 389 390 logrus.Debugf("Probing all drivers for volume with name: %s", name) 391 drivers, err := volumedrivers.GetAllDrivers() 392 if err != nil { 393 return nil, err 394 } 395 396 for _, d := range drivers { 397 v, err := d.Get(name) 398 if err != nil { 399 continue 400 } 401 402 return volumeWrapper{v, labels, d.Scope()}, nil 403 } 404 return nil, errNoSuchVolume 405 } 406 407 // Remove removes the requested volume. A volume is not removed if it has any refs 408 func (s *VolumeStore) Remove(v volume.Volume) error { 409 name := normaliseVolumeName(v.Name()) 410 s.locks.Lock(name) 411 defer s.locks.Unlock(name) 412 413 if refs, exists := s.refs[name]; exists && len(refs) > 0 { 414 return &OpErr{Err: errVolumeInUse, Name: v.Name(), Op: "remove", Refs: refs} 415 } 416 417 vd, err := volumedrivers.GetDriver(v.DriverName()) 418 if err != nil { 419 return &OpErr{Err: err, Name: vd.Name(), Op: "remove"} 420 } 421 422 logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name) 423 vol := unwrapVolume(v) 424 if err := vd.Remove(vol); err != nil { 425 return &OpErr{Err: err, Name: name, Op: "remove"} 426 } 427 428 s.purge(name) 429 return nil 430 } 431 432 // Dereference removes the specified reference to the volume 433 func (s *VolumeStore) Dereference(v volume.Volume, ref string) { 434 s.locks.Lock(v.Name()) 435 defer s.locks.Unlock(v.Name()) 436 437 s.globalLock.Lock() 438 defer s.globalLock.Unlock() 439 var refs []string 440 441 for _, r := range s.refs[v.Name()] { 442 if r != ref { 443 refs = append(refs, r) 444 } 445 } 446 s.refs[v.Name()] = refs 447 } 448 449 // Refs gets the current list of refs for the given volume 450 func (s *VolumeStore) Refs(v volume.Volume) []string { 451 s.locks.Lock(v.Name()) 452 defer s.locks.Unlock(v.Name()) 453 454 s.globalLock.Lock() 455 defer s.globalLock.Unlock() 456 refs, exists := s.refs[v.Name()] 457 if !exists { 458 return nil 459 } 460 461 refsOut := make([]string, len(refs)) 462 copy(refsOut, refs) 463 return refsOut 464 } 465 466 // FilterByDriver returns the available volumes filtered by driver name 467 func (s *VolumeStore) FilterByDriver(name string) ([]volume.Volume, error) { 468 vd, err := volumedrivers.GetDriver(name) 469 if err != nil { 470 return nil, &OpErr{Err: err, Name: name, Op: "list"} 471 } 472 ls, err := vd.List() 473 if err != nil { 474 return nil, &OpErr{Err: err, Name: name, Op: "list"} 475 } 476 for i, v := range ls { 477 ls[i] = volumeWrapper{v, s.labels[v.Name()], vd.Scope()} 478 } 479 return ls, nil 480 } 481 482 // FilterByUsed returns the available volumes filtered by if they are in use or not. 483 // `used=true` returns only volumes that are being used, while `used=false` returns 484 // only volumes that are not being used. 485 func (s *VolumeStore) FilterByUsed(vols []volume.Volume, used bool) []volume.Volume { 486 return s.filter(vols, func(v volume.Volume) bool { 487 s.locks.Lock(v.Name()) 488 l := len(s.refs[v.Name()]) 489 s.locks.Unlock(v.Name()) 490 if (used && l > 0) || (!used && l == 0) { 491 return true 492 } 493 return false 494 }) 495 } 496 497 // filterFunc defines a function to allow filter volumes in the store 498 type filterFunc func(vol volume.Volume) bool 499 500 // filter returns the available volumes filtered by a filterFunc function 501 func (s *VolumeStore) filter(vols []volume.Volume, f filterFunc) []volume.Volume { 502 var ls []volume.Volume 503 for _, v := range vols { 504 if f(v) { 505 ls = append(ls, v) 506 } 507 } 508 return ls 509 } 510 511 func unwrapVolume(v volume.Volume) volume.Volume { 512 if vol, ok := v.(volumeWrapper); ok { 513 return vol.Volume 514 } 515 516 return v 517 }