mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-06-22 00:00:22 -07:00
Support additional options for WinRM connections via inventory variables.
This commit is contained in:
parent
8b56bc1c01
commit
056c6b77d0
2 changed files with 70 additions and 45 deletions
|
@ -19,12 +19,12 @@ from __future__ import (absolute_import, division, print_function)
|
|||
__metaclass__ = type
|
||||
|
||||
import base64
|
||||
import inspect
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
import traceback
|
||||
|
||||
from six.moves.urllib import parse
|
||||
import urlparse
|
||||
|
||||
try:
|
||||
from winrm import Response
|
||||
|
@ -50,11 +50,6 @@ from ansible.utils.unicode import to_bytes, to_unicode
|
|||
class Connection(ConnectionBase):
|
||||
'''WinRM connections over HTTP/HTTPS.'''
|
||||
|
||||
transport_schemes = {
|
||||
'http': [('kerberos', 'http'), ('plaintext', 'http'), ('plaintext', 'https')],
|
||||
'https': [('kerberos', 'https'), ('plaintext', 'https')],
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
self.has_pipelining = False
|
||||
|
@ -74,35 +69,53 @@ class Connection(ConnectionBase):
|
|||
''' used to identify this connection object from other classes '''
|
||||
return 'winrm'
|
||||
|
||||
def set_host_overrides(self, host):
|
||||
'''
|
||||
Override WinRM-specific options from host variables.
|
||||
'''
|
||||
host_vars = host.get_vars()
|
||||
|
||||
self._winrm_host = host_vars.get('ansible_winrm_host', self._play_context.remote_addr)
|
||||
self._winrm_port = int(host_vars.get('ansible_winrm_port', self._play_context.port or 5986))
|
||||
self._winrm_scheme = host_vars.get('ansible_winrm_scheme', 'http' if self._winrm_port == 5985 else 'https')
|
||||
self._winrm_path = host_vars.get('ansible_winrm_path', '/wsman')
|
||||
self._winrm_user = host_vars.get('ansible_winrm_user', self._play_context.remote_user)
|
||||
self._winrm_pass = host_vars.get('ansible_winrm_pass', self._play_context.password)
|
||||
|
||||
if '@' in self._winrm_user:
|
||||
self._winrm_realm = self._winrm_user.split('@', 1)[1].strip() or None
|
||||
else:
|
||||
self._winrm_realm = None
|
||||
self._winrm_realm = host_vars.get('ansible_winrm_realm', self._winrm_realm) or None
|
||||
|
||||
if HAVE_KERBEROS and ('@' in self._winrm_user or self._winrm_realm):
|
||||
self._winrm_transport = 'kerberos,plaintext'
|
||||
else:
|
||||
self._winrm_transport = 'plaintext'
|
||||
self._winrm_transport = host_vars.get('ansible_winrm_transport', self._winrm_transport)
|
||||
if isinstance(self._winrm_transport, basestring):
|
||||
self._winrm_transport = [x.strip() for x in self._winrm_transport.split(',') if x.strip()]
|
||||
|
||||
self._winrm_kwargs = dict(username=self._winrm_user, password=self._winrm_pass, realm=self._winrm_realm)
|
||||
argspec = inspect.getargspec(Protocol.__init__)
|
||||
for arg in argspec.args:
|
||||
if arg in ('self', 'endpoint', 'transport', 'username', 'password', 'realm'):
|
||||
continue
|
||||
if 'ansible_winrm_%s' % arg in host_vars:
|
||||
self._winrm_kwargs[arg] = host_vars['ansible_winrm_%s' % arg]
|
||||
|
||||
def _winrm_connect(self):
|
||||
'''
|
||||
Establish a WinRM connection over HTTP/HTTPS.
|
||||
'''
|
||||
port = self._play_context.port or 5986
|
||||
self._display.vvv("ESTABLISH WINRM CONNECTION FOR USER: %s on PORT %s TO %s" % \
|
||||
(self._play_context.remote_user, port, self._play_context.remote_addr), host=self._play_context.remote_addr)
|
||||
netloc = '%s:%d' % (self._play_context.remote_addr, port)
|
||||
exc = None
|
||||
for transport, scheme in self.transport_schemes['http' if port == 5985 else 'https']:
|
||||
if transport == 'kerberos' and (not HAVE_KERBEROS or not '@' in self._play_context.remote_user):
|
||||
continue
|
||||
|
||||
if transport == 'kerberos':
|
||||
realm = self._play_context.remote_user.split('@', 1)[1].strip() or None
|
||||
else:
|
||||
realm = None
|
||||
|
||||
endpoint = parse.urlunsplit((scheme, netloc, '/wsman', '', ''))
|
||||
|
||||
self._display.vvvvv('WINRM CONNECT: transport=%s endpoint=%s' % (transport, endpoint), host=self._play_context.remote_addr)
|
||||
protocol = Protocol(
|
||||
endpoint,
|
||||
transport=transport,
|
||||
username=self._play_context.remote_user,
|
||||
password=self._play_context.password,
|
||||
realm=realm
|
||||
)
|
||||
|
||||
(self._winrm_user, self._winrm_port, self._winrm_host), host=self._winrm_host)
|
||||
netloc = '%s:%d' % (self._winrm_host, self._winrm_port)
|
||||
endpoint = urlparse.urlunsplit((self._winrm_scheme, netloc, self._winrm_path, '', ''))
|
||||
exc = 'No transport found for WinRM connection'
|
||||
for transport in self._winrm_transport:
|
||||
self._display.vvvvv('WINRM CONNECT: transport=%s endpoint=%s' % (transport, endpoint), host=self._winrm_host)
|
||||
protocol = Protocol(endpoint, transport=transport, **self._winrm_kwargs)
|
||||
try:
|
||||
protocol.send_message('')
|
||||
return protocol
|
||||
|
@ -117,16 +130,16 @@ class Connection(ConnectionBase):
|
|||
raise AnsibleError("the username/password specified for this server was incorrect")
|
||||
elif code == 411:
|
||||
return protocol
|
||||
self._display.vvvvv('WINRM CONNECTION ERROR: %s' % err_msg, host=self._play_context.remote_addr)
|
||||
self._display.vvvvv('WINRM CONNECTION ERROR: %s' % err_msg, host=self._winrm_host)
|
||||
continue
|
||||
if exc:
|
||||
raise AnsibleError(str(exc))
|
||||
|
||||
def _winrm_exec(self, command, args=(), from_exec=False):
|
||||
if from_exec:
|
||||
self._display.vvvvv("WINRM EXEC %r %r" % (command, args), host=self._play_context.remote_addr)
|
||||
self._display.vvvvv("WINRM EXEC %r %r" % (command, args), host=self._winrm_host)
|
||||
else:
|
||||
self._display.vvvvvv("WINRM EXEC %r %r" % (command, args), host=self._play_context.remote_addr)
|
||||
self._display.vvvvvv("WINRM EXEC %r %r" % (command, args), host=self._winrm_host)
|
||||
if not self.protocol:
|
||||
self.protocol = self._winrm_connect()
|
||||
if not self.shell_id:
|
||||
|
@ -136,11 +149,11 @@ class Connection(ConnectionBase):
|
|||
command_id = self.protocol.run_command(self.shell_id, to_bytes(command), map(to_bytes, args))
|
||||
response = Response(self.protocol.get_command_output(self.shell_id, command_id))
|
||||
if from_exec:
|
||||
self._display.vvvvv('WINRM RESULT %r' % to_unicode(response), host=self._play_context.remote_addr)
|
||||
self._display.vvvvv('WINRM RESULT %r' % to_unicode(response), host=self._winrm_host)
|
||||
else:
|
||||
self._display.vvvvv('WINRM RESULT %r' % to_unicode(response), host=self._play_context.remote_addr)
|
||||
self._display.vvvvvv('WINRM STDOUT %s' % to_unicode(response.std_out), host=self._play_context.remote_addr)
|
||||
self._display.vvvvvv('WINRM STDERR %s' % to_unicode(response.std_err), host=self._play_context.remote_addr)
|
||||
self._display.vvvvvv('WINRM RESULT %r' % to_unicode(response), host=self._winrm_host)
|
||||
self._display.vvvvvv('WINRM STDOUT %s' % to_unicode(response.std_out), host=self._winrm_host)
|
||||
self._display.vvvvvv('WINRM STDERR %s' % to_unicode(response.std_err), host=self._winrm_host)
|
||||
return response
|
||||
finally:
|
||||
if command_id:
|
||||
|
@ -171,9 +184,9 @@ class Connection(ConnectionBase):
|
|||
if '-EncodedCommand' in cmd_parts:
|
||||
encoded_cmd = cmd_parts[cmd_parts.index('-EncodedCommand') + 1]
|
||||
decoded_cmd = to_unicode(base64.b64decode(encoded_cmd).decode('utf-16-le'))
|
||||
self._display.vvv("EXEC %s" % decoded_cmd, host=self._play_context.remote_addr)
|
||||
self._display.vvv("EXEC %s" % decoded_cmd, host=self._winrm_host)
|
||||
else:
|
||||
self._display.vvv("EXEC %s" % cmd, host=self._play_context.remote_addr)
|
||||
self._display.vvv("EXEC %s" % cmd, host=self._winrm_host)
|
||||
try:
|
||||
result = self._winrm_exec(cmd_parts[0], cmd_parts[1:], from_exec=True)
|
||||
except Exception as e:
|
||||
|
@ -186,7 +199,7 @@ class Connection(ConnectionBase):
|
|||
def put_file(self, in_path, out_path):
|
||||
super(Connection, self).put_file(in_path, out_path)
|
||||
out_path = self._shell._unquote(out_path)
|
||||
self._display.vvv('PUT "%s" TO "%s"' % (in_path, out_path), host=self._play_context.remote_addr)
|
||||
self._display.vvv('PUT "%s" TO "%s"' % (in_path, out_path), host=self._winrm_host)
|
||||
if not os.path.exists(in_path):
|
||||
raise AnsibleFileNotFound('file or module does not exist: "%s"' % in_path)
|
||||
with open(in_path) as in_file:
|
||||
|
@ -214,7 +227,7 @@ class Connection(ConnectionBase):
|
|||
out_path = out_path + '.ps1'
|
||||
b64_data = base64.b64encode(out_data)
|
||||
script = script_template % (self._shell._escape(out_path), offset, b64_data, in_size)
|
||||
self._display.vvvvv('WINRM PUT "%s" to "%s" (offset=%d size=%d)' % (in_path, out_path, offset, len(out_data)), host=self._play_context.remote_addr)
|
||||
self._display.vvvvv('WINRM PUT "%s" to "%s" (offset=%d size=%d)' % (in_path, out_path, offset, len(out_data)), host=self._winrm_host)
|
||||
cmd_parts = self._shell._encode_script(script, as_list=True)
|
||||
result = self._winrm_exec(cmd_parts[0], cmd_parts[1:])
|
||||
if result.status_code != 0:
|
||||
|
@ -227,7 +240,7 @@ class Connection(ConnectionBase):
|
|||
super(Connection, self).fetch_file(in_path, out_path)
|
||||
in_path = self._shell._unquote(in_path)
|
||||
out_path = out_path.replace('\\', '/')
|
||||
self._display.vvv('FETCH "%s" TO "%s"' % (in_path, out_path), host=self._play_context.remote_addr)
|
||||
self._display.vvv('FETCH "%s" TO "%s"' % (in_path, out_path), host=self._winrm_host)
|
||||
buffer_size = 2**19 # 0.5MB chunks
|
||||
makedirs_safe(os.path.dirname(out_path))
|
||||
out_file = None
|
||||
|
@ -256,7 +269,7 @@ class Connection(ConnectionBase):
|
|||
Exit 1;
|
||||
}
|
||||
''' % dict(buffer_size=buffer_size, path=self._shell._escape(in_path), offset=offset)
|
||||
self._display.vvvvv('WINRM FETCH "%s" to "%s" (offset=%d)' % (in_path, out_path, offset), host=self._play_context.remote_addr)
|
||||
self._display.vvvvv('WINRM FETCH "%s" to "%s" (offset=%d)' % (in_path, out_path, offset), host=self._winrm_host)
|
||||
cmd_parts = self._shell._encode_script(script, as_list=True)
|
||||
result = self._winrm_exec(cmd_parts[0], cmd_parts[1:])
|
||||
if result.status_code != 0:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue