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

enhance recv calls in network_cli (#47345)

* enhance recv calls in network_cli

* updated network_cli test unit

* enhance recv calls in network_cli

* fix mistake

* better timeout management

* remove exception trigger

* test

* test2

* restore exception and timeout

* ganeshrn's way

* correction

* timeout and exception return
This commit is contained in:
f-bor 2018-10-26 06:19:17 +02:00 committed by Ganesh Nalawade
parent 9fe20123cf
commit c649d0ea32
2 changed files with 16 additions and 2 deletions

View file

@ -182,6 +182,7 @@ import os
import signal import signal
import socket import socket
import traceback import traceback
import time
from io import BytesIO from io import BytesIO
from ansible.errors import AnsibleConnectionFailure from ansible.errors import AnsibleConnectionFailure
@ -359,6 +360,15 @@ class Connection(NetworkConnectionBase):
display.debug("ssh connection has been closed successfully") display.debug("ssh connection has been closed successfully")
super(Connection, self).close() super(Connection, self).close()
def receive_ssh_data(self, count, timeout):
if timeout:
start = time.time()
while not self._ssh_shell.recv_ready():
if time.time() - start >= timeout:
raise AnsibleConnectionFailure("timeout waiting ssh data")
time.sleep(0.001)
return self._ssh_shell.recv(count)
def receive(self, command=None, prompts=None, answer=None, newline=True, prompt_retry_check=False, check_all=False): def receive(self, command=None, prompts=None, answer=None, newline=True, prompt_retry_check=False, check_all=False):
''' '''
Handles receiving of output from command Handles receiving of output from command
@ -376,12 +386,14 @@ class Connection(NetworkConnectionBase):
buffer_read_timeout = self.get_option('persistent_buffer_read_timeout') buffer_read_timeout = self.get_option('persistent_buffer_read_timeout')
self._validate_timeout_value(buffer_read_timeout, "persistent_buffer_read_timeout") self._validate_timeout_value(buffer_read_timeout, "persistent_buffer_read_timeout")
receive_data_timeout = self._ssh_shell.gettimeout()
while True: while True:
if command_prompt_matched: if command_prompt_matched:
try: try:
signal.signal(signal.SIGALRM, self._handle_buffer_read_timeout) signal.signal(signal.SIGALRM, self._handle_buffer_read_timeout)
signal.setitimer(signal.ITIMER_REAL, buffer_read_timeout) signal.setitimer(signal.ITIMER_REAL, buffer_read_timeout)
data = self._ssh_shell.recv(256) data = self.receive_ssh_data(256, receive_data_timeout)
signal.alarm(0) signal.alarm(0)
# if data is still received on channel it indicates the prompt string # if data is still received on channel it indicates the prompt string
# is wrongly matched in between response chunks, continue to read # is wrongly matched in between response chunks, continue to read
@ -395,7 +407,7 @@ class Connection(NetworkConnectionBase):
except AnsibleCmdRespRecv: except AnsibleCmdRespRecv:
return self._command_response return self._command_response
else: else:
data = self._ssh_shell.recv(256) data = self.receive_ssh_data(256, receive_data_timeout)
# when a channel stream is closed, received data will be empty # when a channel stream is closed, received data will be empty
if not data: if not data:

View file

@ -126,6 +126,8 @@ class TestConnectionClass(unittest.TestCase):
mock__shell = MagicMock() mock__shell = MagicMock()
conn._ssh_shell = mock__shell conn._ssh_shell = mock__shell
conn._ssh_shell.recv_ready.return_value = True
conn._ssh_shell.gettimeout.return_value = 10
response = b"""device#command response = b"""device#command
command response command response