From 7d544a289852c761fc209772064f794fb0472198 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Mon, 22 Jul 2013 09:08:32 -0400 Subject: Packages: Added timeout to bcfg2-yum-helper calls This involved making the Yum backend use Bcfg2.Utils.Executor to call bcfg2-yum-helper instead of subprocess.Popen directly. This was cherry-picked (kinda) from 3d06f311274d6b942ee89d8cdb13b2ecc99af1b0, so will likely break the maint -> master merge in spectacular ways. --- src/lib/Bcfg2/Options.py | 3 +- src/lib/Bcfg2/Server/Plugins/Packages/Yum.py | 54 +++++++++++----------------- 2 files changed, 22 insertions(+), 35 deletions(-) (limited to 'src/lib/Bcfg2') diff --git a/src/lib/Bcfg2/Options.py b/src/lib/Bcfg2/Options.py index dba3e96ef..3d105bf30 100644 --- a/src/lib/Bcfg2/Options.py +++ b/src/lib/Bcfg2/Options.py @@ -1221,7 +1221,8 @@ SERVER_COMMON_OPTIONS = dict(repo=SERVER_REPOSITORY, authentication=SERVER_AUTHENTICATION, perflog=LOG_PERFORMANCE, perflog_interval=PERFLOG_INTERVAL, - children=SERVER_CHILDREN) + children=SERVER_CHILDREN, + client_timeout=CLIENT_TIMEOUT) CRYPT_OPTIONS = dict(encrypt=ENCRYPT, decrypt=DECRYPT, diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py index 7a90f4f2e..e0002ef34 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py @@ -59,9 +59,9 @@ import errno import socket import logging import lxml.etree -from lockfile import FileLock -from subprocess import Popen, PIPE import Bcfg2.Server.Plugin +from lockfile import FileLock +from Bcfg2.Utils import Executor # pylint: disable=W0622 from Bcfg2.Compat import StringIO, cPickle, HTTPError, URLError, \ ConfigParser, any @@ -279,6 +279,7 @@ class YumCollection(Collection): debug=debug) self.keypath = os.path.join(self.cachepath, "keys") + self._helper = None if self.use_yum: #: Define a unique cache file for this collection to use #: for cached yum metadata @@ -294,8 +295,10 @@ class YumCollection(Collection): os.mkdir(self.cachefile) if not self.disableMetaData: self.setup_data() + self.cmd = Executor() else: self.cachefile = None + self.cmd = None if HAS_PULP and self.has_pulp_sources: _setup_pulp(self.setup) @@ -348,20 +351,18 @@ class YumCollection(Collection): a call to it; I wish there was a way to do this without forking, but apparently not); finally we check in /usr/sbin, the default location. """ - global HELPER - if not HELPER: + if not self._helper: try: - HELPER = self.setup.cfp.get("packages:yum", "helper") + self._helper = self.setup.cfp.get("packages:yum", "helper") except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): # first see if bcfg2-yum-helper is in PATH try: self.debug_log("Checking for bcfg2-yum-helper in $PATH") - Popen(['bcfg2-yum-helper'], - stdin=PIPE, stdout=PIPE, stderr=PIPE).wait() - HELPER = 'bcfg2-yum-helper' + self.cmd.run(['bcfg2-yum-helper']) + self._helper = 'bcfg2-yum-helper' except OSError: - HELPER = "/usr/sbin/bcfg2-yum-helper" - return HELPER + self._helper = "/usr/sbin/bcfg2-yum-helper" + return self._helper @property def use_yum(self): @@ -925,36 +926,21 @@ class YumCollection(Collection): cmd.append("-v") cmd.append(command) self.debug_log("Packages: running %s" % " ".join(cmd)) - try: - helper = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE) - except OSError: - err = sys.exc_info()[1] - self.logger.error("Packages: Failed to execute %s: %s" % - (" ".join(cmd), err)) - return None if inputdata: - idata = json.dumps(inputdata) - (stdout, stderr) = helper.communicate(idata) + result = self.cmd.run(cmd, timeout=self.setup['client_timeout'], + inputdata=json.dumps(inputdata)) else: - (stdout, stderr) = helper.communicate() - rv = helper.wait() - errlines = stderr.splitlines() - if rv: - if not errlines: - errlines.append("No error output") - self.logger.error("Packages: error running bcfg2-yum-helper " - "(returned %d): %s" % (rv, errlines[0])) - for line in errlines[1:]: - self.logger.error("Packages: %s" % line) - elif errlines: + result = self.cmd.run(cmd, timeout=self.setup['client_timeout']) + if not result.success: + self.logger.error("Packages: error running bcfg2-yum-helper: %s" % + result.error) + elif result.stderr: self.debug_log("Packages: debug info from bcfg2-yum-helper: %s" % - errlines[0]) - for line in errlines[1:]: - self.debug_log("Packages: %s" % line) + result.stderr) try: - return json.loads(stdout) + return json.loads(result.stdout) except ValueError: err = sys.exc_info()[1] self.logger.error("Packages: error reading bcfg2-yum-helper " -- cgit v1.2.3-1-g7c22