Remove ansible_winrm_ host/port/user/pass options, update exception handling around establishing a winrm connection.

This commit is contained in:
Chris Church 2015-09-14 15:59:40 -04:00
parent 056c6b77d0
commit c5409ab493
2 changed files with 21 additions and 20 deletions

View file

@ -160,11 +160,11 @@ In group_vars/windows.yml, define the following inventory variables::
# ansible-vault edit group_vars/windows.yml # ansible-vault edit group_vars/windows.yml
ansible_user: Administrator ansible_user: Administrator
ansible_ssh_pass: SecretPasswordGoesHere ansible_password: SecretPasswordGoesHere
ansible_port: 5986 ansible_port: 5986
ansible_connection: winrm ansible_connection: winrm
Notice that the ssh_port is not actually for SSH, but this is a holdover variable name from how Ansible is mostly an SSH-oriented system. Again, Windows management will not happen over SSH (`yet <http://blogs.msdn.com/b/powershell/archive/2015/06/03/looking-forward-microsoft-support-for-secure-shell-ssh.aspx>`). Although Ansible is mostly an SSH-oriented system, Windows management will not happen over SSH (`yet <http://blogs.msdn.com/b/powershell/archive/2015/06/03/looking-forward-microsoft-support-for-secure-shell-ssh.aspx>`).
If you have installed the ``kerberos`` module and ``ansible_user`` contains ``@`` (e.g. ``username@realm``), Ansible will first attempt Kerberos authentication. *This method uses the principal you are authenticated to Kerberos with on the control machine and not ``ansible_user``*. If that fails, either because you are not signed into Kerberos on the control machine or because the corresponding domain account on the remote host is not available, then Ansible will fall back to "plain" username/password authentication. If you have installed the ``kerberos`` module and ``ansible_user`` contains ``@`` (e.g. ``username@realm``), Ansible will first attempt Kerberos authentication. *This method uses the principal you are authenticated to Kerberos with on the control machine and not ``ansible_user``*. If that fails, either because you are not signed into Kerberos on the control machine or because the corresponding domain account on the remote host is not available, then Ansible will fall back to "plain" username/password authentication.
@ -184,11 +184,7 @@ You'll run this command again later though, to make sure everything is working.
Since 2.0, the following custom inventory variables are also supported for additional configuration of WinRM connections:: Since 2.0, the following custom inventory variables are also supported for additional configuration of WinRM connections::
* ``ansible_winrm_scheme``: Specify the connection scheme (``http`` or ``https``) to use for the WinRM connection. Ansible uses ``https`` by default unless the port is 5985. * ``ansible_winrm_scheme``: Specify the connection scheme (``http`` or ``https``) to use for the WinRM connection. Ansible uses ``https`` by default unless the port is 5985.
* ``ansible_winrm_host``: May be used as an alias for ``ansible_ssh_host`` and will take precedence if both are defined.
* ``ansible_winrm_port``: May be used an alias for ``ansible_ssh_port`` and will take precedence if both are defined.
* ``ansible_winrm_path``: Specify an alternate path to the WinRM endpoint. Ansible uses ``/wsman`` by default. * ``ansible_winrm_path``: Specify an alternate path to the WinRM endpoint. Ansible uses ``/wsman`` by default.
* ``ansible_winrm_user``: May be used an alias for ``ansible_ssh_user`` and will take precedence if both are defined.
* ``ansible_winrm_pass``: May be used an alias for ``ansible_ssh_pass`` and will take precedence if both are defined.
* ``ansible_winrm_realm``: Specify the realm to use for Kerberos authentication. If the username contains ``@``, Ansible will use the part of the username after ``@`` by default. * ``ansible_winrm_realm``: Specify the realm to use for Kerberos authentication. If the username contains ``@``, Ansible will use the part of the username after ``@`` by default.
* ``ansible_winrm_transport``: Specify one or more transports as a comma-separated list. By default, Ansible will use ``kerberos,plaintext`` if the ``kerberos`` module is installed and a realm is defined, otherwise ``plaintext``. * ``ansible_winrm_transport``: Specify one or more transports as a comma-separated list. By default, Ansible will use ``kerberos,plaintext`` if the ``kerberos`` module is installed and a realm is defined, otherwise ``plaintext``.
* ``ansible_winrm_*``: Any additional keyword arguments supported by ``winrm.Protocol`` may be provided. * ``ansible_winrm_*``: Any additional keyword arguments supported by ``winrm.Protocol`` may be provided.

View file

@ -75,12 +75,12 @@ class Connection(ConnectionBase):
''' '''
host_vars = host.get_vars() host_vars = host.get_vars()
self._winrm_host = host_vars.get('ansible_winrm_host', self._play_context.remote_addr) self._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_port = int(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_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_path = host_vars.get('ansible_winrm_path', '/wsman')
self._winrm_user = host_vars.get('ansible_winrm_user', self._play_context.remote_user) self._winrm_user = self._play_context.remote_user
self._winrm_pass = host_vars.get('ansible_winrm_pass', self._play_context.password) self._winrm_pass = self._play_context.password
if '@' in self._winrm_user: if '@' in self._winrm_user:
self._winrm_realm = self._winrm_user.split('@', 1)[1].strip() or None self._winrm_realm = self._winrm_user.split('@', 1)[1].strip() or None
@ -112,28 +112,33 @@ class Connection(ConnectionBase):
(self._winrm_user, self._winrm_port, self._winrm_host), host=self._winrm_host) (self._winrm_user, self._winrm_port, self._winrm_host), host=self._winrm_host)
netloc = '%s:%d' % (self._winrm_host, self._winrm_port) netloc = '%s:%d' % (self._winrm_host, self._winrm_port)
endpoint = urlparse.urlunsplit((self._winrm_scheme, netloc, self._winrm_path, '', '')) endpoint = urlparse.urlunsplit((self._winrm_scheme, netloc, self._winrm_path, '', ''))
exc = 'No transport found for WinRM connection' errors = []
for transport in self._winrm_transport: for transport in self._winrm_transport:
if transport == 'kerberos' and not HAVE_KERBEROS:
errors.append('kerberos: the python kerberos library is not installed')
continue
self._display.vvvvv('WINRM CONNECT: transport=%s endpoint=%s' % (transport, endpoint), host=self._winrm_host) self._display.vvvvv('WINRM CONNECT: transport=%s endpoint=%s' % (transport, endpoint), host=self._winrm_host)
protocol = Protocol(endpoint, transport=transport, **self._winrm_kwargs)
try: try:
protocol = Protocol(endpoint, transport=transport, **self._winrm_kwargs)
protocol.send_message('') protocol.send_message('')
return protocol return protocol
except WinRMTransportError as exc: except Exception as e:
err_msg = str(exc) err_msg = (str(e) or repr(e)).strip()
if re.search(r'Operation\s+?timed\s+?out', err_msg, re.I): if re.search(r'Operation\s+?timed\s+?out', err_msg, re.I):
raise AnsibleError("the connection attempt timed out") raise AnsibleError('the connection attempt timed out')
m = re.search(r'Code\s+?(\d{3})', err_msg) m = re.search(r'Code\s+?(\d{3})', err_msg)
if m: if m:
code = int(m.groups()[0]) code = int(m.groups()[0])
if code == 401: if code == 401:
raise AnsibleError("the username/password specified for this server was incorrect") err_msg = 'the username/password specified for this server was incorrect'
elif code == 411: elif code == 411:
return protocol return protocol
self._display.vvvvv('WINRM CONNECTION ERROR: %s' % err_msg, host=self._winrm_host) errors.append('%s: %s' % (transport, err_msg))
continue self._display.vvvvv('WINRM CONNECTION ERROR: %s\n%s' % (err_msg, traceback.format_exc()), host=self._winrm_host)
if exc: if errors:
raise AnsibleError(str(exc)) raise AnsibleError(', '.join(errors))
else:
raise AnsibleError('No transport found for WinRM connection')
def _winrm_exec(self, command, args=(), from_exec=False): def _winrm_exec(self, command, args=(), from_exec=False):
if from_exec: if from_exec: