Timeout when performing time sync during client install

We use ntpd now to sync time before fetching a TGT during client
install.  Unfortuantely, ntpd will hang forever if it is unable to
reach the NTP server.

This patch adds the ability for commands run via ipautil.run() to
have an optional timeout.  This capability is used by the NTP sync
code that is run during ipa-client-install.

Ticket: https://fedorahosted.org/freeipa/ticket/4842
Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
This commit is contained in:
Nathan Kinder
2015-02-25 15:19:47 -08:00
committed by Martin Kosek
parent fbf192f0e2
commit a58b77ca9c
3 changed files with 19 additions and 2 deletions

View File

@@ -18,6 +18,7 @@
#
from ipapython import ipautil
from ipapython.ipa_log_manager import root_logger
import shutil
import os
from ipaplatform.tasks import tasks
@@ -149,7 +150,12 @@ def synconce_ntp(server_fqdn):
tmp_ntp_conf = ipautil.write_tmp_file('server %s' % server_fqdn)
try:
ipautil.run([ntpd, '-qgc', tmp_ntp_conf.name])
# The ntpd command will never exit if it is unable to reach the
# server, so timeout after 15 seconds.
timeout = 15
root_logger.info('Attempting to sync time using ntpd. '
'Will timeout after %d seconds' % timeout)
ipautil.run([ntpd, '-qgc', tmp_ntp_conf.name], timeout=timeout)
return True
except ipautil.CalledProcessError:
return False

View File

@@ -186,6 +186,7 @@ class BasePathNamespace(object):
SSLGET = "/usr/bin/sslget"
SSS_SSH_AUTHORIZEDKEYS = "/usr/bin/sss_ssh_authorizedkeys"
SSS_SSH_KNOWNHOSTSPROXY = "/usr/bin/sss_ssh_knownhostsproxy"
BIN_TIMEOUT = "/usr/bin/timeout"
UPDATE_CA_TRUST = "/usr/bin/update-ca-trust"
BIN_WGET = "/usr/bin/wget"
ZIP = "/usr/bin/zip"

View File

@@ -249,7 +249,7 @@ def shell_quote(string):
def run(args, stdin=None, raiseonerr=True,
nolog=(), env=None, capture_output=True, skip_output=False, cwd=None,
runas=None):
runas=None, timeout=None):
"""
Execute a command and return stdin, stdout and the process return code.
@@ -277,6 +277,8 @@ def run(args, stdin=None, raiseonerr=True,
:param cwd: Current working directory
:param runas: Name of a user that the command shold be run as. The spawned
process will have both real and effective UID and GID set.
:param timeout: Timeout if the command hasn't returned within the specified
number of seconds.
"""
p_in = None
p_out = None
@@ -302,6 +304,11 @@ def run(args, stdin=None, raiseonerr=True,
p_out = subprocess.PIPE
p_err = subprocess.PIPE
if timeout:
# If a timeout was provided, use the timeout command
# to execute the requested command.
args[0:0] = [paths.BIN_TIMEOUT, str(timeout)]
arg_string = nolog_replace(' '.join(shell_quote(a) for a in args), nolog)
root_logger.debug('Starting external process')
root_logger.debug('args=%s' % arg_string)
@@ -332,6 +339,9 @@ def run(args, stdin=None, raiseonerr=True,
if skip_output:
p_out.close() # pylint: disable=E1103
if timeout and p.returncode == 124:
root_logger.debug('Process did not complete before timeout')
root_logger.debug('Process finished, return code=%s', p.returncode)
# The command and its output may include passwords that we don't want