rvc 1.5.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +1 -1
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/bin/rvc +53 -9
- data/lib/rvc/completion.rb +57 -19
- data/lib/rvc/extensions/ComputeResource.rb +2 -2
- data/lib/rvc/extensions/DVPortSetting.rb +108 -0
- data/lib/rvc/extensions/Datacenter.rb +19 -4
- data/lib/rvc/extensions/Datastore.rb +6 -1
- data/lib/rvc/extensions/DistributedVirtualPort.rb +146 -0
- data/lib/rvc/extensions/DistributedVirtualPortgroup.rb +274 -10
- data/lib/rvc/extensions/DistributedVirtualSwitch.rb +124 -3
- data/lib/rvc/extensions/Folder.rb +9 -2
- data/lib/rvc/extensions/HostSystem.rb +60 -0
- data/lib/rvc/extensions/ManagedEntity.rb +19 -0
- data/lib/rvc/extensions/ParaVirtualSCSIController.rb +25 -0
- data/lib/rvc/extensions/PerfCounterInfo.rb +26 -0
- data/lib/rvc/extensions/PerformanceManager.rb +83 -0
- data/lib/rvc/extensions/ResourcePool.rb +21 -0
- data/lib/rvc/extensions/VirtualDevice.rb +59 -0
- data/lib/rvc/extensions/VirtualDisk.rb +25 -0
- data/lib/rvc/extensions/VirtualEthernetCard.rb +32 -0
- data/lib/rvc/extensions/VirtualMachine.rb +112 -1
- data/lib/rvc/field.rb +122 -0
- data/lib/rvc/filesystem_session.rb +20 -0
- data/lib/rvc/inventory.rb +35 -12
- data/lib/rvc/known_hosts.rb +20 -0
- data/lib/rvc/memory_session.rb +20 -0
- data/lib/rvc/modules.rb +67 -7
- data/lib/rvc/modules/alarm.rb +37 -0
- data/lib/rvc/modules/basic.rb +172 -41
- data/lib/rvc/modules/cluster.rb +18 -2
- data/lib/rvc/modules/core.rb +63 -0
- data/lib/rvc/modules/datastore.rb +158 -0
- data/lib/rvc/modules/device.rb +275 -0
- data/lib/rvc/modules/esxcli.rb +193 -0
- data/lib/rvc/modules/find.rb +125 -0
- data/lib/rvc/modules/issue.rb +33 -0
- data/lib/rvc/modules/perf.rb +284 -0
- data/lib/rvc/modules/permissions.rb +20 -0
- data/lib/rvc/modules/resource_pool.rb +69 -0
- data/lib/rvc/modules/role.rb +23 -3
- data/lib/rvc/modules/snapshot.rb +20 -0
- data/lib/rvc/modules/vds.rb +605 -0
- data/lib/rvc/modules/vim.rb +103 -26
- data/lib/rvc/modules/vm.rb +93 -220
- data/lib/rvc/modules/vnc.rb +50 -13
- data/lib/rvc/option_parser.rb +50 -2
- data/lib/rvc/readline-ffi.rb +2 -1
- data/lib/rvc/shell.rb +34 -33
- data/lib/rvc/util.rb +120 -2
- data/test/test_fs.rb +9 -5
- data/test/test_metric.rb +79 -0
- metadata +33 -3
data/README.rdoc
CHANGED
data/Rakefile
CHANGED
@@ -7,11 +7,12 @@ begin
|
|
7
7
|
gem.email = "rlane@vmware.com"
|
8
8
|
#gem.homepage = ""
|
9
9
|
gem.authors = ["Rich Lane"]
|
10
|
-
gem.add_dependency 'rbvmomi', '>= 1.
|
10
|
+
gem.add_dependency 'rbvmomi', '>= 1.5.0'
|
11
11
|
gem.add_dependency 'trollop', '>= 1.16.2'
|
12
12
|
gem.add_dependency 'backports', '>= 1.18.2'
|
13
13
|
gem.add_dependency 'highline', '>= 1.6.1'
|
14
14
|
gem.add_dependency 'zip', '>= 2.0.2'
|
15
|
+
gem.add_dependency 'terminal-table', '>= 1.4.2'
|
15
16
|
#gem.add_dependency 'ffi', '>= 1.0.7'
|
16
17
|
end
|
17
18
|
rescue LoadError
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.6.0
|
data/bin/rvc
CHANGED
@@ -28,6 +28,7 @@ require 'shellwords'
|
|
28
28
|
require 'yaml'
|
29
29
|
require 'backports'
|
30
30
|
require 'rvc'
|
31
|
+
require 'tempfile'
|
31
32
|
|
32
33
|
VIM = RbVmomi::VIM
|
33
34
|
|
@@ -54,6 +55,7 @@ EOS
|
|
54
55
|
opt :create_directory, "Create the initial directory if it doesn't exist", :short => :none
|
55
56
|
opt :cmd, "command to evaluate", :short => 'c', :multi => true, :type => :string
|
56
57
|
opt :script, "file to execute", :short => 's', :type => :string
|
58
|
+
opt :cookie, "authentication cookie file", :short => 'k', :type => :string
|
57
59
|
end
|
58
60
|
|
59
61
|
$interactive = $opts[:script].nil? and $stdin.tty?
|
@@ -77,20 +79,38 @@ $shell.session.connections.each do |key|
|
|
77
79
|
conn = $shell.session.get_connection(key) or fail "no such connection #{key.inspect}"
|
78
80
|
uri = "#{conn['username']}@#{conn['host']}"
|
79
81
|
begin
|
80
|
-
puts "Connecting to #{
|
82
|
+
puts "Connecting to #{conn['host']}..."
|
81
83
|
CMD.vim.connect uri, {}
|
82
84
|
rescue RVC::Util::UserError
|
83
|
-
puts "Failed to connect to #{
|
85
|
+
puts "Failed to connect to #{conn['host']}: #{$!.message}"
|
84
86
|
exit 1
|
85
87
|
end
|
86
88
|
end
|
87
89
|
|
90
|
+
cookies = {}
|
91
|
+
certdigests = {}
|
92
|
+
if $opts[:cookie]
|
93
|
+
File.readlines($opts[:cookie]).each do |info|
|
94
|
+
host, cookie, certdigest = info.chomp.split('|')
|
95
|
+
cookies[host] = cookie
|
96
|
+
certdigests[host] = certdigest
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
88
100
|
ARGV.each do |uri|
|
101
|
+
# get hostname from uri to display in "connecting to..." message
|
102
|
+
hostinfo = uri.split("@")
|
103
|
+
host = if hostinfo.length > 1
|
104
|
+
hostinfo[1].split(":")[0]
|
105
|
+
else
|
106
|
+
hostinfo[0].split(":")[0]
|
107
|
+
end
|
89
108
|
begin
|
90
|
-
puts "Connecting to #{
|
91
|
-
CMD.vim.connect uri, {
|
109
|
+
puts "Connecting to #{host}..." if (ARGV+$shell.session.connections).size > 1
|
110
|
+
CMD.vim.connect uri, {:cookie => cookies[host],
|
111
|
+
:certdigest => certdigests[host]}
|
92
112
|
rescue RVC::Util::UserError
|
93
|
-
puts "Failed to connect to #{
|
113
|
+
puts "Failed to connect to #{host}: #{$!.message}"
|
94
114
|
exit 1
|
95
115
|
end
|
96
116
|
end
|
@@ -99,7 +119,11 @@ if $interactive
|
|
99
119
|
RVC::Completion.install
|
100
120
|
history_fn = "#{ENV['HOME']}/.rvc-history"
|
101
121
|
IO.foreach(history_fn) { |l| Readline::HISTORY << l.chomp } rescue puts "Welcome to RVC. Try the 'help' command."
|
102
|
-
|
122
|
+
begin
|
123
|
+
history = File.open(history_fn, 'a')
|
124
|
+
rescue Errno::EACCES
|
125
|
+
history = nil
|
126
|
+
end
|
103
127
|
end
|
104
128
|
|
105
129
|
if $opts[:path]
|
@@ -127,23 +151,43 @@ if defined? Ocra
|
|
127
151
|
end
|
128
152
|
|
129
153
|
if $interactive
|
130
|
-
|
154
|
+
if ENV['DISPLAY']
|
155
|
+
$stderr.puts "VMRC is not installed. You will be unable to view virtual machine consoles. Use the vmrc.install command to install it." unless CMD.vmrc.find_vmrc
|
156
|
+
end
|
131
157
|
$stderr.puts "Use the 'connect' command to connect to an ESX or VC server." if $shell.connections.empty?
|
132
158
|
CMD.basic.ls RVC::Util.lookup_single('.')
|
133
159
|
end
|
134
160
|
|
161
|
+
trap "SIGCHLD" do |sig|
|
162
|
+
begin
|
163
|
+
while pid = Process.wait(-1, Process::WNOHANG)
|
164
|
+
end
|
165
|
+
rescue Errno::ECHILD
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
135
169
|
if $opts[:script]
|
136
170
|
$shell.eval_ruby File.read($opts[:script]), $opts[:script]
|
137
171
|
else
|
138
172
|
while true
|
139
173
|
begin
|
140
|
-
|
174
|
+
begin
|
175
|
+
input = $opts[:cmd].shift || Readline.readline($shell.prompt, false) or break
|
176
|
+
rescue
|
177
|
+
puts "\n#{$!.class} during readline: #{$!.message}"
|
178
|
+
$!.backtrace.each { |x| puts x } if $shell.debug
|
179
|
+
next
|
180
|
+
end
|
141
181
|
input = input.strip
|
142
182
|
next if input.empty?
|
143
|
-
(history.puts
|
183
|
+
(history && history.puts(input); Readline::HISTORY << input) unless input == Readline::HISTORY.to_a[-1]
|
144
184
|
$shell.eval_input input
|
145
185
|
rescue Interrupt
|
146
186
|
puts
|
147
187
|
end
|
148
188
|
end
|
149
189
|
end
|
190
|
+
|
191
|
+
$shell.connections.each do |name, conn|
|
192
|
+
conn.close if conn.respond_to? :close rescue puts("failed to close connection #{name.inspect}: #{$!.class}: #{$!.message}")
|
193
|
+
end
|
data/lib/rvc/completion.rb
CHANGED
@@ -40,10 +40,16 @@ module Completion
|
|
40
40
|
|
41
41
|
Completor = lambda do |word|
|
42
42
|
return unless word
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
begin
|
44
|
+
line = Readline.line_buffer if Readline.respond_to? :line_buffer
|
45
|
+
append_char, candidates = RVC::Completion.complete word, line
|
46
|
+
Readline.completion_append_character = append_char
|
47
|
+
candidates
|
48
|
+
rescue RVC::Util::UserError
|
49
|
+
puts
|
50
|
+
puts $!.message
|
51
|
+
Readline.refresh_line
|
52
|
+
end
|
47
53
|
end
|
48
54
|
|
49
55
|
def self.install
|
@@ -58,25 +64,44 @@ module Completion
|
|
58
64
|
end
|
59
65
|
|
60
66
|
def self.complete word, line
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
+
line ||= ''
|
68
|
+
first_whitespace_index = line.index(' ')
|
69
|
+
|
70
|
+
if Readline.respond_to? :point
|
71
|
+
do_complete_cmd = !first_whitespace_index || first_whitespace_index >= Readline.point
|
72
|
+
do_complete_args = !do_complete_cmd
|
67
73
|
else
|
68
|
-
|
74
|
+
do_complete_cmd = true
|
75
|
+
do_complete_args = true
|
76
|
+
end
|
77
|
+
|
78
|
+
candidates = []
|
79
|
+
|
80
|
+
if do_complete_cmd
|
81
|
+
candidates.concat cmd_candidates(word)
|
69
82
|
end
|
70
83
|
|
71
|
-
|
84
|
+
if do_complete_args
|
85
|
+
mod, cmd, args = Shell.parse_input line
|
86
|
+
if mod and mod.completor_for cmd
|
87
|
+
candidates.concat RVC::complete_for_cmd(line, word)
|
88
|
+
else
|
89
|
+
candidates.concat(fs_candidates(word) +
|
90
|
+
long_option_candidates(mod, cmd, word))
|
91
|
+
end
|
92
|
+
end
|
72
93
|
|
73
|
-
if candidates.size == 1
|
74
|
-
append_char =
|
94
|
+
if candidates.size == 1
|
95
|
+
append_char = candidates[0][1]
|
75
96
|
else
|
76
|
-
append_char = '
|
97
|
+
append_char = '?' # should never be displayed
|
77
98
|
end
|
78
99
|
|
79
|
-
return append_char, candidates
|
100
|
+
return append_char, candidates.map(&:first)
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.fs_candidates word
|
104
|
+
child_candidates(word) + mark_candidates(word)
|
80
105
|
end
|
81
106
|
|
82
107
|
def self.cmd_candidates word
|
@@ -86,7 +111,18 @@ module Completion
|
|
86
111
|
m.commands.each { |s| ret << "#{name}.#{s}" }
|
87
112
|
end
|
88
113
|
ret.concat ALIASES.keys
|
89
|
-
ret.
|
114
|
+
ret.grep(prefix_regex).sort.
|
115
|
+
map { |x| [x, ' '] }
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.long_option_candidates mod, cmd, word
|
119
|
+
return [] unless mod and cmd
|
120
|
+
parser = mod.opts_for cmd
|
121
|
+
return [] unless parser.is_a? RVC::OptionParser
|
122
|
+
prefix_regex = /^#{Regexp.escape(word)}/
|
123
|
+
parser.specs.map { |k,v| "--#{v[:long]}" }.
|
124
|
+
grep(prefix_regex).sort.
|
125
|
+
map { |x| [x, ' '] }
|
90
126
|
end
|
91
127
|
|
92
128
|
# TODO convert to globbing
|
@@ -101,13 +137,15 @@ module Completion
|
|
101
137
|
children.
|
102
138
|
select { |k,v| k.gsub(' ', '\\ ') =~ /^#{Regexp.escape(last)}/ }.
|
103
139
|
map { |k,v| (arcs+[k])*'/' }.
|
104
|
-
map { |x| x.gsub ' ', '\\ ' }
|
140
|
+
map { |x| x.gsub ' ', '\\ ' }.
|
141
|
+
map { |x| [x, '/'] }
|
105
142
|
end
|
106
143
|
|
107
144
|
def self.mark_candidates word
|
108
145
|
return [] unless word.empty? || word[0..0] == '~'
|
109
146
|
prefix_regex = /^#{Regexp.escape(word[1..-1] || '')}/
|
110
|
-
$shell.session.marks.
|
147
|
+
$shell.session.marks.grep(prefix_regex).sort.
|
148
|
+
map { |x| ["~#{x}", '/'] }
|
111
149
|
end
|
112
150
|
end
|
113
151
|
end
|
@@ -25,8 +25,8 @@ class RbVmomi::VIM::ComputeResource
|
|
25
25
|
pct_cpu_used = 100.0*stats[:usedCPU]/stats[:totalCPU]
|
26
26
|
pct_mem_used = 100.0*stats[:usedMem]/stats[:totalMem]
|
27
27
|
puts "name: #{name}"
|
28
|
-
puts "cpu #{stats[:totalCPU]} GHz (#{pct_cpu_used.to_i}% used)"
|
29
|
-
puts "memory #{stats[:totalMem]} GB (#{pct_mem_used.to_i}% used)"
|
28
|
+
puts "cpu: #{stats[:totalCPU]/1e3} GHz (#{pct_cpu_used.to_i}% used)"
|
29
|
+
puts "memory: #{stats[:totalMem]/1e3} GB (#{pct_mem_used.to_i}% used)"
|
30
30
|
puts "hosts:"
|
31
31
|
host.each do |h|
|
32
32
|
puts " #{h.name}"
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# Copyright (c) 2011 VMware, Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
include RVC::Util
|
22
|
+
|
23
|
+
class RbVmomi::VIM::DVPortSetting
|
24
|
+
def dump_config vds, prefix, show_inheritance = true, show_uplinkinfo = true
|
25
|
+
@show_inheritance = show_inheritance
|
26
|
+
|
27
|
+
# map network respool to human-readable name
|
28
|
+
if self.networkResourcePoolKey
|
29
|
+
poolName = translate_respool vds, self.networkResourcePoolKey, show_inheritance
|
30
|
+
end
|
31
|
+
puts_policy "#{prefix}blocked:", self.blocked
|
32
|
+
puts_policy("#{prefix}vlan:", self.vlan, "", nil) { |v| translate_vlan v }
|
33
|
+
if self.networkResourcePoolKey
|
34
|
+
puts "#{prefix}network resource pool: #{poolName}"
|
35
|
+
end
|
36
|
+
p = self.inShapingPolicy
|
37
|
+
if p
|
38
|
+
puts "#{prefix}Rx Shaper: "
|
39
|
+
puts_policy "#{prefix} enabled:", p.enabled
|
40
|
+
avg_bw = p.averageBandwidth
|
41
|
+
puts_policy("#{prefix} average bw:", avg_bw, "b/sec"){|v|metric(v)}
|
42
|
+
puts_policy("#{prefix} peak bw:", p.peakBandwidth, "b/sec"){|v|metric(v)}
|
43
|
+
puts_policy("#{prefix} burst size:", p.burstSize, "B"){|v|metric(v)}
|
44
|
+
end
|
45
|
+
p = self.outShapingPolicy
|
46
|
+
if p
|
47
|
+
puts "#{prefix}Tx Shaper:"
|
48
|
+
puts_policy "#{prefix} enabled:", p.enabled
|
49
|
+
avg_bw = p.averageBandwidth
|
50
|
+
puts_policy("#{prefix} average bw:", avg_bw, "b/sec") { |v| metric(v) }
|
51
|
+
puts_policy("#{prefix} peak bw:", p.peakBandwidth, "b/sec") {|v| metric(v)}
|
52
|
+
puts_policy("#{prefix} burst size:", p.burstSize, "B") {|v| metric(v)}
|
53
|
+
end
|
54
|
+
if show_uplinkinfo
|
55
|
+
p = self.uplinkTeamingPolicy
|
56
|
+
if p
|
57
|
+
puts "#{prefix}Uplink Teaming Policy:"
|
58
|
+
puts_policy "#{prefix} policy:", p.policy #XXX map the strings values
|
59
|
+
puts_policy "#{prefix} reverse policy:", p.reversePolicy
|
60
|
+
puts_policy "#{prefix} notify switches:", p.notifySwitches
|
61
|
+
puts_policy "#{prefix} rolling order:", p.rollingOrder
|
62
|
+
c = p.failureCriteria
|
63
|
+
if c
|
64
|
+
puts "#{prefix} Failure Criteria: "
|
65
|
+
puts_policy "#{prefix} check speed:", c.checkSpeed
|
66
|
+
puts_policy("#{prefix} speed:", c.speed, "Mb/sec")# { |v| metric(v) }
|
67
|
+
puts_policy "#{prefix} check duplex:", c.checkDuplex
|
68
|
+
puts_policy "#{prefix} full duplex:", c.fullDuplex
|
69
|
+
puts_policy "#{prefix} check error percentage:", c.checkErrorPercent
|
70
|
+
puts_policy "#{prefix} max error percentage:", c.percentage, "%"
|
71
|
+
puts_policy "#{prefix} check beacon:", c.checkBeacon
|
72
|
+
end
|
73
|
+
o = p.uplinkPortOrder
|
74
|
+
if o
|
75
|
+
puts "#{prefix} Uplink Port Order:"
|
76
|
+
puts_policy("#{prefix} active:", o,"", :activeUplinkPort){|v|v.join(',')}
|
77
|
+
puts_policy("#{prefix} standby:",o,"",:standbyUplinkPort){|v|v.join(',')}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
p = self.securityPolicy
|
82
|
+
if p
|
83
|
+
puts "#{prefix}Security:"
|
84
|
+
puts_policy "#{prefix} allow promiscuous mode:", p.allowPromiscuous
|
85
|
+
puts_policy "#{prefix} allow mac changes:", p.macChanges
|
86
|
+
puts_policy "#{prefix} allow forged transmits:", p.forgedTransmits
|
87
|
+
puts_policy "#{prefix}enable ipfix monitoring:", self.ipfixEnabled
|
88
|
+
puts_policy "#{prefix}forward all tx to uplink:", self.txUplink
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def puts_policy prefix, policy, suffix = "", prop = :value, &b
|
93
|
+
b ||= lambda { |v| v }
|
94
|
+
if policy
|
95
|
+
if prop != nil
|
96
|
+
v = policy.send(prop)
|
97
|
+
else
|
98
|
+
v = policy
|
99
|
+
end
|
100
|
+
print "#{prefix} #{b.call(v)}#{suffix}"
|
101
|
+
if @show_inheritance and policy.inherited == false
|
102
|
+
puts "*"
|
103
|
+
else
|
104
|
+
puts ""
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -27,10 +27,25 @@ class RbVmomi::VIM::Datacenter
|
|
27
27
|
vmFolder, datastoreFolder, networkFolder, hostFolder =
|
28
28
|
collect *%w(vmFolder datastoreFolder networkFolder hostFolder)
|
29
29
|
{
|
30
|
-
'
|
31
|
-
'
|
32
|
-
'
|
33
|
-
'
|
30
|
+
'vms' => vmFolder,
|
31
|
+
'datastores' => datastoreFolder,
|
32
|
+
'networks' => networkFolder,
|
33
|
+
'computers' => hostFolder,
|
34
34
|
}
|
35
35
|
end
|
36
|
+
|
37
|
+
# For compatibility with previous RVC versions
|
38
|
+
def traverse_one arc
|
39
|
+
children = self.children
|
40
|
+
return children[arc] if children.member? arc
|
41
|
+
if arc == 'vm' then return vmFolder
|
42
|
+
elsif arc == 'datastore' then return datastoreFolder
|
43
|
+
elsif arc == 'network' then return networkFolder
|
44
|
+
elsif arc == 'host' then return hostFolder
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.folder?
|
49
|
+
true
|
50
|
+
end
|
36
51
|
end
|
@@ -23,10 +23,15 @@ class RbVmomi::VIM::Datastore
|
|
23
23
|
s, info, = collect :summary, :info
|
24
24
|
puts "type: #{s.type}"
|
25
25
|
puts "url: #{s.accessible ? s.url : '<inaccessible>'}"
|
26
|
-
puts "uuid: #{info.vmfs.uuid}"
|
27
26
|
puts "multipleHostAccess: #{s.multipleHostAccess}"
|
28
27
|
puts "capacity: %0.2fGB" % (s.capacity.to_f/10**9)
|
29
28
|
puts "free space: %0.2fGB" % (s.freeSpace.to_f/10**9)
|
29
|
+
case info
|
30
|
+
when VIM::VmfsDatastoreInfo
|
31
|
+
puts "uuid: #{info.vmfs.uuid}"
|
32
|
+
when VIM::NasDatastoreInfo
|
33
|
+
puts "location: #{info.nas.remoteHost}:#{info.nas.remotePath}"
|
34
|
+
end
|
30
35
|
end
|
31
36
|
|
32
37
|
def self.ls_properties
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# Copyright (c) 2011 VMware, Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
class RbVmomi::VIM::DistributedVirtualPort
|
22
|
+
include RVC::InventoryObject
|
23
|
+
|
24
|
+
field 'ip' do
|
25
|
+
summary "The guest tools reported IP address."
|
26
|
+
property 'connectee'
|
27
|
+
block do |c|
|
28
|
+
ip = nil
|
29
|
+
vm = c.connectedEntity
|
30
|
+
if vm.is_a? VIM::VirtualMachine
|
31
|
+
info = vm.guest.net.reject { |info|
|
32
|
+
info.deviceConfigId.to_s != c.nicKey
|
33
|
+
}.first
|
34
|
+
if info != nil
|
35
|
+
#XXX deal with multiple ips?
|
36
|
+
ip = info.ipAddress[0]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
ip
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
field 'mac' do
|
44
|
+
summary "The guest tools reported IP address."
|
45
|
+
property 'connectee'
|
46
|
+
block do |c|
|
47
|
+
mac = nil
|
48
|
+
vm = c.connectedEntity
|
49
|
+
if vm.is_a? VIM::VirtualMachine
|
50
|
+
info = vm.config.hardware.device.reject { |device|
|
51
|
+
!(device.class < VIM::VirtualEthernetCard &&
|
52
|
+
device.key.to_s == c.nicKey)
|
53
|
+
}.first
|
54
|
+
if info != nil
|
55
|
+
mac = info.macAddress
|
56
|
+
end
|
57
|
+
end
|
58
|
+
mac
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def display_info
|
63
|
+
# if possible, get info about the connected VM
|
64
|
+
vm_name = ""
|
65
|
+
mac = ""
|
66
|
+
ip = ""
|
67
|
+
if self.connectee
|
68
|
+
vm = self.connectee.connectedEntity
|
69
|
+
if vm.class == VIM::VirtualMachine
|
70
|
+
vm_name = vm.name
|
71
|
+
mac = vm.config.hardware.device.reject { |device|
|
72
|
+
!(device.class < VIM::VirtualEthernetCard &&
|
73
|
+
device.key.to_s == self.connectee.nicKey)
|
74
|
+
}.first.macAddress
|
75
|
+
nicinfo = vm.guest.net.reject { |info|
|
76
|
+
info.deviceConfigId.to_s != self.connectee.nicKey.to_s
|
77
|
+
}.first
|
78
|
+
|
79
|
+
if nicinfo != nil
|
80
|
+
ip = nicinfo.ipAddress
|
81
|
+
if nicinfo.macAddress != nil and nicinfo.macAddress != ""
|
82
|
+
mac = nicinfo.macAddress
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# if possible, get info about the port configuration
|
89
|
+
poolName = "-"
|
90
|
+
vlan = "-"
|
91
|
+
link_up = false
|
92
|
+
if self.state.runtimeInfo
|
93
|
+
vds = self.rvc_parent.config.distributedVirtualSwitch
|
94
|
+
poolName = translate_respool vds, self.config.setting.networkResourcePoolKey
|
95
|
+
vlan = translate_vlan self.state.runtimeInfo.vlanIds
|
96
|
+
link_up = self.state.runtimeInfo.linkUp
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
#puts "name: #{self.config.name}"
|
101
|
+
puts "link up: #{link_up}"
|
102
|
+
#puts "vds: #{vds.name}"
|
103
|
+
#puts "portgroup: #{self.rvc_parent.name}"
|
104
|
+
#puts "vlan: #{vlan}"
|
105
|
+
#puts "network resource pool: #{poolName}"
|
106
|
+
puts "name: #{self.config.name}"
|
107
|
+
puts "description: #{self.config.description}"
|
108
|
+
puts "host: #{if self.proxyHost then self.proxyHost.name end}"
|
109
|
+
puts "vm: #{vm_name}"
|
110
|
+
puts "mac: #{mac}"
|
111
|
+
puts "ip: #{ip}"
|
112
|
+
puts "Port Settings:"
|
113
|
+
#XXX scope?
|
114
|
+
self.config.setting.dump_config vds, " ", true, false
|
115
|
+
if self.state
|
116
|
+
if self.state.stats
|
117
|
+
puts "Statistics:"
|
118
|
+
stats = self.state.stats
|
119
|
+
# normally, i would explicitly write this out, but in this case
|
120
|
+
# the stats are pretty self explanatory, and require pretty much
|
121
|
+
# no formatting, so we just procedurally generate them
|
122
|
+
stats.class.full_props_desc.map { |stat|
|
123
|
+
stat = stat['name']
|
124
|
+
num = stats.send(stat)
|
125
|
+
# skip uninteresting properties
|
126
|
+
if !num.is_a?(Integer) then next end
|
127
|
+
# un-camelcase the name of the stat
|
128
|
+
stat = stat.gsub(/[A-Z]/) { |p| ' ' + p.downcase}
|
129
|
+
puts " #{stat}: #{num}"
|
130
|
+
}
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def children
|
136
|
+
{
|
137
|
+
'vm' => self.connectee.connectedEntity,
|
138
|
+
'host' => self.proxyHost
|
139
|
+
}
|
140
|
+
end
|
141
|
+
|
142
|
+
def invalidate vds
|
143
|
+
port = vds.FetchDVPorts(:criteria => { :portKey => [self.key] }).first
|
144
|
+
@props = port.props
|
145
|
+
end
|
146
|
+
end
|