Class: RbVmomi::VIM::OvfManager

Inherits:
Object
  • Object
show all
Defined in:
lib/rbvmomi/vim/OvfManager.rb

Overview

TODO:

Use an HTTP library instead of executing curl.

Note:

deployOVF and requires curl. If curl is not in your PATH then set the CURL environment variable to point to it.

Instance Method Summary collapse

Instance Method Details

#deployOVF(opts) ⇒ Object

Deploy an OVF.

Parameters:

  • opts (Hash)

    The options hash.

Options Hash (opts):

  • :uri (String)

    Location of the OVF.

  • :vmName (String)

    Name of the new VM.

  • :vmFolder (VIM::Folder)

    Folder to place the VM in.

  • :host (VIM::HostSystem)

    Host to use.

  • :resourcePool (VIM::ResourcePool)

    Resource pool to use.

  • :datastore (VIM::Datastore)

    Datastore to use.

  • :diskProvisioning (String) — default: thin

    Disk provisioning mode.

  • :networkMappings (Hash)

    Network mappings.

  • :propertyMappings (Hash)

    Property mappings.



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
# File 'lib/rbvmomi/vim/OvfManager.rb', line 19

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].map{|key, value| RbVmomi::VIM::KeyValue(:key => key, :value => value)},
    :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 = 0.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

      # XXX handle file:// URIs
      ovfFilename = opts[:uri].to_s
      tmp = ovfFilename.split(/\//)
      tmp.pop
      tmp << fileItem.path
      filename = tmp.join("/")

      method = fileItem.create ? "PUT" : "POST"

      href = deviceUrl.url.gsub("*", opts[:host].config.network.vnic[0].spec.ip.ipAddress)
      downloadCmd = "#{CURLBIN} -L '#{filename}'"
      uploadCmd = "#{CURLBIN} -X #{method} --insecure -T - -H 'Content-Type: application/x-vnd.vmware-streamVmdk' -H 'Content-Length: #{fileItem.size}' '#{href}'"
      system("#{downloadCmd} | #{uploadCmd}")
      progress += (95.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
  raise
end