deltacloud-core 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (242) hide show
  1. data/LICENSE +145 -0
  2. data/NOTICE +10 -1
  3. data/Rakefile +50 -2
  4. data/bin/deltacloudd +111 -14
  5. data/config/addresses.xml +14 -0
  6. data/config/condor.yaml +30 -0
  7. data/config/drivers/azure.yaml +3 -0
  8. data/config/drivers/condor.yaml +3 -0
  9. data/config/{drivers.yaml → drivers/ec2.yaml} +5 -34
  10. data/config/drivers/eucalyptus.yaml +8 -0
  11. data/config/drivers/gogrid.yaml +3 -0
  12. data/config/drivers/mock.yaml +3 -0
  13. data/config/drivers/opennebula.yaml +4 -0
  14. data/config/drivers/rackspace.yaml +3 -0
  15. data/config/drivers/rhevm.yaml +3 -0
  16. data/config/drivers/rimuhosting.yaml +3 -0
  17. data/config/drivers/sbc.yaml +2 -0
  18. data/config/drivers/terremark.yaml +3 -0
  19. data/config/drivers/vsphere.yaml +8 -0
  20. data/deltacloud-core.gemspec +13 -5
  21. data/deltacloud.rb +4 -2
  22. data/lib/deltacloud/backend_capability.rb +2 -2
  23. data/lib/deltacloud/base_driver/base_driver.rb +23 -52
  24. data/lib/deltacloud/base_driver/exceptions.rb +168 -0
  25. data/lib/deltacloud/base_driver/features.rb +31 -12
  26. data/lib/deltacloud/base_driver/mock_driver.rb +2 -1
  27. data/lib/deltacloud/core_ext/string.rb +2 -0
  28. data/lib/deltacloud/drivers/azure/azure_driver.rb +5 -5
  29. data/lib/deltacloud/drivers/condor/condor_client.rb +273 -0
  30. data/lib/deltacloud/drivers/condor/condor_driver.rb +236 -0
  31. data/lib/deltacloud/drivers/condor/ip_agents/confserver.rb +75 -0
  32. data/lib/deltacloud/drivers/condor/ip_agents/default.rb +84 -0
  33. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +326 -95
  34. data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +3 -3
  35. data/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb +40 -8
  36. data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +7 -7
  37. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +42 -25
  38. data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob1.yml +6 -4
  39. data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob2.yml +7 -5
  40. data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob3.yml +6 -4
  41. data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob4.yml +6 -4
  42. data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob5.yml +6 -4
  43. data/lib/deltacloud/drivers/mock/data/buckets/bucket1.yml +7 -1
  44. data/lib/deltacloud/drivers/mock/data/buckets/bucket2.yml +6 -1
  45. data/lib/deltacloud/drivers/mock/data/images/img1.yml +6 -2
  46. data/lib/deltacloud/drivers/mock/data/images/img2.yml +6 -2
  47. data/lib/deltacloud/drivers/mock/data/images/img3.yml +6 -2
  48. data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +11 -10
  49. data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +14 -7
  50. data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +14 -7
  51. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap1.yml +3 -2
  52. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap2.yml +3 -2
  53. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap3.yml +3 -2
  54. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol1.yml +4 -3
  55. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol2.yml +4 -3
  56. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol3.yml +4 -3
  57. data/lib/deltacloud/drivers/mock/mock_client.rb +101 -0
  58. data/lib/deltacloud/drivers/mock/mock_driver.rb +367 -429
  59. data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +6 -0
  60. data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +59 -9
  61. data/lib/deltacloud/drivers/rhevm/rhevm_client.rb +62 -8
  62. data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +100 -45
  63. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb +3 -2
  64. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +8 -11
  65. data/lib/deltacloud/drivers/sbc/sbc_client.rb +6 -6
  66. data/lib/deltacloud/drivers/sbc/sbc_driver.rb +16 -0
  67. data/lib/deltacloud/drivers/terremark/terremark_driver.rb +17 -12
  68. data/lib/deltacloud/drivers/vsphere/vsphere_client.rb +140 -0
  69. data/lib/deltacloud/drivers/vsphere/vsphere_driver.rb +405 -0
  70. data/lib/deltacloud/drivers/vsphere/vsphere_filemanager.rb +182 -0
  71. data/lib/deltacloud/hardware_profile.rb +1 -1
  72. data/lib/deltacloud/helpers.rb +2 -1
  73. data/lib/deltacloud/helpers/application_helper.rb +92 -20
  74. data/lib/deltacloud/helpers/blob_stream.rb +160 -12
  75. data/lib/deltacloud/helpers/conversion_helper.rb +6 -2
  76. data/lib/deltacloud/helpers/json_helper.rb +31 -0
  77. data/lib/deltacloud/models/address.rb +28 -0
  78. data/lib/deltacloud/models/base_model.rb +5 -1
  79. data/lib/deltacloud/models/blob.rb +1 -1
  80. data/lib/deltacloud/models/bucket.rb +10 -0
  81. data/lib/deltacloud/models/firewall.rb +22 -0
  82. data/lib/deltacloud/models/firewall_rule.rb +23 -0
  83. data/lib/deltacloud/models/image.rb +12 -0
  84. data/lib/deltacloud/models/instance.rb +20 -2
  85. data/lib/deltacloud/models/key.rb +1 -1
  86. data/lib/deltacloud/runner.rb +3 -3
  87. data/lib/deltacloud/validation.rb +3 -7
  88. data/lib/drivers.rb +7 -1
  89. data/lib/sinatra/body_proxy.rb +34 -0
  90. data/lib/sinatra/lazy_auth.rb +5 -0
  91. data/lib/sinatra/rabbit.rb +54 -31
  92. data/lib/sinatra/rack_accept.rb +157 -0
  93. data/lib/sinatra/rack_date.rb +38 -0
  94. data/lib/sinatra/rack_etag.rb +2 -3
  95. data/lib/sinatra/rack_matrix_params.rb +51 -29
  96. data/lib/sinatra/rack_runtime.rb +1 -1
  97. data/lib/sinatra/rack_syslog.rb +86 -0
  98. data/lib/sinatra/url_for.rb +14 -1
  99. data/public/images/address.png +0 -0
  100. data/public/images/balancer.png +0 -0
  101. data/public/images/blob.png +0 -0
  102. data/public/images/bucket.png +0 -0
  103. data/public/images/cloud.png +0 -0
  104. data/public/images/firewall.png +0 -0
  105. data/public/images/image.png +0 -0
  106. data/public/images/key.png +0 -0
  107. data/public/images/machine.png +0 -0
  108. data/public/images/profile.png +0 -0
  109. data/public/images/realm.png +0 -0
  110. data/public/images/snapshot.png +0 -0
  111. data/public/images/volume.png +0 -0
  112. data/public/javascripts/application.js +119 -16
  113. data/public/javascripts/jquery.min.js +18 -0
  114. data/public/javascripts/jquery.mobile-1.0b1.min.js +146 -0
  115. data/public/stylesheets/compiled/application.css +8 -0
  116. data/public/stylesheets/images/ajax-loader.png +0 -0
  117. data/public/{images → stylesheets/images}/bread-bg.png +0 -0
  118. data/public/{images → stylesheets/images}/error.png +0 -0
  119. data/public/{images → stylesheets/images}/grid.png +0 -0
  120. data/public/stylesheets/images/icon-search-black.png +0 -0
  121. data/public/stylesheets/images/icons-18-black.png +0 -0
  122. data/public/stylesheets/images/icons-18-white.png +0 -0
  123. data/public/stylesheets/images/icons-36-black.png +0 -0
  124. data/public/stylesheets/images/icons-36-white.png +0 -0
  125. data/public/{images → stylesheets/images}/logo-wide.png +0 -0
  126. data/public/{images → stylesheets/images}/pending.png +0 -0
  127. data/public/{images → stylesheets/images}/rails.png +0 -0
  128. data/public/{images → stylesheets/images}/running.png +0 -0
  129. data/public/{images → stylesheets/images}/stopped.png +0 -0
  130. data/public/{images → stylesheets/images}/topbar-bg.png +0 -0
  131. data/public/stylesheets/jquery.mobile-1.0b1.min.css +8 -0
  132. data/public/stylesheets/new.css +53 -0
  133. data/server.rb +487 -175
  134. data/support/condor/bash/cached_images.sh +8 -0
  135. data/support/condor/bash/cloud_exit_hook.sh +17 -0
  136. data/support/condor/bash/cloud_functions +175 -0
  137. data/support/condor/bash/cloud_prepare_hook.sh +20 -0
  138. data/support/condor/bash/libvirt_cloud_script.sh +13 -0
  139. data/support/condor/config/50condor_cloud.config +37 -0
  140. data/support/condor/config/50condor_cloud_node.config +37 -0
  141. data/support/condor/config/condor-cloud +2 -0
  142. data/support/condor/config/condor_config.local +44 -0
  143. data/support/fedora/deltacloud-core +48 -26
  144. data/support/fedora/deltacloud-core-config +26 -0
  145. data/support/fedora/deltacloud-core.spec +314 -68
  146. data/support/fedora/deltacloudd-fedora +5 -0
  147. data/tests/common.rb +34 -4
  148. data/tests/drivers/mock/api_test.rb +3 -3
  149. data/tests/drivers/mock/images_test.rb +12 -0
  150. data/tests/drivers/mock/instances_test.rb +2 -0
  151. data/tests/rabbit_test.rb +2 -2
  152. data/views/addresses/_address.html.haml +6 -0
  153. data/views/addresses/associate.html.haml +12 -0
  154. data/views/addresses/index.html.haml +9 -0
  155. data/views/addresses/index.xml.haml +4 -0
  156. data/views/addresses/show.html.haml +21 -0
  157. data/views/addresses/show.xml.haml +14 -0
  158. data/views/api/show.html.haml +6 -11
  159. data/views/api/show.xml.haml +2 -0
  160. data/views/blobs/new.html.haml +24 -23
  161. data/views/blobs/show.html.haml +30 -31
  162. data/views/buckets/index.html.haml +9 -21
  163. data/views/buckets/index.xml.haml +3 -7
  164. data/views/buckets/new.html.haml +13 -12
  165. data/views/buckets/show.html.haml +22 -22
  166. data/views/buckets/show.xml.haml +5 -3
  167. data/views/docs/collection.html.haml +23 -34
  168. data/views/docs/collection.xml.haml +2 -2
  169. data/views/docs/index.html.haml +9 -13
  170. data/views/docs/index.xml.haml +1 -1
  171. data/views/docs/operation.html.haml +28 -38
  172. data/views/docs/operation.xml.haml +1 -1
  173. data/views/drivers/index.html.haml +8 -13
  174. data/views/drivers/show.html.haml +18 -18
  175. data/views/error.html.haml +32 -27
  176. data/views/errors/400.html.haml +41 -0
  177. data/views/errors/{validation_failure.xml.haml → 400.xml.haml} +0 -4
  178. data/views/errors/401.html.haml +41 -0
  179. data/views/errors/{auth_exception.xml.haml → 401.xml.haml} +0 -0
  180. data/views/errors/403.html.haml +42 -0
  181. data/views/errors/{not_allowed.xml.haml → 403.xml.haml} +0 -0
  182. data/views/errors/404.html.haml +29 -0
  183. data/views/errors/{not_found.xml.haml → 404.xml.haml} +1 -1
  184. data/views/errors/405.html.haml +29 -0
  185. data/views/errors/405.xml.haml +5 -0
  186. data/views/errors/500.html.haml +43 -0
  187. data/views/errors/500.xml.haml +5 -0
  188. data/views/errors/502.html.haml +43 -0
  189. data/views/errors/{backend_error.xml.haml → 502.xml.haml} +1 -2
  190. data/views/errors/backend_capability_failure.html.haml +27 -9
  191. data/views/firewalls/index.html.haml +15 -0
  192. data/views/firewalls/index.xml.haml +28 -0
  193. data/views/firewalls/new.html.haml +11 -0
  194. data/views/firewalls/new_rule.html.haml +20 -0
  195. data/views/firewalls/show.html.haml +42 -0
  196. data/views/firewalls/show.xml.haml +26 -0
  197. data/views/hardware_profiles/index.html.haml +15 -23
  198. data/views/hardware_profiles/show.html.haml +22 -18
  199. data/views/images/index.html.haml +11 -23
  200. data/views/images/index.xml.haml +4 -13
  201. data/views/images/new.html.haml +12 -13
  202. data/views/images/show.html.haml +26 -20
  203. data/views/images/show.xml.haml +2 -1
  204. data/views/instance_states/show.html.haml +21 -25
  205. data/views/instances/index.html.haml +13 -30
  206. data/views/instances/index.xml.haml +2 -23
  207. data/views/instances/new.html.haml +83 -88
  208. data/views/instances/show.html.haml +53 -55
  209. data/views/instances/show.xml.haml +12 -10
  210. data/views/keys/index.html.haml +13 -24
  211. data/views/keys/new.html.haml +7 -7
  212. data/views/keys/show.html.haml +26 -21
  213. data/views/layout.html.haml +28 -27
  214. data/views/load_balancers/index.html.haml +11 -31
  215. data/views/load_balancers/index.xml.haml +0 -1
  216. data/views/load_balancers/new.html.haml +1 -1
  217. data/views/load_balancers/show.html.haml +33 -34
  218. data/views/load_balancers/show.xml.haml +2 -2
  219. data/views/realms/index.html.haml +11 -24
  220. data/views/realms/index.xml.haml +2 -8
  221. data/views/realms/show.html.haml +17 -15
  222. data/views/realms/show.xml.haml +2 -1
  223. data/views/storage_snapshots/index.html.haml +11 -21
  224. data/views/storage_snapshots/index.xml.haml +2 -5
  225. data/views/storage_snapshots/new.html.haml +1 -1
  226. data/views/storage_snapshots/show.html.haml +21 -13
  227. data/views/storage_snapshots/show.xml.haml +2 -1
  228. data/views/storage_volumes/index.html.haml +11 -34
  229. data/views/storage_volumes/new.html.haml +1 -1
  230. data/views/storage_volumes/show.html.haml +33 -27
  231. data/views/storage_volumes/show.xml.haml +2 -1
  232. metadata +266 -178
  233. data/lib/sinatra/respond_to.rb +0 -248
  234. data/support/fedora/deltacloudd +0 -128
  235. data/support/fedora/rubygem-deltacloud-core.spec +0 -127
  236. data/views/accounts/index.html.haml +0 -11
  237. data/views/accounts/show.html.haml +0 -30
  238. data/views/errors/auth_exception.html.haml +0 -8
  239. data/views/errors/backend_error.html.haml +0 -22
  240. data/views/errors/not_allowed.html.haml +0 -6
  241. data/views/errors/not_found.html.haml +0 -6
  242. data/views/errors/validation_failure.html.haml +0 -11
@@ -31,6 +31,8 @@ module Deltacloud
31
31
 
32
32
  class OpennebulaDriver < Deltacloud::BaseDriver
33
33
 
34
+ feature :instances, :user_name
35
+
34
36
  ######################################################################
35
37
  # Hardware profiles
36
38
  ######################################################################
@@ -126,6 +128,10 @@ class OpennebulaDriver < Deltacloud::BaseDriver
126
128
 
127
129
  hwp_id = opts[:hwp_id] || 'small'
128
130
 
131
+ if not opts[:name]
132
+ opts[:name] = "#{Time.now.to_i.to_s}#{rand(9)}"
133
+ end
134
+
129
135
  instancexml = ERB.new(OCCI_VM).result(binding)
130
136
  instancefile = "|echo '#{instancexml}'"
131
137
 
@@ -109,6 +109,16 @@ class RackspaceDriver < Deltacloud::BaseDriver
109
109
  end
110
110
  end
111
111
 
112
+ def destroy_image(credentials, image_id)
113
+ rax_client = new_client(credentials)
114
+ safely do
115
+ image = rax_client.get_image(image_id.to_i)
116
+ unless image.delete!
117
+ raise "ERROR: Cannot delete image with ID:#{image_id}"
118
+ end
119
+ end
120
+ end
121
+
112
122
  def run_on_instance(credentials, opts={})
113
123
  target = instance(credentials, :id => opts[:id])
114
124
  param = {}
@@ -262,7 +272,7 @@ class RackspaceDriver < Deltacloud::BaseDriver
262
272
  def create_blob(credentials, bucket_id, blob_id, blob_data, opts={})
263
273
  cf = cloudfiles_client(credentials)
264
274
  #insert ec2-specific header for user metadata ... X-Object-Meta-KEY = VALUE
265
- opts.gsub_keys("HTTP_X_Deltacloud_Blobmeta_", "X-Object-Meta-")
275
+ BlobHelper::rename_metadata_headers(opts, "X-Object-Meta-")
266
276
  opts['Content-Type'] = blob_data[:type]
267
277
  object = nil
268
278
  safely do
@@ -311,11 +321,39 @@ class RackspaceDriver < Deltacloud::BaseDriver
311
321
  cf = cloudfiles_client(credentials)
312
322
  meta_hash = opts['meta_hash']
313
323
  #the set_metadata method actually places the 'X-Object-Meta-' prefix for us:
314
- meta_hash.gsub_keys('HTTP_X_Deltacloud_Blobmeta_', '')
324
+ BlobHelper::rename_metadata_headers(meta_hash, '')
315
325
  safely do
316
326
  blob = cf.container(opts['bucket']).object(opts[:id])
317
327
  blob.set_metadata(meta_hash)
318
- end
328
+ end
329
+ end
330
+
331
+ #params: {:user,:password,:bucket,:blob,:content_type,:content_length,:metadata}
332
+ def blob_stream_connection(params)
333
+ #create a cloudfiles connection object to get the authtoken
334
+ cf, cf_host, cf_path, cf_authtoken = nil
335
+ safely do
336
+ cf = CloudFiles::Connection.new(:username => params[:user],
337
+ :api_key => params[:password])
338
+ cf_authtoken = cf.authtoken
339
+ cf_host = cf.storagehost
340
+ cf_path = cf.storagepath
341
+ end
342
+ provider = "https://#{cf_host}"
343
+ uri = URI.parse(provider)
344
+ http = Net::HTTP.new(uri.host, uri.port )
345
+ http.use_ssl = true
346
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
347
+ request = Net::HTTP::Put.new("#{cf_path}/#{params[:bucket]}/#{params[:blob]}")
348
+ request['Host'] = "#{cf_host}"
349
+ request['X-Auth-Token'] = "#{cf_authtoken}"
350
+ request['Content-Type'] = params[:content_type]
351
+ request['Content-Length'] = params[:content_length]
352
+ request['Expect'] = "100-continue"
353
+ metadata = params[:metadata] || {}
354
+ BlobHelper::rename_metadata_headers(metadata, 'X-Object-Meta-')
355
+ metadata.each{|k,v| request[k] = v}
356
+ return http, request
319
357
  end
320
358
 
321
359
  private
@@ -391,12 +429,24 @@ private
391
429
  end
392
430
  end
393
431
 
394
- def catched_exceptions_list
395
- {
396
- :auth => [ /Authentication failed/ ],
397
- :error => [ /Error/ ],
398
- :glob => [ /CloudServers::Exception::(\w+)/, /Deltacloud::Runner::(\w+)/ ]
399
- }
432
+ exceptions do
433
+
434
+ on /No offering found/ do
435
+ status 400
436
+ end
437
+
438
+ on /Authentication failed/ do
439
+ status 401
440
+ end
441
+
442
+ on /Error/ do
443
+ status 500
444
+ end
445
+
446
+ on /CloudServers::Exception::(\w+)/ do
447
+ status 500
448
+ end
449
+
400
450
  end
401
451
 
402
452
  private
@@ -1,3 +1,19 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership. The
4
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+ #
16
+
1
17
  require 'rubygems'
2
18
  require 'base64'
3
19
  require 'restclient'
@@ -58,7 +74,7 @@ module RHEVM
58
74
  template_(:id => template_id)
59
75
  cluster(:id => opts[:realm_id] || clusters.first.id)
60
76
  type_ opts[:hwp_id] || 'desktop'
61
- memory opts[:hwp_memory] || (512*1024*1024).to_s
77
+ memory opts[:hwp_memory] ? (opts[:hwp_memory].to_i*1024*1024).to_s : (512*1024*1024).to_s
62
78
  cpu {
63
79
  topology( :cores => (opts[:hwp_cpu] || '1'), :sockets => '1' )
64
80
  }
@@ -74,6 +90,35 @@ module RHEVM
74
90
  RHEVM::VM::new(self, Nokogiri::XML(vm).root)
75
91
  end
76
92
 
93
+ def create_template(vm_id, opts={})
94
+ opts ||= {}
95
+ builder = Nokogiri::XML::Builder.new do
96
+ template_ {
97
+ name opts[:name]
98
+ description opts[:description]
99
+ vm(:id => vm_id)
100
+ }
101
+ end
102
+ headers = opts[:headers] || {}
103
+ headers.merge!({
104
+ :content_type => 'application/xml',
105
+ :accept => 'application/xml',
106
+ })
107
+ headers.merge!(auth_header)
108
+ template = RHEVM::client(@api_entrypoint)["/templates"].post(Nokogiri::XML(builder.to_xml).root.to_s, headers)
109
+ RHEVM::Template::new(self, Nokogiri::XML(template).root)
110
+ end
111
+
112
+ def destroy_template(id, headers={})
113
+ headers.merge!({
114
+ :content_type => 'application/xml',
115
+ :accept => 'application/xml',
116
+ })
117
+ headers.merge!(auth_header)
118
+ RHEVM::client(@api_entrypoint)["/templates/%s" % id].delete(headers)
119
+ return true
120
+ end
121
+
77
122
  def templates(opts={})
78
123
  headers = {
79
124
  :accept => "application/xml"
@@ -99,8 +144,8 @@ module RHEVM
99
144
  [ RHEVM::Cluster::new(self, vm)]
100
145
  else
101
146
  Client::parse_response(RHEVM::client(@api_entrypoint)["/clusters"].get(headers)).xpath('/clusters/cluster').collect do |vm|
102
- RHEVM::Cluster::new(self, vm)
103
- end
147
+ RHEVM::Cluster::new(self, vm) if has_datacenter?(vm)
148
+ end.compact
104
149
  end
105
150
  end
106
151
 
@@ -150,7 +195,9 @@ module RHEVM
150
195
  end
151
196
 
152
197
  def auth_header
153
- { :authorization => "Basic " + Base64.encode64("#{@credentials[:username]}:#{@credentials[:password]}"), }
198
+ # As RDOC says this is the function for strict_encode64:
199
+ encoded_credentials = ["#{@credentials[:username]}:#{@credentials[:password]}"].pack("m0").gsub(/\n/,'')
200
+ { :authorization => "Basic " + encoded_credentials }
154
201
  end
155
202
 
156
203
  def base_url
@@ -162,6 +209,10 @@ module RHEVM
162
209
  Nokogiri::XML(response)
163
210
  end
164
211
 
212
+ def has_datacenter?(vm)
213
+ value=!(vm/'data_center').empty?
214
+ value
215
+ end
165
216
  end
166
217
 
167
218
  class BaseObject
@@ -173,7 +224,6 @@ module RHEVM
173
224
  @client = client
174
225
  self
175
226
  end
176
-
177
227
  end
178
228
 
179
229
  class Link
@@ -195,7 +245,7 @@ module RHEVM
195
245
  class VM < BaseObject
196
246
  attr_reader :description, :status, :memory, :profile, :display, :host, :cluster, :template, :macs
197
247
  attr_reader :storage, :cores, :username, :creation_time
198
- attr_reader :ip
248
+ attr_reader :ip, :vnc
199
249
 
200
250
  def initialize(client, xml)
201
251
  super(client, xml[:id], xml[:href], (xml/'name').first.text)
@@ -225,6 +275,10 @@ module RHEVM
225
275
  @macs = (xml/'nics/nic/mac').collect { |mac| mac[:address] }
226
276
  @creation_time = (xml/'creation_time').text
227
277
  @ip = ((xml/'guest_info/ip').first[:address] rescue nil)
278
+ unless @ip
279
+ @vnc = ((xml/'display/address').first.text rescue "127.0.0.1")
280
+ @vnc += ":#{((xml/'display/port').first.text rescue "5890")}"
281
+ end
228
282
  end
229
283
 
230
284
  end
@@ -262,6 +316,7 @@ module RHEVM
262
316
  @description = ((xml/'description').first.text rescue nil)
263
317
  @datacenter = Link::new(@client, (xml/'data_center').first[:id], (xml/'data_center').first[:href])
264
318
  end
319
+
265
320
  end
266
321
 
267
322
  class DataCenter < BaseObject
@@ -318,7 +373,7 @@ module RHEVM
318
373
  @path = ((xml/'storage/path').first.text rescue nil)
319
374
  end
320
375
  end
321
-
376
+
322
377
  end
323
378
 
324
379
  class String
@@ -329,4 +384,3 @@ class String
329
384
  end
330
385
  end
331
386
  end
332
-
@@ -33,7 +33,11 @@ module Deltacloud
33
33
 
34
34
  class RHEVMDriver < Deltacloud::BaseDriver
35
35
 
36
- feature :instances, :user_name
36
+ feature :instances, :user_name do
37
+ constraint :max_length, 50
38
+ end
39
+
40
+ USER_NAME_MAX = feature(:instances, :user_name).constraints[:max_length]
37
41
 
38
42
  # FIXME: These values are just for ilustration
39
43
  # Also I choosed 'SERVER' and 'DESKTOP' names
@@ -56,26 +60,9 @@ class RHEVMDriver < Deltacloud::BaseDriver
56
60
  architecture 'x86_64'
57
61
  end
58
62
 
59
- # Instead of setting a URL for RHEV provider
60
- # do it here in driver, so it can be altered by HTTP headers
61
- #
62
- def provider_uri=(uri)
63
- @RHEVM_URI = uri
64
- end
65
-
66
- # Default Provider URI.
67
- #
68
- # IMPORTANT:
69
- # This URI can be overridden using shell variable API_PROVIDER
70
- # or setting provider using HTTP header X-Deltacloud-Provider to URL.
71
- #
72
- def provider_uri
73
- Deltacloud::Drivers::driver_config[:rhevm][:entrypoints]['default']['default']
74
- end
75
-
76
63
  define_instance_states do
77
64
  start.to( :pending ) .automatically
78
- pending.to( :running ) .automatically
65
+ pending.to( :running ) .on( :start )
79
66
  pending.to( :stopped ) .automatically
80
67
  stopped.to( :running ) .on( :start )
81
68
  running.to( :stopping ) .on( :stop )
@@ -96,6 +83,7 @@ class RHEVMDriver < Deltacloud::BaseDriver
96
83
  realm_arr << convert_realm(r, d)
97
84
  end
98
85
  end
86
+ realm_arr = filter_on( realm_arr, :id, opts )
99
87
  realm_arr
100
88
  end
101
89
 
@@ -115,6 +103,29 @@ class RHEVMDriver < Deltacloud::BaseDriver
115
103
  img_arr.sort_by{|e| [e.owner_id, e.name]}
116
104
  end
117
105
 
106
+ def create_image(credentials, opts={})
107
+ client = new_client(credentials)
108
+ unless opts[:name]
109
+ instance = instances(credentials, :id => opts[:id])
110
+ raise "Specified instance '#{opts[:id]}' not found"
111
+ template_name = "#{instance.first.name}-template"
112
+ end
113
+ safely do
114
+ new_image = client.create_template(opts[:id], :name => (opts[:name] || template_name),
115
+ :description => opts[:description])
116
+ convert_image(client, new_image)
117
+ end
118
+ end
119
+
120
+ def destroy_image(credentials, image_id)
121
+ client = new_client(credentials)
122
+ safely do
123
+ unless client.destroy_template(image_id)
124
+ raise "ERROR: Unable to remove image"
125
+ end
126
+ end
127
+ end
128
+
118
129
  def instances(credentials, opts={})
119
130
  client = new_client(credentials)
120
131
  inst_arr = []
@@ -168,8 +179,15 @@ class RHEVMDriver < Deltacloud::BaseDriver
168
179
  def create_instance(credentials, image_id, opts={})
169
180
  client = new_client(credentials)
170
181
  params = {}
182
+ name = opts[:name]
183
+ if not name
184
+ name = Time.now.to_i.to_s
185
+ end
186
+ if name.length > USER_NAME_MAX
187
+ raise "Parameter name must be #{USER_NAME_MAX} characters or less"
188
+ end
171
189
  safely do
172
- params[:name] = opts[:name] if opts[:name]
190
+ params[:name] = name
173
191
  params[:realm_id] = opts[:realm_id] if opts[:realm_id]
174
192
  params[:hwp_id] = opts[:hwp_id] if opts[:hwp_id]
175
193
  params[:hwp_memory] = opts[:hwp_memory] if opts[:hwp_memory]
@@ -182,8 +200,8 @@ class RHEVMDriver < Deltacloud::BaseDriver
182
200
  retval = true
183
201
  begin
184
202
  realms(credentials)
185
- rescue Deltacloud::BackendError
186
- retval = false
203
+ rescue
204
+ retval = false
187
205
  end
188
206
  retval
189
207
  end
@@ -191,26 +209,35 @@ class RHEVMDriver < Deltacloud::BaseDriver
191
209
  private
192
210
 
193
211
  def new_client(credentials)
194
- url = (Thread.current[:provider] || ENV['API_PROVIDER'] || provider_uri)
212
+ url = api_provider
195
213
  safely do
196
214
  ::RHEVM::Client.new(credentials.user, credentials.password, url)
197
215
  end
198
216
  end
199
217
 
218
+ def confserver_ip(uuid)
219
+ client = RestClient::Resource::new(ENV['CONFIG_SERVER_ADDRESS'])
220
+ client["/ip/%s/%s" % [ (ENV['CONFIG_SERVER_VERSION'] || '0.0.1'), uuid]].get(:accept => 'text/plain').body.strip rescue nil
221
+ end
222
+
200
223
  def convert_instance(client, inst)
201
224
  state = convert_state(inst.status)
202
225
  storage_size = inst.storage.nil? ? 1 : (inst.storage.to_i/1024/1024/1024)
203
- profile = InstanceProfile::new(inst.profile.upcase,
226
+ profile = InstanceProfile::new(inst.profile.upcase,
204
227
  :hwp_memory => inst.memory.to_i/1024/1024,
205
228
  :hwp_cpu => inst.cores,
206
229
  :hwp_storage => "#{storage_size}"
207
230
  )
208
- # Include VNC and SPICE addresses
209
- if inst.ip
210
- public_addresses = [ inst.ip ]
211
- else
212
- public_addresses = [ inst.macs ]
213
- end
231
+ public_addresses = []
232
+ # First check if RHEV-M guest tools are installed and IP address is offered by them
233
+ public_addresses << inst.ip if inst.ip
234
+ # Second check if ConfServer broker is running, then ask for an IP there
235
+ public_addresses << confserver_ip(inst.id) if ENV['CONFIG_SERVER_ADDRESS'] and public_addresses.empty?
236
+ public_addresses.compact!
237
+ # If everything fails fallback to report MAC address
238
+ public_addresses = inst.macs if public_addresses.empty?
239
+ public_addresses.flatten!
240
+ public_addresses << inst.vnc if inst.vnc
214
241
  Instance.new(
215
242
  :id => inst.id,
216
243
  :name => inst.name,
@@ -223,18 +250,23 @@ class RHEVMDriver < Deltacloud::BaseDriver
223
250
  :hardware_profile_id => profile.id,
224
251
  :actions=>instance_actions_for( state ),
225
252
  :public_addresses => public_addresses,
226
- :private_addresses => []
253
+ :private_addresses => [],
254
+ :create_image => true
227
255
  )
228
256
  end
229
257
 
230
- # STATES:
258
+ # STATES:
231
259
  #
232
- # UNASSIGNED, DOWN, UP, POWERING_UP, POWERED_DOWN, PAUSED, MIGRATING_FROM, MIGRATING_TO,
233
- # UNKNOWN, NOT_RESPONDING, WAIT_FOR_LAUNCH, REBOOT_IN_PROGRESS, SAVING_STATE, RESTORING_STATE,
234
- # SUSPENDED, IMAGE_ILLEGAL, IMAGE_LOCKED or POWERING_DOWN
260
+ # UNASSIGNED, DOWN, UP, POWERING_UP, POWERED_DOWN, PAUSED, MIGRATING_FROM,
261
+ # MIGRATING_TO, UNKNOWN, NOT_RESPONDING, WAIT_FOR_LAUNCH, REBOOT_IN_PROGRESS,
262
+ # SAVING_STATE, RESTORING_STATE, SUSPENDED, IMAGE_ILLEGAL,
263
+ # IMAGE_LOCKED or POWERING_DOWN
235
264
  #
236
265
  def convert_state(state)
237
- case state
266
+ unless state.respond_to?(:upcase)
267
+ raise "State #{state.inspect} is not a string"
268
+ end
269
+ case state.strip.upcase
238
270
  when 'WAIT_FOR_LAUNCH', 'REBOOT_IN_PROGRESS', 'SAVING_STATE',
239
271
  'RESTORING_STATE', 'POWERING_DOWN', 'POWERING_UP', 'IMAGE_LOCKED', 'SAVING_STATE' then
240
272
  'PENDING'
@@ -242,6 +274,8 @@ class RHEVMDriver < Deltacloud::BaseDriver
242
274
  'STOPPED'
243
275
  when 'UP', 'MIGRATING_TO', 'MIGRATING_FROM'
244
276
  'RUNNING'
277
+ else
278
+ raise "Unexpected state '#{state}'"
245
279
  end
246
280
  end
247
281
 
@@ -277,15 +311,36 @@ class RHEVMDriver < Deltacloud::BaseDriver
277
311
  )
278
312
  end
279
313
 
280
- # Disabling this error catching will lead to more verbose messages
281
- # on console (eg. response from RHEV-M API (so far I didn't figure our
282
- # how to pass those message to our exception handling tool)
283
- def catched_exceptions_list
284
- {
285
- :auth => [RestClient::Unauthorized],
286
- :error => [RestClient::InternalServerError],
287
- :glob => [ /(RestClient|RHEVM)::(\w+)/ ]
288
- }
314
+ exceptions do
315
+
316
+ on /Bad Request/ do
317
+ status 400
318
+ end
319
+
320
+ on /RestClient::Unauthorized/ do
321
+ status 401
322
+ end
323
+
324
+ on /RestClient::ResourceNotFound/ do
325
+ status 404
326
+ end
327
+
328
+ on /RestClient::InternalServerError/ do
329
+ status 502
330
+ end
331
+
332
+ on /(RestClient|RHEVM)/ do
333
+ status 500
334
+ end
335
+
336
+ on /(.*) not found^/ do
337
+ status 400
338
+ end
339
+
340
+ on /Parameter name/ do
341
+ status 400
342
+ end
343
+
289
344
  end
290
345
 
291
346
  end