nephophobia 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. data/.autotest +29 -0
  2. data/.gitignore +2 -0
  3. data/.rvmrc +1 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +35 -0
  6. data/README.md +23 -0
  7. data/Rakefile +11 -0
  8. data/lib/aws.rb +51 -0
  9. data/lib/hashify.rb +29 -0
  10. data/lib/nephophobia.rb +30 -0
  11. data/lib/nephophobia/client.rb +73 -0
  12. data/lib/nephophobia/compute.rb +150 -0
  13. data/lib/nephophobia/image.rb +78 -0
  14. data/lib/nephophobia/project.rb +113 -0
  15. data/lib/nephophobia/role.rb +5 -0
  16. data/lib/nephophobia/user.rb +86 -0
  17. data/lib/nephophobia/version.rb +3 -0
  18. data/nephophobia.gemspec +30 -0
  19. data/test/fixtures/cassettes/compute_all.yml +28 -0
  20. data/test/fixtures/cassettes/compute_all_with_filter.yml +30 -0
  21. data/test/fixtures/cassettes/compute_all_with_string_into_int_error.yml +28 -0
  22. data/test/fixtures/cassettes/compute_create.yml +28 -0
  23. data/test/fixtures/cassettes/compute_create_with_optional_params.yml +28 -0
  24. data/test/fixtures/cassettes/compute_destroy.yml +28 -0
  25. data/test/fixtures/cassettes/compute_find.yml +28 -0
  26. data/test/fixtures/cassettes/compute_reboot.yml +28 -0
  27. data/test/fixtures/cassettes/compute_start.yml +30 -0
  28. data/test/fixtures/cassettes/compute_stop.yml +30 -0
  29. data/test/fixtures/cassettes/image_all.yml +28 -0
  30. data/test/fixtures/cassettes/image_all_with_filter.yml +28 -0
  31. data/test/fixtures/cassettes/image_all_with_string_into_int_error.yml +28 -0
  32. data/test/fixtures/cassettes/image_find.yml +28 -0
  33. data/test/fixtures/cassettes/project_add_member.yml +28 -0
  34. data/test/fixtures/cassettes/project_all.yml +28 -0
  35. data/test/fixtures/cassettes/project_all_with_string_into_int_error.yml +28 -0
  36. data/test/fixtures/cassettes/project_create.yml +28 -0
  37. data/test/fixtures/cassettes/project_destroy.yml +28 -0
  38. data/test/fixtures/cassettes/project_find.yml +28 -0
  39. data/test/fixtures/cassettes/project_members.yml +28 -0
  40. data/test/fixtures/cassettes/project_remove_member.yml +28 -0
  41. data/test/fixtures/cassettes/user_add_role.yml +28 -0
  42. data/test/fixtures/cassettes/user_create.yml +28 -0
  43. data/test/fixtures/cassettes/user_destroy.yml +28 -0
  44. data/test/fixtures/cassettes/user_find.yml +28 -0
  45. data/test/fixtures/cassettes/user_remove_role.yml +28 -0
  46. data/test/lib/aws_test.rb +22 -0
  47. data/test/lib/hashify_test.rb +15 -0
  48. data/test/lib/nephophobia/compute_test.rb +144 -0
  49. data/test/lib/nephophobia/image_test.rb +76 -0
  50. data/test/lib/nephophobia/project_test.rb +104 -0
  51. data/test/lib/nephophobia/user_test.rb +71 -0
  52. data/test/lib/nephophobia_test.rb +17 -0
  53. data/test/test_helper.rb +47 -0
  54. metadata +221 -0
@@ -0,0 +1,78 @@
1
+ module Nephophobia
2
+ class ImageData
3
+ attr_reader :architecture, :image_id, :image_location, :image_owner_id
4
+ attr_reader :image_type, :kernel_id, :is_public, :state
5
+
6
+ def initialize hash
7
+ @architecture = hash['architecture']
8
+ @id = hash['id']
9
+ @image_id = hash['imageId']
10
+ @image_location = hash['imageLocation']
11
+ @image_owner_id = hash['imageOwnerId']
12
+ @image_type = hash['imageType']
13
+ @is_public = hash['isPublic']
14
+ @kernel_id = hash['kernelId']
15
+ @state = hash['imageState']
16
+ end
17
+ end
18
+
19
+ class Image
20
+ def initialize client
21
+ @client = client
22
+ end
23
+
24
+ ##
25
+ # Returns information about AMIs, AKIs, and ARIs. Images returned include
26
+ # public images, private images that +@client+ owns, and private images
27
+ # owned by other AWS accounts but for which +@client+ has explicit launch
28
+ # permissions.
29
+ #
30
+ # +filter+: An optional Hash, intended for filtering.
31
+ # See the API Reference for further details.
32
+ # {
33
+ # "Filter.1.Name" => "instance-type",
34
+ # "Filter.1.Value.1" => "m1.small",
35
+ # "ExecutableBy.1" => "self",
36
+ # }
37
+
38
+ def all filter = {}
39
+ response = @client.action "DescribeImages", filter
40
+
41
+ Nephophobia.coerce(response.body['DescribeImagesResponse']['imagesSet']['item']).collect do |data|
42
+ ImageData.new data
43
+ end
44
+ end
45
+
46
+ ##
47
+ # Returns information about the specified 'image_id'.
48
+ #
49
+ # +image_id+: A String representing the ID of the image.
50
+
51
+ def find image_id
52
+ filter = {
53
+ "ImageId.1" => image_id
54
+ }
55
+
56
+ response = @client.action "DescribeImages", filter
57
+
58
+ ImageData.new response.body['DescribeImagesResponse']['imagesSet']['item']
59
+ end
60
+
61
+ ##
62
+ # Return information about all public images.
63
+
64
+ def public
65
+ all.select do |image|
66
+ public? image
67
+ end
68
+ end
69
+
70
+ private
71
+ ##
72
+ # images which do not have a valid kernel_id are not runnable.
73
+
74
+ def public? image
75
+ image.is_public == "true" && image.kernel_id != "true"
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,113 @@
1
+ module Nephophobia
2
+ class ProjectData
3
+ attr_reader :name, :manager_id, :description
4
+
5
+ def initialize hash
6
+ @name = hash['projectname']
7
+ @manager_id = hash['projectManagerId']
8
+ @description = hash['description']
9
+ end
10
+ end
11
+
12
+ class Project
13
+ def initialize client
14
+ @client = client
15
+ end
16
+
17
+ ##
18
+ # Adds the given 'user_name' to the specified "project_name".
19
+ # Returns a response to the state change.
20
+ #
21
+ # +user_name+: A String representing a nova user_name.
22
+ # +project_name+: A String representing a nova project_name name.
23
+
24
+ def add_member user_name, project_name
25
+ modify_membership user_name, "add", project_name
26
+ end
27
+
28
+ ##
29
+ # Returns information about all projects.
30
+
31
+ def all
32
+ response = @client.action "DescribeProjects", {}
33
+
34
+ Nephophobia.coerce(response.body['DescribeProjectsResponse']['projectSet']['item']).collect do |data|
35
+ ProjectData.new data
36
+ end
37
+ end
38
+
39
+ ##
40
+ # Creates the given 'project_name'.
41
+ # Returns a response to the state change.
42
+ #
43
+ # +user_name+: A String representing a nova user_name.
44
+ # +project_name+: A String representing a nova project name.
45
+
46
+ def create project_name, user_name
47
+ filter = {
48
+ "Name" => project_name,
49
+ "ManagerUser" => user_name
50
+ }
51
+
52
+ response = @client.action "RegisterProject", filter
53
+
54
+ ProjectData.new response.body['RegisterProjectResponse']
55
+ end
56
+
57
+ ##
58
+ # Removes the given 'project_name'.
59
+ # Returns a response to the state change.
60
+ #
61
+ # +project_name+: A String representing a nova project name.
62
+
63
+ def destroy project_name
64
+ response = @client.action "DeregisterProject", "Name" => project_name
65
+
66
+ ResponseData.new response.body['DeregisterProjectResponse']
67
+ end
68
+
69
+ ##
70
+ # Returns information about the given 'project_name'.
71
+ #
72
+ # +project_name+: A String representing a nova project name.
73
+
74
+ def find project_name
75
+ response = @client.action "DescribeProject", "Name" => project_name
76
+
77
+ ProjectData.new response.body['DescribeProjectResponse']
78
+ end
79
+
80
+ ##
81
+ # Returns information about all members of the given 'project_name'.
82
+
83
+ def members project_name
84
+ response = @client.action "DescribeProjectMembers", "Name" => project_name
85
+
86
+ response.body['DescribeProjectMembersResponse']['members']['item']
87
+ end
88
+
89
+ ##
90
+ # Removes the given 'user_name' from the specified "project_name".
91
+ # Returns a response to the state change.
92
+ #
93
+ # +user_name+: A String representing a nova user_name.
94
+ # +project_name+: A String representing a nova project_name name.
95
+
96
+ def remove_member user_name, project_name
97
+ modify_membership user_name, "remove", project_name
98
+ end
99
+
100
+ private
101
+ def modify_membership user_name, operation, project_name
102
+ params = {
103
+ "User" => user_name,
104
+ "Project" => project_name,
105
+ "Operation" => operation
106
+ }
107
+
108
+ response = @client.action "ModifyProjectMember", params
109
+
110
+ ResponseData.new response.body['ModifyProjectMemberResponse']
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,5 @@
1
+ module Nephophobia
2
+ class Role
3
+ DEFAULT = "sysadmin"
4
+ end
5
+ end
@@ -0,0 +1,86 @@
1
+ module Nephophobia
2
+ class UserData
3
+ attr_reader :accesskey, :username, :secretkey
4
+
5
+ def initialize hash
6
+ @accesskey = hash['accesskey']
7
+ @username = hash['username']
8
+ @secretkey = hash['secretkey']
9
+ end
10
+ end
11
+
12
+ class User
13
+ def initialize client
14
+ @client = client
15
+ end
16
+
17
+ ##
18
+ # Adds the given 'user_name' to the specified "project_name's" 'Role::DEFAULT'.
19
+ # Returns a response to the state change.
20
+ #
21
+ # +user_name+: A String representing a nova user_name.
22
+ # +project_name+: A String representing a nova project_name name.
23
+
24
+ def add_role user_name, project_name
25
+ modify_role user_name, "add", project_name
26
+ end
27
+
28
+ ##
29
+ # Creates the given 'user_name'.
30
+ # Returns a response to the state change.
31
+ #
32
+ # +user_name+: A String representing a nova user_name.
33
+
34
+ def create user_name
35
+ response = @client.action "RegisterUser", "Name" => user_name
36
+
37
+ UserData.new response.body['RegisterUserResponse']
38
+ end
39
+
40
+ ##
41
+ # Removes the given 'user_name'.
42
+ # Returns a response to the state change.
43
+ #
44
+ # +user_name+: A String representing a nova user_name.
45
+
46
+ def destroy user_name
47
+ response = @client.action "DeregisterUser", "Name" => user_name
48
+
49
+ ResponseData.new response.body['DeregisterUserResponse']
50
+ end
51
+
52
+ ##
53
+ # Returns information about the given 'user_name'.
54
+ #
55
+ # +user_name+: A String representing the user_name.
56
+
57
+ def find user_name
58
+ response = @client.action "DescribeUser", "Name" => user_name
59
+
60
+ UserData.new response.body['DescribeUserResponse']
61
+ end
62
+
63
+ ##
64
+ # Removes the given 'user_name' from the specified "project_name's" 'Role::DEFAULT'.
65
+ #
66
+ # +user_name+: A String representing a nova user_name.
67
+ # +project_name+: A String representing a nova project_name name.
68
+
69
+ def remove_role user_name, project_name
70
+ modify_role user_name, "remove", project_name
71
+ end
72
+
73
+ private
74
+ def modify_role user_name, operation, project_name
75
+ params = {
76
+ "User" => user_name,
77
+ "Role" => Role::DEFAULT,
78
+ "Operation" => operation
79
+ }
80
+
81
+ response = @client.action "ModifyUserRole", params
82
+
83
+ ResponseData.new response.body['ModifyUserRoleResponse']
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,3 @@
1
+ module Nephophobia
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "nephophobia/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "nephophobia"
7
+ s.version = Nephophobia::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["John Dewey", "Josh Kleinpeter"]
10
+ s.email = ["jdewey@attinteractive.com", "jkleinpeter@attinteractive.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{Bindings to EC2/OpenStack}
13
+ s.description = %q{This gem is a simple binding to the EC2 API. It has specific extensions to allow extra functionality provided by OpenStack.}
14
+
15
+ s.rubyforge_project = "nephophobia"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency "hugs", "~> 2.5.0"
23
+
24
+ s.add_development_dependency "autotest-standalone"
25
+ s.add_development_dependency "fakeweb", "~> 1.3.0"
26
+ s.add_development_dependency "minitest", "~> 2.0.2"
27
+ s.add_development_dependency "nokogiri", "~> 1.4.4"
28
+ s.add_development_dependency "rake", "~> 0.8.7"
29
+ s.add_development_dependency "vcr", "1.5.0"
30
+ end
@@ -0,0 +1,28 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://10.1.170.32:8773/services/Cloud?AWSAccessKeyId=9c01b833-3047-4f2e-bb2a-5c8dc7c8ae9c%3Aproduction&Action=DescribeInstances&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=1999-12-31T19%3A59%3A59Z&Version=2010-11-15&Signature=WH%2BC76b336Lc35DuC%2Fk7f8UTkiKH0nl6rKYrSlzUqDM%3D
6
+ body:
7
+ headers:
8
+ accept:
9
+ - application/xml
10
+ connection:
11
+ - keep-alive
12
+ keep-alive:
13
+ - 30
14
+ response: !ruby/struct:VCR::Response
15
+ status: !ruby/struct:VCR::ResponseStatus
16
+ code: 200
17
+ message: OK
18
+ headers:
19
+ content-type:
20
+ - text/xml
21
+ content-length:
22
+ - "1598"
23
+ date:
24
+ - Mon, 21 Feb 2011 20:09:55 GMT
25
+ connection:
26
+ - keep-alive
27
+ body: <?xml version="1.0" ?><DescribeInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-11-15/"><requestId>W6P62OURN04XF89JYL86</requestId><reservationSet><item><ownerId>production</ownerId><groupSet><item><groupId>default</groupId></item></groupSet><reservationId>r-6p9fdt2e</reservationId><instancesSet><item><displayDescription/><displayName>Server 199</displayName><keyName>None (production, e3ab3)</keyName><instanceId>i-000000c7</instanceId><instanceState><code>1</code><name>running</name></instanceState><publicDnsName/><imageId>ami-usc3oydl</imageId><productCodesSet/><privateDnsName>10.1.171.8</privateDnsName><dnsName>10.1.171.8</dnsName><launchTime>2011-02-21 17:54:35</launchTime><placement><availabilityZone>nova</availabilityZone></placement><amiLaunchIndex>0</amiLaunchIndex><instanceType>m1.small</instanceType></item></instancesSet></item><item><ownerId>jtran</ownerId><groupSet><item><groupId>default</groupId></item></groupSet><reservationId>r-5oexkoz1</reservationId><instancesSet><item><displayDescription/><displayName>Server 198</displayName><keyName>None (jtran, cm-02)</keyName><instanceId>i-000000c6</instanceId><instanceState><code>1</code><name>running</name></instanceState><publicDnsName/><imageId>ami-usc3oydl</imageId><productCodesSet/><privateDnsName>10.1.173.17</privateDnsName><dnsName>10.1.173.17</dnsName><launchTime>2011-02-20 07:17:03</launchTime><placement><availabilityZone>nova</availabilityZone></placement><amiLaunchIndex>0</amiLaunchIndex><instanceType>m1.small</instanceType></item></instancesSet></item></reservationSet></DescribeInstancesResponse>
28
+ http_version: "1.1"
@@ -0,0 +1,30 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://10.1.170.32:8773/services/Cloud?AWSAccessKeyId=9c01b833-3047-4f2e-bb2a-5c8dc7c8ae9c%3Aproduction&Action=DescribeInstances&Filter.1.Name=instance-type&Filter.1.Value.1=m1.small&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=1999-12-31T19%3A59%3A59Z&Version=2010-11-15&Signature=A%2Foo6aKfI7sbuEdwy8TCgZQq9TPUgu%2BEgrwliuiygZ0%3D
6
+ body:
7
+ headers:
8
+ accept:
9
+ - application/xml
10
+ connection:
11
+ - keep-alive
12
+ keep-alive:
13
+ - 30
14
+ response: !ruby/struct:VCR::Response
15
+ status: !ruby/struct:VCR::ResponseStatus
16
+ code: 400
17
+ message: Bad Request
18
+ headers:
19
+ content-type:
20
+ - text/xml
21
+ content-length:
22
+ - "223"
23
+ date:
24
+ - Sun, 27 Feb 2011 05:55:55 GMT
25
+ connection:
26
+ - keep-alive
27
+ body: |-
28
+ <?xml version="1.0"?>
29
+ <Response><Errors><Error><Code>UnknownError</Code><Message>An unknown error has occurred. Please try your request again.</Message></Error></Errors><RequestID>XPM759MGOM2Y8IHPY5T5</RequestID></Response>
30
+ http_version: "1.1"
@@ -0,0 +1,28 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://10.1.170.32:8773/services/Cloud?AWSAccessKeyId=9c01b833-3047-4f2e-bb2a-5c8dc7c8ae9c%3Aproduction&Action=DescribeInstances&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=1999-12-31T19%3A59%3A59Z&Version=2010-11-15&Signature=WH%2BC76b336Lc35DuC%2Fk7f8UTkiKH0nl6rKYrSlzUqDM%3D
6
+ body:
7
+ headers:
8
+ accept:
9
+ - application/xml
10
+ connection:
11
+ - keep-alive
12
+ keep-alive:
13
+ - 30
14
+ response: !ruby/struct:VCR::Response
15
+ status: !ruby/struct:VCR::ResponseStatus
16
+ code: 200
17
+ message: OK
18
+ headers:
19
+ content-type:
20
+ - text/xml
21
+ content-length:
22
+ - "871"
23
+ date:
24
+ - Fri, 04 Mar 2011 01:56:26 GMT
25
+ connection:
26
+ - keep-alive
27
+ body: <?xml version="1.0" ?><DescribeInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-11-15/"><requestId>8L9E--E0D-DACB097WCL</requestId><reservationSet><item><ownerId>production</ownerId><groupSet><item><groupId>default</groupId></item></groupSet><reservationId>r-g3b3ggz0</reservationId><instancesSet><item><displayDescription/><displayName>Server 260</displayName><keyName/><instanceId>i-00000104</instanceId><instanceState><code>1</code><name>running</name></instanceState><publicDnsName/><imageId>ami-srgo1p2s</imageId><productCodesSet/><privateDnsName>10.3.172.8</privateDnsName><dnsName>10.3.172.8</dnsName><launchTime>2011-02-25 17:50:23</launchTime><placement><availabilityZone>nova</availabilityZone></placement><amiLaunchIndex>0</amiLaunchIndex><instanceType>m1.small</instanceType></item></instancesSet></item></reservationSet></DescribeInstancesResponse>
28
+ http_version: "1.1"
@@ -0,0 +1,28 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://10.1.170.32:8773/services/Cloud?AWSAccessKeyId=9c01b833-3047-4f2e-bb2a-5c8dc7c8ae9c%3Aproduction&Action=RunInstances&ImageId=ami-usc3oydl&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=1999-12-31T19%3A59%3A59Z&Version=2010-11-15&Signature=Pj%2Bk1BhY5X1256%2Bu8lMPvPdoxkDsm0bJPXqF2PGUzwY%3D
6
+ body:
7
+ headers:
8
+ accept:
9
+ - application/xml
10
+ connection:
11
+ - keep-alive
12
+ keep-alive:
13
+ - 30
14
+ response: !ruby/struct:VCR::Response
15
+ status: !ruby/struct:VCR::ResponseStatus
16
+ code: 200
17
+ message: OK
18
+ headers:
19
+ content-type:
20
+ - text/xml
21
+ content-length:
22
+ - "807"
23
+ date:
24
+ - Sun, 27 Feb 2011 05:55:56 GMT
25
+ connection:
26
+ - keep-alive
27
+ body: <?xml version="1.0" ?><RunInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-11-15/"><requestId>ECX3QKATTRPYC9NNJG1M</requestId><ownerId>production</ownerId><groupSet><item><groupId>default</groupId></item></groupSet><reservationId>r-6l687lh5</reservationId><instancesSet><item><displayDescription/><displayName>Server 1145</displayName><keyName>None (production, None)</keyName><instanceId>i-00000479</instanceId><instanceState><code/><name>scheduling</name></instanceState><publicDnsName/><imageId>ami-usc3oydl</imageId><productCodesSet/><privateDnsName/><dnsName/><launchTime>2011-02-27 05:55:56</launchTime><placement><availabilityZone>unknown zone</availabilityZone></placement><amiLaunchIndex>0</amiLaunchIndex><instanceType>m1.small</instanceType></item></instancesSet></RunInstancesResponse>
28
+ http_version: "1.1"
@@ -0,0 +1,28 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://10.1.170.32:8773/services/Cloud?AWSAccessKeyId=9c01b833-3047-4f2e-bb2a-5c8dc7c8ae9c%3Aproduction&Action=RunInstances&DisplayDescription=test%20description&DisplayName=testserver1&ImageId=ami-usc3oydl&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=1999-12-31T19%3A59%3A59Z&Version=2010-11-15&Signature=zCOhKyLotYPqEmkGUsSh387A10CDB4ySLuuM2ZIhRbQ%3D
6
+ body:
7
+ headers:
8
+ accept:
9
+ - application/xml
10
+ connection:
11
+ - keep-alive
12
+ keep-alive:
13
+ - 30
14
+ response: !ruby/struct:VCR::Response
15
+ status: !ruby/struct:VCR::ResponseStatus
16
+ code: 200
17
+ message: OK
18
+ headers:
19
+ content-type:
20
+ - text/xml
21
+ content-length:
22
+ - "843"
23
+ date:
24
+ - Fri, 04 Mar 2011 17:29:48 GMT
25
+ connection:
26
+ - keep-alive
27
+ body: <?xml version="1.0" ?><RunInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-11-15/"><requestId>8SZ3U7WY7ZSI70GT5X9-</requestId><ownerId>production</ownerId><groupSet><item><groupId>default</groupId></item></groupSet><reservationId>r-hmlklbap</reservationId><instancesSet><item><displayDescription>test description</displayDescription><displayName>testserver1</displayName><keyName>None (production, None)</keyName><instanceId>i-0000048f</instanceId><instanceState><code/><name>scheduling</name></instanceState><publicDnsName/><imageId>ami-usc3oydl</imageId><productCodesSet/><privateDnsName/><dnsName/><launchTime>2011-03-04 17:29:48</launchTime><placement><availabilityZone>unknown zone</availabilityZone></placement><amiLaunchIndex>0</amiLaunchIndex><instanceType>m1.small</instanceType></item></instancesSet></RunInstancesResponse>
28
+ http_version: "1.1"