rvc 1.3.6 → 1.4.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.
@@ -0,0 +1,62 @@
1
+ opts :get do
2
+ summary "Display the permissions of a managed entity"
3
+ arg :obj, nil, :lookup => VIM::ManagedEntity, :multi => true
4
+ end
5
+
6
+ def get objs
7
+ conn = single_connection objs
8
+ authMgr = conn.serviceContent.authorizationManager
9
+ roles = Hash[authMgr.roleList.map { |x| [x.roleId, x] }]
10
+ objs.each do |obj|
11
+ puts "#{obj.name}:"
12
+ perms = authMgr.RetrieveEntityPermissions(:entity => obj, :inherited => true)
13
+ perms.each do |perm|
14
+ flags = []
15
+ flags << 'group' if perm[:group]
16
+ flags << 'propagate' if perm[:propagate]
17
+ puts " #{perm[:principal]}#{flags.empty? ? '' : " (#{flags * ', '})"}: #{roles[perm[:roleId]].name}"
18
+ end
19
+ end
20
+ end
21
+
22
+
23
+ opts :set do
24
+ summary "Set the permissions on a managed entity"
25
+ arg :obj, nil, :lookup => VIM::ManagedEntity, :multi => true
26
+ opt :role, "Role", :type => :string, :required => true
27
+ opt :principal, "Principal", :type => :string, :required => true
28
+ opt :group, "Does the principal refer to a group?"
29
+ opt :propagate, "Propagate?"
30
+ end
31
+
32
+ def set objs, opts
33
+ conn = single_connection objs
34
+ authMgr = conn.serviceContent.authorizationManager
35
+ role = authMgr.roleList.find { |x| x.name == opts[:role] }
36
+ err "no such role #{role.inspect}" unless role
37
+ perm = { :roleId => role.roleId,
38
+ :principal => opts[:principal],
39
+ :group => opts[:group],
40
+ :propagate => opts[:propagate] }
41
+ objs.each do |obj|
42
+ authMgr.SetEntityPermissions(:entity => obj, :permission => [perm])
43
+ end
44
+ end
45
+
46
+
47
+ opts :remove do
48
+ summary "Remove permissions for the given user from a managed entity"
49
+ arg :obj, nil, :lookup => VIM::ManagedEntity, :multi => true
50
+ opt :principal, "Principal", :type => :string, :required => true
51
+ opt :group, "Does the principal refer to a group?"
52
+ end
53
+
54
+ def remove objs, opts
55
+ conn = single_connection objs
56
+ authMgr = conn.serviceContent.authorizationManager
57
+ objs.each do |obj|
58
+ authMgr.RemoveEntityPermission :entity => obj,
59
+ :user => opts[:principal],
60
+ :isGroup => opts[:group]
61
+ end
62
+ end
@@ -0,0 +1,116 @@
1
+ def cur_auth_mgr
2
+ conn = $shell.fs.cur._connection
3
+ conn.serviceContent.authorizationManager
4
+ end
5
+
6
+ opts :list do
7
+ summary "List roles in the system"
8
+ end
9
+
10
+ def list
11
+ cur_auth_mgr.roleList.each do |role|
12
+ puts "#{role.name}: #{role.info.summary}"
13
+ end
14
+ end
15
+
16
+
17
+ opts :get do
18
+ summary "Display information about a role"
19
+ arg :role, "Role", :type => :string
20
+ end
21
+
22
+ def get name
23
+ role = cur_auth_mgr.roleList.find { |x| x.name == name }
24
+ err "no such role #{role_name.inspect}" unless role
25
+ puts "label: #{role.info.label}"
26
+ puts "summary: #{role.info.summary}"
27
+ puts "privileges: #{role.privilege.sort * ' '}"
28
+ end
29
+
30
+
31
+ opts :permissions do
32
+ summary "List permissions given to this role"
33
+ arg :role, "Role", :type => :string
34
+ end
35
+
36
+ def permissions name
37
+ role = cur_auth_mgr.roleList.find { |x| x.name == name }
38
+ err "no such role #{role_name.inspect}" unless role
39
+ cur_auth_mgr.RetrieveRolePermissions(roleId: role.roleId).each do |perm|
40
+ flags = []
41
+ flags << 'group' if perm[:group]
42
+ flags << 'propagate' if perm[:propagate]
43
+ puts " #{perm[:principal]}#{flags.empty? ? '' : " (#{flags * ', '})"}: #{perm.entity.name}"
44
+ end
45
+ end
46
+
47
+
48
+ opts :create do
49
+ summary "Create a new role"
50
+ arg :name, "Name of the role", :type => :string
51
+ arg :privilege, "Privileges to assign", :type => :string, :multi => true, :required => false
52
+ end
53
+
54
+ def create name, privileges
55
+ cur_auth_mgr.AddAuthorizationRole :name => name, :privIds => privileges
56
+ end
57
+
58
+
59
+ opts :delete do
60
+ summary "Delete a role"
61
+ arg :name, "Name of the role", :type => :string
62
+ opt :force, "Don't fail if the role is in use"
63
+ end
64
+
65
+ def delete name, opts
66
+ role = cur_auth_mgr.roleList.find { |x| x.name == name }
67
+ err "no such role #{role_name.inspect}" unless role
68
+ cur_auth_mgr.RemoveAuthorizationRole :roleId => role.roleId, :failIfUsed => opts[:force]
69
+ end
70
+
71
+
72
+ opts :rename do
73
+ summary "Rename a role"
74
+ arg :old, "Old name", :type => :string
75
+ arg :new, "New name", :type => :string
76
+ end
77
+
78
+ def rename old, new
79
+ role = cur_auth_mgr.roleList.find { |x| x.name == old }
80
+ err "no such role #{old.inspect}" unless role
81
+ cur_auth_mgr.UpdateAuthorizationRole :roleId => role.roleId,
82
+ :newName => new,
83
+ :privIds => role.privilege
84
+ end
85
+
86
+
87
+ opts :add_privilege do
88
+ summary "Add privileges to a role"
89
+ arg :name, "Role name", :type => :string
90
+ arg :privileges, "Privileges", :type => :string, :multi => true
91
+ end
92
+
93
+ def add_privilege name, privileges
94
+ role = cur_auth_mgr.roleList.find { |x| x.name == name }
95
+ err "no such role #{name.inspect}" unless role
96
+ cur_auth_mgr.UpdateAuthorizationRole :roleId => role.roleId,
97
+ :newName => role.name,
98
+ :privIds => (role.privilege | privileges)
99
+
100
+ end
101
+
102
+
103
+ opts :remove_privilege do
104
+ summary "Remove privileges from a role"
105
+ arg :name, "Role name", :type => :string
106
+ arg :privileges, "Privileges", :type => :string, :multi => true
107
+ end
108
+
109
+ def remove_privilege name, privileges
110
+ role = cur_auth_mgr.roleList.find { |x| x.name == name }
111
+ err "no such role #{name.inspect}" unless role
112
+ cur_auth_mgr.UpdateAuthorizationRole :roleId => role.roleId,
113
+ :newName => role.name,
114
+ :privIds => (role.privilege - privileges)
115
+
116
+ end
@@ -37,7 +37,6 @@ URI_REGEX = %r{
37
37
  opts :connect do
38
38
  summary 'Open a connection to ESX/VC'
39
39
  arg :uri, "Host to connect to"
40
- opt :insecure, "don't verify ssl certificate", :short => 'k', :default => (ENV['RBVMOMI_INSECURE'] == '1')
41
40
  opt :rev, "Override protocol revision", :type => :string
42
41
  end
43
42
 
@@ -51,46 +50,32 @@ def connect uri, opts
51
50
  password = match[2] || ENV['RBVMOMI_PASSWORD']
52
51
  host = match[3]
53
52
  path = match[4]
54
- insecure = opts[:insecure]
53
+ bad_cert = false
55
54
 
56
55
  vim = nil
57
56
  loop do
58
57
  begin
59
58
  vim = RbVmomi::VIM.new :host => host,
60
- :port => 443,
61
- :path => '/sdk',
62
- :ns => 'urn:vim25',
63
- :rev => (opts[:rev]||'4.0'),
64
- :ssl => true,
65
- :insecure => insecure
59
+ :port => 443,
60
+ :path => '/sdk',
61
+ :ns => 'urn:vim25',
62
+ :rev => (opts[:rev]||'4.0'),
63
+ :ssl => true,
64
+ :insecure => bad_cert
66
65
  break
67
66
  rescue OpenSSL::SSL::SSLError
68
- err "Connection failed" unless prompt_cert_insecure
69
- insecure = true
67
+ # We'll check known_hosts next
68
+ raise if bad_cert
69
+ bad_cert = true
70
70
  rescue Errno::EHOSTUNREACH, SocketError
71
71
  err $!.message
72
72
  end
73
73
  end
74
74
 
75
- if opts[:really_insecure]
76
- result = :ok
77
- else
75
+ if bad_cert
76
+ # Fall back to SSH-style known_hosts
78
77
  peer_public_key = vim.http.peer_cert.public_key
79
- known_hosts = RVC::KnownHosts.new
80
- result, arg = known_hosts.verify 'vim', host, peer_public_key.to_s
81
- end
82
-
83
- if result == :not_found
84
- puts "The authenticity of host '#{host}' can't be established."
85
- puts "Public key fingerprint is #{arg}."
86
- err "Connection failed" unless prompt_cert_unknown
87
- puts "Warning: Permanently added '#{host}' (vim) to the list of known hosts"
88
- known_hosts.add 'vim', host, peer_public_key.to_s
89
- elsif result == :mismatch
90
- err "Public key fingerprint for host '#{host}' does not match #{known_hosts.filename}:#{arg}."
91
- elsif result == :ok
92
- else
93
- err "Unexpected result from known_hosts check"
78
+ check_known_hosts(host, peer_public_key)
94
79
  end
95
80
 
96
81
  unless opts[:rev]
@@ -107,6 +92,15 @@ def connect uri, opts
107
92
  puts "Using default username #{username.inspect}."
108
93
  end
109
94
 
95
+ # If we already have a password, then don't bother querying if we have an OSX
96
+ # keychain entry for it. If we have either of them, use it.
97
+ # So will use command line first, then ENV, then keychain on OSX, then prompt.
98
+ loaded_from_keychain = nil
99
+ password = keychain_password( username , host ) if password.nil?
100
+ if not password.nil?
101
+ loaded_from_keychain = password
102
+ end
103
+
110
104
  password_given = password != nil
111
105
  loop do
112
106
  begin
@@ -126,6 +120,9 @@ def connect uri, opts
126
120
  end
127
121
  end
128
122
 
123
+ # if we got to here, save the password, unless we loaded it from keychain
124
+ save_keychain_password( username , password , host ) unless loaded_from_keychain == password
125
+
129
126
  # Stash the address we used to connect so VMRC can use it.
130
127
  vim.define_singleton_method(:_host) { host }
131
128
 
@@ -134,16 +131,136 @@ def connect uri, opts
134
131
  conn_name.succ! while $shell.connections.member? conn_name
135
132
 
136
133
  $shell.connections[conn_name] = vim
134
+ $shell.session.set_connection conn_name,
135
+ 'host' => host,
136
+ 'username' => username,
137
+ 'rev' => opts[:rev]
137
138
  end
138
139
 
139
140
  def prompt_password
140
141
  ask("password: ") { |q| q.echo = false }
141
142
  end
142
143
 
143
- def prompt_cert_insecure
144
- agree("SSL certificate verification failed. Connect anyway (y/n)? ", true)
144
+ def keychain_password username , hostname
145
+ return nil unless RbConfig::CONFIG['host_os'] =~ /^darwin10/
146
+
147
+ begin
148
+ require 'osx_keychain'
149
+ rescue LoadError
150
+ return nil
151
+ end
152
+
153
+ keychain = OSXKeychain.new
154
+ return keychain["rvc", "#{username}@#{hostname}" ]
155
+
156
+ end
157
+
158
+ def save_keychain_password username , password , hostname
159
+ # only works for OSX at the minute.
160
+ return false unless RbConfig::CONFIG['host_os'] =~ /^darwin10/
161
+
162
+ # check we already managed to load that gem.
163
+ if defined? OSXKeychain::VERSION
164
+
165
+ if agree("Save password for connection (y/n)? ", true)
166
+ keychain = OSXKeychain.new
167
+
168
+ # update the keychain, unless it's already set to that.
169
+ keychain.set("rvc", "#{username}@#{hostname}" , password ) unless
170
+ keychain["rvc", "#{username}@#{hostname}" ] == password
171
+ end
172
+ else
173
+ return false
174
+ end
145
175
  end
146
176
 
147
- def prompt_cert_unknown
148
- agree("Are you sure you want to continue connecting (y/n)? ", true)
177
+
178
+ def check_known_hosts host, peer_public_key
179
+ known_hosts = RVC::KnownHosts.new
180
+ result, arg = known_hosts.verify 'vim', host, peer_public_key.to_s
181
+
182
+ if result == :not_found
183
+ puts "The authenticity of host '#{host}' can't be established."
184
+ puts "Public key fingerprint is #{arg}."
185
+ err "Connection failed" unless agree("Are you sure you want to continue connecting (y/n)? ", true)
186
+ puts "Warning: Permanently added '#{host}' (vim) to the list of known hosts"
187
+ known_hosts.add 'vim', host, peer_public_key.to_s
188
+ elsif result == :mismatch
189
+ err "Public key fingerprint for host '#{host}' does not match #{known_hosts.filename}:#{arg}."
190
+ elsif result == :ok
191
+ else
192
+ err "Unexpected result from known_hosts check"
193
+ end
194
+ end
195
+
196
+ class RbVmomi::VIM
197
+ def display_info
198
+ puts serviceContent.about.fullName
199
+ end
200
+
201
+ def _connection
202
+ self
203
+ end
204
+ end
205
+
206
+
207
+ opts :tasks do
208
+ summary "Watch tasks in progress"
209
+ end
210
+
211
+ def tasks
212
+ conn = single_connection [$shell.fs.cur]
213
+
214
+ begin
215
+ view = conn.serviceContent.viewManager.CreateListView
216
+
217
+ collector = conn.serviceContent.taskManager.CreateCollectorForTasks(:filter => {
218
+ :time => {
219
+ :beginTime => conn.serviceInstance.CurrentTime.to_datetime, # XXX
220
+ :timeType => :queuedTime
221
+ }
222
+ })
223
+ collector.SetCollectorPageSize :maxCount => 1
224
+
225
+ filter_spec = {
226
+ :objectSet => [
227
+ {
228
+ :obj => view,
229
+ :skip => true,
230
+ :selectSet => [
231
+ VIM::TraversalSpec(:path => 'view', :type => view.class.wsdl_name)
232
+ ]
233
+ },
234
+ { :obj => collector },
235
+ ],
236
+ :propSet => [
237
+ { :type => 'Task', :pathSet => %w(info.state) },
238
+ { :type => 'TaskHistoryCollector', :pathSet => %w(latestPage) },
239
+ ]
240
+ }
241
+ filter = conn.propertyCollector.CreateFilter(:partialUpdates => false, :spec => filter_spec)
242
+
243
+ ver = ''
244
+ loop do
245
+ result = conn.propertyCollector.WaitForUpdates(:version => ver)
246
+ ver = result.version
247
+ result.filterSet[0].objectSet.each do |r|
248
+ remove = []
249
+ case r.obj
250
+ when VIM::TaskHistoryCollector
251
+ infos = collector.ReadNextTasks :maxCount => 100
252
+ view.ModifyListView :add => infos.map(&:task)
253
+ when VIM::Task
254
+ puts "#{Time.now} #{r.obj.info.name} #{r.obj.info.entityName} #{r['info.state']}" unless r['info.state'] == nil
255
+ remove << r.obj if %w(error success).member? r['info.state']
256
+ end
257
+ view.ModifyListView :remove => remove unless remove.empty?
258
+ end
259
+ end
260
+ rescue Interrupt
261
+ ensure
262
+ filter.DestroyPropertyFilter if filter
263
+ collector.DestroyCollector if collector
264
+ view.DestroyView if view
265
+ end
149
266
  end
@@ -104,6 +104,9 @@ opts :create do
104
104
  opt :pool, "Resource pool", :short => 'p', :type => :string, :lookup => VIM::ResourcePool
105
105
  opt :host, "Host", :short => 'h', :type => :string, :lookup => VIM::HostSystem
106
106
  opt :datastore, "Datastore", :short => 'd', :type => :string, :lookup => VIM::Datastore
107
+ opt :disksize, "Size in KB of primary disk", :short => 's', :type => :int, :default => 4000000
108
+ opt :memory, "Size in MB of memory", :short => 'm', :type => :int, :default => 128
109
+ opt :cpucount, "Number of CPUs", :short => 'c', :type => :int, :default => 1
107
110
  end
108
111
 
109
112
  def create dest, opts
@@ -115,8 +118,8 @@ def create dest, opts
115
118
  :name => name,
116
119
  :guestId => 'otherGuest',
117
120
  :files => { :vmPathName => datastore_path },
118
- :numCPUs => 1,
119
- :memoryMB => 128,
121
+ :numCPUs => opts[:cpucount],
122
+ :memoryMB => opts[:memory],
120
123
  :deviceChange => [
121
124
  {
122
125
  :operation => :add,
@@ -137,7 +140,7 @@ def create dest, opts
137
140
  ),
138
141
  :controllerKey => 1000,
139
142
  :unitNumber => 0,
140
- :capacityInKB => 4000000
143
+ :capacityInKB => opts[:disksize]
141
144
  )
142
145
  }, {
143
146
  :operation => :add,
@@ -516,10 +519,13 @@ opts :snapshot do
516
519
  summary "Snapshot a VM"
517
520
  arg :vm, nil, :lookup => VIM::VirtualMachine
518
521
  arg :name, "Name of new snapshot"
522
+ opt :description, "Description", :short => 'd', :default => ""
523
+ opt :quiesce, "Quiesce", :short => 'q', :default => false
524
+ opt :memory, "Memory", :short => 'm', :default => true
519
525
  end
520
526
 
521
- def snapshot vm, name
522
- tasks [vm], :CreateSnapshot, :memory => true, :name => name, :quiesce => false
527
+ def snapshot vm, name, opts
528
+ tasks [vm], :CreateSnapshot, :description => opts[:description], :memory => opts[:memory], :name => name, :quiesce => opts[:quiesce]
523
529
  end
524
530
 
525
531
 
@@ -648,7 +654,7 @@ def find_vmx_files ds
648
654
  files = []
649
655
  results.each do |result|
650
656
  result.file.each do |file|
651
- files << result.folderPath + file.path
657
+ files << "#{result.folderPath}/#{file.path}"
652
658
  end
653
659
  end
654
660
 
@@ -33,6 +33,9 @@ when /linux/
33
33
  VMRC_SHA256 = "c86ecd9d9a1dd909a119c19d28325cb87d6e2853885d3014a7dac65175dd2ae1"
34
34
  VMRC_BIN = "vmware-vmrc"
35
35
  else
36
+ VMRC_NAME = nil
37
+ VMRC_SHA256 = nil
38
+ VMRC_BIN = nil
36
39
  $stderr.puts "No VMRC available for OS #{RbConfig::CONFIG['host_os']}"
37
40
  end
38
41
 
@@ -40,6 +43,7 @@ VMRC_BASENAME = "#{VMRC_NAME}.xpi"
40
43
  VMRC_URL = "http://cloud.github.com/downloads/vmware/rvc/#{VMRC_BASENAME}"
41
44
 
42
45
  def find_local_vmrc
46
+ return nil if VMRC_NAME.nil?
43
47
  path = File.join(Dir.tmpdir, VMRC_NAME, 'plugins', VMRC_BIN)
44
48
  File.exists?(path) && path
45
49
  end
@@ -52,6 +56,7 @@ end
52
56
  opts :view do
53
57
  summary "Spawn a VMRC"
54
58
  text "The VMware Remote Console allows you to interact with a VM's virtual mouse, keyboard, and screen."
59
+ opt :install, "Automatically install VMRC", :short => 'i'
55
60
  arg :vm, nil, :lookup => VIM::VirtualMachine, :multi => true
56
61
  end
57
62
 
@@ -59,8 +64,16 @@ rvc_alias :view
59
64
  rvc_alias :view, :vmrc
60
65
  rvc_alias :view, :v
61
66
 
62
- def view vms
63
- err "VMRC not found" unless vmrc = find_vmrc
67
+ def view vms, opts
68
+ unless vmrc = find_vmrc
69
+ if opts[:install]
70
+ install
71
+ vmrc = find_vmrc
72
+ else
73
+ err "VMRC not found. You may need to run vmrc.install."
74
+ end
75
+ end
76
+
64
77
  vms.each do |vm|
65
78
  moref = vm._ref
66
79
  ticket = vm._connection.serviceInstance.content.sessionManager.AcquireCloneTicket
@@ -143,6 +156,7 @@ def extract src, dst
143
156
  dst_filename = File.join(dst, e.name)
144
157
  case e.ftype
145
158
  when :file
159
+ FileUtils.mkdir_p File.dirname(dst_filename)
146
160
  zf.extract e.name, dst_filename
147
161
  File.chmod(e.unix_perms, dst_filename) if e.unix_perms
148
162
  when :directory
data/lib/rvc/modules.rb CHANGED
@@ -18,12 +18,16 @@
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/util'
22
+
21
23
  module RVC
22
24
 
23
25
  ALIASES = {}
24
26
  MODULES = {}
25
27
 
26
28
  class CmdModule
29
+ include RVC::Util
30
+
27
31
  def initialize module_name
28
32
  @module_name = module_name
29
33
  @opts = {}
@@ -74,6 +74,8 @@ class OptionParser < Trollop::Parser
74
74
  end
75
75
  end
76
76
  @args << [name,spec]
77
+ description = "Path to a" if description == nil and spec[:lookup]
78
+ description = "Child of a" if description == nil and spec[:lookup_parent]
77
79
  text " #{name}: " + [description, spec[:lookup], spec[:lookup_parent]].compact.join(' ')
78
80
  end
79
81
 
@@ -82,41 +84,41 @@ class OptionParser < Trollop::Parser
82
84
 
83
85
  @specs.each do |name,spec|
84
86
  next unless klass = spec[:lookup] and path = opts[name]
85
- opts[name] = lookup_single! path, klass
87
+ opts[name] = RVC::Util.lookup_single! path, klass
86
88
  end
87
89
 
88
90
  argv = leftovers
89
91
  args = []
90
92
  @args.each do |name,spec|
91
93
  if spec[:multi]
92
- err "missing argument '#{name}'" if spec[:required] and argv.empty?
94
+ RVC::Util.err "missing argument '#{name}'" if spec[:required] and argv.empty?
93
95
  a = (argv.empty? ? spec[:default] : argv.dup)
94
96
  a = a.map { |x| postprocess_arg x, spec }.inject([], :+)
95
- err "no matches for '#{name}'" if spec[:required] and a.empty?
97
+ RVC::Util.err "no matches for '#{name}'" if spec[:required] and a.empty?
96
98
  args << a
97
99
  argv.clear
98
100
  else
99
101
  x = argv.shift
100
- err "missing argument '#{name}'" if spec[:required] and x.nil?
102
+ RVC::Util.err "missing argument '#{name}'" if spec[:required] and x.nil?
101
103
  x = spec[:default] if x.nil?
102
104
  a = x.nil? ? [] : postprocess_arg(x, spec)
103
- err "more than one match for #{name}" if a.size > 1
104
- err "no match for '#{name}'" if spec[:required] and a.empty?
105
+ RVC::Util.err "more than one match for #{name}" if a.size > 1
106
+ RVC::Util.err "no match for '#{name}'" if spec[:required] and a.empty?
105
107
  args << a.first
106
108
  end
107
109
  end
108
- err "too many arguments" unless argv.empty?
110
+ RVC::Util.err "too many arguments" unless argv.empty?
109
111
  return args, opts
110
112
  end
111
113
 
112
114
  def postprocess_arg x, spec
113
115
  if spec[:lookup]
114
- lookup!(x, spec[:lookup]).
115
- tap { |a| err "no matches for #{x.inspect}" if a.empty? }
116
+ RVC::Util.lookup!(x, spec[:lookup]).
117
+ tap { |a| RVC::Util.err "no matches for #{x.inspect}" if a.empty? }
116
118
  elsif spec[:lookup_parent]
117
- lookup!(File.dirname(x), spec[:lookup_parent]).
119
+ RVC::Util.lookup!(File.dirname(x), spec[:lookup_parent]).
118
120
  map { |y| [y, File.basename(x)] }.
119
- tap { |a| err "no matches for #{File.dirname(x).inspect}" if a.empty? }
121
+ tap { |a| RVC::Util.err "no matches for #{File.dirname(x).inspect}" if a.empty? }
120
122
  else
121
123
  [x]
122
124
  end
data/lib/rvc/shell.rb CHANGED
@@ -21,10 +21,11 @@
21
21
  module RVC
22
22
 
23
23
  class Shell
24
- attr_reader :fs, :connections
24
+ attr_reader :fs, :connections, :session
25
25
  attr_accessor :debug
26
26
 
27
- def initialize
27
+ def initialize session
28
+ @session = session
28
29
  @persist_ruby = false
29
30
  @fs = RVC::FS.new RVC::RootNode.new
30
31
  @ruby_evaluator = RubyEvaluator.new @fs
@@ -39,7 +40,7 @@ class Shell
39
40
  end
40
41
 
41
42
  if input[0..0] == '!'
42
- system_fg input[1..-1]
43
+ RVC::Util.system_fg input[1..-1]
43
44
  return
44
45
  end
45
46
 
@@ -57,13 +58,13 @@ class Shell
57
58
  end
58
59
  rescue SystemExit, IOError
59
60
  raise
60
- rescue UserError, RuntimeError, RbVmomi::Fault
61
+ rescue RVC::Util::UserError, RuntimeError, RbVmomi::Fault
61
62
  if ruby or debug
62
63
  puts "#{$!.class}: #{$!.message}"
63
64
  puts $!.backtrace * "\n"
64
65
  else
65
66
  case $!
66
- when RbVmomi::Fault, UserError
67
+ when RbVmomi::Fault, RVC::Util::UserError
67
68
  puts $!.message
68
69
  else
69
70
  puts "#{$!.class}: #{$!.message}"
@@ -78,20 +79,20 @@ class Shell
78
79
  def eval_command input
79
80
  cmd, *args = Shellwords.shellwords(input)
80
81
  return unless cmd
81
- err "invalid command" unless cmd.is_a? String
82
+ RVC::Util.err "invalid command" unless cmd.is_a? String
82
83
  case cmd
83
84
  when RVC::FS::MARK_PATTERN
84
- CMD.basic.cd lookup_single(cmd)
85
+ CMD.basic.cd RVC::Util.lookup_single(cmd)
85
86
  else
86
87
  if cmd.include? '.'
87
88
  module_name, cmd, = cmd.split '.'
88
89
  elsif ALIASES.member? cmd
89
90
  module_name, cmd, = ALIASES[cmd].split '.'
90
91
  else
91
- err "unknown alias #{cmd}"
92
+ RVC::Util.err "unknown alias #{cmd}"
92
93
  end
93
94
 
94
- m = MODULES[module_name] or err("unknown module #{module_name}")
95
+ m = MODULES[module_name] or RVC::Util.err("unknown module #{module_name}")
95
96
 
96
97
  opts_block = m.opts_for(cmd.to_sym)
97
98
  parser = RVC::OptionParser.new cmd, &opts_block
@@ -123,7 +124,11 @@ class Shell
123
124
  end
124
125
 
125
126
  def prompt
126
- "#{@fs.display_path}#{$terminal.color(@persist_ruby ? '~' : '>', :yellow)} "
127
+ if false
128
+ "#{@fs.display_path}#{$terminal.color(@persist_ruby ? '~' : '>', :yellow)} "
129
+ else
130
+ "#{@fs.display_path}#{@persist_ruby ? '~' : '>'} "
131
+ end
127
132
  end
128
133
 
129
134
  def introspect_object obj
@@ -175,6 +180,10 @@ class Shell
175
180
  puts klass
176
181
  end
177
182
  end
183
+
184
+ def delete_numeric_marks
185
+ @session.marks.grep(/^\d+$/).each { |x| @session.set_mark x, nil }
186
+ end
178
187
  end
179
188
 
180
189
  class RubyEvaluator
@@ -204,7 +213,7 @@ class RubyEvaluator
204
213
  if a.empty?
205
214
  if MODULES.member? str
206
215
  MODULES[str]
207
- elsif str =~ /_?([\w\d]+)(!?)/ && objs = @fs.marks[$1]
216
+ elsif str =~ /_?([\w\d]+)(!?)/ && objs = $shell.session.get_mark($1)
208
217
  if $2 == '!'
209
218
  objs
210
219
  else