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:
parent
33c2a9cea7
commit
52946c49a4
2 changed files with 20 additions and 7 deletions
2
changelogs/fragments/psrp-fetch.yaml
Normal file
2
changelogs/fragments/psrp-fetch.yaml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
bugfixes:
|
||||||
|
- psrp - Fix issues when fetching large files causing a memory leak - https://github.com/ansible/ansible/issues/55239
|
|
@ -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):
|
||||||
|
|
Loading…
Reference in a new issue