From a01b57c799d0eb24c4122003c0c295026edc48ba Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 19 Jun 2012 14:39:13 -0400 Subject: added ability to disable Properties write-back --- doc/server/plugins/connectors/properties.txt | 38 ++++++++++++++-------- src/lib/Bcfg2/Server/Plugins/Properties.py | 48 ++++++++++++++++------------ 2 files changed, 52 insertions(+), 34 deletions(-) diff --git a/doc/server/plugins/connectors/properties.txt b/doc/server/plugins/connectors/properties.txt index 123959093..b56c2a488 100644 --- a/doc/server/plugins/connectors/properties.txt +++ b/doc/server/plugins/connectors/properties.txt @@ -56,7 +56,6 @@ raw data, the following access methods are defined: for el in metadata.Properties['ntp.xml'].Match(metadata) if el.tag == "Server"] %} - * ``XMLMatch()`` parses the Group and Client tags in the file and returns an XML document containing only the data that applies to the client described by a set of metadata. (The Group and Client tags @@ -68,9 +67,6 @@ raw data, the following access methods are defined: for el in metadata.Properties['ntp.xml'].XMLMatch(metadata).findall("//Server")] %} -See :ref:`server-plugins-structures-bundler-index` for more details on -how Group and Client tags are parsed. - As we formulate more common use cases, we will add them to the ``PropertyFile`` class as methods. This will simplify templates. @@ -91,6 +87,8 @@ directly in one of several ways: Automatch ========= +.. versionadded:: 1.3.0 + You can enable ``XMLMatch()`` for all Property files by setting ``automatch`` to ``true`` in the ``[properties]`` section of ``bcfg2.conf``. This makes ``metadata.Properties`` values @@ -120,8 +118,10 @@ the attribute ``automatch="true"`` in the top-level ```` tag. .. _server-plugins-connectors-properties-write-back: -Properties Write-Back -===================== +Writing to Properties files +=========================== + +.. versionadded:: 1.2.0 If you need to make persistent changes to properties data, you can use the ``write`` method of the ``PropertyFile`` class:: @@ -138,6 +138,14 @@ the ``write`` method of the ``PropertyFile`` class:: The ``write`` method checks the data in the object against its schema before writing it; see `Data Structures`_ for details. +Note that use of the ``write`` method can cause race conditions if you +run more than one Bcfg2 server. If you run more than one Bcfg2 +server, you can disable Properties write-back by setting the following +in ``bcfg2.conf``:: + + [properties] + writes_enabled = false + .. _server-plugins-connectors-properties-encrypted: Encrypted Properties data @@ -217,15 +225,17 @@ Access contents of ``Properties/auth.xml``:: Configuration ============= -``bcfg2.conf`` contains several miscellaneous configuration options for the -Properties plugin. Any booleans in the config file accept the values -"1", "yes", "true", and "on" for True, and "0", "no", "false", and -"off" for False. +``bcfg2.conf`` contains several miscellaneous configuration options +for the Properties plugin, which can be set in the ``[properties]`` +section. Any booleans in the config file accept the values "1", "yes", +"true", and "on" for True, and "0", "no", "false", and "off" for +False. It understands the following directives: -[properties] section --------------------- - * ``automatch``: Enable - :ref:`server-plugins-connectors-properties-automatch` + :ref:`server-plugins-connectors-properties-automatch`. Default is + false. +* ``writes_enabled``: Enable + :ref:`server-plugins-connectors-properties-write-back`. Default is + true. diff --git a/src/lib/Bcfg2/Server/Plugins/Properties.py b/src/lib/Bcfg2/Server/Plugins/Properties.py index 8d3e049d4..6d1c21328 100644 --- a/src/lib/Bcfg2/Server/Plugins/Properties.py +++ b/src/lib/Bcfg2/Server/Plugins/Properties.py @@ -32,18 +32,27 @@ class PropertyFile(Bcfg2.Server.Plugin.StructFile): def write(self): """ Write the data in this data structure back to the property file """ - if self.validate_data(): - try: - open(self.name, - "wb").write(lxml.etree.tostring(self.xdata, - pretty_print=True)) - return True - except IOError: - err = sys.exc_info()[1] - logger.error("Failed to write %s: %s" % (self.name, err)) - return False - else: - return False + if not SETUP.cfp.getboolean("properties", "writes_enabled", + default=True): + msg = "Properties files write-back is disabled in the configuration" + logger.error(msg) + raise Bcfg2.Server.Plugin.PluginExecutionError(msg) + try: + self.validate_data() + except Bcfg2.Server.Plugin.PluginExecutionError: + msg = "Cannot write %s: %s" % (self.name, sys.exc_info()[1]) + logger.error(msg) + raise Bcfg2.Server.Plugin.PluginExecutionError(msg) + + try: + open(self.name, "wb").write(lxml.etree.tostring(self.xdata, + pretty_print=True)) + return True + except IOError: + err = sys.exc_info()[1] + msg = "Failed to write %s: %s" % (self.name, err) + logger.error(msg) + raise Bcfg2.Server.Plugin.PluginExecutionError(msg) def validate_data(self): """ ensure that the data in this object validates against the @@ -53,16 +62,14 @@ class PropertyFile(Bcfg2.Server.Plugin.StructFile): try: schema = lxml.etree.XMLSchema(file=schemafile) except: - logger.error("Failed to process schema for %s" % self.name) - return False + err = sys.exc_info()[1] + raise Bcfg2.Server.Plugin.PluginExecutionError("Failed to process schema for %s: %s" % (self.name, err)) else: # no schema exists return True if not schema.validate(self.xdata): - logger.error("Data for %s fails to validate; run bcfg2-lint for " - "more details" % self.name) - return False + raise Bcfg2.Server.Plugin.PluginExecutionError("Data for %s fails to validate; run bcfg2-lint for more details" % self.name) else: return True @@ -129,11 +136,12 @@ class Properties(Bcfg2.Server.Plugin.Plugin, SETUP = core.setup def get_additional_data(self, metadata): - autowatch = self.core.setup.cfp.getboolean("properties", "automatch") + autowatch = self.core.setup.cfp.getboolean("properties", "automatch", + default=False) rv = dict() for fname, pfile in self.store.entries.items(): - if autowatch or pfile.xdata.get("automatch", - "false").lower() == "true": + if (autowatch or + pfile.xdata.get("automatch", "false").lower() == "true"): rv[fname] = pfile.XMLMatch(metadata) else: rv[fname] = copy.copy(pfile) -- cgit v1.2.3-1-g7c22