rvc 1.6.0 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/rvc +46 -70
- data/devel/test-dependencies.sh +4 -0
- data/lib/rvc.rb +5 -6
- data/lib/rvc/command.rb +65 -0
- data/lib/rvc/command_slate.rb +112 -0
- data/lib/rvc/completion.rb +89 -58
- data/lib/rvc/connection.rb +48 -0
- data/lib/rvc/extensions/DistributedVirtualPortgroup.rb +1 -1
- data/lib/rvc/extensions/DistributedVirtualSwitch.rb +3 -3
- data/lib/rvc/extensions/HostSystem.rb +90 -0
- data/lib/rvc/extensions/VirtualMachine.rb +37 -7
- data/lib/rvc/field.rb +59 -12
- data/lib/rvc/fs.rb +34 -4
- data/lib/rvc/inventory.rb +5 -1
- data/lib/rvc/modules/alarm.rb +2 -0
- data/lib/rvc/modules/basic.rb +66 -61
- data/lib/rvc/modules/cluster.rb +117 -22
- data/lib/rvc/modules/connection.rb +40 -0
- data/lib/rvc/modules/core.rb +4 -16
- data/lib/rvc/modules/datacenter.rb +2 -0
- data/lib/rvc/modules/datastore.rb +11 -78
- data/lib/rvc/modules/device.rb +40 -5
- data/lib/rvc/modules/diagnostics.rb +169 -0
- data/lib/rvc/modules/esxcli.rb +9 -5
- data/lib/rvc/modules/find.rb +5 -3
- data/lib/rvc/modules/host.rb +46 -3
- data/lib/rvc/modules/issue.rb +2 -0
- data/lib/rvc/modules/mark.rb +5 -3
- data/lib/rvc/modules/perf.rb +99 -33
- data/lib/rvc/modules/permissions.rb +2 -0
- data/lib/rvc/modules/resource_pool.rb +2 -0
- data/lib/rvc/modules/role.rb +3 -1
- data/lib/rvc/modules/snapshot.rb +12 -4
- data/lib/rvc/modules/statsinterval.rb +13 -11
- data/lib/rvc/modules/vds.rb +67 -10
- data/lib/rvc/modules/vim.rb +19 -53
- data/lib/rvc/modules/vm.rb +27 -6
- data/lib/rvc/modules/vm_guest.rb +490 -0
- data/lib/rvc/modules/vmrc.rb +60 -32
- data/lib/rvc/modules/vnc.rb +2 -0
- data/lib/rvc/namespace.rb +114 -0
- data/lib/rvc/option_parser.rb +12 -15
- data/lib/rvc/readline-ffi.rb +4 -1
- data/lib/rvc/ruby_evaluator.rb +84 -0
- data/lib/rvc/shell.rb +68 -83
- data/lib/rvc/uri_parser.rb +59 -0
- data/lib/rvc/util.rb +134 -29
- data/lib/rvc/{extensions/PerfCounterInfo.rb → version.rb} +2 -4
- data/lib/rvc/{memory_session.rb → vim.rb} +10 -32
- data/test/modules/foo.rb +9 -0
- data/test/modules/foo/bar.rb +9 -0
- data/test/test_completion.rb +17 -0
- data/test/test_fs.rb +9 -11
- data/test/test_help.rb +46 -0
- data/test/test_helper.rb +12 -0
- data/test/test_metric.rb +1 -2
- data/test/test_modules.rb +38 -0
- data/test/test_parse_path.rb +1 -2
- data/test/test_shell.rb +138 -0
- data/test/test_uri.rb +34 -0
- metadata +115 -81
- data/lib/rvc/extensions/PerformanceManager.rb +0 -83
- data/lib/rvc/filesystem_session.rb +0 -101
- data/lib/rvc/modules.rb +0 -138
@@ -0,0 +1,48 @@
|
|
1
|
+
# Copyright (c) 2012 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
|
+
module RVC
|
22
|
+
|
23
|
+
# This module should be mixed in with all connection classes.
|
24
|
+
module Connection
|
25
|
+
include InventoryObject
|
26
|
+
|
27
|
+
module ClassMethods
|
28
|
+
include InventoryObject::ClassMethods
|
29
|
+
|
30
|
+
def folder?
|
31
|
+
true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.included m
|
36
|
+
m.extend ClassMethods
|
37
|
+
end
|
38
|
+
|
39
|
+
def _connection
|
40
|
+
self
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class NullConnection
|
45
|
+
include Connection
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -58,11 +58,11 @@ class RbVmomi::VIM::DistributedVirtualSwitch
|
|
58
58
|
vlan.vlanId.each { |range| trunk_ranges << Range.new(range.start,range.end) }
|
59
59
|
end
|
60
60
|
end
|
61
|
-
trunks =
|
61
|
+
trunks = $shell.cmds.vds.merge_ranges(trunk_ranges).map { |r|
|
62
62
|
if r.begin == r.end then "#{r.begin}" else "#{r.begin}-#{r.end}" end
|
63
63
|
}.join ','
|
64
64
|
|
65
|
-
tags =
|
65
|
+
tags = $shell.cmds.vds.merge_ranges(tag_ranges).map { |r|
|
66
66
|
if r.begin == r.end then "#{r.begin}" else "#{r.begin}-#{r.end}" end
|
67
67
|
}.join ','
|
68
68
|
str = ""
|
@@ -141,7 +141,7 @@ class RbVmomi::VIM::DistributedVirtualSwitch
|
|
141
141
|
portgroups = RVC::FakeFolder.new(self, :portgroup_children)
|
142
142
|
portgroups.define_singleton_method :display_info, lambda {
|
143
143
|
vds = self.rvc_parent
|
144
|
-
|
144
|
+
$shell.cmds.basic.table vds.portgroup, {}
|
145
145
|
}
|
146
146
|
|
147
147
|
{
|
@@ -31,7 +31,97 @@ class RbVmomi::VIM::HostSystem
|
|
31
31
|
" (host): cpu #{numCpuPkgs}*#{numCpuCores}*#{"%.2f" % (cpuMhz.to_f/1000)} GHz, memory #{"%.2f" % (memorySize/10**9)} GB"
|
32
32
|
end
|
33
33
|
|
34
|
+
field 'state.connection' do
|
35
|
+
summary "State of connection to VC."
|
36
|
+
property 'runtime.connectionState'
|
37
|
+
end
|
38
|
+
|
39
|
+
field 'state.power' do
|
40
|
+
summary "Host power state."
|
41
|
+
property 'runtime.powerState'
|
42
|
+
end
|
43
|
+
|
44
|
+
field 'uptime' do
|
45
|
+
summary "Host's uptime in days"
|
46
|
+
properties %w(runtime.bootTime)
|
47
|
+
block { |t| t ? MetricNumber.new(((Time.now-t) / (24 * 60 * 60)), 'd') : nil }
|
48
|
+
end
|
49
|
+
|
50
|
+
field 'num.vms' do
|
51
|
+
summary "Number of VMs on the host"
|
52
|
+
properties %w(vm)
|
53
|
+
block { |t| t ? t.length : nil }
|
54
|
+
end
|
55
|
+
|
56
|
+
field 'num.poweredonvms' do
|
57
|
+
summary "Number of VMs on the host"
|
58
|
+
properties %w(vm)
|
59
|
+
block do |vms|
|
60
|
+
if vms && vms.length > 0
|
61
|
+
conn = vms.first._connection
|
62
|
+
pc = conn.propertyCollector
|
63
|
+
vmsProps = pc.collectMultiple(vms, 'runtime.powerState')
|
64
|
+
vmsProps.select{|vm, p| p['runtime.powerState'] == 'poweredOn'}.length
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
field 'cpuusage' do
|
70
|
+
summary "Realtime CPU usage in percent"
|
71
|
+
properties %w(summary.hardware.numCpuCores summary.hardware.cpuMhz summary.quickStats)
|
72
|
+
block do |cores, mhz, stats|
|
73
|
+
if cores && mhz && stats
|
74
|
+
value = stats.overallCpuUsage.to_f * 100 / (cores * mhz)
|
75
|
+
MetricNumber.new(value, '%')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
field 'memusage' do
|
81
|
+
summary "Realtime Mem usage in percent"
|
82
|
+
properties %w(summary.hardware.memorySize summary.quickStats)
|
83
|
+
block do |mem, stats|
|
84
|
+
if mem && stats
|
85
|
+
value = stats.overallMemoryUsage.to_f * 100 / (mem / 1024.0 / 1024.0)
|
86
|
+
MetricNumber.new(value, '%')
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
[['.realtime', 1], ['.5min', 5 * 3], ['.10min', 10 * 3]].each do |label, max_samples|
|
92
|
+
field "cpuusage#{label}" do
|
93
|
+
summary "CPU Usage in Percent"
|
94
|
+
perfmetrics %w(cpu.usage)
|
95
|
+
perfmetric_settings :max_samples => max_samples
|
96
|
+
block do |value|
|
97
|
+
if value
|
98
|
+
value = value.sum.to_f / value.length / 100
|
99
|
+
MetricNumber.new(value, '%')
|
100
|
+
else
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
[['.realtime', 1], ['.5min', 5 * 3], ['.10min', 10 * 3]].each do |label, max_samples|
|
108
|
+
field "memusage#{label}" do
|
109
|
+
summary "Mem Usage in Percent"
|
110
|
+
perfmetrics %w(mem.usage)
|
111
|
+
perfmetric_settings :max_samples => max_samples
|
112
|
+
block do |value|
|
113
|
+
if value
|
114
|
+
value = value.sum.to_f / value.length / 100
|
115
|
+
MetricNumber.new(value, '%')
|
116
|
+
else
|
117
|
+
nil
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
34
123
|
def display_info
|
124
|
+
super
|
35
125
|
summary = self.summary
|
36
126
|
runtime = summary.runtime
|
37
127
|
stats = summary.quickStats
|
@@ -28,26 +28,34 @@ class RbVmomi::VIM::VirtualMachine
|
|
28
28
|
|
29
29
|
field 'storagebw' do
|
30
30
|
summary "Storage Bandwidth"
|
31
|
-
perfmetrics %w(
|
31
|
+
perfmetrics %w(virtualDisk.read virtualDisk.write)
|
32
32
|
block do |read, write|
|
33
33
|
if read && write
|
34
|
-
|
35
|
-
|
34
|
+
read = read.select{|x| x != -1}
|
35
|
+
write = write.select{|x| x != -1}
|
36
|
+
if read.length > 0 && write.length > 0
|
37
|
+
io = (read.sum.to_f / read.length) + (write.sum.to_f / write.length)
|
38
|
+
MetricNumber.new(io * 1024, 'B/s')
|
39
|
+
end
|
36
40
|
else
|
37
41
|
nil
|
38
42
|
end
|
39
43
|
end
|
40
44
|
end
|
41
45
|
|
42
|
-
[['', 5], ['.realtime',
|
46
|
+
[['', 5], ['.realtime', 3], ['.5min', 5 * 3], ['.10min', 10 * 3]].each do |label, max_samples|
|
43
47
|
field "storageiops#{label}" do
|
44
48
|
summary "Storage IOPS"
|
45
|
-
perfmetrics %w(
|
49
|
+
perfmetrics %w(virtualDisk.numberReadAveraged virtualDisk.numberWriteAveraged)
|
46
50
|
perfmetric_settings :max_samples => max_samples
|
47
51
|
block do |read, write|
|
48
52
|
if read && write
|
49
|
-
|
50
|
-
|
53
|
+
read = read.select{|x| x != -1}
|
54
|
+
write = write.select{|x| x != -1}
|
55
|
+
if read.length > 0 && write.length > 0
|
56
|
+
io = (read.sum.to_f / read.length) + (write.sum.to_f / write.length)
|
57
|
+
MetricNumber.new(io, 'IOPS')
|
58
|
+
end
|
51
59
|
else
|
52
60
|
nil
|
53
61
|
end
|
@@ -55,6 +63,24 @@ class RbVmomi::VIM::VirtualMachine
|
|
55
63
|
end
|
56
64
|
end
|
57
65
|
|
66
|
+
['Read', 'Write'].each do |type|
|
67
|
+
[['', 5], ['.realtime', 1], ['.5min', 5 * 3], ['.10min', 10 * 3]].each do |label, max_samples|
|
68
|
+
field "storagelatency.#{type.downcase}#{label}" do
|
69
|
+
summary "Storage Latency #{type}"
|
70
|
+
perfmetrics ["virtualDisk.total#{type}Latency"]
|
71
|
+
perfmetric_settings :max_samples => max_samples
|
72
|
+
block do |latency|
|
73
|
+
if latency
|
74
|
+
io = (latency.sum.to_f / latency.length)
|
75
|
+
MetricNumber.new(io, 'ms')
|
76
|
+
else
|
77
|
+
nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
58
84
|
field 'ip' do
|
59
85
|
summary "The guest tools reported IP address."
|
60
86
|
property 'guest.ipAddress'
|
@@ -157,6 +183,10 @@ class RbVmomi::VIM::VirtualMachine
|
|
157
183
|
storage.perDatastoreUsage.map do |usage|
|
158
184
|
puts " #{usage.datastore.name}: committed=#{usage.committed.metric}B uncommitted=#{usage.uncommitted.metric}B unshared=#{usage.unshared.metric}B"
|
159
185
|
end
|
186
|
+
|
187
|
+
if runtime.dasVmProtection
|
188
|
+
puts "HA protected: #{runtime.dasVmProtection.dasProtected ? 'yes' : 'no'}"
|
189
|
+
end
|
160
190
|
end
|
161
191
|
|
162
192
|
def self.ls_properties
|
data/lib/rvc/field.rb
CHANGED
@@ -18,6 +18,8 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
+
require 'set'
|
22
|
+
|
21
23
|
module RVC
|
22
24
|
|
23
25
|
module ObjectWithFields
|
@@ -39,24 +41,69 @@ module ObjectWithFields
|
|
39
41
|
@fields[name] = RVC::Field.new(name).tap { |f| f.instance_eval &b }
|
40
42
|
end
|
41
43
|
end
|
44
|
+
|
45
|
+
def field_properties names
|
46
|
+
out = []
|
47
|
+
names.each do |name|
|
48
|
+
name = name.to_s
|
49
|
+
field = self.class.fields[name]
|
50
|
+
if field == nil
|
51
|
+
nil
|
52
|
+
elsif self.class < VIM::ManagedObject
|
53
|
+
out += field.properties
|
54
|
+
end
|
55
|
+
end
|
56
|
+
out.uniq
|
57
|
+
end
|
58
|
+
|
59
|
+
def perfmetrics names
|
60
|
+
out = []
|
61
|
+
names.each do |name|
|
62
|
+
name = name.to_s
|
63
|
+
field = self.class.fields[name]
|
64
|
+
if field == nil
|
65
|
+
nil
|
66
|
+
else
|
67
|
+
perfmetrics = field.perfmetrics
|
68
|
+
if perfmetrics.length > 0
|
69
|
+
perfopts = field.perfmetric_settings.dup
|
70
|
+
perfopts[:max_samples] ||= 5
|
71
|
+
out << {:metrics => perfmetrics, :opts => perfopts}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
out.uniq
|
76
|
+
end
|
42
77
|
|
43
|
-
def field name
|
78
|
+
def field name, props_values = {}, perf_values = {}
|
44
79
|
name = name.to_s
|
45
80
|
field = self.class.fields[name]
|
46
81
|
if field == nil
|
47
82
|
return nil
|
48
83
|
elsif self.class < VIM::ManagedObject
|
49
|
-
|
50
|
-
if
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
84
|
+
properties = field.properties
|
85
|
+
if properties.all?{|x| props_values.has_key?(x)}
|
86
|
+
props = properties.map{|x| props_values[x]}
|
87
|
+
else
|
88
|
+
*props = collect *field.properties
|
89
|
+
end
|
90
|
+
perfmetrics = field.perfmetrics
|
91
|
+
if perfmetrics.length > 0
|
92
|
+
if perfmetrics.all?{|x| perf_values.has_key?(x)}
|
93
|
+
props += perfmetrics.map do |x|
|
94
|
+
perf_values[x]
|
95
|
+
end
|
96
|
+
else
|
97
|
+
perfmgr = self._connection.serviceContent.perfManager
|
98
|
+
perfopts = field.perfmetric_settings.dup
|
99
|
+
perfopts[:max_samples] ||= 5
|
100
|
+
stats = perfmgr.retrieve_stats [self], field.perfmetrics, perfopts
|
101
|
+
props += field.perfmetrics.map do |x|
|
102
|
+
if stats[self]
|
103
|
+
stats[self][:metrics][x]
|
104
|
+
else
|
105
|
+
nil
|
106
|
+
end
|
60
107
|
end
|
61
108
|
end
|
62
109
|
end
|
data/lib/rvc/fs.rb
CHANGED
@@ -21,7 +21,7 @@
|
|
21
21
|
module RVC
|
22
22
|
|
23
23
|
class FS
|
24
|
-
attr_reader :root, :cur
|
24
|
+
attr_reader :root, :cur, :marks
|
25
25
|
|
26
26
|
MARK_PATTERN = /^~(?:([\d\w]*|~|@))$/
|
27
27
|
REGEX_PATTERN = /^%/
|
@@ -31,6 +31,7 @@ class FS
|
|
31
31
|
fail unless root.is_a? RVC::InventoryObject
|
32
32
|
@root = root
|
33
33
|
@cur = root
|
34
|
+
@marks = {}
|
34
35
|
end
|
35
36
|
|
36
37
|
def display_path
|
@@ -39,7 +40,7 @@ class FS
|
|
39
40
|
|
40
41
|
def cd dst
|
41
42
|
fail unless dst.is_a? RVC::InventoryObject
|
42
|
-
|
43
|
+
@marks['~'] = [@cur]
|
43
44
|
@cur = dst
|
44
45
|
end
|
45
46
|
|
@@ -70,7 +71,7 @@ class FS
|
|
70
71
|
# XXX shouldnt be nil
|
71
72
|
[(cur.respond_to?(:parent) && cur.parent) ? cur.parent : (cur.rvc_parent || cur)]
|
72
73
|
when MARK_PATTERN
|
73
|
-
if first and objs = $
|
74
|
+
if first and objs = @marks[$1]
|
74
75
|
objs
|
75
76
|
else
|
76
77
|
[]
|
@@ -83,7 +84,7 @@ class FS
|
|
83
84
|
cur.children.select { |k,v| k =~ regex }.map { |k,v| v.rvc_link(cur, k); v }
|
84
85
|
else
|
85
86
|
# XXX check for ambiguous child
|
86
|
-
if first and arc =~ /^\d+$/ and objs =
|
87
|
+
if first and arc =~ /^\d+$/ and objs = @marks[arc]
|
87
88
|
objs
|
88
89
|
else
|
89
90
|
if child = cur.traverse_one(arc)
|
@@ -96,6 +97,35 @@ class FS
|
|
96
97
|
end
|
97
98
|
end
|
98
99
|
|
100
|
+
def delete_numeric_marks
|
101
|
+
@marks.reject! { |k,v| k =~ /^\d+$/ }
|
102
|
+
end
|
103
|
+
|
104
|
+
# Utility methods
|
105
|
+
|
106
|
+
def lookup_single path
|
107
|
+
objs = lookup path
|
108
|
+
Util.err "Not found: #{path.inspect}" if objs.empty?
|
109
|
+
Util.err "More than one match for #{path.inspect}" if objs.size > 1
|
110
|
+
objs.first
|
111
|
+
end
|
112
|
+
|
113
|
+
def lookup! path, types
|
114
|
+
types = [types] unless types.is_a? Enumerable
|
115
|
+
lookup(path).tap do |objs|
|
116
|
+
objs.each do |obj|
|
117
|
+
Util.err "Expected #{types*'/'} but got #{obj.class} at #{path.inspect}" unless types.any? { |type| obj.is_a? type }
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def lookup_single! path, type
|
123
|
+
objs = lookup!(path, type)
|
124
|
+
Util.err "Not found: #{path.inspect}" if objs.empty?
|
125
|
+
Util.err "More than one match for #{path.inspect}" if objs.size > 1
|
126
|
+
objs.first
|
127
|
+
end
|
128
|
+
|
99
129
|
private
|
100
130
|
|
101
131
|
def glob_to_regex str
|
data/lib/rvc/inventory.rb
CHANGED
data/lib/rvc/modules/alarm.rb
CHANGED