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