rvc 1.0.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 (43) hide show
  1. data/LICENSE +19 -0
  2. data/README.rdoc +120 -0
  3. data/Rakefile +39 -0
  4. data/TODO +4 -0
  5. data/VERSION +1 -0
  6. data/bin/rvc +104 -0
  7. data/lib/rvc.rb +31 -0
  8. data/lib/rvc/completion.rb +110 -0
  9. data/lib/rvc/extensions/ClusterComputeResource.rb +42 -0
  10. data/lib/rvc/extensions/ComputeResource.rb +47 -0
  11. data/lib/rvc/extensions/Datacenter.rb +36 -0
  12. data/lib/rvc/extensions/Datastore.rb +188 -0
  13. data/lib/rvc/extensions/DistributedVirtualPortgroup.rb +38 -0
  14. data/lib/rvc/extensions/DistributedVirtualSwitch.rb +40 -0
  15. data/lib/rvc/extensions/Folder.rb +33 -0
  16. data/lib/rvc/extensions/HostSystem.rb +48 -0
  17. data/lib/rvc/extensions/ManagedEntity.rb +28 -0
  18. data/lib/rvc/extensions/Network.rb +28 -0
  19. data/lib/rvc/extensions/ResourcePool.rb +52 -0
  20. data/lib/rvc/extensions/VirtualMachine.rb +72 -0
  21. data/lib/rvc/fs.rb +123 -0
  22. data/lib/rvc/inventory.rb +125 -0
  23. data/lib/rvc/modules.rb +74 -0
  24. data/lib/rvc/modules/basic.rb +276 -0
  25. data/lib/rvc/modules/datastore.rb +63 -0
  26. data/lib/rvc/modules/host.rb +29 -0
  27. data/lib/rvc/modules/resource_pool.rb +95 -0
  28. data/lib/rvc/modules/vim.rb +128 -0
  29. data/lib/rvc/modules/vm.rb +607 -0
  30. data/lib/rvc/modules/vmrc.rb +72 -0
  31. data/lib/rvc/modules/vnc.rb +111 -0
  32. data/lib/rvc/option_parser.rb +114 -0
  33. data/lib/rvc/path.rb +37 -0
  34. data/lib/rvc/readline-ffi.rb +41 -0
  35. data/lib/rvc/shell.rb +220 -0
  36. data/lib/rvc/ttl_cache.rb +44 -0
  37. data/lib/rvc/util.rb +168 -0
  38. data/test/_test_completion.rb +27 -0
  39. data/test/_test_option_parser.rb +6 -0
  40. data/test/inventory_fixtures.rb +15 -0
  41. data/test/test_fs.rb +113 -0
  42. data/test/test_parse_path.rb +41 -0
  43. metadata +146 -0
data/LICENSE ADDED
@@ -0,0 +1,19 @@
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.
@@ -0,0 +1,120 @@
1
+ = RVC - Ruby vSphere Console
2
+
3
+ == Introduction
4
+
5
+ RVC is a console UI for VMware ESX and VirtualCenter. The vSphere object graph
6
+ is presented as a virtual filesystem, allowing you to navigate and run commands
7
+ against managed entities using familiar shell syntax. RVC doesn't (yet) have
8
+ every feature vSphere Client does, but for common tasks it can be much more
9
+ efficient than clicking through a GUI.
10
+
11
+ == Installation
12
+
13
+ gem install rvc
14
+
15
+ == Usage
16
+
17
+ % rvc 192.168.1.105
18
+ username: Administrator
19
+ password:
20
+ 0 dc (datacenter)
21
+ 192.168.1.105:/> cd dc/host/192.168.1.100/
22
+ 192.168.1.105:/dc/host/192.168.1.100/> ls
23
+ 0 host [192.168.1.100] (host): cpu 2*2*2.81 GHz, memory 2.00 GB
24
+ 1 resourcePool [Resources]: cpu 4.35/4.35/normal, mem 0.48/0.48/normal
25
+ 192.168.1.105:/dc/host/192.168.1.100/> ls host/vms/
26
+ 0 foo: poweredOn
27
+ 192.168.1.105:/dc/host/192.168.1.100/> i host/vms/foo
28
+ name: foo
29
+ host: dc/host/192.168.1.100/192.168.1.100
30
+ tools: guestToolsNotRunning
31
+ VC UUID: 5259d5d2-b767-43c9-db6d-fbf5cc4b6f02
32
+ power: poweredOn
33
+ cpus: 1
34
+ memory: 128 MB
35
+ nics:
36
+ Network adapter 1: "VM Network" connected 00:0c:29:c6:5d:2a
37
+ 192.168.1.105:/dc/host/192.168.1.100/> off host/vms/foo
38
+ PowerOffVM foo: success
39
+ 192.168.1.105:/dc/host/192.168.1.100/> quit
40
+
41
+ Enter "help" to see a list of all available commands.
42
+
43
+ All RVC commands exist in modules, and may optionally have aliases. For
44
+ example, the command to power off a VM is actually "vm.off", since it exists in
45
+ the "vm" module, but since it is a common operation it has been aliased to
46
+ "off".
47
+
48
+ == Features
49
+
50
+ === Tab-completion
51
+
52
+ Commands and paths can be tab completed in the usual fashion. Whitespace must
53
+ be escaped with a backslash.
54
+
55
+ === Marks
56
+
57
+ 192.168.1.105:/> mark a dc/vm/foo
58
+ 192.168.1.105:/> on ~a
59
+ PowerOnVM foo: success
60
+ 192.168.1.105:/> off ~a
61
+ PowerOffVM foo: success
62
+
63
+ Marks allow you to save a path for later use. Refer to a mark by prefixing its
64
+ name with a tilde. The "ls" command automatically creates numeric marks for
65
+ each object listed; these are the numbers in the first column. As a special
66
+ case, you don't need to use a tilde with numeric marks. The "cd" command
67
+ automatically creates the mark "~~" pointing to the previous directory. If a
68
+ mark reference is input instead of a command then RVC will cd to the marked
69
+ object. Thus, "~~" is a convenient way to toggle between two directories.
70
+
71
+ When the working directory is a descendant of a Datacenter object, the mark "~"
72
+ refers to the Datacenter. For example "~/datastore" is a convenient way to get
73
+ the datastore folder of the current datacenter.
74
+
75
+ === Ruby mode
76
+
77
+ Beginning an input line with "/" causes RVC to treat it as Ruby code and eval
78
+ it. This gives you direct access to the underlying RbVmomi library. If the line
79
+ "//" is input then RVC will toggle between shell and Ruby mode.
80
+
81
+ Marks can be easily used in Ruby mode since there are magic variables with the
82
+ same names. Since some marks, like numeric ones, aren't valid variable names,
83
+ they also exist with a "_" prefix.
84
+
85
+ The methods "this", "conn", and "dc" are provided in Ruby mode, returning the
86
+ current object, connection, and datacenter respectively. The connection object
87
+ is an instance of RbVmomi::VIM.
88
+
89
+ === VMODL introspection
90
+
91
+ The "type" command can be used to display the properties and methods of a VMODL
92
+ class. For example: "type Datacenter".
93
+
94
+ In Ruby mode, a '#' at the end of the input line will display the output of the
95
+ "type" command for the resulting object's class. This is very useful for
96
+ exploring the vSphere API.
97
+
98
+ === Multiple connections
99
+
100
+ RVC can connect to more than one ESX or VC server at the same time. Simply add
101
+ more hosts to the command line, or use the command "connect". Each connection
102
+ is represented by a top-level node in the virtual filesystem. If more than one
103
+ host is given on the command line, RVC will start in the root of the filesystem
104
+ instead of automatically cd'ing to a connection.
105
+
106
+ == Extensibility
107
+
108
+ RVC is designed to let users easily add commands they need. You can create a
109
+ command module, or add to an existing one, by adding a Ruby file to ~/.rvc or
110
+ any directory on the RVC_MODULE_PATH environment variable. The syntax of a user
111
+ command module is the same as those built-in to RVC, so see the
112
+ "lib/rvc/modules" directory for examples.
113
+
114
+ If you create a generically useful RVC command, please consider sending in a
115
+ patch so everyone can use it.
116
+
117
+ == Development
118
+
119
+ Send patches to rlane@vmware.com, or fork the project on GitHub and send me a
120
+ pull request.
@@ -0,0 +1,39 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gem|
4
+ gem.name = "rvc"
5
+ gem.summary = "vSphere console UI"
6
+ #gem.description = ""
7
+ gem.email = "rlane@vmware.com"
8
+ #gem.homepage = ""
9
+ gem.authors = ["Rich Lane"]
10
+ gem.add_dependency 'rbvmomi', '>= 1.1.5'
11
+ gem.add_dependency 'trollop', '>= 1.16.2'
12
+ gem.add_dependency 'backports', '>= 1.18.2'
13
+ gem.add_dependency 'ffi', '>= 1.0.7'
14
+ end
15
+ rescue LoadError
16
+ puts "Jeweler not available. Install it with: gem install jeweler"
17
+ end
18
+
19
+ require 'rake/testtask'
20
+ Rake::TestTask.new do |t|
21
+ t.libs << "test"
22
+ t.test_files = FileList['test/test_*.rb']
23
+ t.verbose = true
24
+ t.ruby_opts << "-rubygems"
25
+ end
26
+
27
+ begin
28
+ require 'rcov/rcovtask'
29
+ desc 'Measures test coverage using rcov'
30
+ Rcov::RcovTask.new do |rcov|
31
+ rcov.pattern = 'test/test_*.rb'
32
+ rcov.output_dir = 'coverage'
33
+ rcov.verbose = true
34
+ rcov.libs << "test"
35
+ rcov.rcov_opts << '--exclude "gems/*"'
36
+ end
37
+ rescue LoadError
38
+ puts "Rcov not available. Install it with: gem install rcov"
39
+ end
data/TODO ADDED
@@ -0,0 +1,4 @@
1
+ add commands for more entities
2
+ add fake subfolders for more entities
3
+ add fastpass authentication
4
+ globbing?
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/bin/rvc ADDED
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright (c) 2011 VMware, Inc. All Rights Reserved.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ require 'readline'
22
+ require 'pp'
23
+ require 'trollop'
24
+ require 'rbvmomi'
25
+ require 'rbvmomi/trollop'
26
+ require 'shellwords'
27
+ require 'yaml'
28
+ require 'backports'
29
+ require 'rvc'
30
+
31
+ VIM = RbVmomi::VIM
32
+ include RVC::Util
33
+
34
+ Thread.abort_on_exception = true
35
+
36
+ CMD = Module.new
37
+
38
+ $opts = Trollop.options do
39
+ banner <<-EOS
40
+ Ruby vSphere Console.
41
+
42
+ Usage:
43
+ rvc [options] [username[:password]@]hostname
44
+
45
+ where [options] are:
46
+ EOS
47
+
48
+ opt :insecure, "don't verify ssl certificate", :short => 'k', :default => (ENV['RBVMOMI_INSECURE'] == '1')
49
+ opt :path, "Initial directory", :short => :none, :default => ENV['RVC_PATH'], :type => :string
50
+ opt :create_directory, "Create the initial directory if it doesn't exist", :short => :none
51
+ opt :cmd, "command to evaluate", :short => 'c', :multi => true, :type => :string
52
+ end
53
+
54
+ Trollop.die "At least 1 argument expected" unless ARGV.length >= 1
55
+
56
+ RVC.reload_modules false
57
+
58
+ $shell = RVC::Shell.new
59
+
60
+ ARGV.each do |uri|
61
+ begin
62
+ puts "Connecting to #{uri}..." if ARGV.size > 1
63
+ CMD.vim.connect uri, :insecure => $opts[:insecure]
64
+ rescue UserError
65
+ puts "Failed to connect to #{uri}: #{$!.message}"
66
+ exit 1
67
+ end
68
+ end
69
+
70
+ RVC::Completion.install
71
+ history_fn = "#{ENV['HOME']}/.rvc-history"
72
+ IO.foreach(history_fn) { |l| Readline::HISTORY << l.chomp } rescue puts "Welcome to RVC. Try the 'help' command."
73
+ history = File.open(history_fn, 'a')
74
+
75
+ if $opts[:path]
76
+ begin
77
+ CMD.basic.cd $opts[:path]
78
+ rescue UserError
79
+ raise unless $opts[:create_directory]
80
+ parent_path = File.dirname($opts[:path])
81
+ lookup(parent_path).CreateFolder(:name => File.basename($opts[:path]))
82
+ CMD.basic.cd $opts[:path]
83
+ end
84
+ elsif ARGV.size == 1
85
+ CMD.basic.cd $shell.connections.keys.first
86
+ end
87
+
88
+ unless CMD.vmrc.find_vmrc
89
+ $stderr.puts "VMRC is not installed. You will be unable to view virtual machine consoles. Use the vmrc.install command to install it."
90
+ end
91
+
92
+ CMD.basic.ls '.'
93
+
94
+ while true
95
+ begin
96
+ input = $opts[:cmd].shift || Readline.readline($shell.prompt, false) or break
97
+ input = input.strip
98
+ next if input.empty?
99
+ (history.puts input; Readline::HISTORY << input) unless input == Readline::HISTORY.to_a[-1]
100
+ $shell.eval_input input
101
+ rescue Interrupt
102
+ puts
103
+ end
104
+ end
@@ -0,0 +1,31 @@
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 'rbvmomi'
22
+ require 'rvc/inventory'
23
+ require 'rvc/modules'
24
+ require 'rvc/util'
25
+ require 'rvc/path'
26
+ require 'rvc/fs'
27
+ require 'rvc/completion'
28
+ require 'rvc/option_parser'
29
+ require 'rvc/shell'
30
+
31
+ RbVmomi::VIM.extension_dirs << File.join(File.dirname(__FILE__), "rvc/extensions")
@@ -0,0 +1,110 @@
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 'readline'
22
+ require 'rvc/ttl_cache'
23
+
24
+ begin
25
+ require 'rvc/readline-ffi'
26
+ rescue Exception
27
+ end
28
+
29
+ module RVC
30
+ module Completion
31
+ Cache = TTLCache.new 10
32
+
33
+ Completor = lambda do |word|
34
+ return unless word
35
+ line = Readline.line_buffer if Readline.respond_to? :line_buffer
36
+ append_char, candidates = RVC::Completion.complete word, line
37
+ Readline.completion_append_character = append_char
38
+ candidates
39
+ end
40
+
41
+ def self.install
42
+ unless Readline.respond_to? :line_buffer and
43
+ Readline.respond_to? :char_is_quoted=
44
+ $stderr.puts "Install the \"ffi\" gem for better tab completion."
45
+ end
46
+
47
+ if Readline.respond_to? :char_is_quoted=
48
+ Readline.completer_word_break_characters = " \t\n\"'"
49
+ Readline.completer_quote_characters = "\"\\"
50
+ is_quoted = lambda { |str,i| i > 0 && str[i-1] == '\\' && !is_quoted[str,i-1] }
51
+ Readline.char_is_quoted = is_quoted
52
+ end
53
+
54
+ Readline.completion_proc = Completor
55
+ end
56
+
57
+ def self.complete word, line
58
+ candidates = if line
59
+ if line[' ']
60
+ child_candidates(word)
61
+ else
62
+ cmd_candidates(word)
63
+ end
64
+ else
65
+ child_candidates(word) + cmd_candidates(word)
66
+ end
67
+
68
+ candidates += mark_candidates(word)
69
+
70
+ if candidates.size == 1 and cmd_candidates(word).member?(candidates[0])
71
+ append_char = ' '
72
+ else
73
+ append_char = '/'
74
+ end
75
+
76
+ return append_char, candidates
77
+ end
78
+
79
+ def self.cmd_candidates word
80
+ ret = []
81
+ prefix_regex = /^#{Regexp.escape(word)}/
82
+ MODULES.each do |name,m|
83
+ m.commands.each { |s| ret << "#{name}.#{s}" }
84
+ end
85
+ ret.concat ALIASES.keys
86
+ ret.sort.select { |e| e.match(prefix_regex) }
87
+ end
88
+
89
+ def self.child_candidates word
90
+ els, absolute, trailing_slash = Path.parse word
91
+ last = trailing_slash ? '' : (els.pop || '')
92
+ els.map! { |x| x.gsub '\\', '' }
93
+ base_loc = absolute ? Location.new($shell.fs.root) : $shell.fs.loc
94
+ found_loc = $shell.fs.traverse(base_loc, els) or return []
95
+ cur = found_loc.obj
96
+ els.unshift '' if absolute
97
+ children = Cache[cur, :children] rescue []
98
+ children.
99
+ select { |k,v| k.gsub(' ', '\\ ') =~ /^#{Regexp.escape(last)}/ }.
100
+ map { |k,v| (els+[k])*'/' }.
101
+ map { |x| x.gsub ' ', '\\ ' }
102
+ end
103
+
104
+ def self.mark_candidates word
105
+ return [] unless word.empty? || word[0..0] == '~'
106
+ prefix_regex = /^#{Regexp.escape(word[1..-1] || '')}/
107
+ $shell.fs.marks.keys.sort.grep(prefix_regex).map { |x| "~#{x}" }
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,42 @@
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
+ class RbVmomi::VIM::ClusterComputeResource
22
+ def self.ls_properties
23
+ %w(name summary.effectiveCpu summary.effectiveMemory)
24
+ end
25
+
26
+ def ls_text r
27
+ " (cluster): cpu #{r['summary.effectiveCpu']/1000} GHz, memory #{r['summary.effectiveMemory']/1000} GB"
28
+ end
29
+
30
+ # TODO add datastore, network
31
+ def children
32
+ hosts, resourcePool = collect *%w(host resourcePool)
33
+ {
34
+ 'hosts' => RVC::FakeFolder.new(self, :rvc_host_children),
35
+ 'resourcePool' => resourcePool,
36
+ }
37
+ end
38
+
39
+ def rvc_host_children
40
+ RVC::Util.collect_children self, :host
41
+ end
42
+ end