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
data/lib/rvc/field.rb
ADDED
@@ -0,0 +1,122 @@
|
|
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
|
+
module RVC
|
22
|
+
|
23
|
+
module ObjectWithFields
|
24
|
+
module ClassMethods
|
25
|
+
def fields inherited=true
|
26
|
+
@fields ||= {}
|
27
|
+
if inherited
|
28
|
+
ancestors.select { |x| x.respond_to? :fields }.
|
29
|
+
map { |x| x.fields(false) }.
|
30
|
+
reverse.inject({}) { |b,v| b.merge v }
|
31
|
+
else
|
32
|
+
@fields
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def field name, &b
|
37
|
+
name = name.to_s
|
38
|
+
@fields ||= {}
|
39
|
+
@fields[name] = RVC::Field.new(name).tap { |f| f.instance_eval &b }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def field name
|
44
|
+
name = name.to_s
|
45
|
+
field = self.class.fields[name]
|
46
|
+
if field == nil
|
47
|
+
return nil
|
48
|
+
elsif self.class < VIM::ManagedObject
|
49
|
+
*props = collect *field.properties
|
50
|
+
if field.perfmetrics.length > 0
|
51
|
+
perfmgr = self._connection.serviceContent.perfManager
|
52
|
+
perfopts = field.perfmetric_settings.dup
|
53
|
+
perfopts[:max_samples] ||= 5
|
54
|
+
stats = perfmgr.retrieve_stats [self], field.perfmetrics, perfopts
|
55
|
+
props += field.perfmetrics.map do |x|
|
56
|
+
if stats[self]
|
57
|
+
stats[self][:metrics][x]
|
58
|
+
else
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
else
|
64
|
+
props = []
|
65
|
+
field.properties.each do |propstr|
|
66
|
+
obj = self
|
67
|
+
propstr.split('.').each { |prop| obj = obj.send(prop) }
|
68
|
+
props << obj
|
69
|
+
end
|
70
|
+
end
|
71
|
+
props = [self] if props.empty?
|
72
|
+
field.block.call *props
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class Field
|
77
|
+
ALL_FIELD_NAMES = Set.new
|
78
|
+
|
79
|
+
def initialize name
|
80
|
+
@name = name
|
81
|
+
@summary = nil
|
82
|
+
@properties = []
|
83
|
+
@perfmetrics = []
|
84
|
+
@perfmetric_settings = {}
|
85
|
+
@block = nil
|
86
|
+
@default = false
|
87
|
+
ALL_FIELD_NAMES << name
|
88
|
+
end
|
89
|
+
|
90
|
+
def summary x=nil
|
91
|
+
x ? (@summary = x) : @summary
|
92
|
+
end
|
93
|
+
|
94
|
+
def properties x=nil
|
95
|
+
x ? (@properties.concat x) : @properties
|
96
|
+
end
|
97
|
+
|
98
|
+
def perfmetrics x=nil
|
99
|
+
x ? (@perfmetrics.concat x) : @perfmetrics
|
100
|
+
end
|
101
|
+
|
102
|
+
def perfmetric_settings x=nil
|
103
|
+
x ? (@perfmetric_settings.merge! x) : @perfmetric_settings
|
104
|
+
end
|
105
|
+
|
106
|
+
def block &x
|
107
|
+
x ? (@block = x) : @block
|
108
|
+
end
|
109
|
+
|
110
|
+
def default val=true
|
111
|
+
@default = val
|
112
|
+
end
|
113
|
+
|
114
|
+
def default?; @default; end
|
115
|
+
|
116
|
+
def property prop
|
117
|
+
@properties = [prop]
|
118
|
+
@block = lambda { |x| x }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
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
|
module RVC
|
2
22
|
|
3
23
|
class FilesystemSession
|
data/lib/rvc/inventory.rb
CHANGED
@@ -18,10 +18,21 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
+
require 'rvc/field'
|
22
|
+
|
21
23
|
module RVC
|
22
24
|
|
23
25
|
module InventoryObject
|
26
|
+
include ObjectWithFields
|
27
|
+
extend ObjectWithFields::ClassMethods
|
28
|
+
|
24
29
|
module ClassMethods
|
30
|
+
include ObjectWithFields::ClassMethods
|
31
|
+
|
32
|
+
def ls_r
|
33
|
+
""
|
34
|
+
end
|
35
|
+
|
25
36
|
def ls_properties
|
26
37
|
%w()
|
27
38
|
end
|
@@ -29,12 +40,20 @@ module InventoryObject
|
|
29
40
|
def folder?
|
30
41
|
false
|
31
42
|
end
|
43
|
+
|
44
|
+
def traverse?
|
45
|
+
false
|
46
|
+
end
|
32
47
|
end
|
33
48
|
|
34
49
|
def self.included m
|
35
50
|
m.extend ClassMethods
|
36
51
|
end
|
37
52
|
|
53
|
+
field 'rel_path' do
|
54
|
+
block { |me| me.rvc_relative_path_str($shell.fs.cur) }
|
55
|
+
end
|
56
|
+
|
38
57
|
attr_reader :rvc_parent, :rvc_arc
|
39
58
|
|
40
59
|
def display_info
|
@@ -68,6 +87,22 @@ module InventoryObject
|
|
68
87
|
rvc_path.map { |k,v| k } * '/'
|
69
88
|
end
|
70
89
|
|
90
|
+
def rvc_relative_path ref
|
91
|
+
my_path = rvc_path
|
92
|
+
ref_path = ref.rvc_path
|
93
|
+
ref_objs = Set.new(ref_path.map { |x| x[1] })
|
94
|
+
common = my_path.take_while { |x| ref_objs.member? x[1] }
|
95
|
+
fail unless common
|
96
|
+
path_to_ref = my_path.reverse.take_while { |x| x[1] != common.last[1] }.reverse
|
97
|
+
num_ups = ref_path.size - common.size
|
98
|
+
ups = (['..']*num_ups).zip(ref_path.reverse[1..-1].map(&:first))
|
99
|
+
ups + path_to_ref
|
100
|
+
end
|
101
|
+
|
102
|
+
def rvc_relative_path_str ref
|
103
|
+
rvc_relative_path(ref).map { |k,v| k } * '/'
|
104
|
+
end
|
105
|
+
|
71
106
|
def rvc_link parent, arc
|
72
107
|
return if @rvc_parent
|
73
108
|
@rvc_parent = parent
|
@@ -118,15 +153,3 @@ class RootNode
|
|
118
153
|
end
|
119
154
|
|
120
155
|
end
|
121
|
-
|
122
|
-
class RbVmomi::VIM
|
123
|
-
include RVC::InventoryObject
|
124
|
-
|
125
|
-
def children
|
126
|
-
rootFolder.children
|
127
|
-
end
|
128
|
-
|
129
|
-
def self.folder?
|
130
|
-
true
|
131
|
-
end
|
132
|
-
end
|
data/lib/rvc/known_hosts.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
|
require 'digest/sha2'
|
2
22
|
require 'fileutils'
|
3
23
|
require 'rbconfig'
|
data/lib/rvc/memory_session.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
|
module RVC
|
2
22
|
|
3
23
|
class MemorySession
|
data/lib/rvc/modules.rb
CHANGED
@@ -19,6 +19,7 @@
|
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
21
|
require 'rvc/util'
|
22
|
+
require 'shellwords'
|
22
23
|
|
23
24
|
module RVC
|
24
25
|
|
@@ -31,6 +32,7 @@ class CmdModule
|
|
31
32
|
def initialize module_name
|
32
33
|
@module_name = module_name
|
33
34
|
@opts = {}
|
35
|
+
@completors = {}
|
34
36
|
super()
|
35
37
|
end
|
36
38
|
|
@@ -38,20 +40,73 @@ class CmdModule
|
|
38
40
|
@opts.keys
|
39
41
|
end
|
40
42
|
|
43
|
+
def has_command? cmd
|
44
|
+
@opts.member? cmd
|
45
|
+
end
|
46
|
+
|
41
47
|
def opts cmd, &b
|
42
|
-
|
48
|
+
if cmd.to_s =~ /[A-Z]/
|
49
|
+
fail "Camel-casing is not allowed (#{cmd.to_s})"
|
50
|
+
end
|
51
|
+
|
52
|
+
@opts[cmd] = OptionParser.new cmd.to_s, &b
|
53
|
+
|
54
|
+
@opts[cmd].specs.each do |name,spec|
|
55
|
+
if name.to_s =~ /[A-Z]/
|
56
|
+
fail "Camel-casing is not allowed (#{cmd.to_s} option #{name})"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def raw_opts cmd, summary
|
62
|
+
@opts[cmd] = RawOptionParser.new cmd.to_s, summary
|
43
63
|
end
|
44
64
|
|
45
65
|
def opts_for cmd
|
46
66
|
@opts[cmd]
|
47
67
|
end
|
48
68
|
|
69
|
+
def rvc_completor cmd, &b
|
70
|
+
@completors[cmd] = b
|
71
|
+
end
|
72
|
+
|
73
|
+
def completor_for cmd
|
74
|
+
@completors[cmd]
|
75
|
+
end
|
76
|
+
|
49
77
|
def rvc_alias cmd, target=nil
|
50
78
|
target ||= cmd
|
51
79
|
RVC::ALIASES[target.to_s] = "#{@module_name}.#{cmd}"
|
52
80
|
end
|
53
81
|
end
|
54
82
|
|
83
|
+
def self.complete_for_cmd line, word
|
84
|
+
if line == nil
|
85
|
+
return []
|
86
|
+
end
|
87
|
+
mod, cmd, args = Shell.parse_input line
|
88
|
+
return [] unless mod != nil
|
89
|
+
#XXX assumes you aren't going to have any positional arguments with spaces
|
90
|
+
if(/ $/.match(line))
|
91
|
+
argnum = args.size
|
92
|
+
else
|
93
|
+
argnum = args.size - 1
|
94
|
+
end
|
95
|
+
|
96
|
+
completor = mod.completor_for(cmd.to_sym)
|
97
|
+
if completor == nil
|
98
|
+
return []
|
99
|
+
end
|
100
|
+
|
101
|
+
candidates = completor.call(line, args, word, argnum)
|
102
|
+
if candidates == nil
|
103
|
+
[]
|
104
|
+
else
|
105
|
+
prefix_regex = /^#{Regexp.escape word}/
|
106
|
+
candidates.select { |x,a| x =~ prefix_regex }
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
55
110
|
BULTIN_MODULE_PATH = [File.expand_path(File.join(File.dirname(__FILE__), 'modules')),
|
56
111
|
File.join(ENV['HOME'], ".rvc")]
|
57
112
|
ENV_MODULE_PATH = (ENV['RVC_MODULE_PATH'] || '').split ':'
|
@@ -65,13 +120,18 @@ def self.reload_modules verbose=true
|
|
65
120
|
Dir.glob(globs) do |f|
|
66
121
|
module_name = File.basename(f)[0...-3]
|
67
122
|
puts "loading #{module_name} from #{f}" if verbose
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
123
|
+
begin
|
124
|
+
code = File.read f
|
125
|
+
unless RVC::MODULES.member? module_name
|
126
|
+
m = CmdModule.new module_name
|
127
|
+
CMD.define_singleton_method(module_name.to_sym) { m }
|
128
|
+
RVC::MODULES[module_name] = m
|
129
|
+
end
|
130
|
+
RVC::MODULES[module_name].instance_eval code, f
|
131
|
+
rescue
|
132
|
+
puts "#{$!.class} while loading #{f}: #{$!.message}"
|
133
|
+
$!.backtrace.each { |x| puts x }
|
73
134
|
end
|
74
|
-
RVC::MODULES[module_name].instance_eval code, f
|
75
135
|
end
|
76
136
|
end
|
77
137
|
|
@@ -0,0 +1,37 @@
|
|
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
|
+
opts :show do
|
22
|
+
summary "Show alarms on the given entities"
|
23
|
+
arg :entity, nil, :lookup => VIM::ManagedEntity, :multi => true
|
24
|
+
end
|
25
|
+
|
26
|
+
IGNORE_STATUSES = %w(green gray)
|
27
|
+
|
28
|
+
def show objs
|
29
|
+
alarm_states = objs.map(&:triggeredAlarmState).flatten.uniq
|
30
|
+
alarm_states.each do |alarm_state|
|
31
|
+
info = alarm_state.alarm.info
|
32
|
+
colored_alarm_status = status_color alarm_state.overallStatus, alarm_state.overallStatus
|
33
|
+
puts "#{alarm_state.entity.name}: #{info.name} (#{colored_alarm_status}): #{info.description}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
rvc_alias :show, :alarms
|
data/lib/rvc/modules/basic.rb
CHANGED
@@ -44,20 +44,18 @@ HELP_ORDER = %w(basic vm)
|
|
44
44
|
def help path
|
45
45
|
if mod = RVC::MODULES[path]
|
46
46
|
opts = mod.instance_variable_get(:@opts)
|
47
|
-
opts.each do |method_name,
|
48
|
-
parser = RVC::OptionParser.new method_name, &method_opts
|
47
|
+
opts.each do |method_name,parser|
|
49
48
|
help_summary parser, path, method_name
|
50
49
|
end
|
51
50
|
return
|
52
51
|
elsif tgt = RVC::ALIASES[path]
|
53
52
|
fail unless tgt =~ /^(.+)\.(.+)$/
|
54
|
-
|
55
|
-
RVC::OptionParser.new(tgt, &opts_block).educate
|
53
|
+
RVC::MODULES[$1].opts_for($2.to_sym).educate
|
56
54
|
return
|
57
55
|
elsif path =~ /^(.+)\.(.+)$/ and
|
58
56
|
mod = RVC::MODULES[$1] and
|
59
|
-
|
60
|
-
|
57
|
+
parser = mod.opts_for($2.to_sym)
|
58
|
+
parser.educate
|
61
59
|
return
|
62
60
|
end
|
63
61
|
|
@@ -73,8 +71,7 @@ def help path
|
|
73
71
|
HELP_ORDER.index(mod_name) || HELP_ORDER.size
|
74
72
|
end.each do |mod_name,mod|
|
75
73
|
opts = mod.instance_variable_get(:@opts)
|
76
|
-
opts.each do |method_name,
|
77
|
-
parser = RVC::OptionParser.new method_name, &method_opts
|
74
|
+
opts.each do |method_name,parser|
|
78
75
|
next unless obj.nil? or parser.applicable.any? { |x| obj.is_a? x }
|
79
76
|
help_summary parser, mod_name, method_name
|
80
77
|
end
|
@@ -105,32 +102,9 @@ rvc_alias :debug
|
|
105
102
|
def debug
|
106
103
|
debug = $shell.debug = !$shell.debug
|
107
104
|
$shell.connections.each do |name,conn|
|
108
|
-
conn.debug = debug
|
105
|
+
conn.debug = debug if conn.respond_to? :debug
|
109
106
|
end
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
opts :quit do
|
114
|
-
summary "Exit RVC"
|
115
|
-
end
|
116
|
-
|
117
|
-
rvc_alias :quit
|
118
|
-
rvc_alias :quit, :exit
|
119
|
-
rvc_alias :quit, :q
|
120
|
-
|
121
|
-
def quit
|
122
|
-
exit
|
123
|
-
end
|
124
|
-
|
125
|
-
|
126
|
-
opts :reload do
|
127
|
-
summary "Reload RVC command modules"
|
128
|
-
end
|
129
|
-
|
130
|
-
rvc_alias :reload
|
131
|
-
|
132
|
-
def reload
|
133
|
-
RVC.reload_modules
|
107
|
+
puts "debug mode #{debug ? 'en' : 'dis'}abled"
|
134
108
|
end
|
135
109
|
|
136
110
|
|
@@ -162,6 +136,10 @@ rvc_alias :ls
|
|
162
136
|
rvc_alias :ls, :l
|
163
137
|
|
164
138
|
def ls obj
|
139
|
+
if obj.respond_to?(:rvc_ls)
|
140
|
+
return obj.rvc_ls
|
141
|
+
end
|
142
|
+
|
165
143
|
children = obj.children
|
166
144
|
name_map = children.invert
|
167
145
|
children, fake_children = children.partition { |k,v| v.is_a? VIM::ManagedEntity }
|
@@ -187,7 +165,7 @@ def ls obj
|
|
187
165
|
filteredTypes.each do |x|
|
188
166
|
filterSpec.propSet << {
|
189
167
|
:type => x.wsdl_name,
|
190
|
-
:pathSet => x.ls_properties+%w(name),
|
168
|
+
:pathSet => x.ls_properties+%w(name overallStatus),
|
191
169
|
}
|
192
170
|
end
|
193
171
|
|
@@ -198,22 +176,85 @@ def ls obj
|
|
198
176
|
name = name_map[r.obj]
|
199
177
|
text = r.obj.ls_text(r) rescue " (error)"
|
200
178
|
realname = r['name'] if name != r['name']
|
201
|
-
|
179
|
+
colored_name = status_color name, r['overallStatus']
|
180
|
+
puts "#{i} #{colored_name}#{realname && " [#{realname}]"}#{text}"
|
202
181
|
r.obj.rvc_link obj, name
|
203
182
|
CMD.mark.mark i.to_s, [r.obj]
|
204
183
|
i += 1
|
205
184
|
end
|
206
185
|
end
|
207
186
|
|
208
|
-
|
209
187
|
opts :info do
|
210
188
|
summary "Display information about an object"
|
211
189
|
arg :path, nil, :lookup => Object
|
212
|
-
end
|
190
|
+
end
|
213
191
|
|
214
192
|
rvc_alias :info
|
215
193
|
rvc_alias :info, :i
|
216
194
|
|
195
|
+
opts :show do
|
196
|
+
summary "Display information about an object"
|
197
|
+
arg :arg0, nil, :type => :string
|
198
|
+
arg :arg1, nil, :type => :string, :required => false
|
199
|
+
end
|
200
|
+
|
201
|
+
rvc_alias :show
|
202
|
+
|
203
|
+
rvc_completor :show do |line, args, word, index|
|
204
|
+
choices = RVC::Completion.fs_candidates word
|
205
|
+
obj = lookup_single '.'
|
206
|
+
if index == 0
|
207
|
+
if obj.class == VIM::Datacenter || obj.class == VIM
|
208
|
+
choices << ['portgroups', ' ']
|
209
|
+
choices << ['vds', ' ']
|
210
|
+
end
|
211
|
+
if obj.class < VIM::DistributedVirtualSwitch
|
212
|
+
choices << ['running-config', ' ']
|
213
|
+
choices << ['interface', ' ']
|
214
|
+
#choices << ['vlan', ' ']
|
215
|
+
#choices << ['lldp', ' ']
|
216
|
+
#choices << ['cdp', ' ']
|
217
|
+
end
|
218
|
+
#elsif index == 1
|
219
|
+
# if args[0] == 'vlan'
|
220
|
+
# choices << ['summary', ' ']
|
221
|
+
# end
|
222
|
+
end
|
223
|
+
choices
|
224
|
+
end
|
225
|
+
|
226
|
+
def show arg0, arg1
|
227
|
+
arg1 ||= '.'
|
228
|
+
begin
|
229
|
+
obj = lookup_single arg1
|
230
|
+
rescue
|
231
|
+
obj = nil
|
232
|
+
end
|
233
|
+
|
234
|
+
case arg0
|
235
|
+
when 'running-config'
|
236
|
+
if obj.class < VIM::DistributedVirtualSwitch
|
237
|
+
MODULES['vds'].show_running_config obj
|
238
|
+
else
|
239
|
+
if arg1 != '.'
|
240
|
+
err "'#{arg1}' is not a vDS!"
|
241
|
+
else
|
242
|
+
err "you need to be inside a vDS"
|
243
|
+
end
|
244
|
+
end
|
245
|
+
when 'portgroups'
|
246
|
+
MODULES['vds'].show_all_portgroups [obj]
|
247
|
+
when 'vds'
|
248
|
+
MODULES['vds'].show_all_vds [obj]
|
249
|
+
when 'interface'
|
250
|
+
MODULES['vds'].show_all_ports [obj]
|
251
|
+
#when 'vlan'
|
252
|
+
else
|
253
|
+
path = lookup_single arg0
|
254
|
+
info path
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
217
258
|
def info obj
|
218
259
|
puts "path: #{obj.rvc_path_str}"
|
219
260
|
if obj.respond_to? :display_info
|
@@ -248,15 +289,15 @@ def reload_entity objs
|
|
248
289
|
end
|
249
290
|
|
250
291
|
|
251
|
-
opts :
|
292
|
+
opts :what do
|
252
293
|
summary "Basic information about the given objects"
|
253
294
|
arg :obj, nil, :multi => true, :required => false, :lookup => Object
|
254
295
|
end
|
255
296
|
|
256
|
-
rvc_alias :
|
257
|
-
rvc_alias :
|
297
|
+
rvc_alias :what
|
298
|
+
rvc_alias :what, :w
|
258
299
|
|
259
|
-
def
|
300
|
+
def what objs
|
260
301
|
objs.each do |obj|
|
261
302
|
puts "#{obj.rvc_path_str}: #{obj.class}"
|
262
303
|
end
|
@@ -344,3 +385,93 @@ def events obj, opts
|
|
344
385
|
ensure
|
345
386
|
collector.DestroyCollector if collector
|
346
387
|
end
|
388
|
+
|
389
|
+
|
390
|
+
opts :fields do
|
391
|
+
summary "Show available fields on an object"
|
392
|
+
arg :obj, nil, :required => false, :default => '.', :lookup => RVC::InventoryObject
|
393
|
+
end
|
394
|
+
|
395
|
+
def fields obj
|
396
|
+
obj.class.ancestors.select { |x| x.respond_to? :fields }.each do |klass|
|
397
|
+
fields = klass.fields false
|
398
|
+
next if fields.empty?
|
399
|
+
puts "Fields on #{klass}:"
|
400
|
+
fields.each do |name,field|
|
401
|
+
puts " #{name}: #{field.summary}"
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
rvc_alias :fields
|
407
|
+
|
408
|
+
|
409
|
+
opts :table do
|
410
|
+
summary "Display a table with the selected fields"
|
411
|
+
|
412
|
+
text <<-EOS
|
413
|
+
|
414
|
+
You may specify the fields to display using multiple -f options, or
|
415
|
+
separate them with ':'. The available fields for an object are
|
416
|
+
shown by the "fields" command.
|
417
|
+
EOS
|
418
|
+
text ""
|
419
|
+
|
420
|
+
arg :obj, nil, :multi => true, :lookup => RVC::InventoryObject
|
421
|
+
opt :field, "Field to display", :multi => true, :type => :string
|
422
|
+
opt :sort, "Field to sort by", :type => :string
|
423
|
+
opt :reverse, "Reverse sort order"
|
424
|
+
end
|
425
|
+
|
426
|
+
rvc_completor :table do |line, args, word, argnum|
|
427
|
+
if argnum > 0 and args[argnum-1] == '-f'
|
428
|
+
RVC::Field::ALL_FIELD_NAMES.map { |x| [x, ' '] }
|
429
|
+
else
|
430
|
+
RVC::Completion.fs_candidates word
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
def table objs, opts
|
435
|
+
if opts[:field_given]
|
436
|
+
fields = opts[:field].map { |x| x.split ':' }.flatten(1)
|
437
|
+
else
|
438
|
+
fields = objs.map(&:class).uniq.
|
439
|
+
map { |x| x.fields.select { |k,v| v.default? } }.
|
440
|
+
map(&:keys).flatten(1).uniq
|
441
|
+
end
|
442
|
+
|
443
|
+
data = retrieve_fields(objs, fields).values
|
444
|
+
|
445
|
+
if f = opts[:sort]
|
446
|
+
data.sort! { |a,b| table_sort_compare a[f], b[f] }
|
447
|
+
data.reverse! if opts[:reverse]
|
448
|
+
end
|
449
|
+
|
450
|
+
# Invert field components to get an array of header rows
|
451
|
+
field_components = fields.map { |x| x.split '.' }
|
452
|
+
header_rows = []
|
453
|
+
field_components.each_with_index do |cs,i|
|
454
|
+
cs.each_with_index do |c,j|
|
455
|
+
header_rows[j] ||= [nil]*field_components.length
|
456
|
+
header_rows[j][i] = c
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
table = Terminal::Table.new
|
461
|
+
header_rows.each { |row| table.add_row row }
|
462
|
+
table.add_separator
|
463
|
+
data.each do |h|
|
464
|
+
table.add_row(fields.map { |f| h[f] == nil ? 'N/A' : h[f] })
|
465
|
+
end
|
466
|
+
puts table
|
467
|
+
end
|
468
|
+
|
469
|
+
def table_sort_compare a, b
|
470
|
+
return a <=> b if a != nil and b != nil
|
471
|
+
return 0 if a == nil and b == nil
|
472
|
+
return -1 if a == nil
|
473
|
+
return 1 if b == nil
|
474
|
+
fail
|
475
|
+
end
|
476
|
+
|
477
|
+
rvc_alias :table
|