steamcannon-deltacloud-core 0.0.7.1

Sign up to get free protection for your applications and to get access to all the features.
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 +409 -0
@@ -0,0 +1,6 @@
1
+ :owner_id: fedoraproject
2
+ :created: Thu Jul 30 14:35:11 UTC 2009
3
+ :state: AVAILABLE
4
+ :capacity: 1
5
+ :device:
6
+ :instance_id:
@@ -0,0 +1,6 @@
1
+ :owner_id: mockuser
2
+ :created: Thu Jul 30 14:35:11 UTC 2009
3
+ :state: AVAILABLE
4
+ :capacity: 1
5
+ :device:
6
+ :instance_id:
@@ -0,0 +1,6 @@
1
+ :owner_id: mockuser
2
+ :created: Thu Jul 30 14:35:11 UTC 2009
3
+ :state: IN-USE
4
+ :capacity: 1
5
+ :device: /dev/sda1
6
+ :instance_id: inst1
@@ -0,0 +1,356 @@
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
+
20
+ require 'deltacloud/base_driver'
21
+ require 'yaml'
22
+
23
+ module Deltacloud
24
+ module Drivers
25
+ module Mock
26
+ class MockDriver < Deltacloud::BaseDriver
27
+
28
+ def supported_collections
29
+ DEFAULT_COLLECTIONS + [ :buckets ]
30
+ end
31
+
32
+ ( REALMS = [
33
+ Realm.new({
34
+ :id=>'us',
35
+ :name=>'United States',
36
+ :limit=>:unlimited,
37
+ :state=>'AVAILABLE',
38
+ }),
39
+ Realm.new({
40
+ :id=>'eu',
41
+ :name=>'Europe',
42
+ :limit=>:unlimited,
43
+ :state=>'AVAILABLE',
44
+ }),
45
+ ] ) unless defined?( REALMS )
46
+
47
+ define_hardware_profile('m1-small') do
48
+ cpu 1
49
+ memory 1.7 * 1024
50
+ storage 160
51
+ architecture 'i386'
52
+ end
53
+
54
+ define_hardware_profile('m1-large') do
55
+ cpu 2
56
+ memory (7.5*1024 .. 15*1024), :default => 10 * 1024
57
+ storage [ 850, 1024 ]
58
+ architecture 'x86_64'
59
+ end
60
+
61
+ define_hardware_profile('m1-xlarge') do
62
+ cpu 4
63
+ memory (12*1024 .. 32*1024)
64
+ storage [ 1024, 2048, 4096 ]
65
+ architecture 'x86_64'
66
+ end
67
+
68
+ # Some clouds tell us nothing about hardware profiles (e.g., OpenNebula)
69
+ define_hardware_profile 'opaque'
70
+
71
+ define_instance_states do
72
+ start.to( :pending ) .on( :create )
73
+
74
+ pending.to( :running ) .automatically
75
+
76
+ running.to( :running ) .on( :reboot )
77
+ running.to( :stopped ) .on( :stop )
78
+
79
+ stopped.to( :running ) .on( :start )
80
+ stopped.to( :finish ) .on( :destroy )
81
+ end
82
+
83
+ feature :instances, :user_name
84
+
85
+ def initialize
86
+ if ENV["DELTACLOUD_MOCK_STORAGE"]
87
+ @storage_root = ENV["DELTACLOUD_MOCK_STORAGE"]
88
+ elsif ENV["USER"]
89
+ @storage_root = File::join("/var/tmp", "deltacloud-mock-#{ENV["USER"]}")
90
+ else
91
+ raise "Please set either the DELTACLOUD_MOCK_STORAGE or USER environment variable"
92
+ end
93
+ if ! File::directory?(@storage_root)
94
+ FileUtils::rm_rf(@storage_root)
95
+ FileUtils::mkdir_p(@storage_root)
96
+ data = Dir::glob(File::join(File::dirname(__FILE__), "data", "*"))
97
+ FileUtils::cp_r(data, @storage_root)
98
+ end
99
+ end
100
+
101
+ def realms(credentials, opts=nil)
102
+ return REALMS if ( opts.nil? )
103
+ results = REALMS
104
+ results = filter_on( results, :id, opts )
105
+ results
106
+ end
107
+
108
+ #
109
+ # Images
110
+ #
111
+ def images(credentials, opts=nil )
112
+ check_credentials( credentials )
113
+ images = []
114
+ Dir[ "#{@storage_root}/images/*.yml" ].each do |image_file|
115
+ image = YAML.load( File.read( image_file ) )
116
+ image[:id] = File.basename( image_file, ".yml" )
117
+ image[:name] = image[:description]
118
+ images << Image.new( image )
119
+ end
120
+ images = filter_on( images, :id, opts )
121
+ images = filter_on( images, :architecture, opts )
122
+ if ( opts && opts[:owner_id] == 'self' )
123
+ images = images.select{|e| e.owner_id == credentials.user }
124
+ else
125
+ images = filter_on( images, :owner_id, opts )
126
+ end
127
+ images.sort_by{|e| [e.owner_id,e.description]}
128
+ end
129
+
130
+ #
131
+ # Instances
132
+ #
133
+
134
+ def instances(credentials, opts=nil)
135
+ check_credentials( credentials )
136
+ instances = []
137
+ Dir[ "#{@storage_root}/instances/*.yml" ].each do |instance_file|
138
+ instance = YAML.load( File.read( instance_file ) )
139
+ if ( instance[:owner_id] == credentials.user )
140
+ instance[:id] = File.basename( instance_file, ".yml" )
141
+ instance[:actions] = instance_actions_for( instance[:state] )
142
+ instances << Instance.new( instance )
143
+ end
144
+ end
145
+ instances = filter_on( instances, :id, opts )
146
+ instances = filter_on( instances, :state, opts )
147
+ instances
148
+ end
149
+
150
+ def create_instance(credentials, image_id, opts)
151
+ check_credentials( credentials )
152
+ ids = Dir[ "#{@storage_root}/instances/*.yml" ].collect{|e| File.basename( e, ".yml" )}
153
+
154
+ count = 0
155
+ while true
156
+ next_id = "inst" + count.to_s
157
+ if not ids.include?(next_id)
158
+ break
159
+ end
160
+ count = count + 1
161
+ end
162
+
163
+ realm_id = opts[:realm_id]
164
+ if ( realm_id.nil? )
165
+ realm = realms(credentials).first
166
+ ( realm_id = realm.id ) if realm
167
+ end
168
+
169
+ hwp = find_hardware_profile(credentials, opts[:hwp_id], image_id)
170
+
171
+ name = opts[:name] || "i-#{Time.now.to_i}"
172
+
173
+ instance = {
174
+ :name=>name,
175
+ :state=>'RUNNING',
176
+ :image_id=>image_id,
177
+ :owner_id=>credentials.user,
178
+ :public_addresses=>["#{image_id}.#{next_id}.public.com"],
179
+ :private_addresses=>["#{image_id}.#{next_id}.private.com"],
180
+ :instance_profile => InstanceProfile.new(hwp.name, opts),
181
+ :realm_id=>realm_id,
182
+ :actions=>instance_actions_for( 'RUNNING' )
183
+ }
184
+ File.open( "#{@storage_root}/instances/#{next_id}.yml", 'w' ) {|f|
185
+ YAML.dump( instance, f )
186
+ }
187
+ instance[:id] = next_id
188
+ Instance.new( instance )
189
+ end
190
+
191
+ def update_instance_state(credentials, id, state)
192
+ instance_file = "#{@storage_root}/instances/#{id}.yml"
193
+ instance_yml = YAML.load( File.read( instance_file ) )
194
+ instance_yml[:id] = id
195
+ instance_yml[:state] = state
196
+ instance_yml[:actions] = instance_actions_for( instance_yml[:state] )
197
+ File.open( instance_file, 'w' ) do |f|
198
+ f << YAML.dump( instance_yml )
199
+ end
200
+ Instance.new( instance_yml )
201
+ end
202
+
203
+ def start_instance(credentials, id)
204
+ update_instance_state(credentials, id, 'RUNNING')
205
+ end
206
+
207
+ def reboot_instance(credentials, id)
208
+ update_instance_state(credentials, id, 'RUNNING')
209
+ end
210
+
211
+ def stop_instance(credentials, id)
212
+ update_instance_state(credentials, id, 'STOPPED')
213
+ end
214
+
215
+
216
+ def destroy_instance(credentials, id)
217
+ check_credentials( credentials )
218
+ FileUtils.rm( "#{@storage_root}/instances/#{id}.yml" )
219
+ end
220
+
221
+ #
222
+ # Storage Volumes
223
+ #
224
+
225
+ def storage_volumes(credentials, opts=nil)
226
+ check_credentials( credentials )
227
+ volumes = []
228
+ Dir[ "#{@storage_root}/storage_volumes/*.yml" ].each do |storage_volume_file|
229
+ storage_volume = YAML.load( File.read( storage_volume_file ) )
230
+ if ( storage_volume[:owner_id] == credentials.user )
231
+ storage_volume[:id] = File.basename( storage_volume_file, ".yml" )
232
+ volumes << StorageVolume.new( storage_volume )
233
+ end
234
+ end
235
+ volumes = filter_on( volumes, :id, opts )
236
+ volumes
237
+ end
238
+
239
+ #
240
+ # Storage Snapshots
241
+ #
242
+
243
+ def storage_snapshots(credentials, opts=nil)
244
+ check_credentials( credentials )
245
+ snapshots = []
246
+ Dir[ "#{@storage_root}/storage_snapshots/*.yml" ].each do |storage_snapshot_file|
247
+ storage_snapshot = YAML.load( File.read( storage_snapshot_file ) )
248
+ if ( storage_snapshot[:owner_id] == credentials.user )
249
+ storage_snapshot[:id] = File.basename( storage_snapshot_file, ".yml" )
250
+ snapshots << StorageSnapshot.new( storage_snapshot )
251
+ end
252
+ end
253
+ snapshots = filter_on( snapshots, :id, opts )
254
+ snapshots
255
+ end
256
+
257
+ #--
258
+ # Buckets
259
+ #--
260
+ def buckets(credentials, opts=nil)
261
+ check_credentials(credentials)
262
+ buckets=[]
263
+ Dir[ "#{@storage_root}/buckets/*.yml" ].each do |bucket_file|
264
+ bucket = YAML.load( File.read( bucket_file ) )
265
+ bucket[:id] = File.basename( bucket_file, ".yml" )
266
+ bucket[:name] = bucket[:id]
267
+ buckets << Bucket.new( bucket )
268
+ end
269
+ buckets = filter_on( buckets, :id, opts )
270
+ buckets
271
+ end
272
+
273
+ #--
274
+ # Create bucket
275
+ #--
276
+ def create_bucket(credentials, name, opts=nil)
277
+ check_credentials(credentials)
278
+ bucket = {
279
+ :name=>name,
280
+ :size=>'0',
281
+ :blob_list=>[]
282
+ }
283
+ File.open( "#{@storage_root}/buckets/#{name}.yml", 'w' ) {|b| YAML.dump( bucket, b )}
284
+ Bucket.new(bucket)
285
+ end
286
+
287
+ #--
288
+ # Delete bucket
289
+ #--
290
+ def delete_bucket(credentials, name, opts=nil)
291
+ bucket = bucket(credentials, {:id => name})
292
+ unless (bucket.size == "0")
293
+ raise Deltacloud::BackendError.new(403, self.class.to_s, "bucket-not-empty", "delete operation not valid for non-empty bucket")
294
+ end
295
+ safely do
296
+ File.delete("#{@storage_root}/buckets/#{name}.yml")
297
+ end
298
+ end
299
+
300
+ #--
301
+ # Blobs
302
+ #--
303
+ def blobs(credentials, opts = nil)
304
+ check_credentials(credentials)
305
+ blobs=[]
306
+ Dir[ "#{@storage_root}/buckets/blobs/*.yml" ].each do |blob_file|
307
+ blob = YAML.load( File.read( blob_file ) )
308
+ blob[:id] = File.basename( blob_file, ".yml" )
309
+ blob[:name] = blob[:id]
310
+ blobs << Blob.new( blob )
311
+ end
312
+ blobs = filter_on( blobs, :id, opts )
313
+ blobs
314
+ end
315
+
316
+ #--
317
+ # Blob content
318
+ #--
319
+ def blob_data(credentials, bucket_id, blob_id, opts = nil)
320
+ check_credentials(credentials)
321
+ blob=nil
322
+ Dir[ "#{@storage_root}/buckets/blobs/*.yml" ].each do |blob_file|
323
+ if File.basename(blob_file, ".yml") == blob_id
324
+ blob = YAML.load(File.read(blob_file))
325
+ blob[:content].each {|part| yield part}
326
+ end
327
+ end
328
+ end
329
+
330
+ def valid_credentials?(credentials)
331
+ begin
332
+ check_credentials(credentials)
333
+ return true
334
+ rescue Deltacloud::AuthException
335
+ end
336
+ return false
337
+ end
338
+
339
+ private
340
+
341
+ def check_credentials(credentials)
342
+ if ( credentials.user != 'mockuser' )
343
+ raise Deltacloud::AuthException.new
344
+ end
345
+
346
+ if ( credentials.password != 'mockpassword' )
347
+ raise Deltacloud::AuthException.new
348
+ end
349
+ end
350
+
351
+
352
+ end
353
+
354
+ end
355
+ end
356
+ end
@@ -0,0 +1,116 @@
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 'rubygems'
21
+ require 'uri'
22
+
23
+ require 'net/https'
24
+
25
+ begin
26
+ require 'net/http/post/multipart'
27
+ rescue LoadError
28
+ end
29
+
30
+ ###############################################################################
31
+ # The CloudClient module contains general functionality to implement a
32
+ # Cloud Client
33
+ ###############################################################################
34
+ module CloudClient
35
+ # #########################################################################
36
+ # Default location for the authentication file
37
+ # #########################################################################
38
+ DEFAULT_AUTH_FILE = ENV["HOME"]+"/.one/one_auth"
39
+
40
+ # #########################################################################
41
+ # Gets authorization credentials from ONE_AUTH or default
42
+ # auth file.
43
+ #
44
+ # Raises an error if authorization is not found
45
+ # #########################################################################
46
+ def self.get_one_auth
47
+ if ENV["ONE_AUTH"] and !ENV["ONE_AUTH"].empty? and
48
+ File.file?(ENV["ONE_AUTH"])
49
+ one_auth=File.read(ENV["ONE_AUTH"]).strip.split(':')
50
+ elsif File.file?(DEFAULT_AUTH_FILE)
51
+ one_auth=File.read(DEFAULT_AUTH_FILE).strip.split(':')
52
+ else
53
+ raise "No authorization data present"
54
+ end
55
+
56
+ raise "Authorization data malformed" if one_auth.length < 2
57
+
58
+ one_auth
59
+ end
60
+
61
+ # #########################################################################
62
+ # Starts an http connection and calls the block provided. SSL flag
63
+ # is set if needed.
64
+ # #########################################################################
65
+ def self.http_start(url, &block)
66
+ http = Net::HTTP.new(url.host, url.port)
67
+ if url.scheme=='https'
68
+ http.use_ssl = true
69
+ http.verify_mode=OpenSSL::SSL::VERIFY_NONE
70
+ end
71
+
72
+ begin
73
+ http.start do |connection|
74
+ block.call(connection)
75
+ end
76
+ rescue Errno::ECONNREFUSED => e
77
+ str = "Error connecting to server (#{e.to_s})."
78
+ str << "Server: #{url.host}:#{url.port}"
79
+
80
+ return CloudClient::Error.new(str)
81
+ end
82
+ end
83
+
84
+ # #########################################################################
85
+ # The Error Class represents a generic error in the Cloud Client
86
+ # library. It contains a readable representation of the error.
87
+ # #########################################################################
88
+ class Error
89
+ attr_reader :message
90
+
91
+ # +message+ a description of the error
92
+ def initialize(message=nil)
93
+ @message=message
94
+ end
95
+
96
+ def to_s()
97
+ @message
98
+ end
99
+ end
100
+
101
+ # #########################################################################
102
+ # Returns true if the object returned by a method of the OpenNebula
103
+ # library is an Error
104
+ # #########################################################################
105
+ def self.is_error?(value)
106
+ value.class==CloudClient::Error
107
+ end
108
+ end
109
+
110
+ # Command line help functions
111
+ module CloudCLI
112
+ # Returns the command name
113
+ def cmd_name
114
+ File.basename($0)
115
+ end
116
+ end
@@ -0,0 +1,204 @@
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 'rubygems'
21
+ require 'uri'
22
+ require 'rexml/document'
23
+
24
+ require 'deltacloud/drivers/opennebula/cloud_client'
25
+
26
+
27
+ module OCCIClient
28
+
29
+ #####################################################################
30
+ # Client Library to interface with the OpenNebula OCCI Service
31
+ #####################################################################
32
+ class Client
33
+
34
+ ######################################################################
35
+ # Initialize client library
36
+ ######################################################################
37
+ def initialize(endpoint_str=nil, user=nil, pass=nil, debug_flag=true)
38
+ @debug = debug_flag
39
+
40
+ # Server location
41
+ if endpoint_str
42
+ @endpoint = endpoint_str
43
+ elsif ENV["OCCI_URL"]
44
+ @endpoint = ENV["OCCI_URL"]
45
+ else
46
+ @endpoint = "http://localhost:4567"
47
+ end
48
+
49
+ # Autentication
50
+ if user && pass
51
+ @occiauth = [user, pass]
52
+ else
53
+ @occiauth = CloudClient::get_one_auth
54
+ end
55
+
56
+ if !@occiauth
57
+ raise "No authorization data present"
58
+ end
59
+
60
+ @occiauth[1] = Digest::SHA1.hexdigest(@occiauth[1])
61
+ end
62
+
63
+ #################################
64
+ # Pool Resource Request Methods #
65
+ #################################
66
+
67
+ ######################################################################
68
+ # Post a new VM to the VM Pool
69
+ # :instance_type
70
+ # :xmlfile
71
+ ######################################################################
72
+ def post_vms(xmlfile)
73
+ xml=File.read(xmlfile)
74
+
75
+ url = URI.parse(@endpoint+"/compute")
76
+
77
+ req = Net::HTTP::Post.new(url.path)
78
+ req.body=xml
79
+
80
+ req.basic_auth @occiauth[0], @occiauth[1]
81
+
82
+ res = CloudClient::http_start(url) do |http|
83
+ http.request(req)
84
+ end
85
+
86
+ if CloudClient::is_error?(res)
87
+ return res
88
+ else
89
+ return res.body
90
+ end
91
+ end
92
+
93
+ ######################################################################
94
+ # Retieves the pool of Virtual Machines
95
+ ######################################################################
96
+ def get_vms
97
+ url = URI.parse(@endpoint+"/compute")
98
+ req = Net::HTTP::Get.new(url.path)
99
+
100
+ req.basic_auth @occiauth[0], @occiauth[1]
101
+
102
+ res = CloudClient::http_start(url) {|http|
103
+ http.request(req)
104
+ }
105
+
106
+ if CloudClient::is_error?(res)
107
+ return res
108
+ else
109
+ return res.body
110
+ end
111
+ end
112
+
113
+ ######################################################################
114
+ # Retieves the pool of Images owned by the user
115
+ ######################################################################
116
+ def get_images
117
+ url = URI.parse(@endpoint+"/storage")
118
+ req = Net::HTTP::Get.new(url.path)
119
+
120
+ req.basic_auth @occiauth[0], @occiauth[1]
121
+
122
+ res = CloudClient::http_start(url) {|http|
123
+ http.request(req)
124
+ }
125
+
126
+ if CloudClient::is_error?(res)
127
+ return res
128
+ else
129
+ return res.body
130
+ end
131
+ end
132
+
133
+ ####################################
134
+ # Entity Resource Request Methods #
135
+ ####################################
136
+
137
+ ######################################################################
138
+ # :id VM identifier
139
+ ######################################################################
140
+ def get_vm(id)
141
+ url = URI.parse(@endpoint+"/compute/" + id.to_s)
142
+ req = Net::HTTP::Get.new(url.path)
143
+
144
+ req.basic_auth @occiauth[0], @occiauth[1]
145
+
146
+ res = CloudClient::http_start(url) {|http|
147
+ http.request(req)
148
+ }
149
+
150
+ if CloudClient::is_error?(res)
151
+ return res
152
+ else
153
+ return res.body
154
+ end
155
+ end
156
+
157
+ ######################################################################
158
+ # Puts a new Compute representation in order to change its state
159
+ # :xmlfile Compute OCCI xml representation
160
+ ######################################################################
161
+ def put_vm(xmlfile)
162
+ xml=File.read(xmlfile)
163
+ vm_info=REXML::Document.new(xml).root.elements
164
+
165
+ url = URI.parse(@endpoint+'/compute/' + vm_info['ID'].text)
166
+
167
+ req = Net::HTTP::Put.new(url.path)
168
+ req.body = xml
169
+
170
+ req.basic_auth @occiauth[0], @occiauth[1]
171
+
172
+ res = CloudClient::http_start(url) do |http|
173
+ http.request(req)
174
+ end
175
+
176
+ if CloudClient::is_error?(res)
177
+ return res
178
+ else
179
+ return res.body
180
+ end
181
+ end
182
+
183
+ #######################################################################
184
+ # Retieves an Image
185
+ # :image_uuid Image identifier
186
+ ######################################################################
187
+ def get_image(image_uuid)
188
+ url = URI.parse(@endpoint+"/storage/"+image_uuid)
189
+ req = Net::HTTP::Get.new(url.path)
190
+
191
+ req.basic_auth @occiauth[0], @occiauth[1]
192
+
193
+ res = CloudClient::http_start(url) {|http|
194
+ http.request(req)
195
+ }
196
+
197
+ if CloudClient::is_error?(res)
198
+ return res
199
+ else
200
+ return res.body
201
+ end
202
+ end
203
+ end
204
+ end