func (s *testSuite) TestWatchVolumes(c *C) { entChan, errChan := s.client.WatchPrefix(&db.Volume{}) select { case err := <-errChan: c.Assert(err, IsNil) default: } c.Assert(s.client.Set(testPolicies["basic"]), IsNil) vol, err := db.CreateVolume(&db.VolumeRequest{Policy: testPolicies["basic"], Name: "test"}) c.Assert(err, IsNil) c.Assert(s.client.Set(vol), IsNil) select { case err := <-errChan: c.Assert(err, IsNil) case ent := <-entChan: vol2 := ent.(*db.Volume) c.Assert(vol, DeepEquals, vol2) } c.Assert(s.client.WatchPrefixStop(&db.Volume{}), IsNil) vol, err = db.CreateVolume(&db.VolumeRequest{Policy: testPolicies["basic"], Name: "test2"}) c.Assert(err, IsNil) c.Assert(s.client.Set(vol), IsNil) select { case <-entChan: c.Assert(false, Equals, true, Commentf("received on a should-be-closed channel")) default: } }
func (s *testSuite) TestMountSource(c *C) { c.Assert(s.client.Set(testPolicies["nfs"]), IsNil) vol, err := db.CreateVolume(&db.VolumeRequest{Policy: testPolicies["nfs"], Name: "test", Options: map[string]string{"mount": "localhost:/mnt"}}) c.Assert(err, IsNil) c.Assert(vol.MountSource, Equals, "localhost:/mnt") _, err = db.CreateVolume(&db.VolumeRequest{Policy: testPolicies["nfs"], Name: "test2"}) c.Assert(err, NotNil) copy := testPolicies["basic"].Copy() copy.(*db.Policy).Name = "nfs" c.Assert(s.client.Set(testPolicies["basic"]), IsNil) vol, err = db.CreateVolume(&db.VolumeRequest{Policy: copy.(*db.Policy), Name: "test2"}) c.Assert(err, IsNil) c.Assert(vol.MountSource, Equals, "") }
func (s *testSuite) TestWatchVolumes(c *C) { entChan, errChan := s.client.WatchPrefix(&db.Volume{}) select { case err := <-errChan: c.Assert(err, IsNil) default: } c.Assert(s.client.Set(testPolicies["basic"]), IsNil) vol, err := db.CreateVolume(&db.VolumeRequest{Policy: testPolicies["basic"], Name: "test"}) c.Assert(err, IsNil) for i := 0; i < 5; i++ { vol.VolumeName = fmt.Sprintf("test%d", i) c.Assert(s.client.Set(vol), IsNil) select { case err := <-errChan: c.Assert(err, IsNil) case ent := <-entChan: logrus.Infof("Received object for %v during prefix watch", ent) vol2 := ent.(*db.Volume) c.Assert(vol, DeepEquals, vol2) } c.Assert(s.client.Delete(vol), IsNil) time.Sleep(200 * time.Millisecond) // wait for watch select { case <-errChan: panic("error received after delete in watch") case <-entChan: panic("object received after delete in watch") default: logrus.Info("Watch delete was processed successfully") } } c.Assert(s.client.WatchPrefixStop(&db.Volume{}), IsNil) vol, err = db.CreateVolume(&db.VolumeRequest{Policy: testPolicies["basic"], Name: "test2"}) c.Assert(err, IsNil) c.Assert(s.client.Set(vol), IsNil) select { case <-entChan: c.Assert(false, Equals, true, Commentf("received on a should-be-closed channel")) default: } }
func (s *testSuite) TestRuntimeWatch(c *C) { c.Assert(s.client.Set(testPolicies["basic"]), IsNil) policy := db.NewPolicy("basic") c.Assert(s.client.Get(policy), IsNil) vol, err := db.CreateVolume(&db.VolumeRequest{Policy: policy, Name: "bar"}) c.Assert(err, IsNil) objChan, errChan := s.client.WatchPrefix(&db.RuntimeOptions{}) defer s.client.WatchPrefixStop(&db.RuntimeOptions{}) opts := db.NewRuntimeOptions(vol.PolicyName, vol.VolumeName) opts.RateLimit.ReadBPS = 1000 c.Assert(s.client.Set(opts), IsNil) select { case err := <-errChan: c.Assert(err, IsNil) case obj := <-objChan: c.Assert(obj.(*db.RuntimeOptions).RateLimit.ReadBPS, Equals, uint64(1000)) c.Assert(obj.(*db.RuntimeOptions).Policy(), Not(Equals), "") c.Assert(obj.(*db.RuntimeOptions).Policy(), Equals, vol.PolicyName) c.Assert(obj.(*db.RuntimeOptions).Volume(), Not(Equals), "") c.Assert(obj.(*db.RuntimeOptions).Volume(), Equals, vol.VolumeName) } }
func (s *testSuite) TestLockTTLRefresh(c *C) { copy := testPolicies["basic"].Copy() copy.(*db.Policy).Name = "policy1" c.Assert(s.client.Set(copy), IsNil) v, err := db.CreateVolume(&db.VolumeRequest{Policy: copy.(*db.Policy), Name: "test"}) c.Assert(err, IsNil, Commentf("%v", v)) c.Assert(s.client.Set(v), IsNil) lock := db.NewCreateOwner("mon0", v) s.client.Free(lock, true) stopChan, err := s.client.AcquireAndRefresh(lock, 15*time.Second) c.Assert(err, IsNil) sync := make(chan struct{}) sync2 := make(chan struct{}) // gocheck doesn't run very well in goroutines, so these panics are a // makeshift version of what gocheck actually does. go func(v *db.Volume) { for { select { case <-sync: lock := db.NewCreateOwner("mon1", v) time.Sleep(15 * time.Second) if err := s.client.Acquire(lock); err != nil { panic(err) } if err := s.client.Free(lock, false); err != nil { panic(err) } close(sync2) return default: lock := db.NewCreateOwner("mon1", v) if err := s.client.Acquire(lock); err == nil { panic("Acquired lock for mon1") } } } }(v) logrus.Infof("Creating contention in %s", Driver) time.Sleep(time.Minute) close(stopChan) close(sync) <-sync2 logrus.Info("Lock successfully traded in background goroutine!") }
func (s *testSuite) TestLockBattery(c *C) { copy := testPolicies["basic"].Copy() copy.(*db.Policy).Name = "policy1" c.Assert(s.client.Set(copy), IsNil) v, err := db.CreateVolume(&db.VolumeRequest{Policy: copy.(*db.Policy), Name: "test"}) c.Assert(err, IsNil, Commentf("%v", v)) c.Assert(s.client.Set(v), IsNil) lock := db.NewCreateOwner("mon0", v) c.Assert(s.client.Acquire(lock), IsNil) // go routine A should never free the lock. // go routine B should never succeed at acquiring it. syncChan1 := make(chan struct{}) syncChan2 := make(chan struct{}, 1) defer func() { syncChan2 <- struct{}{} // this relays to the first one to ensure the lock is freed syncChan1 <- struct{}{} // this relays to the second one to terminate it }() go func(v *db.Volume) { lock := db.NewCreateOwner("mon0", v) for { select { case <-syncChan1: s.client.Free(lock, true) return default: c.Assert(s.client.Acquire(lock), IsNil) } } }(v) go func(v *db.Volume) { lock := db.NewCreateOwner("mon1", v) for { select { case <-syncChan2: return default: logrus.Debug("Attempting to acquire lock (should fail)") c.Assert(s.client.Acquire(lock), NotNil) } } }(v) logrus.Infof("Creating contention in %s", Driver) time.Sleep(time.Minute) }
func (s *testSuite) TestLockAcquire(c *C) { copy := testPolicies["basic"].Copy() copy.(*db.Policy).Name = "policy1" c.Assert(s.client.Set(copy), IsNil) v, err := db.CreateVolume(&db.VolumeRequest{Policy: copy.(*db.Policy), Name: "test"}) c.Assert(err, IsNil, Commentf("%v", v)) c.Assert(s.client.Set(v), IsNil) lock := db.NewCreateOwner("mon0", v) path, err := lock.Path() c.Assert(err, IsNil) c.Assert(path, Equals, strings.Join([]string{lock.Prefix(), v.String()}, "/")) c.Assert(lock.Prefix(), Equals, "users/volume") c.Assert(s.client.Acquire(lock), IsNil) testUse := db.NewUse(v) c.Assert(s.client.Get(testUse), IsNil) // test that we can acquire the fetched lock. path, err = testUse.Path() c.Assert(err, IsNil) c.Assert(path, Equals, strings.Join([]string{lock.Prefix(), v.String()}, "/")) c.Assert(lock.Prefix(), Equals, "users/volume") c.Assert(s.client.Acquire(lock), IsNil) lock2 := db.NewCreateOwner("mon1", v) c.Assert(s.client.Acquire(lock2), NotNil) c.Assert(s.client.Free(lock2, false), NotNil) c.Assert(s.client.Free(lock, false), IsNil) c.Assert(s.client.Acquire(lock2), IsNil) c.Assert(s.client.Free(lock2, false), IsNil) c.Assert(s.client.Acquire(lock), IsNil) c.Assert(s.client.Free(lock2, true), IsNil) }
func (s *testSuite) TestLockTTL(c *C) { copy := testPolicies["basic"].Copy() copy.(*db.Policy).Name = "policy1" c.Assert(s.client.Set(copy), IsNil) v, err := db.CreateVolume(&db.VolumeRequest{Policy: copy.(*db.Policy), Name: "test"}) c.Assert(err, IsNil, Commentf("%v", v)) c.Assert(s.client.Set(v), IsNil) lock := db.NewCreateOwner("mon0", v) lock2 := db.NewCreateOwner("mon1", v) s.client.Free(lock, true) c.Assert(s.client.AcquireWithTTL(lock, 15*time.Second), IsNil) c.Assert(s.client.AcquireWithTTL(lock2, 15*time.Second), NotNil) time.Sleep(5 * time.Second) // wait for ttl to expire. minimum timeout is 10s so we're testing that. c.Assert(s.client.AcquireWithTTL(lock2, time.Second), NotNil) // test in the middle so we're sure the lock isn't freed yet. time.Sleep(11 * time.Second) c.Assert(s.client.AcquireWithTTL(lock2, time.Second), IsNil) c.Assert(s.client.Free(lock2, false), IsNil) }
func (s *testSuite) TestToDriverOptions(c *C) { c.Assert(s.client.Set(testPolicies["basic"]), IsNil) vol, err := db.CreateVolume(&db.VolumeRequest{Policy: testPolicies["basic"], Name: "test"}) c.Assert(err, IsNil) do, err := vol.ToDriverOptions(1) c.Assert(err, IsNil) expected := storage.DriverOptions{ Volume: storage.Volume{ Name: "basic/test", Size: 0xa, Params: storage.Params{"pool": "rbd"}, }, FSOptions: storage.FSOptions{ Type: "ext4", CreateCommand: "", }, Timeout: 1, Options: nil, } c.Assert(do, DeepEquals, expected) }
func (s *testSuite) TestVolumeCRUD(c *C) { policyNames := []string{"foo", "bar"} volumeNames := []string{"baz", "quux"} c.Assert(s.client.Set(&db.Volume{}), NotNil) _, err := db.CreateVolume(&db.VolumeRequest{Policy: nil}) c.Assert(err, NotNil) // populate the policies so the next few tests don't give false positives for _, policy := range policyNames { copy := testPolicies["basic"].Copy() copy.(*db.Policy).Name = policy err := s.client.Set(copy) c.Assert(err, IsNil, Commentf("%v", err)) } _, err = db.CreateVolume(&db.VolumeRequest{Policy: db.NewPolicy("foo"), Name: "bar", Options: map[string]string{"quux": "derp"}}) c.Assert(err, NotNil) _, err = db.CreateVolume(&db.VolumeRequest{Policy: db.NewPolicy("foo"), Name: ""}) c.Assert(err, NotNil) vol := db.NewVolume("foo", "bar") c.Assert(s.client.Get(vol).(*errored.Error).Contains(errors.NotExists), Equals, true) // _, err = s.client.ListVolumes("quux") // c.Assert(err, NotNil) for _, policyName := range policyNames { for _, volumeName := range volumeNames { policy := db.NewPolicy(policyName) c.Assert(s.client.Get(policy), IsNil) vcfg, err := db.CreateVolume(&db.VolumeRequest{Policy: policy, Name: volumeName, Options: map[string]string{"filesystem": ""}}) c.Assert(err, IsNil) err = s.client.Set(vcfg) c.Assert(err, IsNil, Commentf("%v", err)) err = s.client.Set(vcfg) c.Assert(err.(*errored.Error).Contains(errors.Exists), Equals, true) c.Assert(vcfg.CreateOptions.FileSystem, Equals, "ext4") defer func() { c.Assert(s.client.Delete(vcfg), IsNil) }() c.Assert(vcfg.VolumeName, Equals, volumeName) vcfg2 := db.NewVolume(policyName, volumeName) c.Assert(s.client.Get(vcfg2), IsNil) c.Assert(vcfg, DeepEquals, vcfg2) runtime := db.NewRuntimeOptions(policyName, volumeName) c.Assert(s.client.Get(runtime), IsNil) c.Assert(runtime, DeepEquals, vcfg.RuntimeOptions) vcfg.CreateOptions.Size = "0" c.Assert(s.client.Set(vcfg), NotNil) } volumes, err := s.client.ListPrefix(policyName, &db.Volume{}) c.Assert(err, IsNil) volumeKeys := []string{} for _, volume := range volumes { volumeKeys = append(volumeKeys, volume.(*db.Volume).VolumeName) } sort.Strings(volumeKeys) c.Assert(volumeNames, DeepEquals, volumeKeys) for _, entity := range volumes { vol := entity.(*db.Volume) testPolicies["basic"].RuntimeOptions.SetKey(vol.String()) c.Assert(vol.CreateOptions, DeepEquals, testPolicies["basic"].CreateOptions) c.Assert(vol.RuntimeOptions, DeepEquals, testPolicies["basic"].RuntimeOptions) } } allVols, err := s.client.List(&db.Volume{}) c.Assert(err, IsNil) for _, policy := range policyNames { for _, volume := range volumeNames { found := false for _, ent := range allVols { vol := ent.(*db.Volume) if vol.PolicyName == policy && vol.VolumeName == volume { found = true } c.Assert(vol.CreateOptions, DeepEquals, testPolicies["basic"].CreateOptions) // Cannot use deepequals because of the private members in runtimeoptions now. c.Assert(vol.RuntimeOptions.UseSnapshots, Equals, testPolicies["basic"].RuntimeOptions.UseSnapshots) c.Assert(vol.RuntimeOptions.Snapshot, DeepEquals, testPolicies["basic"].RuntimeOptions.Snapshot) c.Assert(vol.RuntimeOptions.RateLimit, DeepEquals, testPolicies["basic"].RuntimeOptions.RateLimit) } c.Assert(found, Equals, true, Commentf("%s/%s", policy, volume)) } } }