From a064cc19b3c65c7011e732930c5df25612996ec2 Mon Sep 17 00:00:00 2001 From: Nico Schottelius Date: Tue, 30 Apr 2013 10:58:23 +0200 Subject: [PATCH] try new object orientated (hrrr) code instead of stage based Signed-off-by: Nico Schottelius --- cdist/config_install.py | 68 ++++++++++++++++++++++-- cdist/core/cdist_object.py | 18 +++++++ docs/dev/logs/2013-04-12.execution-order | 39 ++++++++++++++ 3 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 docs/dev/logs/2013-04-12.execution-order diff --git a/cdist/config_install.py b/cdist/config_install.py index 7c7a876d..841a19df 100644 --- a/cdist/config_install.py +++ b/cdist/config_install.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- # -# 2010-2012 Nico Schottelius (nico-cdist at schottelius.org) +# 2010-2013 Nico Schottelius (nico-cdist at schottelius.org) # # This file is part of cdist. # @@ -65,8 +65,13 @@ class ConfigInstall(object): def deploy_to(self): """Mimic the old deploy to: Deploy to one host""" - self.stage_prepare() - self.stage_run() + + # Old Code + # self.stage_prepare() + # self.stage_run() + + # New Code + self.run() def deploy_and_cleanup(self): """Do what is most often done: deploy & cleanup""" @@ -76,6 +81,62 @@ class ConfigInstall(object): self.log.info("Finished successful run in %s seconds", time.time() - start_time) + ###################################################################### + # New code for running on object priority (not stage priority) + # + + def run(self): + """The main runner""" + self.explorer.run_global_explorers(self.context.local.global_explorer_out_path) + self.manifest.run_initial_manifest(self.context.initial_manifest) + self.iterate_until_finished() + + def object_list(self): + """Short name for object list retrieval""" + for cdist_object in core.CdistObject.list_objects(self.context.local.object_path, + self.context.local.type_path): + yield cdist_object + + def iterate_until_finished(self): + # Continue process until no new objects are created anymore + + objects_changed = True + + while objects_changed: + objects_changed = False + + for cdist_object in self.object_list(): + if not cdist_object.requirements_satisfied(cdist_object.requirements): + """We cannot do anything for this poor object""" + continue + + if cdist_object.state == core.CdistObject.STATE_UNDEF: + """Prepare the virgin object""" + + self.object_prepare(cdist_object) + objects_changed = True + + if not cdist_object.requirements_satisfied(cdist_object.autorequire): + """The previous step created objects we depend on - wait for them""" + continue + + if cdist_object.state == core.CdistObject.STATE_PREPARED: + self.object_run(cdist_object) + + # Check whether all objects have been finished + unfinished_object_names = [] + for cdist_object in self.object_list(): + if not cdist_object.state == cdist_object.STATE_DONE: + unfinished_object_names.append(cdist_object.name) + + if unfinished_object_names: + raise cdist.Error("The following objects could not be resolved: %s" % + (" ".join(unfinished_object_names)) + + ###################################################################### + # Stages based code + # + def stage_prepare(self): """Do everything for a deploy, minus the actual code stage""" self.explorer.run_global_explorers(self.context.local.global_explorer_out_path) @@ -89,6 +150,7 @@ class ConfigInstall(object): new_objects_created = False for cdist_object in core.CdistObject.list_objects(self.context.local.object_path, self.context.local.type_path): + if cdist_object.state == core.CdistObject.STATE_PREPARED: self.log.debug("Skipping re-prepare of object %s", cdist_object) continue diff --git a/cdist/core/cdist_object.py b/cdist/core/cdist_object.py index 73537f80..30d002f6 100644 --- a/cdist/core/cdist_object.py +++ b/cdist/core/cdist_object.py @@ -61,6 +61,7 @@ class CdistObject(object): """ # Constants for use with Object.state + STATE_UNDEF = "" STATE_PREPARED = "prepared" STATE_RUNNING = "running" STATE_DONE = "done" @@ -223,6 +224,23 @@ class CdistObject(object): except EnvironmentError as error: raise cdist.Error('Error creating directories for cdist object: %s: %s' % (self, error)) + @property + def requirements_satisfied(self): + """Return state whether normal depedencies are satisfied""" + + satisfied = True + + for requirement in self.requirements: + cdist_object = self.object_from_name(requirement) + + if not cdist_object.state == self.STATE_DONE: + satisfied = False + break + + log.debug("%s is satisfied: %s" % (self.name, satisfied)) + + return satisfied + @property def satisfied_requirements(self): """Return state whether all of our dependencies have been resolved already""" diff --git a/docs/dev/logs/2013-04-12.execution-order b/docs/dev/logs/2013-04-12.execution-order new file mode 100644 index 00000000..1739c287 --- /dev/null +++ b/docs/dev/logs/2013-04-12.execution-order @@ -0,0 +1,39 @@ +Old: + +- global explores (all) +- initial manifest +- for each object + execute type explorers + execute manifest + + continue until all objects (including newly created) + have their type explorers/manifests run +- build dependency tree +- for each object + execute gencode-* + execute code-* + +New: +- run all global explorers +- run initial manifest + creates zero or more cdist_objects +- for each cdist_object + if not cdist_object.has_unfullfilled_requirements: + execute type explorers + execute manifest + may create new objects, resulting in autorequirements + + # Gained requirements during manifest run + if object.has_auto_requirements(): + continue + + cdist_object.execute gencode-* + cdist_object.execute code-* + + +Requirements / Test cases for requirments / resolver: + + - omnipotence + - + +Test