rvc 1.5.0 → 1.6.0

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