class Train::Transports::VMware::Connection
Constants
- POWERSHELL_PROMPT_REGEX
Public Class Methods
new(options)
click to toggle source
Calls superclass method
# File lib/train/transports/vmware.rb, line 22 def initialize(options) super(options) options[:viserver] = options[:viserver] || options[:host] options[:username] = options[:username] || options[:user] @username = options[:username] @viserver = options[:viserver] @session = nil @stdout_buffer = "" @stderr_buffer = "" @powershell_binary = detect_powershell_binary if @powershell_binary == :powershell require_relative "local" @powershell = Train::Transports::Local::Connection.new(options) end if options[:insecure] == true run_command_via_connection("Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Scope Session -Confirm:$False") end @platform_details = { release: "vmware-powercli-#{powercli_version}", } connect end
Public Instance Methods
connect()
click to toggle source
# File lib/train/transports/vmware.rb, line 52 def connect login_command = "Connect-VIServer #{options[:viserver]} -User #{options[:username]} -Password #{options[:password]} | Out-Null" result = run_command_via_connection(login_command) if result.exit_status != 0 message = "Unable to connect to VIServer at #{options[:viserver]}. " case result.stderr when /Invalid server certificate/ message += "Certification verification failed. Please use `--insecure` or set `Set-PowerCLIConfiguration -InvalidCertificateAction Ignore` in PowerShell" when /incorrect user name or password/ message += "Incorrect username or password" else message += result.stderr.gsub(/-Password .*\s/, "-Password REDACTED") end raise message end end
platform()
click to toggle source
# File lib/train/transports/vmware.rb, line 71 def platform force_platform!("vmware", @platform_details) end
run_command_via_connection(cmd, &_data_handler)
click to toggle source
# File lib/train/transports/vmware.rb, line 75 def run_command_via_connection(cmd, &_data_handler) if @powershell_binary == :pwsh result = parse_pwsh_output(cmd) # Attach exit status to result exit_status = parse_pwsh_output("echo $?").stdout.chomp result.exit_status = exit_status == "True" ? 0 : 1 result else @powershell.run_command(cmd) end end
unique_identifier()
click to toggle source
# File lib/train/transports/vmware.rb, line 89 def unique_identifier uuid_command = "(Get-VMHost | Get-View).hardware.systeminfo.uuid" run_command_via_connection(uuid_command).stdout.chomp end
uri()
click to toggle source
# File lib/train/transports/vmware.rb, line 94 def uri "vmware://#{@username}@#{@viserver}" end
Private Instance Methods
detect_powershell_binary()
click to toggle source
# File lib/train/transports/vmware.rb, line 100 def detect_powershell_binary if find_executable0("pwsh") :pwsh elsif find_executable0("powershell") :powershell else raise "Cannot find PowerShell binary, is `pwsh` installed?" end end
flush_stderr(pipe)
click to toggle source
This must be called after `flush_stdout` to ensure buffer is full
# File lib/train/transports/vmware.rb, line 122 def flush_stderr(pipe) loop do @stderr_buffer += pipe.read_nonblock(1) end rescue IO::EAGAINWaitReadable # If `flush_stderr` is ran after reading stdout we know that all of # stderr is in the pipe. Thus, we can return the buffer once the pipe # is unreadable. @stderr_buffer ensure @stderr_buffer = "" end
flush_stdout(pipe)
click to toggle source
Read from stdout pipe until prompt is received
# File lib/train/transports/vmware.rb, line 111 def flush_stdout(pipe) @stdout_buffer += pipe.read_nonblock(1) while @stdout_buffer !~ POWERSHELL_PROMPT_REGEX @stdout_buffer rescue IO::EAGAINWaitReadable # We cannot know when the stdout pipe is finished so we keep reading retry ensure @stdout_buffer = "" end
parse_pwsh_output(cmd)
click to toggle source
# File lib/train/transports/vmware.rb, line 135 def parse_pwsh_output(cmd) session.stdin.puts(cmd) stdout = flush_stdout(session.stdout) # Remove stdin from stdout (including trailing newline) stdout.slice!(0, cmd.length + 1) # Remove prompt from stdout stdout.gsub!(POWERSHELL_PROMPT_REGEX, "") # Grab stderr stderr = flush_stderr(session.stderr) CommandResult.new( stdout, stderr, nil # exit_status is attached in `run_command_via_connection` ) end
powercli_version()
click to toggle source
# File lib/train/transports/vmware.rb, line 156 def powercli_version version_command = "[string](Get-Module -Name VMware.PowerCLI -ListAvailable | Select -ExpandProperty Version)" result = run_command_via_connection(version_command) if result.stdout.empty? || result.exit_status != 0 raise "Unable to determine PowerCLI Module version, is it installed?" end result.stdout.chomp end
session()
click to toggle source
# File lib/train/transports/vmware.rb, line 166 def session return @session unless @session.nil? stdin, stdout, stderr = Open3.popen3("pwsh") # Remove leading prompt and intro text flush_stdout(stdout) @session = OpenStruct.new @session.stdin = stdin @session.stdout = stdout @session.stderr = stderr @session end