summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Server
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2013-02-20 10:38:38 -0500
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2013-02-20 10:38:38 -0500
commit69ebf49d54aac70a42142d0d04e562496bce58ea (patch)
treead0f346ff95a14ad49440128ff76d7e2b3f0816a /src/lib/Bcfg2/Server
parent602ba6af6bd1c9b3910940dee766660ab8e81a19 (diff)
parente17e41dcff096ead7e129a0db063f75de44aaa2b (diff)
downloadbcfg2-69ebf49d54aac70a42142d0d04e562496bce58ea.tar.gz
bcfg2-69ebf49d54aac70a42142d0d04e562496bce58ea.tar.bz2
bcfg2-69ebf49d54aac70a42142d0d04e562496bce58ea.zip
Merge branch 'master' into 1.4.x
Conflicts: doc/appendix/contributors.txt schemas/bundle.xsd src/lib/Bcfg2/Client/Tools/__init__.py src/lib/Bcfg2/Server/Encryption.py src/lib/Bcfg2/Server/Lint/Genshi.py src/lib/Bcfg2/Server/Plugins/Bundler.py src/lib/Bcfg2/Server/Plugins/Decisions.py src/lib/Bcfg2/Server/Plugins/TemplateHelper.py src/sbin/bcfg2-test testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIX/Test__init.py testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIXUsers.py testsuite/Testsrc/Testlib/TestServer/TestPlugin/Testhelpers.py testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestProperties.py tools/bcfg2-profile-templates.py
Diffstat (limited to 'src/lib/Bcfg2/Server')
-rw-r--r--src/lib/Bcfg2/Server/Core.py40
-rwxr-xr-xsrc/lib/Bcfg2/Server/Encryption.py6
-rw-r--r--src/lib/Bcfg2/Server/Lint/Comments.py2
-rwxr-xr-xsrc/lib/Bcfg2/Server/Lint/Genshi.py48
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Cfg/CfgExternalCommandVerifier.py9
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py1
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py9
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Defaults.py29
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Git.py48
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Metadata.py2
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Packages/Collection.py2
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Packages/Yum.py93
-rw-r--r--src/lib/Bcfg2/Server/Plugins/SSLCA.py5
-rw-r--r--src/lib/Bcfg2/Server/Plugins/TemplateHelper.py18
-rw-r--r--src/lib/Bcfg2/Server/Reports/updatefix.py5
15 files changed, 189 insertions, 128 deletions
diff --git a/src/lib/Bcfg2/Server/Core.py b/src/lib/Bcfg2/Server/Core.py
index f93ca0a7b..1b0ecadf5 100644
--- a/src/lib/Bcfg2/Server/Core.py
+++ b/src/lib/Bcfg2/Server/Core.py
@@ -332,9 +332,23 @@ class BaseCore(object):
self.fam.handle_event_set(self.lock)
except:
continue
- # VCS plugin periodic updates
- for plugin in self.plugins_by_type(Bcfg2.Server.Plugin.Version):
- self.revision = plugin.get_revision()
+ self._update_vcs_revision()
+
+ @track_statistics()
+ def _update_vcs_revision(self):
+ """ Update the revision of the current configuration on-disk
+ from the VCS plugin """
+ for plugin in self.plugins_by_type(Bcfg2.Server.Plugin.Version):
+ try:
+ newrev = plugin.get_revision()
+ if newrev != self.revision:
+ self.logger.debug("Updated to revision %s" % newrev)
+ self.revision = newrev
+ break
+ except:
+ self.logger.warning("Error getting revision from %s: %s" %
+ (plugin.name, sys.exc_info()[1]))
+ self.revision = '-1'
def init_plugin(self, plugin):
""" Import and instantiate a single plugin. The plugin is
@@ -360,8 +374,8 @@ class BaseCore(object):
try:
plug = getattr(mod, plugin.split('.')[-1])
except AttributeError:
- self.logger.error("Failed to load plugin %s (AttributeError)" %
- plugin)
+ self.logger.error("Failed to load plugin %s: %s" %
+ (plugin, sys.exc_info()[1]))
return
# Blacklist conflicting plugins
cplugs = [conflict for conflict in plug.conflicts
@@ -536,18 +550,16 @@ class BaseCore(object):
continue
try:
self.Bind(entry, metadata)
- except PluginExecutionError:
- exc = sys.exc_info()[1]
- if 'failure' not in entry.attrib:
- entry.set('failure', 'bind error: %s' % exc)
- self.logger.error("Failed to bind entry %s:%s: %s" %
- (entry.tag, entry.get('name'), exc))
- except Exception:
+ except:
exc = sys.exc_info()[1]
if 'failure' not in entry.attrib:
entry.set('failure', 'bind error: %s' % exc)
- self.logger.error("Unexpected failure in BindStructure: %s %s"
- % (entry.tag, entry.get('name')), exc_info=1)
+ if isinstance(exc, PluginExecutionError):
+ msg = "Failed to bind entry"
+ else:
+ msg = "Unexpected failure binding entry"
+ self.logger.error("%s %s:%s: %s" %
+ (msg, entry.tag, entry.get('name'), exc))
def Bind(self, entry, metadata):
""" Bind a single entry using the appropriate generator.
diff --git a/src/lib/Bcfg2/Server/Encryption.py b/src/lib/Bcfg2/Server/Encryption.py
index c931ed2a7..b46337eb0 100755
--- a/src/lib/Bcfg2/Server/Encryption.py
+++ b/src/lib/Bcfg2/Server/Encryption.py
@@ -30,6 +30,9 @@ CFG_SECTION = "encryption"
#: The config option used to store the algorithm
CFG_ALGORITHM = "algorithm"
+#: The config option used to store the decryption strictness
+CFG_DECRYPT = "decrypt"
+
#: Default cipher algorithm. To get a full list of valid algorithms,
#: you can run::
#:
@@ -40,6 +43,7 @@ ALGORITHM = Bcfg2.Options.get_option_parser().cfp.get( # pylint: disable=E1103
CFG_ALGORITHM,
default="aes_256_cbc").lower().replace("-", "_")
+
Rand.rand_seed(os.urandom(1024))
@@ -165,7 +169,7 @@ def get_passphrases():
if setup.cfp.has_section(CFG_SECTION):
return dict([(o, setup.cfp.get(CFG_SECTION, o))
for o in setup.cfp.options(CFG_SECTION)
- if o != CFG_ALGORITHM])
+ if o not in [CFG_ALGORITHM, CFG_DECRYPT]])
else:
return dict()
diff --git a/src/lib/Bcfg2/Server/Lint/Comments.py b/src/lib/Bcfg2/Server/Lint/Comments.py
index ecea1ad1b..8bfb76461 100644
--- a/src/lib/Bcfg2/Server/Lint/Comments.py
+++ b/src/lib/Bcfg2/Server/Lint/Comments.py
@@ -130,7 +130,7 @@ class Comments(Bcfg2.Server.Lint.ServerPlugin):
rtype)
def check_plaintext(self, filename, data, rtype):
- """ check generic plaintex files for required headers """
+ """ check generic plaintext files for required headers """
self.check_lines(filename, data.splitlines(), rtype)
def check_lines(self, filename, lines, rtype):
diff --git a/src/lib/Bcfg2/Server/Lint/Genshi.py b/src/lib/Bcfg2/Server/Lint/Genshi.py
index 437e69d82..ed0d9930f 100755
--- a/src/lib/Bcfg2/Server/Lint/Genshi.py
+++ b/src/lib/Bcfg2/Server/Lint/Genshi.py
@@ -1,8 +1,11 @@
""" Check Genshi templates for syntax errors """
import sys
-import genshi.template
import Bcfg2.Server.Lint
+from genshi.template import TemplateLoader, NewTextTemplate, MarkupTemplate, \
+ TemplateSyntaxError
+from Bcfg2.Server.Plugins.Bundler import BundleTemplateFile
+from Bcfg2.Server.Plugins.Cfg.CfgGenshiGenerator import CfgGenshiGenerator
class Genshi(Bcfg2.Server.Lint.ServerPlugin):
@@ -10,29 +13,40 @@ class Genshi(Bcfg2.Server.Lint.ServerPlugin):
def Run(self):
""" run plugin """
- loader = genshi.template.TemplateLoader()
if 'Cfg' in self.core.plugins:
- self.check_files(self.core.plugins['Cfg'].entries,
- loader=loader)
+ self.check_cfg()
+ if 'Bundler' in self.core.plugins:
+ self.check_bundler()
@classmethod
def Errors(cls):
return {"genshi-syntax-error": "error"}
- def check_files(self, entries, loader=None):
- """ Check genshi templates in a list of entries for syntax
- errors """
- if loader is None:
- loader = genshi.template.TemplateLoader()
-
- for eset in entries.values():
- for fname, sdata in list(eset.entries.items()):
- if (self.HandlesFile(fname) and
- (fname.endswith(".genshi") or fname.endswith(".newtxt"))):
+ def check_cfg(self):
+ """ Check genshi templates in Cfg for syntax errors """
+ for entryset in self.core.plugins['Cfg'].entries.values():
+ for entry in entryset.entries.values():
+ if (self.HandlesFile(entry.name) and
+ isinstance(entry, CfgGenshiGenerator) and
+ not entry.template):
try:
- loader.load(sdata.name,
- cls=genshi.template.NewTextTemplate)
- except genshi.template.TemplateSyntaxError:
+ entry.loader.load(entry.name,
+ cls=NewTextTemplate)
+ except TemplateSyntaxError:
err = sys.exc_info()[1]
self.LintError("genshi-syntax-error",
"Genshi syntax error: %s" % err)
+
+ def check_bundler(self):
+ """ Check templates in Bundler for syntax errors """
+ loader = TemplateLoader()
+
+ for entry in self.core.plugins['Bundler'].entries.values():
+ if (self.HandlesFile(entry.name) and
+ isinstance(entry, BundleTemplateFile)):
+ try:
+ loader.load(entry.name, cls=MarkupTemplate)
+ except TemplateSyntaxError:
+ err = sys.exc_info()[1]
+ self.LintError("genshi-syntax-error",
+ "Genshi syntax error: %s" % err)
diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgExternalCommandVerifier.py b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgExternalCommandVerifier.py
index b702ac899..313e53ee9 100644
--- a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgExternalCommandVerifier.py
+++ b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgExternalCommandVerifier.py
@@ -23,10 +23,15 @@ class CfgExternalCommandVerifier(CfgVerifier):
def verify_entry(self, entry, metadata, data):
try:
proc = Popen(self.cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- err = proc.communicate(input=data)[1]
+ out, err = proc.communicate(input=data)
rv = proc.wait()
if rv != 0:
- raise CfgVerificationError(err)
+ # pylint: disable=E1103
+ raise CfgVerificationError(err.strip() or out.strip() or
+ "Non-zero return value %s" % rv)
+ # pylint: enable=E1103
+ except CfgVerificationError:
+ raise
except:
err = sys.exc_info()[1]
raise CfgVerificationError("Error running external command "
diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py
index c11939bd5..5f10879be 100644
--- a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py
+++ b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py
@@ -166,6 +166,7 @@ class CfgGenshiGenerator(CfgGenerator):
raise
def handle_event(self, event):
+ CfgGenerator.handle_event(self, event)
try:
self.template = self.loader.load(self.name, cls=NewTextTemplate,
encoding=self.encoding)
diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py b/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py
index 81adea42f..2301de725 100644
--- a/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py
+++ b/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py
@@ -553,11 +553,10 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet,
try:
self._validate_data(entry, metadata, data)
except CfgVerificationError:
- msg = "Data for %s for %s failed to verify: %s" % \
- (entry.get('name'), metadata.hostname,
- sys.exc_info()[1])
- self.logger.error(msg)
- raise PluginExecutionError(msg)
+ raise PluginExecutionError("Failed to verify %s for %s: %s" %
+ (entry.get('name'),
+ metadata.hostname,
+ sys.exc_info()[1]))
if entry.get('encoding') == 'base64':
data = b64encode(data)
diff --git a/src/lib/Bcfg2/Server/Plugins/Defaults.py b/src/lib/Bcfg2/Server/Plugins/Defaults.py
index f4d86a64f..04c14aa96 100644
--- a/src/lib/Bcfg2/Server/Plugins/Defaults.py
+++ b/src/lib/Bcfg2/Server/Plugins/Defaults.py
@@ -5,7 +5,7 @@ import Bcfg2.Server.Plugins.Rules
class Defaults(Bcfg2.Server.Plugins.Rules.Rules,
- Bcfg2.Server.Plugin.StructureValidator):
+ Bcfg2.Server.Plugin.GoalValidator):
"""Set default attributes on bound entries"""
__author__ = 'bcfg-dev@mcs.anl.gov'
@@ -22,27 +22,18 @@ class Defaults(Bcfg2.Server.Plugins.Rules.Rules,
def HandleEvent(self, event):
Bcfg2.Server.Plugin.XMLDirectoryBacked.HandleEvent(self, event)
- def validate_structures(self, metadata, structures):
+ def validate_goals(self, metadata, config):
""" Apply defaults """
- for struct in structures:
+ for struct in config.getchildren():
for entry in struct.getchildren():
- if entry.tag.startswith("Bound"):
- is_bound = True
- entry.tag = entry.tag[5:]
- else:
- is_bound = False
try:
- try:
- self.BindEntry(entry, metadata)
- except Bcfg2.Server.Plugin.PluginExecutionError:
- # either no matching defaults (which is okay),
- # or multiple matching defaults (which is not
- # okay, but is logged). either way, we don't
- # care about the error.
- pass
- finally:
- if is_bound:
- entry.tag = "Bound" + entry.tag
+ self.BindEntry(entry, metadata)
+ except Bcfg2.Server.Plugin.PluginExecutionError:
+ # either no matching defaults (which is okay),
+ # or multiple matching defaults (which is not
+ # okay, but is logged). either way, we don't
+ # care about the error.
+ pass
@property
def _regex_enabled(self):
diff --git a/src/lib/Bcfg2/Server/Plugins/Git.py b/src/lib/Bcfg2/Server/Plugins/Git.py
index 8cc63a46f..c8362db41 100644
--- a/src/lib/Bcfg2/Server/Plugins/Git.py
+++ b/src/lib/Bcfg2/Server/Plugins/Git.py
@@ -2,7 +2,7 @@
git. """
import sys
-import Bcfg2.Server.Plugin
+from Bcfg2.Server.Plugin import Version, PluginExecutionError
from subprocess import Popen, PIPE
try:
@@ -12,16 +12,16 @@ except ImportError:
HAS_GITPYTHON = False
-class Git(Bcfg2.Server.Plugin.Version):
+class Git(Version):
""" The Git plugin provides a revision interface for Bcfg2 repos
using git. """
__author__ = 'bcfg-dev@mcs.anl.gov'
__vcs_metadata_path__ = ".git"
if HAS_GITPYTHON:
- __rmi__ = Bcfg2.Server.Plugin.Version.__rmi__ + ['Update']
+ __rmi__ = Version.__rmi__ + ['Update']
def __init__(self, core, datastore):
- Bcfg2.Server.Plugin.Version.__init__(self, core, datastore)
+ Version.__init__(self, core, datastore)
if HAS_GITPYTHON:
self.repo = git.Repo(self.vcs_root)
else:
@@ -31,6 +31,11 @@ class Git(Bcfg2.Server.Plugin.Version):
self.logger.debug("Initialized git plugin with git directory %s" %
self.vcs_path)
+ def _log_git_cmd(self, output):
+ """ Send output from a GitPython command to the debug log """
+ for line in output.strip().splitlines():
+ self.debug_log("Git: %s" % line)
+
def get_revision(self):
"""Read git revision information for the Bcfg2 repository."""
try:
@@ -46,11 +51,9 @@ class Git(Bcfg2.Server.Plugin.Version):
raise Exception(err)
return rv
except:
- err = sys.exc_info()[1]
- msg = "Git: Error getting revision from %s: %s" % (self.vcs_root,
- err)
- self.logger.error(msg)
- raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+ raise PluginExecutionError("Git: Error getting revision from %s: "
+ "%s" % (self.vcs_root,
+ sys.exc_info()[1]))
def Update(self, ref=None):
""" Git.Update() => True|False
@@ -60,20 +63,25 @@ class Git(Bcfg2.Server.Plugin.Version):
self.debug_log("Git: Performing garbage collection on repo at %s" %
self.vcs_root)
try:
- self.repo.git.gc('--auto')
+ self._log_git_cmd(self.repo.git.gc('--auto'))
except git.GitCommandError:
self.logger.warning("Git: Failed to perform garbage collection: %s"
% sys.exc_info()[1])
+ self.debug_log("Git: Fetching all refs for repo at %s" % self.vcs_root)
+ try:
+ self._log_git_cmd(self.repo.git.fetch('--all'))
+ except git.GitCommandError:
+ self.logger.warning("Git: Failed to fetch refs: %s" %
+ sys.exc_info()[1])
+
if ref:
self.debug_log("Git: Checking out %s" % ref)
try:
- self.repo.git.checkout('-f', ref)
+ self._log_git_cmd(self.repo.git.checkout('-f', ref))
except git.GitCommandError:
- err = sys.exc_info()[1]
- msg = "Git: Failed to checkout %s: %s" % (ref, err)
- self.logger.error(msg)
- raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+ raise PluginExecutionError("Git: Failed to checkout %s: %s" %
+ (ref, sys.exc_info()[1]))
# determine if we should try to pull to get the latest commit
# on this head
@@ -87,12 +95,10 @@ class Git(Bcfg2.Server.Plugin.Version):
self.debug_log("Git: %s is a tracking branch, pulling from %s" %
(self.repo.head.ref.name, tracking))
try:
- self.repo.git.pull("--rebase")
- except: # pylint: disable=W0702
- err = sys.exc_info()[1]
- msg = "Git: Failed to pull from upstream: %s" % err
- self.logger.error(msg)
- raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+ self._log_git_cmd(self.repo.git.pull("--rebase"))
+ except git.GitCommandError:
+ raise PluginExecutionError("Git: Failed to pull from "
+ "upstream: %s" % sys.exc_info()[1])
self.logger.info("Git: Repo at %s updated to %s" %
(self.vcs_root, self.get_revision()))
diff --git a/src/lib/Bcfg2/Server/Plugins/Metadata.py b/src/lib/Bcfg2/Server/Plugins/Metadata.py
index e568c5c65..b053e65d3 100644
--- a/src/lib/Bcfg2/Server/Plugins/Metadata.py
+++ b/src/lib/Bcfg2/Server/Plugins/Metadata.py
@@ -1452,7 +1452,7 @@ class MetadataLint(Bcfg2.Server.Lint.ServerPlugin):
defaults = []
for grp in self.metadata.groups_xml.xdata.xpath("//Groups/Group") + \
self.metadata.groups_xml.xdata.xpath("//Groups/Group//Group"):
- if grp.get("default"):
+ if grp.get("default", "false").lower() == "true":
defaults.append(self.RenderXML(grp))
if len(defaults) > 1:
self.LintError("multiple-default-groups",
diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Collection.py b/src/lib/Bcfg2/Server/Plugins/Packages/Collection.py
index 3ad64b242..59eefe143 100644
--- a/src/lib/Bcfg2/Server/Plugins/Packages/Collection.py
+++ b/src/lib/Bcfg2/Server/Plugins/Packages/Collection.py
@@ -533,7 +533,7 @@ class Collection(list, Bcfg2.Server.Plugin.Debuggable):
# should be resolved
current = pkgs.pop()
self.debug_log("Packages: handling package requirement %s" %
- current)
+ (current,))
packages.add(current)
deps = self.get_deps(current)
newdeps = set(deps).difference(examined)
diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py
index 4057ed230..775caaa08 100644
--- a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py
+++ b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py
@@ -684,6 +684,21 @@ class YumCollection(Collection):
return self.call_helper("get_groups", inputdata=gdicts)
+ def _element_to_pkg(self, el, name):
+ """ Convert a Package or Instance element to a package tuple """
+ rv = (name, el.get("arch"), el.get("epoch"),
+ el.get("version"), el.get("release"))
+ if rv[3] in ['any', 'auto']:
+ rv = (rv[0], rv[1], rv[2], None, None)
+ # if a package requires no specific version, we just use
+ # the name, not the tuple. this limits the amount of JSON
+ # encoding/decoding that has to be done to pass the
+ # package list to bcfg2-yum-helper.
+ if rv[1:] == (None, None, None, None):
+ return name
+ else:
+ return rv
+
def packages_from_entry(self, entry):
""" When using the Python yum libraries, convert a Package
entry to a list of package tuples. See :ref:`yum-pkg-objects`
@@ -693,32 +708,42 @@ class YumCollection(Collection):
:type entry: lxml.etree._Element
:returns: list of tuples
"""
+ if not self.use_yum:
+ return Collection.packages_from_entry(self, entry)
+
rv = set()
name = entry.get("name")
- def _tag_to_pkg(tag):
- """ Convert a Package or Instance tag to a package tuple """
- rv = (name, tag.get("arch"), tag.get("epoch"),
- tag.get("version"), tag.get("release"))
- if rv[3] in ['any', 'auto']:
- rv = (rv[0], rv[1], rv[2], None, None)
- # if a package requires no specific version, we just use
- # the name, not the tuple. this limits the amount of JSON
- # encoding/decoding that has to be done to pass the
- # package list to bcfg2-yum-helper.
- if rv[1:] == (None, None, None, None):
- return name
- else:
- return rv
-
for inst in entry.getchildren():
if inst.tag != "Instance":
continue
- rv.add(_tag_to_pkg(inst))
+ rv.add(self._element_to_pkg(inst, name))
if not rv:
- rv.add(_tag_to_pkg(entry))
+ rv.add(self._element_to_pkg(entry, name))
return list(rv)
+ def _get_entry_attrs(self, pkgtup):
+ """ Given a package tuple, return a dict of attributes
+ suitable for applying to either a Package or an Instance
+ tag """
+ attrs = dict(version=self.setup.cfp.get("packages", "version",
+ default="auto"))
+ if attrs['version'] == 'any' or not isinstance(pkgtup, tuple):
+ return attrs
+
+ try:
+ if pkgtup[1]:
+ attrs['arch'] = pkgtup[1]
+ if pkgtup[2]:
+ attrs['epoch'] = pkgtup[2]
+ if pkgtup[3]:
+ attrs['version'] = pkgtup[3]
+ if pkgtup[4]:
+ attrs['release'] = pkgtup[4]
+ except IndexError:
+ self.logger.warning("Malformed package tuple: %s" % pkgtup)
+ return attrs
+
def packages_to_entry(self, pkglist, entry):
""" When using the Python yum libraries, convert a list of
package tuples to a Package entry. See :ref:`yum-pkg-objects`
@@ -738,28 +763,8 @@ class YumCollection(Collection):
:type entry: lxml.etree._Element
:returns: None
"""
- def _get_entry_attrs(pkgtup):
- """ Given a package tuple, return a dict of attributes
- suitable for applying to either a Package or an Instance
- tag """
- attrs = dict(version=self.setup.cfp.get("packages",
- "version",
- default="auto"))
- if attrs['version'] == 'any' or not isinstance(pkgtup, tuple):
- return attrs
-
- try:
- if pkgtup[1]:
- attrs['arch'] = pkgtup[1]
- if pkgtup[2]:
- attrs['epoch'] = pkgtup[2]
- if pkgtup[3]:
- attrs['version'] = pkgtup[3]
- if pkgtup[4]:
- attrs['release'] = pkgtup[4]
- except IndexError:
- self.logger.warning("Malformed package tuple: %s" % pkgtup)
- return attrs
+ if not self.use_yum:
+ return Collection.packages_to_entry(self, pkglist, entry)
packages = dict()
for pkg in pkglist:
@@ -776,9 +781,9 @@ class YumCollection(Collection):
**pkgattrs)
for inst in instances:
lxml.etree.SubElement(pkg_el, "Instance",
- _get_entry_attrs(inst))
+ self._get_entry_attrs(inst))
else:
- attrs = _get_entry_attrs(instances[0])
+ attrs = self._get_entry_attrs(instances[0])
attrs.update(pkgattrs)
lxml.etree.SubElement(entry, 'BoundPackage', **attrs)
@@ -803,7 +808,11 @@ class YumCollection(Collection):
initial_names.append(pkg)
new = []
for pkg in complete:
- if pkg[0] not in initial_names:
+ if isinstance(pkg, tuple):
+ name = pkg[0]
+ else:
+ name = pkg
+ if name not in initial_names:
new.append(pkg)
return new
diff --git a/src/lib/Bcfg2/Server/Plugins/SSLCA.py b/src/lib/Bcfg2/Server/Plugins/SSLCA.py
index cc1a2ceac..ab2f80552 100644
--- a/src/lib/Bcfg2/Server/Plugins/SSLCA.py
+++ b/src/lib/Bcfg2/Server/Plugins/SSLCA.py
@@ -180,7 +180,7 @@ class SSLCAEntrySet(Bcfg2.Server.Plugin.EntrySet):
self.logger.error("SSLCA: Failed to unlink temporary files: %s"
% sys.exc_info()[1])
if cert_spec['append_chain'] and 'chaincert' in ca:
- cert += open(self.parent.get_ca(ca)['chaincert']).read()
+ cert += open(ca['chaincert']).read()
open(os.path.join(self.path, filename), 'w').write(cert)
return cert
@@ -363,7 +363,8 @@ class SSLCA(Bcfg2.Server.Plugin.GroupSpool):
""" The SSLCA generator handles the creation and management of ssl
certificates and their keys. """
__author__ = 'g.hagger@gmail.com'
- es_cls = lambda self, *args: SSLCAEntrySet(*args, parent=self)
+ # python 2.5 doesn't support mixing *magic and keyword arguments
+ es_cls = lambda self, *args: SSLCAEntrySet(*args, **dict(parent=self))
es_child_cls = SSLCADataFile
def get_ca(self, name):
diff --git a/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py b/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py
index e3f8ed749..ad3eb65bc 100644
--- a/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py
+++ b/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py
@@ -12,12 +12,25 @@ LOGGER = logging.getLogger(__name__)
MODULE_RE = re.compile(r'(?P<filename>(?P<module>[^\/]+)\.py)$')
+def safe_module_name(module):
+ """ Munge the name of a TemplateHelper module to avoid collisions
+ with other Python modules. E.g., if someone has a helper named
+ 'ldap.py', it should not be added to ``sys.modules`` as ``ldap``,
+ but rather as something more obscure. """
+ return '__TemplateHelper_%s' % module
+
+
class HelperModule(object):
""" Representation of a TemplateHelper module """
def __init__(self, name):
self.name = name
+
+ #: The name of the module as used by get_additional_data().
+ #: the name of the file with .py stripped off.
self._module_name = MODULE_RE.search(self.name).group('module')
+
+ #: The attributes exported by this module
self._attrs = []
def HandleEvent(self, event=None):
@@ -31,7 +44,8 @@ class HelperModule(object):
return
try:
- module = imp.load_source(self._module_name, self.name)
+ module = imp.load_source(safe_module_name(self._module_name),
+ self.name)
except: # pylint: disable=W0702
err = sys.exc_info()[1]
LOGGER.error("TemplateHelper: Failed to import %s: %s" %
@@ -97,7 +111,7 @@ class TemplateHelperLint(Bcfg2.Server.Lint.ServerPlugin):
module_name = MODULE_RE.search(helper).group(1)
try:
- module = imp.load_source(module_name, helper)
+ module = imp.load_source(safe_module_name(module_name), helper)
except: # pylint: disable=W0702
err = sys.exc_info()[1]
self.LintError("templatehelper-import-error",
diff --git a/src/lib/Bcfg2/Server/Reports/updatefix.py b/src/lib/Bcfg2/Server/Reports/updatefix.py
index b377806ab..cb131c29d 100644
--- a/src/lib/Bcfg2/Server/Reports/updatefix.py
+++ b/src/lib/Bcfg2/Server/Reports/updatefix.py
@@ -80,6 +80,9 @@ def _populate_interaction_entry_counts():
cursor.close()
+def update_noop():
+ return True
+
# be sure to test your upgrade query before reflecting the change in the models
# the list of function and sql command to do should go here
_fixes = [_merge_database_table_entries,
@@ -103,6 +106,8 @@ _fixes = [_merge_database_table_entries,
_interactions_constraint_or_idx,
'alter table reports_reason add is_binary bool NOT NULL default False;',
'alter table reports_reason add is_sensitive bool NOT NULL default False;',
+ update_noop, #_remove_table_column('reports_interaction', 'client_version'),
+ "alter table reports_reason add unpruned varchar(1280) not null default 'N/A';",
]
# this will calculate the last possible version of the database