207 |
207 |
|
208 |
208 |
|
209 |
209 |
def ProcessChildIO(child, socat_stderr_read_fd, dd_stderr_read_fd,
|
210 |
|
dd_pid_read_fd, status_file, child_logger,
|
|
210 |
dd_pid_read_fd, exp_size_read_fd, status_file, child_logger,
|
211 |
211 |
signal_notify, signal_handler, mode):
|
212 |
212 |
"""Handles the child processes' output.
|
213 |
213 |
|
... | ... | |
221 |
221 |
socat_stderr_read = os.fdopen(socat_stderr_read_fd, "r", 0)
|
222 |
222 |
dd_stderr_read = os.fdopen(dd_stderr_read_fd, "r", 0)
|
223 |
223 |
dd_pid_read = os.fdopen(dd_pid_read_fd, "r", 0)
|
|
224 |
exp_size_read = os.fdopen(exp_size_read_fd, "r", 0)
|
224 |
225 |
|
225 |
226 |
tp_samples = DD_THROUGHPUT_SAMPLES
|
226 |
227 |
|
|
228 |
if options.exp_size == constants.IE_CUSTOM_SIZE:
|
|
229 |
exp_size = None
|
|
230 |
else:
|
|
231 |
exp_size = options.exp_size
|
|
232 |
|
227 |
233 |
child_io_proc = impexpd.ChildIOProcessor(options.debug, status_file,
|
228 |
|
child_logger,
|
229 |
|
throughput_samples=tp_samples)
|
|
234 |
child_logger, tp_samples,
|
|
235 |
exp_size)
|
230 |
236 |
try:
|
231 |
237 |
fdmap = {
|
232 |
238 |
child.stderr.fileno():
|
... | ... | |
237 |
243 |
(dd_pid_read, child_io_proc.GetLineSplitter(impexpd.PROG_DD_PID)),
|
238 |
244 |
dd_stderr_read.fileno():
|
239 |
245 |
(dd_stderr_read, child_io_proc.GetLineSplitter(impexpd.PROG_DD)),
|
|
246 |
exp_size_read.fileno():
|
|
247 |
(exp_size_read, child_io_proc.GetLineSplitter(impexpd.PROG_EXP_SIZE)),
|
240 |
248 |
signal_notify.fileno(): (signal_notify, None),
|
241 |
249 |
}
|
242 |
250 |
|
... | ... | |
372 |
380 |
type="choice", help="Compression method",
|
373 |
381 |
metavar="[%s]" % "|".join(constants.IEC_ALL),
|
374 |
382 |
choices=list(constants.IEC_ALL), default=constants.IEC_GZIP)
|
|
383 |
parser.add_option("--expected-size", dest="exp_size", action="store",
|
|
384 |
type="string", default=None,
|
|
385 |
help="Expected import/export size (MiB)")
|
375 |
386 |
parser.add_option("--cmd-prefix", dest="cmd_prefix", action="store",
|
376 |
387 |
type="string", help="Command prefix")
|
377 |
388 |
parser.add_option("--cmd-suffix", dest="cmd_suffix", action="store",
|
... | ... | |
390 |
401 |
# Won't return
|
391 |
402 |
parser.error("Invalid mode: %s" % mode)
|
392 |
403 |
|
|
404 |
if (options.exp_size is not None and
|
|
405 |
options.exp_size != constants.IE_CUSTOM_SIZE):
|
|
406 |
try:
|
|
407 |
options.exp_size = int(options.exp_size)
|
|
408 |
except (ValueError, TypeError), err:
|
|
409 |
# Won't return
|
|
410 |
parser.error("Invalid value for --expected-size: %s (%s)" %
|
|
411 |
(options.exp_size, err))
|
|
412 |
|
393 |
413 |
return (status_file_path, mode)
|
394 |
414 |
|
395 |
415 |
|
396 |
416 |
class ChildProcess(subprocess.Popen):
|
397 |
|
def __init__(self, cmd, noclose_fds):
|
|
417 |
def __init__(self, env, cmd, noclose_fds):
|
398 |
418 |
"""Initializes this class.
|
399 |
419 |
|
400 |
420 |
"""
|
... | ... | |
402 |
422 |
|
403 |
423 |
# Not using close_fds because doing so would also close the socat stderr
|
404 |
424 |
# pipe, which we still need.
|
405 |
|
subprocess.Popen.__init__(self, cmd, shell=False, close_fds=False,
|
|
425 |
subprocess.Popen.__init__(self, cmd, env=env, shell=False, close_fds=False,
|
406 |
426 |
stderr=subprocess.PIPE, stdout=None, stdin=None,
|
407 |
427 |
preexec_fn=self._ChildPreexec)
|
408 |
428 |
self._SetProcessGroup()
|
... | ... | |
474 |
494 |
# Pipe to receive dd's PID
|
475 |
495 |
(dd_pid_read_fd, dd_pid_write_fd) = os.pipe()
|
476 |
496 |
|
|
497 |
# Pipe to receive size predicted by export script
|
|
498 |
(exp_size_read_fd, exp_size_write_fd) = os.pipe()
|
|
499 |
|
477 |
500 |
# Get child process command
|
478 |
501 |
cmd_builder = impexpd.CommandBuilder(mode, options, socat_stderr_write_fd,
|
479 |
502 |
dd_stderr_write_fd, dd_pid_write_fd)
|
480 |
503 |
cmd = cmd_builder.GetCommand()
|
481 |
504 |
|
|
505 |
# Prepare command environment
|
|
506 |
cmd_env = os.environ.copy()
|
|
507 |
|
|
508 |
if options.exp_size == constants.IE_CUSTOM_SIZE:
|
|
509 |
cmd_env["EXP_SIZE_FD"] = str(exp_size_write_fd)
|
|
510 |
|
482 |
511 |
logging.debug("Starting command %r", cmd)
|
483 |
512 |
|
484 |
513 |
# Start child process
|
485 |
|
child = ChildProcess(cmd, [socat_stderr_write_fd, dd_stderr_write_fd,
|
486 |
|
dd_pid_write_fd])
|
|
514 |
child = ChildProcess(cmd_env, cmd,
|
|
515 |
[socat_stderr_write_fd, dd_stderr_write_fd,
|
|
516 |
dd_pid_write_fd, exp_size_write_fd])
|
487 |
517 |
try:
|
488 |
518 |
def _ForwardSignal(signum, _):
|
489 |
519 |
"""Forwards signals to child process.
|
... | ... | |
506 |
536 |
utils.RetryOnSignal(os.close, socat_stderr_write_fd)
|
507 |
537 |
utils.RetryOnSignal(os.close, dd_stderr_write_fd)
|
508 |
538 |
utils.RetryOnSignal(os.close, dd_pid_write_fd)
|
|
539 |
utils.RetryOnSignal(os.close, exp_size_write_fd)
|
509 |
540 |
|
510 |
541 |
if ProcessChildIO(child, socat_stderr_read_fd, dd_stderr_read_fd,
|
511 |
|
dd_pid_read_fd, status_file, child_logger,
|
|
542 |
dd_pid_read_fd, exp_size_read_fd,
|
|
543 |
status_file, child_logger,
|
512 |
544 |
signal_wakeup, signal_handler, mode):
|
513 |
545 |
# The child closed all its file descriptors and there was no
|
514 |
546 |
# signal
|