Beispiel #1
0
    def logs(self, limit=10):
        """Find all log entries for script"""
        logs = []

        session = Session()

        for log in (session.query(Log).filter(Log.script == self.uid).order_by(
                Log.date.desc()).limit(limit).all()):
            try:
                stdout = log.text.decode("utf-8")
            except AttributeError:
                stdout = log.text

            try:
                stderr = log.error.decode("utf-8")
            except AttributeError:
                stderr = log.error

            logs.append({
                "stdout": stdout,
                "stderr": stderr,
                "date": log.date,
                "exitcode": log.exitcode,
            })

        session.close()

        return logs
Beispiel #2
0
def get_setting(key):
    """Get setting value from database. Return None or value."""
    session = Session()
    value = session.query(Setting).get(key)
    session.close()

    return value
Beispiel #3
0
def run(arguments, event):
    session = Session()

    for script in session.query(ScriptModel).all():
        script = Script(script.uid)
        script.prune_logs()

    return 
Beispiel #4
0
def get_all_settings():
    """Get all settings from database."""
    session = Session()

    all_settings = session.query(Setting).all()
    session.close()

    return session
Beispiel #5
0
def execute_task(id):
    session = Session()
    task = session.query(Task).get(id)
    logger.debug("Processing task with ID: {}", id)
    task_uid = task.task_id
    task_module = importlib.import_module("chronos.tasks.{}".format(task_uid))
    task_id_dict = {"task_id": id}

    logger.debug("Starting task with ID: {}", id)
    task.time_started = datetime.datetime.now()
    task.status = "STARTED"
    session.commit()

    event.trigger("task_started", task_id_dict)
    arguments = {**json.loads(task.task_arguments), **task_id_dict}

    task.output = task_module.run(json.dumps(arguments), event)

    event.trigger("task_finished", task_id_dict)

    task.time_finished = datetime.datetime.now()
    task.status = "FINISHED"
    session.commit()
    logger.debug("Finished task with ID: {}", id)

    session.close()

    return
Beispiel #6
0
def scripts():
    scripts = []

    session = Session()

    for s in session.query(ScriptModel).all():
        scripts.append(chronos.script.Script(s.uid).to_dict())

    session.close()

    return jsonify(scripts), 200
Beispiel #7
0
    def prune_logs(self):
        session = Session()

        if session.query(Log).count() > 10:
            logger.debug("Pruning logs for {}".format(self.uid))
            too_old = datetime.now() - timedelta(days=3)

            # logger.debug(too_old)

            logger.debug("Found {} logs to be pruned".format(
                session.query(Log).filter(Log.date < too_old).count()))
            session.query(Log).filter(Log.date < too_old).delete()

        session.commit()
        session.close()
Beispiel #8
0
def set_setting(key, value):
    """Update setting or create new."""
    session = Session()
    if get_setting(key) is None:
        session.add(Setting(key=key, value=value))
        logger.debug("Created new 'setting': {} with value: '{}'", key, value)
    else:
        session.query(Setting).get(key).value = value
        logger.debug("Updated 'setting': {} with value: '{}'", key, value)

    session.commit()
    session.close()
Beispiel #9
0
    def put(self, uid):
        """Update script."""
        args = request.get_json(force=True)

        session = Session()

        try:
            script = chronos.script.Script(uid)
            model = session.query(ScriptModel).get(uid)

            # Update each field if it exists
            try:
                model.name = args["name"]
            except KeyError:
                pass

            try:
                model.triggers = args["triggers"]
            except KeyError:
                pass

            try:
                model.enabled = args["enabled"]
            except KeyError:
                pass

            try:
                script.write_contents(args["contents"])
            except KeyError:
                pass

            try:
                script.write_requirements(args["requirements"])
            except KeyError:
                pass

            session.commit()

            return "OK", 200

        except KeyError:
            return None, 404
Beispiel #10
0
def execute_next_task():
    session = Session()
    tasks = session.query(Task).filter(Task.status == "WAITING")

    # logger.debug("Executing next available task...")

    for task in tasks:
        if task.priority == "NOW":
            task_thread = threading.Thread(target=execute_task(task.id))
            task_thread.start()
            # logger.debug("Next task has been scheduled")

            return

    if tasks.count() > 0:
        task_thread = threading.Thread(target=execute_task(tasks[0].id))
        task_thread.start()
    #  logger.debug("Next task has been scheduled")

    session.close()
Beispiel #11
0
def run(arguments, event):
    arguments = json.loads(arguments)
    name = arguments["name"]

    session = Session()
    """Create a new script by creating a virtualenv, creating .sh scripts and registering metadata."""
    if name is "":
        # Generate random UID if no name is given
        uid = generate_uid()
    else:
        # Convert name to UID by "sluggifying" it (e.g. "Simon's script" -> "simons-script")
        uid = for_uid(name)

    # Check that the scripts folder exists (important for first-time users)
    if not os.path.isdir(CHRONOS + os.path.sep + "scripts"):
        os.mkdir(CHRONOS + os.path.sep + "scripts")

    # Find script path given UID
    path = CHRONOS + os.path.sep + "scripts" + os.path.sep + uid

    # Create folder, if it doesn't already exist
    if not os.path.isdir(path):
        os.mkdir(path)
    else:
        os.rmdir(path)
        os.mkdir(path)

    # Create virtual environment
    create_env(uid)

    # Create database entry
    script = ScriptModel(name=name, uid=uid, enabled=True, triggers=[])
    session.add(script)
    session.commit()

    # Create script and requirements.txt file
    script_path = path + os.path.sep + uid + ".py"
    requirements_path = path + os.path.sep + "requirements.txt"
    open(script_path, "a").close()
    open(requirements_path, "a").close()

    # Create execute script
    # TODO: Move this script to a folder so it can be copied instead
    with open(path + os.path.sep + "execute.sh", "w") as file:
        file.write('''#!/bin/bash
cd "{}"
source "{}"
python -u "{}"'''.format(path, get_activate(uid), script_path))

    # Create pip install
    # TODO: Move this script to a folder so it can be copied instead
    with open(path + os.path.sep + "install.sh", "w") as file:
        file.write('''#!/bin/bash
source "{}"
pip install -r "{}"'''.format(get_activate(uid), requirements_path))

    event.trigger("script_created", Script(uid).to_dict())

    return uid
Beispiel #12
0
    def enable(self):
        session = Session()
        script_from_database = session.query(ScriptModel).get(self.uid)
        script_from_database.enabled = True
        session.commit()
        session.close()

        self.enabled = True

        event.trigger("script_updated", self.__dict__())
        event.trigger("action_complete", {"action": "enable", "uid": self.uid})
Beispiel #13
0
def run(arguments, event):
    arguments = json.loads(arguments)
    uid = arguments["uid"]

    script = Script(uid)

    session = Session()

    # Remove script folder
    shutil.rmtree(script.folder)

    # Remove all logs from script
    session.query(Log).filter(Log.script == script.uid).delete()

    # Delete metadata
    session.delete(script.db)
    session.commit()
    session.close()

    event.trigger("action_complete", {"action": "delete", "uid": script.uid})
    event.trigger("script_deleted", {"uid": script.uid})

    return uid
Beispiel #14
0
    def __init__(self, uid):
        """Initialise script class given UID."""

        session = Session()

        # UID
        self.uid = uid

        # Get database entry
        self.db = session.query(ScriptModel).get(uid)

        # Store dictionary version of model
        self.dict = {
            "name": self.db.name,
            "triggers": self.db.triggers,
            "logs": self.logs(),
            "created": str(self.db.created),
        }

        self.enabled = self.db.enabled

        # Get script folder
        self.folder = CHRONOS + os.path.sep + "scripts" + os.path.sep + self.uid

        # Get path of script
        self.path = self.folder + os.path.sep + self.uid + ".py"

        # Get path of requirements file
        self.requirements = self.folder + os.path.sep + "requirements.txt"

        # Get path of execute.sh script
        self.execute_path = self.folder + os.path.sep + "execute.sh"

        # Get path of install.sh script
        self.install_requirements_path = self.folder + os.path.sep + "install.sh"

        session.close()
Beispiel #15
0
def dispatch_task(task_id, task_arguments, task_priority="ROUTINE"):
    session = Session()
    task = Task(
        task_id=task_id,
        task_arguments=json.dumps(task_arguments),
        priority=task_priority,
        status="WAITING",
    )

    session.add(task)
    session.commit()
    logger.debug("Dispatched task: {}", task_id)
    event.trigger("task_dispatched", {"task_id": task_id})

    session.close()

    return True
Beispiel #16
0
import threading

# Third-party dependencies
import cronex
from loguru import logger

# First-party dependencies
from chronos.util import *
from chronos.venv import *
from chronos.metadata import Session
from chronos.metadata import Script as ScriptModel
from chronos.script import Script
from chronos.task import dispatch_task
from chronos.bus import interval_trigger

session = Session()


def evalaute_script_interval_triggers(tick, interval):
    second = tick * interval / 1000

    for script in session.query(ScriptModel).all():
        s = Script(script.uid)

        if script.enabled:

            for trigger in script.triggers:

                if trigger["type"] == "interval":
                    if second % int(trigger["options"]["interval"]) == 0:
                        dispatch_task(
Beispiel #17
0
def run(arguments, event):
    arguments = json.loads(arguments)
    script_uid = arguments["script_uid"]
    task_id = arguments["task_id"]

    event.trigger("action_started", {"uid": script_uid, "action": "execute"})

    script = Script(script_uid)

    process = Popen(["bash", script.execute_path],
                    stdout=PIPE,
                    stderr=PIPE,
                    shell=False)

    exitcode = 0
    process_output = ""

    while True:
        output = process.stdout.readline()
        process_output += output.decode("utf-8")
        if process.poll() is not None:
            break

        if output:
            event.trigger(
                "task_output",
                {
                    "task_id": task_id,
                    "script_uid": script_uid,
                    "output": output.decode("utf-8"),
                    "task": "execute",
                },
            )

    exitcode = process.poll()

    stdout, stderr = process.communicate()

    if stderr:
        event.trigger(
            "task_output",
            {
                "task_id": task_id,
                "script_uid": script_uid,
                "output": stderr.decode("utf-8"),
                "task": "execute",
            },
        )

    session = Session()
    log = Log(script=script_uid,
              text=process_output,
              error=stderr,
              exitcode=exitcode)
    session.add(log)
    session.commit()
    session.close()

    event.trigger(
        "task_output",
        {
            "task_id": task_id,
            "output": "",
            "script_uid": script.uid,
            "task": "execute"
        },
    )
    script = script.to_dict()

    # Decode bytes to string
    try:
        stderr = stderr.decode("utf-8")
    except AttributeError:
        pass

    try:
        process_output = process_output.decode("utf-8")
    except AttributeError:
        pass

    script["logs"].insert(
        0,
        {
            "date": maya.now().rfc2822(),
            "stderr": stderr,
            "stdout": process_output,
            "exitcode": exitcode,
        },
    )
    event.trigger("script_executed", script)

    event.trigger("script_updated", script)
    event.trigger("action_complete", {
        "action": "execute",
        "uid": script["uid"]
    })

    return stdout
Beispiel #18
0
 def prune_logs(self):
     session = Session()
     session.query(Log).filter(Log.date >= timedelta(days=3)).delete()
     session.commit()
     session.close()