deltacloud-core 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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