Skip to content

Commit e95a0e7

Browse files
Radovan Zvoncekadejanovski
authored andcommitted
Remove code duplication of #40
1 parent c545395 commit e95a0e7

File tree

1 file changed

+54
-92
lines changed

1 file changed

+54
-92
lines changed

cstar/remote_paramiko.py

Lines changed: 54 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -101,55 +101,13 @@ def run_job(self, file, jobid, timeout=None, env={}):
101101
self.write_command(wrapper, "%s/wrapper" % (dir,))
102102

103103
cmd = """
104-
cd %s
105-
nohup ./wrapper
106-
""" % (self.escape(dir),)
104+
cd %s
105+
nohup ./wrapper
106+
""" % (self.escape(dir),)
107107

108108
stdin, stdout, stderr = self.client.exec_command(cmd, timeout=timeout)
109-
# get the shared channel for stdout/stderr/stdin
110-
channel = stdout.channel
111-
112-
stdin.close()
113-
# indicate that we're not going to write to that channel anymore
114-
channel.shutdown_write()
115-
116-
# read stdout/stderr in order to prevent read block hangs
117-
stdout_chunks = []
118-
stdout_chunks.append(stdout.channel.recv(len(stdout.channel.in_buffer)))
119-
# chunked read to prevent stalls
120-
while not channel.closed or channel.recv_ready() or channel.recv_stderr_ready():
121-
# stop if channel was closed prematurely, and there is no data in the buffers.
122-
got_chunk = False
123-
readq, _, _ = select.select([stdout.channel], [], [], timeout)
124-
for c in readq:
125-
if c.recv_ready():
126-
stdout_chunks.append(stdout.channel.recv(len(c.in_buffer)))
127-
got_chunk = True
128-
if c.recv_stderr_ready():
129-
# make sure to read stderr to prevent stall
130-
stderr.channel.recv_stderr(len(c.in_stderr_buffer))
131-
got_chunk = True
132-
'''
133-
1) make sure that there are at least 2 cycles with no data in the input buffers in order to not exit too early (i.e. cat on a >200k file).
134-
2) if no data arrived in the last loop, check if we already received the exit code
135-
3) check if input buffers are empty
136-
4) exit the loop
137-
'''
138-
if not got_chunk \
139-
and stdout.channel.exit_status_ready() \
140-
and not stderr.channel.recv_stderr_ready() \
141-
and not stdout.channel.recv_ready():
142-
# indicate that we're not going to read from this channel anymore
143-
stdout.channel.shutdown_read()
144-
# close the channel
145-
stdout.channel.close()
146-
break # exit as remote side is finished and our bufferes are empty
147-
148-
# close all the pseudofiles
149-
stdout.close()
150-
stderr.close()
109+
_, _, _ = self._read_results(stdin, stdout, stderr, timeout)
151110

152-
stdout.channel.recv_exit_status()
153111
real_output = self.read_file(dir + "/stdout")
154112
real_error = self.read_file(dir + "/stderr")
155113
real_status = int(self.read_file(dir + "/status"))
@@ -165,54 +123,10 @@ def run(self, argv):
165123
self._connect()
166124
cmd = " ".join(self.escape(s) for s in argv)
167125
stdin, stdout, stderr = self.client.exec_command(cmd)
168-
# get the shared channel for stdout/stderr/stdin
169-
channel = stdout.channel
170-
171-
# we do not need stdin.
172-
stdin.close()
173-
# indicate that we're not going to write to that channel anymore
174-
channel.shutdown_write()
175-
176-
# read stdout/stderr in order to prevent read block hangs
177-
stdout_chunks = []
178-
stderr_chunks = []
179-
stdout_chunks.append(stdout.channel.recv(len(stdout.channel.in_buffer)))
180-
# chunked read to prevent stalls
181-
while not channel.closed or channel.recv_ready() or channel.recv_stderr_ready():
182-
# stop if channel was closed prematurely, and there is no data in the buffers.
183-
got_chunk = False
184-
readq, _, _ = select.select([stdout.channel], [], [], 30)
185-
for c in readq:
186-
if c.recv_ready():
187-
stdout_chunks.append(stdout.channel.recv(len(c.in_buffer)))
188-
got_chunk = True
189-
if c.recv_stderr_ready():
190-
# make sure to read stderr to prevent stall
191-
stderr_chunks.append(stderr.channel.recv_stderr(len(c.in_stderr_buffer)))
192-
got_chunk = True
193-
'''
194-
1) make sure that there are at least 2 cycles with no data in the input buffers in order to not exit too early (i.e. cat on a >200k file).
195-
2) if no data arrived in the last loop, check if we already received the exit code
196-
3) check if input buffers are empty
197-
4) exit the loop
198-
'''
199-
if not got_chunk \
200-
and stdout.channel.exit_status_ready() \
201-
and not stderr.channel.recv_stderr_ready() \
202-
and not stdout.channel.recv_ready():
203-
# indicate that we're not going to read from this channel anymore
204-
stdout.channel.shutdown_read()
205-
# close the channel
206-
stdout.channel.close()
207-
break # exit as remote side is finished and our bufferes are empty
208-
209-
# close all the pseudofiles
210-
stdout.close()
211-
stderr.close()
212-
126+
status, stdout_chunks, stderr_chunks = self._read_results(stdin, stdout, stderr)
213127
out = b''.join(stdout_chunks)
214128
error = b''.join(stderr_chunks)
215-
status = stdout.channel.recv_exit_status()
129+
216130
if status != 0:
217131
err("Command %s failed with status %d on host %s" % (cmd, status, self.hostname))
218132
else:
@@ -223,6 +137,54 @@ def run(self, argv):
223137
self.client = None
224138
raise BadSSHHost("SSH connection to host %s was reset" % (self.hostname,))
225139

140+
def _read_results(self, stdin, stdout, stderr, timeout=30):
141+
142+
# get the shared channel for stdout/stderr/stdin
143+
channel = stdout.channel
144+
145+
stdin.close()
146+
# indicate that we're not going to write to that channel anymore
147+
channel.shutdown_write()
148+
149+
# read stdout/stderr in order to prevent read block hangs
150+
stdout_chunks, stderr_chunks = [], []
151+
stdout_chunks.append(stdout.channel.recv(len(stdout.channel.in_buffer)))
152+
# chunked read to prevent stalls
153+
while not channel.closed or channel.recv_ready() or channel.recv_stderr_ready():
154+
# stop if channel was closed prematurely, and there is no data in the buffers.
155+
got_chunk = False
156+
readq, _, _ = select.select([stdout.channel], [], [], timeout)
157+
for c in readq:
158+
if c.recv_ready():
159+
stdout_chunks.append(stdout.channel.recv(len(c.in_buffer)))
160+
got_chunk = True
161+
if c.recv_stderr_ready():
162+
# make sure to read stderr to prevent stall
163+
stderr_chunks.append(stderr.channel.recv_stderr(len(c.in_stderr_buffer)))
164+
got_chunk = True
165+
'''
166+
1) make sure that there are at least 2 cycles with no data in the input buffers in order to not exit too early (i.e. cat on a >200k file).
167+
2) if no data arrived in the last loop, check if we already received the exit code
168+
3) check if input buffers are empty
169+
4) exit the loop
170+
'''
171+
if not got_chunk \
172+
and stdout.channel.exit_status_ready() \
173+
and not stderr.channel.recv_stderr_ready() \
174+
and not stdout.channel.recv_ready():
175+
# indicate that we're not going to read from this channel anymore
176+
stdout.channel.shutdown_read()
177+
# close the channel
178+
stdout.channel.close()
179+
break # exit as remote side is finished and our bufferes are empty
180+
181+
# close all the pseudofiles
182+
stdout.close()
183+
stderr.close()
184+
185+
status = stdout.channel.recv_exit_status()
186+
return status, stdout_chunks, stderr_chunks
187+
226188
@staticmethod
227189
def escape(input):
228190
if _alnum_re.search(input):

0 commit comments

Comments
 (0)