lib/chef_metal/transport/winrm.rb in chef-metal-0.14.2 vs lib/chef_metal/transport/winrm.rb in chef-metal-0.15
- old
+ new
@@ -1,134 +2 @@
-require 'chef_metal/transport'
-require 'base64'
-require 'timeout'
-
-module ChefMetal
- class Transport
- class WinRM < ChefMetal::Transport
- def initialize(endpoint, type, options, global_config)
- @endpoint = endpoint
- @type = type
- @options = options
- @config = global_config
- end
-
- attr_reader :endpoint
- attr_reader :type
- attr_reader :options
- attr_reader :config
-
- def execute(command, execute_options = {})
- output = with_execute_timeout(execute_options) do
- session.set_timeout(execute_timeout(execute_options))
- session.run_powershell_script(command) do |stdout, stderr|
- stream_chunk(execute_options, stdout, stderr)
- end
- end
- WinRMResult.new(command, execute_options, config, output)
- end
-
- def read_file(path)
- result = execute("[Convert]::ToBase64String((Get-Content #{escape(path)} -Encoding byte -ReadCount 0))")
- if result.exitstatus == 0
- Base64.decode64(result.stdout)
- else
- nil
- end
- end
-
- def write_file(path, content)
- chunk_size = options[:chunk_size] || 1024
- # TODO if we could marshal this data directly, we wouldn't have to base64 or do this godawful slow stuff :(
- index = 0
- execute("
-$ByteArray = [System.Convert]::FromBase64String(#{escape(Base64.encode64(content[index..index+chunk_size-1]))})
-$file = [System.IO.File]::Open(#{escape(path)}, 'Create', 'Write')
-$file.Write($ByteArray, 0, $ByteArray.Length)
-$file.Close
-").error!
- index += chunk_size
- while index < content.length
- execute("
-$ByteArray = [System.Convert]::FromBase64String(#{escape(Base64.encode64(content[index..index+chunk_size-1]))})
-$file = [System.IO.File]::Open(#{escape(path)}, 'Append', 'Write')
-$file.Write($ByteArray, 0, $ByteArray.Length)
-$file.Close
-").error!
- index += chunk_size
- end
- end
-
- def disconnect
- #
- end
-
- def escape(string)
- "\"#{string.gsub("\"", "`\"")}\""
- end
-
- def available?
- # If you can't pwd within 10 seconds, you can't pwd
- execute('pwd', :timeout => 10)
- true
- rescue Timeout::Error, Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET, ::WinRM::WinRMHTTPTransportError, ::WinRM::WinRMWebServiceError, ::WinRM::WinRMWSManFault
- Chef::Log.debug("unavailable: network connection failed or broke: #{$!.inspect}")
- disconnect
- false
- rescue ::WinRM::WinRMAuthorizationError
- Chef::Log.debug("unavailable: winrm authentication error: #{$!.inspect} ")
- disconnect
- false
- end
-
- def make_url_available_to_remote(local_url)
- uri = URI(local_url)
- host = Socket.getaddrinfo(uri.host, uri.scheme, nil, :STREAM)[0][3]
- if host == '127.0.0.1' || host == '::1'
- raise 'Unable to converge locally via winrm. Local converge is currently only supported with SSH. You may only converge with winrm against a chef-server.'
- end
- local_url
- end
-
- protected
-
- def session
- @session ||= begin
- require 'kconv' # Really, people? *sigh*
- require 'winrm'
- ::WinRM::WinRMWebService.new(endpoint, type, options)
- end
- end
-
- class WinRMResult
- def initialize(command, options, config, output)
- @command = command
- @options = options
- @config = config
- @exitstatus = output[:exitcode]
- @stdout = ''
- @stderr = ''
- output[:data].each do |data|
- @stdout << data[:stdout] if data[:stdout]
- @stderr << data[:stderr] if data[:stderr]
- end
- end
-
- attr_reader :stdout
- attr_reader :stderr
- attr_reader :exitstatus
- attr_reader :command
- attr_reader :options
- attr_reader :config
-
- def error!
- if exitstatus != 0
- msg = "Error: command '#{command}' exited with code #{exitstatus}.\n"
- msg << "STDOUT: #{stdout}" if !options[:stream] && !options[:stream_stdout] && config[:log_level] != :debug
- msg << "STDERR: #{stderr}" if !options[:stream] && !options[:stream_stderr] && config[:log_level] != :debug
- raise msg
- end
- end
- end
- end
- end
-end
+require "chef/provisioning/transport/winrm"