rbvmomi 1.2.3 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|