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,170 @@
1
+ module RightAws
2
+ class MockEc2
3
+
4
+ def initialize(opts={})
5
+ end
6
+
7
+ def describe_images(id)
8
+ load_fixtures_for(:images).select { |i| i[:aws_id].eql?(id) }
9
+ end
10
+
11
+ def describe_images_by_owner(id)
12
+ load_fixtures_for(:images).select { |i| i[:aws_owner].eql?(id) }
13
+ end
14
+
15
+ def describe_images(opts={})
16
+ load_fixtures_for(:images)
17
+ end
18
+
19
+ def describe_availability_zones(opts={})
20
+ load_fixtures_for(:realms)
21
+ end
22
+
23
+ def describe_instances(opts={})
24
+ instances = load_fixtures_for(:instances)
25
+ instances.each_with_index do |instance, i|
26
+ instances[i] = update_delayed_state(instance)
27
+ return [instance] if opts and opts[:id] and instance[:aws_instance_id].eql?(opts[:id])
28
+ end
29
+ update_fixtures_for(:instances, instances)
30
+ instances
31
+ end
32
+
33
+ def run_instances(image_id, min_count, max_count, group_ids, key_name, user_data='', addressing_type = nil, instance_type = nil, kernel_id = nil, ramdisk_id = nil, availability_zone = nil, block_device_mappings = nil)
34
+
35
+ instances = load_fixtures_for(:instances)
36
+ image = load_fixtures_for(:images).select { |img| img[:aws_id].eql?(image_id) }.first
37
+
38
+ if availability_zone
39
+ realm = load_fixtures_for(:realms).select { |realm| realm[:zone_name].eql?(availability_zone) }.first
40
+ else
41
+ realm = load_fixtures_for(:realms).first
42
+ end
43
+
44
+ raise Exception unless image
45
+ raise Exception unless realm
46
+
47
+ instance = { }
48
+ instance[:aws_image_id] = image[:aws_id]
49
+ instance[:aws_availability_zone] = realm[:zone_name]
50
+ instance[:aws_instance_type] = instance_type
51
+ instance[:aws_owner] = user_data
52
+ instance[:aws_state] = 'pending'
53
+ instance[:aws_reason] = ''
54
+ instance[:dns_name] = "#{random_dns}-01-C9.usma2.compute.amazonaws.com"
55
+ instance[:private_dns_name] = "#{random_dns}-02-P9.usma2.compute.amazonaws.com"
56
+ instance[:aws_state_code] = "0"
57
+ instance[:aws_key_name] = "staging"
58
+ instance[:aws_kernel_id] = "aki-be3adfd7"
59
+ instance[:aws_ramdisk_id] = "ari-ce34gad7"
60
+ instance[:aws_groups] = ["default"]
61
+ instance[:aws_instance_id] = random_instance_id
62
+ instance[:aws_reservation_id] = "r-aabbccdd"
63
+ instance[:aws_launch_time] = instance_time_format
64
+
65
+ instances << instance
66
+
67
+ update_fixtures_for(:instances, instances)
68
+
69
+ return [instance]
70
+ end
71
+
72
+
73
+ def terminate_instances(id)
74
+ update_instance_state(id, 'stopping', '80')
75
+ end
76
+
77
+ def reboot_instances(id)
78
+ update_instance_state(id, 'pending', '0')
79
+ end
80
+
81
+ alias :destroy_instance :terminate_instances
82
+
83
+ def describe_snapshots(opts={})
84
+ load_fixtures_for(:storage_snapshot)
85
+ end
86
+
87
+ def describe_volumes(opts={})
88
+ load_fixtures_for(:storage_volume)
89
+ end
90
+
91
+ private
92
+
93
+ def driver_dir
94
+ File::expand_path(File::join(File::dirname(__FILE__), '../../../../features/support/ec2'))
95
+ end
96
+
97
+ def fixtures_path
98
+ File::expand_path(File::join(driver_dir, 'fixtures'))
99
+ end
100
+
101
+ def load_fixtures_for(collection)
102
+ YAML.load_file(File::join(fixtures_path, "#{collection}.yaml"))
103
+ end
104
+
105
+ def update_fixtures_for(collection, new_data)
106
+ File.open(File::join(fixtures_path, "#{collection}.yaml"), 'w' ) do |out|
107
+ YAML.dump(new_data, out)
108
+ end
109
+ return new_data
110
+ end
111
+
112
+ def instance_time_format
113
+ DateTime.now.to_s.gsub(/\+(.+)$/, '.000Z')
114
+ end
115
+
116
+ def random_instance_id
117
+ id_1 = ("%.4s" % Time.now.to_i.to_s.reverse).reverse
118
+ id_2 = ("%.3s" % Time.now.to_i.to_s.reverse)
119
+ "i-#{id_1}f#{id_2}"
120
+ end
121
+
122
+ def random_dns
123
+ "domU-#{rand(90)+10}-#{rand(90)+10}-#{rand(90)+10}-#{rand(90)+10}"
124
+ end
125
+
126
+ def update_delayed_state(instance)
127
+ time = DateTime.now - DateTime.parse(instance[:aws_launch_time])
128
+ hours, minutes, seconds, frac = Date.day_fraction_to_time(time)
129
+
130
+ if (minutes>(rand(2)+1) or hours>0) and instance[:aws_state].eql?('pending')
131
+ instance[:aws_state], instance[:aws_state_code] = 'running', '16'
132
+ end
133
+
134
+ if (minutes>(rand(1)+1) or hours>0) and instance[:aws_state].eql?('stopping')
135
+ instance[:aws_state], instance[:aws_state_code] = 'stopped', '80'
136
+ end
137
+
138
+ return instance
139
+ end
140
+
141
+ def update_instance_state(id, state, state_code)
142
+ instance = describe_instances(:id => id).first
143
+ if instance
144
+ instance[:aws_state], instance[:aws_state_code] = state, state_code
145
+ instance[:aws_launch_time] = instance_time_format
146
+ instances = load_fixtures_for(:instances)
147
+ instances.each_with_index do |inst, i|
148
+ instances[i] = instance if inst[:aws_instance_id].eql?(id)
149
+ end
150
+ update_fixtures_for(:instances, instances)
151
+ return instance
152
+ else
153
+ raise Exception
154
+ end
155
+ end
156
+
157
+ end
158
+ end
159
+
160
+ Deltacloud::Drivers::EC2::EC2Driver.class_eval do
161
+ alias_method :original_new_client, :new_client
162
+
163
+ def new_client(credentials, opts={})
164
+ if credentials.user != 'mockuser' and credentials.password != 'mockpassword'
165
+ raise Deltacloud::AuthException.new
166
+ end
167
+ RightAws::MockEc2.new
168
+ end
169
+
170
+ end
@@ -0,0 +1,45 @@
1
+ require 'digest/md5'
2
+ require 'cgi'
3
+ require 'open-uri'
4
+ require 'json'
5
+
6
+ class GoGridClient
7
+
8
+ def initialize(server='https://api.gogrid.com/api',
9
+ apikey='YOUR API KEY',
10
+ secret='YOUR SHARED SECRET',
11
+ format='json',
12
+ version='1.4')
13
+ @server = server
14
+ @secret = secret
15
+ @default_params = {'format'=>format, 'v'=>version,'api_key' => apikey}
16
+ end
17
+
18
+ def getRequestURL(method,params)
19
+ requestURL = @server+'/'+method+'?'
20
+ call_params = @default_params.merge(params)
21
+ call_params['sig']=getSignature(@default_params['api_key'],@secret)
22
+ requestURL = requestURL+encode_params(call_params)
23
+ end
24
+
25
+ def getSignature(key,secret)
26
+ Digest::MD5.hexdigest(key+secret+"%.0f"%Time.new.to_f)
27
+ end
28
+
29
+ def sendAPIRequest(method,params={})
30
+ open(getRequestURL(method,params)).read
31
+ end
32
+
33
+ def request(method, params={})
34
+ begin
35
+ JSON::parse(sendAPIRequest(method, params))
36
+ rescue Exception => e
37
+ STDERR.puts("ERROR: #{e.message}")
38
+ end
39
+ end
40
+
41
+ def encode_params(params)
42
+ params.map {|k,v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join("&")
43
+ end
44
+
45
+ end
@@ -0,0 +1,239 @@
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
+ require 'deltacloud/base_driver'
19
+ require 'deltacloud/drivers/gogrid/gogrid_client'
20
+
21
+ module Deltacloud
22
+ module Drivers
23
+ module Gogrid
24
+
25
+ class GogridDriver < Deltacloud::BaseDriver
26
+
27
+ define_hardware_profile 'server' do
28
+ cpu 2
29
+ memory [512, 1024, 2048, 4096, 8192]
30
+ storage 10
31
+ end
32
+
33
+ # The only valid option for flavors is server RAM for now
34
+ def flavors(credentials, opts=nil)
35
+ flavors = []
36
+ safely do
37
+ flavors=new_client(credentials).request('common/lookup/list', { 'lookup' => 'server.ram' })['list'].collect do |flavor|
38
+ convert_flavor(flavor)
39
+ end
40
+ end
41
+ flavors = filter_on( flavors, :id, opts )
42
+ flavors = filter_on( flavors, :architecture, opts )
43
+ flavors
44
+ end
45
+
46
+ def images(credentials, opts=nil)
47
+ imgs = []
48
+ if opts and opts[:id]
49
+ safely do
50
+ imgs = [convert_image(new_client(credentials).request('grid/image/get', { 'id' => opts[:id] })['list'].first)]
51
+ end
52
+ else
53
+ safely do
54
+ imgs = new_client(credentials).request('grid/image/list', { 'state' => 'Available'})['list'].collect do |image|
55
+ convert_image(image, credentials.user)
56
+ end
57
+ end
58
+ end
59
+ imgs = filter_on( imgs, :architecture, opts )
60
+ imgs.sort_by{|e| [e.owner_id, e.description]}
61
+ end
62
+
63
+ def realms(credentials, opts=nil)
64
+ safely do
65
+ new_client(credentials).request('common/lookup/list', { 'lookup' => 'image.type' })['list'].collect do |realm|
66
+ convert_realm(realm)
67
+ end
68
+ end
69
+ end
70
+
71
+ def create_instance(credentials, image_id, opts=nil)
72
+ server_ram = nil
73
+ if opts[:hwp_memory]
74
+ mem = opts[:hwp_memory].to_i
75
+ server_ram = (mem == 512) ? "512MB" : "#{mem / 1024}GB"
76
+ else
77
+ server_ram = "512MB"
78
+ end
79
+ name = (opts[:name] && opts[:name]!='') ? opts[:name] : get_random_instance_name
80
+ safely do
81
+ convert_instance(new_client(credentials).request('grid/server/add', {
82
+ 'name' => name,
83
+ 'image' => image_id,
84
+ 'server.ram' => server_ram,
85
+ 'ip' => get_next_free_ip(credentials)
86
+ })['list'].first, credentials.user)
87
+ end
88
+ end
89
+
90
+ def instances(credentials, opts=nil)
91
+ instances = []
92
+ 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)
101
+ end
102
+ end
103
+ end
104
+ instances = filter_on( instances, :state, opts )
105
+ instances
106
+ end
107
+
108
+ def reboot_instance(credentials, id)
109
+ safely do
110
+ new_client(credentials).request('grid/server/power', { 'id' => id, 'power' => 'reboot'})
111
+ end
112
+ end
113
+
114
+ def stop_instance(credentials, id)
115
+ safely do
116
+ new_client(credentials).request('grid/server/power', { 'id' => id, 'power' => 'off'})
117
+ end
118
+ end
119
+
120
+ def destroy_instance(credentials, id)
121
+ safely do
122
+ new_client(credentials).request('grid/server/delete', { 'id' => id})
123
+ end
124
+ end
125
+
126
+ define_instance_states do
127
+ start.to( :pending ) .automatically
128
+ pending.to( :running ) .automatically
129
+ running.to( :stopped ) .on( :stop )
130
+ stopped.to( :running ) .on( :start )
131
+ stopped.to( :finish ) .automatically
132
+ end
133
+
134
+ private
135
+
136
+ def new_client(credentials)
137
+ GoGridClient.new('https://api.gogrid.com/api', credentials.user, credentials.password)
138
+ end
139
+
140
+ def convert_image(gg_image, owner_id=nil)
141
+ Image.new( {
142
+ :id=>gg_image['id'],
143
+ :name => gg_image['friendlyName'],
144
+ :description=> convert_description(gg_image),
145
+ :owner_id=>gg_image['owner']['name'],
146
+ :architecture=>convert_arch(gg_image['description']),
147
+ } )
148
+ end
149
+
150
+ def convert_description(image)
151
+ if image['price'].eql?(0)
152
+ image['description']
153
+ else
154
+ "#{image['description']} (#{image['price']}$)"
155
+ end
156
+ end
157
+
158
+ def convert_flavor(flavor)
159
+ Flavor.new(
160
+ :id => flavor['id'],
161
+ :architecture => 'x86',
162
+ :memory => flavor['name'].tr('G', ''),
163
+ :storage => '1'
164
+ )
165
+ end
166
+
167
+ def convert_realm(realm)
168
+ Realm.new(
169
+ :id => realm['id'],
170
+ :name => realm['name'],
171
+ :state => :unlimited,
172
+ :storage => :unlimited
173
+ )
174
+ end
175
+
176
+ def convert_arch(description)
177
+ description.include?('64-bit') ? 'x86_64' : 'i386'
178
+ end
179
+
180
+ def convert_instance(instance, owner_id)
181
+ opts = {}
182
+ unless instance['ram']['id'] == "1"
183
+ mem = instance['ram']['name']
184
+ if mem == "512MB"
185
+ opts[:hwp_memory] = "512"
186
+ else
187
+ opts[:hwp_memory] = (mem.to_i * 1024).to_s
188
+ end
189
+ end
190
+ prof = InstanceProfile.new("server", opts)
191
+
192
+ Instance.new(
193
+ :id => instance['name'],
194
+ :owner_id => owner_id,
195
+ :image_id => instance['image']['id'],
196
+ :flavor_id => instance['ram']['id'],
197
+ :instance_profile => prof,
198
+ :name => instance['name'],
199
+ :realm_id => instance['type']['id'],
200
+ :state => convert_server_state(instance['state']['name'], instance['id']),
201
+ :actions => instance_actions_for(convert_server_state(instance['state']['name'], instance['id'])),
202
+ :public_addresses => [ instance['ip']['ip'] ],
203
+ :private_addresses => []
204
+ )
205
+ end
206
+
207
+ def get_random_instance_name
208
+ "Server #{Time.now.to_i.to_s.reverse[0..3]}#{rand(9)}"
209
+ end
210
+
211
+ def convert_server_state(state, id)
212
+ return 'PENDING' unless id
213
+ state.eql?('Off') ? 'STOPPED' : 'RUNNING'
214
+ end
215
+
216
+ def get_next_free_ip(credentials)
217
+ ip = ""
218
+ safely do
219
+ ip = new_client(credentials).request('grid/ip/list', {
220
+ 'ip.type' => '1',
221
+ 'ip.state' => '1'
222
+ })['list'].first['ip']
223
+ end
224
+ return ip
225
+ end
226
+
227
+ def safely(&block)
228
+ begin
229
+ block.call
230
+ rescue Exception => e
231
+ puts "ERROR: #{e.message}"
232
+ end
233
+ end
234
+
235
+ end
236
+
237
+ end
238
+ end
239
+ end