summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Harlow <harlowja@yahoo-inc.com>2012-09-19 21:19:43 -0400
committerScott Moser <smoser@ubuntu.com>2012-09-19 21:19:43 -0400
commit94b9647e4df742982cac8a2c2925fb4894281dbf (patch)
treea10d98b98272020401c06d8cbc4be9b0bd256f8e
parent3912209cdb075b7af8f87c1e41170fd8614ca520 (diff)
parent5eef154928c75499c545c8c242bcf11d9ccf70d1 (diff)
downloadvyos-cloud-init-94b9647e4df742982cac8a2c2925fb4894281dbf.tar.gz
vyos-cloud-init-94b9647e4df742982cac8a2c2925fb4894281dbf.zip
if a logged message fails, fallback to logging to stdout
This most commonly occurs if a user-data script does '/sbin/poweroff' where syslog was being used. Once poweroff is invoked, syslog gets killed and logging would start to show stack traces. This generally tries to continue working instead, but log to stderr.
-rw-r--r--ChangeLog2
-rwxr-xr-xbin/cloud-init3
-rw-r--r--cloudinit/patcher.py56
3 files changed, 61 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index aca34d6e..c5dcd418 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,6 @@
0.7.0:
+ - catch signals and exit rather than stack tracing
+ - if logging fails, enable a fallback logger by patching the logging module
- do not 'start networking' in cloud-init-nonet, but add
cloud-init-container job that runs only if in container and emits
net-device-added (LP: #1031065)
diff --git a/bin/cloud-init b/bin/cloud-init
index a6ad14a6..c5a5b949 100755
--- a/bin/cloud-init
+++ b/bin/cloud-init
@@ -33,6 +33,9 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(
if os.path.exists(os.path.join(possible_topdir, "cloudinit", "__init__.py")):
sys.path.insert(0, possible_topdir)
+from cloudinit import patcher
+patcher.patch()
+
from cloudinit import log as logging
from cloudinit import netinfo
from cloudinit import signal_handler
diff --git a/cloudinit/patcher.py b/cloudinit/patcher.py
new file mode 100644
index 00000000..8921a79a
--- /dev/null
+++ b/cloudinit/patcher.py
@@ -0,0 +1,56 @@
+# vi: ts=4 expandtab
+#
+# Copyright (C) 2012 Canonical Ltd.
+# Copyright (C) 2012 Yahoo! Inc.
+#
+# Author: Scott Moser <scott.moser@canonical.com>
+# Author: Joshua Harlow <harlowja@yahoo-inc.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 3, as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import imp
+import logging
+import sys
+
+# Default fallback format
+FALL_FORMAT = 'FALLBACK: %(asctime)s - %(filename)s[%(levelname)s]: %(message)s'
+
+
+class QuietStreamHandler(logging.StreamHandler):
+ def handleError(self, record):
+ pass
+
+
+def _patch_logging():
+ # Replace 'handleError' with one that will be more
+ # tolerant of errors in that it can avoid
+ # re-notifying on exceptions and when errors
+ # do occur, it can at least try to write to
+ # sys.stderr using a fallback logger
+ fallback_handler = QuietStreamHandler(sys.stderr)
+ fallback_handler.setFormatter(logging.Formatter(FALL_FORMAT))
+ def handleError(self, record):
+ try:
+ fallback_handler.handle(record)
+ fallback_handler.flush()
+ except IOError:
+ pass
+ setattr(logging.Handler, 'handleError', handleError)
+
+
+def patch():
+ imp.acquire_lock()
+ try:
+ _patch_logging()
+ finally:
+ imp.release_lock()