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
@@ -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
|
data/lib/rvc/modules/role.rb
CHANGED
@@ -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 #{
|
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 #{
|
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 #{
|
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
|
|
data/lib/rvc/modules/snapshot.rb
CHANGED
@@ -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
|