github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/provider/maas/volumes_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package maas 5 6 import ( 7 "github.com/juju/gomaasapi" 8 "github.com/juju/names" 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 12 "github.com/juju/juju/constraints" 13 "github.com/juju/juju/instance" 14 "github.com/juju/juju/storage" 15 "github.com/juju/juju/testing" 16 ) 17 18 type volumeSuite struct { 19 providerSuite 20 } 21 22 var _ = gc.Suite(&volumeSuite{}) 23 24 func (s *volumeSuite) TestBuildMAASVolumeParametersNoVolumes(c *gc.C) { 25 vInfo, err := buildMAASVolumeParameters(nil, constraints.Value{}) 26 c.Assert(err, jc.ErrorIsNil) 27 c.Assert(vInfo, gc.HasLen, 0) 28 } 29 30 func (s *volumeSuite) TestBuildMAASVolumeParametersJustRootDisk(c *gc.C) { 31 var cons constraints.Value 32 rootSize := uint64(20000) 33 cons.RootDisk = &rootSize 34 vInfo, err := buildMAASVolumeParameters(nil, cons) 35 c.Assert(err, jc.ErrorIsNil) 36 c.Assert(vInfo, jc.DeepEquals, []volumeInfo{ 37 {"root", 20, nil}, 38 }) 39 } 40 41 func (s *volumeSuite) TestBuildMAASVolumeParametersNoTags(c *gc.C) { 42 vInfo, err := buildMAASVolumeParameters([]storage.VolumeParams{ 43 {Tag: names.NewVolumeTag("1"), Size: 2000000}, 44 }, constraints.Value{}) 45 c.Assert(err, jc.ErrorIsNil) 46 c.Assert(vInfo, jc.DeepEquals, []volumeInfo{ 47 {"root", 0, nil}, //root disk 48 {"1", 1954, nil}, 49 }) 50 } 51 52 func (s *volumeSuite) TestBuildMAASVolumeParametersWithRootDisk(c *gc.C) { 53 var cons constraints.Value 54 rootSize := uint64(20000) 55 cons.RootDisk = &rootSize 56 vInfo, err := buildMAASVolumeParameters([]storage.VolumeParams{ 57 {Tag: names.NewVolumeTag("1"), Size: 2000000}, 58 }, cons) 59 c.Assert(err, jc.ErrorIsNil) 60 c.Assert(vInfo, jc.DeepEquals, []volumeInfo{ 61 {"root", 20, nil}, //root disk 62 {"1", 1954, nil}, 63 }) 64 } 65 66 func (s *volumeSuite) TestBuildMAASVolumeParametersWithTags(c *gc.C) { 67 vInfo, err := buildMAASVolumeParameters([]storage.VolumeParams{ 68 {Tag: names.NewVolumeTag("1"), Size: 2000000, Attributes: map[string]interface{}{"tags": "tag1,tag2"}}, 69 }, constraints.Value{}) 70 c.Assert(err, jc.ErrorIsNil) 71 c.Assert(vInfo, jc.DeepEquals, []volumeInfo{ 72 {"root", 0, nil}, //root disk 73 {"1", 1954, []string{"tag1", "tag2"}}, 74 }) 75 } 76 77 func (s *volumeSuite) TestInstanceVolumesMAAS2(c *gc.C) { 78 instance := maas2Instance{ 79 machine: &fakeMachine{}, 80 constraintMatches: gomaasapi.ConstraintMatches{ 81 Storage: map[string]gomaasapi.BlockDevice{ 82 "root": &fakeBlockDevice{name: "sda", path: "/dev/disk/by-dname/sda", size: 250059350016}, 83 "1": &fakeBlockDevice{name: "sdb", path: "/dev/disk/by-dname/sdb", size: 500059350016}, 84 "2": &fakeBlockDevice{name: "sdc", path: "/dev/disk/by-dname/sdc", size: 250362438230}, 85 "3": &fakeBlockDevice{name: "sdd", path: "/dev/disk/by-dname/sdd", size: 250362438230}, 86 "4": &fakeBlockDevice{name: "sde", path: "/dev/disk/by-dname/sde", size: 250362438230}, 87 }, 88 }, 89 } 90 mTag := names.NewMachineTag("1") 91 volumes, attachments, err := instance.volumes(mTag, []names.VolumeTag{ 92 names.NewVolumeTag("1"), 93 names.NewVolumeTag("2"), 94 }) 95 c.Assert(err, jc.ErrorIsNil) 96 // Expect 2 volumes - root volume is ignored. 97 c.Assert(volumes, gc.HasLen, 2) 98 c.Assert(attachments, gc.HasLen, 2) 99 c.Check(volumes, jc.SameContents, []storage.Volume{{ 100 names.NewVolumeTag("1"), 101 storage.VolumeInfo{ 102 VolumeId: "volume-1", 103 Size: 476893, 104 Persistent: false, 105 }, 106 }, { 107 names.NewVolumeTag("2"), 108 storage.VolumeInfo{ 109 VolumeId: "volume-2", 110 Size: 238764, 111 Persistent: false, 112 }, 113 }}) 114 c.Assert(attachments, jc.SameContents, []storage.VolumeAttachment{ 115 { 116 names.NewVolumeTag("1"), 117 mTag, 118 storage.VolumeAttachmentInfo{ 119 DeviceLink: "/dev/disk/by-dname/sdb", 120 ReadOnly: false, 121 }, 122 }, 123 { 124 names.NewVolumeTag("2"), 125 mTag, 126 storage.VolumeAttachmentInfo{ 127 DeviceLink: "/dev/disk/by-dname/sdc", 128 ReadOnly: false, 129 }, 130 }, 131 }) 132 } 133 134 func (s *volumeSuite) TestInstanceVolumes(c *gc.C) { 135 obj := s.testMAASObject.TestServer.NewNode(validVolumeJson) 136 statusGetter := func(instance.Id) (string, string) { 137 return "unknown", "FAKE" 138 } 139 140 instance := maas1Instance{&obj, nil, statusGetter} 141 mTag := names.NewMachineTag("1") 142 volumes, attachments, err := instance.volumes(mTag, []names.VolumeTag{ 143 names.NewVolumeTag("1"), 144 names.NewVolumeTag("2"), 145 }) 146 c.Assert(err, jc.ErrorIsNil) 147 // Expect 2 volumes - root volume is ignored. 148 c.Assert(volumes, gc.HasLen, 2) 149 c.Assert(attachments, gc.HasLen, 2) 150 c.Check(volumes, jc.DeepEquals, []storage.Volume{ 151 { 152 // This volume has no id_path. 153 names.NewVolumeTag("1"), 154 storage.VolumeInfo{ 155 HardwareId: "", 156 VolumeId: "volume-1", 157 Size: 476893, 158 Persistent: false, 159 }, 160 }, 161 { 162 names.NewVolumeTag("2"), 163 storage.VolumeInfo{ 164 HardwareId: "id_for_sdc", 165 VolumeId: "volume-2", 166 Size: 238764, 167 Persistent: false, 168 }, 169 }, 170 }) 171 c.Assert(attachments, jc.DeepEquals, []storage.VolumeAttachment{ 172 { 173 names.NewVolumeTag("1"), 174 mTag, 175 storage.VolumeAttachmentInfo{ 176 DeviceName: "sdb", 177 ReadOnly: false, 178 }, 179 }, 180 // Device name not set because there's a hardware id in the volume. 181 { 182 names.NewVolumeTag("2"), 183 mTag, 184 storage.VolumeAttachmentInfo{ 185 DeviceName: "", 186 ReadOnly: false, 187 }, 188 }, 189 }) 190 } 191 192 func (s *volumeSuite) TestInstanceVolumesOldMass(c *gc.C) { 193 obj := s.testMAASObject.TestServer.NewNode(`{"system_id": "node0"}`) 194 statusGetter := func(instance.Id) (string, string) { 195 // status, substatus or status info. 196 return "provisioning", "substatus" 197 } 198 199 instance := maas1Instance{&obj, nil, statusGetter} 200 volumes, attachments, err := instance.volumes(names.NewMachineTag("1"), []names.VolumeTag{ 201 names.NewVolumeTag("1"), 202 names.NewVolumeTag("2"), 203 }) 204 c.Assert(err, jc.ErrorIsNil) 205 c.Assert(volumes, gc.HasLen, 0) 206 c.Assert(attachments, gc.HasLen, 0) 207 } 208 209 var validVolumeJson = ` 210 { 211 "system_id": "node0", 212 "physicalblockdevice_set": [ 213 { 214 "name": "sda", 215 "tags": [ 216 "ssd", 217 "sata" 218 ], 219 "id": 1, 220 "id_path": "/dev/disk/by-id/id_for_sda", 221 "path": "/dev/sda", 222 "model": "Samsung_SSD_850_EVO_250GB", 223 "block_size": 4096, 224 "serial": "S21NNSAFC38075L", 225 "size": 250059350016 226 }, 227 { 228 "name": "sdb", 229 "tags": [ 230 "ssd", 231 "sata" 232 ], 233 "id": 2, 234 "path": "/dev/sdb", 235 "model": "Samsung_SSD_850_EVO_500GB", 236 "block_size": 4096, 237 "serial": "S21NNSAFC38076L", 238 "size": 500059350016 239 }, 240 { 241 "name": "sdb", 242 "tags": [ 243 "ssd", 244 "sata" 245 ], 246 "id": 3, 247 "id_path": "/dev/disk/by-id/id_for_sdc", 248 "path": "/dev/sdc", 249 "model": "Samsung_SSD_850_EVO_250GB", 250 "block_size": 4096, 251 "serial": "S21NNSAFC38999L", 252 "size": 250362438230 253 }, 254 { 255 "name": "sdd", 256 "tags": [ 257 "ssd", 258 "sata" 259 ], 260 "id": 4, 261 "id_path": "/dev/disk/by-id/id_for_sdd", 262 "path": "/dev/sdd", 263 "model": "Samsung_SSD_850_EVO_250GB", 264 "block_size": 4096, 265 "serial": "S21NNSAFC386666L", 266 "size": 250362438230 267 }, 268 { 269 "name": "sde", 270 "tags": [ 271 "ssd", 272 "sata" 273 ], 274 "id": 666, 275 "id_path": "/dev/disk/by-id/id_for_sde", 276 "path": "/dev/sde", 277 "model": "Samsung_SSD_850_EVO_250GB", 278 "block_size": 4096, 279 "serial": "S21NNSAFC388888L", 280 "size": 250362438230 281 } 282 ], 283 "constraint_map": { 284 "1": "root", 285 "2": "1", 286 "3": "2", 287 "4": "3" 288 } 289 } 290 `[1:] 291 292 type storageProviderSuite struct { 293 testing.BaseSuite 294 } 295 296 var _ = gc.Suite(&storageProviderSuite{}) 297 298 func (*storageProviderSuite) TestValidateConfigTags(c *gc.C) { 299 p := maasStorageProvider{} 300 validate := func(tags interface{}) { 301 cfg, err := storage.NewConfig("foo", maasStorageProviderType, map[string]interface{}{ 302 "tags": tags, 303 }) 304 c.Assert(err, jc.ErrorIsNil) 305 err = p.ValidateConfig(cfg) 306 c.Assert(err, jc.ErrorIsNil) 307 } 308 validate("singular") 309 validate("mul,ti,ple") 310 validate(" leading, spaces") 311 validate("trailing ,spaces ") 312 validate(" and,everything, in , between ") 313 } 314 315 func (*storageProviderSuite) TestValidateConfigInvalidConfig(c *gc.C) { 316 p := maasStorageProvider{} 317 cfg, err := storage.NewConfig("foo", maasStorageProviderType, map[string]interface{}{ 318 "tags": "white space", 319 }) 320 c.Assert(err, jc.ErrorIsNil) 321 err = p.ValidateConfig(cfg) 322 c.Assert(err, gc.ErrorMatches, `tags may not contain whitespace: "white space"`) 323 } 324 325 func (*storageProviderSuite) TestValidateConfigUnknownAttribute(c *gc.C) { 326 p := maasStorageProvider{} 327 cfg, err := storage.NewConfig("foo", maasStorageProviderType, map[string]interface{}{ 328 "unknown": "config", 329 }) 330 c.Assert(err, jc.ErrorIsNil) 331 err = p.ValidateConfig(cfg) 332 c.Assert(err, jc.ErrorIsNil) // unknown attributes are ignored 333 } 334 335 func (s *storageProviderSuite) TestSupports(c *gc.C) { 336 p := maasStorageProvider{} 337 c.Assert(p.Supports(storage.StorageKindBlock), jc.IsTrue) 338 c.Assert(p.Supports(storage.StorageKindFilesystem), jc.IsFalse) 339 } 340 341 func (s *storageProviderSuite) TestScope(c *gc.C) { 342 p := maasStorageProvider{} 343 c.Assert(p.Scope(), gc.Equals, storage.ScopeEnviron) 344 }