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,144 @@
1
+ require 'deltacloud/validation'
2
+
3
+ # Add advertising of optional features to the base driver
4
+ module Deltacloud
5
+
6
+ class FeatureError < StandardError; end
7
+ class DuplicateFeatureDeclError < FeatureError; end
8
+ class UndeclaredFeatureError < FeatureError; end
9
+
10
+ class BaseDriver
11
+
12
+ # An operation on a collection like cretae or show. Features
13
+ # can add parameters to operations
14
+ class Operation
15
+ attr_reader :name
16
+
17
+ include Deltacloud::Validation
18
+
19
+ def initialize(name, &block)
20
+ @name = name
21
+ @params = {}
22
+ instance_eval &block
23
+ end
24
+ end
25
+
26
+ # The declaration of a feature, defines what operations
27
+ # are modified by it
28
+ class FeatureDecl
29
+ attr_reader :name, :operations
30
+
31
+ def initialize(name, &block)
32
+ @name = name
33
+ @operations = []
34
+ instance_eval &block
35
+ end
36
+
37
+ def description(text=nil)
38
+ @description = text if text
39
+ @description
40
+ end
41
+
42
+ # Add a new operation or modify an existing one through BLOCK
43
+ def operation(name, &block)
44
+ unless op = @operations.find { |op| op.name == name }
45
+ op = Operation.new(name, &block)
46
+ @operations << op
47
+ else
48
+ op.instance_eval(&block) if block_given?
49
+ end
50
+ op
51
+ end
52
+ end
53
+
54
+ # A specific feature enabled by a driver (see +feature+)
55
+ class Feature
56
+ attr_reader :decl
57
+
58
+ def initialize(decl, &block)
59
+ @decl = decl
60
+ instance_eval &block if block_given?
61
+ end
62
+
63
+ def name
64
+ decl.name
65
+ end
66
+
67
+ def operations
68
+ decl.operations
69
+ end
70
+
71
+ def description
72
+ decl.description
73
+ end
74
+ end
75
+
76
+ def self.feature_decls
77
+ @@feature_decls ||= {}
78
+ end
79
+
80
+ def self.feature_decl_for(collection, name)
81
+ decls = feature_decls[collection]
82
+ if decls
83
+ decls.find { |dcl| dcl.name == name }
84
+ else
85
+ nil
86
+ end
87
+ end
88
+
89
+ # Declare a new feature
90
+ def self.declare_feature(collection, name, &block)
91
+ feature_decls[collection] ||= []
92
+ raise DuplicateFeatureDeclError if feature_decl_for(collection, name)
93
+ feature_decls[collection] << FeatureDecl.new(name, &block)
94
+ end
95
+
96
+ def self.features
97
+ @@features ||= {}
98
+ end
99
+
100
+ # Declare in a driver that it supports a specific feature
101
+ #
102
+ # The same feature can be declared multiple times in a driver, so that
103
+ # it can be changed successively by passing in different blocks.
104
+ def self.feature(collection, name, &block)
105
+ features[collection] ||= []
106
+ if f = features[collection].find { |f| f.name == name }
107
+ f.instance_eval(&block) if block_given?
108
+ return f
109
+ end
110
+ unless decl = feature_decl_for(collection, name)
111
+ raise UndeclaredFeatureError, "No feature #{name} for #{collection}"
112
+ end
113
+ features[collection] << Feature.new(decl, &block)
114
+ end
115
+
116
+ def features(collection)
117
+ self.class.features[collection] || []
118
+ end
119
+
120
+ #
121
+ # Declaration of optional features
122
+ #
123
+ declare_feature :instances, :user_name do
124
+ description "Accept a user-defined name on instance creation"
125
+ operation :create do
126
+ param :name, :string, :optional, nil,
127
+ "The user-defined name"
128
+ end
129
+ end
130
+
131
+ declare_feature :instances, :user_data do
132
+ description "Make user-defined data available on a special webserver"
133
+ operation :create do
134
+ param :user_data, :string, :optional, nil,
135
+ "Base64 encoded user data will be published to internal webserver"
136
+ end
137
+ end
138
+
139
+ declare_feature :instances, :hardware_profiles do
140
+ description "Size instances according to changes to a hardware profile"
141
+ # The parameters are filled in from the hardware profiles
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,318 @@
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
+
19
+ require 'deltacloud/base_driver'
20
+ begin
21
+ require 'AWS'
22
+ rescue LoadError
23
+ puts "ERROR: Please install Amazon-EC2 gem first. (gem install amazon-ec2)"
24
+ exit(1)
25
+ end
26
+
27
+ module Deltacloud
28
+ module Drivers
29
+ module EC2
30
+ class EC2Driver < Deltacloud::BaseDriver
31
+
32
+ feature :instances, :user_data
33
+
34
+ define_hardware_profile('m1-small') do
35
+ cpu 1
36
+ memory 1.7 * 1024
37
+ storage 160
38
+ architecture 'i386'
39
+ end
40
+
41
+ define_hardware_profile('m1-large') do
42
+ cpu 4
43
+ memory 7.5 * 1024
44
+ storage 850
45
+ architecture 'x86_64'
46
+ end
47
+
48
+ define_hardware_profile('m1-xlarge') do
49
+ cpu 8
50
+ memory 15 * 1024
51
+ storage 1690
52
+ architecture 'x86_64'
53
+ end
54
+
55
+ define_hardware_profile('c1-medium') do
56
+ cpu 5
57
+ memory 1.7 * 1024
58
+ storage 350
59
+ architecture 'i386'
60
+ end
61
+
62
+ define_hardware_profile('c1-xlarge') do
63
+ cpu 20
64
+ memory 7 * 1024
65
+ storage 1690
66
+ architecture 'x86_64'
67
+ end
68
+
69
+ define_hardware_profile('m2-xlarge') do
70
+ cpu 6.5
71
+ memory 17.1 * 1024
72
+ storage 420
73
+ architecture 'x86_64'
74
+ end
75
+
76
+ define_hardware_profile('m2-2xlarge') do
77
+ cpu 13
78
+ memory 34.2 * 1024
79
+ storage 850
80
+ architecture 'x86_64'
81
+ end
82
+
83
+ define_instance_states do
84
+ start.to( :pending ) .automatically
85
+ pending.to( :running ) .automatically
86
+ pending.to( :stopping ) .on( :stop )
87
+ pending.to( :stopped ) .automatically
88
+ stopped.to( :running ) .on( :start )
89
+ running.to( :running ) .on( :reboot )
90
+ running.to( :stopping ) .on( :stop )
91
+ shutting_down.to( :stopped ) .automatically
92
+ stopped.to( :finish ) .automatically
93
+ end
94
+
95
+ #
96
+ # Images
97
+ #
98
+
99
+ def images(credentials, opts={} )
100
+ ec2 = new_client(credentials)
101
+ img_arr = []
102
+ config = { :owner_id => "amazon" }
103
+ config.merge!({ :owner_id => opts[:owner_id] }) if opts and opts[:owner_id]
104
+ config.merge!({ :image_id => opts[:id] }) if opts and opts[:id]
105
+ safely do
106
+ ec2.describe_images(config).imagesSet.item.each do |image|
107
+ img_arr << convert_image(image)
108
+ end
109
+ end
110
+ img_arr = filter_on( img_arr, :architecture, opts )
111
+ img_arr.sort_by{|e| [e.owner_id, e.name]}
112
+ end
113
+
114
+ #
115
+ # Realms
116
+ #
117
+
118
+ def realms(credentials, opts=nil)
119
+ ec2 = new_client(credentials)
120
+ realms = []
121
+ safely do
122
+ ec2.describe_availability_zones.availabilityZoneInfo.item.each do |ec2_realm|
123
+ realms << convert_realm( ec2_realm )
124
+ end
125
+ end
126
+ realms
127
+ end
128
+
129
+ #
130
+ # Instances
131
+ #
132
+ def instances(credentials, opts=nil)
133
+ ec2 = new_client(credentials)
134
+ instances = []
135
+ safely do
136
+ param = opts.nil? ? nil : opts[:id]
137
+ ec2_instances = ec2.describe_instances.reservationSet
138
+ return [] unless ec2_instances
139
+ ec2_instances.item.each do |item|
140
+ item.instancesSet.item.each do |ec2_instance|
141
+ instances << convert_instance( ec2_instance, item.ownerId )
142
+ end
143
+ end
144
+ end
145
+ instances = filter_on( instances, :id, opts )
146
+ instances = filter_on( instances, :state, opts )
147
+ instances
148
+ end
149
+
150
+
151
+ def create_instance(credentials, image_id, opts)
152
+ ec2 = new_client( credentials )
153
+ realm_id = opts[:realm_id]
154
+ image = image(credentials, :id => image_id )
155
+ hwp = find_hardware_profile(credentials, opts[:hwp_id], image.id)
156
+ ec2_instances = ec2.run_instances(
157
+ :image_id => image.id,
158
+ :user_data => opts[:user_data],
159
+ :key_name => opts[:key_name],
160
+ :availability_zone => realm_id,
161
+ :monitoring_enabled => true,
162
+ :instance_type => hwp.name.tr('-', '.'),
163
+ :disable_api_termination => false,
164
+ :instance_initiated_shutdown_behavior => 'terminate'
165
+ )
166
+ convert_instance( ec2_instances.instancesSet.item.first, 'pending' )
167
+ end
168
+
169
+ def reboot_instance(credentials, id)
170
+ ec2 = new_client(credentials)
171
+ safely do
172
+ ec2.reboot_instances( :instance_id => id )
173
+ end
174
+ end
175
+
176
+ def stop_instance(credentials, id)
177
+ ec2 = new_client(credentials)
178
+ safely do
179
+ ec2.terminate_instances( :instance_id => id )
180
+ end
181
+ end
182
+
183
+ def destroy_instance(credentials, id)
184
+ ec2 = new_client(credentials)
185
+ safely do
186
+ ec2.terminate_instances( :instance_id => id )
187
+ end
188
+ end
189
+
190
+ #
191
+ # Storage Volumes
192
+ #
193
+ def storage_volumes(credentials, opts=nil)
194
+ ec2 = new_client( credentials )
195
+ volumes = []
196
+ safely do
197
+ if (opts)
198
+ ec2.describe_volumes(:volume_id => opts[:id]).volumeSet.item.each do |ec2_volume|
199
+ volumes << convert_volume( ec2_volume )
200
+ end
201
+ else
202
+ ec2_volumes = ec2.describe_volumes.volumeSet
203
+ return [] unless ec2_volumes
204
+ ec2_volumes.item.each do |ec2_volume|
205
+ volumes << convert_volume( ec2_volume )
206
+ end
207
+ end
208
+ end
209
+ volumes
210
+ end
211
+
212
+ #
213
+ # Storage Snapshots
214
+ #
215
+
216
+ def storage_snapshots(credentials, opts=nil)
217
+ ec2 = new_client( credentials )
218
+ snapshots = []
219
+ safely do
220
+ if (opts)
221
+ ec2.describe_snapshots(:owner => 'self', :snapshot_id => opts[:id]).snapshotSet.item.each do |ec2_snapshot|
222
+ snapshots << convert_snapshot( ec2_snapshot )
223
+ end
224
+ else
225
+ ec2_snapshots = ec2.describe_snapshots(:owner => 'self').snapshotSet
226
+ return [] unless ec2_snapshots
227
+ ec2_snapshots.item.each do |ec2_snapshot|
228
+ snapshots << convert_snapshot( ec2_snapshot )
229
+ end
230
+ end
231
+ end
232
+ snapshots
233
+ end
234
+
235
+ private
236
+
237
+ def new_client(credentials)
238
+ AWS::EC2::Base.new(
239
+ :access_key_id => credentials.user,
240
+ :secret_access_key => credentials.password
241
+ )
242
+ end
243
+
244
+ def convert_image(ec2_image)
245
+ Image.new( {
246
+ :id=>ec2_image['imageId'],
247
+ :name=>ec2_image['name'] || ec2_image['imageId'],
248
+ :description=>ec2_image['description'] || ec2_image['imageLocation'] || '',
249
+ :owner_id=>ec2_image['imageOwnerId'],
250
+ :architecture=>ec2_image['architecture'],
251
+ } )
252
+ end
253
+
254
+ def convert_realm(ec2_realm)
255
+ Realm.new( {
256
+ :id=>ec2_realm['zoneName'],
257
+ :name=>ec2_realm['regionName'],
258
+ :limit=>ec2_realm['zoneState'].eql?('available') ? :unlimited : 0,
259
+ :state=>ec2_realm['zoneState'].upcase,
260
+ } )
261
+ end
262
+
263
+ def convert_instance(ec2_instance, owner_id)
264
+ state = ec2_instance['instanceState']['name'].upcase
265
+ state_key = state.downcase.underscore.to_sym
266
+ realm_id = ec2_instance['placement']['availabilityZone']
267
+ (realm_id = nil ) if ( realm_id == '' )
268
+ hwp_name = ec2_instance['instanceType'].gsub( /\./, '-')
269
+ Instance.new( {
270
+ :id=>ec2_instance['instanceId'],
271
+ :name => ec2_instance['imageId'],
272
+ :state=>state,
273
+ :image_id=>ec2_instance['imageId'],
274
+ :owner_id=>owner_id,
275
+ :realm_id=>realm_id,
276
+ :public_addresses=>( ec2_instance['dnsName'] == '' ? [] : [ec2_instance['dnsName']] ),
277
+ :private_addresses=>( ec2_instance['privateDnsName'] == '' ? [] : [ec2_instance['privateDnsName']] ),
278
+ :flavor_id=>ec2_instance['instanceType'].gsub( /\./, '-'),
279
+ :instance_profile =>InstanceProfile.new(hwp_name),
280
+ :actions=>instance_actions_for( state ),
281
+ } )
282
+ end
283
+
284
+ def convert_volume(ec2_volume)
285
+ StorageVolume.new( {
286
+ :id=>ec2_volume['volumeId'],
287
+ :created=>ec2_volume['createTime'],
288
+ :state=>ec2_volume['status'].upcase,
289
+ :capacity=>ec2_volume['size'],
290
+ :instance_id=>ec2_volume['snapshotId'],
291
+ :device=>ec2_volume['attachmentSet'],
292
+ } )
293
+ end
294
+
295
+ def convert_snapshot(ec2_snapshot)
296
+ StorageSnapshot.new( {
297
+ :id=>ec2_snapshot['snapshotId'],
298
+ :state=>ec2_snapshot['status'].upcase,
299
+ :storage_volume_id=>ec2_snapshot['volumeId'],
300
+ :created=>ec2_snapshot['startTime'],
301
+ } )
302
+ end
303
+
304
+ def safely(&block)
305
+ begin
306
+ block.call
307
+ rescue AWS::AuthFailure => e
308
+ raise Deltacloud::AuthException.new
309
+ rescue Exception => e
310
+ puts "ERROR: #{e.message}"
311
+ end
312
+ end
313
+
314
+ end
315
+
316
+ end
317
+ end
318
+ end