From 8d14b30de885c9531ad7d2b365f5fd473b8702e1 Mon Sep 17 00:00:00 2001 From: Iustin Pop <iustin@google.com> Date: Mon, 21 Apr 2008 13:04:57 +0000 Subject: [PATCH] Abstract the json functions into a separate module This simple patch adds a new module that holds the simplejson functions for serialization/deserialization. This reduces the amount of redundant code. The patch also adds some normalizations to the json output: - the output text will always have an EOL as last char - extra spaces before EOL are removed Reviewed-by: ultrotter --- lib/Makefile.am | 2 +- lib/cmdlib.py | 22 ++++------------- lib/config.py | 6 +++-- lib/objects.py | 37 ----------------------------- lib/serializer.py | 60 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 58 deletions(-) create mode 100644 lib/serializer.py diff --git a/lib/Makefile.am b/lib/Makefile.am index 994b2a394..067034540 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -4,7 +4,7 @@ nodist_pkgpython_PYTHON = _autoconf.py pkgpython_PYTHON = __init__.py backend.py cli.py cmdlib.py config.py \ objects.py errors.py logger.py ssh.py utils.py rpc.py \ bdev.py hypervisor.py opcodes.py mcpu.py constants.py \ - ssconf.py locking.py luxi.py jqueue.py + ssconf.py locking.py luxi.py jqueue.py serializer.py all-local: _autoconf.py diff --git a/lib/cmdlib.py b/lib/cmdlib.py index 873f216db..2acbc05a5 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -30,7 +30,6 @@ import time import tempfile import re import platform -import simplejson from ganeti import rpc from ganeti import ssh @@ -43,14 +42,7 @@ from ganeti import constants from ganeti import objects from ganeti import opcodes from ganeti import ssconf - - -# Check whether the simplejson module supports indentation -_JSON_INDENT = 2 -try: - simplejson.dumps(1, indent=_JSON_INDENT) -except TypeError: - _JSON_INDENT = None +from ganeti import serializer class LogicalUnit(object): @@ -3162,10 +3154,7 @@ class LUCreateInstance(LogicalUnit): _IAllocatorAddNewInstance(al_data, op) - if _JSON_INDENT is None: - text = simplejson.dumps(al_data) - else: - text = simplejson.dumps(al_data, indent=_JSON_INDENT) + text = serializer.Dump(al_data) result = _IAllocatorRun(self.op.iallocator, text) @@ -4876,7 +4865,7 @@ def _IAllocatorValidateResult(data): """ try: - rdict = simplejson.loads(data) + rdict = serializer.Load(data) except Exception, err: raise errors.OpExecError("Can't parse iallocator results: %s" % str(err)) @@ -4968,10 +4957,7 @@ class LUTestAllocator(NoHooksLU): else: _IAllocatorAddRelocateInstance(data, self.op) - if _JSON_INDENT is None: - text = simplejson.dumps(data) - else: - text = simplejson.dumps(data, indent=_JSON_INDENT) + text = serializer.Dump(data) if self.op.direction == constants.IALLOCATOR_DIR_IN: result = text else: diff --git a/lib/config.py b/lib/config.py index 3b2599412..59d72515f 100644 --- a/lib/config.py +++ b/lib/config.py @@ -42,6 +42,7 @@ from ganeti import utils from ganeti import constants from ganeti import rpc from ganeti import objects +from ganeti import serializer class ConfigWriter: @@ -502,7 +503,7 @@ class ConfigWriter: f = open(self._cfg_file, 'r') try: try: - data = objects.ConfigData.Load(f) + data = objects.ConfigData.FromDict(serializer.Load(f.read())) except Exception, err: raise errors.ConfigurationError(err) finally: @@ -560,11 +561,12 @@ class ConfigWriter: if destination is None: destination = self._cfg_file self._BumpSerialNo() + txt = serializer.Dump(self._config_data.ToDict()) dir_name, file_name = os.path.split(destination) fd, name = tempfile.mkstemp('.newconfig', file_name, dir_name) f = os.fdopen(fd, 'w') try: - self._config_data.Dump(f) + f.write(txt) os.fsync(f.fileno()) finally: f.close() diff --git a/lib/objects.py b/lib/objects.py index 74c0c7e64..c84043375 100644 --- a/lib/objects.py +++ b/lib/objects.py @@ -27,7 +27,6 @@ pass to and from external parties. """ -import simplejson import ConfigParser import re from cStringIO import StringIO @@ -40,14 +39,6 @@ __all__ = ["ConfigObject", "ConfigData", "NIC", "Disk", "Instance", "OS", "Node", "Cluster"] -# Check whether the simplejson module supports indentation -_JSON_INDENT = 2 -try: - simplejson.dumps(1, indent=_JSON_INDENT) -except TypeError: - _JSON_INDENT = None - - class ConfigObject(object): """A generic config object. @@ -90,34 +81,6 @@ class ConfigObject(object): if name in self.__slots__: setattr(self, name, state[name]) - def Dump(self, fobj): - """Dump to a file object. - - """ - data = self.ToDict() - if _JSON_INDENT is None: - simplejson.dump(data, fobj) - else: - simplejson.dump(data, fobj, indent=_JSON_INDENT) - - @classmethod - def Load(cls, fobj): - """Load data from the given stream. - - """ - return cls.FromDict(simplejson.load(fobj)) - - def Dumps(self): - """Dump and return the string representation.""" - buf = StringIO() - self.Dump(buf) - return buf.getvalue() - - @classmethod - def Loads(cls, data): - """Load data from a string.""" - return cls.Load(StringIO(data)) - def ToDict(self): """Convert to a dict holding only standard python types. diff --git a/lib/serializer.py b/lib/serializer.py new file mode 100644 index 000000000..d00dbc593 --- /dev/null +++ b/lib/serializer.py @@ -0,0 +1,60 @@ +# +# + +# Copyright (C) 2007, 2008 Google Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +"""Serializer abstraction module + +This module introduces a simple abstraction over the serialization +backend (currently json). + +""" + +import simplejson +import ConfigParser +import re + +# Check whether the simplejson module supports indentation +_JSON_INDENT = 2 +try: + simplejson.dumps(1, indent=_JSON_INDENT) +except TypeError: + _JSON_INDENT = None + +_RE_EOLSP = re.compile('\s+$', re.MULTILINE) + + +def Dump(data): + """Serialize a given object. + + """ + if _JSON_INDENT is None: + txt = simplejson.dumps(data) + else: + txt = simplejson.dumps(data, indent=_JSON_INDENT) + if not txt.endswith('\n'): + txt += '\n' + txt = _RE_EOLSP.sub("", txt) + return txt + + +def Load(txt): + """Unserialize data from a string. + + """ + return simplejson.loads(txt) -- GitLab