github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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:14.04:s390x", 111 "com.ubuntu.cloud:server:14.04:amd64", 112 "com.ubuntu.cloud:server:14.04:arm64", 113 "com.ubuntu.cloud:server:14.04:ppc64el", 114 "com.ubuntu.cloud:server:12.10:amd64", 115 "com.ubuntu.cloud:server:13.04:amd64" 116 ], 117 "path": "image-metadata/products.json" 118 } 119 }, 120 "updated": "Wed, 01 May 2013 13:31:26 +0000", 121 "format": "index:1.0" 122 } 123 ` 124 125 var imagesData = ` 126 { 127 "content_id": "com.ubuntu.cloud:released:openstack", 128 "products": { 129 "com.ubuntu.cloud:server:14.04:amd64": { 130 "release": "trusty", 131 "version": "14.04", 132 "arch": "amd64", 133 "versions": { 134 "20121218": { 135 "items": { 136 "inst1": { 137 "root_store": "ebs", 138 "virt": "pv", 139 "region": "some-region", 140 "id": "1" 141 }, 142 "inst2": { 143 "root_store": "ebs", 144 "virt": "pv", 145 "region": "another-region", 146 "id": "2" 147 } 148 }, 149 "pubname": "ubuntu-trusty-14.04-amd64-server-20121218", 150 "label": "release" 151 }, 152 "20121111": { 153 "items": { 154 "inst3": { 155 "root_store": "ebs", 156 "virt": "pv", 157 "region": "some-region", 158 "id": "3" 159 } 160 }, 161 "pubname": "ubuntu-trusty-14.04-amd64-server-20121111", 162 "label": "release" 163 } 164 } 165 }, 166 "com.ubuntu.cloud:server:14.04:arm64": { 167 "release": "trusty", 168 "version": "14.04", 169 "arch": "arm64", 170 "versions": { 171 "20121111": { 172 "items": { 173 "inst33": { 174 "root_store": "ebs", 175 "virt": "pv", 176 "region": "some-region", 177 "id": "33" 178 } 179 }, 180 "pubname": "ubuntu-trusty-14.04-arm64-server-20121111", 181 "label": "release" 182 } 183 } 184 }, 185 "com.ubuntu.cloud:server:14.04:ppc64el": { 186 "release": "trusty", 187 "version": "14.04", 188 "arch": "ppc64el", 189 "versions": { 190 "20121111": { 191 "items": { 192 "inst33": { 193 "root_store": "ebs", 194 "virt": "pv", 195 "region": "some-region", 196 "id": "33" 197 } 198 }, 199 "pubname": "ubuntu-trusty-14.04-ppc64el-server-20121111", 200 "label": "release" 201 } 202 } 203 }, 204 "com.ubuntu.cloud:server:12.10:amd64": { 205 "release": "quantal", 206 "version": "12.10", 207 "arch": "amd64", 208 "versions": { 209 "20121218": { 210 "items": { 211 "inst3": { 212 "root_store": "ebs", 213 "virt": "pv", 214 "region": "region-1", 215 "id": "id-1" 216 }, 217 "inst4": { 218 "root_store": "ebs", 219 "virt": "pv", 220 "region": "region-2", 221 "id": "id-2" 222 } 223 }, 224 "pubname": "ubuntu-quantal-12.14-amd64-server-20121218", 225 "label": "release" 226 } 227 } 228 }, 229 "com.ubuntu.cloud:server:13.04:amd64": { 230 "release": "raring", 231 "version": "13.04", 232 "arch": "amd64", 233 "versions": { 234 "20121218": { 235 "items": { 236 "inst5": { 237 "root_store": "ebs", 238 "virt": "pv", 239 "region": "some-region", 240 "id": "id-y" 241 }, 242 "inst6": { 243 "root_store": "ebs", 244 "virt": "pv", 245 "region": "another-region", 246 "id": "id-z" 247 } 248 }, 249 "pubname": "ubuntu-raring-13.04-amd64-server-20121218", 250 "label": "release" 251 } 252 } 253 }, 254 "com.ubuntu.cloud:server:14.04:s390x": { 255 "release": "trusty", 256 "version": "14.04", 257 "arch": "s390x", 258 "versions": { 259 "20121218": { 260 "items": { 261 "inst5": { 262 "root_store": "ebs", 263 "virt": "pv", 264 "region": "some-region", 265 "id": "id-y" 266 }, 267 "inst6": { 268 "root_store": "ebs", 269 "virt": "pv", 270 "region": "another-region", 271 "id": "id-z" 272 } 273 }, 274 "pubname": "ubuntu-trusty-14.04-s390x-server-20121218", 275 "label": "release" 276 } 277 } 278 }, 279 "com.ubuntu.cloud:server:16.04:s390x": { 280 "release": "xenial", 281 "version": "16.04", 282 "arch": "s390x", 283 "versions": { 284 "20121218": { 285 "items": { 286 "inst5": { 287 "root_store": "ebs", 288 "virt": "pv", 289 "region": "some-region", 290 "id": "id-y" 291 }, 292 "inst6": { 293 "root_store": "ebs", 294 "virt": "pv", 295 "region": "another-region", 296 "id": "id-z" 297 } 298 }, 299 "pubname": "ubuntu-xenial-16.04-s390x-server-20121218", 300 "label": "release" 301 } 302 } 303 } 304 }, 305 "format": "products:1.0" 306 } 307 ` 308 309 const productMetadatafile = "image-metadata/products.json" 310 311 func UseTestImageData(stor envstorage.Storage, cred *identity.Credentials) { 312 // Put some image metadata files into the public storage. 313 t := template.Must(template.New("").Parse(indexData)) 314 var metadata bytes.Buffer 315 if err := t.Execute(&metadata, cred); err != nil { 316 panic(fmt.Errorf("cannot generate index metdata: %v", err)) 317 } 318 data := metadata.Bytes() 319 stor.Put(simplestreams.UnsignedIndex("v1", 1), bytes.NewReader(data), int64(len(data))) 320 stor.Put( 321 productMetadatafile, strings.NewReader(imagesData), int64(len(imagesData))) 322 323 envtesting.SignTestTools(stor) 324 } 325 326 func RemoveTestImageData(stor envstorage.Storage) { 327 stor.RemoveAll() 328 } 329 330 // DiscardSecurityGroup cleans up a security group, it is not an error to 331 // delete something that doesn't exist. 332 func DiscardSecurityGroup(e environs.Environ, name string) error { 333 env := e.(*Environ) 334 novaClient := env.nova() 335 group, err := novaClient.SecurityGroupByName(name) 336 if err != nil { 337 if errors.IsNotFound(err) { 338 // Group already deleted, done 339 return nil 340 } 341 } 342 err = novaClient.DeleteSecurityGroup(group.Id) 343 if err != nil { 344 return err 345 } 346 return nil 347 } 348 349 func FindInstanceSpec( 350 e environs.Environ, 351 series, arch, cons string, 352 imageMetadata []*imagemetadata.ImageMetadata, 353 ) (spec *instances.InstanceSpec, err error) { 354 env := e.(*Environ) 355 return findInstanceSpec(env, &instances.InstanceConstraint{ 356 Series: series, 357 Arches: []string{arch}, 358 Region: env.ecfg().region(), 359 Constraints: constraints.MustParse(cons), 360 }, imageMetadata) 361 } 362 363 func GetSwiftURL(e environs.Environ) (string, error) { 364 return e.(*Environ).client.MakeServiceURL("object-store", nil) 365 } 366 367 func SetUseFloatingIP(e environs.Environ, val bool) { 368 env := e.(*Environ) 369 env.ecfg().attrs["use-floating-ip"] = val 370 } 371 372 func SetUpGlobalGroup(e environs.Environ, name string, apiPort int) (nova.SecurityGroup, error) { 373 return e.(*Environ).firewaller.(*defaultFirewaller).setUpGlobalGroup(name, apiPort) 374 } 375 376 func EnsureGroup(e environs.Environ, name string, rules []nova.RuleInfo) (nova.SecurityGroup, error) { 377 return e.(*Environ).firewaller.(*defaultFirewaller).ensureGroup(name, rules) 378 } 379 380 // ImageMetadataStorage returns a Storage object pointing where the goose 381 // infrastructure sets up its keystone entry for image metadata 382 func ImageMetadataStorage(e environs.Environ) envstorage.Storage { 383 env := e.(*Environ) 384 return &openstackstorage{ 385 containerName: "imagemetadata", 386 swift: swift.New(env.client), 387 } 388 } 389 390 // CreateCustomStorage creates a swift container and returns the Storage object 391 // so you can put data into it. 392 func CreateCustomStorage(e environs.Environ, containerName string) envstorage.Storage { 393 env := e.(*Environ) 394 swiftClient := swift.New(env.client) 395 if err := swiftClient.CreateContainer(containerName, swift.PublicRead); err != nil { 396 panic(err) 397 } 398 return &openstackstorage{ 399 containerName: containerName, 400 swift: swiftClient, 401 } 402 } 403 404 // BlankContainerStorage creates a Storage object with blank container name. 405 func BlankContainerStorage() envstorage.Storage { 406 return &openstackstorage{} 407 } 408 409 func GetNovaClient(e environs.Environ) *nova.Client { 410 return e.(*Environ).nova() 411 } 412 413 // ResolveNetwork exposes environ helper function resolveNetwork for testing 414 func ResolveNetwork(e environs.Environ, networkName string) (string, error) { 415 return e.(*Environ).resolveNetwork(networkName) 416 } 417 418 var PortsToRuleInfo = portsToRuleInfo 419 var RuleMatchesPortRange = ruleMatchesPortRange 420 421 var MakeServiceURL = &makeServiceURL 422 var ProviderInstance = providerInstance 423 424 var GetVolumeEndpointURL = getVolumeEndpointURL