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