github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/uniter/runner/context/unitStorage_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package context_test 5 6 import ( 7 jc "github.com/juju/testing/checkers" 8 "github.com/juju/utils" 9 "github.com/juju/utils/set" 10 gc "gopkg.in/check.v1" 11 "gopkg.in/juju/names.v2" 12 13 "github.com/juju/juju/apiserver/params" 14 "github.com/juju/juju/provider/dummy" 15 "github.com/juju/juju/state" 16 "github.com/juju/juju/storage/poolmanager" 17 "github.com/juju/juju/storage/provider" 18 "github.com/juju/juju/worker/uniter/runner/context" 19 ) 20 21 type unitStorageSuite struct { 22 HookContextSuite 23 expectedStorageNames set.Strings 24 charmName string 25 initCons map[string]state.StorageConstraints 26 ch *state.Charm 27 initialStorageInstancesCount int 28 } 29 30 var _ = gc.Suite(&unitStorageSuite{}) 31 32 const ( 33 testPool = "block" 34 testPersistentPool = "block-persistent" 35 ) 36 37 func (s *unitStorageSuite) SetUpTest(c *gc.C) { 38 s.HookContextSuite.SetUpTest(c) 39 setupTestStorageSupport(c, s.State) 40 } 41 42 func (s *unitStorageSuite) TestAddUnitStorage(c *gc.C) { 43 s.createStorageBlockUnit(c) 44 count := uint64(1) 45 s.assertUnitStorageAdded(c, 46 map[string]params.StorageConstraints{ 47 "allecto": params.StorageConstraints{Count: &count}}) 48 } 49 50 func (s *unitStorageSuite) TestAddUnitStorageIgnoresBlocks(c *gc.C) { 51 s.createStorageBlockUnit(c) 52 count := uint64(1) 53 s.BlockDestroyModel(c, "TestAddUnitStorageIgnoresBlocks") 54 s.BlockRemoveObject(c, "TestAddUnitStorageIgnoresBlocks") 55 s.BlockAllChanges(c, "TestAddUnitStorageIgnoresBlocks") 56 s.assertUnitStorageAdded(c, 57 map[string]params.StorageConstraints{ 58 "allecto": params.StorageConstraints{Count: &count}}) 59 } 60 61 func (s *unitStorageSuite) TestAddUnitStorageZeroCount(c *gc.C) { 62 s.createStorageBlockUnit(c) 63 cons := map[string]params.StorageConstraints{ 64 "allecto": params.StorageConstraints{}} 65 66 ctx := s.addUnitStorage(c, cons) 67 68 // Flush the context with a success. 69 err := ctx.Flush("success", nil) 70 c.Assert(err, gc.ErrorMatches, `.*count must be specified.*`) 71 72 // Make sure no storage instances was added 73 after, err := s.State.AllStorageInstances() 74 c.Assert(err, jc.ErrorIsNil) 75 c.Assert(len(after)-s.initialStorageInstancesCount, gc.Equals, 0) 76 s.assertExistingStorage(c, after) 77 } 78 79 func (s *unitStorageSuite) TestAddUnitStorageWithSize(c *gc.C) { 80 s.createStorageBlockUnit(c) 81 size := uint64(1) 82 cons := map[string]params.StorageConstraints{ 83 "allecto": params.StorageConstraints{Size: &size}} 84 85 ctx := s.addUnitStorage(c, cons) 86 87 // Flush the context with a success. 88 err := ctx.Flush("success", nil) 89 c.Assert(err, gc.ErrorMatches, `.*only count can be specified.*`) 90 91 // Make sure no storage instances was added 92 after, err := s.State.AllStorageInstances() 93 c.Assert(err, jc.ErrorIsNil) 94 c.Assert(len(after)-s.initialStorageInstancesCount, gc.Equals, 0) 95 s.assertExistingStorage(c, after) 96 } 97 98 func (s *unitStorageSuite) TestAddUnitStorageWithPool(c *gc.C) { 99 s.createStorageBlockUnit(c) 100 cons := map[string]params.StorageConstraints{ 101 "allecto": params.StorageConstraints{Pool: "loop"}} 102 103 ctx := s.addUnitStorage(c, cons) 104 105 // Flush the context with a success. 106 err := ctx.Flush("success", nil) 107 c.Assert(err, gc.ErrorMatches, `.*only count can be specified.*`) 108 109 // Make sure no storage instances was added 110 after, err := s.State.AllStorageInstances() 111 c.Assert(err, jc.ErrorIsNil) 112 c.Assert(len(after)-s.initialStorageInstancesCount, gc.Equals, 0) 113 s.assertExistingStorage(c, after) 114 } 115 116 func (s *unitStorageSuite) TestAddUnitStorageAccumulated(c *gc.C) { 117 s.createStorageBlock2Unit(c) 118 count := uint64(1) 119 s.assertUnitStorageAdded(c, 120 map[string]params.StorageConstraints{ 121 "multi2up": params.StorageConstraints{Count: &count}}, 122 map[string]params.StorageConstraints{ 123 "multi1to10": params.StorageConstraints{Count: &count}}) 124 } 125 126 func (s *unitStorageSuite) TestAddUnitStorageAccumulatedSame(c *gc.C) { 127 s.createStorageBlock2Unit(c) 128 count := uint64(1) 129 s.assertUnitStorageAdded(c, 130 map[string]params.StorageConstraints{ 131 "multi2up": params.StorageConstraints{Count: &count}}, 132 map[string]params.StorageConstraints{ 133 "multi2up": params.StorageConstraints{Count: &count}}) 134 } 135 136 func setupTestStorageSupport(c *gc.C, s *state.State) { 137 stsetts := state.NewStateSettings(s) 138 poolManager := poolmanager.New(stsetts, dummy.StorageProviders()) 139 _, err := poolManager.Create(testPool, provider.LoopProviderType, map[string]interface{}{"it": "works"}) 140 c.Assert(err, jc.ErrorIsNil) 141 _, err = poolManager.Create(testPersistentPool, "environscoped", map[string]interface{}{"persistent": true}) 142 c.Assert(err, jc.ErrorIsNil) 143 } 144 145 func (s *unitStorageSuite) createStorageEnabledUnit(c *gc.C) { 146 s.ch = s.AddTestingCharm(c, s.charmName) 147 s.service = s.AddTestingServiceWithStorage(c, s.charmName, s.ch, s.initCons) 148 s.unit = s.AddUnit(c, s.service) 149 150 s.assertStorageCreated(c) 151 s.createHookSupport(c) 152 } 153 154 func (s *unitStorageSuite) createStorageBlockUnit(c *gc.C) { 155 s.charmName = "storage-block" 156 s.initCons = map[string]state.StorageConstraints{ 157 "data": makeStorageCons("block", 1024, 1), 158 } 159 s.createStorageEnabledUnit(c) 160 s.assertStorageCreated(c) 161 s.createHookSupport(c) 162 } 163 164 func (s *unitStorageSuite) createStorageBlock2Unit(c *gc.C) { 165 s.charmName = "storage-block2" 166 s.initCons = map[string]state.StorageConstraints{ 167 "multi1to10": makeStorageCons("loop", 0, 3), 168 } 169 s.createStorageEnabledUnit(c) 170 s.assertStorageCreated(c) 171 s.createHookSupport(c) 172 } 173 174 func (s *unitStorageSuite) assertStorageCreated(c *gc.C) { 175 all, err := s.State.AllStorageInstances() 176 c.Assert(err, jc.ErrorIsNil) 177 s.initialStorageInstancesCount = len(all) 178 s.expectedStorageNames = set.NewStrings() 179 for _, one := range all { 180 s.expectedStorageNames.Add(one.StorageName()) 181 } 182 } 183 184 func (s *unitStorageSuite) createHookSupport(c *gc.C) { 185 password, err := utils.RandomPassword() 186 err = s.unit.SetPassword(password) 187 c.Assert(err, jc.ErrorIsNil) 188 s.st = s.OpenAPIAs(c, s.unit.Tag(), password) 189 s.uniter, err = s.st.Uniter() 190 c.Assert(err, jc.ErrorIsNil) 191 c.Assert(s.uniter, gc.NotNil) 192 s.apiUnit, err = s.uniter.Unit(s.unit.Tag().(names.UnitTag)) 193 c.Assert(err, jc.ErrorIsNil) 194 195 err = s.unit.SetCharmURL(s.ch.URL()) 196 c.Assert(err, jc.ErrorIsNil) 197 } 198 199 func makeStorageCons(pool string, size, count uint64) state.StorageConstraints { 200 return state.StorageConstraints{Pool: pool, Size: size, Count: count} 201 } 202 203 func (s *unitStorageSuite) addUnitStorage(c *gc.C, cons ...map[string]params.StorageConstraints) *context.HookContext { 204 // Get the context. 205 ctx := s.getHookContext(c, s.State.ModelUUID(), -1, "", noProxies) 206 c.Assert(ctx.UnitName(), gc.Equals, s.unit.Name()) 207 208 for _, one := range cons { 209 for storage, _ := range one { 210 s.expectedStorageNames.Add(storage) 211 } 212 ctx.AddUnitStorage(one) 213 } 214 return ctx 215 } 216 217 func (s *unitStorageSuite) assertUnitStorageAdded(c *gc.C, cons ...map[string]params.StorageConstraints) { 218 ctx := s.addUnitStorage(c, cons...) 219 220 // Flush the context with a success. 221 err := ctx.Flush("success", nil) 222 c.Assert(err, jc.ErrorIsNil) 223 224 after, err := s.State.AllStorageInstances() 225 c.Assert(err, jc.ErrorIsNil) 226 c.Assert(len(after)-s.initialStorageInstancesCount, gc.Equals, len(cons)) 227 s.assertExistingStorage(c, after) 228 } 229 230 func (s *unitStorageSuite) assertExistingStorage(c *gc.C, all []state.StorageInstance) { 231 for _, one := range all { 232 c.Assert(s.expectedStorageNames.Contains(one.StorageName()), jc.IsTrue) 233 } 234 }