rvc 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/Rakefile +1 -1
  2. data/VERSION +1 -1
  3. data/bin/rvc +46 -70
  4. data/devel/test-dependencies.sh +4 -0
  5. data/lib/rvc.rb +5 -6
  6. data/lib/rvc/command.rb +65 -0
  7. data/lib/rvc/command_slate.rb +112 -0
  8. data/lib/rvc/completion.rb +89 -58
  9. data/lib/rvc/connection.rb +48 -0
  10. data/lib/rvc/extensions/DistributedVirtualPortgroup.rb +1 -1
  11. data/lib/rvc/extensions/DistributedVirtualSwitch.rb +3 -3
  12. data/lib/rvc/extensions/HostSystem.rb +90 -0
  13. data/lib/rvc/extensions/VirtualMachine.rb +37 -7
  14. data/lib/rvc/field.rb +59 -12
  15. data/lib/rvc/fs.rb +34 -4
  16. data/lib/rvc/inventory.rb +5 -1
  17. data/lib/rvc/modules/alarm.rb +2 -0
  18. data/lib/rvc/modules/basic.rb +66 -61
  19. data/lib/rvc/modules/cluster.rb +117 -22
  20. data/lib/rvc/modules/connection.rb +40 -0
  21. data/lib/rvc/modules/core.rb +4 -16
  22. data/lib/rvc/modules/datacenter.rb +2 -0
  23. data/lib/rvc/modules/datastore.rb +11 -78
  24. data/lib/rvc/modules/device.rb +40 -5
  25. data/lib/rvc/modules/diagnostics.rb +169 -0
  26. data/lib/rvc/modules/esxcli.rb +9 -5
  27. data/lib/rvc/modules/find.rb +5 -3
  28. data/lib/rvc/modules/host.rb +46 -3
  29. data/lib/rvc/modules/issue.rb +2 -0
  30. data/lib/rvc/modules/mark.rb +5 -3
  31. data/lib/rvc/modules/perf.rb +99 -33
  32. data/lib/rvc/modules/permissions.rb +2 -0
  33. data/lib/rvc/modules/resource_pool.rb +2 -0
  34. data/lib/rvc/modules/role.rb +3 -1
  35. data/lib/rvc/modules/snapshot.rb +12 -4
  36. data/lib/rvc/modules/statsinterval.rb +13 -11
  37. data/lib/rvc/modules/vds.rb +67 -10
  38. data/lib/rvc/modules/vim.rb +19 -53
  39. data/lib/rvc/modules/vm.rb +27 -6
  40. data/lib/rvc/modules/vm_guest.rb +490 -0
  41. data/lib/rvc/modules/vmrc.rb +60 -32
  42. data/lib/rvc/modules/vnc.rb +2 -0
  43. data/lib/rvc/namespace.rb +114 -0
  44. data/lib/rvc/option_parser.rb +12 -15
  45. data/lib/rvc/readline-ffi.rb +4 -1
  46. data/lib/rvc/ruby_evaluator.rb +84 -0
  47. data/lib/rvc/shell.rb +68 -83
  48. data/lib/rvc/uri_parser.rb +59 -0
  49. data/lib/rvc/util.rb +134 -29
  50. data/lib/rvc/{extensions/PerfCounterInfo.rb → version.rb} +2 -4
  51. data/lib/rvc/{memory_session.rb → vim.rb} +10 -32
  52. data/test/modules/foo.rb +9 -0
  53. data/test/modules/foo/bar.rb +9 -0
  54. data/test/test_completion.rb +17 -0
  55. data/test/test_fs.rb +9 -11
  56. data/test/test_help.rb +46 -0
  57. data/test/test_helper.rb +12 -0
  58. data/test/test_metric.rb +1 -2
  59. data/test/test_modules.rb +38 -0
  60. data/test/test_parse_path.rb +1 -2
  61. data/test/test_shell.rb +138 -0
  62. data/test/test_uri.rb +34 -0
  63. metadata +115 -81
  64. data/lib/rvc/extensions/PerformanceManager.rb +0 -83
  65. data/lib/rvc/filesystem_session.rb +0 -101
  66. data/lib/rvc/modules.rb +0 -138
@@ -18,40 +18,59 @@
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/vim'
22
+
21
23
  require 'tmpdir'
22
24
  require 'digest/sha2'
23
25
  require 'zip'
24
26
  require 'rbconfig'
25
27
 
26
- case RbConfig::CONFIG['host_os']
27
- when /mswin/, /mingw/
28
- VMRC_NAME = "vmware-vmrc-win32-x86-3.0.0-309851"
29
- VMRC_SHA256 = "8d8f9655121db5987bef1c2fa3a08ef2c4dd7769eb230bbd5b3ba9fd9576db56"
30
- VMRC_BIN = "vmware-vmrc.exe"
31
- when /linux/
32
- VMRC_NAME = "vmware-vmrc-linux-x86-3.0.0-309851"
33
- VMRC_SHA256 = "c86ecd9d9a1dd909a119c19d28325cb87d6e2853885d3014a7dac65175dd2ae1"
34
- VMRC_BIN = "vmware-vmrc"
35
- else
36
- VMRC_NAME = nil
37
- VMRC_SHA256 = nil
38
- VMRC_BIN = nil
39
- $stderr.puts "No VMRC available for OS #{RbConfig::CONFIG['host_os']}"
28
+ VMRC_CHECKSUMS = {
29
+ "i686-linux" => "b8f11c92853502c3dd208da79514a66d2dd4734b8564aceb9952333037859d04",
30
+ "x86_64-linux" => "86ec4bc6f23da0c33045d9bf48d9fe66ab2f426b523d8b37531646819891bf54",
31
+ "i686-mswin" => "f8455f0df038fbc8e817e4381af44fa2141496cb4e2b61f505f75bc447841949",
32
+ }
33
+
34
+ PACKAGE_VERSION = 'A'
35
+ ARCH = RbConfig::CONFIG['arch']
36
+ ON_WINDOWS = (RbConfig::CONFIG['host_os'] =~ /(mswin|mingw)/) != nil
37
+
38
+ def vmrc_url arch
39
+ "http://cloud.github.com/downloads/vmware/rvc/vmware-vmrc-public-#{arch}-#{PACKAGE_VERSION}.zip"
40
40
  end
41
41
 
42
- VMRC_BASENAME = "#{VMRC_NAME}.xpi"
43
- VMRC_URL = "http://cloud.github.com/downloads/vmware/rvc/#{VMRC_BASENAME}"
42
+ def local_vmrc_dir arch
43
+ File.join(Dir.tmpdir, "vmware-vmrc-#{arch}-#{Process.uid}-#{PACKAGE_VERSION}")
44
+ end
45
+
46
+ def check_installed
47
+ File.exists? local_vmrc_dir(ARCH)
48
+ end
44
49
 
45
- def find_local_vmrc
46
- return nil if VMRC_NAME.nil?
47
- path = File.join(Dir.tmpdir, VMRC_NAME, 'plugins', VMRC_BIN)
50
+ def find_vmrc arch, version
51
+ path = if version == '3.0.0'
52
+ basename = ON_WINDOWS ? 'vmware-vmrc.exe' : 'vmware-vmrc'
53
+ File.join(local_vmrc_dir(arch), version, 'plugins', basename)
54
+ else
55
+ fail "VMRC5 not yet supported on win32" if ON_WINDOWS
56
+ File.join(local_vmrc_dir(arch), version, 'vmware-vmrc-5.0', 'run.sh')
57
+ end
48
58
  File.exists?(path) && path
49
59
  end
50
60
 
51
- def find_vmrc
52
- find_local_vmrc || search_path('vmrc')
61
+ def choose_vmrc_version vim_version
62
+ if vim_version >= '5.1.0'
63
+ '5.0.0'
64
+ else
65
+ '3.0.0'
66
+ end
53
67
  end
54
68
 
69
+ fail unless choose_vmrc_version('4.1.0') == '3.0.0'
70
+ fail unless choose_vmrc_version('5.0.1') == '3.0.0'
71
+ fail unless choose_vmrc_version('5.1.0') == '5.0.0'
72
+ fail unless choose_vmrc_version('6.0.0') == '5.0.0'
73
+
55
74
 
56
75
  opts :view do
57
76
  summary "Spawn a VMRC"
@@ -65,10 +84,13 @@ rvc_alias :view, :vmrc
65
84
  rvc_alias :view, :v
66
85
 
67
86
  def view vms, opts
68
- unless vmrc = find_vmrc
87
+ conn = single_connection vms
88
+ vim_version = conn.serviceContent.about.version
89
+ vmrc_version = choose_vmrc_version vim_version
90
+ unless vmrc = find_vmrc(ARCH, vmrc_version)
69
91
  if opts[:install]
70
92
  install
71
- vmrc = find_vmrc
93
+ vmrc = find_vmrc(ARCH, vmrc_version)
72
94
  else
73
95
  err "VMRC not found. You may need to run vmrc.install."
74
96
  end
@@ -82,8 +104,7 @@ def view vms, opts
82
104
  end
83
105
  end
84
106
 
85
- case RbConfig::CONFIG['host_os']
86
- when /mswin/, /mingw/
107
+ if ON_WINDOWS
87
108
  def spawn_vmrc vmrc, moref, host, ticket
88
109
  err "Ruby 1.9 required" unless Process.respond_to? :spawn
89
110
  Process.spawn vmrc, '-h', host, '-p', ticket, '-M', moref,
@@ -109,10 +130,12 @@ opts :install do
109
130
  end
110
131
 
111
132
  def install
112
- zip_filename = File.join(Dir.tmpdir, VMRC_BASENAME)
113
- download VMRC_URL, zip_filename
114
- verify zip_filename, VMRC_SHA256
115
- extract zip_filename, File.join(Dir.tmpdir, VMRC_NAME)
133
+ err "No VMRC available for architecture #{ARCH}" unless VMRC_CHECKSUMS.member? ARCH
134
+ zip_filename = "#{local_vmrc_dir(ARCH)}.zip"
135
+ url = vmrc_url ARCH
136
+ download url, zip_filename
137
+ verify zip_filename, VMRC_CHECKSUMS[ARCH]
138
+ extract zip_filename, local_vmrc_dir(ARCH)
116
139
  puts "VMRC was installed successfully."
117
140
  end
118
141
 
@@ -136,6 +159,7 @@ def download url_str, dest
136
159
  io.write segment
137
160
  end
138
161
  end
162
+ res.value
139
163
  end
140
164
  rescue Exception
141
165
  err "Error downloading VMRC: #{$!.class}: #{$!.message}"
@@ -143,9 +167,13 @@ def download url_str, dest
143
167
  end
144
168
 
145
169
  def verify filename, expected_hash
146
- puts "Checking integrity..."
147
- hexdigest = Digest::SHA256.file(filename).hexdigest
148
- err "Hash mismatch" if hexdigest != VMRC_SHA256
170
+ if expected_hash == :nocheck
171
+ puts "WARNING: skipping hash check"
172
+ else
173
+ puts "Checking integrity..."
174
+ hexdigest = Digest::SHA256.file(filename).hexdigest
175
+ err "Hash mismatch: expected #{expected_hash}, found #{hexdigest}" if hexdigest != expected_hash
176
+ end
149
177
  end
150
178
 
151
179
  def extract src, dst
@@ -18,6 +18,8 @@
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/vim'
22
+
21
23
  VNC = ENV['VNC'] || search_path('tightvnc') || search_path('vncviewer') || search_path('vinagre')
22
24
 
23
25
  opts :view do
@@ -0,0 +1,114 @@
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 'rvc/command_slate'
22
+
23
+ module RVC
24
+
25
+ class Namespace
26
+ attr_reader :name, :shell, :parent, :slate, :namespaces, :commands, :aliases
27
+
28
+ def inspect
29
+ "#<RVC::Namespace:#{name}>"
30
+ end
31
+
32
+ def initialize name, shell, parent
33
+ @name = name
34
+ @shell = shell
35
+ @parent = parent
36
+ @slate = CommandSlate.new self
37
+ @namespaces = {}
38
+ @commands = {}
39
+ @aliases = {}
40
+ end
41
+
42
+ def load_code code, filename
43
+ @slate.instance_eval code, filename
44
+ end
45
+
46
+ def child_namespace name
47
+ if ns = namespaces[name]
48
+ return ns
49
+ else
50
+ namespaces[name] = Namespace.new(name, shell, self)
51
+ end
52
+ end
53
+
54
+ def lookup cmdpath, accept=Command
55
+ if cmdpath.empty?
56
+ if accept == Command
57
+ return nil
58
+ elsif accept == Namespace
59
+ return self
60
+ end
61
+ elsif cmdpath.length == 1 and accept == Command
62
+ sym = cmdpath[0]
63
+ if @aliases.member? sym
64
+ @shell.cmds.lookup @aliases[sym], accept
65
+ else
66
+ @commands[sym]
67
+ end
68
+ else
69
+ sym = cmdpath[0]
70
+ child = @namespaces[sym]
71
+ return nil if child == nil
72
+ child.lookup cmdpath[1..-1], accept
73
+ end
74
+ end
75
+
76
+ def [] sym
77
+ @namespaces[sym]
78
+ end
79
+
80
+ def method_missing sym, *args
81
+ if cmd = @commands[sym]
82
+ cmd.invoke *args
83
+ elsif args.empty? and x = self[sym]
84
+ x
85
+ else
86
+ super
87
+ end
88
+ end
89
+
90
+ def load_module_dir dir, verbose
91
+ puts "loading module directory #{dir}" if verbose
92
+ Dir.foreach(dir) do |f|
93
+ path = File.join(dir, f)
94
+ if f[0..0] == '.'
95
+ next
96
+ elsif File.directory? path
97
+ ns_name = f.to_sym
98
+ child_namespace(ns_name).load_module_dir(path, verbose)
99
+ elsif f =~ /\.rb$/
100
+ ns_name = f[0...-3].to_sym
101
+ puts "loading #{ns_name} from #{path}" if verbose
102
+ begin
103
+ code = File.read path
104
+ child_namespace(ns_name).load_code(code, path)
105
+ rescue
106
+ puts "#{$!.class} while loading #{f}: #{$!.message}"
107
+ $!.backtrace.each { |x| puts x }
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ end
@@ -19,21 +19,23 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  require 'trollop'
22
+ require 'set'
23
+
24
+ module RVC
22
25
 
23
26
  begin
24
27
  require 'chronic'
25
- RVC::HAVE_CHRONIC = true
28
+ HAVE_CHRONIC = true
26
29
  rescue LoadError
27
- RVC::HAVE_CHRONIC = false
30
+ HAVE_CHRONIC = false
28
31
  end
29
32
 
30
- module RVC
31
-
32
33
  class OptionParser < Trollop::Parser
33
34
  attr_reader :applicable
34
35
 
35
- def initialize cmd, &b
36
+ def initialize cmd, fs, &b
36
37
  @cmd = cmd
38
+ @fs = fs
37
39
  @summary = nil
38
40
  @args = []
39
41
  @has_options = false
@@ -41,8 +43,8 @@ class OptionParser < Trollop::Parser
41
43
  @seen_multi = false
42
44
  @applicable = Set.new
43
45
  super() do
44
- opt :help, "Show this message", :short => 'h'
45
46
  instance_eval &b
47
+ opt :help, "Show this message", :short => 'h'
46
48
  end
47
49
  end
48
50
 
@@ -97,7 +99,7 @@ class OptionParser < Trollop::Parser
97
99
 
98
100
  @specs.each do |name,spec|
99
101
  next unless klass = spec[:lookup] and path = opts[name]
100
- opts[name] = RVC::Util.lookup_single! path, klass
102
+ opts[name] = @fs.lookup_single! path, klass
101
103
  end
102
104
 
103
105
  argv = leftovers
@@ -136,10 +138,10 @@ class OptionParser < Trollop::Parser
136
138
 
137
139
  def postprocess_arg x, spec
138
140
  if spec[:lookup]
139
- RVC::Util.lookup!(x, spec[:lookup]).
141
+ @fs.lookup!(x, spec[:lookup]).
140
142
  tap { |a| RVC::Util.err "no matches for #{x.inspect}" if a.empty? }
141
143
  elsif spec[:lookup_parent]
142
- RVC::Util.lookup!(File.dirname(x), spec[:lookup_parent]).
144
+ @fs.lookup!(File.dirname(x), spec[:lookup_parent]).
143
145
  map { |y| [y, File.basename(x)] }.
144
146
  tap { |a| RVC::Util.err "no matches for #{File.dirname(x).inspect}" if a.empty? }
145
147
  else
@@ -163,16 +165,11 @@ end
163
165
  class RawOptionParser
164
166
  attr_reader :applicable
165
167
 
166
- def initialize cmd, summary
168
+ def initialize cmd
167
169
  @cmd = cmd
168
- @summary = summary
169
170
  @applicable = []
170
171
  end
171
172
 
172
- def summary?
173
- @summary
174
- end
175
-
176
173
  def parse args
177
174
  [args, {}]
178
175
  end
@@ -19,8 +19,10 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  require 'ffi'
22
+ require 'readline'
22
23
 
23
- module RVC::ReadlineFFI
24
+ module RVC
25
+ module ReadlineFFI
24
26
  extend FFI::Library
25
27
  libreadline = ENV['RVC_READLINE'] == nil ? 'readline.so' : ENV['RVC_READLINE']
26
28
  ffi_lib libreadline
@@ -28,6 +30,7 @@ module RVC::ReadlineFFI
28
30
  attach_variable :rl_char_is_quoted_p, :rl_char_is_quoted_p, :rl_linebuf_func_t
29
31
  attach_variable :rl_line_buffer, :rl_line_buffer, :string
30
32
  end
33
+ end
31
34
 
32
35
  unless Readline.respond_to? :line_buffer
33
36
  def Readline.line_buffer
@@ -0,0 +1,84 @@
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 'rvc/util'
22
+
23
+ module RVC
24
+
25
+ class RubyEvaluator
26
+ include RVC::Util
27
+
28
+ def initialize shell
29
+ @binding = toplevel
30
+ @shell = shell
31
+ end
32
+
33
+ def toplevel
34
+ binding
35
+ end
36
+
37
+ def do_eval input, file
38
+ begin
39
+ eval input, @binding, file
40
+ rescue Exception => e
41
+ bt = e.backtrace
42
+ bt = bt.reverse.drop_while { |x| !(x =~ /toplevel/) }.reverse
43
+ bt[-1].gsub! ':in `toplevel\'', '' if bt[-1]
44
+ e.set_backtrace bt
45
+ raise
46
+ end
47
+ end
48
+
49
+ def this
50
+ @shell.fs.cur
51
+ end
52
+
53
+ def dc
54
+ @shell.fs.lookup("~").first
55
+ end
56
+
57
+ def conn
58
+ @shell.fs.lookup("~@").first
59
+ end
60
+
61
+ def rvc_exec command
62
+ @shell.eval_command command
63
+ end
64
+
65
+ def method_missing sym, *a
66
+ if a.empty?
67
+ if @shell.cmds.namespaces.member? sym
68
+ @shell.cmds.namespaces[sym]
69
+ elsif sym.to_s =~ /_?([\w\d]+)(!?)/ && objs = @shell.fs.marks[$1]
70
+ if $2 == '!'
71
+ objs
72
+ else
73
+ objs.first
74
+ end
75
+ else
76
+ super
77
+ end
78
+ else
79
+ super
80
+ end
81
+ end
82
+ end
83
+
84
+ end