Class: Support::GuestOperations
- Inherits:
-
Object
- Object
- Support::GuestOperations
- Defined in:
- lib/train-vsphere-gom/guest_operations.rb
Overview
Encapsulate VMware Tools GOM interaction, originally inspired by github:dnuffer/raidopt
Constant Summary collapse
- SHELL_TYPES =
{ linux: { suffix: ".sh", cmd: "/bin/sh", args: '-c ". %<cmdfile>s" > %<outfile>s 2> %<errfile>s', }, # BUG: Includes prompt cmd: { suffix: ".cmd", cmd: "cmd.exe", args: '/s /c "%<cmdfile>s" > %<outfile>s 2> %<errfile>s', }, # Invoking PS via cmd seems the only way to get this to work powershell: { suffix: ".ps1", cmd: "cmd.exe", args: "/C powershell -NonInteractive -ExecutionPolicy Bypass -File %<cmdfile>s >%<outfile>s 2>%<errfile>s", }, }.freeze
Instance Attribute Summary collapse
-
#gom ⇒ Object
writeonly
Sets the attribute gom.
-
#logger ⇒ Object
writeonly
Sets the attribute logger.
Instance Method Summary collapse
-
#delete_directory(remote_dir, recursive: true) ⇒ Object
Required privilege: VirtualMachine.GuestOperations.Modify.
-
#delete_file(remote_file) ⇒ Object
Required privilege: VirtualMachine.GuestOperations.Modify.
-
#download_file(remote_file, local_file) ⇒ Object
Required privilege: VirtualMachine.GuestOperations.Modify.
-
#exist?(remote_file) ⇒ Boolean
Required privilege: VirtualMachine.GuestOperations.Query.
-
#initialize(vim, vm, username, password, ssl_verify: true, logger: nil, quick: false) ⇒ GuestOperations
constructor
A new instance of GuestOperations.
- #read_file(remote_file) ⇒ Object
-
#run(command, shell_type: :auto, timeout: 60.0) ⇒ Object
Required privileges: VirtualMachine.GuestOperations.Execute, VirtualMachine.GuestOperations.Modify.
-
#upload_file(local_file, remote_file) ⇒ Object
Required privilege: VirtualMachine.GuestOperations.Modify.
-
#write_file(remote_file, contents) ⇒ Object
Required privilege: VirtualMachine.GuestOperations.Modify.
-
#write_temp_file(contents, prefix: "", suffix: "") ⇒ Object
Required privilege: VirtualMachine.GuestOperations.Modify.
Constructor Details
#initialize(vim, vm, username, password, ssl_verify: true, logger: nil, quick: false) ⇒ GuestOperations
Returns a new instance of GuestOperations.
31 32 33 34 35 36 37 38 39 |
# File 'lib/train-vsphere-gom/guest_operations.rb', line 31 def initialize(vim, vm, username, password, ssl_verify: true, logger: nil, quick: false) @vim = vim @vm = vm @guest_auth = RbVmomi::VIM::NamePasswordAuthentication(interactiveSession: false, username: username, password: password) @ssl_verify = ssl_verify @quick = quick end |
Instance Attribute Details
#gom=(value) ⇒ Object
Sets the attribute gom
29 30 31 |
# File 'lib/train-vsphere-gom/guest_operations.rb', line 29 def gom=(value) @gom = value end |
#logger=(value) ⇒ Object
Sets the attribute logger
29 30 31 |
# File 'lib/train-vsphere-gom/guest_operations.rb', line 29 def logger=(value) @logger = value end |
Instance Method Details
#delete_directory(remote_dir, recursive: true) ⇒ Object
Required privilege: VirtualMachine.GuestOperations.Modify
174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/train-vsphere-gom/guest_operations.rb', line 174 def delete_directory(remote_dir, recursive: true) logger.debug format("Deleting remote directory %s", remote_dir) gom.fileManager.DeleteDirectoryInGuest(vm: @vm, auth: @guest_auth, directoryPath: remote_dir, recursive: recursive) true rescue RbVmomi::Fault => e raise if e..start_with? "NotADirectory:" false end |
#delete_file(remote_file) ⇒ Object
Required privilege: VirtualMachine.GuestOperations.Modify
161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/train-vsphere-gom/guest_operations.rb', line 161 def delete_file(remote_file) logger.debug format("Deleting remote file %s", remote_file) gom.fileManager.DeleteFileInGuest(vm: @vm, auth: @guest_auth, filePath: remote_file) true rescue RbVmomi::Fault => e raise unless e..start_with? "FileNotFound:" false end |
#download_file(remote_file, local_file) ⇒ Object
Required privilege: VirtualMachine.GuestOperations.Modify
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/train-vsphere-gom/guest_operations.rb', line 144 def download_file(remote_file, local_file) logger.debug format("Downloading remote file %s to %s", local_file, remote_file) info = gom.fileManager.InitiateFileTransferFromGuest(vm: @vm, auth: @guest_auth, guestFilePath: remote_file) uri = URI.parse(info.url) request = Net::HTTP::Get.new(uri.request_uri) response = http_request(info.url, request) if response.body.size != info.size raise format("Downloaded file has different size than reported: %s (%d bytes instead of %d bytes)", remote_file, response.body.size, info.size) end local_file.nil? ? response.body : File.open(local_file, "w") { |file| file.write(response.body) } end |
#exist?(remote_file) ⇒ Boolean
Required privilege: VirtualMachine.GuestOperations.Query
83 84 85 86 87 88 89 90 91 |
# File 'lib/train-vsphere-gom/guest_operations.rb', line 83 def exist?(remote_file) logger.debug format("Checking for remote file %s", remote_file) gom.fileManager.ListFilesInGuest(vm: @vm, auth: @guest_auth, filePath: remote_file) true rescue RbVmomi::Fault false end |
#read_file(remote_file) ⇒ Object
93 94 95 96 97 |
# File 'lib/train-vsphere-gom/guest_operations.rb', line 93 def read_file(remote_file) return "" unless @quick || exist?(remote_file) download_file(remote_file, nil) || "" end |
#run(command, shell_type: :auto, timeout: 60.0) ⇒ Object
Required privileges: VirtualMachine.GuestOperations.Execute, VirtualMachine.GuestOperations.Modify
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 73 74 75 76 77 78 79 80 |
# File 'lib/train-vsphere-gom/guest_operations.rb', line 42 def run(command, shell_type: :auto, timeout: 60.0) logger.debug format("Running `%s` remotely", command) if shell_type == :auto shell_type = :linux if linux? shell_type = :powershell if windows? end shell = SHELL_TYPES[shell_type] raise "Unsupported shell type #{shell_type}" unless shell logger.warn "Command execution on Windows is very slow" unless @warned || linux? @warned = true temp_file = write_temp_file(command, suffix: shell[:suffix] || "") temp_out = "#{temp_file}-out.txt" temp_err = "#{temp_file}-err.txt" begin args = format(shell[:args], cmdfile: temp_file, outfile: temp_out, errfile: temp_err) exit_code = run_program(shell[:cmd], args, timeout) rescue StandardError proc_err = read_file(temp_err) raise format("Error executing command %s. Exit code: %d. StdErr %s", command, exit_code || -1, proc_err) end stdout = read_file(temp_out) stdout = ascii_only(stdout) if bom?(stdout) stderr = read_file(temp_err) unless exit_code == 0 && @quick unless @quick delete_file(temp_file) delete_file(temp_out) delete_file(temp_err) end ::Train::Extras::CommandResult.new(stdout, stderr || "", exit_code) end |
#upload_file(local_file, remote_file) ⇒ Object
Required privilege: VirtualMachine.GuestOperations.Modify
137 138 139 140 141 |
# File 'lib/train-vsphere-gom/guest_operations.rb', line 137 def upload_file(local_file, remote_file) logger.debug format("Uploading %s to remote file %s", local_file, remote_file) write_file(remote_file, File.open(local_file, "rb").read) end |
#write_file(remote_file, contents) ⇒ Object
Required privilege: VirtualMachine.GuestOperations.Modify
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/train-vsphere-gom/guest_operations.rb', line 100 def write_file(remote_file, contents) logger.debug format("Writing to remote file %s", remote_file) put_url = gom.fileManager.InitiateFileTransferToGuest( vm: @vm, auth: @guest_auth, guestFilePath: remote_file, fileAttributes: RbVmomi::VIM::GuestFileAttributes(), fileSize: contents.size, overwrite: true ) # VCenter internal name might mismatch the external, so fix it put_url = put_url.gsub(%r{^https://\*:}, format("https://%s:%s", @vm._connection.host, put_url)) uri = URI.parse(put_url) request = Net::HTTP::Put.new(uri.request_uri) request["Transfer-Encoding"] = "chunked" request["Content-Length"] = contents.size request.body = contents http_request(put_url, request) rescue RbVmomi::Fault => e logger.error "Error during upload, check permissions on remote system: '" + e. + "'" end |
#write_temp_file(contents, prefix: "", suffix: "") ⇒ Object
Required privilege: VirtualMachine.GuestOperations.Modify
127 128 129 130 131 132 133 134 |
# File 'lib/train-vsphere-gom/guest_operations.rb', line 127 def write_temp_file(contents, prefix: "", suffix: "") logger.debug format("Writing to temporary remote file") temp_name = gom.fileManager.CreateTemporaryFileInGuest(vm: @vm, auth: @guest_auth, prefix: prefix, suffix: suffix) write_file(temp_name, contents) temp_name end |