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.
Files changed (54) hide show
  1. data/README.rdoc +1 -1
  2. data/Rakefile +2 -1
  3. data/VERSION +1 -1
  4. data/bin/rvc +53 -9
  5. data/lib/rvc/completion.rb +57 -19
  6. data/lib/rvc/extensions/ComputeResource.rb +2 -2
  7. data/lib/rvc/extensions/DVPortSetting.rb +108 -0
  8. data/lib/rvc/extensions/Datacenter.rb +19 -4
  9. data/lib/rvc/extensions/Datastore.rb +6 -1
  10. data/lib/rvc/extensions/DistributedVirtualPort.rb +146 -0
  11. data/lib/rvc/extensions/DistributedVirtualPortgroup.rb +274 -10
  12. data/lib/rvc/extensions/DistributedVirtualSwitch.rb +124 -3
  13. data/lib/rvc/extensions/Folder.rb +9 -2
  14. data/lib/rvc/extensions/HostSystem.rb +60 -0
  15. data/lib/rvc/extensions/ManagedEntity.rb +19 -0
  16. data/lib/rvc/extensions/ParaVirtualSCSIController.rb +25 -0
  17. data/lib/rvc/extensions/PerfCounterInfo.rb +26 -0
  18. data/lib/rvc/extensions/PerformanceManager.rb +83 -0
  19. data/lib/rvc/extensions/ResourcePool.rb +21 -0
  20. data/lib/rvc/extensions/VirtualDevice.rb +59 -0
  21. data/lib/rvc/extensions/VirtualDisk.rb +25 -0
  22. data/lib/rvc/extensions/VirtualEthernetCard.rb +32 -0
  23. data/lib/rvc/extensions/VirtualMachine.rb +112 -1
  24. data/lib/rvc/field.rb +122 -0
  25. data/lib/rvc/filesystem_session.rb +20 -0
  26. data/lib/rvc/inventory.rb +35 -12
  27. data/lib/rvc/known_hosts.rb +20 -0
  28. data/lib/rvc/memory_session.rb +20 -0
  29. data/lib/rvc/modules.rb +67 -7
  30. data/lib/rvc/modules/alarm.rb +37 -0
  31. data/lib/rvc/modules/basic.rb +172 -41
  32. data/lib/rvc/modules/cluster.rb +18 -2
  33. data/lib/rvc/modules/core.rb +63 -0
  34. data/lib/rvc/modules/datastore.rb +158 -0
  35. data/lib/rvc/modules/device.rb +275 -0
  36. data/lib/rvc/modules/esxcli.rb +193 -0
  37. data/lib/rvc/modules/find.rb +125 -0
  38. data/lib/rvc/modules/issue.rb +33 -0
  39. data/lib/rvc/modules/perf.rb +284 -0
  40. data/lib/rvc/modules/permissions.rb +20 -0
  41. data/lib/rvc/modules/resource_pool.rb +69 -0
  42. data/lib/rvc/modules/role.rb +23 -3
  43. data/lib/rvc/modules/snapshot.rb +20 -0
  44. data/lib/rvc/modules/vds.rb +605 -0
  45. data/lib/rvc/modules/vim.rb +103 -26
  46. data/lib/rvc/modules/vm.rb +93 -220
  47. data/lib/rvc/modules/vnc.rb +50 -13
  48. data/lib/rvc/option_parser.rb +50 -2
  49. data/lib/rvc/readline-ffi.rb +2 -1
  50. data/lib/rvc/shell.rb +34 -33
  51. data/lib/rvc/util.rb +120 -2
  52. data/test/test_fs.rb +9 -5
  53. data/test/test_metric.rb +79 -0
  54. 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
- config, = collect(:config)
24
- puts "name: #{config.name}"
25
- puts "ports: #{config.numPorts}"
26
- puts "description: #{config.description}"
27
- puts "switch: #{config.distributedVirtualSwitch.name}"
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 self.ls_properties
31
- %w(name config.distributedVirtualSwitch)
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
- def ls_text r
35
- # XXX optimize
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 self.ls_properties
34
- %w(name summary.description)
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
- " (dvs)"
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
- @soap.searchIndex.FindChild :entity => self, :name => arc
23
+ _connection.searchIndex.FindChild :entity => self, :name => arc
24
24
  end
25
25
 
26
26
  def children
27
- RVC::Util.collect_children self, :childEntity
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