steamcannon-deltacloud-core 0.0.7.1-java

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 (152) hide show
  1. data/COPYING +176 -0
  2. data/Rakefile +106 -0
  3. data/bin/deltacloudd +120 -0
  4. data/config.ru +5 -0
  5. data/deltacloud.rb +20 -0
  6. data/lib/deltacloud/base_driver/base_driver.rb +259 -0
  7. data/lib/deltacloud/base_driver/features.rb +173 -0
  8. data/lib/deltacloud/base_driver/mock_driver.rb +58 -0
  9. data/lib/deltacloud/base_driver.rb +20 -0
  10. data/lib/deltacloud/drivers/azure/azure_driver.rb +127 -0
  11. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +580 -0
  12. data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +170 -0
  13. data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +50 -0
  14. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +343 -0
  15. data/lib/deltacloud/drivers/gogrid/test.rb +13 -0
  16. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob1.yml +5 -0
  17. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob2.yml +5 -0
  18. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob3.yml +5 -0
  19. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob4.yml +5 -0
  20. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob5.yml +5 -0
  21. data/lib/deltacloud/drivers/mock/data/buckets/bucket1.yml +2 -0
  22. data/lib/deltacloud/drivers/mock/data/buckets/bucket2.yml +2 -0
  23. data/lib/deltacloud/drivers/mock/data/images/img1.yml +3 -0
  24. data/lib/deltacloud/drivers/mock/data/images/img2.yml +3 -0
  25. data/lib/deltacloud/drivers/mock/data/images/img3.yml +3 -0
  26. data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +16 -0
  27. data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +9 -0
  28. data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +9 -0
  29. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap1.yml +4 -0
  30. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap2.yml +4 -0
  31. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap3.yml +4 -0
  32. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol1.yml +6 -0
  33. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol2.yml +6 -0
  34. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol3.yml +6 -0
  35. data/lib/deltacloud/drivers/mock/mock_driver.rb +356 -0
  36. data/lib/deltacloud/drivers/opennebula/cloud_client.rb +116 -0
  37. data/lib/deltacloud/drivers/opennebula/occi_client.rb +204 -0
  38. data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +241 -0
  39. data/lib/deltacloud/drivers/rackspace/rackspace_client.rb +130 -0
  40. data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +290 -0
  41. data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +258 -0
  42. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb +85 -0
  43. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +166 -0
  44. data/lib/deltacloud/drivers/terremark/terremark_driver.rb +295 -0
  45. data/lib/deltacloud/hardware_profile.rb +153 -0
  46. data/lib/deltacloud/helpers/application_helper.rb +122 -0
  47. data/lib/deltacloud/helpers/blob_stream.rb +51 -0
  48. data/lib/deltacloud/helpers/conversion_helper.rb +39 -0
  49. data/lib/deltacloud/helpers/hardware_profiles_helper.rb +35 -0
  50. data/lib/deltacloud/helpers.rb +5 -0
  51. data/lib/deltacloud/method_serializer.rb +85 -0
  52. data/lib/deltacloud/models/base_model.rb +59 -0
  53. data/lib/deltacloud/models/blob.rb +26 -0
  54. data/lib/deltacloud/models/bucket.rb +24 -0
  55. data/lib/deltacloud/models/image.rb +27 -0
  56. data/lib/deltacloud/models/instance.rb +38 -0
  57. data/lib/deltacloud/models/instance_profile.rb +48 -0
  58. data/lib/deltacloud/models/key.rb +35 -0
  59. data/lib/deltacloud/models/realm.rb +26 -0
  60. data/lib/deltacloud/models/storage_snapshot.rb +27 -0
  61. data/lib/deltacloud/models/storage_volume.rb +28 -0
  62. data/lib/deltacloud/state_machine.rb +84 -0
  63. data/lib/deltacloud/validation.rb +70 -0
  64. data/lib/drivers.rb +51 -0
  65. data/lib/sinatra/accept_media_types.rb +128 -0
  66. data/lib/sinatra/lazy_auth.rb +56 -0
  67. data/lib/sinatra/rabbit.rb +279 -0
  68. data/lib/sinatra/respond_to.rb +238 -0
  69. data/lib/sinatra/static_assets.rb +83 -0
  70. data/lib/sinatra/url_for.rb +53 -0
  71. data/public/favicon.ico +0 -0
  72. data/public/images/grid.png +0 -0
  73. data/public/images/logo-wide.png +0 -0
  74. data/public/images/rails.png +0 -0
  75. data/public/images/topbar-bg.png +0 -0
  76. data/public/javascripts/application.js +32 -0
  77. data/public/javascripts/jquery-1.4.2.min.js +154 -0
  78. data/public/stylesheets/compiled/application.css +613 -0
  79. data/public/stylesheets/compiled/ie.css +31 -0
  80. data/public/stylesheets/compiled/print.css +27 -0
  81. data/public/stylesheets/compiled/screen.css +456 -0
  82. data/server.rb +516 -0
  83. data/support/fedora/deltacloudd +68 -0
  84. data/support/fedora/rubygem-deltacloud-core.spec +91 -0
  85. data/tests/api_test.rb +37 -0
  86. data/tests/hardware_profiles_test.rb +120 -0
  87. data/tests/images_test.rb +111 -0
  88. data/tests/instance_states_test.rb +51 -0
  89. data/tests/instances_test.rb +222 -0
  90. data/tests/realms_test.rb +78 -0
  91. data/tests/url_for_test.rb +50 -0
  92. data/views/accounts/index.html.haml +11 -0
  93. data/views/accounts/show.html.haml +30 -0
  94. data/views/api/show.html.haml +15 -0
  95. data/views/api/show.xml.haml +5 -0
  96. data/views/blobs/show.html.haml +20 -0
  97. data/views/blobs/show.xml.haml +7 -0
  98. data/views/buckets/index.html.haml +33 -0
  99. data/views/buckets/index.xml.haml +10 -0
  100. data/views/buckets/new.html.haml +13 -0
  101. data/views/buckets/show.html.haml +19 -0
  102. data/views/buckets/show.xml.haml +8 -0
  103. data/views/docs/collection.html.haml +37 -0
  104. data/views/docs/collection.xml.haml +14 -0
  105. data/views/docs/index.html.haml +15 -0
  106. data/views/docs/index.xml.haml +5 -0
  107. data/views/docs/operation.html.haml +31 -0
  108. data/views/docs/operation.xml.haml +10 -0
  109. data/views/errors/auth_exception.html.haml +8 -0
  110. data/views/errors/auth_exception.xml.haml +2 -0
  111. data/views/errors/backend_error.html.haml +19 -0
  112. data/views/errors/backend_error.xml.haml +8 -0
  113. data/views/errors/not_found.html.haml +6 -0
  114. data/views/errors/not_found.xml.haml +2 -0
  115. data/views/errors/validation_failure.html.haml +11 -0
  116. data/views/errors/validation_failure.xml.haml +7 -0
  117. data/views/hardware_profiles/index.html.haml +25 -0
  118. data/views/hardware_profiles/index.xml.haml +4 -0
  119. data/views/hardware_profiles/show.html.haml +19 -0
  120. data/views/hardware_profiles/show.xml.haml +18 -0
  121. data/views/images/index.html.haml +30 -0
  122. data/views/images/index.xml.haml +8 -0
  123. data/views/images/show.html.haml +21 -0
  124. data/views/images/show.xml.haml +5 -0
  125. data/views/instance_states/show.html.haml +31 -0
  126. data/views/instance_states/show.png.erb +45 -0
  127. data/views/instance_states/show.xml.haml +8 -0
  128. data/views/instances/index.html.haml +30 -0
  129. data/views/instances/index.xml.haml +21 -0
  130. data/views/instances/new.html.haml +55 -0
  131. data/views/instances/show.html.haml +43 -0
  132. data/views/instances/show.xml.haml +49 -0
  133. data/views/keys/index.html.haml +26 -0
  134. data/views/keys/index.xml.haml +4 -0
  135. data/views/keys/new.html.haml +8 -0
  136. data/views/keys/show.html.haml +22 -0
  137. data/views/keys/show.xml.haml +20 -0
  138. data/views/layout.html.haml +26 -0
  139. data/views/realms/index.html.haml +29 -0
  140. data/views/realms/index.xml.haml +10 -0
  141. data/views/realms/show.html.haml +15 -0
  142. data/views/realms/show.xml.haml +9 -0
  143. data/views/root/index.html.haml +4 -0
  144. data/views/storage_snapshots/index.html.haml +20 -0
  145. data/views/storage_snapshots/index.xml.haml +9 -0
  146. data/views/storage_snapshots/show.html.haml +14 -0
  147. data/views/storage_snapshots/show.xml.haml +7 -0
  148. data/views/storage_volumes/index.html.haml +21 -0
  149. data/views/storage_volumes/index.xml.haml +23 -0
  150. data/views/storage_volumes/show.html.haml +20 -0
  151. data/views/storage_volumes/show.xml.haml +24 -0
  152. metadata +367 -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" : "STOPPED"
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,130 @@
1
+ #
2
+ # Copyright (C) 2009 Red Hat, Inc.
3
+ #
4
+ # Licensed to the Apache Software Foundation (ASF) under one or more
5
+ # contributor license agreements. See the NOTICE file distributed with
6
+ # this work for additional information regarding copyright ownership. The
7
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance with the
9
+ # License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
+ # License for the specific language governing permissions and limitations
17
+ # under the License.
18
+
19
+ require "net/http"
20
+ require "net/https"
21
+ require 'rubygems'
22
+ require 'json'
23
+
24
+ #
25
+ # author: Michael Neale
26
+ # TODO: catch generic errors in JSON response and throw (probably)
27
+ #
28
+ module Deltacloud
29
+ module Drivers
30
+ module Rackspace
31
+
32
+ class RackspaceClient
33
+
34
+ @@AUTH_API = URI.parse('https://auth.api.rackspacecloud.com/v1.0')
35
+
36
+ def initialize(username, auth_key)
37
+ http = Net::HTTP.new(@@AUTH_API.host,@@AUTH_API.port)
38
+ http.use_ssl = true
39
+ authed = http.get(@@AUTH_API.path, {'X-Auth-User' => username, 'X-Auth-Key' => auth_key})
40
+ if authed.is_a?(Net::HTTPUnauthorized)
41
+ raise Deltacloud::AuthException, "Failed to authenticate to Rackspace"
42
+ elsif !authed.is_a?(Net::HTTPSuccess)
43
+ backend_error!(resp)
44
+ end
45
+ @auth_token = authed.header['X-Auth-Token']
46
+ @service_uri = URI.parse(authed.header['X-Server-Management-Url'])
47
+ @service = Net::HTTP.new(@service_uri.host, @service_uri.port)
48
+ @service.use_ssl = true
49
+ end
50
+
51
+ def list_flavors
52
+ JSON.parse(get('/flavors/detail'))['flavors']
53
+ end
54
+
55
+ def list_images
56
+ JSON.parse(get('/images/detail'))['images']
57
+ end
58
+
59
+ def list_servers
60
+ JSON.parse(get('/servers/detail'))['servers']
61
+ end
62
+
63
+
64
+ def load_server_details( server_id )
65
+ JSON.parse(get("/servers/#{server_id}"))['server']
66
+ end
67
+
68
+
69
+ def start_server(image_id, flavor_id, name)
70
+ json = { :server => { :name => name,
71
+ :imageId => image_id.to_i,
72
+ :flavorId => flavor_id.to_i }}.to_json
73
+ # FIXME: The response has the root password in 'adminPass'; we somehow
74
+ # need to communicate this back since it's the only place where we can
75
+ # get it from
76
+ JSON.parse(post("/servers", json, headers).body)["server"]
77
+ end
78
+
79
+ def delete_server(server_id)
80
+ delete("/servers/#{server_id}", headers)
81
+ end
82
+
83
+ def reboot_server(server_id)
84
+ json = { :reboot => { :type => :SOFT }}.to_json
85
+ post("/servers/#{server_id}/action", json, headers)
86
+ end
87
+
88
+
89
+ def headers
90
+ {"Accept" => "application/json", "X-Auth-Token" => @auth_token, "Content-Type" => "application/json"}
91
+ end
92
+
93
+ private
94
+ def get(path)
95
+ resp = @service.get(@service_uri.path + path, {"Accept" => "application/json", "X-Auth-Token" => @auth_token})
96
+ unless resp.is_a?(Net::HTTPSuccess)
97
+ backend_error!(resp)
98
+ end
99
+ resp.body
100
+ end
101
+
102
+ def post(path, json, headers)
103
+ resp = @service.post(@service_uri.path + path, json, headers)
104
+ unless resp.is_a?(Net::HTTPSuccess)
105
+ backend_error!(resp)
106
+ end
107
+ resp
108
+ end
109
+
110
+ def delete(path, headers)
111
+ resp = @service.delete(@service_uri.path + path, headers)
112
+ unless resp.is_a?(Net::HTTPSuccess)
113
+ backend_error!(resp)
114
+ end
115
+ resp
116
+ end
117
+
118
+ def backend_error!(resp)
119
+ json = JSON.parse(resp.body)
120
+ cause = json.keys[0]
121
+ code = json[cause]["code"]
122
+ message = json[cause]["message"]
123
+ details = json[cause]["details"]
124
+ raise Deltacloud::BackendError.new(code, cause, message, details)
125
+ end
126
+
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,290 @@
1
+ #
2
+ # Copyright (C) 2009 Red Hat, Inc.
3
+ #
4
+ # Licensed to the Apache Software Foundation (ASF) under one or more
5
+ # contributor license agreements. See the NOTICE file distributed with
6
+ # this work for additional information regarding copyright ownership. The
7
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance with the
9
+ # License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
+ # License for the specific language governing permissions and limitations
17
+ # under the License.
18
+
19
+ require 'deltacloud/base_driver'
20
+ require 'deltacloud/drivers/rackspace/rackspace_client'
21
+ require 'cloudfiles'
22
+
23
+ module Deltacloud
24
+ module Drivers
25
+ module Rackspace
26
+
27
+ class RackspaceDriver < Deltacloud::BaseDriver
28
+
29
+ feature :instances, :user_name
30
+
31
+ def supported_collections
32
+ DEFAULT_COLLECTIONS + [ :buckets ]
33
+ end
34
+
35
+ def hardware_profiles(credentials, opts = nil)
36
+ racks = new_client( credentials )
37
+ results=""
38
+ safely do
39
+ results = racks.list_flavors.map do |flav|
40
+ HardwareProfile.new(flav["id"].to_s) do
41
+ architecture 'x86_64'
42
+ memory flav["ram"].to_i
43
+ storage flav["disk"].to_i
44
+ end
45
+ end
46
+ end
47
+ filter_hardware_profiles(results, opts)
48
+ end
49
+
50
+ def images(credentials, opts=nil)
51
+ racks = new_client( credentials )
52
+ results=""
53
+ safely do
54
+ results = racks.list_images.map do |img|
55
+ Image.new( {
56
+ :id=>img["id"].to_s,
57
+ :name=>img["name"],
58
+ :description => img["name"] + " " + img["status"] + "",
59
+ :owner_id=>"root",
60
+ :architecture=>'x86_64'
61
+ } )
62
+ end
63
+ end
64
+ results.sort_by{|e| [e.description]}
65
+ results = filter_on( results, :id, opts )
66
+ results
67
+ end
68
+
69
+ #rackspace does not at this stage have realms... its all US/TX, all the time (at least at time of writing)
70
+ def realms(credentials, opts=nil)
71
+ [Realm.new( {
72
+ :id=>"us",
73
+ :name=>"United States",
74
+ :state=> "AVAILABLE"
75
+ } )]
76
+ end
77
+
78
+ def reboot_instance(credentials, id)
79
+ racks = new_client(credentials)
80
+ safely do
81
+ racks.reboot_server(id)
82
+ end
83
+ Instance.new( {
84
+ :id => id,
85
+ :state => "RUNNING",
86
+ :actions => instance_actions_for( "RUNNING" ),
87
+ } )
88
+ end
89
+
90
+ def stop_instance(credentials, id)
91
+ destroy_instance(credentials, id)
92
+ end
93
+
94
+ def destroy_instance(credentials, id)
95
+ racks = new_client(credentials)
96
+ safely do
97
+ racks.delete_server(id)
98
+ end
99
+ Instance.new( {
100
+ :id => id,
101
+ :state => "STOPPED",
102
+ :actions => instance_actions_for( "STOPPED" ),
103
+ } )
104
+ end
105
+
106
+
107
+ #
108
+ # create instance. Default to flavor 1 - really need a name though...
109
+ # In rackspace, all flavors work with all images.
110
+ #
111
+ def create_instance(credentials, image_id, opts)
112
+ racks = new_client( credentials )
113
+ hwp_id = opts[:hwp_id] || 1
114
+ name = Time.now.to_s
115
+ if (opts[:name]) then name = opts[:name] end
116
+ safely do
117
+ return convert_srv_to_instance(racks.start_server(image_id, hwp_id, name))
118
+ end
119
+ end
120
+
121
+ #
122
+ # Instances
123
+ #
124
+ def instances(credentials, opts=nil)
125
+ racks = new_client(credentials)
126
+ instances = []
127
+ safely do
128
+ if (opts.nil?)
129
+ instances = racks.list_servers.map do |srv|
130
+ convert_srv_to_instance(srv)
131
+ end
132
+ else
133
+ instances << convert_srv_to_instance(racks.load_server_details(opts[:id]))
134
+ end
135
+ end
136
+ instances = filter_on( instances, :id, opts )
137
+ instances = filter_on( instances, :state, opts )
138
+ instances
139
+ end
140
+
141
+ def valid_credentials?(credentials)
142
+ begin
143
+ new_client(credentials)
144
+ rescue
145
+ return false
146
+ end
147
+ true
148
+ end
149
+
150
+
151
+
152
+
153
+ define_instance_states do
154
+ start.to( :pending ) .on( :create )
155
+
156
+ pending.to( :running ) .automatically
157
+
158
+ running.to( :running ) .on( :reboot )
159
+ running.to( :shutting_down ) .on( :stop )
160
+
161
+ shutting_down.to( :stopped ) .automatically
162
+
163
+ stopped.to( :finish ) .automatically
164
+ end
165
+
166
+ #--
167
+ # Buckets
168
+ #--
169
+ def buckets(credentials, opts)
170
+ bucket_list = []
171
+ cf = cloudfiles_client(credentials)
172
+ safely do
173
+ cf.containers.each do |container_name|
174
+ current = cf.container(container_name)
175
+ bucket_list << convert_container(current)
176
+ end #containers.each
177
+ end #safely
178
+ bucket_list = filter_on(bucket_list, :id, opts)
179
+ bucket_list
180
+ end
181
+
182
+ #--
183
+ # Create Bucket
184
+ #--
185
+ def create_bucket(credentials, name, opts)
186
+ bucket = nil
187
+ cf = cloudfiles_client(credentials)
188
+ safely do
189
+ new_bucket = cf.create_container(name)
190
+ bucket = convert_container(new_bucket)
191
+ end
192
+ bucket
193
+ end
194
+
195
+ #--
196
+ # Delete Bucket
197
+ #--
198
+ def delete_bucket(credentials, name, opts)
199
+ cf = cloudfiles_client(credentials)
200
+ safely do
201
+ cf.delete_container(name)
202
+ end
203
+ end
204
+
205
+ #--
206
+ # Blobs
207
+ #--
208
+ def blobs(credentials, opts)
209
+ cf = cloudfiles_client(credentials)
210
+ blobs = []
211
+ safely do
212
+ cf_container = cf.container(opts['bucket'])
213
+ cf_container.objects.each do |object_name|
214
+ blobs << convert_object(cf_container.object(object_name))
215
+ end
216
+ end
217
+ blobs = filter_on(blobs, :id, opts)
218
+ blobs
219
+ end
220
+
221
+ #-
222
+ # Blob data
223
+ #-
224
+ def blob_data(credentials, bucket_id, blob_id, opts)
225
+ cf = cloudfiles_client(credentials)
226
+ cf.container(bucket_id).object(blob_id).data_stream do |chunk|
227
+ yield chunk
228
+ end
229
+ end
230
+
231
+ private
232
+
233
+ def convert_srv_to_instance(srv)
234
+ inst = Instance.new(:id => srv["id"].to_s,
235
+ :owner_id => "root",
236
+ :realm_id => "us")
237
+ inst.name = srv["name"]
238
+ inst.state = srv["status"] == "ACTIVE" ? "RUNNING" : "PENDING"
239
+ inst.actions = instance_actions_for(inst.state)
240
+ inst.image_id = srv["imageId"].to_s
241
+ inst.instance_profile = InstanceProfile.new(srv["flavorId"].to_s)
242
+ if srv["addresses"]
243
+ inst.public_addresses = srv["addresses"]["public"]
244
+ inst.private_addresses = srv["addresses"]["private"]
245
+ end
246
+ inst
247
+ end
248
+
249
+ def new_client(credentials)
250
+ safely do
251
+ return RackspaceClient.new(credentials.user, credentials.password)
252
+ end
253
+ end
254
+
255
+ def convert_container(cf_container)
256
+ Bucket.new({ :id => cf_container.name,
257
+ :name => cf_container.name,
258
+ :size => cf_container.count,
259
+ :blob_list => cf_container.objects
260
+ })
261
+ end
262
+
263
+ def convert_object(cf_object)
264
+ Blob.new({ :id => cf_object.name,
265
+ :bucket => cf_object.container.name,
266
+ :content_length => cf_object.bytes,
267
+ :content_type => cf_object.content_type,
268
+ :last_modified => cf_object.last_modified
269
+ })
270
+ end
271
+
272
+ def cloudfiles_client(credentials)
273
+ safely do
274
+ CloudFiles::Connection.new(credentials.user, credentials.password)
275
+ end
276
+ end
277
+
278
+ def safely(&block)
279
+ begin
280
+ block.call
281
+ rescue Exception => e
282
+ raise Deltacloud::BackendError.new(500, e.class.to_s, e.message, e.backtrace)
283
+ end
284
+ end
285
+
286
+ end
287
+
288
+ end
289
+ end
290
+ end