deltacloud-core 0.1.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. data/DISCLAIMER +8 -0
  2. data/{COPYING → LICENSE} +0 -0
  3. data/NOTICE +13 -0
  4. data/Rakefile +50 -51
  5. data/bin/deltacloudd +8 -1
  6. data/config.ru +0 -2
  7. data/config/drivers.yaml +48 -0
  8. data/deltacloud-core.gemspec +75 -0
  9. data/deltacloud.rb +3 -2
  10. data/lib/deltacloud/backend_capability.rb +15 -3
  11. data/lib/deltacloud/base_driver.rb +0 -2
  12. data/lib/deltacloud/base_driver/base_driver.rb +85 -89
  13. data/lib/deltacloud/base_driver/features.rb +61 -7
  14. data/lib/deltacloud/base_driver/mock_driver.rb +42 -43
  15. data/lib/deltacloud/core_ext.rb +18 -0
  16. data/lib/deltacloud/core_ext/integer.rb +31 -0
  17. data/lib/deltacloud/core_ext/string.rb +50 -0
  18. data/lib/deltacloud/drivers/azure/azure_driver.rb +71 -22
  19. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +641 -584
  20. data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +0 -2
  21. data/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb +167 -0
  22. data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +39 -1
  23. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +41 -25
  24. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob1.yml +6 -3
  25. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob2.yml +6 -3
  26. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob3.yml +4 -2
  27. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob4.yml +5 -2
  28. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob5.yml +4 -2
  29. data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +1 -0
  30. data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +1 -0
  31. data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +1 -0
  32. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol1.yml +1 -0
  33. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol2.yml +1 -0
  34. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol3.yml +1 -0
  35. data/lib/deltacloud/drivers/mock/mock_driver.rb +138 -30
  36. data/lib/deltacloud/drivers/opennebula/cloud_client.rb +13 -15
  37. data/lib/deltacloud/drivers/opennebula/occi_client.rb +13 -15
  38. data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +13 -15
  39. data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +224 -113
  40. data/lib/deltacloud/drivers/rhevm/rhevm_client.rb +332 -0
  41. data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +221 -170
  42. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +0 -1
  43. data/lib/deltacloud/drivers/sbc/sbc_client.rb +247 -0
  44. data/lib/deltacloud/drivers/sbc/sbc_driver.rb +297 -0
  45. data/lib/deltacloud/drivers/terremark/terremark_driver.rb +0 -2
  46. data/lib/deltacloud/hardware_profile.rb +1 -3
  47. data/lib/deltacloud/helpers.rb +0 -2
  48. data/lib/deltacloud/helpers/application_helper.rb +86 -12
  49. data/lib/deltacloud/helpers/blob_stream.rb +19 -2
  50. data/lib/deltacloud/helpers/conversion_helper.rb +0 -2
  51. data/lib/deltacloud/helpers/hardware_profiles_helper.rb +0 -2
  52. data/lib/deltacloud/method_serializer.rb +0 -2
  53. data/lib/deltacloud/models/base_model.rb +0 -2
  54. data/lib/deltacloud/models/blob.rb +1 -2
  55. data/lib/deltacloud/models/bucket.rb +0 -2
  56. data/lib/deltacloud/models/image.rb +0 -2
  57. data/lib/deltacloud/models/instance.rb +19 -2
  58. data/lib/deltacloud/models/instance_profile.rb +4 -2
  59. data/lib/deltacloud/models/key.rb +0 -2
  60. data/lib/deltacloud/models/load_balancer.rb +0 -2
  61. data/lib/deltacloud/models/realm.rb +0 -2
  62. data/lib/deltacloud/models/storage_snapshot.rb +0 -2
  63. data/lib/deltacloud/models/storage_volume.rb +4 -2
  64. data/lib/deltacloud/runner.rb +132 -0
  65. data/lib/deltacloud/state_machine.rb +0 -2
  66. data/lib/deltacloud/validation.rb +9 -7
  67. data/lib/drivers.rb +36 -48
  68. data/lib/sinatra/accept_media_types.rb +26 -0
  69. data/lib/sinatra/lazy_auth.rb +16 -0
  70. data/lib/sinatra/rabbit.rb +112 -54
  71. data/lib/sinatra/rack_driver_select.rb +50 -16
  72. data/lib/sinatra/rack_etag.rb +79 -0
  73. data/lib/sinatra/rack_matrix_params.rb +84 -0
  74. data/lib/sinatra/rack_runtime.rb +47 -0
  75. data/lib/sinatra/static_assets.rb +16 -0
  76. data/lib/sinatra/url_for.rb +31 -4
  77. data/public/favicon.ico +0 -0
  78. data/public/images/bread-bg.png +0 -0
  79. data/public/images/error.png +0 -0
  80. data/public/images/pending.png +0 -0
  81. data/public/images/running.png +0 -0
  82. data/public/images/stopped.png +0 -0
  83. data/public/javascripts/application.js +35 -0
  84. data/public/stylesheets/compiled/application.css +59 -5
  85. data/public/stylesheets/compiled/screen.css +1 -1
  86. data/server.rb +293 -29
  87. data/support/fedora/deltacloud-core +78 -0
  88. data/support/fedora/deltacloud-core.spec +143 -0
  89. data/support/fedora/deltacloudd +78 -18
  90. data/support/fedora/rubygem-deltacloud-core.spec +76 -40
  91. data/tests/common.rb +172 -0
  92. data/tests/drivers/mock/api_test.rb +133 -0
  93. data/tests/drivers/mock/hardware_profiles_test.rb +134 -0
  94. data/tests/drivers/mock/images_test.rb +126 -0
  95. data/tests/drivers/mock/instance_states_test.rb +71 -0
  96. data/tests/drivers/mock/instances_test.rb +236 -0
  97. data/tests/drivers/mock/realms_test.rb +93 -0
  98. data/tests/drivers/mock/setup.rb +3 -0
  99. data/tests/drivers/mock/url_for_test.rb +67 -0
  100. data/tests/drivers/rackspace/api_test.rb +41 -0
  101. data/tests/drivers/rackspace/hardware_profiles_test.rb +53 -0
  102. data/tests/drivers/rackspace/images_test.rb +40 -0
  103. data/tests/drivers/rackspace/instances_test.rb +161 -0
  104. data/tests/drivers/rackspace/realms_test.rb +36 -0
  105. data/tests/drivers/rackspace/setup.rb +14 -0
  106. data/tests/drivers/rhevm/api_test.rb +39 -0
  107. data/tests/drivers/rhevm/hardware_profiles_test.rb +53 -0
  108. data/tests/drivers/rhevm/images_test.rb +42 -0
  109. data/tests/drivers/rhevm/instances_test.rb +179 -0
  110. data/tests/drivers/rhevm/realms_test.rb +35 -0
  111. data/tests/drivers/rhevm/setup.rb +14 -0
  112. data/tests/rabbit_test.rb +52 -0
  113. data/views/api/show.html.haml +2 -5
  114. data/views/blobs/new.html.haml +17 -1
  115. data/views/blobs/show.html.haml +6 -0
  116. data/views/blobs/show.xml.haml +5 -1
  117. data/views/buckets/index.html.haml +1 -12
  118. data/views/buckets/index.xml.haml +3 -5
  119. data/views/docs/operation.html.haml +23 -11
  120. data/views/drivers/index.html.haml +15 -0
  121. data/views/drivers/index.xml.haml +7 -0
  122. data/views/drivers/show.html.haml +20 -0
  123. data/views/drivers/show.xml.haml +7 -0
  124. data/views/error.html.haml +31 -0
  125. data/views/errors/auth_exception.xml.haml +2 -1
  126. data/views/errors/backend_capability_failure.xml.haml +2 -1
  127. data/views/errors/backend_error.html.haml +3 -0
  128. data/views/errors/backend_error.xml.haml +2 -2
  129. data/views/errors/validation_failure.xml.haml +3 -2
  130. data/views/images/index.html.haml +1 -6
  131. data/views/images/index.xml.haml +2 -0
  132. data/views/images/new.html.haml +14 -0
  133. data/views/images/show.xml.haml +2 -0
  134. data/views/instances/index.html.haml +8 -6
  135. data/views/instances/index.xml.haml +4 -0
  136. data/views/instances/new.html.haml +40 -11
  137. data/views/instances/run.html.haml +9 -0
  138. data/views/instances/run.xml.haml +7 -0
  139. data/views/instances/run_command.html.haml +16 -0
  140. data/views/instances/show.html.haml +14 -0
  141. data/views/instances/show.xml.haml +12 -4
  142. data/views/layout.html.haml +7 -2
  143. data/views/load_balancers/index.html.haml +1 -1
  144. data/views/load_balancers/new.html.haml +2 -2
  145. data/views/load_balancers/show.html.haml +1 -1
  146. data/views/storage_snapshots/index.html.haml +3 -0
  147. data/views/storage_snapshots/new.html.haml +9 -0
  148. data/views/storage_volumes/attach.html.haml +20 -0
  149. data/views/storage_volumes/index.html.haml +16 -1
  150. data/views/storage_volumes/index.xml.haml +1 -10
  151. data/views/storage_volumes/new.html.haml +17 -0
  152. data/views/storage_volumes/show.html.haml +8 -0
  153. data/views/storage_volumes/show.xml.haml +25 -3
  154. metadata +197 -127
  155. data/lib/deltacloud/drivers/rackspace/rackspace_client.rb +0 -130
  156. data/parse.rb +0 -7
  157. data/test.rb +0 -3
  158. data/views/api/drivers.xml.haml +0 -6
@@ -1,4 +1,3 @@
1
- #
2
1
  # Copyright (C) 2009 RimuHosting Ltd
3
2
  # Author: Ivan Meredith <ivan@ivan.net.nz>
4
3
  #
@@ -0,0 +1,247 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one or more
3
+ # contributor license agreements. See the NOTICE file distributed with
4
+ # this work for additional information regarding copyright ownership. The
5
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance with the
7
+ # License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ # License for the specific language governing permissions and limitations
15
+ # under the License.
16
+
17
+ require 'base64'
18
+ require 'net/https'
19
+ require 'json'
20
+ require 'digest/md5'
21
+
22
+ module Deltacloud
23
+ module Drivers
24
+ module SBC
25
+
26
+ class FixtureNotFound < Exception; end
27
+
28
+ #
29
+ # Client for the IBM Smart Business Cloud (SBC).
30
+ #
31
+ # 31 January 2011
32
+ #
33
+ class SBCClient
34
+ API_URL = URI.parse('https://www-147.ibm.com/computecloud/enterprise/api/rest/20100331')
35
+
36
+ #
37
+ # Initialize the client
38
+ #
39
+ def initialize(username, password)
40
+ @username, @password = username, password
41
+ @rest_base = '/computecloud/enterprise/api/rest/20100331'
42
+ @service = Net::HTTP.new(API_URL.host, API_URL.port)
43
+ @service.use_ssl = true
44
+ end
45
+
46
+ #
47
+ # Retrieve instances
48
+ #
49
+ def list_instances(instance_id=nil)
50
+ if instance_id.nil?
51
+ JSON.parse(get('/instances', default_headers))['instances']
52
+ else
53
+ [ JSON.parse(get('/instances/' + instance_id, default_headers)) ]
54
+ end
55
+ end
56
+
57
+ #
58
+ # Reboot an instance
59
+ #
60
+ def reboot_instance(instance_id)
61
+ headers = default_headers
62
+ headers['Content-Type'] = 'application/x-www-form-urlencoded'
63
+ put('/instances/' + instance_id, 'state=restart', headers)
64
+ end
65
+
66
+ #
67
+ # Delete an instance
68
+ #
69
+ def delete_instance(instance_id)
70
+ delete('/instances/' + instance_id, default_headers)
71
+ end
72
+
73
+ #
74
+ # Retrieve images
75
+ #
76
+ def list_images(image_id=nil)
77
+ if image_id.nil?
78
+ JSON.parse(get('/offerings/image', default_headers))['images']
79
+ else
80
+ [ JSON.parse(get('/offerings/image/' + image_id, default_headers)) ]
81
+ end
82
+ end
83
+
84
+ #
85
+ # Retrieve locations; returns an XML document.
86
+ #
87
+ def list_locations
88
+ headers = default_headers
89
+ headers['Accept'] = 'text/xml' # JSON locations not supported
90
+ Nokogiri.XML(get('/locations', headers))
91
+ end
92
+
93
+ #
94
+ # Creates an instance
95
+ #
96
+ # body is a name/value hash to configure the instance
97
+ #
98
+ def create_instance(body)
99
+ headers = default_headers
100
+ headers['Content-Type'] = 'application/x-www-form-urlencoded'
101
+ JSON.parse(post('/instances', urlencode(body), headers))['instances']
102
+ end
103
+
104
+ #
105
+ # -------------------- Private Helpers -----------------
106
+ #
107
+ private
108
+
109
+ #
110
+ # HTTP GET
111
+ #
112
+ def get(path, headers)
113
+ if ENV['RACK_ENV'] == 'test'
114
+ mock_request(:get, path, {}, headers)
115
+ else
116
+ resp = @service.get(@rest_base + path, headers)
117
+ unless resp.is_a?(Net::HTTPSuccess)
118
+ backend_error!(resp)
119
+ end
120
+ resp.body
121
+ end
122
+ end
123
+
124
+ #
125
+ # HTTP PUT
126
+ #
127
+ def put(path, body, headers)
128
+ if ENV['RACK_ENV'] == 'test'
129
+ mock_request(:get, path, {}, headers)
130
+ else
131
+ resp = @service.put(@rest_base + path, body, headers)
132
+ unless resp.is_a?(Net::HTTPSuccess)
133
+ backend_error!(resp)
134
+ end
135
+ resp.body
136
+ end
137
+ end
138
+
139
+ #
140
+ # HTTP POST
141
+ #
142
+ def post(path, body, headers)
143
+ if ENV['RACK_ENV'] == 'test'
144
+ mock_request(:get, path, {}, headers)
145
+ else
146
+ resp = @service.post(@rest_base + path, body, headers)
147
+ unless resp.is_a?(Net::HTTPSuccess)
148
+ backend_error!(resp)
149
+ end
150
+ resp.body
151
+ end
152
+ end
153
+
154
+ #
155
+ # HTTP DELETE
156
+ #
157
+ def delete(path, headers)
158
+ if ENV['RACK_ENV'] == 'test'
159
+ mock_request(:get, path, {}, headers)
160
+ else
161
+ resp = @service.delete(@rest_base + path, headers)
162
+ unless resp.is_a?(Net::HTTPSuccess)
163
+ backend_error!(resp)
164
+ end
165
+ resp.body
166
+ end
167
+ end
168
+
169
+ #
170
+ # Default request headers.
171
+ #
172
+ def default_headers
173
+ {"Accept" => "application/json",
174
+ "User-Agent" => "deltacloud",
175
+ "Authorization" => "Basic " + Base64.encode64("#{@username}:#{@password}")}
176
+ end
177
+
178
+ #
179
+ # Handle request error
180
+ #
181
+ def backend_error!(resp)
182
+ if resp.is_a?(Net::HTTPUnauthorized)
183
+ raise Deltacloud::AuthException, resp.message
184
+ else
185
+ raise Deltacloud::BackendError.new(resp.code, resp.body, resp.message, '')
186
+ end
187
+ end
188
+
189
+ #
190
+ # Utility to URL encode a hash.
191
+ #
192
+ def urlencode(hash)
193
+ hash.keys.map { |k| "#{URI.encode(k)}=#{URI.encode(hash[k])}" }.join("&")
194
+ end
195
+
196
+ #
197
+ # Reads a fake URL from local fixtures
198
+ #
199
+ def read_fake_url(filename)
200
+ fixture_file = "../tests/sbc/support/fixtures/#{filename}"
201
+ if File.exists?(fixture_file)
202
+ puts "Using fixture: #{fixture_file}"
203
+ return JSON::parse(File.read(fixture_file))
204
+ else
205
+ raise FixtureNotFound.new
206
+ end
207
+ end
208
+
209
+ #
210
+ # Executes a fake request from local fixtures
211
+ #
212
+ def mock_request(*args)
213
+ http_method, request_uri, params, headers = args[0].to_sym, args[1], args[2], args[3]
214
+ params ||= {}
215
+ fixture_filename = fixture_filename = "#{Digest::MD5.hexdigest("#{http_method}#{request_uri}#{params.inspect}#{headers.reject{|key, value| key == "Authorization"}}")}.fixture"
216
+ puts "fixture filename: " + fixture_filename
217
+ begin
218
+ return read_fake_url(fixture_filename)[2]["body"]
219
+ rescue FixtureNotFound
220
+ if http_method.eql?(:get)
221
+ r = @service.get(@rest_base + request_uri, headers)
222
+ elsif http_method.eql?(:post)
223
+ r = @service.post(@rest_base + request_uri, body, headers)
224
+ elsif http_method.eql?(:put)
225
+ r = @service.put(@rest_base + request_uri, params, headers)
226
+ elsif http_method.eql?(:delete)
227
+ r = @service.delete(@rest_base + request_uri, headers)
228
+ end
229
+ response = {
230
+ "body" => r.body,
231
+ "status" => r.code,
232
+ "Content-Type" => r["Content-Type"]
233
+ }
234
+ fixtures_dir = "../tests/sbc/support/fixtures/"
235
+ FileUtils.mkdir_p(fixtures_dir)
236
+ puts "Saving fixture #{fixture_filename}"
237
+ File.open(File::join(fixtures_dir, fixture_filename), 'w') do |f|
238
+ f.puts [request_uri, http_method, response].to_json
239
+ end
240
+ retry
241
+ end
242
+ end
243
+
244
+ end
245
+ end
246
+ end
247
+ end
@@ -0,0 +1,297 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one or more
3
+ # contributor license agreements. See the NOTICE file distributed with
4
+ # this work for additional information regarding copyright ownership. The
5
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance with the
7
+ # License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ # License for the specific language governing permissions and limitations
15
+ # under the License.
16
+
17
+ require 'nokogiri'
18
+ require 'deltacloud/drivers/sbc/sbc_client'
19
+
20
+ module Deltacloud
21
+ module Drivers
22
+ module SBC
23
+ #
24
+ # Driver for the IBM Smart Business Cloud (SBC).
25
+ #
26
+ # 31 January 2011
27
+ #
28
+ class SBCDriver < Deltacloud::BaseDriver
29
+ #
30
+ # Retrieves images
31
+ #
32
+ def images(credentials, opts={})
33
+ sbc_client = new_client(credentials)
34
+ opts ||= {}
35
+ images = []
36
+ images = sbc_client.list_images(opts[:id]).map do |image|
37
+ # Cache image for create_instance; hwp is image-specific. In the
38
+ # current flow of the server, images is always called before a
39
+ # create_instance, making this caching profitable
40
+ @last_image = image
41
+ convert_image(image)
42
+ end
43
+ images = filter_on(images, :architecture, opts)
44
+ images = filter_on(images, :owner_id, opts)
45
+ images
46
+ end
47
+
48
+ #
49
+ # Retrieves realms
50
+ #
51
+ def realms(credentials, opts={})
52
+ sbc_client = new_client(credentials)
53
+ doc = sbc_client.list_locations
54
+ doc.xpath('ns2:DescribeLocationsResponse/Location').map { |loc| convert_location(loc) }
55
+ end
56
+
57
+ #
58
+ # Retrieves instances
59
+ #
60
+ def instances(credentials, opts={})
61
+ sbc_client = new_client(credentials)
62
+ opts ||= {}
63
+ instances = []
64
+ instances = sbc_client.list_instances(opts[:id]).map do |instance|
65
+ convert_instance(instance)
66
+ end
67
+ end
68
+
69
+ #
70
+ # Creates an instance
71
+ #
72
+ def create_instance(credentials, image_id, opts={})
73
+ sbc_client = new_client(credentials)
74
+
75
+ # Copy opts to body; keywords are mapped later
76
+ body = opts.dup
77
+ body.delete('image_id')
78
+ body.delete('hwp_id')
79
+ body.delete('realm_id')
80
+
81
+ # Lookup image if nil; tries to avoids extra lookup
82
+ if @last_image.nil? || @last_image['id'] != opts[:image_id]
83
+ @last_image = sbc_client.list_images(image_id).map[0]
84
+ end
85
+
86
+ # Map DeltaCloud keywords to SBC
87
+ body['imageID'] = opts[:image_id]
88
+ body['location'] = opts[:realm_id] || @last_image['location']
89
+ body['instanceType'] = opts[:hwp_id].gsub('-', '/') || @last_image['supportedInstanceTypes'][0]['id']
90
+
91
+ # Submit instance, parse response
92
+ convert_instance(sbc_client.create_instance(body).map[0])
93
+ end
94
+
95
+ #
96
+ # Reboots an instance
97
+ #
98
+ def reboot_instance(credentials, instance_id)
99
+ sbc_client = new_client(credentials)
100
+ sbc_client.reboot_instance(instance_id)
101
+ instance(credentials, instance_id)
102
+ end
103
+
104
+ #
105
+ # Stops an instance
106
+ #
107
+ def stop_instance(credentials, instance_id)
108
+ # Stop not supported; rebooting
109
+ reboot_instance(credentials, instance_id)
110
+ end
111
+
112
+ #
113
+ # Destroys an instance
114
+ #
115
+ def destroy_instance(credentials, instance_id)
116
+ sbc_client = new_client(credentials)
117
+ sbc_client.delete_instance(instance_id)
118
+ instance(credentials, instance_id)
119
+ end
120
+
121
+ #
122
+ # --------------------- Private helpers ---------------------
123
+ #
124
+ private
125
+
126
+ # SBC instance states mapped to DeltaCloud
127
+ @@INSTANCE_STATE_MAP = {
128
+ 0 => "PENDING", # New
129
+ 1 => "PENDING", # Provisioning
130
+ 2 => "STOPPED", # Failed
131
+ 3 => "STOPPED", # Removed
132
+ 4 => "STOPPED", # Rejected
133
+ 5 => "RUNNING", # Active
134
+ 6 => "STOPPED", # Unknown
135
+ 7 => "PENDING", # Deprovisioning
136
+ 8 => "PENDING", # Restarting
137
+ 9 => "PENDING", # Starting
138
+ 10 => "SHUTTING_DOWN", # Stopping
139
+ 11 => "STOPPED", # Stopped
140
+ 12 => "PENDING", # Deprovision pending
141
+ 13 => "PENDING", # Restart pending
142
+ 14 => "PENDING", # Attaching
143
+ 15 => "PENDING" # Detaching
144
+ }
145
+
146
+ # SBC image states mapped to DeltaCloud
147
+ @@IMAGE_STATE_MAP = {
148
+ 0 => "UNAVAILABLE", # New
149
+ 1 => "AVAILABLE", # Available
150
+ 2 => "UNAVAILABLE", # Unavailable
151
+ 3 => "UNAVAILABLE", # Deleted
152
+ 4 => "UNAVAILABLE" # Capturing
153
+ }
154
+
155
+ # SBC location states mapped to DeltaCloud
156
+ @@LOCATION_STATE_MAP = {
157
+ 0 => "UNAVAILABLE", # Unavailable
158
+ 1 => "AVAILABLE" # Available
159
+ }
160
+
161
+ #
162
+ # Define state machine for instances
163
+ #
164
+ define_instance_states do
165
+ start.to( :pending ) .automatically
166
+ pending.to( :running ) .automatically
167
+ running.to( :running ) .on( :reboot )
168
+ running.to( :finish ) .on( :destroy )
169
+ end
170
+
171
+ #
172
+ # Creates an IBM SBC client
173
+ #
174
+ def new_client(credentials)
175
+ safely do
176
+ return SBCClient.new(credentials.user, credentials.password)
177
+ end
178
+ end
179
+
180
+ #
181
+ # Converts JSON to an instance
182
+ #
183
+ def convert_instance(instance)
184
+ state = @@INSTANCE_STATE_MAP[instance["status"]]
185
+ Instance.new(
186
+ :id => instance["id"],
187
+ :owner_id => instance["owner"],
188
+ :image_id => instance["imageId"],
189
+ :name => instance["name"],
190
+ :realm_id => instance["location"],
191
+ :state => state,
192
+ :actions => instance_actions_for(state),
193
+ :public_addresses => [instance["primaryIP"]["ip"]],
194
+ :private_addresses => [],
195
+ :instance_profile => InstanceProfile.new(instance["instanceType"].gsub('/', '-')),
196
+ :launch_time => instance["launchTime"],
197
+ :keyname => instance["keyName"]
198
+ )
199
+ end
200
+
201
+ #
202
+ # Converts JSON to an image
203
+ #
204
+ def convert_image(image)
205
+ Image.new(
206
+ :id => image["id"],
207
+ :name => image["name"],
208
+ :owner_id => image["owner"],
209
+ :description => image["description"],
210
+ :architecture => "i386", # TODO: parse this from supportedInstanceType IDs w/ HW profile lookup
211
+ :state => @@IMAGE_STATE_MAP[image["state"]]
212
+ )
213
+ end
214
+
215
+ #
216
+ # Converts XML to a location
217
+ #
218
+ def convert_location(location)
219
+ Realm.new(
220
+ :id => location.xpath('ID').text,
221
+ :name => location.xpath('Name').text,
222
+ :limit => :unlimited,
223
+ :state => @@LOCATION_STATE_MAP[location.xpath('State').text.to_i]
224
+ )
225
+ end
226
+
227
+ #
228
+ # -------------------- Hardware Profiles -----------------
229
+ #
230
+ # TODO: HWP IDs contain '/'; results in invalid URL
231
+ #
232
+ define_hardware_profile('COP32.1-2048-60') do
233
+ cpu 1
234
+ memory 2 * 1024
235
+ storage 60
236
+ architecture 'i386'
237
+ end
238
+
239
+ define_hardware_profile('COP64.2-4096-60') do
240
+ cpu 2
241
+ memory 4 * 1024
242
+ storage 60
243
+ architecture 'i386_x64'
244
+ end
245
+
246
+ define_hardware_profile('BRZ32.1-2048-60*175') do
247
+ cpu 1
248
+ memory 2 * 1024
249
+ storage 175
250
+ architecture 'i386'
251
+ end
252
+
253
+ define_hardware_profile('BRZ64.2-4096-60*500*350') do
254
+ cpu 2
255
+ memory 4 * 1024
256
+ storage 850
257
+ architecture 'i386_x64'
258
+ end
259
+
260
+ define_hardware_profile('SLV32.2-4096-60*350') do
261
+ cpu 3
262
+ memory 5 * 1024
263
+ storage 350
264
+ architecture 'i386'
265
+ end
266
+
267
+ define_hardware_profile('SLV64.4-8192-60*500*500') do
268
+ cpu 4
269
+ memory 8 * 1024
270
+ storage 1024
271
+ architecture 'i386_x64'
272
+ end
273
+
274
+ define_hardware_profile('GLD32.4-4096-60*350') do
275
+ cpu 4
276
+ memory 4 * 1024
277
+ storage 350
278
+ architecture 'i386'
279
+ end
280
+
281
+ define_hardware_profile('GLD64.8-16384-60*500*500') do
282
+ cpu 8
283
+ memory 16 * 1024
284
+ storage 1024
285
+ architecture 'i386_x64'
286
+ end
287
+
288
+ define_hardware_profile('PLT64.16-16384-60*500*500*500*500') do
289
+ cpu 16
290
+ memory 16 * 1024
291
+ storage 2048
292
+ architecture 'i386_x64'
293
+ end
294
+ end
295
+ end
296
+ end
297
+ end