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