github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/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 "launchpad.net/goose/errors" 13 "launchpad.net/goose/identity" 14 "launchpad.net/goose/nova" 15 "launchpad.net/goose/swift" 16 17 "github.com/juju/juju/constraints" 18 "github.com/juju/juju/environs" 19 "github.com/juju/juju/environs/instances" 20 "github.com/juju/juju/environs/jujutest" 21 "github.com/juju/juju/environs/simplestreams" 22 "github.com/juju/juju/environs/storage" 23 "github.com/juju/juju/instance" 24 "github.com/juju/juju/network" 25 ) 26 27 // This provides the content for code accessing test:///... URLs. This allows 28 // us to set the responses for things like the Metadata server, by pointing 29 // metadata requests at test:///... rather than http://169.254.169.254 30 var testRoundTripper = &jujutest.ProxyRoundTripper{} 31 32 func init() { 33 testRoundTripper.RegisterForScheme("test") 34 } 35 36 var ( 37 ShortAttempt = &shortAttempt 38 StorageAttempt = &storageAttempt 39 ) 40 41 // MetadataStorage returns a Storage instance which is used to store simplestreams metadata for tests. 42 func MetadataStorage(e environs.Environ) storage.Storage { 43 ecfg := e.(*environ).ecfg() 44 authModeCfg := AuthMode(ecfg.authMode()) 45 container := "juju-dist-test" 46 metadataStorage := &openstackstorage{ 47 containerName: container, 48 swift: swift.New(e.(*environ).authClient(ecfg, authModeCfg)), 49 } 50 51 // Ensure the container exists. 52 err := metadataStorage.makeContainer(container, swift.PublicRead) 53 if err != nil { 54 panic(fmt.Errorf("cannot create %s container: %v", container, err)) 55 } 56 return metadataStorage 57 } 58 59 func InstanceAddress(addresses map[string][]nova.IPAddress) string { 60 return network.SelectPublicAddress(convertNovaAddresses(addresses)) 61 } 62 63 func InstanceServerDetail(inst instance.Instance) *nova.ServerDetail { 64 return inst.(*openstackInstance).serverDetail 65 } 66 67 var ( 68 NovaListAvailabilityZones = &novaListAvailabilityZones 69 BestAvailabilityZoneAllocations = &bestAvailabilityZoneAllocations 70 ) 71 72 var indexData = ` 73 { 74 "index": { 75 "com.ubuntu.cloud:released:openstack": { 76 "updated": "Wed, 01 May 2013 13:31:26 +0000", 77 "clouds": [ 78 { 79 "region": "{{.Region}}", 80 "endpoint": "{{.URL}}" 81 } 82 ], 83 "cloudname": "test", 84 "datatype": "image-ids", 85 "format": "products:1.0", 86 "products": [ 87 "com.ubuntu.cloud:server:12.04:amd64", 88 "com.ubuntu.cloud:server:12.04:i386", 89 "com.ubuntu.cloud:server:12.04:ppc64", 90 "com.ubuntu.cloud:server:12.10:amd64", 91 "com.ubuntu.cloud:server:13.04:amd64" 92 ], 93 "path": "image-metadata/products.json" 94 } 95 }, 96 "updated": "Wed, 01 May 2013 13:31:26 +0000", 97 "format": "index:1.0" 98 } 99 ` 100 101 var imagesData = ` 102 { 103 "content_id": "com.ubuntu.cloud:released:openstack", 104 "products": { 105 "com.ubuntu.cloud:server:12.04:amd64": { 106 "release": "precise", 107 "version": "12.04", 108 "arch": "amd64", 109 "versions": { 110 "20121218": { 111 "items": { 112 "inst1": { 113 "root_store": "ebs", 114 "virt": "pv", 115 "region": "some-region", 116 "id": "1" 117 }, 118 "inst2": { 119 "root_store": "ebs", 120 "virt": "pv", 121 "region": "another-region", 122 "id": "2" 123 } 124 }, 125 "pubname": "ubuntu-precise-12.04-amd64-server-20121218", 126 "label": "release" 127 }, 128 "20121111": { 129 "items": { 130 "inst3": { 131 "root_store": "ebs", 132 "virt": "pv", 133 "region": "some-region", 134 "id": "3" 135 } 136 }, 137 "pubname": "ubuntu-precise-12.04-amd64-server-20121111", 138 "label": "release" 139 } 140 } 141 }, 142 "com.ubuntu.cloud:server:12.04:i386": { 143 "release": "precise", 144 "version": "12.04", 145 "arch": "i386", 146 "versions": { 147 "20121111": { 148 "items": { 149 "inst33": { 150 "root_store": "ebs", 151 "virt": "pv", 152 "region": "some-region", 153 "id": "33" 154 } 155 }, 156 "pubname": "ubuntu-precise-12.04-i386-server-20121111", 157 "label": "release" 158 } 159 } 160 }, 161 "com.ubuntu.cloud:server:12.04:ppc64": { 162 "release": "precise", 163 "version": "12.04", 164 "arch": "ppc64", 165 "versions": { 166 "20121111": { 167 "items": { 168 "inst33": { 169 "root_store": "ebs", 170 "virt": "pv", 171 "region": "some-region", 172 "id": "33" 173 } 174 }, 175 "pubname": "ubuntu-precise-12.04-ppc64-server-20121111", 176 "label": "release" 177 } 178 } 179 }, 180 "com.ubuntu.cloud:server:12.10:amd64": { 181 "release": "quantal", 182 "version": "12.10", 183 "arch": "amd64", 184 "versions": { 185 "20121218": { 186 "items": { 187 "inst3": { 188 "root_store": "ebs", 189 "virt": "pv", 190 "region": "region-1", 191 "id": "id-1" 192 }, 193 "inst4": { 194 "root_store": "ebs", 195 "virt": "pv", 196 "region": "region-2", 197 "id": "id-2" 198 } 199 }, 200 "pubname": "ubuntu-quantal-12.14-amd64-server-20121218", 201 "label": "release" 202 } 203 } 204 }, 205 "com.ubuntu.cloud:server:13.04:amd64": { 206 "release": "raring", 207 "version": "13.04", 208 "arch": "amd64", 209 "versions": { 210 "20121218": { 211 "items": { 212 "inst5": { 213 "root_store": "ebs", 214 "virt": "pv", 215 "region": "some-region", 216 "id": "id-y" 217 }, 218 "inst6": { 219 "root_store": "ebs", 220 "virt": "pv", 221 "region": "another-region", 222 "id": "id-z" 223 } 224 }, 225 "pubname": "ubuntu-raring-13.04-amd64-server-20121218", 226 "label": "release" 227 } 228 } 229 } 230 }, 231 "format": "products:1.0" 232 } 233 ` 234 235 const productMetadatafile = "image-metadata/products.json" 236 237 func UseTestImageData(stor storage.Storage, cred *identity.Credentials) { 238 // Put some image metadata files into the public storage. 239 t := template.Must(template.New("").Parse(indexData)) 240 var metadata bytes.Buffer 241 if err := t.Execute(&metadata, cred); err != nil { 242 panic(fmt.Errorf("cannot generate index metdata: %v", err)) 243 } 244 data := metadata.Bytes() 245 stor.Put(simplestreams.DefaultIndexPath+".json", bytes.NewReader(data), int64(len(data))) 246 stor.Put( 247 productMetadatafile, strings.NewReader(imagesData), int64(len(imagesData))) 248 } 249 250 func RemoveTestImageData(stor storage.Storage) { 251 stor.Remove(simplestreams.DefaultIndexPath + ".json") 252 stor.Remove(productMetadatafile) 253 } 254 255 // DiscardSecurityGroup cleans up a security group, it is not an error to 256 // delete something that doesn't exist. 257 func DiscardSecurityGroup(e environs.Environ, name string) error { 258 env := e.(*environ) 259 novaClient := env.nova() 260 group, err := novaClient.SecurityGroupByName(name) 261 if err != nil { 262 if errors.IsNotFound(err) { 263 // Group already deleted, done 264 return nil 265 } 266 } 267 err = novaClient.DeleteSecurityGroup(group.Id) 268 if err != nil { 269 return err 270 } 271 return nil 272 } 273 274 func FindInstanceSpec(e environs.Environ, series, arch, cons string) (spec *instances.InstanceSpec, err error) { 275 env := e.(*environ) 276 spec, err = findInstanceSpec(env, &instances.InstanceConstraint{ 277 Series: series, 278 Arches: []string{arch}, 279 Region: env.ecfg().region(), 280 Constraints: constraints.MustParse(cons), 281 }) 282 return 283 } 284 285 func ControlBucketName(e environs.Environ) string { 286 env := e.(*environ) 287 return env.ecfg().controlBucket() 288 } 289 290 func GetSwiftURL(e environs.Environ) (string, error) { 291 return e.(*environ).client.MakeServiceURL("object-store", nil) 292 } 293 294 func SetUseFloatingIP(e environs.Environ, val bool) { 295 env := e.(*environ) 296 env.ecfg().attrs["use-floating-ip"] = val 297 } 298 299 func SetUpGlobalGroup(e environs.Environ, name string, statePort, apiPort int) (nova.SecurityGroup, error) { 300 return e.(*environ).setUpGlobalGroup(name, statePort, apiPort) 301 } 302 303 func EnsureGroup(e environs.Environ, name string, rules []nova.RuleInfo) (nova.SecurityGroup, error) { 304 return e.(*environ).ensureGroup(name, rules) 305 } 306 307 func CollectInstances(e environs.Environ, ids []instance.Id, out map[instance.Id]instance.Instance) []instance.Id { 308 return e.(*environ).collectInstances(ids, out) 309 } 310 311 // ImageMetadataStorage returns a Storage object pointing where the goose 312 // infrastructure sets up its keystone entry for image metadata 313 func ImageMetadataStorage(e environs.Environ) storage.Storage { 314 env := e.(*environ) 315 return &openstackstorage{ 316 containerName: "imagemetadata", 317 swift: swift.New(env.client), 318 } 319 } 320 321 // CreateCustomStorage creates a swift container and returns the Storage object 322 // so you can put data into it. 323 func CreateCustomStorage(e environs.Environ, containerName string) storage.Storage { 324 env := e.(*environ) 325 swiftClient := swift.New(env.client) 326 if err := swiftClient.CreateContainer(containerName, swift.PublicRead); err != nil { 327 panic(err) 328 } 329 return &openstackstorage{ 330 containerName: containerName, 331 swift: swiftClient, 332 } 333 } 334 335 func GetNovaClient(e environs.Environ) *nova.Client { 336 return e.(*environ).nova() 337 } 338 339 // ResolveNetwork exposes environ helper function resolveNetwork for testing 340 func ResolveNetwork(e environs.Environ, networkName string) (string, error) { 341 return e.(*environ).resolveNetwork(networkName) 342 }