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') || search_path('vncviewer')
- 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
- #_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_nfs_datastore(hosts, opts) ⇒ Object
- #add_privilege(name, privileges) ⇒ Object
- #annotate(vm, str) ⇒ Object
- #answer(vm, str) ⇒ Object
- #bootconfig(vm, opts) ⇒ 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
- #describe(snapshot, description) ⇒ 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
- #help_summary(parser, mod_name, method_name) ⇒ 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.
- #modify_cpu(vm, opts) ⇒ Object
- #modify_memory(vm, opts) ⇒ Object
- #mv(objs) ⇒ Object
- #off(vm) ⇒ Object
- #on(vms) ⇒ Object
- #permissions(name) ⇒ Object
- #ping(vm) ⇒ Object
- #prompt_password ⇒ Object
- #quit ⇒ Object
- #reachable_ip(host) ⇒ Object
- #realdisksize(size) ⇒ 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(snapshot, name) ⇒ Object
- #reset(vms) ⇒ Object
- #revert(arg) ⇒ Object
- #rvc(vm, opts) ⇒ 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
- #ssh(vm, cmd, opts) ⇒ Object
- #standby_guest(vms) ⇒ Object
-
#stats_time(secs) ⇒ Object
see vSphere Client: Administration -> vCenter Server Settings -> Statistics -> Statistics Intervals.
- #suspend(vms) ⇒ Object
- #tasks ⇒ Object
- #type(name) ⇒ Object
- #unregister(vm) ⇒ Object
- #unused_vnc_port(ip) ⇒ Object
- #update(name, 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
563 564 565 566 567 568 569 570 |
# File 'lib/rvc/modules/vm.rb', line 563 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
572 573 574 575 576 577 578 579 580 581 582 583 584 |
# File 'lib/rvc/modules/vm.rb', line 572 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 |
#_extraConfig(vm, *regexes) ⇒ Object
450 451 452 453 454 455 456 457 |
# File 'lib/rvc/modules/vm.rb', line 450 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
443 444 445 446 447 448 |
# File 'lib/rvc/modules/vm.rb', line 443 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 64 |
# 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 break 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
552 553 554 555 556 557 558 559 560 |
# File 'lib/rvc/modules/vm.rb', line 552 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_nfs_datastore(hosts, opts) ⇒ Object
151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/rvc/modules/host.rb', line 151 def add_nfs_datastore hosts, opts hosts.each do |host| datastoreSystem, = host.collect 'configManager.datastoreSystem' spec = { :accessMode => 'readWrite', :localPath => opts[:name], :remoteHost => opts[:address], :remotePath => opts[:path] } datastoreSystem.CreateNasDatastore :spec => spec 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
682 683 684 |
# File 'lib/rvc/modules/vm.rb', line 682 def annotate vm, str vm.ReconfigVM_Task(:spec => { :annotation => str }).wait_for_completion end |
#answer(vm, str) ⇒ Object
336 337 338 339 340 341 342 |
# File 'lib/rvc/modules/vm.rb', line 336 def answer vm, str q = vm.runtime.question err "no question" unless q choice = q.choice.choiceInfo.find { |x| x.label == str } err("invalid answer") unless choice vm.AnswerVM :questionid => q.path, :answerChoice => choice.key end |
#bootconfig(vm, opts) ⇒ Object
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/rvc/modules/vm.rb', line 263 def bootconfig vm, opts if opts[:show] pp vm.config.bootOptions return end cur_delay = vm.config.bootOptions.bootDelay cur_retrydelay = vm.config.bootOptions.bootRetryDelay cur_retryenabled = vm.config.bootOptions.bootRetryEnabled if opts[:delay] and opts[:delay] != cur_delay new_delay = opts[:delay] else new_delay = cur_delay end if opts[:retrydelay] and opts[:retrydelay] != cur_retrydelay new_retrydelay = opts[:retrydelay] new_retryenabled = true else new_retrydelay = cur_retrydelay end if opts[:enablebootretry] new_retryenabled = true elsif opts[:disablebootretry] new_retryenabled = false else new_retryenabled = cur_retryenabled end spec = { :bootOptions => { :bootDelay => new_delay, :bootRetryDelay => new_retrydelay, :bootRetryEnabled => new_retryenabled, } } vm.ReconfigVM_Task(:spec => spec).wait_for_completion end |
#cd(obj) ⇒ Object
144 145 146 147 148 149 |
# File 'lib/rvc/modules/basic.rb', line 144 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
733 734 735 736 737 738 739 740 741 742 743 |
# File 'lib/rvc/modules/vm.rb', line 733 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
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/rvc/modules/vim.rb', line 183 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
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 |
# File 'lib/rvc/modules/vm.rb', line 630 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
378 379 380 |
# File 'lib/rvc/modules/vm.rb', line 378 def connect vm, label change_device_connectivity vm, label, true end |
#create(name, parent, opts) ⇒ Object
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 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/rvc/modules/vm.rb', line 143 def create dest, opts err "must specify resource pool (--pool)" unless opts[:pool] err "must specify datastore (--datastore)" unless opts[:datastore] err "memory must be a multiple of 4MB" unless opts[:memory] % 4 == 0 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 => realdisksize( 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
105 106 107 108 109 110 |
# File 'lib/rvc/modules/basic.rb', line 105 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
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 |
# File 'lib/rvc/modules/vm.rb', line 654 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 |
#describe(snapshot, description) ⇒ Object
48 49 50 |
# File 'lib/rvc/modules/snapshot.rb', line 48 def describe snapshot, description snapshot.find_tree.snapshot.RenameSnapshot :description => description end |
#destroy(objs) ⇒ Object
234 235 236 |
# File 'lib/rvc/modules/basic.rb', line 234 def destroy objs tasks objs, :Destroy end |
#devices(vm) ⇒ Object
362 363 364 365 366 367 368 369 |
# File 'lib/rvc/modules/vm.rb', line 362 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
389 390 391 |
# File 'lib/rvc/modules/vm.rb', line 389 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
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 |
# File 'lib/rvc/modules/basic.rb', line 330 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
426 427 428 |
# File 'lib/rvc/modules/vm.rb', line 426 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
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 |
# File 'lib/rvc/modules/vm.rb', line 401 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
151 152 153 |
# File 'lib/rvc/modules/basic.rb', line 151 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
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 |
# File 'lib/rvc/modules/vm.rb', line 711 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 86 87 88 89 90 |
# File 'lib/rvc/modules/basic.rb', line 44 def help path if mod = RVC::MODULES[path] opts = mod.instance_variable_get(:@opts) opts.each do |method_name,method_opts| parser = RVC::OptionParser.new method_name, &method_opts help_summary parser, path, method_name end return elsif 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 } help_summary parser, mod_name, method_name 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 |
#help_summary(parser, mod_name, method_name) ⇒ Object
92 93 94 95 96 |
# File 'lib/rvc/modules/basic.rb', line 92 def help_summary parser, mod_name, method_name 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 |
#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
217 218 219 220 221 222 223 224 |
# File 'lib/rvc/modules/basic.rb', line 217 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
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/rvc/modules/vm.rb', line 220 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
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 |
# File 'lib/rvc/modules/vm.rb', line 514 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
149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/rvc/modules/vim.rb', line 149 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
323 324 325 326 327 |
# File 'lib/rvc/modules/vm.rb', line 323 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
350 351 352 353 354 |
# File 'lib/rvc/modules/vm.rb', line 350 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
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 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/rvc/modules/basic.rb', line 164 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
612 613 614 615 616 |
# File 'lib/rvc/modules/vm.rb', line 612 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
316 317 318 319 |
# File 'lib/rvc/modules/basic.rb', line 316 def mkdir path parent = lookup_single! File.dirname(path), RbVmomi::VIM::Folder parent.CreateFolder(:name => File.basename(path)) end |
#modify_cpu(vm, opts) ⇒ Object
693 694 695 696 |
# File 'lib/rvc/modules/vm.rb', line 693 def modify_cpu vm, opts spec = { :numCPUs => opts[:num] } tasks [vm], :ReconfigVM, :spec => spec end |
#modify_memory(vm, opts) ⇒ Object
705 706 707 708 |
# File 'lib/rvc/modules/vm.rb', line 705 def modify_memory vm, opts spec = { :memoryMB => opts[:size] } tasks [vm], :ReconfigVM, :spec => spec end |
#mv(objs) ⇒ Object
274 275 276 277 278 |
# File 'lib/rvc/modules/basic.rb', line 274 def mv objs err "Destination entity missing" unless objs.size > 1 dst = objs.pop progress [dst.MoveIntoFolder_Task(:list => objs)] 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
503 504 505 506 |
# File 'lib/rvc/modules/vm.rb', line 503 def ping vm ip = vm_ip vm system_fg "ping #{Shellwords.escape ip}" end |
#prompt_password ⇒ Object
145 146 147 |
# File 'lib/rvc/modules/vim.rb', line 145 def prompt_password ask("password: ") { |q| q.echo = false } end |
#quit ⇒ Object
121 122 123 |
# File 'lib/rvc/modules/basic.rb', line 121 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 |
#realdisksize(size) ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/rvc/modules/vm.rb', line 119 def realdisksize( size ) size.downcase! if size =~ /([0-9][0-9,]*)([mgt])?/i size = $1.delete(',').to_i unit = $2 case unit when 'm' return size * 1024 when 'g' return size * ( 1024 ** 2 ) when 't' return size * ( 1024 ** 3 ) when nil return size else err "Unknown size modifer of '#{unit}'" end else err "Problem with #{size}" end 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
245 246 247 248 249 250 |
# File 'lib/rvc/modules/vm.rb', line 245 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
132 133 134 |
# File 'lib/rvc/modules/basic.rb', line 132 def reload RVC.reload_modules end |
#reload_entity(objs) ⇒ Object
246 247 248 |
# File 'lib/rvc/modules/basic.rb', line 246 def reload_entity objs objs.each(&:Reload) end |
#remove(objs, opts) ⇒ Object
59 60 61 |
# File 'lib/rvc/modules/snapshot.rb', line 59 def remove snapshot, opts tasks [snapshot.find_tree.snapshot], :RemoveSnapshot, :removeChildren => opts[:remove_children] end |
#remove_device(vm, label) ⇒ Object
593 594 595 596 597 598 599 600 601 602 |
# File 'lib/rvc/modules/vm.rb', line 593 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(snapshot, name) ⇒ 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(arg) ⇒ Object
22 23 24 25 26 27 28 |
# File 'lib/rvc/modules/snapshot.rb', line 22 def revert arg if arg.is_a? VIM::VirtualMachine tasks [arg], :RevertToCurrentSnapshot else tasks [arg.find_tree.snapshot], :RevertToSnapshot end end |
#rvc(vm, opts) ⇒ Object
485 486 487 488 489 490 491 492 493 |
# File 'lib/rvc/modules/vm.rb', line 485 def rvc vm, opts 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 #{opts[:user] && Shellwords.escape("#{opts[:user]}@")}#{Shellwords.escape ip}" system_fg(cmd, env) end |
#save_keychain_password(username, password, hostname) ⇒ Object
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/rvc/modules/vim.rb', line 163 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
437 438 439 440 |
# File 'lib/rvc/modules/vm.rb', line 437 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
259 260 261 262 263 |
# File 'lib/rvc/modules/basic.rb', line 259 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 |
#ssh(vm, cmd, opts) ⇒ Object
469 470 471 472 473 474 |
# File 'lib/rvc/modules/vm.rb', line 469 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 |
#stats_time(secs) ⇒ Object
see vSphere Client: Administration -> vCenter Server Settings -> Statistics -> Statistics Intervals
23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/rvc/modules/statsinterval.rb', line 23 def stats_time secs length = secs / 60 [[60, "Minutes"], [24, "Hours"], [7, "Days"], [4, "Weeks"], [12, "Months"]].each do |div, name| if length < div return "#{length} #{name}" end length = length / div end return "#{length} Years" end |
#suspend(vms) ⇒ Object
66 67 68 |
# File 'lib/rvc/modules/vm.rb', line 66 def suspend vms tasks vms, :SuspendVM end |
#tasks ⇒ Object
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 267 268 269 270 271 |
# File 'lib/rvc/modules/vim.rb', line 216 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
310 311 312 |
# File 'lib/rvc/modules/vm.rb', line 310 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(name, 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
745 746 747 748 749 750 751 752 753 754 755 756 757 |
# File 'lib/rvc/modules/vm.rb', line 745 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 |