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
@@ -1,3 +1,23 @@
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
+
1
21
  opts :get do
2
22
  summary "Display the permissions of a managed entity"
3
23
  arg :obj, nil, :lookup => VIM::ManagedEntity, :multi => true
@@ -93,3 +93,72 @@ def update pool, opts
93
93
  }
94
94
  pool.UpdateConfig(:name => opts[:name], :spec => spec)
95
95
  end
96
+
97
+
98
+ opts :storage do
99
+ summary "Show the storage used by a resource pool hierarchy"
100
+ arg :pool, nil, :lookup => VIM::ResourcePool
101
+ end
102
+
103
+ def storage root
104
+ propSet = [
105
+ { :type => 'ResourcePool', :pathSet => ['name', 'parent'] },
106
+ { :type => 'VirtualMachine', :pathSet => ['name', 'parent', 'storage', 'resourcePool'] }
107
+ ]
108
+
109
+ filterSpec = RbVmomi::VIM.PropertyFilterSpec(
110
+ :objectSet => [
111
+ :obj => root,
112
+ :selectSet => [
113
+ RbVmomi::VIM.TraversalSpec(
114
+ :name => 'tsResourcePool1',
115
+ :type => 'ResourcePool',
116
+ :path => 'resourcePool',
117
+ :skip => false,
118
+ :selectSet => [
119
+ RbVmomi::VIM.SelectionSpec(:name => 'tsResourcePool1'),
120
+ RbVmomi::VIM.SelectionSpec(:name => 'tsResourcePool2')
121
+ ]
122
+ ),
123
+ RbVmomi::VIM.TraversalSpec(
124
+ :name => 'tsResourcePool2',
125
+ :type => 'ResourcePool',
126
+ :path => 'vm',
127
+ :skip => false,
128
+ :selectSet => [
129
+ RbVmomi::VIM.SelectionSpec(:name => 'tsResourcePool1'),
130
+ RbVmomi::VIM.SelectionSpec(:name => 'tsResourcePool2')
131
+ ]
132
+ )
133
+ ]
134
+ ],
135
+ :propSet => propSet
136
+ )
137
+
138
+ result = root._connection.propertyCollector.RetrieveProperties(:specSet => [filterSpec])
139
+
140
+ objs = Hash[result.map { |r| [r.obj, r] }]
141
+ usages = Hash.new { |h,k| h[k] = 0 }
142
+
143
+ objs.each do |obj,r|
144
+ next unless obj.is_a? VIM::VirtualMachine
145
+ cur = r['resourcePool']
146
+ usage = r['storage'].perDatastoreUsage.map(&:unshared).sum
147
+ while cur
148
+ usages[cur] += usage
149
+ cur = cur == root ? nil : objs[cur]['parent']
150
+ end
151
+ end
152
+
153
+ children = Hash.new { |h,k| h[k] = [] }
154
+ objs.each { |obj,r| children[r['parent']] << obj }
155
+
156
+ display = lambda do |level,obj|
157
+ puts "#{' '*level}#{objs[obj]['name']}: #{usages[obj].metric}B"
158
+ children[obj].each do |child|
159
+ display[level+1, child]
160
+ end
161
+ end
162
+
163
+ display[0, root]
164
+ end
@@ -1,3 +1,23 @@
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
+
1
21
  def cur_auth_mgr
2
22
  conn = $shell.fs.cur._connection
3
23
  conn.serviceContent.authorizationManager
@@ -21,7 +41,7 @@ end
21
41
 
22
42
  def get name
23
43
  role = cur_auth_mgr.roleList.find { |x| x.name == name }
24
- err "no such role #{role_name.inspect}" unless role
44
+ err "no such role #{name.inspect}" unless role
25
45
  puts "label: #{role.info.label}"
26
46
  puts "summary: #{role.info.summary}"
27
47
  puts "privileges: #{role.privilege.sort * ' '}"
@@ -35,7 +55,7 @@ end
35
55
 
36
56
  def permissions name
37
57
  role = cur_auth_mgr.roleList.find { |x| x.name == name }
38
- err "no such role #{role_name.inspect}" unless role
58
+ err "no such role #{name.inspect}" unless role
39
59
  cur_auth_mgr.RetrieveRolePermissions(:roleId => role.roleId).each do |perm|
40
60
  flags = []
41
61
  flags << 'group' if perm[:group]
@@ -64,7 +84,7 @@ end
64
84
 
65
85
  def delete name, opts
66
86
  role = cur_auth_mgr.roleList.find { |x| x.name == name }
67
- err "no such role #{role_name.inspect}" unless role
87
+ err "no such role #{name.inspect}" unless role
68
88
  cur_auth_mgr.RemoveAuthorizationRole :roleId => role.roleId, :failIfUsed => opts[:force]
69
89
  end
70
90
 
@@ -1,3 +1,23 @@
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
+
1
21
  opts :create do
2
22
  summary "Snapshot a VM"
3
23
  arg :vm, nil, :lookup => VIM::VirtualMachine
@@ -0,0 +1,605 @@
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
+ require "terminal-table/import"
22
+
23
+ opts :summarize do
24
+ summary ""
25
+ arg :obj, nil, :multi => false, :lookup => VIM::ManagedObject
26
+ end
27
+
28
+ def summarize obj
29
+ if !obj.respond_to?(:summarize)
30
+ puts "not a vds or portgroup!"
31
+ return
32
+ end
33
+ obj.summarize
34
+ end
35
+
36
+ opts :create_portgroup do
37
+ summary "Create a new portgroup on a vDS"
38
+ arg :vds, nil, :lookup => VIM::DistributedVirtualSwitch
39
+ arg :name, "Portgroup Name", :type => :string
40
+ opt :num_ports, "Number of Ports", :type => :int, :default => 128
41
+ opt :type, "Portgroup Type (i.e. 'earlyBinding', 'ephemeral', 'lateBinding'",
42
+ :type => :string, :default => 'earlyBinding'
43
+ end
44
+
45
+ def create_portgroup vds, name, opts
46
+ tasks [vds], :AddDVPortgroup, :spec => [{ :name => name,
47
+ :type => opts[:type],
48
+ :numPorts => opts[:num_ports] }]
49
+ end
50
+
51
+ opts :create_vds do
52
+ summary "Create a new vDS"
53
+ arg :dest, "Destination", :lookup_parent => VIM::Folder
54
+ opt :vds_version, "vDS version (i.e. '5.0.0', '4.1.0', '4.0.0')",
55
+ :type => :string
56
+ end
57
+
58
+ def create_vds dest, opts
59
+ folder, name = *dest
60
+ tasks [folder], :CreateDVS, :spec => { :configSpec => { :name => name },
61
+ :productInfo => {
62
+ :version => opts[:vds_version] } }
63
+ end
64
+
65
+ def get_inherited_config obj
66
+ if obj.is_a?(VIM::DistributedVirtualSwitch)
67
+ nil
68
+ elsif obj.is_a?(VIM::DistributedVirtualPortgroup)
69
+ obj.config.distributedVirtualSwitch.config.defaultPortConfig
70
+ elsif obj.is_a?(VIM::DistributedVirtualPort)
71
+ obj.rvc_parent.config.defaultPortConfig
72
+ end
73
+ end
74
+
75
+ def apply_settings obj, port_spec
76
+ if obj.is_a?(VIM::DistributedVirtualSwitch)
77
+ tasks [obj], :ReconfigureDvs, :spec =>{:defaultPortConfig => port_spec,
78
+ :configVersion => obj.config.configVersion}
79
+ elsif obj.is_a?(VIM::DistributedVirtualPortgroup)
80
+ vds = obj.config.distributedVirtualSwitch
81
+ collapse_inheritance vds.config.defaultPortConfig, port_spec
82
+ tasks [obj], :ReconfigureDVPortgroup,
83
+ :spec => { :defaultPortConfig => port_spec,
84
+ :configVersion => obj.config.configVersion}
85
+ elsif obj.is_a?(VIM::DistributedVirtualPort)
86
+ config = obj.rvc_parent.config
87
+ vds = config.distributedVirtualSwitch
88
+ collapse_inheritance config.defaultPortConfig, port_spec
89
+ tasks [vds], :ReconfigureDVPort, :port => [{ :key => obj.key,
90
+ :operation => 'edit',
91
+ :setting => port_spec }]
92
+ obj.invalidate vds
93
+ end
94
+ end
95
+
96
+
97
+ def collapse_inheritance default_spec, port_spec
98
+ inherited = true
99
+ if port_spec.is_a? Hash
100
+ port_spec.keys.each do |key|
101
+ if key == :inherited then next end
102
+ default_child = default_spec.send key
103
+ child = port_spec[key]
104
+ child_inheritance = collapse_inheritance default_child, child
105
+ inherited = inherited && child_inheritance
106
+ end
107
+ if port_spec.has_key?(:inherited)
108
+ port_spec[:inherited] = inherited
109
+ end
110
+ inherited
111
+ else
112
+ if default_spec == port_spec
113
+ true
114
+ else
115
+ false
116
+ end
117
+ end
118
+ end
119
+
120
+
121
+ opts :shaper do
122
+ summary "Configure a traffic shaping on a vDS or portgroup"
123
+ arg :obj, nil,
124
+ :lookup => [VIM::DistributedVirtualPort,
125
+ VIM::DistributedVirtualPortgroup,
126
+ VIM::DistributedVirtualSwitch]
127
+ opt :tx, "Apply Settings for Tx Shaping", :type => :bool
128
+ opt :rx, "Apply Settings for Rx Shaping", :type => :bool
129
+ opt :enable, "Enable Traffic Shaping", :type => :bool
130
+ opt :disable, "Disable Traffic Shaping", :type => :bool
131
+ opt :average_bw, "Average Bandwith in kilobits per second", :type => :int
132
+ opt :burst_size, "Maximum burst size allowed in kilobytes", :type => :int
133
+ opt :peak_bw, "Peak bandwidth during bursts in kilobits per second", :type => :int
134
+ end
135
+
136
+ def shaper obj, opts
137
+ if !(opts[:tx] or opts[:rx]) or (opts[:tx] and opts[:rx])
138
+ puts "Need to configure either Rx or Tx Shaping!"
139
+ return
140
+ end
141
+
142
+ if opts[:enable] and opts[:disable]
143
+ puts "Can't both enable and disable traffic shaping!"
144
+ return
145
+ end
146
+
147
+ shaper_spec = { :inherited => false}
148
+ if opts[:enable]
149
+ shaper_spec[:enabled] = { :value => true, :inherited => false }
150
+ end
151
+ if opts[:disable]
152
+ shaper_spec[:enabled] = { :value => false, :inherited => false }
153
+ end
154
+
155
+ if opts[:average_bw]
156
+ shaper_spec[:averageBandwidth] = { :value => (opts[:average_bw] * 1000),
157
+ :inherited => false }
158
+ end
159
+
160
+ if opts[:burst_size]
161
+ shaper_spec[:burstSize] = { :value => (opts[:burst_size] * 1000),
162
+ :inherited => false }
163
+ end
164
+
165
+ if opts[:peak_bw]
166
+ shaper_spec[:peakBandwidth] = { :value => (opts[:peak_bw] * 1000),
167
+ :inherited => false }
168
+ end
169
+
170
+ if opts[:rx]
171
+ port_spec = { :inShapingPolicy => shaper_spec }
172
+ else
173
+ port_spec = { :outShapingPolicy => shaper_spec }
174
+ end
175
+
176
+ apply_settings obj, port_spec
177
+ end
178
+
179
+ opts :block do
180
+ summary "Block traffic on a vDS, portgroup, or port"
181
+ arg :obj, nil,
182
+ :lookup => [VIM::DistributedVirtualPort,
183
+ VIM::DistributedVirtualPortgroup,
184
+ VIM::DistributedVirtualSwitch]
185
+ end
186
+
187
+ def block obj
188
+ apply_settings obj, { :blocked => { :value => true, :inherited => false } }
189
+ end
190
+
191
+ rvc_alias :block, :shut
192
+
193
+ opts :unblock do
194
+ summary "Unblock traffic on a vDS, portgroup, or port"
195
+ arg :obj, nil,
196
+ :lookup => [VIM::DistributedVirtualPort,
197
+ VIM::DistributedVirtualPortgroup,
198
+ VIM::DistributedVirtualSwitch]
199
+ end
200
+
201
+ def unblock obj
202
+ apply_settings obj, { :blocked => { :value => false, :inherited => false } }
203
+ end
204
+
205
+ rvc_alias :unblock, :"no-shut"
206
+
207
+ # XXX pvlan?
208
+ opts :vlan_trunk do
209
+ summary "Configure a VLAN range on a vDS or portgroup to be trunked"
210
+ arg :obj, nil,
211
+ :lookup => [VIM::DistributedVirtualPort,
212
+ VIM::DistributedVirtualPortgroup,
213
+ VIM::DistributedVirtualSwitch]
214
+ arg :vlan, "VLAN Configuration (i.e. '1000-2000', '2012', '2012,3013', '1000-2000,2012')", :type => :string
215
+ opt :append, "Append new VLAN settings to configuration, rather than replacing the existing settings", :type => :bool
216
+ opt :exclude, "Remove a specific range of VLAN settings from configuration. ", :type => :bool
217
+ end
218
+
219
+ def vlan_trunk obj, vlan, opts
220
+ ranges = []
221
+ vlan.sub(' ', '').split(',').each do |range_str|
222
+ range_val = range_str.split('-')
223
+ ranges << Range.new(range_val[0].to_i,
224
+ if range_val.length > 1
225
+ range_val[1].to_i
226
+ else
227
+ range_val[0].to_i
228
+ end)
229
+ end
230
+
231
+ if opts[:append] or opts[:exclude]
232
+ old_vlan = obj.config.defaultPortConfig.vlan
233
+ if old_vlan.class == VIM::VmwareDistributedVirtualSwitchVlanIdSpec
234
+ puts "Can't append/exclude trunk range to switch tagging configuration!"
235
+ return
236
+ elsif old_vlan.class == VIM::VmwareDistributedVirtualSwitchTrunkVlanSpec
237
+ old_vlan = old_vlan.vlanId.map { |r| r.start..r.end }
238
+ end
239
+ old_vlan = merge_ranges(old_vlan)
240
+ end
241
+
242
+ if opts[:append]
243
+ ranges = ranges + old_vlan
244
+ end
245
+
246
+ ranges = merge_ranges(ranges)
247
+
248
+ if opts[:exclude]
249
+ ranges = subtract_ranges(old_vlan, ranges)
250
+ ranges = merge_ranges(ranges)
251
+ end
252
+
253
+ spec = VIM::VMwareDVSPortSetting.new()
254
+ spec.vlan = VIM::VmwareDistributedVirtualSwitchTrunkVlanSpec.new()
255
+ spec.vlan.vlanId = ranges.map { |r| { :start => r.first, :end => r.last } }
256
+ spec.vlan.inherited = false
257
+
258
+ if ranges.empty?
259
+ # if we excluded all ranges, just allow everything
260
+ vlan_switchtag obj, 0
261
+ return
262
+ end
263
+
264
+ inherited_spec = get_inherited_config(obj)
265
+ if inherited_spec != nil then inherited_spec = inherited_spec.vlan end
266
+
267
+ if inherited_spec.class == VIM::VmwareDistributedVirtualSwitchTrunkVlanSpec
268
+ inherited_ranges = inherited.vlanId.map { |range| range.start..range.end }
269
+ if (merge_ranges(inherited_ranges) - ranges) == []
270
+ spec.vlan.inherited = true
271
+ end
272
+ end
273
+
274
+ apply_settings obj, spec
275
+ end
276
+
277
+ opts :vlan_switchtag do
278
+ summary "Configure a VLAN on a vDS or portgroup for vSwitch tagging"
279
+ arg :obj, nil,
280
+ :lookup => [VIM::DistributedVirtualPort,
281
+ VIM::DistributedVirtualPortgroup,
282
+ VIM::DistributedVirtualSwitch]
283
+ arg :vlan, "VLAN id", :type => :int
284
+ end
285
+
286
+ def vlan_switchtag obj, vlan
287
+ # if it matches, inherit settings from switch or portgroup
288
+ inherited = false
289
+ inherited_spec = get_inherited_config(obj)
290
+ if inherited_spec != nil then inherited_spec = inherited_spec.vlan end
291
+
292
+ if inherited_spec.class == VIM::VmwareDistributedVirtualSwitchVlanIdSpec
293
+ if inherited_spec.vlanId.to_s == vlan.to_s
294
+ inherited = true
295
+ end
296
+ end
297
+
298
+ spec = VIM::VMwareDVSPortSetting.new()
299
+ spec.vlan = VIM::VmwareDistributedVirtualSwitchVlanIdSpec.new()
300
+ spec.vlan.vlanId = vlan
301
+ spec.vlan.inherited = inherited
302
+ apply_settings obj, spec
303
+ end
304
+
305
+ def merge_ranges(ranges)
306
+ ranges = ranges.sort_by {|r| r.first }
307
+ if !ranges.empty?
308
+ *outages = ranges.shift
309
+ else
310
+ outages = []
311
+ end
312
+ ranges.each do |r|
313
+ lastr = outages[-1]
314
+ if lastr.last >= r.first - 1
315
+ outages[-1] = lastr.first..[r.last, lastr.last].max
316
+ else
317
+ outages.push(r)
318
+ end
319
+ end
320
+ outages
321
+ end
322
+
323
+
324
+ def subtract_ranges(ranges, minus_ranges)
325
+ outages = []
326
+ minus_range = minus_ranges.shift
327
+ ranges.each do |r|
328
+ while true
329
+ if minus_range == nil or (minus_range.first > r.last)
330
+ break
331
+ elsif minus_range.first < r.first and minus_range.last < r.first
332
+ next
333
+ elsif minus_range.first <= r.first and minus_range.last < r.last
334
+ r = ((minus_range.last+1)..r.last)
335
+ minus_range = minus_ranges.shift
336
+ next
337
+ elsif minus_range.first > r.first and minus_range.last >= r.last
338
+ r = (r.first..(minus_range.first-1))
339
+ break
340
+ elsif minus_range.first > r.first and minus_range.last < r.last
341
+ outages << (r.first..(minus_range.first-1))
342
+ r = ((minus_range.last+1)..r.last)
343
+ minus_range = minus_ranges.shift
344
+ break
345
+ elsif minus_range.first <= r.first and minus_range.last >= r.last
346
+ if minus_range.last == r.last
347
+ minus_range = minus_ranges.shift
348
+ end
349
+ r = nil
350
+ break
351
+ end
352
+ end
353
+ if r != nil
354
+ outages << r
355
+ end
356
+ end
357
+ outages
358
+ end
359
+
360
+ opts :security do
361
+ summary "Configure a security settings on a vDS or portgroup"
362
+ arg :obj, nil,
363
+ :lookup => [VIM::DistributedVirtualPort,
364
+ VIM::DistributedVirtualPortgroup,
365
+ VIM::DistributedVirtualSwitch]
366
+ opt :allow_promisc, "Allow VMs to enter promiscuous mode", :type => :bool
367
+ opt :deny_promisc, "Prevent VMs from entering promiscuous mode", :type => :bool
368
+ opt :allow_mac_changes, "Allow VMs to change their MAC addresses from within the Guest OS.", :type => :bool
369
+ opt :deny_mac_changes, "Prevent VMs from changing their MAC addresses from within the Guest OS.", :type => :bool
370
+ opt :allow_forged, "Allow VMs to transmit packets originating from other MAC addresses", :type => :bool
371
+ opt :deny_forged, "Prevent VMs from transmitting packets originating from other MAC addresses", :type => :bool
372
+ end
373
+
374
+ def security obj, opts
375
+ if (opts[:allow_promisc] and opts[:deny_promisc]) or
376
+ (opts[:allow_mac_changes] and opts[:deny_mac_changes]) or
377
+ (opts[:allow_forged] and opts[:deny_forged])
378
+ puts "Can't both allow and deny!"
379
+ return
380
+ end
381
+
382
+ policy = { :inherited => false }
383
+ if opts[:allow_promisc]
384
+ policy[:allowPromiscuous] = { :inherited => false, :value => true }
385
+ elsif opts[:deny_promisc]
386
+ policy[:allowPromiscuous] = { :inherited => false, :value => false }
387
+ end
388
+
389
+ if opts[:allow_mac_changes]
390
+ policy[:macChanges] = { :inherited => false, :value => true }
391
+ elsif opts[:deny_mac_changes]
392
+ policy[:macChanges] = { :inherited => false, :value => false }
393
+ end
394
+
395
+ if opts[:allow_forged]
396
+ policy[:forgedTransmits] = { :inherited => false, :value => true }
397
+ elsif opts[:deny_forged]
398
+ policy[:forgedTransmits] = { :inherited => false, :value => false }
399
+ end
400
+
401
+ inherited_spec = get_inherited_config(obj)
402
+ if inherited_spec != nil
403
+ collapse_inheritance inherited_spec.securityPolicy, policy
404
+ end
405
+
406
+ spec = VIM::VMwareDVSPortSetting.new()
407
+ spec.securityPolicy = policy
408
+
409
+ apply_settings obj, spec
410
+ end
411
+
412
+ opts :unset_respool do
413
+ summary "Remove vDS portgroup or port from a network resource pool"
414
+ arg :obj, nil,
415
+ :lookup => [VIM::DistributedVirtualPort,
416
+ VIM::DistributedVirtualPortgroup]
417
+ end
418
+
419
+ def unset_respool obj
420
+ apply_settings obj, {:networkResourcePoolKey => {:inherited => false,
421
+ :value => nil} }
422
+ end
423
+
424
+ opts :set_respool do
425
+ summary "Remove vDS portgroup or port from a network resource pool"
426
+ arg :obj, nil,
427
+ :lookup => [VIM::DistributedVirtualPort,
428
+ VIM::DistributedVirtualPortgroup]
429
+ arg :respool, nil, :lookup => [VIM::DVSNetworkResourcePool]
430
+ end
431
+
432
+ def set_respool obj, respool
433
+ apply_settings obj, {:networkResourcePoolKey => {:inherited => false,
434
+ :value => respool.key} }
435
+ end
436
+
437
+ opts :show_running_config do
438
+ summary "Dump the configuration of a vDS and all child portgroups"
439
+ arg :vds, nil, :lookup => [VIM::DistributedVirtualSwitch]
440
+ end
441
+
442
+ def show_running_config vds
443
+ MODULES['basic'].info vds
444
+ portgroups = vds.children['portgroups']
445
+ portgroups.rvc_link vds, 'portgroups'
446
+ vds.children['portgroups'].children.each do |name, pg|
447
+ pg.rvc_link portgroups, name
448
+ puts '---'
449
+ MODULES['basic'].info pg
450
+ end
451
+ end
452
+
453
+ opts :show_all_portgroups do
454
+ summary "Show all portgroups in a given path."
455
+ arg :path, nil, :lookup => InventoryObject, :multi => true, :required => false
456
+ end
457
+
458
+ def show_all_portgroups path
459
+ paths = path.map { |p| p.rvc_path_str }
460
+ if paths.empty?
461
+ paths = nil
462
+ end
463
+
464
+ vds = MODULES['find'].find_items nil, paths, ['vds']
465
+ pgs = []
466
+ vds.each do |v|
467
+ v.portgroup.each { |pg| pgs << pg}
468
+ end
469
+ RVC::MODULES['basic'].table pgs, { :field => ["vds_name", "name", "vlan"],
470
+ :field_given => true }
471
+ end
472
+
473
+ opts :show_all_vds do
474
+ summary "Show all vDS's in a given path."
475
+ arg :path, nil, :lookup => InventoryObject, :multi => true, :required => false
476
+ end
477
+
478
+ def show_all_vds path
479
+ paths = path.map { |p| p.rvc_path_str }
480
+ if paths.empty?
481
+ paths = nil
482
+ end
483
+
484
+ vds = MODULES['find'].find_items nil, paths, ['vds']
485
+ RVC::MODULES['basic'].table vds, { :field => ['name', 'vlans', 'hosts'],
486
+ :field_given => true }
487
+ end
488
+
489
+ opts :show_all_ports do
490
+ summary "Show all ports in a given vDS/portgroup."
491
+ arg :path, nil, :lookup => [VIM::DistributedVirtualSwitch,
492
+ VIM::DistributedVirtualPortgroup],
493
+ :multi => true, :required => false
494
+ end
495
+
496
+ def show_all_ports path
497
+ rows = []
498
+ num_vds = 0
499
+ num_pgs = 0
500
+ path.each do |obj|
501
+ if obj.class < VIM::DistributedVirtualSwitch
502
+ num_vds += 1
503
+ vds = obj
504
+ ports = vds.FetchDVPorts(:criteria => { :active => true })
505
+ else #obj.class < VIM::DistributedVirtualPortgroup
506
+ num_pgs += 1
507
+ vds = obj.config.distributedVirtualSwitch
508
+ ports = vds.FetchDVPorts(:criteria => {
509
+ :portgroupKey => [obj.key], :inside => true,
510
+ :active => true})
511
+ end
512
+ pc = vds._connection.propertyCollector
513
+
514
+ # fetch names of VMs, portgroups, vDS
515
+ objects = []
516
+ ports.each do |port|
517
+ objects << port.proxyHost
518
+ if port.connectee
519
+ objects << port.connectee.connectedEntity
520
+ end
521
+ end
522
+ vds.portgroup.each { |pg| objects << pg }
523
+ objects << vds
524
+ spec = {
525
+ :objectSet => objects.map { |obj| { :obj => obj } },
526
+ :propSet => [{:type => "ManagedEntity", :pathSet => %w(name) },
527
+ {:type => "DistributedVirtualPortgroup",
528
+ :pathSet => %w(name key)}]
529
+ }
530
+ props = pc.RetrieveProperties(:specSet => [spec])
531
+ names = {}
532
+ props.each do |prop|
533
+ names[prop.obj] = prop['name']
534
+ if prop['key']
535
+ names[prop['key']] = prop['name']
536
+ end
537
+ end
538
+ vds_name = names[vds]
539
+
540
+ # put each port as a row in the table
541
+ ports.each do |port|
542
+ port_key = begin port.key.to_i; rescue port.key; end
543
+
544
+ connectee = nil
545
+ hostname = names[port.proxyHost].dup
546
+ if port.connectee and port.connectee.type == "vmVnic"
547
+ connectee = names[port.connectee.connectedEntity]
548
+ elsif port.connectee
549
+ connectee = port.connectee.nicKey
550
+ end
551
+
552
+ rows << [port_key, port.config.name, vds_name, names[port.portgroupKey],
553
+ translate_vlan(port.config.setting.vlan),
554
+ port.state.runtimeInfo.blocked, hostname, connectee]
555
+ end
556
+ end
557
+
558
+ abbrev_hostnames(rows.map { |r| r[6] })
559
+
560
+ columns = ['key', 'name', 'vds', 'portgroup', 'vlan', 'blocked', 'host', 'connectee']
561
+
562
+ # if we're just querying against a single vDS, skip the vds name column
563
+ if num_vds <= 1
564
+ columns.delete_at(2)
565
+ rows.each { |r| r.delete_at(2) }
566
+ end
567
+
568
+ # if we're just querying against one portgroup, skip portgroup name column
569
+ if num_pgs <= 1 and num_vds < 1
570
+ columns.delete_at(2)
571
+ rows.each { |r| r.delete_at(2) }
572
+ end
573
+
574
+ t = table(columns)
575
+ rows.sort_by { |o| o[0] }.each { |o| t << o }
576
+ puts t
577
+ end
578
+
579
+ def abbrev_hostnames names
580
+ min_len = 999
581
+ split_names = names.map { |name|
582
+ new_r = name.split('.').reverse
583
+ min_len = [min_len, new_r.size].min
584
+ new_r
585
+ }
586
+
587
+ matches = 0
588
+ (0..(min_len-1)).each do |i|
589
+ if split_names.first[i] == split_names.last[i]
590
+ matches = i+1
591
+ else
592
+ break
593
+ end
594
+ end
595
+
596
+ if matches == min_len
597
+ matches -= 1
598
+ end
599
+
600
+ if matches > 0
601
+ names.each { |n|
602
+ n.replace(n.split('.').reverse.drop(matches).reverse.join('.') + '.~')
603
+ }
604
+ end
605
+ end