1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

psrp - Fix fetch for large files (#55351)

* psrp - Fix fetch for large files

* Fix typo
This commit is contained in:
Jordan Borean 2019-04-17 08:19:33 +10:00 committed by GitHub
parent 33c2a9cea7
commit 52946c49a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 7 deletions

View file

@ -0,0 +1,2 @@
bugfixes:
- psrp - Fix issues when fetching large files causing a memory leak - https://github.com/ansible/ansible/issues/55239

View file

@ -283,7 +283,7 @@ HAS_PYPSRP = True
PYPSRP_IMP_ERR = None PYPSRP_IMP_ERR = None
try: try:
import pypsrp import pypsrp
from pypsrp.complex_objects import GenericComplexObject, RunspacePoolState from pypsrp.complex_objects import GenericComplexObject, PSInvocationState, RunspacePoolState
from pypsrp.exceptions import AuthenticationError, WinRMError from pypsrp.exceptions import AuthenticationError, WinRMError
from pypsrp.host import PSHost, PSHostUserInterface from pypsrp.host import PSHost, PSHostUserInterface
from pypsrp.powershell import PowerShell, RunspacePool from pypsrp.powershell import PowerShell, RunspacePool
@ -502,7 +502,7 @@ class Connection(ConnectionBase):
# setup the file stream with read only mode # setup the file stream with read only mode
setup_script = '''$ErrorActionPreference = "Stop" setup_script = '''$ErrorActionPreference = "Stop"
$path = "%s" $path = '%s'
if (Test-Path -Path $path -PathType Leaf) { if (Test-Path -Path $path -PathType Leaf) {
$fs = New-Object -TypeName System.IO.FileStream -ArgumentList @( $fs = New-Object -TypeName System.IO.FileStream -ArgumentList @(
@ -533,7 +533,8 @@ if ($bytes_read -gt 0) {
# need to run the setup script outside of the local scope so the # need to run the setup script outside of the local scope so the
# file stream stays active between fetch operations # file stream stays active between fetch operations
rc, stdout, stderr = self._exec_psrp_script(setup_script, rc, stdout, stderr = self._exec_psrp_script(setup_script,
use_local_scope=False) use_local_scope=False,
force_stop=True)
if rc != 0: if rc != 0:
raise AnsibleError("failed to setup file stream for fetch '%s': %s" raise AnsibleError("failed to setup file stream for fetch '%s': %s"
% (out_path, to_native(stderr))) % (out_path, to_native(stderr)))
@ -549,8 +550,7 @@ if ($bytes_read -gt 0) {
while True: while True:
display.vvvvv("PSRP FETCH %s to %s (offset=%d" % display.vvvvv("PSRP FETCH %s to %s (offset=%d" %
(in_path, out_path, offset), host=self._psrp_host) (in_path, out_path, offset), host=self._psrp_host)
rc, stdout, stderr = \ rc, stdout, stderr = self._exec_psrp_script(read_script % offset, force_stop=True)
self._exec_psrp_script(read_script % offset)
if rc != 0: if rc != 0:
raise AnsibleError("failed to transfer file to '%s': %s" raise AnsibleError("failed to transfer file to '%s': %s"
% (out_path, to_native(stderr))) % (out_path, to_native(stderr)))
@ -559,8 +559,9 @@ if ($bytes_read -gt 0) {
out_file.write(data) out_file.write(data)
if len(data) < buffer_size: if len(data) < buffer_size:
break break
offset += len(data)
rc, stdout, stderr = self._exec_psrp_script("$fs.Close()") rc, stdout, stderr = self._exec_psrp_script("$fs.Close()", force_stop=True)
if rc != 0: if rc != 0:
display.warning("failed to close remote file stream of file " display.warning("failed to close remote file stream of file "
"'%s': %s" % (in_path, to_native(stderr))) "'%s': %s" % (in_path, to_native(stderr)))
@ -682,12 +683,22 @@ if ($bytes_read -gt 0) {
option = self.get_option('_extras')['ansible_psrp_%s' % arg] option = self.get_option('_extras')['ansible_psrp_%s' % arg]
self._psrp_conn_kwargs[arg] = option self._psrp_conn_kwargs[arg] = option
def _exec_psrp_script(self, script, input_data=None, use_local_scope=True): def _exec_psrp_script(self, script, input_data=None, use_local_scope=True, force_stop=False):
ps = PowerShell(self.runspace) ps = PowerShell(self.runspace)
ps.add_script(script, use_local_scope=use_local_scope) ps.add_script(script, use_local_scope=use_local_scope)
ps.invoke(input=input_data) ps.invoke(input=input_data)
rc, stdout, stderr = self._parse_pipeline_result(ps) rc, stdout, stderr = self._parse_pipeline_result(ps)
if force_stop:
# This is usually not needed because we close the Runspace after our exec and we skip the call to close the
# pipeline manually to save on some time. Set to True when running multiple exec calls in the same runspace.
# Current pypsrp versions raise an exception if the current state was not RUNNING. We manually set it so we
# can call stop without any issues.
ps.state = PSInvocationState.RUNNING
ps.stop()
return rc, stdout, stderr return rc, stdout, stderr
def _parse_pipeline_result(self, pipeline): def _parse_pipeline_result(self, pipeline):