From ff6db37a956022ec82e38be461be5d3e8a7a3472 Mon Sep 17 00:00:00 2001 From: chris meyers Date: Mon, 15 Oct 2018 09:48:00 -0400 Subject: [PATCH] correct stop DNR propogation * If a child has a parent that is not in the finished state then do not propogate the DNR to the child in question. * If a parent is in a finished state; do not propogate the DNR to the child if the path to the child is traversed (based on the parent job status). --- awx/main/scheduler/dag_simple.py | 24 +++++++++++++++++------- awx/main/scheduler/dag_workflow.py | 19 +++++++++++++++++-- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/awx/main/scheduler/dag_simple.py b/awx/main/scheduler/dag_simple.py index d436c0c194..c78e76482d 100644 --- a/awx/main/scheduler/dag_simple.py +++ b/awx/main/scheduler/dag_simple.py @@ -21,21 +21,31 @@ class SimpleDAG(object): def generate_graphviz_plot(self): def run_status(obj): + dnr = "RUN" + status = "NA" + if obj.job: + status = obj.job.status if obj.do_not_run is True: - s = "DNR" - else: - s = "RUN" - s += "_{}".format(obj.id) - return s + dnr = "DNR" + return "{}_{}_{}".format(dnr, status, obj.id) doc = """ digraph g { rankdir = LR """ for n in self.nodes: + obj = n['node_object'] + status = "NA" + if obj.job: + status = obj.job.status + color = 'black' + if status == 'successful': + color = 'green' + elif status == 'failed': + color = 'red' doc += "%s [color = %s]\n" % ( run_status(n['node_object']), - "red" if getattr(n['node_object'], 'status', 'N/A') == 'running' else "black", + color ) for from_node, to_node, label in self.edges: doc += "%s -> %s [ label=\"%s\" ];\n" % ( @@ -44,7 +54,7 @@ class SimpleDAG(object): label, ) doc += "}\n" - gv_file = open('/tmp/graph.gv', 'w') + gv_file = open('/awx_devel/graph.gv', 'w') gv_file.write(doc) gv_file.close() diff --git a/awx/main/scheduler/dag_workflow.py b/awx/main/scheduler/dag_workflow.py index c872e3a712..dd9e5b7bb5 100644 --- a/awx/main/scheduler/dag_workflow.py +++ b/awx/main/scheduler/dag_workflow.py @@ -120,15 +120,30 @@ class WorkflowDAG(SimpleDAG): if not job and obj.do_not_run is False and n not in root_nodes: parent_nodes = [p['node_object'] for p in self.get_dependents(obj)] all_parents_dnr = True + parent_run_path = False for p in parent_nodes: if not p.job and p.do_not_run is False: all_parents_dnr = False - break + + elif p.job and p.job.status in ['new', 'pending', 'waiting', 'running']: + parent_run_path = True + + elif p.job and p.job.status == 'successful': + if n in self.get_dependencies(p, 'success_nodes'): + parent_run_path = True + + elif p.job and p.job.status == 'failed': + children_failed = self.get_dependencies(p, 'failure_nodes') + children_always = self.get_dependencies(p, 'always_nodes') + if n in children_always or n in children_failed: + parent_run_path = True + #all_parents_dnr = reduce(lambda p: bool(p.do_not_run == True), parent_nodes) - if all_parents_dnr: + if all_parents_dnr and parent_run_path is False: obj.do_not_run = True nodes_marked_do_not_run.append(n) + if obj.do_not_run: children_success = self.get_dependencies(obj, 'success_nodes') children_failed = self.get_dependencies(obj, 'failure_nodes')