deltacloud-core 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 (110) hide show
  1. data/COPYING +502 -0
  2. data/Rakefile +108 -0
  3. data/bin/deltacloudd +88 -0
  4. data/config.ru +5 -0
  5. data/deltacloud.rb +14 -0
  6. data/lib/converters/xml_converter.rb +133 -0
  7. data/lib/deltacloud/base_driver.rb +19 -0
  8. data/lib/deltacloud/base_driver/base_driver.rb +189 -0
  9. data/lib/deltacloud/base_driver/features.rb +144 -0
  10. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +318 -0
  11. data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +170 -0
  12. data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +45 -0
  13. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +239 -0
  14. data/lib/deltacloud/drivers/mock/mock_driver.rb +275 -0
  15. data/lib/deltacloud/drivers/opennebula/cloud_client.rb +116 -0
  16. data/lib/deltacloud/drivers/opennebula/occi_client.rb +204 -0
  17. data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +241 -0
  18. data/lib/deltacloud/drivers/rackspace/rackspace_client.rb +129 -0
  19. data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +150 -0
  20. data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +254 -0
  21. data/lib/deltacloud/drivers/rimu/rimu_hosting_client.rb +87 -0
  22. data/lib/deltacloud/drivers/rimu/rimu_hosting_driver.rb +143 -0
  23. data/lib/deltacloud/hardware_profile.rb +131 -0
  24. data/lib/deltacloud/helpers.rb +5 -0
  25. data/lib/deltacloud/helpers/application_helper.rb +38 -0
  26. data/lib/deltacloud/helpers/conversion_helper.rb +39 -0
  27. data/lib/deltacloud/helpers/hardware_profiles_helper.rb +35 -0
  28. data/lib/deltacloud/models/base_model.rb +58 -0
  29. data/lib/deltacloud/models/image.rb +26 -0
  30. data/lib/deltacloud/models/instance.rb +37 -0
  31. data/lib/deltacloud/models/instance_profile.rb +47 -0
  32. data/lib/deltacloud/models/realm.rb +25 -0
  33. data/lib/deltacloud/models/storage_snapshot.rb +26 -0
  34. data/lib/deltacloud/models/storage_volume.rb +27 -0
  35. data/lib/deltacloud/state_machine.rb +84 -0
  36. data/lib/deltacloud/validation.rb +70 -0
  37. data/lib/drivers.rb +37 -0
  38. data/lib/sinatra/lazy_auth.rb +56 -0
  39. data/lib/sinatra/rabbit.rb +272 -0
  40. data/lib/sinatra/respond_to.rb +262 -0
  41. data/lib/sinatra/static_assets.rb +83 -0
  42. data/lib/sinatra/url_for.rb +44 -0
  43. data/public/favicon.ico +0 -0
  44. data/public/images/grid.png +0 -0
  45. data/public/images/logo-wide.png +0 -0
  46. data/public/images/rails.png +0 -0
  47. data/public/images/topbar-bg.png +0 -0
  48. data/public/javascripts/application.js +2 -0
  49. data/public/javascripts/controls.js +963 -0
  50. data/public/javascripts/dragdrop.js +973 -0
  51. data/public/javascripts/effects.js +1128 -0
  52. data/public/javascripts/prototype.js +4320 -0
  53. data/public/stylesheets/compiled/application.css +613 -0
  54. data/public/stylesheets/compiled/ie.css +31 -0
  55. data/public/stylesheets/compiled/print.css +27 -0
  56. data/public/stylesheets/compiled/screen.css +456 -0
  57. data/server.rb +340 -0
  58. data/tests/deltacloud_test.rb +60 -0
  59. data/tests/images_test.rb +94 -0
  60. data/tests/instances_test.rb +136 -0
  61. data/tests/realms_test.rb +56 -0
  62. data/tests/storage_snapshots_test.rb +48 -0
  63. data/tests/storage_volumes_test.rb +48 -0
  64. data/views/accounts/index.html.haml +11 -0
  65. data/views/accounts/show.html.haml +30 -0
  66. data/views/api/show.html.haml +15 -0
  67. data/views/api/show.xml.haml +5 -0
  68. data/views/docs/collection.html.haml +37 -0
  69. data/views/docs/collection.xml.haml +14 -0
  70. data/views/docs/index.html.haml +15 -0
  71. data/views/docs/index.xml.haml +5 -0
  72. data/views/docs/operation.html.haml +31 -0
  73. data/views/docs/operation.xml.haml +10 -0
  74. data/views/errors/auth_exception.html.haml +8 -0
  75. data/views/errors/auth_exception.xml.haml +2 -0
  76. data/views/errors/backend_error.html.haml +17 -0
  77. data/views/errors/backend_error.xml.haml +8 -0
  78. data/views/errors/validation_failure.html.haml +11 -0
  79. data/views/errors/validation_failure.xml.haml +7 -0
  80. data/views/hardware_profiles/index.html.haml +25 -0
  81. data/views/hardware_profiles/index.xml.haml +4 -0
  82. data/views/hardware_profiles/show.html.haml +19 -0
  83. data/views/hardware_profiles/show.xml.haml +17 -0
  84. data/views/images/index.html.haml +30 -0
  85. data/views/images/index.xml.haml +7 -0
  86. data/views/images/show.html.haml +21 -0
  87. data/views/images/show.xml.haml +5 -0
  88. data/views/instance_states/show.gv.erb +45 -0
  89. data/views/instance_states/show.html.haml +31 -0
  90. data/views/instance_states/show.xml.haml +8 -0
  91. data/views/instances/index.html.haml +29 -0
  92. data/views/instances/index.xml.haml +23 -0
  93. data/views/instances/new.html.haml +49 -0
  94. data/views/instances/show.html.haml +42 -0
  95. data/views/instances/show.xml.haml +28 -0
  96. data/views/layout.html.haml +23 -0
  97. data/views/realms/index.html.haml +29 -0
  98. data/views/realms/index.xml.haml +12 -0
  99. data/views/realms/show.html.haml +15 -0
  100. data/views/realms/show.xml.haml +10 -0
  101. data/views/root/index.html.haml +4 -0
  102. data/views/storage_snapshots/index.html.haml +20 -0
  103. data/views/storage_snapshots/index.xml.haml +11 -0
  104. data/views/storage_snapshots/show.html.haml +14 -0
  105. data/views/storage_snapshots/show.xml.haml +9 -0
  106. data/views/storage_volumes/index.html.haml +21 -0
  107. data/views/storage_volumes/index.xml.haml +13 -0
  108. data/views/storage_volumes/show.html.haml +20 -0
  109. data/views/storage_volumes/show.xml.haml +13 -0
  110. metadata +311 -0
@@ -0,0 +1,241 @@
1
+ #--------------------------------------------------------------------------- #
2
+ # Copyright 2002-2009, Distributed Systems Architecture Group, Universidad
3
+ # Complutense de Madrid (dsa-research.org)
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ #--------------------------------------------------------------------------- #
19
+
20
+ require 'deltacloud/base_driver'
21
+
22
+ require 'erb'
23
+ require 'rexml/document'
24
+
25
+ path = File.dirname(__FILE__)
26
+ $: << path
27
+
28
+ require 'occi_client'
29
+
30
+ module Deltacloud
31
+ module Drivers
32
+ module Opennebula
33
+
34
+ class OpennebulaDriver < Deltacloud::BaseDriver
35
+
36
+ ######################################################################
37
+ # Hardware profiles
38
+ ######################################################################
39
+
40
+ define_hardware_profile 'small'
41
+
42
+ define_hardware_profile 'medium'
43
+
44
+ define_hardware_profile 'large'
45
+
46
+ ######################################################################
47
+ # Realms
48
+ ######################################################################
49
+
50
+ (REALMS = [
51
+ Realm.new( {
52
+ :id=>'Any id',
53
+ :name=>'Any name',
54
+ :limit=>:unlimited,
55
+ :state=>'Any state',
56
+ } ),
57
+ ] ) unless defined?( REALMS )
58
+
59
+
60
+ def realms(credentials, opts=nil)
61
+ return REALMS if ( opts.nil? )
62
+ results = REALMS
63
+ results = filter_on( results, :id, opts )
64
+ results
65
+ end
66
+
67
+
68
+ ######################################################################
69
+ # Images
70
+ ######################################################################
71
+
72
+ def images(credentials, opts=nil)
73
+ occi_client = new_client(credentials)
74
+
75
+ images = []
76
+ imagesxml = occi_client.get_images
77
+
78
+ storage = REXML::Document.new(imagesxml)
79
+ storage.root.elements.each do |d|
80
+ id = d.attributes['href'].split("/").last
81
+
82
+ diskxml = occi_client.get_image(id)
83
+
84
+ images << convert_image(diskxml.to_s(), credentials)
85
+ end
86
+ images
87
+ end
88
+
89
+
90
+ ######################################################################
91
+ # Instances
92
+ ######################################################################
93
+
94
+ define_instance_states do
95
+ start.to( :pending ) .on( :create )
96
+
97
+ pending.to( :running ) .automatically
98
+
99
+ running.to( :stopped ) .on( :stop )
100
+
101
+ stopped.to( :running ) .on( :start )
102
+ stopped.to( :finish ) .on( :destroy )
103
+ end
104
+
105
+
106
+ def instances(credentials, opts=nil)
107
+ occi_client = new_client(credentials)
108
+
109
+ instances = []
110
+ instancesxml = occi_client.get_vms
111
+
112
+ computes = REXML::Document.new(instancesxml)
113
+ computes.root.elements.each do |d|
114
+ vm_id = d.attributes['href'].split("/").last
115
+
116
+ computexml = occi_client.get_vm(vm_id)
117
+
118
+ instances << convert_instance(computexml.to_s(), credentials)
119
+ end
120
+ instances = filter_on( instances, :id, opts )
121
+ instances = filter_on( instances, :state, opts )
122
+ instances
123
+ end
124
+
125
+
126
+ def create_instance(credentials, image_id, opts=nil)
127
+ occi_client = new_client(credentials)
128
+
129
+ hwp_id = opts[:hwp_id] || 'small'
130
+
131
+ instancexml = ERB.new(OCCI_VM).result(binding)
132
+ instancefile = "|echo '#{instancexml}'"
133
+
134
+ xmlvm = occi_client.post_vms(instancefile)
135
+
136
+ convert_instance(xmlvm.to_s(), credentials)
137
+ end
138
+
139
+
140
+ def start_instance(credentials, id)
141
+ occi_action(credentials, id, 'RESUME')
142
+ end
143
+
144
+
145
+ def stop_instance(credentials, id)
146
+ occi_action(credentials, id, 'STOPPED')
147
+ end
148
+
149
+
150
+ def destroy_instance(credentials, id)
151
+ occi_action(credentials, id, 'DONE')
152
+ end
153
+
154
+
155
+
156
+ private
157
+
158
+ def new_client(credentials)
159
+ OCCIClient::Client.new(nil, credentials.user, credentials.password, false)
160
+ end
161
+
162
+
163
+ def convert_image(diskxml, credentials)
164
+ disk = REXML::Document.new(diskxml)
165
+ diskhash = disk.root.elements
166
+
167
+ Image.new( {
168
+ :id=>diskhash['ID'].text,
169
+ :name=>diskhash['NAME'].text,
170
+ :description=>diskhash['NAME'].text,
171
+ :owner_id=>credentials.user,
172
+ :architecture=>'Any architecture',
173
+ } )
174
+ end
175
+
176
+
177
+ def convert_instance(computexml, credentials)
178
+ compute = REXML::Document.new(computexml)
179
+ computehash = compute.root.elements
180
+
181
+ imageid = computehash['STORAGE/DISK[@type="disk"]'].attributes['href'].split("/").last
182
+
183
+ state = (computehash['STATE'].text == 'ACTIVE') ? 'RUNNING' : computehash['STATE'].text
184
+
185
+ hwp_name = computehash['INSTANCE_TYPE'] || 'small'
186
+
187
+ networks = []
188
+ (computehash['NETWORK'].each do |n|
189
+ networks << n.attributes['ip']
190
+ end) unless computehash['NETWORK'].nil?
191
+
192
+ Instance.new( {
193
+ :id=>computehash['ID'].text,
194
+ :owner_id=>credentials.user,
195
+ :name=>computehash['NAME'].text,
196
+ :image_id=>imageid,
197
+ :instance_profile=>InstanceProfile.new(hwp_name),
198
+ :realm_id=>'Any realm',
199
+ :state=>state,
200
+ :public_addreses=>networks,
201
+ :private_addreses=>networks,
202
+ :actions=> instance_actions_for( state )
203
+ } )
204
+ end
205
+
206
+
207
+ def occi_action(credentials, id, strstate)
208
+ occi_client = new_client(credentials)
209
+
210
+ actionxml = ERB.new(OCCI_ACTION).result(binding)
211
+ actionfile = "|echo '#{actionxml}'"
212
+
213
+ xmlvm = occi_client.put_vm(actionfile)
214
+
215
+ convert_instance(xmlvm.to_s(), credentials)
216
+ end
217
+
218
+
219
+ (OCCI_VM = %q{
220
+ <COMPUTE>
221
+ <NAME><%=opts[:name]%></NAME>
222
+ <INSTANCE_TYPE><%= hwp_id %></INSTANCE_TYPE>
223
+ <STORAGE>
224
+ <DISK image="<%= image_id %>" dev="sda1" />
225
+ </STORAGE>
226
+ </COMPUTE>
227
+ }.gsub(/^ /, '') ) unless defined?( OCCI_VM )
228
+
229
+
230
+ (OCCI_ACTION = %q{
231
+ <COMPUTE>
232
+ <ID><%= id %></ID>
233
+ <STATE><%= strstate %></STATE>
234
+ </COMPUTE>
235
+ }.gsub(/^ /, '') ) unless defined?( OCCI_ACTION )
236
+
237
+ end
238
+
239
+ end
240
+ end
241
+ end
@@ -0,0 +1,129 @@
1
+ #
2
+ # Copyright (C) 2009 Red Hat, Inc.
3
+ #
4
+ # This library is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU Lesser General Public
6
+ # License as published by the Free Software Foundation; either
7
+ # version 2.1 of the License, or (at your option) any later version.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
+
18
+ require "net/http"
19
+ require "net/https"
20
+ require 'rubygems'
21
+ require 'json'
22
+
23
+ #
24
+ # author: Michael Neale
25
+ # TODO: catch generic errors in JSON response and throw (probably)
26
+ #
27
+ module Deltacloud
28
+ module Drivers
29
+ module Rackspace
30
+
31
+ class RackspaceClient
32
+
33
+ @@AUTH_API = URI.parse('https://auth.api.rackspacecloud.com/v1.0')
34
+
35
+ def initialize(username, auth_key)
36
+ http = Net::HTTP.new(@@AUTH_API.host,@@AUTH_API.port)
37
+ http.use_ssl = true
38
+ authed = http.get(@@AUTH_API.path, {'X-Auth-User' => username, 'X-Auth-Key' => auth_key})
39
+ if authed.is_a?(Net::HTTPUnauthorized)
40
+ raise Deltacloud::AuthException, "Failed to authenticate to Rackspace"
41
+ elsif !authed.is_a?(Net::HTTPSuccess)
42
+ backend_error!(resp)
43
+ end
44
+ @auth_token = authed.header['X-Auth-Token']
45
+ @service_uri = URI.parse(authed.header['X-Server-Management-Url'])
46
+ @service = Net::HTTP.new(@service_uri.host, @service_uri.port)
47
+ @service.use_ssl = true
48
+ end
49
+
50
+ def list_flavors
51
+ JSON.parse(get('/flavors/detail'))['flavors']
52
+ end
53
+
54
+ def list_images
55
+ JSON.parse(get('/images/detail'))['images']
56
+ end
57
+
58
+ def list_servers
59
+ JSON.parse(get('/servers/detail'))['servers']
60
+ end
61
+
62
+
63
+ def load_server_details( server_id )
64
+ JSON.parse(get("/servers/#{server_id}"))['server']
65
+ end
66
+
67
+
68
+ def start_server(image_id, flavor_id, name)
69
+ json = { :server => { :name => name,
70
+ :imageId => image_id.to_i,
71
+ :flavorId => flavor_id.to_i }}.to_json
72
+ # FIXME: The response has the root password in 'adminPass'; we somehow
73
+ # need to communicate this back since it's the only place where we can
74
+ # get it from
75
+ JSON.parse(post("/servers", json, headers).body)["server"]
76
+ end
77
+
78
+ def delete_server(server_id)
79
+ delete("/servers/#{server_id}", headers)
80
+ end
81
+
82
+ def reboot_server(server_id)
83
+ json = { :reboot => { :type => :SOFT }}.to_json
84
+ post("/servers/#{server_id}/action", json, headers)
85
+ end
86
+
87
+
88
+ def headers
89
+ {"Accept" => "application/json", "X-Auth-Token" => @auth_token, "Content-Type" => "application/json"}
90
+ end
91
+
92
+ private
93
+ def get(path)
94
+ resp = @service.get(@service_uri.path + path, {"Accept" => "application/json", "X-Auth-Token" => @auth_token})
95
+ unless resp.is_a?(Net::HTTPSuccess)
96
+ backend_error!(resp)
97
+ end
98
+ resp.body
99
+ end
100
+
101
+ def post(path, json, headers)
102
+ resp = @service.post(@service_uri.path + path, json, headers)
103
+ unless resp.is_a?(Net::HTTPSuccess)
104
+ backend_error!(resp)
105
+ end
106
+ resp
107
+ end
108
+
109
+ def delete(path, headers)
110
+ resp = @service.delete(@service_uri.path + path, headers)
111
+ unless resp.is_a?(Net::HTTPSuccess)
112
+ backend_error!(resp)
113
+ end
114
+ resp
115
+ end
116
+
117
+ def backend_error!(resp)
118
+ json = JSON.parse(resp.body)
119
+ cause = json.keys[0]
120
+ code = json[cause]["code"]
121
+ message = json[cause]["message"]
122
+ details = json[cause]["details"]
123
+ raise Deltacloud::BackendError.new(code, cause, message, details)
124
+ end
125
+
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,150 @@
1
+ #
2
+ # Copyright (C) 2009 Red Hat, Inc.
3
+ #
4
+ # This library is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU Lesser General Public
6
+ # License as published by the Free Software Foundation; either
7
+ # version 2.1 of the License, or (at your option) any later version.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
+
18
+ require 'deltacloud/base_driver'
19
+ require 'deltacloud/drivers/rackspace/rackspace_client'
20
+
21
+ module Deltacloud
22
+ module Drivers
23
+ module Rackspace
24
+
25
+ class RackspaceDriver < Deltacloud::BaseDriver
26
+
27
+ feature :instances, :user_name
28
+
29
+ def hardware_profiles(credentials, opts = nil)
30
+ racks = new_client( credentials )
31
+ results = racks.list_flavors.map do |flav|
32
+ HardwareProfile.new(flav["id"].to_s) do
33
+ architecture 'x86_64'
34
+ memory flav["ram"].to_i
35
+ storage flav["disk"].to_i
36
+ end
37
+ end
38
+ filter_hardware_profiles(results, opts)
39
+ end
40
+
41
+ def images(credentials, opts=nil)
42
+ racks = new_client( credentials )
43
+ results = racks.list_images.map do |img|
44
+ Image.new( {
45
+ :id=>img["id"].to_s,
46
+ :name=>img["name"],
47
+ :description => img["name"] + " " + img["status"] + "",
48
+ :owner_id=>"root",
49
+ :architecture=>'x86_64'
50
+ } )
51
+ end
52
+ results.sort_by{|e| [e.description]}
53
+ results = filter_on( results, :id, opts )
54
+ results
55
+ end
56
+
57
+ #rackspace does not at this stage have realms... its all US/TX, all the time (at least at time of writing)
58
+ def realms(credentials, opts=nil)
59
+ [Realm.new( {
60
+ :id=>"us",
61
+ :name=>"United States",
62
+ :state=> "AVAILABLE"
63
+ } )]
64
+ end
65
+
66
+ def reboot_instance(credentials, id)
67
+ racks = new_client(credentials)
68
+ racks.reboot_server(id)
69
+ end
70
+
71
+ def stop_instance(credentials, id)
72
+ destroy_instance(credentials, id)
73
+ end
74
+
75
+ def destroy_instance(credentials, id)
76
+ racks = new_client(credentials)
77
+ racks.delete_server(id)
78
+ end
79
+
80
+
81
+ #
82
+ # create instance. Default to flavor 1 - really need a name though...
83
+ # In rackspace, all flavors work with all images.
84
+ #
85
+ def create_instance(credentials, image_id, opts)
86
+ racks = new_client( credentials )
87
+ hwp_id = opts[:hwp_id] || 1
88
+ name = Time.now.to_s
89
+ if (opts[:name]) then name = opts[:name] end
90
+ convert_srv_to_instance(racks.start_server(image_id, hwp_id, name))
91
+ end
92
+
93
+ #
94
+ # Instances
95
+ #
96
+ def instances(credentials, opts=nil)
97
+ racks = new_client(credentials)
98
+ instances = []
99
+ if (opts.nil?)
100
+ instances = racks.list_servers.map do |srv|
101
+ convert_srv_to_instance(srv)
102
+ end
103
+ else
104
+ instances << convert_srv_to_instance(racks.load_server_details(opts[:id]))
105
+ end
106
+ instances = filter_on( instances, :id, opts )
107
+ instances = filter_on( instances, :state, opts )
108
+ instances
109
+ end
110
+
111
+
112
+ def convert_srv_to_instance(srv)
113
+ status = srv["status"] == "ACTIVE" ? "RUNNING" : "PENDING"
114
+ inst = Instance.new(:id => srv["id"].to_s,
115
+ :owner_id => "root",
116
+ :realm_id => "us")
117
+ inst.name = srv["name"]
118
+ inst.state = srv["status"] == "ACTIVE" ? "RUNNING" : "PENDING"
119
+ inst.actions = instance_actions_for(inst.state)
120
+ inst.image_id = srv["imageId"].to_s
121
+ inst.instance_profile = InstanceProfile.new(srv["flavorId"].to_s)
122
+ if srv["addresses"]
123
+ inst.public_addresses = srv["addresses"]["public"]
124
+ inst.private_addresses = srv["addresses"]["private"]
125
+ end
126
+ inst
127
+ end
128
+
129
+ def new_client(credentials)
130
+ RackspaceClient.new(credentials.user, credentials.password)
131
+ end
132
+
133
+ define_instance_states do
134
+ start.to( :pending ) .on( :create )
135
+
136
+ pending.to( :running ) .automatically
137
+
138
+ running.to( :running ) .on( :reboot )
139
+ running.to( :shutting_down ) .on( :stop )
140
+
141
+ shutting_down.to( :stopped ) .automatically
142
+
143
+ stopped.to( :finish ) .automatically
144
+ end
145
+
146
+ end
147
+
148
+ end
149
+ end
150
+ end