forked from vmware-archive/rbvmomi
/
OvfManager.rb
115 lines (98 loc) · 3.82 KB
/
OvfManager.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
class RbVmomi::VIM::OvfManager
# Deploy an OVF.
#
# @param [Hash] opts The options hash.
# @option opts [String] :uri Location of the OVF.
# @option opts [String] :vmName Name of the new VM.
# @option opts [VIM::Folder] :vmFolder Folder to place the VM in.
# @option opts [VIM::HostSystem] :host Host to use.
# @option opts [VIM::ResourcePool] :resourcePool Resource pool to use.
# @option opts [VIM::Datastore] :datastore Datastore to use.
# @option opts [String] :diskProvisioning (thin) Disk provisioning mode.
# @option opts [Hash] :networkMappings Network mappings.
# @option opts [Hash] :propertyMappings Property mappings.
def deployOVF opts
opts = { :networkMappings => {},
:propertyMappings => {},
:diskProvisioning => :thin }.merge opts
%w(uri vmName vmFolder host resourcePool datastore).each do |k|
fail "parameter #{k} required" unless opts[k.to_sym]
end
ovfImportSpec = RbVmomi::VIM::OvfCreateImportSpecParams(
:hostSystem => opts[:host],
:locale => "US",
:entityName => opts[:vmName],
:deploymentOption => "",
:networkMapping => opts[:networkMappings].map{|from, to| RbVmomi::VIM::OvfNetworkMapping(:name => from, :network => to)},
:propertyMapping => opts[:propertyMappings].to_a,
:diskProvisioning => opts[:diskProvisioning]
)
result = CreateImportSpec(
:ovfDescriptor => open(opts[:uri]).read,
:resourcePool => opts[:resourcePool],
:datastore => opts[:datastore],
:cisp => ovfImportSpec
)
raise result.error[0].localizedMessage if result.error && !result.error.empty?
if result.warning
result.warning.each{|x| puts "OVF Warning: #{x.localizedMessage.chomp}" }
end
nfcLease = opts[:resourcePool].ImportVApp(:spec => result.importSpec,
:folder => opts[:vmFolder],
:host => opts[:host])
nfcLease.wait_until(:state) { nfcLease.state != "initializing" }
raise nfcLease.error if nfcLease.state == "error"
begin
nfcLease.HttpNfcLeaseProgress(:percent => 5)
progress = 5.0
result.fileItem.each do |fileItem|
deviceUrl = nfcLease.info.deviceUrl.find{|x| x.importKey == fileItem.deviceId}
if !deviceUrl
raise "Couldn't find deviceURL for device '#{fileItem.deviceId}'"
end
keepAliveThread = Thread.new do
while true
sleep 2 * 60
nfcLease.HttpNfcLeaseProgress(:percent => progress.to_i)
end
end
href = deviceUrl.url.gsub("*", opts[:host].config.network.vnic[0].spec.ip.ipAddress)
# fileItem.create actually means that the object has been already
# created
ovfFilename = opts[:uri].to_s
file_body = file_body(ovfFilename, fileItem.path)
unless fileItem.create
Excon.post(URI::escape(href), :body => file_body)
else
Excon.put(URI::escape(href), :body => file_body)
end
keepAliveThread.kill
keepAliveThread.join
progress += (90.0 / result.fileItem.length)
nfcLease.HttpNfcLeaseProgress(:percent => progress.to_i)
end
nfcLease.HttpNfcLeaseProgress(:percent => 100)
vm = nfcLease.info.entity
nfcLease.HttpNfcLeaseComplete
vm
end
rescue Exception
(nfcLease.HttpNfcLeaseAbort rescue nil) if nfcLease
raise
end
def file_body(ovf_uri, path)
require 'uri'
uri = URI.parse(ovf_uri)
if uri.scheme.nil?
# local path
File.open(File.expand_path(path, File.dirname(ovf_uri)))
else
# same hack that we had before
tmp = ovf_uri.split(/\//)
tmp.pop
tmp << path
tmp.join("/")
Excon.get(tmp).body
end
end
end