rbvmomi 1.2.3 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  RbVmomi is a Ruby interface to the vSphere API. Like the Perl and Java SDKs,
6
6
  you can use it to manage ESX and VirtualCenter servers. The current release
7
- supports the vSphere 4.1 API. RbVmomi specific documentation is
7
+ supports the vSphere 5.0 API. RbVmomi specific documentation is
8
8
  online[http://rdoc.info/github/rlane/rbvmomi/master/frames] and is meant to
9
9
  be used alongside the official documentation[http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/index.html].
10
10
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.2.3
1
+ 1.3.0
@@ -49,6 +49,6 @@ case cmd
49
49
  when 'list'
50
50
  vm.config.extraConfig.each { |x| puts "#{x.key}: #{x.value}" }
51
51
  when 'set'
52
- extraConfig = ARGV.map { |x| x.split("=", 2) }.map { |k,v| { :key => k, :value => v } }
52
+ extraConfig = ARGV[2..-1].map { |x| x.split("=", 2) }.map { |k,v| { :key => k, :value => v } }
53
53
  vm.ReconfigVM_Task(:spec => VIM.VirtualMachineConfigSpec(:extraConfig => extraConfig)).wait_for_completion
54
54
  end
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env ruby
2
+ require 'trollop'
3
+ require 'rbvmomi'
4
+ require 'rbvmomi/trollop'
5
+
6
+ VIM = RbVmomi::VIM
7
+ CMDS = %w(mount unmount)
8
+
9
+ opts = Trollop.options do
10
+ banner <<-EOS
11
+ Mount/Unmount an NFS datastore from a cluster or single host system.
12
+
13
+ Usage:
14
+ nfs_datastore.rb [options] resource mount nfs-hostname:/remote/path [name]
15
+ nfs_datastore.rb [options] resource unmount nfs-hostname:/remote/path [name]
16
+
17
+ Commands: #{CMDS * ' '}
18
+
19
+ VIM connection options:
20
+ EOS
21
+
22
+ rbvmomi_connection_opts
23
+
24
+ text <<-EOS
25
+
26
+ VM location options:
27
+ EOS
28
+
29
+ rbvmomi_datacenter_opt
30
+
31
+ text <<-EOS
32
+
33
+ Other options:
34
+ EOS
35
+
36
+ stop_on CMDS
37
+ end
38
+
39
+ Trollop.die("must specify host") unless opts[:host]
40
+
41
+ cr_path = ARGV[0] or Trollop.die("no system name given")
42
+ cmd = ARGV[1] or Trollop.die("no command given")
43
+ abort "invalid command" unless CMDS.member? cmd
44
+ nfs_spec = ARGV[2] or Trollop.die("no nfs path given")
45
+ remoteHost, remotePath = nfs_spec.split(":")
46
+ localPath = ARGV[3] || remoteHost
47
+ mode = "readOnly" #hardcoded.
48
+
49
+ vim = VIM.connect opts
50
+ dc = vim.serviceInstance.find_datacenter(opts[:datacenter]) or abort "datacenter not found"
51
+ cr = dc.find_compute_resource(cr_path) || dc.hostFolder.children.find(cr_path).first
52
+ abort "compute resource not found" unless cr
53
+
54
+ case cr
55
+ when VIM::ClusterComputeResource
56
+ hosts = cr.host
57
+ when VIM::ComputeResource
58
+ hosts = [cr]
59
+ else
60
+ abort "invalid resource"
61
+ end
62
+
63
+ hosts.each do |host|
64
+ hds = host.configManager.datastoreSystem
65
+
66
+ ds = hds.datastore.select {|ds|
67
+ ds.info.respond_to?(:nas) and
68
+ ds.info.name == localPath and
69
+ ds.info.nas.remoteHost == remoteHost and
70
+ ds.info.nas.remotePath == remotePath
71
+ }.first
72
+
73
+ case cmd
74
+ when 'mount'
75
+ if ds
76
+ puts "already mounted on #{host.name} as #{ds.name}"
77
+ else
78
+ ds =
79
+ hds.CreateNasDatastore(:spec => VIM.HostNasVolumeSpec(:remoteHost => remoteHost,
80
+ :remotePath => remotePath,
81
+ :localPath => localPath,
82
+ :accessMode => mode))
83
+ puts "mounted on #{host.name} as #{ds.name}"
84
+ end
85
+ when 'unmount'
86
+ if ds
87
+ hds.RemoveDatastore(:datastore => ds)
88
+ puts "unmounted from #{host.name}"
89
+ else
90
+ puts "not mounted on #{host.name}"
91
+ end
92
+ else
93
+ abort "invalid command"
94
+ end
95
+ end
@@ -111,6 +111,10 @@ class DataObject < ObjectWithProperties
111
111
  @props[sym] = val
112
112
  end
113
113
 
114
+ def []= sym, val
115
+ _set_property sym, val
116
+ end
117
+
114
118
  def == o
115
119
  return false unless o.class == self.class
116
120
  keys = (props.keys + o.props.keys).uniq
@@ -165,7 +169,7 @@ class ManagedObject < ObjectWithMethods
165
169
  }])[0]
166
170
 
167
171
  if ret.propSet.empty?
168
- fail if ret.missingSet.empty?
172
+ return nil if ret.missingSet.empty?
169
173
  raise ret.missingSet[0].fault
170
174
  else
171
175
  ret.propSet[0].val
@@ -20,8 +20,17 @@ class RbVmomi::TrivialSoap
20
20
  restart_http
21
21
  end
22
22
 
23
+ def close
24
+ @http.finish rescue IOError
25
+ end
26
+
23
27
  def restart_http
24
- @http.finish if @http
28
+ begin
29
+ @http.finish if @http
30
+ rescue Exception => ex
31
+ puts "WARNING: Ignoring exception: #{ex.message}"
32
+ puts ex.backtrace.join("\n")
33
+ end
25
34
  @http = Net::HTTP.new(@opts[:host], @opts[:port], @opts[:proxyHost], @opts[:proxyPort])
26
35
  if @opts[:ssl]
27
36
  require 'net/https'
@@ -77,8 +86,12 @@ class RbVmomi::TrivialSoap
77
86
  end
78
87
  end
79
88
  end_time = Time.now
89
+
90
+ if response.is_a? Net::HTTPServiceUnavailable
91
+ raise "Got HTTP 503: Service unavailable"
92
+ end
80
93
 
81
- @cookie = response['set-cookie'] if response.key? 'set-cookie'
94
+ self.cookie = response['set-cookie'] if response.key? 'set-cookie'
82
95
 
83
96
  nk = Nokogiri(response.body)
84
97
 
@@ -1,5 +1,6 @@
1
1
  # Copyright (c) 2010 VMware, Inc. All Rights Reserved.
2
2
  require 'set'
3
+ require 'monitor'
3
4
 
4
5
  module RbVmomi
5
6
 
@@ -21,6 +22,7 @@ class TypeLoader
21
22
  def initialize target, fn
22
23
  @target = target
23
24
  @db = TypeStore.new fn
25
+ @lock = Monitor.new
24
26
  end
25
27
 
26
28
  def init
@@ -42,8 +44,10 @@ class TypeLoader
42
44
 
43
45
  def load_type name
44
46
  fail unless name.is_a? String
45
- @target.const_set name, make_type(name)
46
- load_extension name
47
+ @lock.synchronize do
48
+ @target.const_set name, make_type(name)
49
+ load_extension name
50
+ end
47
51
  nil
48
52
  end
49
53
 
data/lib/rbvmomi/vim.rb CHANGED
@@ -35,11 +35,37 @@ class VIM < Connection
35
35
  vim.serviceContent.sessionManager.Login :userName => opts[:user], :password => opts[:password]
36
36
  unless rev_given
37
37
  rev = vim.serviceContent.about.apiVersion
38
- vim.rev = [rev, '4.1'].min
38
+ vim.rev = [rev, '5.0'].min
39
39
  end
40
40
  end
41
41
  end
42
42
 
43
+ def close
44
+ VIM::SessionManager(self, 'SessionManager').Logout
45
+ super
46
+ end
47
+
48
+ def cookie= cookie
49
+ super
50
+ ObjectSpace.undefine_finalizer self
51
+ ObjectSpace.define_finalizer(self, self.class.finalizer(cookie,@opts))
52
+ end
53
+
54
+ def self.finalizer cookie, opts
55
+ proc do |object_id|
56
+ new(opts).tap do |vim|
57
+ vim.instance_variable_set :@cookie, cookie
58
+ vim.close
59
+ end
60
+ nil
61
+ end
62
+ end
63
+
64
+ def rev= x
65
+ super
66
+ @serviceContent = nil
67
+ end
68
+
43
69
  # Return the ServiceInstance
44
70
  #
45
71
  # The ServiceInstance is the root of the vSphere inventory.
@@ -75,7 +101,7 @@ class VIM < Connection
75
101
  pp.text "VIM(#{@opts[:host]})"
76
102
  end
77
103
 
78
- @extension_dirs = [File.join(File.dirname(__FILE__), "vim")]
104
+ @extension_dirs = [File.join(File.dirname(__FILE__), "vim")] + (ENV['RBVMOMI_VIM_EXTENSION_PATH']||'').split(':')
79
105
 
80
106
  # Directories to search for extensions
81
107
  def self.extension_dirs
@@ -84,6 +84,8 @@ class RbVmomi::VIM::Folder
84
84
  x
85
85
  elsif create and type == RbVmomi::VIM::Folder
86
86
  p.CreateFolder(:name => final)
87
+ elsif create and type == RbVmomi::VIM::Datacenter
88
+ p.CreateDatacenter(:name => final)
87
89
  else
88
90
  nil
89
91
  end
@@ -54,10 +54,9 @@ class RbVmomi::VIM::OvfManager
54
54
 
55
55
  nfcLease.wait_until(:state) { nfcLease.state != "initializing" }
56
56
  raise nfcLease.error if nfcLease.state == "error"
57
-
58
57
  begin
59
58
  nfcLease.HttpNfcLeaseProgress(:percent => 5)
60
- progress = 0.0
59
+ progress = 5.0
61
60
  result.fileItem.each do |fileItem|
62
61
  deviceUrl = nfcLease.info.deviceUrl.find{|x| x.importKey == fileItem.deviceId}
63
62
  if !deviceUrl
@@ -73,11 +72,26 @@ class RbVmomi::VIM::OvfManager
73
72
 
74
73
  method = fileItem.create ? "PUT" : "POST"
75
74
 
75
+ keepAliveThread = Thread.new do
76
+ while true
77
+ sleep 2 * 60
78
+ nfcLease.HttpNfcLeaseProgress(:percent => progress.to_i)
79
+ end
80
+ end
81
+
76
82
  href = deviceUrl.url.gsub("*", opts[:host].config.network.vnic[0].spec.ip.ipAddress)
77
83
  downloadCmd = "#{CURLBIN} -L '#{URI::escape(filename)}'"
78
- uploadCmd = "#{CURLBIN} -X #{method} --insecure -T - -H 'Content-Type: application/x-vnd.vmware-streamVmdk' -H 'Content-Length: #{fileItem.size}' '#{URI::escape(href)}'"
79
- system("#{downloadCmd} | #{uploadCmd}")
80
- progress += (95.0 / result.fileItem.length)
84
+ uploadCmd = "#{CURLBIN} -Ss -X #{method} --insecure -T - -H 'Content-Type: application/x-vnd.vmware-streamVmdk' '#{URI::escape(href)}'"
85
+ # Previously we used to append "-H 'Content-Length: #{fileItem.size}'"
86
+ # to the uploadCmd. It is not clear to me why, but that leads to
87
+ # trucation of the uploaded disk. Without this option curl can't tell
88
+ # the progress, but who cares
89
+ system("#{downloadCmd} | #{uploadCmd}", STDOUT => "/dev/null")
90
+
91
+ keepAliveThread.kill
92
+ keepAliveThread.join
93
+
94
+ progress += (90.0 / result.fileItem.length)
81
95
  nfcLease.HttpNfcLeaseProgress(:percent => progress.to_i)
82
96
  end
83
97
 
@@ -0,0 +1,23 @@
1
+ class RbVmomi::VIM::PropertyCollector
2
+ def collectMultiple objs, *pathSet
3
+ klasses = objs.map{|x| x.class}.uniq
4
+ klass = if klasses.length > 1
5
+ # common superclass
6
+ klasses.map(&:ancestors).inject(&:&)[0]
7
+ else
8
+ klasses.first
9
+ end
10
+
11
+ spec = {
12
+ :objectSet => objs.map{|x| { :obj => x }},
13
+ :propSet => [{
14
+ :pathSet => pathSet,
15
+ :type => klass.wsdl_name
16
+ }]
17
+ }
18
+ res = RetrieveProperties(:specSet => [spec])
19
+ Hash[res.map do |x|
20
+ [x.obj, x.to_hash]
21
+ end]
22
+ end
23
+ end
@@ -43,11 +43,13 @@ class RbVmomi::VIM::ServiceInstance
43
43
  end
44
44
  end
45
45
 
46
- yield task_props
46
+ yield task_props if block_given?
47
47
  end
48
48
  ensure
49
49
  @soap.propertyCollector.CancelWaitForUpdates
50
50
  filter.DestroyPropertyFilter
51
51
  end
52
+
53
+ task_props
52
54
  end
53
55
  end
@@ -4,4 +4,10 @@ class RbVmomi::VIM::VirtualMachine
4
4
  def macs
5
5
  Hash[self.config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard).map { |x| [x.deviceInfo.label, x.macAddress] }]
6
6
  end
7
+
8
+ # Retrieve all virtual disk devices.
9
+ # @return [Array] Array of virtual disk devices.
10
+ def disks
11
+ self.config.hardware.device.grep(RbVmomi::VIM::VirtualDisk)
12
+ end
7
13
  end
data/vmodl.db CHANGED
Binary file
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: rbvmomi
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.2.3
5
+ version: 1.3.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Rich Lane
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-04-05 00:00:00 -07:00
13
+ date: 2011-09-02 00:00:00 -07:00
14
14
  default_executable: rbvmomish
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -72,6 +72,7 @@ files:
72
72
  - examples/extraConfig.rb
73
73
  - examples/logbundle.rb
74
74
  - examples/logtail.rb
75
+ - examples/nfs_datastore.rb
75
76
  - examples/power.rb
76
77
  - examples/readme-1.rb
77
78
  - examples/readme-2.rb
@@ -96,6 +97,7 @@ files:
96
97
  - lib/rbvmomi/vim/ObjectContent.rb
97
98
  - lib/rbvmomi/vim/ObjectUpdate.rb
98
99
  - lib/rbvmomi/vim/OvfManager.rb
100
+ - lib/rbvmomi/vim/PropertyCollector.rb
99
101
  - lib/rbvmomi/vim/ResourcePool.rb
100
102
  - lib/rbvmomi/vim/ServiceInstance.rb
101
103
  - lib/rbvmomi/vim/Task.rb
@@ -144,6 +146,7 @@ test_files:
144
146
  - examples/extraConfig.rb
145
147
  - examples/logbundle.rb
146
148
  - examples/logtail.rb
149
+ - examples/nfs_datastore.rb
147
150
  - examples/power.rb
148
151
  - examples/readme-1.rb
149
152
  - examples/readme-2.rb