rvc 1.5.0 → 1.6.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/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
@@ -19,20 +19,284 @@
|
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
21
|
class RbVmomi::VIM::DistributedVirtualPortgroup
|
22
|
+
field 'vlan' do
|
23
|
+
summary 'VLAN configuration for the portgroup'
|
24
|
+
property 'config.defaultPortConfig'
|
25
|
+
block do |config|
|
26
|
+
translate_vlan config.vlan
|
27
|
+
end
|
28
|
+
default
|
29
|
+
end
|
30
|
+
|
31
|
+
field 'vds_name' do
|
32
|
+
summary 'Parent vDS of the portgroup'
|
33
|
+
property 'config.distributedVirtualSwitch'
|
34
|
+
block { |vds| vds.config.name }
|
35
|
+
end
|
36
|
+
|
37
|
+
#field 'active ports' do
|
38
|
+
# summary 'number of active ports'
|
39
|
+
# property 'config'
|
40
|
+
# block do |config|
|
41
|
+
# vds = config.distributedVirtualSwitch
|
42
|
+
# ports = vds.FetchDVPorts(:criteria => {
|
43
|
+
# :portgroupKey => [self.key], :inside => true,
|
44
|
+
# :active => true})
|
45
|
+
# ports.size
|
46
|
+
# end
|
47
|
+
# default
|
48
|
+
#end
|
49
|
+
|
50
|
+
field 'status' do
|
51
|
+
default false
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def summarize
|
56
|
+
vds = self.config.distributedVirtualSwitch
|
57
|
+
pc = vds._connection.propertyCollector
|
58
|
+
ports = vds.FetchDVPorts(:criteria => {
|
59
|
+
:portgroupKey => [self.key], :inside => true,
|
60
|
+
:active => true})
|
61
|
+
|
62
|
+
if ports.empty?
|
63
|
+
puts "No active ports in portgroup"
|
64
|
+
return
|
65
|
+
end
|
66
|
+
|
67
|
+
objects = []
|
68
|
+
ports.each { |port|
|
69
|
+
objects << port.proxyHost
|
70
|
+
objects << port.connectee.connectedEntity
|
71
|
+
}
|
72
|
+
|
73
|
+
spec = {
|
74
|
+
:objectSet => objects.map { |obj| { :obj => obj } },
|
75
|
+
:propSet => [{:type => "ManagedEntity", :pathSet => %w(name) }]
|
76
|
+
}
|
77
|
+
|
78
|
+
props = pc.RetrieveProperties(:specSet => [spec])
|
79
|
+
t = table(['key', 'name', 'vlan', 'blocked', 'host', 'connectee'])
|
80
|
+
data = []
|
81
|
+
|
82
|
+
names = {}
|
83
|
+
props.each { |prop| names[prop.obj] = prop['name'] }
|
84
|
+
ports.each { |port|
|
85
|
+
port_key = begin port.key.to_i; rescue port.key; end
|
86
|
+
# XXX map resource pools, vlan config properly
|
87
|
+
data << [port_key, port.config.name,
|
88
|
+
#puts [port_key, port.config.name,
|
89
|
+
translate_vlan(port.config.setting.vlan),
|
90
|
+
port.state.runtimeInfo.blocked,
|
91
|
+
names[port.proxyHost],
|
92
|
+
#port.config.setting.networkResourcePoolKey.value,
|
93
|
+
"#{names[port.connectee.connectedEntity]}"]
|
94
|
+
}
|
95
|
+
data.sort { |x,y| x[0] <=> y[0] }.each { |row| t << row }
|
96
|
+
puts t
|
97
|
+
end
|
98
|
+
|
22
99
|
def display_info
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
100
|
+
vds = self.config.distributedVirtualSwitch
|
101
|
+
self.config.defaultPortConfig.dump_config vds, ""
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
def self.folder?
|
106
|
+
true
|
107
|
+
end
|
108
|
+
|
109
|
+
def children
|
110
|
+
vds = self.config.distributedVirtualSwitch
|
111
|
+
|
112
|
+
ports = vds.FetchDVPorts(:criteria => {:portgroupKey => [self.key],
|
113
|
+
:inside => true, :active => true})
|
114
|
+
children = {}
|
115
|
+
begin
|
116
|
+
# try to sort port keys in numeric order
|
117
|
+
keys = ports.map {|port| [port.key.to_i, port]}.sort {|x,y| x[0] <=> y[0]}
|
118
|
+
rescue
|
119
|
+
keys = ports.map { |port| port.key }
|
120
|
+
end
|
121
|
+
keys.each { |i| children["port-#{i[0]}"] = i[1] }
|
122
|
+
children['all'] = RVC::FakeFolder.new(self, :get_all_ports)
|
123
|
+
|
124
|
+
children
|
28
125
|
end
|
29
126
|
|
30
|
-
def
|
31
|
-
|
127
|
+
def traverse_one arc
|
128
|
+
if arc == 'all'
|
129
|
+
RVC::FakeFolder.new(self, :get_all_ports)
|
130
|
+
else
|
131
|
+
port_num = arc.gsub(/^port-/, '').to_i
|
132
|
+
vds = self.config.distributedVirtualSwitch
|
133
|
+
ports = vds.FetchDVPorts(:criteria => {:portKey => [port_num.to_s]})
|
134
|
+
return ports[0]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def rvc_ls
|
139
|
+
children = self.children
|
140
|
+
name_map = children.invert
|
141
|
+
children, fake_children = children.partition { |k,v| v.is_a? VIM::ManagedEntity }
|
142
|
+
i = 0
|
143
|
+
|
144
|
+
pc = self.config.distributedVirtualSwitch._connection.propertyCollector
|
145
|
+
|
146
|
+
objects = []
|
147
|
+
fake_children.each do |name, port|
|
148
|
+
if port.respond_to?(:connectee)
|
149
|
+
objects << port.connectee.connectedEntity
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
if objects.any? { |x| x.is_a? VIM::VirtualMachine }
|
154
|
+
spec = {
|
155
|
+
:objectSet => objects.map { |obj| { :obj => obj } },
|
156
|
+
:propSet => [{:type => "VirtualMachine",
|
157
|
+
:pathSet => %w(guest.net config.hardware.device name)}]
|
158
|
+
}
|
159
|
+
|
160
|
+
prop_sets = pc.RetrieveProperties(:specSet => [spec])
|
161
|
+
else
|
162
|
+
prop_sets = []
|
163
|
+
end
|
164
|
+
|
165
|
+
#pp prop_sets
|
166
|
+
|
167
|
+
ips = {}
|
168
|
+
macs = {}
|
169
|
+
device_macs = {}
|
170
|
+
names = {}
|
171
|
+
prop_sets.each do |prop_set|
|
172
|
+
prop_set.propSet.each do |prop|
|
173
|
+
if prop.name == "guest.net"
|
174
|
+
prop.val.each do |nicinfo|
|
175
|
+
#XXX nicinfo.ipConfig has more info and IPv6
|
176
|
+
ips[prop_set.obj.to_s +
|
177
|
+
nicinfo.deviceConfigId.to_s] = nicinfo.ipAddress
|
178
|
+
macs[prop_set.obj.to_s +
|
179
|
+
nicinfo.deviceConfigId.to_s] = nicinfo.macAddress
|
180
|
+
end
|
181
|
+
elsif prop.name == "config.hardware.device"
|
182
|
+
prop.val.each do |device|
|
183
|
+
if device.class < VIM::VirtualEthernetCard
|
184
|
+
device_macs[prop_set.obj.to_s +
|
185
|
+
device.key.to_s] = device.macAddress
|
186
|
+
end
|
187
|
+
end
|
188
|
+
elsif prop.name == "name"
|
189
|
+
names[prop_set.obj] = prop.val
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
#pp ip
|
194
|
+
#pp mac
|
195
|
+
#pp device_mac
|
196
|
+
|
197
|
+
fake_children.each do |name,child|
|
198
|
+
print "#{i} #{name}"
|
199
|
+
if child.class.folder?
|
200
|
+
print "/"
|
201
|
+
end
|
202
|
+
if child.respond_to?(:connectee)
|
203
|
+
vm_name = names[child.connectee.connectedEntity]
|
204
|
+
mac = macs[child.connectee.connectedEntity.to_s +
|
205
|
+
child.connectee.nicKey]
|
206
|
+
ip = ips[child.connectee.connectedEntity.to_s + child.connectee.nicKey]
|
207
|
+
device_mac = device_macs[child.connectee.connectedEntity.to_s +
|
208
|
+
child.connectee.nicKey]
|
209
|
+
if mac and ip
|
210
|
+
puts " (#{mac} #{ip} #{vm_name})"
|
211
|
+
elsif device_mac
|
212
|
+
puts " (#{device_mac} #{vm_name})"
|
213
|
+
else
|
214
|
+
puts ""
|
215
|
+
end
|
216
|
+
else
|
217
|
+
puts ""
|
218
|
+
end
|
219
|
+
child.rvc_link self, name
|
220
|
+
CMD.mark.mark i.to_s, [child]
|
221
|
+
i += 1
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def get_all_ports
|
226
|
+
hash = {}
|
227
|
+
vds = self.config.distributedVirtualSwitch
|
228
|
+
begin
|
229
|
+
keys = self.portKeys.map { |key| key.to_i }.sort
|
230
|
+
rescue
|
231
|
+
keys = self.portKeys
|
232
|
+
end
|
233
|
+
keys.each { |key| hash["port-#{key}"] = LazyDVPort.new(self, key) }
|
234
|
+
hash
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
#XXX can we use a lazy delegate but not fetch the object during `ls`?
|
239
|
+
class LazyDVPort
|
240
|
+
include RVC::InventoryObject
|
241
|
+
|
242
|
+
def initialize(pg, key)
|
243
|
+
@pg = pg
|
244
|
+
@key = key
|
245
|
+
end
|
246
|
+
|
247
|
+
def get_real_port
|
248
|
+
@port ||= @pg.config.distributedVirtualSwitch.FetchDVPorts(:criteria => {:portKey => [@key]})[0]
|
249
|
+
end
|
250
|
+
|
251
|
+
def display_info
|
252
|
+
self.get_real_port.display_info
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def translate_vlan vlan
|
257
|
+
case "#{vlan.class}"
|
258
|
+
when "VmwareDistributedVirtualSwitchVlanIdSpec"
|
259
|
+
config = vlan.vlanId == 0 ? "-" : vlan.vlanId.to_s + " (tagging)"
|
260
|
+
when "VmwareDistributedVirtualSwitchTrunkVlanSpec"
|
261
|
+
config = vlan.vlanId.map { |r|
|
262
|
+
if r.start != r.end
|
263
|
+
"#{r.start}-#{r.end}"
|
264
|
+
else
|
265
|
+
"#{r.start}"
|
266
|
+
end
|
267
|
+
}.join(',') + " (trunked)"
|
268
|
+
when "Array"
|
269
|
+
config = vlan.map { |r|
|
270
|
+
if r.start != r.end
|
271
|
+
"#{r.start}-#{r.end}"
|
272
|
+
else
|
273
|
+
"#{r.start}"
|
274
|
+
end
|
275
|
+
}.join(',')
|
276
|
+
if config == "0"
|
277
|
+
config = "-"
|
278
|
+
else
|
279
|
+
config += " (trunked)"
|
280
|
+
end
|
281
|
+
when "VmwareDistributedVirtualSwitchPvlanSpec"
|
282
|
+
# XXX needs to be mapped
|
283
|
+
config = vlan.pvlanId.to_s + " (pvlan?)"
|
284
|
+
end
|
285
|
+
|
286
|
+
config
|
287
|
+
end
|
288
|
+
|
289
|
+
def translate_respool vds, pk, show_inheritance = true
|
290
|
+
if pk.value == '-1'
|
291
|
+
poolName = "-"
|
292
|
+
else
|
293
|
+
poolName = vds.networkResourcePool.find_all { |pool|
|
294
|
+
pk.value == pool.key
|
295
|
+
}[0].name
|
32
296
|
end
|
33
297
|
|
34
|
-
|
35
|
-
|
36
|
-
" (dvpg): <#{r['config.distributedVirtualSwitch'].name}"
|
298
|
+
if show_inheritance and !pk.inherited
|
299
|
+
poolName += "*"
|
37
300
|
end
|
301
|
+
poolName
|
38
302
|
end
|
@@ -19,6 +19,68 @@
|
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
21
|
class RbVmomi::VIM::DistributedVirtualSwitch
|
22
|
+
field 'type' do
|
23
|
+
summary 'Type of the object'
|
24
|
+
block do
|
25
|
+
['vds']
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
field 'hosts' do
|
30
|
+
summary 'Host members of the vDS'
|
31
|
+
property 'config'
|
32
|
+
block do |config|
|
33
|
+
hostnames = config.host.map { |host| host.config.host.name }
|
34
|
+
size = hostnames.size
|
35
|
+
if size > 10
|
36
|
+
hostnames = hostnames[0..10]
|
37
|
+
size -= 10
|
38
|
+
hostnames << "(and #{size} more...)"
|
39
|
+
end
|
40
|
+
hostnames.join "\n"
|
41
|
+
end
|
42
|
+
default
|
43
|
+
end
|
44
|
+
|
45
|
+
field 'vlans' do
|
46
|
+
summary 'VLANs in use by the vDS'
|
47
|
+
property 'portgroup'
|
48
|
+
block do |portgroups|
|
49
|
+
trunk_ranges = []
|
50
|
+
tag_ranges = []
|
51
|
+
portgroups.each do |pg|
|
52
|
+
vlan = pg.config.defaultPortConfig.vlan
|
53
|
+
if vlan.class == VIM::VmwareDistributedVirtualSwitchVlanIdSpec
|
54
|
+
if vlan.vlanId != 0
|
55
|
+
tag_ranges << Range.new(vlan.vlanId,vlan.vlanId)
|
56
|
+
end
|
57
|
+
elsif vlan.class == VIM::VmwareDistributedVirtualSwitchTrunkVlanSpec
|
58
|
+
vlan.vlanId.each { |range| trunk_ranges << Range.new(range.start,range.end) }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
trunks = RVC::MODULES['vds'].merge_ranges(trunk_ranges).map { |r|
|
62
|
+
if r.begin == r.end then "#{r.begin}" else "#{r.begin}-#{r.end}" end
|
63
|
+
}.join ','
|
64
|
+
|
65
|
+
tags = RVC::MODULES['vds'].merge_ranges(tag_ranges).map { |r|
|
66
|
+
if r.begin == r.end then "#{r.begin}" else "#{r.begin}-#{r.end}" end
|
67
|
+
}.join ','
|
68
|
+
str = ""
|
69
|
+
if !trunk_ranges.empty?
|
70
|
+
str += "#{trunks} (trunked)"
|
71
|
+
end
|
72
|
+
if !tag_ranges.empty?
|
73
|
+
str += "\n#{tags} (switch tagged)\n"
|
74
|
+
end
|
75
|
+
str
|
76
|
+
end
|
77
|
+
default
|
78
|
+
end
|
79
|
+
|
80
|
+
field 'status' do
|
81
|
+
default false
|
82
|
+
end
|
83
|
+
|
22
84
|
def display_info
|
23
85
|
config, = collect(:config)
|
24
86
|
puts "name: #{config.name}"
|
@@ -28,13 +90,72 @@ class RbVmomi::VIM::DistributedVirtualSwitch
|
|
28
90
|
puts "standalone ports: #{config.numStandalonePorts}"
|
29
91
|
puts "maximum ports: #{config.maxPorts}"
|
30
92
|
puts "netIORM: #{config.networkResourceManagementEnabled}"
|
93
|
+
puts "Default Port Configuration:"
|
94
|
+
config.defaultPortConfig.dump_config self, " ", false
|
95
|
+
end
|
96
|
+
|
97
|
+
def summarize
|
98
|
+
t = table(['portgroup name', 'num ports', 'vlan', 'resource pool'])
|
99
|
+
self.portgroup.each { |pg|
|
100
|
+
if pg.config.defaultPortConfig
|
101
|
+
respool = translate_respool self, pg.config.defaultPortConfig.networkResourcePoolKey
|
102
|
+
vlan = pg.config.defaultPortConfig.vlan
|
103
|
+
end
|
104
|
+
|
105
|
+
if pg.config.defaultPortConfig
|
106
|
+
t << [pg.config.name, pg.config.numPorts, translate_vlan(vlan), respool]
|
107
|
+
else
|
108
|
+
t << [pg.config.name, pg.config.numPorts, nil, nil]
|
109
|
+
end
|
110
|
+
}
|
111
|
+
puts t
|
112
|
+
end
|
113
|
+
|
114
|
+
def portgroup_children
|
115
|
+
portgroups = {}
|
116
|
+
self.portgroup.each { |pg|
|
117
|
+
portgroups[pg.name] = pg
|
118
|
+
}
|
119
|
+
portgroups
|
120
|
+
end
|
121
|
+
|
122
|
+
def respool_children
|
123
|
+
respools = {}
|
124
|
+
self.networkResourcePool.each do |pool|
|
125
|
+
respools[pool.name] = pool
|
126
|
+
end
|
127
|
+
|
128
|
+
respools
|
31
129
|
end
|
32
130
|
|
33
|
-
def
|
34
|
-
|
131
|
+
def hosts_children
|
132
|
+
hosts = {}
|
133
|
+
self.config.host.each do |hostinfo|
|
134
|
+
host = hostinfo.config.host
|
135
|
+
hosts[host.collect(:name).first] = host
|
136
|
+
end
|
137
|
+
hosts
|
138
|
+
end
|
139
|
+
|
140
|
+
def children
|
141
|
+
portgroups = RVC::FakeFolder.new(self, :portgroup_children)
|
142
|
+
portgroups.define_singleton_method :display_info, lambda {
|
143
|
+
vds = self.rvc_parent
|
144
|
+
RVC::MODULES['basic'].table vds.portgroup, {}
|
145
|
+
}
|
146
|
+
|
147
|
+
{
|
148
|
+
'portgroups' => portgroups,
|
149
|
+
'respools' => RVC::FakeFolder.new(self, :respool_children),
|
150
|
+
'hosts' => RVC::FakeFolder.new(self, :hosts_children),
|
151
|
+
}
|
35
152
|
end
|
36
153
|
|
37
154
|
def ls_text r
|
38
|
-
" (
|
155
|
+
" (vds)"
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.folder?
|
159
|
+
true
|
39
160
|
end
|
40
161
|
end
|
@@ -20,14 +20,21 @@
|
|
20
20
|
|
21
21
|
class RbVmomi::VIM::Folder
|
22
22
|
def traverse_one arc
|
23
|
-
|
23
|
+
_connection.searchIndex.FindChild :entity => self, :name => arc
|
24
24
|
end
|
25
25
|
|
26
26
|
def children
|
27
|
-
RVC::Util.collect_children
|
27
|
+
RVC::Util.collect_children(self, :childEntity).reject { |name, item|
|
28
|
+
# hack -- we want to display dvportgroups under the dvs folder
|
29
|
+
item.class == RbVmomi::VIM::DistributedVirtualPortgroup
|
30
|
+
}
|
28
31
|
end
|
29
32
|
|
30
33
|
def self.folder?
|
31
34
|
true
|
32
35
|
end
|
36
|
+
|
37
|
+
def self.traverse?
|
38
|
+
true
|
39
|
+
end
|
33
40
|
end
|