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 +1 -1
- data/VERSION +1 -1
- data/examples/extraConfig.rb +1 -1
- data/examples/nfs_datastore.rb +95 -0
- data/lib/rbvmomi/basic_types.rb +5 -1
- data/lib/rbvmomi/trivial_soap.rb +15 -2
- data/lib/rbvmomi/type_loader.rb +6 -2
- data/lib/rbvmomi/vim.rb +28 -2
- data/lib/rbvmomi/vim/Folder.rb +2 -0
- data/lib/rbvmomi/vim/OvfManager.rb +19 -5
- data/lib/rbvmomi/vim/PropertyCollector.rb +23 -0
- data/lib/rbvmomi/vim/ServiceInstance.rb +3 -1
- data/lib/rbvmomi/vim/VirtualMachine.rb +6 -0
- data/vmodl.db +0 -0
- metadata +5 -2
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
|
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.
|
1
|
+
1.3.0
|
data/examples/extraConfig.rb
CHANGED
@@ -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
|
data/lib/rbvmomi/basic_types.rb
CHANGED
@@ -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
|
-
|
172
|
+
return nil if ret.missingSet.empty?
|
169
173
|
raise ret.missingSet[0].fault
|
170
174
|
else
|
171
175
|
ret.propSet[0].val
|
data/lib/rbvmomi/trivial_soap.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
94
|
+
self.cookie = response['set-cookie'] if response.key? 'set-cookie'
|
82
95
|
|
83
96
|
nk = Nokogiri(response.body)
|
84
97
|
|
data/lib/rbvmomi/type_loader.rb
CHANGED
@@ -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
|
-
@
|
46
|
-
|
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, '
|
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
|
data/lib/rbvmomi/vim/Folder.rb
CHANGED
@@ -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 =
|
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'
|
79
|
-
|
80
|
-
|
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.
|
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-
|
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
|