deltacloud-core 0.0.1 → 0.0.2

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 (32) hide show
  1. data/Rakefile +1 -24
  2. data/lib/deltacloud/base_driver/features.rb +15 -0
  3. data/lib/deltacloud/base_driver/mock_driver.rb +37 -0
  4. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +70 -48
  5. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +97 -14
  6. data/lib/deltacloud/drivers/{rimu/rimu_hosting_client.rb → rimuhosting/rimuhosting_client.rb} +5 -8
  7. data/lib/deltacloud/drivers/{rimu/rimu_hosting_driver.rb → rimuhosting/rimuhosting_driver.rb} +6 -5
  8. data/lib/deltacloud/drivers/terremark/terremark_driver.rb +261 -0
  9. data/lib/deltacloud/hardware_profile.rb +22 -0
  10. data/lib/deltacloud/helpers/application_helper.rb +18 -0
  11. data/lib/deltacloud/helpers/conversion_helper.rb +2 -3
  12. data/lib/deltacloud/method_serializer.rb +84 -0
  13. data/lib/drivers.rb +4 -3
  14. data/lib/sinatra/accept_media_types.rb +128 -0
  15. data/lib/sinatra/respond_to.rb +23 -16
  16. data/public/javascripts/application.js +30 -0
  17. data/public/javascripts/jquery-1.4.2.min.js +154 -0
  18. data/server.rb +23 -21
  19. data/support/fedora/deltacloudd +68 -0
  20. data/support/fedora/rubygem-deltacloud-core.spec +91 -0
  21. data/views/instances/index.html.haml +2 -1
  22. data/views/instances/index.xml.haml +3 -3
  23. data/views/instances/new.html.haml +9 -3
  24. data/views/instances/show.html.haml +2 -1
  25. data/views/instances/show.xml.haml +16 -3
  26. data/views/layout.html.haml +2 -0
  27. metadata +19 -37
  28. data/lib/converters/xml_converter.rb +0 -133
  29. data/public/javascripts/controls.js +0 -963
  30. data/public/javascripts/dragdrop.js +0 -973
  31. data/public/javascripts/effects.js +0 -1128
  32. data/public/javascripts/prototype.js +0 -4320
data/Rakefile CHANGED
@@ -22,8 +22,6 @@ require 'rake'
22
22
  require 'rake/testtask'
23
23
  require 'rake/gempackagetask'
24
24
 
25
-
26
-
27
25
  desc "Run basic unit tests"
28
26
  Rake::TestTask.new("test") { |t|
29
27
  t.test_files = FileList[
@@ -37,29 +35,8 @@ Rake::TestTask.new("test") { |t|
37
35
  t.warning = false
38
36
  }
39
37
 
40
- begin
41
- require 'cucumber'
42
- require 'cucumber/rake/task'
43
-
44
- Cucumber::Rake::Task.new(:features) do |t|
45
- t.cucumber_opts = "features --format html --out tmp/cucumber.html"
46
- t.rcov = false
47
- end
48
-
49
- Cucumber::Rake::Task.new(:rcov) do |t|
50
- t.cucumber_opts = "features --format pretty"
51
- t.rcov = true
52
- t.rcov_opts << %[-o "tmp/coverage"]
53
- end
54
- rescue LoadError
55
- desc 'Cucumber rake task not available'
56
- task :features do
57
- abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem'
58
- end
59
- end
60
-
61
-
62
38
  load 'deltacloud-core.gemspec'
39
+
63
40
  Rake::GemPackageTask.new(@spec) do |pkg|
64
41
  pkg.need_tar = true
65
42
  end
@@ -136,6 +136,21 @@ module Deltacloud
136
136
  end
137
137
  end
138
138
 
139
+ declare_feature :instances, :authentication_key do
140
+ operation :create do
141
+ param :keyname, :string, :optional, nil
142
+ "EC2 key authentification method"
143
+ end
144
+ operation :show do
145
+ end
146
+ end
147
+
148
+ declare_feature :instances, :authentication_password do
149
+ operation :create do
150
+ param :password, :string, :optional
151
+ end
152
+ end
153
+
139
154
  declare_feature :instances, :hardware_profiles do
140
155
  description "Size instances according to changes to a hardware profile"
141
156
  # The parameters are filled in from the hardware profiles
@@ -0,0 +1,37 @@
1
+ require 'deltacloud/method_serializer'
2
+
3
+ # Create 'mock' version of original driver client/gem:
4
+
5
+ module Mock
6
+ class EC2 < AWS::EC2::Base
7
+
8
+ include MethodSerializer::Cache
9
+
10
+ def self.cached_methods
11
+ [
12
+ :describe_images,
13
+ :describe_availability_zones,
14
+ :run_instances,
15
+ :describe_instances,
16
+ :reboot_instances,
17
+ :terminate_instances
18
+ ]
19
+ end
20
+
21
+ MethodSerializer::Cache::wrap_methods(self, :cache_dir => File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'tests', 'ec2', 'support'))
22
+ end
23
+ end
24
+
25
+
26
+ # Replace original client with mock client
27
+ Deltacloud::Drivers::EC2::EC2Driver.class_eval do
28
+ alias_method :original_new_client, :new_client
29
+
30
+ def new_client(credentials, opts={})
31
+ Mock::EC2.new(
32
+ :access_key_id => credentials.user,
33
+ :secret_access_key => credentials.password
34
+ )
35
+ end
36
+
37
+ end
@@ -17,11 +17,16 @@
17
17
 
18
18
 
19
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)
20
+ require 'AWS'
21
+
22
+ class Instance
23
+ attr_accessor :keyname
24
+ attr_accessor :authn_error
25
+
26
+ def authn_feature_failed?
27
+ return true unless authn_error.nil?
28
+ end
29
+
25
30
  end
26
31
 
27
32
  module Deltacloud
@@ -30,54 +35,62 @@ module Deltacloud
30
35
  class EC2Driver < Deltacloud::BaseDriver
31
36
 
32
37
  feature :instances, :user_data
38
+ feature :instances, :authentication_key
33
39
 
34
- define_hardware_profile('m1-small') do
35
- cpu 1
36
- memory 1.7 * 1024
37
- storage 160
38
- architecture 'i386'
40
+ define_hardware_profile('m1.small') do
41
+ cpu 1
42
+ memory 1.7 * 1024
43
+ storage 160
44
+ architecture 'i386'
39
45
  end
40
46
 
41
- define_hardware_profile('m1-large') do
47
+ define_hardware_profile('m1.large') do
42
48
  cpu 4
43
- memory 7.5 * 1024
44
- storage 850
45
- architecture 'x86_64'
49
+ memory 7.5 * 1024
50
+ storage 850
51
+ architecture 'x86_64'
46
52
  end
47
53
 
48
- define_hardware_profile('m1-xlarge') do
54
+ define_hardware_profile('m1.xlarge') do
49
55
  cpu 8
50
- memory 15 * 1024
51
- storage 1690
52
- architecture 'x86_64'
56
+ memory 15 * 1024
57
+ storage 1690
58
+ architecture 'x86_64'
53
59
  end
54
60
 
55
- define_hardware_profile('c1-medium') do
61
+ define_hardware_profile('c1.medium') do
56
62
  cpu 5
57
- memory 1.7 * 1024
58
- storage 350
59
- architecture 'i386'
63
+ memory 1.7 * 1024
64
+ storage 350
65
+ architecture 'i386'
60
66
  end
61
67
 
62
- define_hardware_profile('c1-xlarge') do
63
- cpu 20
64
- memory 7 * 1024
65
- storage 1690
66
- architecture 'x86_64'
68
+ define_hardware_profile('c1.xlarge') do
69
+ cpu 20
70
+ memory 7 * 1024
71
+ storage 1690
72
+ architecture 'x86_64'
67
73
  end
68
74
 
69
- define_hardware_profile('m2-xlarge') do
70
- cpu 6.5
71
- memory 17.1 * 1024
72
- storage 420
73
- architecture 'x86_64'
75
+ define_hardware_profile('m2.xlarge') do
76
+ cpu 6.5
77
+ memory 17.1 * 1024
78
+ storage 420
79
+ architecture 'x86_64'
74
80
  end
75
81
 
76
- define_hardware_profile('m2-2xlarge') do
77
- cpu 13
78
- memory 34.2 * 1024
79
- storage 850
80
- architecture 'x86_64'
82
+ define_hardware_profile('m2.2xlarge') do
83
+ cpu 13
84
+ memory 34.2 * 1024
85
+ storage 850
86
+ architecture 'x86_64'
87
+ end
88
+
89
+ define_hardware_profile('m2.4xlarge') do
90
+ cpu 26
91
+ memory 68.4 * 1024
92
+ storage 1690
93
+ architecture 'x86_64'
81
94
  end
82
95
 
83
96
  define_instance_states do
@@ -99,9 +112,14 @@ class EC2Driver < Deltacloud::BaseDriver
99
112
  def images(credentials, opts={} )
100
113
  ec2 = new_client(credentials)
101
114
  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]
115
+ # if we know the image_id, we don't want to limit by owner_id, since this
116
+ # will exclude public images
117
+ if (opts and opts[:id])
118
+ config = { :image_id => opts[:id] }
119
+ else
120
+ config = { :owner_id => "amazon" }
121
+ config.merge!({ :owner_id => opts[:owner_id] }) if opts and opts[:owner_id]
122
+ end
105
123
  safely do
106
124
  ec2.describe_images(config).imagesSet.item.each do |image|
107
125
  img_arr << convert_image(image)
@@ -156,10 +174,10 @@ class EC2Driver < Deltacloud::BaseDriver
156
174
  ec2_instances = ec2.run_instances(
157
175
  :image_id => image.id,
158
176
  :user_data => opts[:user_data],
159
- :key_name => opts[:key_name],
177
+ :key_name => opts[:keyname],
160
178
  :availability_zone => realm_id,
161
179
  :monitoring_enabled => true,
162
- :instance_type => hwp.name.tr('-', '.'),
180
+ :instance_type => hwp.name,
163
181
  :disable_api_termination => false,
164
182
  :instance_initiated_shutdown_behavior => 'terminate'
165
183
  )
@@ -235,10 +253,12 @@ class EC2Driver < Deltacloud::BaseDriver
235
253
  private
236
254
 
237
255
  def new_client(credentials)
238
- AWS::EC2::Base.new(
256
+ opts = {
239
257
  :access_key_id => credentials.user,
240
258
  :secret_access_key => credentials.password
241
- )
259
+ }
260
+ opts[:server] = ENV['DCLOUD_EC2_URL'] if ENV['DCLOUD_EC2_URL']
261
+ AWS::EC2::Base.new(opts)
242
262
  end
243
263
 
244
264
  def convert_image(ec2_image)
@@ -265,8 +285,8 @@ class EC2Driver < Deltacloud::BaseDriver
265
285
  state_key = state.downcase.underscore.to_sym
266
286
  realm_id = ec2_instance['placement']['availabilityZone']
267
287
  (realm_id = nil ) if ( realm_id == '' )
268
- hwp_name = ec2_instance['instanceType'].gsub( /\./, '-')
269
- Instance.new( {
288
+ hwp_name = ec2_instance['instanceType']
289
+ instance = Instance.new( {
270
290
  :id=>ec2_instance['instanceId'],
271
291
  :name => ec2_instance['imageId'],
272
292
  :state=>state,
@@ -275,10 +295,12 @@ class EC2Driver < Deltacloud::BaseDriver
275
295
  :realm_id=>realm_id,
276
296
  :public_addresses=>( ec2_instance['dnsName'] == '' ? [] : [ec2_instance['dnsName']] ),
277
297
  :private_addresses=>( ec2_instance['privateDnsName'] == '' ? [] : [ec2_instance['privateDnsName']] ),
278
- :flavor_id=>ec2_instance['instanceType'].gsub( /\./, '-'),
279
298
  :instance_profile =>InstanceProfile.new(hwp_name),
280
299
  :actions=>instance_actions_for( state ),
300
+ :keyname => ec2_instance['keyName']
281
301
  } )
302
+ instance.authn_error = "Key not set for instance" unless ec2_instance['keyName']
303
+ return instance
282
304
  end
283
305
 
284
306
  def convert_volume(ec2_volume)
@@ -307,7 +329,7 @@ class EC2Driver < Deltacloud::BaseDriver
307
329
  rescue AWS::AuthFailure => e
308
330
  raise Deltacloud::AuthException.new
309
331
  rescue Exception => e
310
- puts "ERROR: #{e.message}"
332
+ puts "ERROR: #{e.message}\n#{e.backtrace.join("\n")}"
311
333
  end
312
334
  end
313
335
 
@@ -18,12 +18,24 @@
18
18
  require 'deltacloud/base_driver'
19
19
  require 'deltacloud/drivers/gogrid/gogrid_client'
20
20
 
21
+ class Instance
22
+ attr_accessor :username
23
+ attr_accessor :password
24
+ attr_accessor :authn_error
25
+
26
+ def authn_feature_failed?
27
+ return true unless authn_error.nil?
28
+ end
29
+ end
30
+
21
31
  module Deltacloud
22
32
  module Drivers
23
33
  module Gogrid
24
34
 
25
35
  class GogridDriver < Deltacloud::BaseDriver
26
36
 
37
+ feature :instances, :authentication_password
38
+
27
39
  define_hardware_profile 'server' do
28
40
  cpu 2
29
41
  memory [512, 1024, 2048, 4096, 8192]
@@ -76,30 +88,72 @@ class GogridDriver < Deltacloud::BaseDriver
76
88
  else
77
89
  server_ram = "512MB"
78
90
  end
91
+ client = new_client(credentials)
79
92
  name = (opts[:name] && opts[:name]!='') ? opts[:name] : get_random_instance_name
80
93
  safely do
81
- convert_instance(new_client(credentials).request('grid/server/add', {
94
+ instance = client.request('grid/server/add', {
82
95
  'name' => name,
83
96
  'image' => image_id,
84
97
  'server.ram' => server_ram,
85
98
  'ip' => get_next_free_ip(credentials)
86
- })['list'].first, credentials.user)
99
+ })['list'].first
100
+ if instance
101
+ login_data = get_login_data(client, instance[:id])
102
+ if login_data['username'] and login_data['password']
103
+ instance['username'] = login_data['username']
104
+ instance['password'] = login_data['password']
105
+ inst = convert_instance(instance, credentials.user)
106
+ else
107
+ inst = convert_instance(instance, credentials.user)
108
+ inst.authn_error = "Unable to fetch password"
109
+ end
110
+ return inst
111
+ else
112
+ return nil
113
+ end
87
114
  end
88
115
  end
89
116
 
117
+ def list_instances(credentials, id)
118
+ instances = []
119
+ safely do
120
+ new_client(credentials).request('grid/server/list')['list'].collect do |instance|
121
+ if id.nil? or instance['name'] == id
122
+ instances << convert_instance(instance, credentials.user)
123
+ end
124
+ end
125
+ end
126
+ instances
127
+ end
128
+
90
129
  def instances(credentials, opts=nil)
91
130
  instances = []
92
131
  if opts and opts[:id]
93
- safely do
94
- instance = new_client(credentials).request('grid/server/get', { 'id' => opts[:id]})['list'].first
95
- instances = [convert_instance(instance, credentials.user)]
96
- end
97
- else
98
- safely do
99
- instances = new_client(credentials).request('grid/server/list')['list'].collect do |instance|
100
- convert_instance(instance, credentials.user)
132
+ begin
133
+ client = new_client(credentials)
134
+ instance = client.request('grid/server/get', { 'name' => opts[:id] })['list'].first
135
+ login_data = get_login_data(client, instance['id'])
136
+ if login_data['username'] and login_data['password']
137
+ instance['username'] = login_data['username']
138
+ instance['password'] = login_data['password']
139
+ inst = convert_instance(instance, credentials.user)
140
+ else
141
+ inst = convert_instance(instance, credentials.user)
142
+ inst.authn_error = "Unable to fetch password"
143
+ end
144
+ instances = [inst]
145
+ rescue Exception => e
146
+ if e.message == "400 Bad Request"
147
+ # in the case of a VM that we just made, the grid/server/get method
148
+ # throws a "400 Bad Request error". In this case we try again by
149
+ # getting a full listing a filtering on the id. This could
150
+ # potentially take a long time, but I don't see another way to get
151
+ # information about a newly created instance
152
+ instances = list_instances(credentials, opts[:id])
101
153
  end
102
154
  end
155
+ else
156
+ instances = list_instances(credentials, nil)
103
157
  end
104
158
  instances = filter_on( instances, :state, opts )
105
159
  instances
@@ -111,15 +165,21 @@ class GogridDriver < Deltacloud::BaseDriver
111
165
  end
112
166
  end
113
167
 
168
+ def destroy_instance(credentials, id)
169
+ safely do
170
+ new_client(credentials).request('grid/server/delete', { 'id' => id})
171
+ end
172
+ end
173
+
114
174
  def stop_instance(credentials, id)
115
175
  safely do
116
176
  new_client(credentials).request('grid/server/power', { 'id' => id, 'power' => 'off'})
117
177
  end
118
178
  end
119
179
 
120
- def destroy_instance(credentials, id)
180
+ def start_instance(credentials, id)
121
181
  safely do
122
- new_client(credentials).request('grid/server/delete', { 'id' => id})
182
+ new_client(credentials).request('grid/server/power', { 'id' => id, 'power' => 'on'})
123
183
  end
124
184
  end
125
185
 
@@ -128,7 +188,8 @@ class GogridDriver < Deltacloud::BaseDriver
128
188
  pending.to( :running ) .automatically
129
189
  running.to( :stopped ) .on( :stop )
130
190
  stopped.to( :running ) .on( :start )
131
- stopped.to( :finish ) .automatically
191
+ running.to( :finish ) .on( :destroy )
192
+ stopped.to( :finish ) .on( :destroy )
132
193
  end
133
194
 
134
195
  private
@@ -137,6 +198,22 @@ class GogridDriver < Deltacloud::BaseDriver
137
198
  GoGridClient.new('https://api.gogrid.com/api', credentials.user, credentials.password)
138
199
  end
139
200
 
201
+ def get_login_data(client, instance_id)
202
+ login_data = {}
203
+ begin
204
+ client.request('support/password/list')['list'].each do |passwd|
205
+ next unless passwd['server']
206
+ if passwd['server']['id'] == instance_id
207
+ login_data['username'], login_data['password'] = passwd['username'], passwd['password']
208
+ break
209
+ end
210
+ end
211
+ rescue Exception => e
212
+ login_data[:error] = e.message
213
+ end
214
+ return login_data
215
+ end
216
+
140
217
  def convert_image(gg_image, owner_id=nil)
141
218
  Image.new( {
142
219
  :id=>gg_image['id'],
@@ -190,6 +267,10 @@ class GogridDriver < Deltacloud::BaseDriver
190
267
  prof = InstanceProfile.new("server", opts)
191
268
 
192
269
  Instance.new(
270
+ # note that we use 'name' as the id here, because newly created instances
271
+ # don't get a real ID until later on. The name is good enough; from
272
+ # what I can tell, 'name' per user is unique, so it should be sufficient
273
+ # to uniquely identify this instance.
193
274
  :id => instance['name'],
194
275
  :owner_id => owner_id,
195
276
  :image_id => instance['image']['id'],
@@ -200,7 +281,9 @@ class GogridDriver < Deltacloud::BaseDriver
200
281
  :state => convert_server_state(instance['state']['name'], instance['id']),
201
282
  :actions => instance_actions_for(convert_server_state(instance['state']['name'], instance['id'])),
202
283
  :public_addresses => [ instance['ip']['ip'] ],
203
- :private_addresses => []
284
+ :private_addresses => [],
285
+ :username => instance['username'],
286
+ :password => instance['password']
204
287
  )
205
288
  end
206
289