github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/provider/openstack/export_test.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package openstack 5 6 import ( 7 "bytes" 8 "fmt" 9 "strings" 10 "text/template" 11 12 "gopkg.in/goose.v1/errors" 13 "gopkg.in/goose.v1/identity" 14 "gopkg.in/goose.v1/nova" 15 "gopkg.in/goose.v1/swift" 16 17 "github.com/juju/juju/constraints" 18 "github.com/juju/juju/environs" 19 "github.com/juju/juju/environs/imagemetadata" 20 "github.com/juju/juju/environs/instances" 21 "github.com/juju/juju/environs/simplestreams" 22 envstorage "github.com/juju/juju/environs/storage" 23 envtesting "github.com/juju/juju/environs/testing" 24 "github.com/juju/juju/instance" 25 "github.com/juju/juju/network" 26 "github.com/juju/juju/storage" 27 "github.com/juju/juju/testing" 28 ) 29 30 var ( 31 ShortAttempt = &shortAttempt 32 StorageAttempt = &storageAttempt 33 CinderAttempt = &cinderAttempt 34 ) 35 36 // MetadataStorage returns a Storage instance which is used to store simplestreams metadata for tests. 37 func MetadataStorage(e environs.Environ) envstorage.Storage { 38 env := e.(*Environ) 39 ecfg := env.ecfg() 40 container := "juju-dist-test" 41 client, err := authClient(env.cloud, ecfg) 42 if err != nil { 43 panic(fmt.Errorf("cannot create %s container: %v", container, err)) 44 } 45 metadataStorage := &openstackstorage{ 46 containerName: container, 47 swift: swift.New(client), 48 } 49 50 // Ensure the container exists. 51 err = metadataStorage.makeContainer(container, swift.PublicRead) 52 if err != nil { 53 panic(fmt.Errorf("cannot create %s container: %v", container, err)) 54 } 55 return metadataStorage 56 } 57 58 func InstanceAddress(publicIP string, addresses map[string][]nova.IPAddress) string { 59 addr, _ := network.SelectPublicAddress(convertNovaAddresses(publicIP, addresses)) 60 return addr.Value 61 } 62 63 func InstanceServerDetail(inst instance.Instance) *nova.ServerDetail { 64 return inst.(*openstackInstance).serverDetail 65 } 66 67 func InstanceFloatingIP(inst instance.Instance) *nova.FloatingIP { 68 return inst.(*openstackInstance).floatingIP 69 } 70 71 var ( 72 NovaListAvailabilityZones = &novaListAvailabilityZones 73 AvailabilityZoneAllocations = &availabilityZoneAllocations 74 NewOpenstackStorage = &newOpenstackStorage 75 ) 76 77 func NewCinderVolumeSource(s OpenstackStorage) storage.VolumeSource { 78 const envName = "testenv" 79 modelUUID := testing.ModelTag.Id() 80 return &cinderVolumeSource{s, envName, modelUUID} 81 } 82 83 // Include images for arches currently supported. i386 is no longer 84 // supported, so it can be excluded. 85 var indexData = ` 86 { 87 "index": { 88 "com.ubuntu.cloud:released:openstack": { 89 "updated": "Wed, 01 May 2013 13:31:26 +0000", 90 "clouds": [ 91 { 92 "region": "{{.Region}}", 93 "endpoint": "{{.URL}}" 94 } 95 ], 96 "cloudname": "test", 97 "datatype": "image-ids", 98 "format": "products:1.0", 99 "products": [ 100 "com.ubuntu.cloud:server:16.04:s390x", 101 "com.ubuntu.cloud:server:16.04:amd64", 102 "com.ubuntu.cloud:server:16.04:arm64", 103 "com.ubuntu.cloud:server:16.04:ppc64el", 104 "com.ubuntu.cloud:server:14.04:s390x", 105 "com.ubuntu.cloud:server:14.04:amd64", 106 "com.ubuntu.cloud:server:14.04:arm64", 107 "com.ubuntu.cloud:server:14.04:ppc64el", 108 "com.ubuntu.cloud:server:12.10:amd64", 109 "com.ubuntu.cloud:server:13.04:amd64" 110 ], 111 "path": "image-metadata/products.json" 112 } 113 }, 114 "updated": "Wed, 01 May 2013 13:31:26 +0000", 115 "format": "index:1.0" 116 } 117 ` 118 119 var imagesData = ` 120 { 121 "content_id": "com.ubuntu.cloud:released:openstack", 122 "products": { 123 "com.ubuntu.cloud:server:16.04:amd64": { 124 "release": "trusty", 125 "version": "16.04", 126 "arch": "amd64", 127 "versions": { 128 "20121218": { 129 "items": { 130 "inst1": { 131 "root_store": "ebs", 132 "virt": "pv", 133 "region": "some-region", 134 "id": "1" 135 }, 136 "inst2": { 137 "root_store": "ebs", 138 "virt": "pv", 139 "region": "another-region", 140 "id": "2" 141 } 142 }, 143 "pubname": "ubuntu-trusty-16.04-amd64-server-20121218", 144 "label": "release" 145 }, 146 "20121111": { 147 "items": { 148 "inst3": { 149 "root_store": "ebs", 150 "virt": "pv", 151 "region": "some-region", 152 "id": "3" 153 } 154 }, 155 "pubname": "ubuntu-trusty-16.04-amd64-server-20121111", 156 "label": "release" 157 } 158 } 159 }, 160 "com.ubuntu.cloud:server:16.04:arm64": { 161 "release": "xenial", 162 "version": "16.04", 163 "arch": "arm64", 164 "versions": { 165 "20121111": { 166 "items": { 167 "inst1604arm64": { 168 "root_store": "ebs", 169 "virt": "pv", 170 "region": "some-region", 171 "id": "id-1604arm64" 172 } 173 }, 174 "pubname": "ubuntu-xenial-16.04-arm64-server-20121111", 175 "label": "release" 176 } 177 } 178 }, 179 "com.ubuntu.cloud:server:16.04:ppc64el": { 180 "release": "xenial", 181 "version": "16.04", 182 "arch": "ppc64el", 183 "versions": { 184 "20121111": { 185 "items": { 186 "inst1604ppc64el": { 187 "root_store": "ebs", 188 "virt": "pv", 189 "region": "some-region", 190 "id": "id-1604ppc64el" 191 } 192 }, 193 "pubname": "ubuntu-xenial-16.04-ppc64el-server-20121111", 194 "label": "release" 195 } 196 } 197 }, 198 "com.ubuntu.cloud:server:14.04:amd64": { 199 "release": "trusty", 200 "version": "14.04", 201 "arch": "amd64", 202 "versions": { 203 "20121218": { 204 "items": { 205 "inst1": { 206 "root_store": "ebs", 207 "virt": "pv", 208 "region": "some-region", 209 "id": "1" 210 }, 211 "inst2": { 212 "root_store": "ebs", 213 "virt": "pv", 214 "region": "another-region", 215 "id": "2" 216 } 217 }, 218 "pubname": "ubuntu-trusty-14.04-amd64-server-20121218", 219 "label": "release" 220 }, 221 "20121111": { 222 "items": { 223 "inst3": { 224 "root_store": "ebs", 225 "virt": "pv", 226 "region": "some-region", 227 "id": "3" 228 } 229 }, 230 "pubname": "ubuntu-trusty-14.04-amd64-server-20121111", 231 "label": "release" 232 } 233 } 234 }, 235 "com.ubuntu.cloud:server:14.04:arm64": { 236 "release": "trusty", 237 "version": "14.04", 238 "arch": "arm64", 239 "versions": { 240 "20121111": { 241 "items": { 242 "inst33": { 243 "root_store": "ebs", 244 "virt": "pv", 245 "region": "some-region", 246 "id": "33" 247 } 248 }, 249 "pubname": "ubuntu-trusty-14.04-arm64-server-20121111", 250 "label": "release" 251 } 252 } 253 }, 254 "com.ubuntu.cloud:server:14.04:ppc64el": { 255 "release": "trusty", 256 "version": "14.04", 257 "arch": "ppc64el", 258 "versions": { 259 "20121111": { 260 "items": { 261 "inst33": { 262 "root_store": "ebs", 263 "virt": "pv", 264 "region": "some-region", 265 "id": "33" 266 } 267 }, 268 "pubname": "ubuntu-trusty-14.04-ppc64el-server-20121111", 269 "label": "release" 270 } 271 } 272 }, 273 "com.ubuntu.cloud:server:12.10:amd64": { 274 "release": "quantal", 275 "version": "12.10", 276 "arch": "amd64", 277 "versions": { 278 "20121218": { 279 "items": { 280 "inst3": { 281 "root_store": "ebs", 282 "virt": "pv", 283 "region": "region-1", 284 "id": "id-1" 285 }, 286 "inst4": { 287 "root_store": "ebs", 288 "virt": "pv", 289 "region": "region-2", 290 "id": "id-2" 291 } 292 }, 293 "pubname": "ubuntu-quantal-12.14-amd64-server-20121218", 294 "label": "release" 295 } 296 } 297 }, 298 "com.ubuntu.cloud:server:13.04:amd64": { 299 "release": "raring", 300 "version": "13.04", 301 "arch": "amd64", 302 "versions": { 303 "20121218": { 304 "items": { 305 "inst5": { 306 "root_store": "ebs", 307 "virt": "pv", 308 "region": "some-region", 309 "id": "id-y" 310 }, 311 "inst6": { 312 "root_store": "ebs", 313 "virt": "pv", 314 "region": "another-region", 315 "id": "id-z" 316 } 317 }, 318 "pubname": "ubuntu-raring-13.04-amd64-server-20121218", 319 "label": "release" 320 } 321 } 322 }, 323 "com.ubuntu.cloud:server:14.04:s390x": { 324 "release": "trusty", 325 "version": "14.04", 326 "arch": "s390x", 327 "versions": { 328 "20121218": { 329 "items": { 330 "inst5": { 331 "root_store": "ebs", 332 "virt": "pv", 333 "region": "some-region", 334 "id": "id-y" 335 }, 336 "inst6": { 337 "root_store": "ebs", 338 "virt": "pv", 339 "region": "another-region", 340 "id": "id-z" 341 } 342 }, 343 "pubname": "ubuntu-trusty-14.04-s390x-server-20121218", 344 "label": "release" 345 } 346 } 347 }, 348 "com.ubuntu.cloud:server:16.04:s390x": { 349 "release": "xenial", 350 "version": "16.04", 351 "arch": "s390x", 352 "versions": { 353 "20121218": { 354 "items": { 355 "inst5": { 356 "root_store": "ebs", 357 "virt": "pv", 358 "region": "some-region", 359 "id": "id-y" 360 }, 361 "inst6": { 362 "root_store": "ebs", 363 "virt": "pv", 364 "region": "another-region", 365 "id": "id-z" 366 } 367 }, 368 "pubname": "ubuntu-xenial-16.04-s390x-server-20121218", 369 "label": "release" 370 } 371 } 372 } 373 }, 374 "format": "products:1.0" 375 } 376 ` 377 378 const productMetadatafile = "image-metadata/products.json" 379 380 func UseTestImageData(stor envstorage.Storage, cred *identity.Credentials) { 381 // Put some image metadata files into the public storage. 382 t := template.Must(template.New("").Parse(indexData)) 383 var metadata bytes.Buffer 384 if err := t.Execute(&metadata, cred); err != nil { 385 panic(fmt.Errorf("cannot generate index metdata: %v", err)) 386 } 387 data := metadata.Bytes() 388 stor.Put(simplestreams.UnsignedIndex("v1", 1), bytes.NewReader(data), int64(len(data))) 389 stor.Put( 390 productMetadatafile, strings.NewReader(imagesData), int64(len(imagesData))) 391 392 envtesting.SignTestTools(stor) 393 } 394 395 func RemoveTestImageData(stor envstorage.Storage) { 396 stor.RemoveAll() 397 } 398 399 // DiscardSecurityGroup cleans up a security group, it is not an error to 400 // delete something that doesn't exist. 401 func DiscardSecurityGroup(e environs.Environ, name string) error { 402 env := e.(*Environ) 403 novaClient := env.nova() 404 group, err := novaClient.SecurityGroupByName(name) 405 if err != nil { 406 if errors.IsNotFound(err) { 407 // Group already deleted, done 408 return nil 409 } 410 } 411 err = novaClient.DeleteSecurityGroup(group.Id) 412 if err != nil { 413 return err 414 } 415 return nil 416 } 417 418 func FindInstanceSpec( 419 e environs.Environ, 420 series, arch, cons string, 421 imageMetadata []*imagemetadata.ImageMetadata, 422 ) (spec *instances.InstanceSpec, err error) { 423 env := e.(*Environ) 424 return findInstanceSpec(env, &instances.InstanceConstraint{ 425 Series: series, 426 Arches: []string{arch}, 427 Region: env.cloud.Region, 428 Constraints: constraints.MustParse(cons), 429 }, imageMetadata) 430 } 431 432 func GetSwiftURL(e environs.Environ) (string, error) { 433 return e.(*Environ).client.MakeServiceURL("object-store", nil) 434 } 435 436 func SetUseFloatingIP(e environs.Environ, val bool) { 437 env := e.(*Environ) 438 env.ecfg().attrs["use-floating-ip"] = val 439 } 440 441 func SetUpGlobalGroup(e environs.Environ, name string, apiPort int) (nova.SecurityGroup, error) { 442 return e.(*Environ).firewaller.(*defaultFirewaller).setUpGlobalGroup(name, apiPort) 443 } 444 445 func EnsureGroup(e environs.Environ, name string, rules []nova.RuleInfo) (nova.SecurityGroup, error) { 446 return e.(*Environ).firewaller.(*defaultFirewaller).ensureGroup(name, rules) 447 } 448 449 // ImageMetadataStorage returns a Storage object pointing where the goose 450 // infrastructure sets up its keystone entry for image metadata 451 func ImageMetadataStorage(e environs.Environ) envstorage.Storage { 452 env := e.(*Environ) 453 return &openstackstorage{ 454 containerName: "imagemetadata", 455 swift: swift.New(env.client), 456 } 457 } 458 459 // CreateCustomStorage creates a swift container and returns the Storage object 460 // so you can put data into it. 461 func CreateCustomStorage(e environs.Environ, containerName string) envstorage.Storage { 462 env := e.(*Environ) 463 swiftClient := swift.New(env.client) 464 if err := swiftClient.CreateContainer(containerName, swift.PublicRead); err != nil { 465 panic(err) 466 } 467 return &openstackstorage{ 468 containerName: containerName, 469 swift: swiftClient, 470 } 471 } 472 473 // BlankContainerStorage creates a Storage object with blank container name. 474 func BlankContainerStorage() envstorage.Storage { 475 return &openstackstorage{} 476 } 477 478 func GetNovaClient(e environs.Environ) *nova.Client { 479 return e.(*Environ).nova() 480 } 481 482 // ResolveNetwork exposes environ helper function resolveNetwork for testing 483 func ResolveNetwork(e environs.Environ, networkName string) (string, error) { 484 return e.(*Environ).resolveNetwork(networkName) 485 } 486 487 var PortsToRuleInfo = portsToRuleInfo 488 var RuleMatchesPortRange = ruleMatchesPortRange 489 490 var MakeServiceURL = &makeServiceURL 491 var ProviderInstance = providerInstance 492 493 var GetVolumeEndpointURL = getVolumeEndpointURL