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