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.
- data/LICENSE +145 -0
- data/NOTICE +10 -1
- data/Rakefile +50 -2
- data/bin/deltacloudd +111 -14
- data/config/addresses.xml +14 -0
- data/config/condor.yaml +30 -0
- data/config/drivers/azure.yaml +3 -0
- data/config/drivers/condor.yaml +3 -0
- data/config/{drivers.yaml → drivers/ec2.yaml} +5 -34
- data/config/drivers/eucalyptus.yaml +8 -0
- data/config/drivers/gogrid.yaml +3 -0
- data/config/drivers/mock.yaml +3 -0
- data/config/drivers/opennebula.yaml +4 -0
- data/config/drivers/rackspace.yaml +3 -0
- data/config/drivers/rhevm.yaml +3 -0
- data/config/drivers/rimuhosting.yaml +3 -0
- data/config/drivers/sbc.yaml +2 -0
- data/config/drivers/terremark.yaml +3 -0
- data/config/drivers/vsphere.yaml +8 -0
- data/deltacloud-core.gemspec +13 -5
- data/deltacloud.rb +4 -2
- data/lib/deltacloud/backend_capability.rb +2 -2
- data/lib/deltacloud/base_driver/base_driver.rb +23 -52
- data/lib/deltacloud/base_driver/exceptions.rb +168 -0
- data/lib/deltacloud/base_driver/features.rb +31 -12
- data/lib/deltacloud/base_driver/mock_driver.rb +2 -1
- data/lib/deltacloud/core_ext/string.rb +2 -0
- data/lib/deltacloud/drivers/azure/azure_driver.rb +5 -5
- data/lib/deltacloud/drivers/condor/condor_client.rb +273 -0
- data/lib/deltacloud/drivers/condor/condor_driver.rb +236 -0
- data/lib/deltacloud/drivers/condor/ip_agents/confserver.rb +75 -0
- data/lib/deltacloud/drivers/condor/ip_agents/default.rb +84 -0
- data/lib/deltacloud/drivers/ec2/ec2_driver.rb +326 -95
- data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +3 -3
- data/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb +40 -8
- data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +7 -7
- data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +42 -25
- data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob1.yml +6 -4
- data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob2.yml +7 -5
- data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob3.yml +6 -4
- data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob4.yml +6 -4
- data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob5.yml +6 -4
- data/lib/deltacloud/drivers/mock/data/buckets/bucket1.yml +7 -1
- data/lib/deltacloud/drivers/mock/data/buckets/bucket2.yml +6 -1
- data/lib/deltacloud/drivers/mock/data/images/img1.yml +6 -2
- data/lib/deltacloud/drivers/mock/data/images/img2.yml +6 -2
- data/lib/deltacloud/drivers/mock/data/images/img3.yml +6 -2
- data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +11 -10
- data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +14 -7
- data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +14 -7
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap1.yml +3 -2
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap2.yml +3 -2
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap3.yml +3 -2
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol1.yml +4 -3
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol2.yml +4 -3
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol3.yml +4 -3
- data/lib/deltacloud/drivers/mock/mock_client.rb +101 -0
- data/lib/deltacloud/drivers/mock/mock_driver.rb +367 -429
- data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +6 -0
- data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +59 -9
- data/lib/deltacloud/drivers/rhevm/rhevm_client.rb +62 -8
- data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +100 -45
- data/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb +3 -2
- data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +8 -11
- data/lib/deltacloud/drivers/sbc/sbc_client.rb +6 -6
- data/lib/deltacloud/drivers/sbc/sbc_driver.rb +16 -0
- data/lib/deltacloud/drivers/terremark/terremark_driver.rb +17 -12
- data/lib/deltacloud/drivers/vsphere/vsphere_client.rb +140 -0
- data/lib/deltacloud/drivers/vsphere/vsphere_driver.rb +405 -0
- data/lib/deltacloud/drivers/vsphere/vsphere_filemanager.rb +182 -0
- data/lib/deltacloud/hardware_profile.rb +1 -1
- data/lib/deltacloud/helpers.rb +2 -1
- data/lib/deltacloud/helpers/application_helper.rb +92 -20
- data/lib/deltacloud/helpers/blob_stream.rb +160 -12
- data/lib/deltacloud/helpers/conversion_helper.rb +6 -2
- data/lib/deltacloud/helpers/json_helper.rb +31 -0
- data/lib/deltacloud/models/address.rb +28 -0
- data/lib/deltacloud/models/base_model.rb +5 -1
- data/lib/deltacloud/models/blob.rb +1 -1
- data/lib/deltacloud/models/bucket.rb +10 -0
- data/lib/deltacloud/models/firewall.rb +22 -0
- data/lib/deltacloud/models/firewall_rule.rb +23 -0
- data/lib/deltacloud/models/image.rb +12 -0
- data/lib/deltacloud/models/instance.rb +20 -2
- data/lib/deltacloud/models/key.rb +1 -1
- data/lib/deltacloud/runner.rb +3 -3
- data/lib/deltacloud/validation.rb +3 -7
- data/lib/drivers.rb +7 -1
- data/lib/sinatra/body_proxy.rb +34 -0
- data/lib/sinatra/lazy_auth.rb +5 -0
- data/lib/sinatra/rabbit.rb +54 -31
- data/lib/sinatra/rack_accept.rb +157 -0
- data/lib/sinatra/rack_date.rb +38 -0
- data/lib/sinatra/rack_etag.rb +2 -3
- data/lib/sinatra/rack_matrix_params.rb +51 -29
- data/lib/sinatra/rack_runtime.rb +1 -1
- data/lib/sinatra/rack_syslog.rb +86 -0
- data/lib/sinatra/url_for.rb +14 -1
- data/public/images/address.png +0 -0
- data/public/images/balancer.png +0 -0
- data/public/images/blob.png +0 -0
- data/public/images/bucket.png +0 -0
- data/public/images/cloud.png +0 -0
- data/public/images/firewall.png +0 -0
- data/public/images/image.png +0 -0
- data/public/images/key.png +0 -0
- data/public/images/machine.png +0 -0
- data/public/images/profile.png +0 -0
- data/public/images/realm.png +0 -0
- data/public/images/snapshot.png +0 -0
- data/public/images/volume.png +0 -0
- data/public/javascripts/application.js +119 -16
- data/public/javascripts/jquery.min.js +18 -0
- data/public/javascripts/jquery.mobile-1.0b1.min.js +146 -0
- data/public/stylesheets/compiled/application.css +8 -0
- data/public/stylesheets/images/ajax-loader.png +0 -0
- data/public/{images → stylesheets/images}/bread-bg.png +0 -0
- data/public/{images → stylesheets/images}/error.png +0 -0
- data/public/{images → stylesheets/images}/grid.png +0 -0
- data/public/stylesheets/images/icon-search-black.png +0 -0
- data/public/stylesheets/images/icons-18-black.png +0 -0
- data/public/stylesheets/images/icons-18-white.png +0 -0
- data/public/stylesheets/images/icons-36-black.png +0 -0
- data/public/stylesheets/images/icons-36-white.png +0 -0
- data/public/{images → stylesheets/images}/logo-wide.png +0 -0
- data/public/{images → stylesheets/images}/pending.png +0 -0
- data/public/{images → stylesheets/images}/rails.png +0 -0
- data/public/{images → stylesheets/images}/running.png +0 -0
- data/public/{images → stylesheets/images}/stopped.png +0 -0
- data/public/{images → stylesheets/images}/topbar-bg.png +0 -0
- data/public/stylesheets/jquery.mobile-1.0b1.min.css +8 -0
- data/public/stylesheets/new.css +53 -0
- data/server.rb +487 -175
- data/support/condor/bash/cached_images.sh +8 -0
- data/support/condor/bash/cloud_exit_hook.sh +17 -0
- data/support/condor/bash/cloud_functions +175 -0
- data/support/condor/bash/cloud_prepare_hook.sh +20 -0
- data/support/condor/bash/libvirt_cloud_script.sh +13 -0
- data/support/condor/config/50condor_cloud.config +37 -0
- data/support/condor/config/50condor_cloud_node.config +37 -0
- data/support/condor/config/condor-cloud +2 -0
- data/support/condor/config/condor_config.local +44 -0
- data/support/fedora/deltacloud-core +48 -26
- data/support/fedora/deltacloud-core-config +26 -0
- data/support/fedora/deltacloud-core.spec +314 -68
- data/support/fedora/deltacloudd-fedora +5 -0
- data/tests/common.rb +34 -4
- data/tests/drivers/mock/api_test.rb +3 -3
- data/tests/drivers/mock/images_test.rb +12 -0
- data/tests/drivers/mock/instances_test.rb +2 -0
- data/tests/rabbit_test.rb +2 -2
- data/views/addresses/_address.html.haml +6 -0
- data/views/addresses/associate.html.haml +12 -0
- data/views/addresses/index.html.haml +9 -0
- data/views/addresses/index.xml.haml +4 -0
- data/views/addresses/show.html.haml +21 -0
- data/views/addresses/show.xml.haml +14 -0
- data/views/api/show.html.haml +6 -11
- data/views/api/show.xml.haml +2 -0
- data/views/blobs/new.html.haml +24 -23
- data/views/blobs/show.html.haml +30 -31
- data/views/buckets/index.html.haml +9 -21
- data/views/buckets/index.xml.haml +3 -7
- data/views/buckets/new.html.haml +13 -12
- data/views/buckets/show.html.haml +22 -22
- data/views/buckets/show.xml.haml +5 -3
- data/views/docs/collection.html.haml +23 -34
- data/views/docs/collection.xml.haml +2 -2
- data/views/docs/index.html.haml +9 -13
- data/views/docs/index.xml.haml +1 -1
- data/views/docs/operation.html.haml +28 -38
- data/views/docs/operation.xml.haml +1 -1
- data/views/drivers/index.html.haml +8 -13
- data/views/drivers/show.html.haml +18 -18
- data/views/error.html.haml +32 -27
- data/views/errors/400.html.haml +41 -0
- data/views/errors/{validation_failure.xml.haml → 400.xml.haml} +0 -4
- data/views/errors/401.html.haml +41 -0
- data/views/errors/{auth_exception.xml.haml → 401.xml.haml} +0 -0
- data/views/errors/403.html.haml +42 -0
- data/views/errors/{not_allowed.xml.haml → 403.xml.haml} +0 -0
- data/views/errors/404.html.haml +29 -0
- data/views/errors/{not_found.xml.haml → 404.xml.haml} +1 -1
- data/views/errors/405.html.haml +29 -0
- data/views/errors/405.xml.haml +5 -0
- data/views/errors/500.html.haml +43 -0
- data/views/errors/500.xml.haml +5 -0
- data/views/errors/502.html.haml +43 -0
- data/views/errors/{backend_error.xml.haml → 502.xml.haml} +1 -2
- data/views/errors/backend_capability_failure.html.haml +27 -9
- data/views/firewalls/index.html.haml +15 -0
- data/views/firewalls/index.xml.haml +28 -0
- data/views/firewalls/new.html.haml +11 -0
- data/views/firewalls/new_rule.html.haml +20 -0
- data/views/firewalls/show.html.haml +42 -0
- data/views/firewalls/show.xml.haml +26 -0
- data/views/hardware_profiles/index.html.haml +15 -23
- data/views/hardware_profiles/show.html.haml +22 -18
- data/views/images/index.html.haml +11 -23
- data/views/images/index.xml.haml +4 -13
- data/views/images/new.html.haml +12 -13
- data/views/images/show.html.haml +26 -20
- data/views/images/show.xml.haml +2 -1
- data/views/instance_states/show.html.haml +21 -25
- data/views/instances/index.html.haml +13 -30
- data/views/instances/index.xml.haml +2 -23
- data/views/instances/new.html.haml +83 -88
- data/views/instances/show.html.haml +53 -55
- data/views/instances/show.xml.haml +12 -10
- data/views/keys/index.html.haml +13 -24
- data/views/keys/new.html.haml +7 -7
- data/views/keys/show.html.haml +26 -21
- data/views/layout.html.haml +28 -27
- data/views/load_balancers/index.html.haml +11 -31
- data/views/load_balancers/index.xml.haml +0 -1
- data/views/load_balancers/new.html.haml +1 -1
- data/views/load_balancers/show.html.haml +33 -34
- data/views/load_balancers/show.xml.haml +2 -2
- data/views/realms/index.html.haml +11 -24
- data/views/realms/index.xml.haml +2 -8
- data/views/realms/show.html.haml +17 -15
- data/views/realms/show.xml.haml +2 -1
- data/views/storage_snapshots/index.html.haml +11 -21
- data/views/storage_snapshots/index.xml.haml +2 -5
- data/views/storage_snapshots/new.html.haml +1 -1
- data/views/storage_snapshots/show.html.haml +21 -13
- data/views/storage_snapshots/show.xml.haml +2 -1
- data/views/storage_volumes/index.html.haml +11 -34
- data/views/storage_volumes/new.html.haml +1 -1
- data/views/storage_volumes/show.html.haml +33 -27
- data/views/storage_volumes/show.xml.haml +2 -1
- metadata +266 -178
- data/lib/sinatra/respond_to.rb +0 -248
- data/support/fedora/deltacloudd +0 -128
- data/support/fedora/rubygem-deltacloud-core.spec +0 -127
- data/views/accounts/index.html.haml +0 -11
- data/views/accounts/show.html.haml +0 -30
- data/views/errors/auth_exception.html.haml +0 -8
- data/views/errors/backend_error.html.haml +0 -22
- data/views/errors/not_allowed.html.haml +0 -6
- data/views/errors/not_found.html.haml +0 -6
- data/views/errors/validation_failure.html.haml +0 -11
@@ -40,14 +40,15 @@ class RimuHostingClient
|
|
40
40
|
if(!@auth.nil?)
|
41
41
|
headers["Authorization"] = @auth
|
42
42
|
end
|
43
|
+
safely do
|
43
44
|
r = @service.send_request(method, @uri.path + resource, data, headers)
|
44
45
|
puts r.body
|
45
46
|
res = JSON.parse(r.body)
|
46
47
|
res = res[res.keys[0]]
|
47
48
|
|
48
49
|
if(res['response_type'] == "ERROR" and ( (res['error_info']['error_class'] == "PermissionException") or
|
49
|
-
(res['error_info']['error_class'] == "LoginRequired") ))
|
50
|
-
raise
|
50
|
+
(res['error_info']['error_class'] == "LoginRequired") ))
|
51
|
+
raise "AuthFailure"
|
51
52
|
end
|
52
53
|
res
|
53
54
|
end
|
@@ -108,13 +108,13 @@ class RimuHostingDriver < Deltacloud::BaseDriver
|
|
108
108
|
end
|
109
109
|
|
110
110
|
def create_instance(credentials, image_id, opts)
|
111
|
-
|
111
|
+
rh = RimuHostingClient.new(credentials)
|
112
112
|
# really need to raise an exception here.
|
113
113
|
hwp_id = opts[:hwp_id] || 1
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
name =
|
114
|
+
name = opts[:name]
|
115
|
+
if not name
|
116
|
+
# really bad, but at least its a fqdn
|
117
|
+
name = Time.now.to_i.to_s + '.com'
|
118
118
|
end
|
119
119
|
convert_srv_to_instance(rh.create_server(image_id, hwp_id, name))
|
120
120
|
|
@@ -149,15 +149,12 @@ class RimuHostingDriver < Deltacloud::BaseDriver
|
|
149
149
|
stopped.to( :finish ) .automatically
|
150
150
|
end
|
151
151
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
rescue Exception => e
|
156
|
-
raise Deltacloud::BackendError.new(500, e.class.to_s, e.message, e.backtrace)
|
152
|
+
exceptions do
|
153
|
+
on /AuthFailure/ do
|
154
|
+
status 401
|
157
155
|
end
|
158
156
|
end
|
159
157
|
|
160
|
-
|
161
158
|
end
|
162
159
|
|
163
160
|
end
|
@@ -22,9 +22,9 @@ require 'digest/md5'
|
|
22
22
|
module Deltacloud
|
23
23
|
module Drivers
|
24
24
|
module SBC
|
25
|
-
|
25
|
+
|
26
26
|
class FixtureNotFound < Exception; end
|
27
|
-
|
27
|
+
|
28
28
|
#
|
29
29
|
# Client for the IBM Smart Business Cloud (SBC).
|
30
30
|
#
|
@@ -180,9 +180,9 @@ class SBCClient
|
|
180
180
|
#
|
181
181
|
def backend_error!(resp)
|
182
182
|
if resp.is_a?(Net::HTTPUnauthorized)
|
183
|
-
raise
|
183
|
+
raise "AuthFailure"
|
184
184
|
else
|
185
|
-
raise
|
185
|
+
raise "BackendError"
|
186
186
|
end
|
187
187
|
end
|
188
188
|
|
@@ -192,7 +192,7 @@ class SBCClient
|
|
192
192
|
def urlencode(hash)
|
193
193
|
hash.keys.map { |k| "#{URI.encode(k)}=#{URI.encode(hash[k])}" }.join("&")
|
194
194
|
end
|
195
|
-
|
195
|
+
|
196
196
|
#
|
197
197
|
# Reads a fake URL from local fixtures
|
198
198
|
#
|
@@ -240,7 +240,7 @@ class SBCClient
|
|
240
240
|
retry
|
241
241
|
end
|
242
242
|
end
|
243
|
-
|
243
|
+
|
244
244
|
end
|
245
245
|
end
|
246
246
|
end
|
@@ -88,6 +88,10 @@ class SBCDriver < Deltacloud::BaseDriver
|
|
88
88
|
body['location'] = opts[:realm_id] || @last_image['location']
|
89
89
|
body['instanceType'] = opts[:hwp_id].gsub('-', '/') || @last_image['supportedInstanceTypes'][0]['id']
|
90
90
|
|
91
|
+
if not body['name']
|
92
|
+
body['name'] = Time.now.to_i.to_s
|
93
|
+
end
|
94
|
+
|
91
95
|
# Submit instance, parse response
|
92
96
|
convert_instance(sbc_client.create_instance(body).map[0])
|
93
97
|
end
|
@@ -118,6 +122,18 @@ class SBCDriver < Deltacloud::BaseDriver
|
|
118
122
|
instance(credentials, instance_id)
|
119
123
|
end
|
120
124
|
|
125
|
+
exceptions do
|
126
|
+
|
127
|
+
on /AuthFailure/ do
|
128
|
+
status 401
|
129
|
+
end
|
130
|
+
|
131
|
+
on /BackendError/ do
|
132
|
+
status 502
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
121
137
|
#
|
122
138
|
# --------------------- Private helpers ---------------------
|
123
139
|
#
|
@@ -31,7 +31,11 @@ module Deltacloud
|
|
31
31
|
|
32
32
|
class TerremarkDriver < Deltacloud::BaseDriver
|
33
33
|
|
34
|
-
feature :instances, :user_name
|
34
|
+
feature :instances, :user_name do
|
35
|
+
constraint :max_length, 15
|
36
|
+
end
|
37
|
+
|
38
|
+
USER_NAME_MAX = feature(:instances, :user_name).constraints[:max_length]
|
35
39
|
|
36
40
|
#--
|
37
41
|
# Vapp State Map... for use with convert_instance (get an integer back from terremark)
|
@@ -128,9 +132,13 @@ VAPP_STATE_MAP = { "0" => "PENDING", "1" => "PENDING", "2" => "STOPPED", "4"
|
|
128
132
|
new_vapp = nil
|
129
133
|
vapp_opts = {} #assemble options to pass to Fog::Terremark::Real.instantiate_vapp_template
|
130
134
|
terremark_hwp = hardware_profiles(credentials, {:name => 'default'}).first #sanity check values against default
|
131
|
-
name = opts[
|
132
|
-
|
133
|
-
|
135
|
+
name = opts[:name]
|
136
|
+
if not name
|
137
|
+
name = "inst#{Time.now.to_i}"
|
138
|
+
end
|
139
|
+
if name.length > USER_NAME_MAX
|
140
|
+
raise "Parameter name must be #{USER_NAME_MAX} characters or less"
|
141
|
+
end
|
134
142
|
unless ( (terremark_hwp.include?(:cpu, opts[:hwp_cpu].to_i)) &&
|
135
143
|
(terremark_hwp.include?(:memory, opts[:hwp_memory].to_i)) ) then
|
136
144
|
raise Deltacloud::Validation::Failure.new(Deltacloud::Validation::Param.new(["cpu"]), "Error with cpu and/or memory values. you said cpu->#{opts[:hwp_cpu]} and mem->#{opts[:hwp_memory]}")
|
@@ -192,7 +200,7 @@ end
|
|
192
200
|
def valid_credentials?(credentials)
|
193
201
|
begin
|
194
202
|
new_client(credentials)
|
195
|
-
rescue
|
203
|
+
rescue
|
196
204
|
return false
|
197
205
|
end
|
198
206
|
true
|
@@ -272,20 +280,17 @@ end
|
|
272
280
|
vdc_id = terremark_client.default_vdc_id
|
273
281
|
end
|
274
282
|
if (vdc_id.nil?)
|
275
|
-
raise
|
283
|
+
raise "AuthFailure"
|
276
284
|
end
|
277
285
|
terremark_client
|
278
286
|
end
|
279
287
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
rescue Exception => e
|
284
|
-
raise Deltacloud::BackendError.new(500, e.class.to_s, e.message, e.backtrace)
|
288
|
+
exceptions do
|
289
|
+
on /AuthFailure/ do
|
290
|
+
status 401
|
285
291
|
end
|
286
292
|
end
|
287
293
|
|
288
|
-
|
289
294
|
end
|
290
295
|
|
291
296
|
end
|
@@ -0,0 +1,140 @@
|
|
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
|
+
|
17
|
+
module Deltacloud::Drivers::VSphere
|
18
|
+
|
19
|
+
require 'deltacloud/drivers/vsphere/vsphere_filemanager'
|
20
|
+
|
21
|
+
module Helper
|
22
|
+
|
23
|
+
# Find a VirtualMachine traversing through all Datastores and Datacenters
|
24
|
+
#
|
25
|
+
# This helper will return a Hash: { :datastore => NAME_OF_DS, :instance => VM }
|
26
|
+
# Returning datastore is necesarry for constructing a correct realm for an
|
27
|
+
# instance
|
28
|
+
#
|
29
|
+
def find_vm(credentials, name)
|
30
|
+
vsphere = new_client(credentials)
|
31
|
+
safely do
|
32
|
+
rootFolder = vsphere.serviceInstance.content.rootFolder
|
33
|
+
vm = {}
|
34
|
+
rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).each do |dc|
|
35
|
+
dc.datastoreFolder.childEntity.collect do |datastore|
|
36
|
+
vm[:instance] = datastore.vm.find { |x| x.name == name }
|
37
|
+
if vm[:instance]
|
38
|
+
vm[:datastore] = datastore.name
|
39
|
+
break
|
40
|
+
end
|
41
|
+
stored_tasks(datastore, vsphere) do |task|
|
42
|
+
if task.info.entity.class == RbVmomi::VIM::VirtualMachine and ['queued', 'running'].member? task.info.state
|
43
|
+
vm = { :stored_instance => load_serialized_instance(datastore,task.info.key), :datastore => datastore.name }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
break if [:datastore]
|
48
|
+
end
|
49
|
+
vm
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Find a ResourcePool[1] object associated by given Datastore
|
54
|
+
# ResourcePool is defined for Datacenter and is used for launching a new
|
55
|
+
# instance
|
56
|
+
#
|
57
|
+
# [1] http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.ResourcePool.html
|
58
|
+
#
|
59
|
+
def find_resource_pool(credentials, name)
|
60
|
+
vsphere = new_client(credentials)
|
61
|
+
safely do
|
62
|
+
rootFolder = vsphere.serviceInstance.content.rootFolder
|
63
|
+
dc = rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).select do |dc|
|
64
|
+
dc.datastoreFolder.childEntity.find { |d| d.name == name }.nil? == false
|
65
|
+
end.flatten.compact.first
|
66
|
+
dc.hostFolder.childEntity.collect.first.resourcePool
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# This helper will try to find a Datastore[1] object in all Datacenters.
|
71
|
+
# Datastore is used to place instance on create to correct place
|
72
|
+
#
|
73
|
+
# [1] http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.Datastore.html
|
74
|
+
#
|
75
|
+
def find_datastore(credentials, name)
|
76
|
+
vsphere = new_client(credentials)
|
77
|
+
safely do
|
78
|
+
rootFolder = vsphere.serviceInstance.content.rootFolder
|
79
|
+
rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).collect do |dc|
|
80
|
+
dc.datastoreFolder.childEntity.find { |d| d.name == name }
|
81
|
+
end.flatten.compact.first
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# This helper will traverse across all datacenters and datastores and gather
|
86
|
+
# all virtual machines available on vSphere
|
87
|
+
#
|
88
|
+
def list_virtual_machines(credentials)
|
89
|
+
vsphere = new_client(credentials)
|
90
|
+
vms = []
|
91
|
+
rootFolder = vsphere.serviceInstance.content.rootFolder
|
92
|
+
rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).each do |dc|
|
93
|
+
dc.datastoreFolder.childEntity.each do |datastore|
|
94
|
+
vms += datastore.vm.collect { |vm| { :instance => vm, :datastore => datastore.name } unless vm.nil? }
|
95
|
+
stored_tasks(datastore, vsphere) do |task|
|
96
|
+
if task.info.entity.class == RbVmomi::VIM::VirtualMachine
|
97
|
+
vms << { :stored_instance => load_serialized_instance(datastore, task.info.key), :datastore => datastore.name }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
vms.flatten.compact
|
103
|
+
end
|
104
|
+
|
105
|
+
# Map given instance to task. Task name is used as a filename.
|
106
|
+
#
|
107
|
+
def map_task_to_instance(datastore, task_key, new_instance)
|
108
|
+
VSphere::FileManager::store_mapping!(datastore, YAML::dump(new_instance).to_s, task_key)
|
109
|
+
new_instance
|
110
|
+
end
|
111
|
+
|
112
|
+
def load_serialized_instance(datastore, task_key)
|
113
|
+
VSphere::FileManager::load_mapping(datastore, task_key)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Yield all tasks if they are included in mapper storage directory.
|
117
|
+
def stored_tasks(datastore, vsphere)
|
118
|
+
tasks = VSphere::FileManager::list_mappings(datastore)
|
119
|
+
return [] if tasks.empty?
|
120
|
+
vsphere.serviceInstance.content.taskManager.recentTask.each do |task|
|
121
|
+
if tasks.include?(task.info.key) and ['queued', 'running'].member?(task.info.state)
|
122
|
+
yield task
|
123
|
+
tasks.delete(task.info.key)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
# Delete old left tasks
|
127
|
+
tasks.select { |f| f =~ /task-(\d+)/ }.each do |task|
|
128
|
+
VSphere::FileManager::delete_mapping!(datastore, task)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def extract_architecture(text)
|
133
|
+
'x86_64' if text.include?('64-bit')
|
134
|
+
'i386' if text.include?('32-bit')
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
@@ -0,0 +1,405 @@
|
|
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
|
+
|
17
|
+
require 'deltacloud/base_driver'
|
18
|
+
require 'rbvmomi'
|
19
|
+
require 'deltacloud/drivers/vsphere/vsphere_client'
|
20
|
+
|
21
|
+
module Deltacloud::Drivers::VSphere
|
22
|
+
|
23
|
+
MAPPER_STORAGE_ROOT = File::join("/var/tmp", "deltacloud-vsphere-#{ENV["USER"]}")
|
24
|
+
|
25
|
+
class VSphereDriver < Deltacloud::BaseDriver
|
26
|
+
|
27
|
+
include Deltacloud::Drivers::VSphere::Helper
|
28
|
+
include Deltacloud::Drivers::VSphere::FileManager
|
29
|
+
|
30
|
+
# You can use 'user_iso' feature to set 'user_iso' parameter when creating
|
31
|
+
# a new instance where this parameter can hold gzipped CDROM iso which will
|
32
|
+
# be mounted into created instance after boot
|
33
|
+
feature :instances, :user_iso
|
34
|
+
feature :instances, :user_data
|
35
|
+
feature :instances, :user_name
|
36
|
+
|
37
|
+
# There is just one hardware profile where memory is measured using maximum
|
38
|
+
# memory available on ESX for virtual machines and CPU using maximum free
|
39
|
+
# CPU cores in ESX.
|
40
|
+
def hardware_profiles(credentials, opts={})
|
41
|
+
vsphere = new_client(credentials)
|
42
|
+
safely do
|
43
|
+
service = vsphere.serviceInstance.content
|
44
|
+
max_memory, max_cpu_cores = 0, 0
|
45
|
+
service.rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).each do |dc|
|
46
|
+
max_memory += dc.hostFolder.childEntity.first.summary.effectiveMemory
|
47
|
+
max_cpu_cores += dc.hostFolder.childEntity.first.summary.numCpuCores
|
48
|
+
end
|
49
|
+
[Deltacloud::HardwareProfile::new('default') do
|
50
|
+
cpu (1..max_cpu_cores)
|
51
|
+
memory (128..max_memory)
|
52
|
+
architecture ['x86_64', 'i386']
|
53
|
+
end]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Configure instance state machine
|
58
|
+
define_instance_states do
|
59
|
+
start.to(:pending) .on( :create )
|
60
|
+
pending.to(:stopped) .automatically
|
61
|
+
stopped.to(:running) .on( :start )
|
62
|
+
running.to(:running) .on( :reboot )
|
63
|
+
running.to(:shutting_down) .on( :stop )
|
64
|
+
shutting_down.to(:stopped) .automatically
|
65
|
+
stopped.to(:finish) .on( :destroy )
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
# Images are virtual machines with 'template' flag set to be true.
|
70
|
+
# Thus we're getting them using find_vm and list_virtual_machines
|
71
|
+
def images(credentials, opts=nil)
|
72
|
+
cloud = new_client(credentials)
|
73
|
+
img_arr = []
|
74
|
+
|
75
|
+
# Skip traversing through all instances in all datacenters when ID
|
76
|
+
# attribute is set
|
77
|
+
safely do
|
78
|
+
if opts[:id]
|
79
|
+
template_vms = [ find_vm(credentials, opts[:id]) ].select { |vm| vm[:instance] }.compact
|
80
|
+
else
|
81
|
+
template_vms = list_virtual_machines(credentials).select { |vm| vm[:instance] && vm[:instance].summary.config[:template] }
|
82
|
+
end
|
83
|
+
img_arr = template_vms.collect do |image_hash|
|
84
|
+
image, realm = image_hash[:instance], image_hash[:datastore]
|
85
|
+
config = image.summary.config
|
86
|
+
instance_state = convert_state(:instance, image.summary.runtime[:powerState])
|
87
|
+
# Preload all properties to save multiple SOAP calls to vSphere
|
88
|
+
properties = {
|
89
|
+
:name => config[:name],
|
90
|
+
:full_name => config[:guestFullName]
|
91
|
+
}
|
92
|
+
image_state = convert_state(:image, image.summary.runtime[:powerState])
|
93
|
+
# This will determine image architecture using image description.
|
94
|
+
# Ussualy description include '64-bit' or '32-bit'. In case you used
|
95
|
+
# some weird template/OS it will fallback to 64 bit
|
96
|
+
image_architecture = extract_architecture(properties[:full_name]) || 'x86_64'
|
97
|
+
Image.new(
|
98
|
+
:id => properties[:name],
|
99
|
+
:name => properties[:name],
|
100
|
+
:architecture => image_architecture,
|
101
|
+
:owner_id => credentials.user,
|
102
|
+
:description => properties[:full_name],
|
103
|
+
:state => image_state
|
104
|
+
)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
img_arr = filter_on( img_arr, :architecture, opts )
|
108
|
+
img_arr.sort_by{|e| [e.owner_id, e.name]}
|
109
|
+
end
|
110
|
+
|
111
|
+
def create_image(credentials, opts={})
|
112
|
+
vsphere = new_client(credentials)
|
113
|
+
safely do
|
114
|
+
find_vm(credentials, opts[:id])[:instance].MarkAsTemplate
|
115
|
+
end
|
116
|
+
images(credentials, :id => opts[:id])
|
117
|
+
end
|
118
|
+
|
119
|
+
# List all datacenters managed by the vSphere or vCenter entrypoint.
|
120
|
+
def realms(credentials, opts=nil)
|
121
|
+
vsphere = new_client(credentials)
|
122
|
+
safely do
|
123
|
+
if opts and opts[:id]
|
124
|
+
datastore = find_datastore(credentials, opts[:id])
|
125
|
+
[convert_realm(datastore)]
|
126
|
+
else
|
127
|
+
rootFolder = vsphere.serviceInstance.content.rootFolder
|
128
|
+
rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).collect do |dc|
|
129
|
+
dc.datastoreFolder.childEntity.collect { |datastore| convert_realm(datastore) }
|
130
|
+
end.flatten
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# List all running instances, across all datacenters. DeltaCloud API does
|
136
|
+
# not yet support filtering instances by realm.
|
137
|
+
def instances(credentials, opts=nil)
|
138
|
+
cloud = new_client(credentials)
|
139
|
+
inst_arr, machine_vms, pending_vms = [], [], []
|
140
|
+
safely do
|
141
|
+
# Using find_vm is a way faster than listing all virtual machines
|
142
|
+
if opts[:id]
|
143
|
+
list_vms = [ find_vm(credentials, opts[:id]) ].compact
|
144
|
+
else
|
145
|
+
list_vms = list_virtual_machines(credentials)
|
146
|
+
end
|
147
|
+
# Split machines to the 'real' one and PENDING one.
|
148
|
+
machine_vms = list_vms.select { |vm| vm[:instance] && !vm[:instance].summary.config[:template] }
|
149
|
+
pending_vms = list_vms.select { |vm| vm[:stored_instance] }.collect { |vm| vm[:stored_instance]}
|
150
|
+
end
|
151
|
+
safely do
|
152
|
+
inst_arr = machine_vms.collect do |vm_hash|
|
153
|
+
# Since all calls to vm are threaten as SOAP calls, reduce them using
|
154
|
+
# local variable.
|
155
|
+
vm, realm_id = vm_hash[:instance], vm_hash[:datastore]
|
156
|
+
config = vm.summary.config
|
157
|
+
next if not config
|
158
|
+
# Template (image_id) is beeing stored as 'extraConfig' parameter in
|
159
|
+
# instance.
|
160
|
+
template_id = vm.config[:extraConfig].select { |k| k.key == 'template_id' }
|
161
|
+
template_id = template_id.first.value unless template_id.empty?
|
162
|
+
properties = {
|
163
|
+
:memory => config[:memorySizeMB],
|
164
|
+
:cpus => config[:numCpu],
|
165
|
+
:storage => vm.summary.storage[:unshared],
|
166
|
+
:name => config[:name],
|
167
|
+
:full_name => config[:guestFullName],
|
168
|
+
}
|
169
|
+
instance_state = convert_state(:instance, vm.summary.runtime[:powerState])
|
170
|
+
instance_profile = InstanceProfile::new('default',
|
171
|
+
:hwp_cpu => properties[:cpus],
|
172
|
+
:hwp_memory => properties[:memory],
|
173
|
+
:hwp_storage => properties[:storage])
|
174
|
+
|
175
|
+
# We're getting IP address from 'vmware guest tools'.
|
176
|
+
# If guest tools are not installed, we return list of MAC addresses
|
177
|
+
# assigned to this instance.
|
178
|
+
instance_address = vm.guest[:net].empty? ? vm.macs.values.first : vm.guest[:net].first[:ipAddress].first
|
179
|
+
Instance.new(
|
180
|
+
:id => properties[:name],
|
181
|
+
:name => properties[:name],
|
182
|
+
:owner_id => credentials.user,
|
183
|
+
:image_id => template_id,
|
184
|
+
:description => properties[:full_name],
|
185
|
+
:realm_id => realm_id,
|
186
|
+
:state => instance_state,
|
187
|
+
:public_addresses => instance_address,
|
188
|
+
:private_addresses => [],
|
189
|
+
:instance_profile => instance_profile,
|
190
|
+
:actions => instance_actions_for( instance_state ),
|
191
|
+
:create_image => true
|
192
|
+
)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
inst_arr.compact!
|
196
|
+
# Append 'temporary' instances to real instances.
|
197
|
+
# 'Temporary' or 'stored' instance are used to speed up instance creation
|
198
|
+
# process by serializing instances to datastore and map instance to task.
|
199
|
+
#
|
200
|
+
inst_arr += pending_vms
|
201
|
+
filter_on( inst_arr, :state, opts )
|
202
|
+
end
|
203
|
+
|
204
|
+
|
205
|
+
def create_instance(credentials, image_id, opts)
|
206
|
+
vsphere = new_client(credentials)
|
207
|
+
safely do
|
208
|
+
rootFolder = vsphere.serviceInstance.content.rootFolder
|
209
|
+
vm = find_vm(credentials, opts[:image_id])
|
210
|
+
# New instance need valid resource pool and datastore to be placed.
|
211
|
+
# For this reason, realm_id **needs** to be set.
|
212
|
+
if opts and opts[:realm_id]
|
213
|
+
resourcePool = find_resource_pool(credentials, opts[:realm_id])
|
214
|
+
datastore = find_datastore(credentials, opts[:realm_id])
|
215
|
+
else
|
216
|
+
resourcePool = find_resource_pool(credentials, vm[:datastore])
|
217
|
+
datastore = find_datastore(credentials, vm[:datastore])
|
218
|
+
end
|
219
|
+
relocate = { :pool => resourcePool, :datastore => datastore }
|
220
|
+
relocateSpec = RbVmomi::VIM.VirtualMachineRelocateSpec(relocate)
|
221
|
+
# Set extra configuration for VM, like template_id
|
222
|
+
machine_config = {
|
223
|
+
:memoryMB => opts[:hwp_memory],
|
224
|
+
:numCPUs => opts[:hwp_cpu],
|
225
|
+
:extraConfig => [
|
226
|
+
{ :key => 'template_id', :value => image_id },
|
227
|
+
]
|
228
|
+
}
|
229
|
+
if (opts[:user_data] and not opts[:user_data].empty?) and (opts[:user_iso] and not opts[:user_iso].empty?)
|
230
|
+
raise "ERROR: You cannot use user_data and user_iso features together"
|
231
|
+
end
|
232
|
+
# If user wants to inject data into instance he need to submit a Base64
|
233
|
+
# encoded gzipped ISO image.
|
234
|
+
# This image will be uplaoded to the Datastore given in 'realm_id'
|
235
|
+
# parameter and them attached to instance.
|
236
|
+
if opts[:user_data] and not opts[:user_data].empty?
|
237
|
+
device = vm[:instance].config.hardware.device.select { |hw| hw.class == RbVmomi::VIM::VirtualCdrom }.first
|
238
|
+
if device
|
239
|
+
VSphere::FileManager::user_data!(datastore, opts[:user_data], "#{opts[:name]}.iso")
|
240
|
+
machine_config[:extraConfig] << {
|
241
|
+
:key => 'user_data_file', :value => "#{opts[:name]}.iso"
|
242
|
+
}
|
243
|
+
device.backing = RbVmomi::VIM.VirtualCdromIsoBackingInfo(:fileName => "[#{opts[:realm_id] || vm[:datastore]}] "+
|
244
|
+
"/#{VSphere::FileManager::DIRECTORY_PATH}/#{opts[:name]}.iso")
|
245
|
+
machine_config.merge!({
|
246
|
+
:deviceChange => [{
|
247
|
+
:operation => :edit,
|
248
|
+
:device => device
|
249
|
+
}]
|
250
|
+
})
|
251
|
+
else
|
252
|
+
raise "Failed to inject data to device because there is no CD-ROM drive defined in given template"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
if opts[:user_iso] and not opts[:user_iso].empty?
|
256
|
+
device = vm[:instance].config.hardware.device.select { |hw| hw.class == RbVmomi::VIM::VirtualCdrom }.first
|
257
|
+
if device
|
258
|
+
VSphere::FileManager::store_iso!(datastore, opts[:user_iso], "#{opts[:name]}.iso")
|
259
|
+
machine_config[:extraConfig] << {
|
260
|
+
:key => 'user_iso_file', :value => "#{opts[:name]}.iso"
|
261
|
+
}
|
262
|
+
device.backing = RbVmomi::VIM.VirtualCdromIsoBackingInfo(:fileName => "[#{opts[:realm_id] || vm[:datastore]}] "+
|
263
|
+
"/#{VSphere::FileManager::DIRECTORY_PATH}/#{opts[:name]}.iso")
|
264
|
+
machine_config.merge!({
|
265
|
+
:deviceChange => [{
|
266
|
+
:operation => :edit,
|
267
|
+
:device => device
|
268
|
+
}]
|
269
|
+
})
|
270
|
+
else
|
271
|
+
raise "Failed to inject data to device because there is no CD-ROM drive defined in given template"
|
272
|
+
end
|
273
|
+
end
|
274
|
+
spec = RbVmomi::VIM.VirtualMachineCloneSpec(
|
275
|
+
:location => relocateSpec,
|
276
|
+
:powerOn => true,
|
277
|
+
:template => false,
|
278
|
+
:config => RbVmomi::VIM.VirtualMachineConfigSpec(machine_config)
|
279
|
+
)
|
280
|
+
instance_profile = InstanceProfile::new('default', :hwp_memory => opts[:hwp_memory], :hwp_cpu => opts[:hwp_cpu])
|
281
|
+
task = vm[:instance].CloneVM_Task(:folder => vm[:instance].parent, :name => opts[:name], :spec => spec)
|
282
|
+
new_instance = Instance::new(
|
283
|
+
:id => opts[:name],
|
284
|
+
:name => opts[:name],
|
285
|
+
:description => opts[:name],
|
286
|
+
:owner_id => credentials.user,
|
287
|
+
:image_id => opts[:image_id],
|
288
|
+
:realm_id => opts[:realm_id] || vm[:datastore],
|
289
|
+
:state => 'PENDING',
|
290
|
+
:public_addresses => [],
|
291
|
+
:private_addresses => [],
|
292
|
+
:instance_profile => instance_profile,
|
293
|
+
:actions => instance_actions_for( 'PENDING' ),
|
294
|
+
:create_image => false
|
295
|
+
)
|
296
|
+
# This will 'serialize' instance to YAML file and map it to the task.
|
297
|
+
# Ussualy it takes like 2-3 minutes (depending on storage size) to
|
298
|
+
# complete instance cloning process.
|
299
|
+
map_task_to_instance(datastore, task.info.key, new_instance)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
# Reboot an instance, given its id.
|
304
|
+
def reboot_instance(credentials, id)
|
305
|
+
find_vm(credentials, id)[:instance].ResetVM_Task
|
306
|
+
end
|
307
|
+
|
308
|
+
# Start an instance, given its id.
|
309
|
+
def start_instance(credentials, id)
|
310
|
+
find_vm(credentials, id)[:instance].PowerOnVM_Task
|
311
|
+
end
|
312
|
+
|
313
|
+
# Stop an instance, given its id.
|
314
|
+
def stop_instance(credentials, id)
|
315
|
+
find_vm(credentials, id)[:instance].PowerOffVM_Task
|
316
|
+
end
|
317
|
+
|
318
|
+
# Destroy an instance, given its id. Note that this will destroy all
|
319
|
+
# instance data.
|
320
|
+
#
|
321
|
+
# If there is user-data dile asocciated with instance, remove this file as
|
322
|
+
# well.
|
323
|
+
def destroy_instance(credentials, instance_id)
|
324
|
+
vm = find_vm(credentials, instance_id)
|
325
|
+
user_file = vm[:instance].config[:extraConfig].select { |k| k.key == 'user_iso_file' }.first
|
326
|
+
VSphere::FileManager::delete_iso!(vm[:instance].send(:datastore).first, user_file.value) if user_file
|
327
|
+
vm[:instance].Destroy_Task.wait_for_completion
|
328
|
+
end
|
329
|
+
|
330
|
+
alias :destroy_image :destroy_instance
|
331
|
+
|
332
|
+
exceptions do
|
333
|
+
|
334
|
+
on /InvalidLogin/ do
|
335
|
+
status 401
|
336
|
+
end
|
337
|
+
|
338
|
+
on /ERROR/ do
|
339
|
+
status 500
|
340
|
+
end
|
341
|
+
|
342
|
+
on /RbVmomi::Fault/ do
|
343
|
+
status 502
|
344
|
+
end
|
345
|
+
|
346
|
+
on /Failed to inject data/ do
|
347
|
+
status 502
|
348
|
+
end
|
349
|
+
|
350
|
+
end
|
351
|
+
|
352
|
+
def valid_credentials?(credentials)
|
353
|
+
begin
|
354
|
+
RbVmomi::VIM.connect(:host => host_endpoint, :user => credentials.user, :password => credentials.password, :insecure => true)
|
355
|
+
return true
|
356
|
+
rescue
|
357
|
+
return false
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
#######
|
362
|
+
private
|
363
|
+
#######
|
364
|
+
|
365
|
+
def new_client(credentials)
|
366
|
+
safely do
|
367
|
+
RbVmomi::VIM.connect(:host => host_endpoint, :user => credentials.user, :password => credentials.password, :insecure => true)
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
def host_endpoint
|
372
|
+
endpoint = api_provider
|
373
|
+
endpoint || Deltacloud::Drivers::driver_config[:vsphere][:entrypoints]['default']['default']
|
374
|
+
end
|
375
|
+
|
376
|
+
def convert_realm(datastore)
|
377
|
+
Realm::new(
|
378
|
+
:id => datastore.name,
|
379
|
+
:name => datastore.name,
|
380
|
+
:limit => datastore.summary.freeSpace,
|
381
|
+
:state => datastore.summary.accessible ? 'AVAILABLE' : 'UNAVAILABLE'
|
382
|
+
)
|
383
|
+
end
|
384
|
+
|
385
|
+
def convert_state(object, state)
|
386
|
+
new_state = ''
|
387
|
+
if object == :image
|
388
|
+
new_state = case state
|
389
|
+
when 'poweredOff' then 'AVAILABLE'
|
390
|
+
when 'poweredOn' then 'UNAVAILABLE'
|
391
|
+
end
|
392
|
+
end
|
393
|
+
if object == :instance
|
394
|
+
new_state = case state
|
395
|
+
when 'poweredOff' then 'STOPPED'
|
396
|
+
when 'poweredOn' then 'RUNNING'
|
397
|
+
else 'PENDING'
|
398
|
+
end
|
399
|
+
end
|
400
|
+
new_state
|
401
|
+
end
|
402
|
+
|
403
|
+
end
|
404
|
+
|
405
|
+
end
|