[Python-modules-commits] [txwinrm] 01/09: Import txwinrm_1.2.20.orig.tar.gz
Christopher Stuart Hoskin
mans0954 at moszumanska.debian.org
Mon Jun 26 01:47:00 UTC 2017
This is an automated email from the git hooks/post-receive script.
mans0954 pushed a commit to branch master
in repository txwinrm.
commit 725ae9c1a9a2e5be561af17bc361181305870603
Author: Christopher Hoskin <mans0954 at debian.org>
Date: Mon Jun 26 02:23:36 2017 +0100
Import txwinrm_1.2.20.orig.tar.gz
---
setup.py | 2 +-
txwinrm/SessionManager.py | 6 +-
txwinrm/WinRMClient.py | 148 +++++++++++++++++++++-------------------------
txwinrm/app.py | 4 +-
txwinrm/krb5.py | 42 ++++++++-----
txwinrm/shell.py | 108 +++++++++++++++++++++++++++------
txwinrm/util.py | 60 ++++++++++++-------
7 files changed, 231 insertions(+), 139 deletions(-)
diff --git a/setup.py b/setup.py
index b0b2ba7..28b475e 100755
--- a/setup.py
+++ b/setup.py
@@ -11,7 +11,7 @@
setup_kwargs = dict(
name='txwinrm',
- version='1.2.7',
+ version='1.2.20',
description='Asynchronous Python WinRM client',
long_description=open('README.rst').read(),
license='See LICENSE file',
diff --git a/txwinrm/SessionManager.py b/txwinrm/SessionManager.py
index c03508a..e60dc28 100755
--- a/txwinrm/SessionManager.py
+++ b/txwinrm/SessionManager.py
@@ -98,8 +98,7 @@ class Session(object):
self._token = None
- if client in self._clients:
- self._clients.remove(client)
+ self._clients.discard(client)
returnValue(None)
@inlineCallbacks
@@ -171,8 +170,7 @@ class SessionManager(object):
session = self.get_connection(client.key)
if session:
if session._token:
- if client not in session._clients:
- session._clients.add(client)
+ session._clients.add(client)
returnValue(session._token)
if session is None:
diff --git a/txwinrm/WinRMClient.py b/txwinrm/WinRMClient.py
index 2cfac59..216cc42 100755
--- a/txwinrm/WinRMClient.py
+++ b/txwinrm/WinRMClient.py
@@ -7,6 +7,7 @@
#
##############################################################################
+import copy
import logging
from collections import namedtuple
from httplib import BAD_REQUEST, UNAUTHORIZED, FORBIDDEN, OK
@@ -51,12 +52,13 @@ from .util import (
from .shell import (
_find_shell_id,
_build_command_line_elem,
+ _build_ps_command_line_elem,
_find_command_id,
_MAX_REQUESTS_PER_COMMAND,
_find_stream,
_find_exit_code,
CommandResponse,
- _stripped_lines
+ _stripped_lines,
)
from .enumerate import (
DEFAULT_RESOURCE_URI,
@@ -67,48 +69,6 @@ from .SessionManager import SESSION_MANAGER, Session
kerberos = None
LOG = logging.getLogger('winrm')
-EnumInfo = namedtuple('EnumInfo', ['wql', 'resource_uri'])
-
-
-def _build_ps_command_line_elem(ps_command, ps_script):
- """Build PowerShell command line elements without splitting
- the actual ps script into arguments. using _build_command_line_elem
- with a ps script splits the script into separate arguments. Remote
- Windows shell inserts spaces when reconstituting the script.
-
- ps_command - powershell command with arguments as string
- e.g. 'powershell -NoLogo -NonInteractive -NoProfile -Command'
- ps_script - script to be run in powershell as single line string
- e.g. "& {get-counter -counter \"\memory\pages output/sec\" }"
- """
- command_line_parts = shlex.split(ps_command, posix=False)
- # ensure '-command' is last
- if command_line_parts[-1:][0].lower() != '-command':
- index = 0
- for option in command_line_parts:
- if option.lower() == '-command':
- command_line_parts.pop(index)
- break
- index += 1
- command_line_parts.append(option)
- prefix = "rsp"
- ET.register_namespace(prefix, c.XML_NS_MSRSP)
- command_line_elem = ET.Element('{%s}CommandLine' % c.XML_NS_MSRSP)
- command_elem = ET.Element('{%s}Command' % c.XML_NS_MSRSP)
- command_elem.text = command_line_parts[0]
- command_line_elem.append(command_elem)
- for arguments_text in command_line_parts[1:]:
- arguments_elem = ET.Element('{%s}Arguments' % c.XML_NS_MSRSP)
- arguments_elem.text = arguments_text
- command_line_elem.append(arguments_elem)
- arguments_elem = ET.Element('{%s}Arguments' % c.XML_NS_MSRSP)
- arguments_elem.text = ps_script
- command_line_elem.append(arguments_elem)
- tree = ET.ElementTree(command_line_elem)
- str_io = StringIO()
- tree.write(str_io, encoding='utf-8')
- return str_io.getvalue()
-
class WinRMSession(Session):
'''
@@ -250,7 +210,7 @@ class WinRMSession(Session):
import xml.dom.minidom
xml = xml.dom.minidom.parseString(xml_str)
LOG.debug(xml.toprettyxml())
- except:
+ except Exception:
LOG.debug('Could not prettify response XML: "{0}"'.format(xml_str))
returnValue(ET.fromstring(xml_str))
@@ -305,49 +265,62 @@ class WinRMClient(object):
verify_conn_info(conn_info)
self.key = None
self._conn_info = conn_info
- self.session_manager = SESSION_MANAGER
- self._session = None
self.ps_script = None
+ def _session(self):
+ return SESSION_MANAGER.get_connection(self.key)
+
@inlineCallbacks
def init_connection(self):
- '''Initialize a connection through the session_manager'''
- yield self.session_manager.init_connection(self, WinRMSession)
- self._session = self.session_manager.get_connection(self.key)
+ """Initialize a connection through the session_manager"""
+ if self._session() is not None:
+ try:
+ self._refresh_dc.cancel()
+ except Exception:
+ pass
+ yield SESSION_MANAGER.init_connection(self, WinRMSession)
returnValue(None)
def is_kerberos(self):
return self._conn_info.auth_type == 'kerberos'
def decrypt_body(self, body):
- return self._session.decrypt_body(body)
+ return self._session().decrypt_body(body)
+
+ @inlineCallbacks
+ def send_request(self, request, **kwargs):
+ if not self._session():
+ yield self.init_connection()
+
+ if not self._session():
+ raise Exception('Could not connect to device {}'.format(self.conn_info.hostname))
+ response = yield self._session().send_request(request, self, **kwargs)
+ returnValue(response)
@inlineCallbacks
def _create_shell(self):
- elem = yield self._session.send_request('create', self)
+ elem = yield self.send_request('create')
returnValue(_find_shell_id(elem))
@inlineCallbacks
def _delete_shell(self, shell_id):
- yield self._session.send_request('delete', self, shell_id=shell_id)
+ yield self.send_request('delete', shell_id=shell_id)
returnValue(None)
@inlineCallbacks
def _signal_terminate(self, shell_id, command_id):
- yield self._session.send_request('signal',
- self,
- shell_id=shell_id,
- command_id=command_id,
- signal_code=c.SHELL_SIGNAL_TERMINATE)
+ yield self.send_request('signal',
+ shell_id=shell_id,
+ command_id=command_id,
+ signal_code=c.SHELL_SIGNAL_TERMINATE)
returnValue(None)
@inlineCallbacks
def _signal_ctrl_c(self, shell_id, command_id):
- yield self._session.send_request('signal',
- self,
- shell_id=shell_id,
- command_id=command_id,
- signal_code=c.SHELL_SIGNAL_CTRL_C)
+ yield self.send_request('signal',
+ shell_id=shell_id,
+ command_id=command_id,
+ signal_code=c.SHELL_SIGNAL_CTRL_C)
returnValue(None)
@inlineCallbacks
@@ -360,20 +333,20 @@ class WinRMClient(object):
LOG.debug('WinRMClient._send_command: sending command request '
'(shell_id={0}, command_line_elem={1})'.format(
shell_id, command_line_elem))
- command_elem = yield self._session.send_request(
- 'command', self, shell_id=shell_id, command_line_elem=command_line_elem,
+ command_elem = yield self.send_request(
+ 'command', shell_id=shell_id, command_line_elem=command_line_elem,
timeout=self._conn_info.timeout)
returnValue(command_elem)
@inlineCallbacks
def _send_receive(self, shell_id, command_id):
- receive_elem = yield self._session.send_request(
- 'receive', self, shell_id=shell_id, command_id=command_id)
+ receive_elem = yield self.send_request(
+ 'receive', shell_id=shell_id, command_id=command_id)
returnValue(receive_elem)
@inlineCallbacks
def close_connection(self):
- yield self._session.close_connection(self)
+ yield self._session().close_connection(self)
returnValue(None)
@@ -397,8 +370,8 @@ class SingleCommandClient(WinRMClient):
self.ps_script = ps_script
yield self.init_connection()
try:
- cmd_response = yield self._session.sem.run(self.run_single_command,
- command_line)
+ cmd_response = yield self._session().sem.run(self.run_single_command,
+ command_line)
except Exception:
yield self.close_connection()
raise
@@ -449,7 +422,14 @@ class SingleCommandClient(WinRMClient):
class LongCommandClient(WinRMClient):
- """Client to run a single long running command to a winrm device"""
+ """UNDER CONSTRUCTION!!! DO NOT USE!!
+
+ Having issues with this client. May Need to be reworked a bit
+
+ TODO: If raising exception, we need to delete the remote shell
+ before closing connection
+
+ Client to run a single long running command to a winrm device"""
def __init__(self, conn_info):
super(LongCommandClient, self).__init__(conn_info)
self._shell_id = None
@@ -470,11 +450,13 @@ class LongCommandClient(WinRMClient):
self.key = (self._conn_info.ipaddress, command_line + str(ps_script))
self.ps_script = ps_script
yield self.init_connection()
- self._shell_id = yield self._create_shell()
+ if self._shell_id is None:
+ self._shell_id = yield self._create_shell()
try:
command_elem = yield self._send_command(self._shell_id,
command_line)
except TimeoutError:
+ yield self._sender.send_request('delete', shell_id=self._shell_id)
yield self.close_connection()
raise
self._command_id = _find_command_id(command_elem)
@@ -524,7 +506,8 @@ class EnumerateClient(WinRMClient):
@inlineCallbacks
def enumerate(self, wql, resource_uri=DEFAULT_RESOURCE_URI):
"""Runs a remote WQL query."""
- yield self.init_connection()
+ if self._session() is None:
+ yield self.init_connection()
request_template_name = 'enumerate'
enumeration_context = None
items = []
@@ -532,7 +515,7 @@ class EnumerateClient(WinRMClient):
for i in xrange(_MAX_REQUESTS_PER_ENUMERATION):
LOG.info('{0} "{1}" {2}'.format(
self._hostname, wql, request_template_name))
- response = yield self._session._send_request(
+ response = yield self._session()._send_request(
request_template_name,
self,
resource_uri=resource_uri,
@@ -564,12 +547,11 @@ class EnumerateClient(WinRMClient):
"""
items = {}
yield self.init_connection()
- self._session = self.session_manager.get_connection(self.key)
for enum_info in enum_infos:
try:
- items[enum_info] = yield self._session.sem.run(self.enumerate,
- enum_info.wql,
- enum_info.resource_uri)
+ items[enum_info] = yield self._session().sem.run(self.enumerate,
+ enum_info.wql,
+ enum_info.resource_uri)
except (UnauthorizedError, ForbiddenError):
# Fail the collection for general errors.
raise
@@ -628,17 +610,23 @@ class AssociatorClient(EnumerateClient):
see https://msdn.microsoft.com/en-us/library/aa384793(v=vs.85).aspx
"""
+ associations_copy = copy.deepcopy(associations)
items = {}
wql = 'Select {} from {}'.format(','.join(fields), seed_class)
if where:
wql += ' where {}'.format(where)
+ EnumInfo = namedtuple('EnumInfo', ['wql', 'resource_uri'])
enum_info = EnumInfo(wql, resource_uri)
results = yield self.do_collect([enum_info])
- input_results = results[enum_info]
+
+ try:
+ input_results = results[enum_info]
+ except KeyError:
+ raise Exception('No results for seed class {}.'.format(seed_class))
items[seed_class] = input_results
- while associations:
- association = associations.pop(0)
+ while associations_copy:
+ association = associations_copy.pop(0)
associate_results = []
prop_results = {}
for item in input_results:
diff --git a/txwinrm/app.py b/txwinrm/app.py
index 5a93753..2feda3c 100644
--- a/txwinrm/app.py
+++ b/txwinrm/app.py
@@ -221,6 +221,7 @@ def _parse_args(utility):
parser.add_argument("--ipaddress", "-s")
parser.add_argument("--service", "-e", help='http/https/wsman', default='http')
parser.add_argument("--includedir", help="valid includedir")
+ parser.add_argument("--disable_rdns", action="store_true", help="disable kerberos reverse lookups")
utility.add_args(parser)
args = parser.parse_args()
if not args.config:
@@ -236,12 +237,13 @@ def _parse_args(utility):
if not password:
password = getpass()
connectiontype = 'Keep-Alive'
+ disable_rdns = True if args.disable_rdns else False
args.conn_info = ConnectionInfo(
hostname, args.authentication,
args.username, password, scheme,
port, connectiontype, args.keytab,
args.dcip, ipaddress=args.ipaddress, service=args.service,
- include_dir=args.includedir)
+ include_dir=args.includedir, disable_rdns=disable_rdns)
try:
verify_conn_info(args.conn_info)
except Exception as e:
diff --git a/txwinrm/krb5.py b/txwinrm/krb5.py
index eed3bf3..1a733fe 100644
--- a/txwinrm/krb5.py
+++ b/txwinrm/krb5.py
@@ -26,7 +26,7 @@ __all__ = [
KRB5_CONF_TEMPLATE = (
"# This file is managed by the txwinrm python module.\n"
- "# NOTE: Any changes to the logging, libdefaults, domain_realm"
+ "# NOTE: Any changes to the logging, libdefaults, domain_realm\n"
"# sections of this file will be overwritten.\n"
"#\n"
"\n"
@@ -43,6 +43,7 @@ KRB5_CONF_TEMPLATE = (
" ticket_lifetime = 24h\n"
" renew_lifetime = 7d\n"
" forwardable = true\n"
+ "{disable_rdns}"
"\n"
"[realms]\n"
"{realms_text}"
@@ -98,6 +99,7 @@ class Config(object):
"""Initialize instance with data from KRB5_CONFIG."""
self.path = self.get_path()
self.includedirs = set()
+ self.disable_rdns = False
self.realms, self.admin_servers = self.load()
# For further usage by kerberos python module.
@@ -131,7 +133,7 @@ class Config(object):
self.save()
defer.returnValue(None)
- def add_kdc(self, realm, kdcs):
+ def add_kdc(self, realm, kdcs, disable_rdns=False):
"""Add realm and KDC to KRB5_CONFIG.
Allow for comma separated string of kdcs with regex
Use + or nothing to add, - to remove, * for admin_server
@@ -167,10 +169,13 @@ class Config(object):
new_kdcs = self.realms[realm].symmetric_difference(set(valid_kdcs))
bad_kdcs = self.realms[realm].intersection(set(remove_kdcs))
- if not new_kdcs and not bad_kdcs and admin_server == self.admin_servers[realm]:
+ if (not new_kdcs and not bad_kdcs and
+ admin_server == self.admin_servers[realm] and
+ self.disable_rdns == disable_rdns):
# nothing to do
return
+ self.disable_rdns = disable_rdns
self.realms[realm] = self.realms[realm].union(new_kdcs) - bad_kdcs
self.admin_servers[realm] = admin_server
self.save()
@@ -237,6 +242,11 @@ class Config(object):
match = re.search(r'includedir (\S+)', line)
if match:
self.includedirs.add(match.group(1))
+ elif line.strip().startswith('rdns'):
+ try:
+ self.disable_rdns = True if line.split('=')[1].strip() == 'false' else False
+ except Exception:
+ self.disable_rdns = False
elif in_realms_section:
line = line.strip()
if not line:
@@ -297,13 +307,17 @@ class Config(object):
INCLUDEDIR_TEMPLATE.format(
includedir=includedir))
- with open(self.path, 'w') as krb5_conf:
- krb5_conf.write(
- KRB5_CONF_TEMPLATE.format(
- includedir=''.join(includedir_list),
- realms_text=''.join(realms_list),
- domain_realm_text=''.join(domain_realm_list)))
-
+ disable_rdns = ' rdns = false\n' if self.disable_rdns else ''
+ try:
+ with open(self.path, 'w') as krb5_conf:
+ krb5_conf.write(
+ KRB5_CONF_TEMPLATE.format(
+ disable_rdns=disable_rdns,
+ includedir=''.join(includedir_list),
+ realms_text=''.join(realms_list),
+ domain_realm_text=''.join(domain_realm_list)))
+ except IOError as e:
+ pass
# Singleton. Loads from KRB5_CONFIG on import.
config = Config()
@@ -340,7 +354,7 @@ class KinitProcessProtocol(ProcessProtocol):
@defer.inlineCallbacks
-def kinit(username, password, kdc, includedir=None):
+def kinit(username, password, kdc, includedir=None, disable_rdns=False):
"""Perform kerberos initialization."""
kinit = None
for path in ('/usr/bin/kinit', '/usr/kerberos/bin/kinit'):
@@ -362,7 +376,7 @@ def kinit(username, password, kdc, includedir=None):
if includedir:
yield config.add_includedir(includedir)
- config.add_kdc(realm, kdc)
+ config.add_kdc(realm, kdc, disable_rdns)
ccname = config.get_ccname(username)
dirname = os.path.dirname(ccname)
@@ -388,8 +402,8 @@ def ccname(username):
return config.get_ccname(username)
-def add_trusted_realm(realm, kdc):
+def add_trusted_realm(realm, kdc, disable_rdns=False):
"""Add a trusted realm for cross realm authentication"""
trusted_realm = realm.upper()
global config
- config.add_kdc(trusted_realm, kdc)
+ config.add_kdc(trusted_realm, kdc, disable_rdns)
diff --git a/txwinrm/shell.py b/txwinrm/shell.py
index 0b4b1fb..f497499 100644
--- a/txwinrm/shell.py
+++ b/txwinrm/shell.py
@@ -19,10 +19,11 @@ from twisted.internet import reactor, defer, task
from twisted.internet.error import TimeoutError
from xml.etree import cElementTree as ET
from . import constants as c
-from .util import create_etree_request_sender, get_datetime
+from .util import create_etree_request_sender, get_datetime, RequestError
log = logging.getLogger('winrm')
_MAX_REQUESTS_PER_COMMAND = 9999
+_MAX_RETRIES = 3
class CommandResponse(object):
@@ -49,6 +50,46 @@ class CommandResponse(object):
stdout=self.stdout, stderr=self.stderr, exit_code=self.exit_code))
+def _build_ps_command_line_elem(ps_command, ps_script):
+ """Build PowerShell command line elements without splitting
+ the actual ps script into arguments. using _build_command_line_elem
+ with a ps script splits the script into separate arguments. Remote
+ Windows shell inserts spaces when reconstituting the script.
+
+ ps_command - powershell command with arguments as string
+ e.g. 'powershell -NoLogo -NonInteractive -NoProfile -Command'
+ ps_script - script to be run in powershell as single line string
+ e.g. "& {get-counter -counter \"\memory\pages output/sec\" }"
+ """
+ command_line_parts = shlex.split(ps_command, posix=False)
+ # ensure '-command' is last
+ if command_line_parts[-1:][0].lower() != '-command':
+ index = 0
+ for option in command_line_parts:
+ if option.lower() == '-command':
+ command_line_parts.pop(index)
+ break
+ index += 1
+ command_line_parts.append(option)
+ prefix = "rsp"
+ ET.register_namespace(prefix, c.XML_NS_MSRSP)
+ command_line_elem = ET.Element('{%s}CommandLine' % c.XML_NS_MSRSP)
+ command_elem = ET.Element('{%s}Command' % c.XML_NS_MSRSP)
+ command_elem.text = command_line_parts[0]
+ command_line_elem.append(command_elem)
+ for arguments_text in command_line_parts[1:]:
+ arguments_elem = ET.Element('{%s}Arguments' % c.XML_NS_MSRSP)
+ arguments_elem.text = arguments_text
+ command_line_elem.append(arguments_elem)
+ arguments_elem = ET.Element('{%s}Arguments' % c.XML_NS_MSRSP)
+ arguments_elem.text = ps_script
+ command_line_elem.append(arguments_elem)
+ tree = ET.ElementTree(command_line_elem)
+ str_io = StringIO()
+ tree.write(str_io, encoding='utf-8')
+ return str_io.getvalue()
+
+
def _build_command_line_elem(command_line):
command_line_parts = shlex.split(command_line, posix=False)
prefix = "rsp"
@@ -182,11 +223,15 @@ class LongRunningCommand(object):
self._exit_code = None
@defer.inlineCallbacks
- def start(self, command_line):
+ def start(self, command_line, ps_script=None):
log.debug("LongRunningCommand run_command: {0}".format(command_line))
- elem = yield self._sender.send_request('create')
- self._shell_id = _find_shell_id(elem)
- command_line_elem = _build_command_line_elem(command_line)
+ if self._shell_id is None:
+ elem = yield self._sender.send_request('create')
+ self._shell_id = _find_shell_id(elem)
+ if ps_script is not None:
+ command_line_elem = _build_ps_command_line_elem(command_line, ps_script)
+ else:
+ command_line_elem = _build_command_line_elem(command_line)
log.debug('LongRunningCommand run_command: sending command request '
'(shell_id={0}, command_line_elem={1})'.format(
self._shell_id, command_line_elem))
@@ -196,7 +241,7 @@ class LongRunningCommand(object):
command_line_elem=command_line_elem,
timeout=self._sender._sender._conn_info.timeout)
except TimeoutError:
- yield self._sender.close_connections()
+ yield self.delete_and_close()
raise
self._command_id = _find_command_id(command_elem)
@@ -208,7 +253,7 @@ class LongRunningCommand(object):
shell_id=self._shell_id,
command_id=self._command_id)
except TimeoutError:
- yield self._sender.close_connections()
+ yield self.delete_and_close()
raise
stdout_parts = _find_stream(receive_elem, self._command_id, 'stdout')
stderr_parts = _find_stream(receive_elem, self._command_id, 'stderr')
@@ -218,23 +263,48 @@ class LongRunningCommand(object):
defer.returnValue((stdout, stderr))
@defer.inlineCallbacks
+ def delete_and_close(self):
+ """Delete the remote shell and close connection"""
+ yield self._sender.send_request('delete', shell_id=self._shell_id)
+ self._shell_id = None
+ yield self._sender.close_connections()
+ defer.returnValue(None)
+
+ @defer.inlineCallbacks
def stop(self):
- yield self._sender.send_request(
- 'signal',
- shell_id=self._shell_id,
- command_id=self._command_id,
- signal_code=c.SHELL_SIGNAL_CTRL_C)
+ for _ in xrange(_MAX_RETRIES):
+ try:
+ yield self._sender.send_request(
+ 'signal',
+ shell_id=self._shell_id,
+ command_id=self._command_id,
+ signal_code=c.SHELL_SIGNAL_CTRL_C)
+ except RequestError as e:
+ # if we get a 500 error back, let's try again
+ if 'HTTP status: 500. An internal error occurred' in e.message:
+ continue
+ else:
+ yield self.delete_and_close()
+ raise e
+ except Exception:
+ yield self.delete_and_close()
+ raise
+ else:
+ break
try:
stdout, stderr = yield self.receive()
except TimeoutError:
- # close_connections done in receive()
+ # close_connections done in receive() for TimeoutError
+ raise
+ try:
+ yield self._sender.send_request(
+ 'signal',
+ shell_id=self._shell_id,
+ command_id=self._command_id,
+ signal_code=c.SHELL_SIGNAL_TERMINATE)
+ except RequestError:
pass
- yield self._sender.send_request(
- 'signal',
- shell_id=self._shell_id,
- command_id=self._command_id,
- signal_code=c.SHELL_SIGNAL_TERMINATE)
- yield self._sender.send_request('delete', shell_id=self._shell_id)
+ yield self.delete_and_close()
defer.returnValue(CommandResponse(stdout, stderr, self._exit_code))
diff --git a/txwinrm/util.py b/txwinrm/util.py
index 79a8694..417a5f9 100755
--- a/txwinrm/util.py
+++ b/txwinrm/util.py
@@ -19,6 +19,7 @@ from xml.etree.ElementTree import ParseError
from twisted.internet import reactor, defer
from twisted.internet.protocol import Protocol
from twisted.web.client import Agent
+from twisted.internet.error import ConnectError
from twisted.internet.ssl import ClientContextFactory
from twisted.web.http_headers import Headers
from twisted.internet.threads import deferToThread
@@ -149,7 +150,11 @@ class _ErrorReader(Protocol):
def connectionLost(self, reason):
if self.gssclient:
- body = self.gssclient.decrypt_body(''.join(self._data))
+ try:
+ body = self.gssclient.decrypt_body(''.join(self._data))
+ except Exception as e:
+ body = 'There was a problem decrypting an error message: {}.'\
+ ' Check WinRM logs on {}'.format(e.message, self.gssclient._conn_info.hostname)
else:
body = ''.join(self._data)
message = _parse_error_message(body)
@@ -265,7 +270,8 @@ class AuthGSSClient(object):
kinit_result = yield kinit(self._username,
self._password,
self._dcip,
- includedir=self._include_dir)
+ includedir=self._include_dir,
+ disable_rdns=self._conn_info.disable_rdns)
if kinit_result:
# this error is ok. it just means more
# than one process is calling kinit
@@ -432,11 +438,12 @@ class ConnectionInfo(namedtuple(
'envelope_size',
'code_page',
'locale',
- 'include_dir'])):
+ 'include_dir',
+ 'disable_rdns'])):
def __new__(cls, hostname, auth_type, username, password, scheme, port,
connectiontype, keytab, dcip, timeout=60, trusted_realm='',
trusted_kdc='', ipaddress='', service='', envelope_size=512000,
- code_page=65001, locale='en-US', include_dir=None):
+ code_page=65001, locale='en-US', include_dir=None, disable_rdns=False):
if not ipaddress:
ipaddress = hostname
if not service:
@@ -448,7 +455,7 @@ class ConnectionInfo(namedtuple(
trusted_realm, trusted_kdc,
ipaddress, service,
envelope_size, code_page, locale,
- include_dir)
+ include_dir, disable_rdns)
def verify_include_dir(conn_info):
@@ -614,30 +621,43 @@ class RequestSender(object):
body_producer = _StringProducer(encrypted_request)
else:
body_producer = _StringProducer(request)
+
+ @defer.inlineCallbacks
+ def reset_agent_resend(sender, request, body_producer):
+ sender.agent = _get_agent()
+ if sender.gssclient is not None:
+ # do some cleanup first. memory leaks were occurring
+ sender.gssclient.cleanup()
+ sender.gssclient = None
+ try:
+ yield sender._set_url_and_headers()
+ encrypted_request = sender.gssclient.encrypt_body(request)
+ if not encrypted_request.startswith("--Encrypted Boundary"):
+ sender._headers.setRawHeaders('Content-Type', _CONTENT_TYPE['Content-Type'])
+ body_producer = _StringProducer(encrypted_request)
+ except Exception as e:
+ raise e
+ try:
+ response = yield sender.agent.request(
+ 'POST', sender._url, sender._headers, body_producer)
+ except Exception as e:
+ raise e
+ defer.returnValue(response)
+
try:
response = yield self.agent.request(
'POST', self._url, self._headers, body_producer)
+ except ConnectError:
+ # network timeout. could be stale connection, so let's reset
+ response = yield reset_agent_resend(self, request, body_producer)
except Exception as e:
raise e
+
log.debug('received response {0} {1}'.format(
response.code, request_template_name))
if response.code == httplib.UNAUTHORIZED or response.code == httplib.BAD_REQUEST:
# check to see if we need to re-authorize due to lost connection or bad request error
- if self.gssclient is not None:
- self.agent = _get_agent()
- # do some cleanup first. memory leaks were occurring
- self.gssclient.cleanup()
- self.gssclient = None
- try:
- yield self._set_url_and_headers()
- encrypted_request = self.gssclient.encrypt_body(request)
- if not encrypted_request.startswith("--Encrypted Boundary"):
- self._headers.setRawHeaders('Content-Type', _CONTENT_TYPE['Content-Type'])
- body_producer = _StringProducer(encrypted_request)
- response = yield self.agent.request(
- 'POST', self._url, self._headers, body_producer)
- except Exception as e:
- raise e
+ response = yield reset_agent_resend(self, request, body_producer)
if response.code == httplib.UNAUTHORIZED:
if self.is_kerberos():
auth_header = response.headers.getRawHeaders('WWW-Authenticate')[0]
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/txwinrm.git
More information about the Python-modules-commits
mailing list