summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Client
diff options
context:
space:
mode:
authorAlexander Sulfrian <alexander@sulfrian.net>2014-11-25 00:51:23 +0100
committerAlexander Sulfrian <alexander@sulfrian.net>2014-11-25 16:00:48 +0100
commitbe564316c7c4deaad090bfc0bc79c460965cb1d6 (patch)
tree38c7ab16fc403d8d067cdae1f91fcc3d9af07317 /src/lib/Bcfg2/Client
parentc544b18a985edd7444593e75ad52483f4842c119 (diff)
downloadbcfg2-be564316c7c4deaad090bfc0bc79c460965cb1d6.tar.gz
bcfg2-be564316c7c4deaad090bfc0bc79c460965cb1d6.tar.bz2
bcfg2-be564316c7c4deaad090bfc0bc79c460965cb1d6.zip
Bundler: add modification support to Bundle dependencies
Bundle dependencies are now realized with RequiredBundle and support inheritance of the modification flag. This requires new client support and will only work with clients >= 1.4.0pre2.
Diffstat (limited to 'src/lib/Bcfg2/Client')
-rw-r--r--src/lib/Bcfg2/Client/Tools/BundleDeps.py34
-rw-r--r--src/lib/Bcfg2/Client/__init__.py59
2 files changed, 81 insertions, 12 deletions
diff --git a/src/lib/Bcfg2/Client/Tools/BundleDeps.py b/src/lib/Bcfg2/Client/Tools/BundleDeps.py
new file mode 100644
index 000000000..aaa090633
--- /dev/null
+++ b/src/lib/Bcfg2/Client/Tools/BundleDeps.py
@@ -0,0 +1,34 @@
+""" Bundle dependency support """
+
+import Bcfg2.Client.Tools
+
+
+class BundleDeps(Bcfg2.Client.Tools.Tool):
+ """Bundle dependency helper for Bcfg2. It handles Bundle tags inside the
+ bundles that references the required other bundles that should change the
+ modification status if the referenced bundles is modified."""
+
+ name = 'Bundle'
+ __handles__ = [('Bundle', None)]
+ __req__ = {'Bundle': ['name']}
+
+ def InstallBundle(self, _):
+ """Simple no-op because we only need the BundleUpdated hook."""
+ return dict()
+
+ def VerifyBundle(self, entry, _): # pylint: disable=W0613
+ """Simple no-op because we only need the BundleUpdated hook."""
+ return True
+
+ def BundleUpdated(self, entry):
+ """This handles the dependencies on this bundle. It searches all
+ Bundle tags in other bundles that references the current bundle name
+ and marks those tags as modified to trigger the modification hook on
+ the other bundles."""
+
+ bundle_name = entry.get('name')
+ for bundle in self.config.findall('./Bundle/Bundle'):
+ if bundle.get('name') == bundle_name and \
+ bundle not in self.modified:
+ self.modified.append(bundle)
+ return dict()
diff --git a/src/lib/Bcfg2/Client/__init__.py b/src/lib/Bcfg2/Client/__init__.py
index 5f4f15dcc..d834576c9 100644
--- a/src/lib/Bcfg2/Client/__init__.py
+++ b/src/lib/Bcfg2/Client/__init__.py
@@ -768,27 +768,27 @@ class Client(object):
if not Bcfg2.Options.setup.interactive:
self.DispatchInstallCalls(clobbered)
- for bundle in self.config.findall('.//Bundle'):
+ all_bundles = self.config.findall('./Bundle')
+ mbundles.extend(self._get_all_modified_bundles(mbundles, all_bundles))
+
+ for bundle in all_bundles:
if (Bcfg2.Options.setup.only_bundles and
bundle.get('name') not in
Bcfg2.Options.setup.only_bundles):
# prune out unspecified bundles when running with -b
continue
if bundle in mbundles:
- self.logger.debug("Bundle %s was modified" %
- bundle.get('name'))
- func = "BundleUpdated"
- else:
- self.logger.debug("Bundle %s was not modified" %
- bundle.get('name'))
- func = "BundleNotUpdated"
+ continue
+
+ self.logger.debug("Bundle %s was not modified" %
+ bundle.get('name'))
for tool in self.tools:
try:
- self.states.update(getattr(tool, func)(bundle))
+ self.states.update(tool.BundleNotUpdated(bundle))
except: # pylint: disable=W0702
- self.logger.error("%s.%s(%s:%s) call failed:" %
- (tool.name, func, bundle.tag,
- bundle.get("name")), exc_info=1)
+ self.logger.error('%s.BundleNotUpdated(%s:%s) call failed:'
+ % (tool.name, bundle.tag,
+ bundle.get('name')), exc_info=1)
for indep in self.config.findall('.//Independent'):
for tool in self.tools:
@@ -799,6 +799,41 @@ class Client(object):
% (tool.name, indep.tag,
indep.get("name")), exc_info=1)
+ def _get_all_modified_bundles(self, mbundles, all_bundles):
+ """This gets all modified bundles by calling BundleUpdated until no
+ new bundles get added to the modification list."""
+ new_mbundles = mbundles
+ add_mbundles = []
+
+ while new_mbundles:
+ for bundle in self.config.findall('./Bundle'):
+ if (Bcfg2.Options.setup.only_bundles and
+ bundle.get('name') not in
+ Bcfg2.Options.setup.only_bundles):
+ # prune out unspecified bundles when running with -b
+ continue
+ if bundle not in new_mbundles:
+ continue
+
+ self.logger.debug('Bundle %s was modified' %
+ bundle.get('name'))
+ for tool in self.tools:
+ try:
+ self.states.update(tool.BundleUpdated(bundle))
+ except: # pylint: disable=W0702
+ self.logger.error('%s.BundleUpdated(%s:%s) call '
+ 'failed:' % (tool.name, bundle.tag,
+ bundle.get("name")),
+ exc_info=1)
+
+ mods = self.modified
+ new_mbundles = [struct for struct in all_bundles
+ if any(True for mod in mods if mod in struct)
+ and struct not in mbundles + add_mbundles]
+ add_mbundles.extend(new_mbundles)
+
+ return add_mbundles
+
def Remove(self):
"""Remove extra entries."""
for tool in self.tools: