Top Level Namespace
Defined Under Namespace
Modules: RVC Classes: ProgressStream
Constant Summary collapse
- URI_REGEX =
%r{ ^ (?: ([^@:]+) (?:: ([^@]*) )? @ )? ([^@:]+) (?::(.*))? $ }x
- VNC =
Copyright © 2011 VMware, Inc. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
ENV['VNC'] || search_path('vinagre') || search_path('tightvnc')
- VMRC_BASENAME =
"#{VMRC_NAME}.xpi"
- VMRC_URL =
"http://cloud.github.com/downloads/vmware/rvc/#{VMRC_BASENAME}"
- HELP_ORDER =
%w(basic vm)
Instance Method Summary collapse
- #_add_device(vm, dev) ⇒ Object
- #_add_net_device(vm, klass, network) ⇒ Object
- #_display_snapshot_tree(nodes, indent) ⇒ Object
- #_extraConfig(vm, *regexes) ⇒ Object
- #_setExtraConfig(vm, hash) ⇒ Object
- #add_host(cluster, hostname, opts) ⇒ Object
- #add_iscsi_target(hosts, opts) ⇒ Object
- #add_net_device(vm, opts) ⇒ Object
- #add_privilege(name, privileges) ⇒ Object
- #annotate(vm, str) ⇒ Object
- #answer(vm, str) ⇒ Object
- #cd(obj) ⇒ Object
- #change_device_connectivity(vm, label, connected) ⇒ Object
- #check_known_hosts(host, peer_public_key) ⇒ Object
- #clone(src, dst, opts) ⇒ Object
- #connect(uri, opts) ⇒ Object
- #create(name, parent, opts) ⇒ Object
- #cur_auth_mgr ⇒ Object
- #debug ⇒ Object
- #delete(name, opts) ⇒ Object
- #deltaize_disks(vm) ⇒ Object
- #destroy(objs) ⇒ Object
- #devices(vm) ⇒ Object
- #disconnect(connection) ⇒ Object
- #download(file, local_path) ⇒ Object
- #edit(file) ⇒ Object
- #enter_maintenance_mode(hosts, opts) ⇒ Object
- #evacuate(src, dsts, opts) ⇒ Object
- #events(obj, opts) ⇒ Object
- #exit_maintenance_mode(hosts, opts) ⇒ Object
- #extraConfig(vm, regexes) ⇒ Object
- #extract(src, dst) ⇒ Object
- #find(ds, opts) ⇒ Object
- #find_ancestor(klass) ⇒ Object
- #find_local_vmrc ⇒ Object
- #find_vmrc ⇒ Object
- #find_vmx_files(ds) ⇒ Object
- #get(objs) ⇒ Object
- #help(path) ⇒ Object
- #http_path(dc_name, ds_name, path) ⇒ Object
- #info(obj) ⇒ Object
- #insert_cdrom(vm, iso) ⇒ Object
- #install ⇒ Object
- #ip(vms) ⇒ Object
- #keychain_password(username, hostname) ⇒ Object
- #kill(vms) ⇒ Object
- #layout(vm) ⇒ Object
- #list ⇒ Object
- #ls(obj) ⇒ Object
- #mark(key, objs) ⇒ Object
- #migrate(vms, opts) ⇒ Object
-
#mkdir(datastore_path) ⇒ Object
TODO dispatch to datastore.mkdir if path is in a datastore.
- #mv(src, dst) ⇒ Object
- #off(vm) ⇒ Object
- #on(vms) ⇒ Object
- #permissions(name) ⇒ Object
- #ping(vm) ⇒ Object
- #prompt_password ⇒ Object
- #quit ⇒ Object
- #reachable_ip(host) ⇒ Object
- #reboot(hosts, opts) ⇒ Object
- #reboot_guest(vms) ⇒ Object
- #reconnect(hosts, opts) ⇒ Object
- #register(vmx_file, opts) ⇒ Object
- #reload ⇒ Object
- #reload_entity(objs) ⇒ Object
- #remove(objs, opts) ⇒ Object
- #remove_device(vm, label) ⇒ Object
- #remove_privilege(name, privileges) ⇒ Object
- #rename(old, new) ⇒ Object
- #reset(vms) ⇒ Object
- #revert(vm) ⇒ Object
- #rvc(vm) ⇒ Object
- #save_keychain_password(username, password, hostname) ⇒ Object
- #set(objs, opts) ⇒ Object
- #setExtraConfig(vm, pairs) ⇒ Object
- #shares_from_string(str) ⇒ Object
- #show(objs) ⇒ Object
- #shutdown_guest(vms) ⇒ Object
- #snapshot(vm, name, opts) ⇒ Object
- #snapshots(vm) ⇒ Object
- #ssh(vm, cmd, opts) ⇒ Object
- #standby_guest(vms) ⇒ Object
- #suspend(vms) ⇒ Object
- #tasks ⇒ Object
- #type(name) ⇒ Object
- #unregister(vm) ⇒ Object
- #unused_vnc_port(ip) ⇒ Object
- #update(pool, opts) ⇒ Object
- #upload(local_path, dest) ⇒ Object
- #verify(filename, expected_hash) ⇒ Object
- #view(vms, opts) ⇒ Object
- #vm_ip(vm) ⇒ Object
-
#vnc_client(ip, port, password) ⇒ Object
Override this to spawn a VNC client differently.
-
#vnc_password ⇒ Object
Override this if you don’t want a random password.
Instance Method Details
#_add_device(vm, dev) ⇒ Object
476 477 478 479 480 481 482 483 |
# File 'lib/rvc/modules/vm.rb', line 476 def _add_device vm, dev spec = { :deviceChange => [ { :operation => :add, :device => dev }, ] } vm.ReconfigVM_Task(:spec => spec).wait_for_completion end |
#_add_net_device(vm, klass, network) ⇒ Object
485 486 487 488 489 490 491 492 493 494 495 496 497 |
# File 'lib/rvc/modules/vm.rb', line 485 def _add_net_device vm, klass, network _add_device vm, klass.new( :key => -1, :deviceInfo => { :summary => network, :label => `uuidgen`.chomp }, :backing => VIM.VirtualEthernetCardNetworkBackingInfo( :deviceName => network ), :addressType => 'generated' ) end |
#_display_snapshot_tree(nodes, indent) ⇒ Object
542 543 544 545 546 547 |
# File 'lib/rvc/modules/vm.rb', line 542 def _display_snapshot_tree nodes, indent nodes.each do |node| puts "#{' '*indent}#{node.name} #{node.createTime}" _display_snapshot_tree node.childSnapshotList, (indent+1) end end |
#_extraConfig(vm, *regexes) ⇒ Object
364 365 366 367 368 369 370 371 |
# File 'lib/rvc/modules/vm.rb', line 364 def _extraConfig vm, *regexes vm.config.extraConfig.each do |h| if regexes.empty? or regexes.any? { |r| h[:key] =~ r } puts "#{h[:key]}: #{h[:value]}" end end nil end |
#_setExtraConfig(vm, hash) ⇒ Object
357 358 359 360 361 362 |
# File 'lib/rvc/modules/vm.rb', line 357 def _setExtraConfig vm, hash cfg = { :extraConfig => hash.map { |k,v| { :key => k, :value => v } }, } vm.ReconfigVM_Task(:spec => cfg).wait_for_completion end |
#add_host(cluster, hostname, opts) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/rvc/modules/cluster.rb', line 40 def add_host cluster, hostname, opts sslThumbprint = nil while true spec = { :force => false, :hostName => hostname, :userName => opts[:username], :password => opts[:password], :sslThumbprint => sslThumbprint, } task = cluster.AddHost_Task :spec => spec, :asConnected => false begin task.wait_for_completion rescue VIM::SSLVerifyFault puts "SSL thumbprint: #{$!.fault.thumbprint}" $stdout.write "Accept this thumbprint? (y/n) " $stdout.flush answer = $stdin.readline.chomp err "Aborted" unless answer == 'y' or answer == 'yes' sslThumbprint = $!.fault.thumbprint end end end |
#add_iscsi_target(hosts, opts) ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/rvc/modules/host.rb', line 130 def add_iscsi_target hosts, opts hosts.each do |host| puts "configuring host #{host.name}" storage = host.configManager.storageSystem storage.UpdateSoftwareInternetScsiEnabled(enabled: true) adapter = storage.storageDeviceInfo.hostBusAdapter.grep(VIM::HostInternetScsiHba)[0] storage.AddInternetScsiStaticTargets( iScsiHbaDevice: adapter.device, targets: [ VIM::HostInternetScsiHbaStaticTarget(address: opts[:address], iScsiName: opts[:iqn]) ] ) storage.RescanAllHba end end |
#add_net_device(vm, opts) ⇒ Object
465 466 467 468 469 470 471 472 473 |
# File 'lib/rvc/modules/vm.rb', line 465 def add_net_device vm, opts case opts[:type] when 'e1000' _add_net_device vm, VIM::VirtualE1000, opts[:network] when 'vmxnet3' _add_net_device vm, VIM::VirtualVmxnet3, opts[:network] else err "unknown device" end end |
#add_privilege(name, privileges) ⇒ Object
93 94 95 96 97 98 99 100 |
# File 'lib/rvc/modules/role.rb', line 93 def add_privilege name, privileges role = cur_auth_mgr.roleList.find { |x| x.name == name } err "no such role #{name.inspect}" unless role cur_auth_mgr.UpdateAuthorizationRole :roleId => role.roleId, :newName => role.name, :privIds => (role.privilege | privileges) end |
#annotate(vm, str) ⇒ Object
637 638 639 |
# File 'lib/rvc/modules/vm.rb', line 637 def annotate vm, str vm.ReconfigVM_Task(:spec => { :annotation => str }).wait_for_completion end |
#answer(vm, str) ⇒ Object
252 253 254 255 256 |
# File 'lib/rvc/modules/vm.rb', line 252 def answer vm, str choice = q.choice.choiceInfo.find { |x| x.label == str } err("invalid answer") unless choice vm.AnswerVM :questionid => q.path, :answerChoice => choice.key end |
#cd(obj) ⇒ Object
133 134 135 136 137 138 |
# File 'lib/rvc/modules/basic.rb', line 133 def cd obj $shell.fs.cd(obj) $shell.session.set_mark '', [find_ancestor(RbVmomi::VIM::Datacenter)].compact $shell.session.set_mark '@', [find_ancestor(RbVmomi::VIM)].compact $shell.delete_numeric_marks end |
#change_device_connectivity(vm, label, connected) ⇒ Object
664 665 666 667 668 669 670 671 672 673 674 |
# File 'lib/rvc/modules/vm.rb', line 664 def change_device_connectivity vm, label, connected dev = vm.config.hardware.device.find { |x| x.deviceInfo.label == label } err "no such device" unless dev dev.connectable.connected = connected spec = { :deviceChange => [ { :operation => :edit, :device => dev }, ] } vm.ReconfigVM_Task(:spec => spec).wait_for_completion end |
#check_known_hosts(host, peer_public_key) ⇒ Object
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/rvc/modules/vim.rb', line 178 def check_known_hosts host, peer_public_key known_hosts = RVC::KnownHosts.new result, arg = known_hosts.verify 'vim', host, peer_public_key.to_s if result == :not_found puts "The authenticity of host '#{host}' can't be established." puts "Public key fingerprint is #{arg}." err "Connection failed" unless agree("Are you sure you want to continue connecting (y/n)? ", true) puts "Warning: Permanently added '#{host}' (vim) to the list of known hosts" known_hosts.add 'vim', host, peer_public_key.to_s elsif result == :mismatch err "Public key fingerprint for host '#{host}' does not match #{known_hosts.filename}:#{arg}." elsif result == :ok else err "Unexpected result from known_hosts check" end end |
#clone(src, dst, opts) ⇒ Object
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 |
# File 'lib/rvc/modules/vm.rb', line 585 def clone src, dst, opts folder, name = *dst diskMoveType = nil if opts[:linked] deltaize_disks src diskMoveType = :moveChildMostDiskBacking end task = src.CloneVM_Task(:folder => folder, :name => name, :spec => { :location => { :diskMoveType => diskMoveType, :host => opts[:host], :pool => opts[:pool], }, :template => opts[:template], :powerOn => opts[:powerOn], }) progress [task] end |
#connect(uri, opts) ⇒ Object
292 293 294 |
# File 'lib/rvc/modules/vm.rb', line 292 def connect vm, label change_device_connectivity vm, label, true end |
#create(name, parent, opts) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/rvc/modules/vm.rb', line 112 def create dest, opts err "must specify resource pool (--pool)" unless opts[:pool] err "must specify datastore (--datastore)" unless opts[:datastore] vmFolder, name = *dest datastore_path = "[#{opts[:datastore].name}]" config = { :name => name, :guestId => 'otherGuest', :files => { :vmPathName => datastore_path }, :numCPUs => opts[:cpucount], :memoryMB => opts[:memory], :deviceChange => [ { :operation => :add, :device => VIM.VirtualLsiLogicController( :key => 1000, :busNumber => 0, :sharedBus => :noSharing ) }, { :operation => :add, :fileOperation => :create, :device => VIM.VirtualDisk( :key => -1, :backing => VIM.VirtualDiskFlatVer2BackingInfo( :fileName => datastore_path, :diskMode => :persistent, :thinProvisioned => true ), :controllerKey => 1000, :unitNumber => 0, :capacityInKB => opts[:disksize] ) }, { :operation => :add, :device => VIM.VirtualCdrom( :key => -2, :connectable => { :allowGuestControl => true, :connected => true, :startConnected => true, }, :backing => VIM.VirtualCdromIsoBackingInfo( :fileName => datastore_path ), :controllerKey => 200, :unitNumber => 0 ) }, { :operation => :add, :device => VIM.VirtualE1000( :key => -3, :deviceInfo => { :label => 'Network Adapter 1', :summary => 'VM Network' }, :backing => VIM.VirtualEthernetCardNetworkBackingInfo( :deviceName => 'VM Network' ), :addressType => 'generated' ) } ], } vmFolder.CreateVM_Task(:config => config, :pool => opts[:pool], :host => opts[:host]).wait_for_completion end |
#cur_auth_mgr ⇒ Object
1 2 3 4 |
# File 'lib/rvc/modules/role.rb', line 1 def cur_auth_mgr conn = $shell.fs.cur._connection conn.serviceContent. end |
#debug ⇒ Object
94 95 96 97 98 99 |
# File 'lib/rvc/modules/basic.rb', line 94 def debug debug = $shell.debug = !$shell.debug $shell.connections.each do |name,conn| conn.debug = debug end end |
#delete(name, opts) ⇒ Object
65 66 67 68 69 |
# File 'lib/rvc/modules/role.rb', line 65 def delete name, opts role = cur_auth_mgr.roleList.find { |x| x.name == name } err "no such role #{role_name.inspect}" unless role cur_auth_mgr.RemoveAuthorizationRole :roleId => role.roleId, :failIfUsed => opts[:force] end |
#deltaize_disks(vm) ⇒ Object
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 |
# File 'lib/rvc/modules/vm.rb', line 609 def deltaize_disks vm real_disks = vm.config.hardware.device.grep(VIM::VirtualDisk).select { |x| x.backing.parent == nil } unless real_disks.empty? puts "Reconfiguring source VM to use delta disks..." deviceChange = [] real_disks.each do |disk| deviceChange << { :operation => :remove, :device => disk } deviceChange << { :operation => :add, :fileOperation => :create, :device => disk.dup.tap { |x| x.backing = x.backing.dup x.backing.fileName = "[#{disk.backing.datastore.name}]" x.backing.parent = disk.backing } } end progress [vm.ReconfigVM_Task(:spec => { :deviceChange => deviceChange })] end end |
#destroy(objs) ⇒ Object
223 224 225 |
# File 'lib/rvc/modules/basic.rb', line 223 def destroy objs tasks objs, :Destroy end |
#devices(vm) ⇒ Object
276 277 278 279 280 281 282 283 |
# File 'lib/rvc/modules/vm.rb', line 276 def devices vm devs = vm.config.hardware.device devs.each do |dev| = [] << (dev.connectable.connected ? :connected : :disconnected) if dev.props.member? :connectable puts "#{dev.deviceInfo.label} (#{dev.class}): #{dev.deviceInfo.summary}; #{ * ' '}" end end |
#disconnect(connection) ⇒ Object
303 304 305 |
# File 'lib/rvc/modules/vm.rb', line 303 def disconnect vm, label change_device_connectivity vm, label, false end |
#download(file, local_path) ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/rvc/modules/vmrc.rb', line 119 def download url_str, dest puts "Downloading VMRC..." url = URI.parse(url_str) http = if ENV['http_proxy'] proxy_uri = URI.parse(ENV['http_proxy']) proxy_user, proxy_pass = proxy_uri.userinfo.split(/:/) if proxy_uri.userinfo Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_user, proxy_pass) else Net::HTTP end begin File.open(dest, 'wb') do |io| res = http.start(url.host, url.port) do |http| http.get(url.path) do |segment| io.write segment end end end rescue Exception err "Error downloading VMRC: #{$!.class}: #{$!.}" end end |
#edit(file) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/rvc/modules/mark.rb', line 43 def edit key editor = ENV['VISUAL'] || ENV['EDITOR'] || 'vi' objs = $shell.session.get_mark(key) or err "no such mark #{key.inspect}" filename = File.join(Dir.tmpdir, "rvc.#{Time.now.to_i}.#{rand(65536)}") File.open(filename, 'w') { |io| objs.each { |obj| io.puts(obj.rvc_path_str) } } begin system("#{editor} #{filename}") new_paths = File.readlines(filename).map(&:chomp) rescue return new_objs = new_paths.map { |path| lookup(path) }.inject([], &:+) mark key, new_objs ensure File.unlink filename end end |
#enter_maintenance_mode(hosts, opts) ⇒ Object
81 82 83 |
# File 'lib/rvc/modules/host.rb', line 81 def enter_maintenance_mode hosts, opts tasks hosts, :EnterMaintenanceMode, :timeout => opts[:timeout] end |
#evacuate(src, dsts, opts) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/rvc/modules/host.rb', line 39 def evacuate src, dsts, opts vim = src._connection vms = src.vm dst_hosts = dsts.map(&:host).flatten checks = ['cpu', 'software'] dst_hosts.reject! { |host| host == src || host.runtime.connectionState != 'connected' || host.runtime.inMaintenanceMode } candidates = {} vms.each do |vm| required_datastores = vm.datastore result = vim.serviceInstance.QueryVMotionCompatibility(:vm => vm, :host => dst_hosts, :compatibility => checks) result.reject! { |x| x.compatibility != checks || x.host.datastore & required_datastores != required_datastores } candidates[vm] = result.map { |x| x.host } end if candidates.any? { |vm,hosts| hosts.empty? } puts "The following VMs have no compatible vMotion destination:" candidates.select { |vm,hosts| hosts.empty? }.each { |vm,hosts| puts " #{vm.name}" } return end tasks = candidates.map do |vm,hosts| host = hosts[rand(hosts.size)] vm.MigrateVM_Task(:host => host, :priority => :defaultPriority) end progress tasks end |
#events(obj, opts) ⇒ Object
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
# File 'lib/rvc/modules/basic.rb', line 309 def events obj, opts err "'events' not supported at this level" unless obj.respond_to?(:_connection) manager = obj._connection.serviceContent.eventManager @event_details ||= Hash[manager.collect("description.eventInfo").first.collect { |d| [d.key, d] }] spec = VIM::EventFilterSpec(:entity => VIM::EventFilterSpecByEntity(:entity => obj, :recursion => "all")) collector = manager.CreateCollectorForEvents(:filter => spec) collector.SetCollectorPageSize(:maxCount => opts[:lines]) collector.latestPage.reverse.each do |event| time = event.createdTime.localtime.strftime("%m/%d/%Y %I:%M %p") category = @event_details[event.class.to_s].category puts "[#{time}] [#{category}] #{event.fullFormattedMessage.strip}" end ensure collector.DestroyCollector if collector end |
#exit_maintenance_mode(hosts, opts) ⇒ Object
92 93 94 |
# File 'lib/rvc/modules/host.rb', line 92 def exit_maintenance_mode hosts, opts tasks hosts, :ExitMaintenanceMode, :timeout => opts[:timeout] end |
#extraConfig(vm, regexes) ⇒ Object
340 341 342 |
# File 'lib/rvc/modules/vm.rb', line 340 def extraConfig vm, regexes _extraConfig(vm, *regexes.map { |x| /#{x}/ }) end |
#extract(src, dst) ⇒ Object
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/rvc/modules/vmrc.rb', line 151 def extract src, dst puts "Installing VMRC..." FileUtils.mkdir_p dst Zip::ZipFile.open(src) do |zf| zf.each do |e| dst_filename = File.join(dst, e.name) case e.ftype when :file FileUtils.mkdir_p File.dirname(dst_filename) zf.extract e.name, dst_filename File.chmod(e.unix_perms, dst_filename) if e.unix_perms when :directory FileUtils.mkdir_p dst_filename else $stderr.puts "unknown file type #{e.ftype}" end end end end |
#find(ds, opts) ⇒ Object
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 |
# File 'lib/rvc/modules/vm.rb', line 315 def find ds, opts folder = opts[:folder] rp = opts[:resource_pool] || opts[:folder]._connection.rootFolder.childEntity[0].hostFolder.childEntity[0].resourcePool paths = find_vmx_files(ds) if paths.empty? puts "no VMX files found" return end puts "Select a VMX file" path = (paths) or return folder.RegisterVM_Task(:path => path, :asTemplate => false, :pool => rp).wait_for_completion end |
#find_ancestor(klass) ⇒ Object
140 141 142 |
# File 'lib/rvc/modules/basic.rb', line 140 def find_ancestor klass $shell.fs.cur.rvc_path.map { |k,v| v }.reverse.find { |x| x.is_a? klass } end |
#find_local_vmrc ⇒ Object
45 46 47 48 49 |
# File 'lib/rvc/modules/vmrc.rb', line 45 def find_local_vmrc return nil if VMRC_NAME.nil? path = File.join(Dir.tmpdir, VMRC_NAME, 'plugins', VMRC_BIN) File.exists?(path) && path end |
#find_vmrc ⇒ Object
51 52 53 |
# File 'lib/rvc/modules/vmrc.rb', line 51 def find_vmrc find_local_vmrc || search_path('vmrc') end |
#find_vmx_files(ds) ⇒ Object
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 |
# File 'lib/rvc/modules/vm.rb', line 642 def find_vmx_files ds datastorePath = "[#{ds.name}] /" searchSpec = { :details => { :fileOwner => false, :fileSize => false, :fileType => true, :modification => false }, :query => [ VIM::VmConfigFileQuery() ] } task = ds.browser.SearchDatastoreSubFolders_Task(:datastorePath => datastorePath, :searchSpec => searchSpec) results = task.wait_for_completion files = [] results.each do |result| result.file.each do |file| files << "#{result.folderPath}/#{file.path}" end end files end |
#get(objs) ⇒ Object
22 23 24 25 26 27 28 |
# File 'lib/rvc/modules/role.rb', line 22 def get name role = cur_auth_mgr.roleList.find { |x| x.name == name } err "no such role #{role_name.inspect}" unless role puts "label: #{role.info.label}" puts "summary: #{role.info.summary}" puts "privileges: #{role.privilege.sort * ' '}" end |
#help(path) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/rvc/modules/basic.rb', line 44 def help path if tgt = RVC::ALIASES[path] fail unless tgt =~ /^(.+)\.(.+)$/ opts_block = RVC::MODULES[$1].opts_for($2.to_sym) RVC::OptionParser.new(tgt, &opts_block).educate return elsif path =~ /^(.+)\.(.+)$/ and mod = RVC::MODULES[$1] and opts_block = mod.opts_for($2.to_sym) RVC::OptionParser.new(path, &opts_block).educate return end obj = lookup_single(path) if path if obj puts "Relevant commands for #{obj.class}:" else puts "All commands:" end MODULES.sort_by do |mod_name,mod| HELP_ORDER.index(mod_name) || HELP_ORDER.size end.each do |mod_name,mod| opts = mod.instance_variable_get(:@opts) opts.each do |method_name,method_opts| parser = RVC::OptionParser.new method_name, &method_opts next unless obj.nil? or parser.applicable.any? { |x| obj.is_a? x } aliases = ALIASES.select { |k,v| v == "#{mod_name}.#{method_name}" }.map(&:first) aliases_text = aliases.empty? ? '' : " (#{aliases*', '})" puts "#{mod_name}.#{method_name}#{aliases_text}: #{parser.summary?}" if parser.summary? end end if not obj puts (<<-EOS) To see detailed help for a command, use its --help option. To show only commands relevant to a specific object, use "help /path/to/object". EOS end end |
#http_path(dc_name, ds_name, path) ⇒ Object
163 164 165 |
# File 'lib/rvc/modules/datastore.rb', line 163 def http_path dc_name, ds_name, path "/folder/#{URI.escape path}?dcPath=#{URI.escape dc_name}&dsName=#{URI.escape ds_name}" end |
#info(obj) ⇒ Object
206 207 208 209 210 211 212 213 |
# File 'lib/rvc/modules/basic.rb', line 206 def info obj puts "path: #{obj.rvc_path_str}" if obj.respond_to? :display_info obj.display_info else puts "class: #{obj.class.name}" end end |
#insert_cdrom(vm, iso) ⇒ Object
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/rvc/modules/vm.rb', line 188 def insert_cdrom vm, iso device = vm.config.hardware.device.grep(VIM::VirtualCdrom)[0] err "No virtual CDROM drive found" unless device device.backing = VIM.VirtualCdromIsoBackingInfo(:fileName => iso.datastore_path) spec = { :deviceChange => [ { :operation => :edit, :device => device } ] } vm.ReconfigVM_Task(:spec => spec) end |
#install ⇒ Object
111 112 113 114 115 116 117 |
# File 'lib/rvc/modules/vmrc.rb', line 111 def install zip_filename = File.join(Dir.tmpdir, VMRC_BASENAME) download VMRC_URL, zip_filename verify zip_filename, VMRC_SHA256 extract zip_filename, File.join(Dir.tmpdir, VMRC_NAME) puts "VMRC was installed successfully." end |
#ip(vms) ⇒ Object
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 |
# File 'lib/rvc/modules/vm.rb', line 427 def ip vms props = %w(summary.runtime.powerState summary.guest.ipAddress summary.config.annotation) connection = single_connection vms filters = vms.map do |vm| connection.propertyCollector.CreateFilter :spec => { :propSet => [{ :type => 'VirtualMachine', :all => false, :pathSet => props }], :objectSet => [{ :obj => vm }], }, :partialUpdates => false end ver = '' while not vms.empty? result = connection.propertyCollector.WaitForUpdates(:version => ver) ver = result.version vms.reject! do |vm| begin ip = vm_ip(vm) puts "#{vm.name}: #{ip}" true rescue UserError false end end end ensure filters.each(&:DestroyPropertyFilter) if filters end |
#keychain_password(username, hostname) ⇒ Object
144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/rvc/modules/vim.rb', line 144 def keychain_password username , hostname return nil unless RbConfig::CONFIG['host_os'] =~ /^darwin10/ begin require 'osx_keychain' rescue LoadError return nil end keychain = OSXKeychain.new return keychain["rvc", "#{username}@#{hostname}" ] end |
#kill(vms) ⇒ Object
239 240 241 242 243 |
# File 'lib/rvc/modules/vm.rb', line 239 def kill vms on_vms = vms.select { |x| x.summary.runtime.powerState == 'poweredOn' } off on_vms unless on_vms.empty? CMD.basic.destroy vms unless vms.empty? end |
#layout(vm) ⇒ Object
264 265 266 267 268 |
# File 'lib/rvc/modules/vm.rb', line 264 def layout vm vm.layoutEx.file.each do |f| puts "#{f.type}: #{f.name}" end end |
#list ⇒ Object
63 64 65 |
# File 'lib/rvc/modules/mark.rb', line 63 def list $shell.session.marks.each { |x| puts x } end |
#ls(obj) ⇒ Object
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/rvc/modules/basic.rb', line 153 def ls obj children = obj.children name_map = children.invert children, fake_children = children.partition { |k,v| v.is_a? VIM::ManagedEntity } i = 0 fake_children.each do |name,child| puts "#{i} #{name}#{child.ls_text(nil)}" child.rvc_link obj, name CMD.mark.mark i.to_s, [child] i += 1 end return if children.empty? filterSpec = VIM.PropertyFilterSpec(:objectSet => [], :propSet => []) filteredTypes = Set.new children.each do |name,child| filterSpec.objectSet << { :obj => child } filteredTypes << child.class end filteredTypes.each do |x| filterSpec.propSet << { :type => x.wsdl_name, :pathSet => x.ls_properties+%w(name), } end connection = single_connection(children.map { |k,v| v }) results = connection.propertyCollector.RetrieveProperties(:specSet => [filterSpec]) results.each do |r| name = name_map[r.obj] text = r.obj.ls_text(r) rescue " (error)" realname = r['name'] if name != r['name'] puts "#{i} #{name}#{realname && " [#{realname}]"}#{text}" r.obj.rvc_link obj, name CMD.mark.mark i.to_s, [r.obj] i += 1 end end |
#mark(key, objs) ⇒ Object
30 31 32 33 |
# File 'lib/rvc/modules/mark.rb', line 30 def mark key, objs err "invalid mark name" unless key =~ /^\w+$/ $shell.session.set_mark key, objs end |
#migrate(vms, opts) ⇒ Object
567 568 569 570 571 |
# File 'lib/rvc/modules/vm.rb', line 567 def migrate vms, opts tasks vms, :MigrateVM, :pool => opts[:pool], :host => opts[:host], :priority => :defaultPriority end |
#mkdir(datastore_path) ⇒ Object
TODO dispatch to datastore.mkdir if path is in a datastore
295 296 297 298 |
# File 'lib/rvc/modules/basic.rb', line 295 def mkdir path parent = lookup_single! File.dirname(path), RbVmomi::VIM::Folder parent.CreateFolder(:name => File.basename(path)) end |
#mv(src, dst) ⇒ Object
263 264 265 266 267 268 269 270 |
# File 'lib/rvc/modules/basic.rb', line 263 def mv src, dst src_dir = File.dirname(src) dst_dir = File.dirname(dst) err "cross-directory mv not yet supported" unless src_dir == dst_dir dst_name = File.basename(dst) obj = lookup(src) obj.Rename_Task(:newName => dst_name).wait_for_completion end |
#off(vm) ⇒ Object
40 41 42 |
# File 'lib/rvc/modules/vm.rb', line 40 def off vms tasks vms, :PowerOffVM end |
#on(vms) ⇒ Object
28 29 30 |
# File 'lib/rvc/modules/vm.rb', line 28 def on vms tasks vms, :PowerOnVM end |
#permissions(name) ⇒ Object
36 37 38 39 40 41 42 43 44 45 |
# File 'lib/rvc/modules/role.rb', line 36 def name role = cur_auth_mgr.roleList.find { |x| x.name == name } err "no such role #{role_name.inspect}" unless role cur_auth_mgr.RetrieveRolePermissions(roleId: role.roleId).each do |perm| flags = [] flags << 'group' if perm[:group] flags << 'propagate' if perm[:propagate] puts " #{perm[:principal]}#{flags.empty? ? '' : " (#{flags * ', '})"}: #{perm.entity.name}" end end |
#ping(vm) ⇒ Object
416 417 418 419 |
# File 'lib/rvc/modules/vm.rb', line 416 def ping vm ip = vm_ip vm system_fg "ping #{Shellwords.escape ip}" end |
#prompt_password ⇒ Object
140 141 142 |
# File 'lib/rvc/modules/vim.rb', line 140 def prompt_password ask("password: ") { |q| q.echo = false } end |
#quit ⇒ Object
110 111 112 |
# File 'lib/rvc/modules/basic.rb', line 110 def quit exit end |
#reachable_ip(host) ⇒ Object
70 71 72 73 74 75 76 77 78 79 |
# File 'lib/rvc/modules/vnc.rb', line 70 def reachable_ip host ips = host.config.network.vnic.map { |x| x.spec.ip.ipAddress } # TODO optimize ips.find do |x| begin Timeout.timeout(1) { TCPSocket.new(x, 443).close; true } rescue false end end or err("could not find IP for server #{host.name}") end |
#reboot(hosts, opts) ⇒ Object
27 28 29 |
# File 'lib/rvc/modules/host.rb', line 27 def reboot hosts, opts tasks hosts, :RebootHost, :force => opts[:force] end |
#reboot_guest(vms) ⇒ Object
96 97 98 |
# File 'lib/rvc/modules/vm.rb', line 96 def reboot_guest vms vms.each(&:RebootGuest) end |
#reconnect(hosts, opts) ⇒ Object
114 115 116 117 118 119 120 121 |
# File 'lib/rvc/modules/host.rb', line 114 def reconnect hosts, opts spec = { :force => false, :userName => opts[:username], :password => opts[:password], } tasks hosts, :ReconnectHost end |
#register(vmx_file, opts) ⇒ Object
213 214 215 216 217 218 |
# File 'lib/rvc/modules/vm.rb', line 213 def register vmx_file, opts rp = opts[:resource_pool] || opts[:folder]._connection.rootFolder.childEntity[0].hostFolder.childEntity[0].resourcePool vm = opts[:folder].RegisterVM_Task(:path => vmx_file.datastore_path, :asTemplate => false, :pool => rp).wait_for_completion end |
#reload ⇒ Object
121 122 123 |
# File 'lib/rvc/modules/basic.rb', line 121 def reload RVC.reload_modules end |
#reload_entity(objs) ⇒ Object
235 236 237 |
# File 'lib/rvc/modules/basic.rb', line 235 def reload_entity objs objs.each(&:Reload) end |
#remove(objs, opts) ⇒ Object
54 55 56 57 58 59 60 61 62 |
# File 'lib/rvc/modules/permissions.rb', line 54 def remove objs, opts conn = single_connection objs authMgr = conn.serviceContent. objs.each do |obj| authMgr.RemoveEntityPermission :entity => obj, :user => opts[:principal], :isGroup => opts[:group] end end |
#remove_device(vm, label) ⇒ Object
506 507 508 509 510 511 512 513 514 515 |
# File 'lib/rvc/modules/vm.rb', line 506 def remove_device vm, label dev = vm.config.hardware.device.find { |x| x.deviceInfo.label == label } err "no such device" unless dev spec = { :deviceChange => [ { :operation => :remove, :device => dev }, ] } vm.ReconfigVM_Task(:spec => spec).wait_for_completion end |
#remove_privilege(name, privileges) ⇒ Object
109 110 111 112 113 114 115 116 |
# File 'lib/rvc/modules/role.rb', line 109 def remove_privilege name, privileges role = cur_auth_mgr.roleList.find { |x| x.name == name } err "no such role #{name.inspect}" unless role cur_auth_mgr.UpdateAuthorizationRole :roleId => role.roleId, :newName => role.name, :privIds => (role.privilege - privileges) end |
#rename(old, new) ⇒ Object
78 79 80 81 82 83 84 |
# File 'lib/rvc/modules/role.rb', line 78 def rename old, new role = cur_auth_mgr.roleList.find { |x| x.name == old } err "no such role #{old.inspect}" unless role cur_auth_mgr.UpdateAuthorizationRole :roleId => role.roleId, :newName => new, :privIds => role.privilege end |
#reset(vms) ⇒ Object
53 54 55 |
# File 'lib/rvc/modules/vm.rb', line 53 def reset vms tasks vms, :ResetVM end |
#revert(vm) ⇒ Object
555 556 557 |
# File 'lib/rvc/modules/vm.rb', line 555 def revert vm tasks [vm], :RevertToCurrentSnapshot end |
#rvc(vm) ⇒ Object
398 399 400 401 402 403 404 405 406 |
# File 'lib/rvc/modules/vm.rb', line 398 def rvc vm ip = vm_ip vm env = Hash[%w(RBVMOMI_PASSWORD RBVMOMI_HOST RBVMOMI_USER RBVMOMI_SSL RBVMOMI_PORT RBVMOMI_FOLDER RBVMOMI_DATASTORE RBVMOMI_PATH RBVMOMI_DATACENTER RBVMOMI_COMPUTER).map { |k| [k,nil] }] cmd = "rvc #{Shellwords.escape ip}" system_fg(cmd, env) end |
#save_keychain_password(username, password, hostname) ⇒ Object
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/rvc/modules/vim.rb', line 158 def save_keychain_password username , password , hostname # only works for OSX at the minute. return false unless RbConfig::CONFIG['host_os'] =~ /^darwin10/ # check we already managed to load that gem. if defined? OSXKeychain::VERSION if agree("Save password for connection (y/n)? ", true) keychain = OSXKeychain.new # update the keychain, unless it's already set to that. keychain.set("rvc", "#{username}@#{hostname}" , password ) unless keychain["rvc", "#{username}@#{hostname}" ] == password end else return false end end |
#set(objs, opts) ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/rvc/modules/permissions.rb', line 32 def set objs, opts conn = single_connection objs authMgr = conn.serviceContent. role = authMgr.roleList.find { |x| x.name == opts[:role] } err "no such role #{role.inspect}" unless role perm = { :roleId => role.roleId, :principal => opts[:principal], :group => opts[:group], :propagate => opts[:propagate] } objs.each do |obj| authMgr.SetEntityPermissions(:entity => obj, :permission => [perm]) end end |
#setExtraConfig(vm, pairs) ⇒ Object
351 352 353 354 |
# File 'lib/rvc/modules/vm.rb', line 351 def setExtraConfig vm, pairs h = Hash[pairs.map { |x| x.split('=', 2).tap { |a| a << '' if a.size == 1 } }] _setExtraConfig vm, h end |
#shares_from_string(str) ⇒ Object
35 36 37 38 39 40 41 42 43 44 |
# File 'lib/rvc/modules/resource_pool.rb', line 35 def shares_from_string str case str when 'normal', 'low', 'high' { :level => str, :shares => 0 } when /^\d+$/ { :level => 'custom', :shares => str.to_i } else err "Invalid shares argument #{str.inspect}" end end |
#show(objs) ⇒ Object
248 249 250 251 252 |
# File 'lib/rvc/modules/basic.rb', line 248 def show objs objs.each do |obj| puts "#{obj.rvc_path_str}: #{obj.class}" end end |
#shutdown_guest(vms) ⇒ Object
76 77 78 |
# File 'lib/rvc/modules/vm.rb', line 76 def shutdown_guest vms vms.each(&:ShutdownGuest) end |
#snapshot(vm, name, opts) ⇒ Object
527 528 529 |
# File 'lib/rvc/modules/vm.rb', line 527 def snapshot vm, name, opts tasks [vm], :CreateSnapshot, :description => opts[:description], :memory => opts[:memory], :name => name, :quiesce => opts[:quiesce] end |
#snapshots(vm) ⇒ Object
538 539 540 |
# File 'lib/rvc/modules/vm.rb', line 538 def snapshots vm _display_snapshot_tree vm.snapshot.rootSnapshotList, 0 end |
#ssh(vm, cmd, opts) ⇒ Object
383 384 385 386 387 388 |
# File 'lib/rvc/modules/vm.rb', line 383 def ssh vm, cmd, opts ip = vm_ip vm cmd_arg = cmd ? Shellwords.escape(cmd) : "" ssh_cmd = "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l #{Shellwords.escape opts[:login]} #{Shellwords.escape ip} #{cmd_arg}" system_fg(ssh_cmd) end |
#standby_guest(vms) ⇒ Object
86 87 88 |
# File 'lib/rvc/modules/vm.rb', line 86 def standby_guest vms vms.each(&:StandbyGuest) end |
#suspend(vms) ⇒ Object
66 67 68 |
# File 'lib/rvc/modules/vm.rb', line 66 def suspend vms tasks vms, :SuspendVM end |
#tasks ⇒ Object
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/rvc/modules/vim.rb', line 211 def tasks conn = single_connection [$shell.fs.cur] begin view = conn.serviceContent.viewManager.CreateListView collector = conn.serviceContent.taskManager.CreateCollectorForTasks(:filter => { :time => { :beginTime => conn.serviceInstance.CurrentTime.to_datetime, # XXX :timeType => :queuedTime } }) collector.SetCollectorPageSize :maxCount => 1 filter_spec = { :objectSet => [ { :obj => view, :skip => true, :selectSet => [ VIM::TraversalSpec(:path => 'view', :type => view.class.wsdl_name) ] }, { :obj => collector }, ], :propSet => [ { :type => 'Task', :pathSet => %w(info.state) }, { :type => 'TaskHistoryCollector', :pathSet => %w(latestPage) }, ] } filter = conn.propertyCollector.CreateFilter(:partialUpdates => false, :spec => filter_spec) ver = '' loop do result = conn.propertyCollector.WaitForUpdates(:version => ver) ver = result.version result.filterSet[0].objectSet.each do |r| remove = [] case r.obj when VIM::TaskHistoryCollector infos = collector.ReadNextTasks :maxCount => 100 view.ModifyListView :add => infos.map(&:task) when VIM::Task puts "#{Time.now} #{r.obj.info.name} #{r.obj.info.entityName} #{r['info.state']}" unless r['info.state'] == nil remove << r.obj if %w(error success).member? r['info.state'] end view.ModifyListView :remove => remove unless remove.empty? end end rescue Interrupt ensure filter.DestroyPropertyFilter if filter collector.DestroyCollector if collector view.DestroyView if view end end |
#type(name) ⇒ Object
28 29 30 31 32 |
# File 'lib/rvc/modules/basic.rb', line 28 def type name klass = RbVmomi::VIM.type(name) rescue err("#{name.inspect} is not a VMODL type.") $shell.introspect_class klass nil end |
#unregister(vm) ⇒ Object
226 227 228 |
# File 'lib/rvc/modules/vm.rb', line 226 def unregister vm vm.UnregisterVM end |
#unused_vnc_port(ip) ⇒ Object
81 82 83 84 85 86 87 88 |
# File 'lib/rvc/modules/vnc.rb', line 81 def unused_vnc_port ip 10.times do port = 5901 + rand(64) unused = (TCPSocket.connect(ip, port).close rescue true) return port if unused end err "no unused port found" end |
#update(pool, opts) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/rvc/modules/resource_pool.rb', line 79 def update pool, opts spec = { :cpuAllocation => { :limit => opts[:cpu_limit], :reservation => opts[:cpu_reservation], :expandableReservation => opts[:cpu_expandable], :shares => shares_from_string(opts[:cpu_shares]), }, :memoryAllocation => { :limit => opts[:mem_limit], :reservation => opts[:mem_reservation], :expandableReservation => opts[:mem_expandable], :shares => shares_from_string(opts[:mem_shares]), }, } pool.UpdateConfig(:name => opts[:name], :spec => spec) end |
#upload(local_path, dest) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/rvc/modules/datastore.rb', line 65 def upload local_path, dest dir, datastore_filename = *dest err "local file does not exist" unless File.exists? local_path real_datastore_path = "#{dir.path}/#{datastore_filename}" main_http = dir.datastore._connection.http http = Net::HTTP.new(main_http.address, main_http.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE #http.set_debug_output $stderr http.start err "certificate mismatch" unless main_http.peer_cert.to_der == http.peer_cert.to_der File.open(local_path, 'rb') do |io| stream = ProgressStream.new(io, io.stat.size) do |s| $stdout.write "\e[0G\e[Kuploading #{s.count}/#{s.len} bytes (#{(s.count*100)/s.len}%)" $stdout.flush end headers = { 'cookie' => dir.datastore._connection., 'content-length' => io.stat.size.to_s, 'Content-Type' => 'application/octet-stream', } path = http_path dir.datastore.send(:datacenter).name, dir.datastore.name, real_datastore_path request = Net::HTTP::Put.new path, headers request.body_stream = stream res = http.request(request) $stdout.puts case res when Net::HTTPOK else err "upload failed: #{res.}" end end end |
#verify(filename, expected_hash) ⇒ Object
145 146 147 148 149 |
# File 'lib/rvc/modules/vmrc.rb', line 145 def verify filename, expected_hash puts "Checking integrity..." hexdigest = Digest::SHA256.file(filename).hexdigest err "Hash mismatch" if hexdigest != VMRC_SHA256 end |
#view(vms, opts) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/rvc/modules/vnc.rb', line 31 def view vm ip = reachable_ip vm.runtime.host extraConfig = vm.config.extraConfig already_enabled = extraConfig.find { |x| x.key == 'RemoteDisplay.vnc.enabled' && x.value.downcase == 'true' } if already_enabled puts "VNC already enabled" port = extraConfig.find { |x| x.key == 'RemoteDisplay.vnc.port' }.value password = extraConfig.find { |x| x.key == 'RemoteDisplay.vnc.password' }.value else port = unused_vnc_port ip password = vnc_password vm.ReconfigVM_Task(:spec => { :extraConfig => [ { :key => 'RemoteDisplay.vnc.enabled', :value => 'true' }, { :key => 'RemoteDisplay.vnc.password', :value => password }, { :key => 'RemoteDisplay.vnc.port', :value => port.to_s } ] }).wait_for_completion end vnc_client ip, port, password end |
#vm_ip(vm) ⇒ Object
676 677 678 679 680 681 682 683 684 685 686 687 688 |
# File 'lib/rvc/modules/vm.rb', line 676 def vm_ip vm summary = vm.summary err "VM is not powered on" unless summary.runtime.powerState == 'poweredOn' ip = if summary.guest.ipAddress and summary.guest.ipAddress != '127.0.0.1' summary.guest.ipAddress elsif note = YAML.load(summary.config.annotation) and note.is_a? Hash and note.member? 'ip' note['ip'] else err "no IP known for this VM" end end |
#vnc_client(ip, port, password) ⇒ Object
Override this to spawn a VNC client differently
98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/rvc/modules/vnc.rb', line 98 def vnc_client ip, port, password if VNC fork do $stderr.reopen("#{ENV['HOME']||'.'}/.rvc-vmrc.log", "w") Process.setpgrp exec VNC, "#{ip}:#{port}" end puts "spawning #{VNC}" puts "#{ip}:#{port} password: #{password}" else puts "no VNC client configured" puts "#{ip}:#{port} password: #{password}" end end |
#vnc_password ⇒ Object
Override this if you don’t want a random password
91 92 93 94 95 |
# File 'lib/rvc/modules/vnc.rb', line 91 def vnc_password n = 8 chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' (0...n).map { chars[rand(chars.length)].chr }.join end |