Esempio n. 1
0
    def __run_job(self, job):
        try:
            spirit = TaskLoader.init(job["spirit_id"], task_root=self.task_dir)
        except TaskLoadError:
            trace = traceback.format_exc()
            print("Could not load job %s" % job)
            print(trace)
            self.__finish_job(job, FinishState.LOAD_ERROR, message=trace)
        except Exception:
            trace = traceback.format_exc()
            print("Aborted job %s with error %s" % (job, trace))
            self.__finish_job(job, FinishState.WORKER_ERROR, message=trace)
        else:
            # Run spirit with runner, and send different finish states
            # depending on if there was an execution error, unit test error, abort, or success

            try:
                dep_input = TaskLoader.load_dependencies(
                    spirit, self.config, default_driver=self.default_driver)

                if spirit.stored_in() is None:
                    writer = self.default_driver.write(spirit, self.config)
                else:
                    writer = spirit.stored_in().write(spirit, self.config)
            except Exception:
                trace = traceback.format_exc()
                print("Aborted spirit %s with error %s" % (spirit, trace))
                self.__finish_job(job, FinishState.LOAD_ERROR, message=trace)
            else:
                do_heartbeat = True

                try:
                    print("Run spirit %s" % spirit)

                    def do_thread():
                        timeout = 0.1 * self.config.get("watchdog.timeout")
                        transaction_id = job["transaction_id"]

                        while do_heartbeat:
                            self.remote.heartbeat(transaction_id)
                            time.sleep(timeout)

                    heartbeat_thread = threading.Thread(target=do_thread)
                    heartbeat_thread.start()

                    spirit.executed_by().run(
                        PathFinder.get_task_path(spirit.name(),
                                                 task_root=self.task_dir),
                        spirit.parameters, dep_input, writer)
                except Exception:
                    trace = traceback.format_exc()
                    print("Aborted spirit %s with error %s" % (spirit, trace))
                    self.__finish_job(job,
                                      FinishState.EXEC_ERROR,
                                      message=trace)
                else:
                    print("Completed spirit %s" % spirit)
                    self.__finish_job(job, FinishState.SUCCESS)

                do_heartbeat = False
    def test_recursive_branches(self):
        r2 = TaskLoader.init(("testing.recursive_dependency", {
            "n": 4,
            "m": 5
        }))
        r3 = TaskLoader.init(("testing.parameter_requires", {
            "requires": [r2.spirit_id(), r2.spirit_id()]
        }))

        self.assertEqual(
            len(DependencyExplorer.involved_spirits(r3.spirit_id())), 6)
    def test_recursive(self):
        r1 = TaskLoader.init(("testing.recursive_dependency", {
            "n": 10,
            "m": 1
        }))
        r2 = TaskLoader.init(("testing.recursive_dependency", {
            "n": 4,
            "m": 5
        }))

        with self.assertRaises(CyclicDependencyException):
            DependencyExplorer.build_graph(r1.spirit_id())

        self.assertEqual(
            len(DependencyExplorer.involved_spirits(r2.spirit_id())), 5)
Esempio n. 4
0
    def delete_corrupt(self):
        self.logger.notice("Delete corrupt requested")

        # Delete all casks that are not registered in the meta db,
        # is a pipe (now) or cannot be initiated from its still
        existing_casks = [spirit for spirit in self.__cask_spirits() if not TaskLoader.spirit_is_pipe(spirit)]

        self.delete_all(whitelist=existing_casks)
Esempio n. 5
0
        def enforce_expired(spirit):
            cask_dt = self.__get_cask_datetime(spirit)

            return not TaskLoader.spirit_is_pipe(spirit) and (
                cask_dt is None or
                (scheduling_info.age_requirement is not None
                 and cask_dt + datetime.timedelta(
                     seconds=scheduling_info.age_requirement) < now))
Esempio n. 6
0
    def remove_cask_spirit(self, handle, params, body):
        try:
            spirit_id = body.get("spirit_id", None)
        except Exception:
            return handle.error(400)

        if spirit_id is None:
            return handle.error(400)

        try:
            spirit = TaskLoader.init(spirit_id)
            handle.server.env.gc.delete_spirit(spirit)
        except Exception as e:
            handle.server.env.logger.claim("CoreHandler").error(e)
            return handle.error(500)

        handle.json({"status": "ok"})
Esempio n. 7
0
    def add(self, scheduling_info, persistent=False):
        """Add a scheduling rule to the backlog
        Only for once instance of the daemon if persistent=False
        Or in the meta db if persistent=True"""

        if TaskLoader.init(scheduling_info.spirit_id).inherits("DefaultPipe"):
            raise ValueError("Target cannot be a pipe")

        if (persistent or scheduling_info.reoccurring
            ) and scheduling_info.age_requirement == 0:
            raise ValueError(
                "Reoccurring target cannot have age requirement 0")

        if persistent:
            scheduling_info.reoccurring = True
            scheduling_info = self.env.meta.add_scheduled_spirit(
                scheduling_info)

        heapq.heappush(self.backlog, scheduling_info)
Esempio n. 8
0
 def __cask_spirits(self):
     return [
         TaskLoader.init(cask["spirit_id"], none_on_error=True)
         for cask in self.env.meta.get_all_casks()
     ]
Esempio n. 9
0
 def test_not_found(self):
     with self.assertRaises(TaskLoadError):
         TaskLoader.load("testing.not_existing")
Esempio n. 10
0
 def test_valid_definition(self):
     ValidSpirit = TaskLoader.load("testing.valid_definition")
     aSpirit = ValidSpirit()
     self.assertTrue(aSpirit.a_test_function())
Esempio n. 11
0
 def test_corrupt_definition(self):
     with self.assertRaises(TaskLoadError):
         TaskLoader.load("testing.corrupt_definition")
Esempio n. 12
0
 def involved_spirits(cls, target_spirit_id, **kwargs):
     return list(
         cls.__explore(TaskLoader.init(target_spirit_id),
                       **kwargs)[0].keys())
Esempio n. 13
0
 def build_graph(cls, target_spirit_id, **kwargs):
     return cls.__explore(TaskLoader.init(target_spirit_id), **kwargs)[2]
Esempio n. 14
0
    def __explore(cls,
                  current_spirit,
                  all_nodes=None,
                  downward_used_spirits=None,
                  downward_occurrences=None,
                  **kwargs):
        enforce_func = kwargs.get("enforce_func", None)
        skip_pipes = kwargs.get("skip_pipes", True)

        if all_nodes is None:
            all_nodes = dict()
        if downward_used_spirits is None:
            downward_used_spirits = set()
        if downward_occurrences is None:
            downward_occurrences = dict()

        # Check if current spirit has already been used
        if current_spirit in downward_used_spirits:
            raise CyclicDependencyException(current_spirit.spirit_id())

        up_downward_used_spirits = set(downward_used_spirits)
        up_downward_used_spirits.add(current_spirit)

        # Check if the task exceeds its occurrence count
        up_downward_occurrences = dict(downward_occurrences)

        curr_task_id = current_spirit.name()

        if curr_task_id not in up_downward_occurrences:
            up_downward_occurrences[curr_task_id] = current_spirit.occurrences(
            )

        up_downward_occurrences[curr_task_id] -= 1

        if up_downward_occurrences[curr_task_id] < 0:
            raise CyclicDependencyException(curr_task_id, task=True)

        parents = set()
        roots = set()

        for dep in current_spirit.requires():
            dep_spirit = TaskLoader.init(dep)

            _, dep_nodes, dep_roots = cls.__explore(
                dep_spirit,
                all_nodes=all_nodes,
                downward_used_spirits=up_downward_used_spirits,
                downward_occurrences=up_downward_occurrences,
                **kwargs)

            if dep_nodes is not None:
                parents.update(dep_nodes)
                roots.update(dep_roots)

        has_parents = len(parents) > 0
        # Default is all enforced
        build_enforced = enforce_func is None or enforce_func(current_spirit)
        is_pipe = TaskLoader.spirit_is_pipe(current_spirit)

        # No prune possible if upward needs to be built or build for this spirit is enforced.
        if skip_pipes and is_pipe:
            if has_parents:
                return all_nodes, parents, roots
            else:
                return all_nodes, None, []
        elif has_parents or build_enforced:
            curr_node = cls.__get_node(all_nodes, current_spirit)

            for parent in parents:
                curr_node.add_parent(parent)

            # No parents? This is the first with enforced build.
            # Therefore, it is the first root of this path.
            if not has_parents:
                roots = [curr_node]

            return all_nodes, [curr_node], roots
        else:
            return all_nodes, None, []
    def setUp(self):
        self.t1 = TaskLoader.init(("testing.parameter_requires_pipe", {
            "requires": [],
            "id": 1
        }))
        self.t2 = TaskLoader.init(("testing.parameter_requires", {
            "requires": [self.t1.spirit_id()],
            "id": 2
        }))
        self.t3 = TaskLoader.init(("testing.parameter_requires", {
            "requires": [self.t2.spirit_id()],
            "id": 3
        }))
        self.t4 = TaskLoader.init(("testing.parameter_requires_pipe", {
            "requires": [self.t3.spirit_id()],
            "id": 4
        }))
        self.t5 = TaskLoader.init(("testing.parameter_requires", {
            "requires": [self.t4.spirit_id()],
            "id": 5
        }))
        self.t6 = TaskLoader.init(("testing.parameter_requires", {
            "requires": [],
            "id": 6
        }))
        self.t7 = TaskLoader.init(("testing.parameter_requires_pipe", {
            "requires": [self.t6.spirit_id()],
            "id": 7
        }))
        self.t8 = TaskLoader.init(("testing.parameter_requires", {
            "requires": [],
            "id": 8
        }))
        self.t9 = TaskLoader.init(("testing.parameter_requires", {
            "requires": [self.t7.spirit_id(),
                         self.t8.spirit_id()],
            "id":
            9
        }))
        self.t10 = TaskLoader.init(("testing.parameter_requires", {
            "requires": [self.t7.spirit_id()],
            "id": 10
        }))
        self.t11 = TaskLoader.init(("testing.parameter_requires", {
            "requires":
            [self.t5.spirit_id(),
             self.t9.spirit_id(),
             self.t10.spirit_id()],
            "id":
            11
        }))

        self.ua = TaskLoader.init(("testing.parameter_requires", {
            "requires": [],
            "id": "A"
        }))
        self.ub = TaskLoader.init(("testing.parameter_requires", {
            "requires": [],
            "id": "B"
        }))
        self.uc = TaskLoader.init(("testing.parameter_requires", {
            "requires": [],
            "id": "C"
        }))
        self.up1 = TaskLoader.init(("testing.parameter_requires_pipe", {
            "requires": [self.ua.spirit_id(),
                         self.ub.spirit_id()],
            "id":
            "P1"
        }))
        self.up2 = TaskLoader.init(("testing.parameter_requires_pipe", {
            "requires": [self.up1.spirit_id(),
                         self.uc.spirit_id()],
            "id":
            "P2"
        }))
        self.ud = TaskLoader.init(("testing.parameter_requires", {
            "requires": [self.up2.spirit_id()],
            "id": "D"
        }))
Esempio n. 16
0
 def it(self):
     return PipeIterator(
         self.spirit.pipe_iterator(
             TaskLoader.load_dependencies(self.spirit, self.config)))
Esempio n. 17
0
 def test_missing_definition(self):
     with self.assertRaises(TaskLoadError):
         TaskLoader.load("testing.missing_definition")