Commit 26f15862 authored by Iustin Pop's avatar Iustin Pop
Browse files

An attempt at fixing some encoding issues

This patch unifies the hardcoded re-encoding attempts into a single
function in This function is used to take either an unicode or
str object and convert it to a ASCII-only str object which can be safely
displayed and transmitted.

We replace then the current manual re-encodings with this function. In
mcpu we stop re-encoding the hooks output and instead we do it right at
the hook generation in

This passes on my 'custom' lvs output with non-ASCII chars. But there
are probably other places we will need to fix.

Reviewed-by: ultrotter
parent d1687c6f
......@@ -691,7 +691,7 @@ def AddOSToInstance(instance):
logging.error("os create command '%s' returned error: %s, logfile: %s,"
" output: %s", result.cmd, result.fail_reason, logfile,
lines = [val.encode("string_escape")
lines = [utils.SafeEncode(val)
for val in utils.TailFile(logfile, lines=20)]
return (False, "OS create script failed (%s), last lines in the"
" log file:\n%s" % (result.fail_reason, "\n".join(lines)))
......@@ -725,7 +725,7 @@ def RunRenameInstance(instance, old_name):
if result.failed:
logging.error("os create command '%s' returned error: %s output: %s",
result.cmd, result.fail_reason, result.output)
lines = [val.encode("string_escape")
lines = [utils.SafeEncode(val)
for val in utils.TailFile(logfile, lines=20)]
return (False, "OS rename script failed (%s), last lines in the"
" log file:\n%s" % (result.fail_reason, "\n".join(lines)))
......@@ -2434,7 +2434,7 @@ class HooksRunner(object):
#logging.exception("Error while closing fd %s", fd)
return result == 0, output
return result == 0, utils.SafeEncode(output.strip())
def RunHooks(self, hpath, phase, env):
"""Run the scripts in the hooks directory.
......@@ -554,7 +554,8 @@ def PollJob(job_id, cl=None, feedback_fn=None):
if callable(feedback_fn):
print "%s %s" % (time.ctime(utils.MergeTime(timestamp)), message)
encoded = utils.SafeEncode(message)
print "%s %s" % (time.ctime(utils.MergeTime(timestamp)), encoded)
prev_logmsg_serial = max(prev_logmsg_serial, serial)
# TODO: Handle canceled and archived jobs
......@@ -976,7 +976,7 @@ class LUVerifyCluster(LogicalUnit):
lvdata = nresult.get(constants.NV_LVLIST, "Missing LV data")
if isinstance(lvdata, basestring):
feedback_fn(" - ERROR: LVM problem on node %s: %s" %
(node, lvdata.encode('string_escape')))
(node, utils.SafeEncode(lvdata)))
bad = True
node_volume[node] = {}
elif not isinstance(lvdata, dict):
......@@ -346,7 +346,6 @@ class HooksMaster(object):
for script, hkr, output in
if hkr == constants.HKR_FAIL:
output = output.strip().encode("string_escape")
errs.append((node_name, script, output))
if errs:
raise errors.HooksAbort(errs)
......@@ -576,7 +576,7 @@ def CheckBEParams(beparams):
val = int(val)
except ValueError, err:
raise errors.OpPrereqError("Invalid %s size: %s" % (item, str(err)))
raise errors.OpPrereqError("Invalid %s size: %s" % (item, err))
beparams[item] = val
if item in (constants.BE_AUTO_BALANCE):
val = beparams[item]
......@@ -1743,6 +1743,27 @@ def TailFile(fname, lines=20):
return rows[-lines:]
def SafeEncode(text):
"""Return a 'safe' version of a source string.
This function mangles the input string and returns a version that
should be safe to disply/encode as ASCII. To this end, we first
convert it to ASCII using the 'backslashreplace' encoding which
should get rid of any non-ASCII chars, and then we again encode it
via 'string_escape' which converts '\n' into '\\n' so that log
messages remain one-line.
@type text: str or unicode
@param text: input data
@rtype: str
@return: a safe version of text
text = text.encode('ascii', 'backslashreplace')
text = text.encode('string_escape')
return text
def LockedMethod(fn):
"""Synchronized object access decorator.
......@@ -381,7 +381,7 @@ def VerifyDisks(opts, args):
if nlvm:
for node, text in nlvm.iteritems():
ToStdout("Error on node %s: LVM error: %s",
node, text[-400:].encode('string_escape'))
node, utils.SafeEncode(text[-400:]))
retcode |= 1
ToStdout("You need to fix these nodes first before fixing instances")
......@@ -28,6 +28,7 @@ import sys
from ganeti.cli import *
from ganeti import constants
from ganeti import errors
from ganeti import utils
#: default list of fields for L{ListJobs}
......@@ -307,7 +308,7 @@ def ShowJobs(opts, args):
format(3, "Execution log:")
for serial, log_ts, log_type, log_msg in log:
time_txt = FormatTimestamp(log_ts)
encoded = str(log_msg).encode('string_escape')
encoded = utils.SafeEncode(log_msg)
format(4, "%s:%s:%s %s" % (serial, time_txt, log_type, encoded))
return 0
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment