def test_insert(self):
        # A job can not be created without a jobtype, create one first
        jobtype = JobType()
        jobtype.name = "foo"
        jobtype.description = "this is a job type"
        jobtype_version = JobTypeVersion()
        jobtype_version.jobtype = jobtype
        jobtype_version.version = 1
        jobtype_version.classname = "Foobar"
        jobtype_version.code = ("""
            class Foobar(JobType):
                pass""").encode("utf-8")
        db.session.add(jobtype_version)

        queue = JobQueue()
        queue.name = "FooQueue"

        job = Job()
        job.title = "Test Job"
        job.jobtype_version = jobtype_version
        job.queue = queue

        tag = Tag()
        tag.jobs = [job]
        tag.tag = "foo456"
        db.session.add_all([tag, job])
        db.session.commit()
        model_id = tag.id
        job_id = job.id
        db.session.remove()
        result = Tag.query.filter_by(id=model_id).first()
        self.assertEqual(result.tag, "foo456")
        self.assertEqual(result.jobs[0].id, job_id)
    def test_insert(self):
        jobtype = JobType()
        jobtype.name = "foo"
        jobtype.description = "this is a job type"
        jobtype_version = JobTypeVersion()
        jobtype_version.jobtype = jobtype
        jobtype_version.version = 1
        jobtype_version.classname = "Foobar"
        jobtype_version.code = ("""
            class Foobar(JobType):
                pass""").encode("utf-8")
        db.session.add(jobtype_version)

        job = Job()
        job.title = "Test Job"
        job.jobtype_version = jobtype_version

        task = Task(state=WorkState.DONE,
                    priority=404,
                    frame=1,
                    last_error="foobar",
                    job=job)
        db.session.add(task)
        db.session.commit()
        task_id = task.id
        db.session.remove()
        searched = Task.query.filter_by(id=task_id).first()
        self.assertIsNotNone(searched)
        self.assertEqual(searched.state, WorkState.DONE)
        self.assertEqual(searched.priority, 404)
        self.assertEqual(searched.attempts, 0)
        self.assertEqual(searched.frame, 1)
    def test_insert(self):
        jobtype = JobType()
        jobtype.name = "foo"
        jobtype.description = "this is a job type"
        jobtype_version = JobTypeVersion()
        jobtype_version.jobtype = jobtype
        jobtype_version.version = 1
        jobtype_version.classname = "Foobar"
        jobtype_version.code = ("""
            class Foobar(JobType):
                pass""").encode("utf-8")
        db.session.add(jobtype_version)

        job = Job()
        job.title = "Test Job"
        job.jobtype_version = jobtype_version

        task = Task(
            state=WorkState.DONE,
            priority=404,
            frame=1,
            last_error="foobar",
            job=job)
        db.session.add(task)
        db.session.commit()
        task_id = task.id
        db.session.remove()
        searched = Task.query.filter_by(id=task_id).first()
        self.assertIsNotNone(searched)
        self.assertEqual(searched.state, WorkState.DONE)
        self.assertEqual(searched.priority, 404)
        self.assertEqual(searched.attempts, 0)
        self.assertEqual(searched.frame, 1)
    def create_jobtype_version(self):
        jobtype = JobType()
        jobtype.name = "foo"
        jobtype.description = "this is a job type"
        jobtype_version = JobTypeVersion()
        jobtype_version.jobtype = jobtype
        jobtype_version.version = 1
        jobtype_version.classname = "Foobar"
        jobtype_version.code = ("""
            class Foobar(JobType):
                pass""").encode("utf-8")
        db.session.add(jobtype_version)
        db.session.flush()

        return jobtype_version
Beispiel #5
0
    def create_jobtype_version(self):
        jobtype = JobType()
        jobtype.name = "foo"
        jobtype.description = "this is a job type"
        jobtype_version = JobTypeVersion()
        jobtype_version.jobtype = jobtype
        jobtype_version.version = 1
        jobtype_version.classname = "Foobar"
        jobtype_version.code = ("""
            class Foobar(JobType):
                pass""").encode("utf-8")
        db.session.add(jobtype_version)
        db.session.flush()

        return jobtype_version
    def test_insert(self):
        # A job can not be created without a jobtype, create one first
        jobtype = JobType()
        jobtype.name = "foo"
        jobtype.description = "this is a job type"
        jobtype.classname = "Foobar"
        jobtype.code = dedent("""
        class Foobar(JobType):
            pass""").encode("utf-8")
        jobtype.mode = JobTypeLoadMode.OPEN
        db.session.add(jobtype)

        job = Job()
        job.job_type = jobtype
        tag = Tag()
        tag.jobs = [job]
        tag.tag = "foo456"
        db.session.add_all([tag, job])
        db.session.commit()
        model_id = tag.id
        job_id = job.id
        db.session.remove()
        result = Tag.query.filter_by(id=model_id).first()
        self.assertEqual(result.tag, "foo456")
        self.assertEqual(result.jobs[0].id, job_id)
Beispiel #7
0
    def test_basic_insert(self):
        value_name = "foo"
        value_description = "this is a job type"
        value_classname = "Foobar"
        value_code = dedent("""
        class %s(JobType):
            pass""" % value_classname)
        value_mode = JobTypeLoadMode.OPEN

        # create jobtype
        jobtype = JobType()
        jobtype.name = value_name
        jobtype.description = value_description
        jobtype.classname = value_classname
        jobtype.code = value_code
        jobtype.mode = value_mode
        db.session.add(jobtype)
        db.session.commit()

        # store id and remove the session
        jobtypeid = jobtype.id
        db.session.remove()

        jobtype = JobType.query.filter_by(id=jobtypeid).first()
        self.assertEqual(jobtype.name, value_name)
        self.assertEqual(jobtype.description, value_description)
        self.assertEqual(jobtype.classname, value_classname)
        self.assertEqual(jobtype.code, value_code)
        self.assertEqual(jobtype.mode, value_mode)
    def test_insert(self):
        # A job can not be created without a jobtype, create one first
        jobtype = JobType()
        jobtype.name = "foo"
        jobtype.description = "this is a job type"
        jobtype.classname = "Foobar"
        jobtype.code = dedent("""
        class Foobar(JobType):
            pass""").encode("utf-8")
        jobtype.mode = JobTypeLoadMode.OPEN
        db.session.add(jobtype)

        job = Job()
        job.job_type = jobtype
        software = Software()
        software.jobs = [job]
        software.software = "foo"
        db.session.add_all([job, software])
        db.session.commit()
        job_id = job.id
        software_id = software.id
        db.session.remove()
        software = Software.query.filter_by(id=software_id).first()
        self.assertEqual(software.jobs[0].id, job_id)
        self.assertEqual(software.software, "foo")
        self.assertEqual(software.version, "any")
    def test_unique(self):
        # A job can not be created without a jobtype, create one first
        jobtype = JobType()
        jobtype.name = "foo"
        jobtype.description = "this is a job type"
        jobtype.classname = "Foobar"
        jobtype.code = dedent("""
        class Foobar(JobType):
            pass""").encode("utf-8")
        db.session.add(jobtype)

        job = Job()
        job.job_type = jobtype

        software = Software()
        software.software = "foo"

        requirementA = JobSoftwareRequirement()
        requirementB = JobSoftwareRequirement()
        requirementA.job = job
        requirementA.software = software
        requirementB.job = job
        requirementB.software = software
        db.session.add_all([job, requirementA, requirementB])

        with self.assertRaises(DatabaseError):
            db.session.commit()
    def test_insert(self):
        # A job can not be created without a jobtype, create one first
        jobtype = JobType()
        jobtype.name = "foo"
        jobtype.description = "this is a job type"
        jobtype_version = JobTypeVersion()
        jobtype_version.jobtype = jobtype
        jobtype_version.version = 1
        jobtype_version.classname = "Foobar"
        jobtype_version.code = ("""
            class Foobar(JobType):
                pass""").encode("utf-8")
        db.session.add(jobtype_version)

        queue = JobQueue()
        queue.name = "FooQueue"

        job = Job()
        job.title = "Test Job"
        job.jobtype_version = jobtype_version
        job.queue = queue

        # Software requirement needs a software first
        software = Software()
        software.software = "foo"
        requirement = JobSoftwareRequirement()
        requirement.job = job
        requirement.software = software
        db.session.add(job)
        db.session.commit()
        job_id = job.id
        requirement_id = requirement.id
        requirement2 = JobSoftwareRequirement.query.\
            filter_by(id=requirement_id).first()
        self.assertEqual(requirement.job.id, job_id)
        self.assertEqual(requirement2.software.software, "foo")
        self.assertEqual(requirement2.min_version, None)
        self.assertEqual(requirement2.max_version, None)
Beispiel #11
0
    def test_clear_last_error(self):
        jobtype = JobType()
        jobtype.name = "foo"
        jobtype.description = "this is a job type"
        jobtype_version = JobTypeVersion()
        jobtype_version.jobtype = jobtype
        jobtype_version.version = 1
        jobtype_version.classname = "Foobar"
        jobtype_version.code = ("""
            class Foobar(JobType):
                pass""").encode("utf-8")
        db.session.add(jobtype_version)

        job = Job()
        job.title = "Test Job"
        job.jobtype_version = jobtype_version

        task = Task(frame=1, job=job, last_error="foobar")
        db.session.add(task)
        db.session.commit()
        db.session.add(task)
        task.state = WorkState.DONE
        self.assertIsNone(task.last_error)
    def test_clear_last_error(self):
        jobtype = JobType()
        jobtype.name = "foo"
        jobtype.description = "this is a job type"
        jobtype_version = JobTypeVersion()
        jobtype_version.jobtype = jobtype
        jobtype_version.version = 1
        jobtype_version.classname = "Foobar"
        jobtype_version.code = ("""
            class Foobar(JobType):
                pass""").encode("utf-8")
        db.session.add(jobtype_version)

        job = Job()
        job.title = "Test Job"
        job.jobtype_version = jobtype_version

        task = Task(frame=1, job=job, last_error="foobar")
        db.session.add(task)
        db.session.commit()
        db.session.add(task)
        task.state = WorkState.DONE
        self.assertIsNone(task.last_error)
Beispiel #13
0
    def test_before_insert_parent_class(self):
        value_name = "foo"
        value_description = "this is a job type"
        value_classname = "Foobar"
        value_code = dedent("""
        class %s(object):
            pass""" % value_classname).encode("utf-8")

        # create jobtype
        jobtype = JobType()
        jobtype.name = value_name
        jobtype.description = value_description
        jobtype.classname = value_classname
        jobtype.code = value_code
        jobtype.mode = JobTypeLoadMode.DOWNLOAD
        db.session.add(jobtype)

        with self.assertRaises(SyntaxError):
            db.session.commit()
Beispiel #14
0
def schema():
    """
    Returns the basic schema of :class:`.JobType`

    .. http:get:: /api/v1/jobtypes/schema HTTP/1.1

        **Request**

        .. sourcecode:: http

            GET /api/v1/jobtypes/schema HTTP/1.1
            Accept: application/json

        **Response**

        .. sourcecode:: http

            HTTP/1.1 200 OK
            Content-Type: application/json

            {
                "batch_contiguous": "BOOLEAN",
                "classname": "VARCHAR(64)",
                "code": "TEXT",
                "description": "TEXT",
                "id": "INTEGER",
                "version": "INTEGER",
                "max_batch": "INTEGER",
                "no_automatic_start_time": "INTEGER",
                "name": "VARCHAR(64)"
            }

    :statuscode 200:
        no error
    """
    schema_dict = JobTypeVersion.to_schema()
    schema_dict.update(JobType.to_schema())
    return jsonify(schema_dict), OK
def schema():
    """
    Returns the basic schema of :class:`.JobType`

    .. http:get:: /api/v1/jobtypes/schema HTTP/1.1

        **Request**

        .. sourcecode:: http

            GET /api/v1/jobtypes/schema HTTP/1.1
            Accept: application/json

        **Response**

        .. sourcecode:: http

            HTTP/1.1 200 OK
            Content-Type: application/json

            {
                "batch_contiguous": "BOOLEAN",
                "classname": "VARCHAR(64)",
                "code": "TEXT",
                "description": "TEXT",
                "id": "INTEGER",
                "version": "INTEGER",
                "max_batch": "INTEGER",
                "no_automatic_start_time": "INTEGER",
                "name": "VARCHAR(64)"
            }

    :statuscode 200:
        no error
    """
    schema_dict = JobTypeVersion.to_schema()
    schema_dict.update(JobType.to_schema())
    return jsonify(schema_dict), OK
    def post(self):
        """
        A ``POST`` to this endpoint will create a new jobtype.

        .. http:post:: /api/v1/jobtypes/ HTTP/1.1

            **Request**

            .. sourcecode:: http

                POST /api/v1/jobtypes/ HTTP/1.1
                Accept: application/json

                {
                    "name": "TestJobType",
                    "classname": "TestJobType",
                    "description": "Jobtype for testing inserts and queries",
                    "code": "\\nfrom pyfarm.jobtypes.core.jobtype import "
                            "JobType\\n\\nclass TestJobType(JobType):\\n"
                            "    def get_command(self):\\n"
                            "        return \"/usr/bin/touch\"\\n\\n"
                            "    def get_arguments(self):\\n"
                            "           return [os.path.join("
                            "self.assignment_data[\"job\"][\"data\"][\"path\"], "
                            "\"%04d\" % self.assignment_data[\"tasks\"]"
                            "[0][\"frame\"])]\\n"
                }

            **Response**

            .. sourcecode:: http

                HTTP/1.1 200 OK
                Content-Type: application/json

                {
                    "id": 1,
                    "batch_contiguous": true,
                    "software_requirements": [],
                    "version": 1,
                    "max_batch": 1,
                    "name": "TestJobType",
                    "classname": "TestJobType",
                    "description": "Jobtype for testing inserts and queries",
                    "code": "\\nfrom pyfarm.jobtypes.core.jobtype import "
                            "JobType\\n\\nclass TestJobType(JobType):\\n"
                            "    def get_command(self):\\n"
                            "        return \"/usr/bin/touch\"\\n\\n"
                            "    def get_arguments(self):\\n"
                            "           return [os.path.join("
                            "self.assignment_data[\"job\"][\"data\"][\"path\"], "
                            "\"%04d\" % self.assignment_data[\"tasks\"]"
                            "[0][\"frame\"])]\\n"
                }

        :statuscode 201:
            a new jobtype item was created

        :statuscode 400:
            there was something wrong with the request (such as
            invalid columns being included)

        :statuscode 409:
            a conflicting jobtype already exists
        """
        if "name" not in g.json:
            return jsonify(
                error="Jobtype does not specify a name"), BAD_REQUEST
        jobtype = JobType.query.filter_by(name=g.json["name"]).first()

        if jobtype:
            return (jsonify(error="Jobtype %s already exixts" %
                            g.json["name"]), CONFLICT)

        try:
            jobtype = JobType()
            jobtype.name = g.json.pop("name")
            jobtype.description = g.json.pop("description", None)
            jobtype_version = JobTypeVersion()
            jobtype_version.jobtype = jobtype
            jobtype_version.version = 1
            jobtype_version.code = g.json.pop("code")
            jobtype_version.classname = g.json.pop("classname", None)
            jobtype_version.batch_contiguous = g.json.pop(
                "batch_contiguous", None)
            jobtype_version.no_automatic_start_time = g.json.pop(
                "no_automatic_start_time", None)
            if "max_batch" in g.json and g.json["max_batch"] is None:
                g.json.pop("max_batch")
                jobtype_version.max_batch = sql.null()
            else:
                jobtype_version.max_batch = g.json.pop("max_batch", None)
        except KeyError as e:
            return (jsonify(error="Missing key in input: %r" % e.args),
                    BAD_REQUEST)

        if "software_requirements" in g.json:
            try:
                for r in parse_requirements(g.json["software_requirements"]):
                    r.jobtype_version = jobtype_version
                    db.session.add(r)
            except (TypeError, ValueError) as e:
                return jsonify(error=e.args), BAD_REQUEST
            except ObjectNotFound as e:
                return jsonify(error=e.args), NOT_FOUND
            del g.json["software_requirements"]

        if g.json:
            return (jsonify(error="Unexpected keys in input: %r" %
                            g.json.keys()), BAD_REQUEST)

        db.session.add_all([jobtype, jobtype_version])
        db.session.commit()
        jobtype_data = jobtype_version.to_dict(unpack_relationships=False)
        jobtype_data.update(
            jobtype.to_dict(unpack_relationships=["software_requirements"]))
        del jobtype_data["jobtype_id"]
        logger.info("created jobtype %s: %r", jobtype.name, jobtype_data)

        return jsonify(jobtype_data), CREATED
Beispiel #17
0
def create_jobtype():
    if request.method == "GET":
        return render_template("pyfarm/user_interface/jobtype_create.html",
                               jobtypes=JobType.query,
                               software_items=Software.query)
    else:
        with db.session.no_autoflush:
            jobtype = JobType()
            jobtype.name = request.form["name"]
            jobtype.description = request.form["description"]
            jobtype_version = JobTypeVersion()
            jobtype_version.jobtype = jobtype
            jobtype_version.version = 1
            jobtype_version.max_batch = request.form["max_batch"].strip() or\
                sql.null()
            jobtype_version.batch_contiguous =\
                ("batch_contiguous" in request.form and
                 request.form["batch_contiguous"] == "true")
            jobtype_version.no_automatic_start_time =\
                ("no_automatic_start_time" in request.form and
                 request.form["no_automatic_start_time"] == "true")
            jobtype_version.classname = request.form["classname"]
            jobtype_version.code = request.form["code"]

            requirements = zip(request.form.getlist("software"),
                            request.form.getlist("min_version"),
                            request.form.getlist("min_version"))

            for requirement_tuple in requirements:
                software = Software.query.filter_by(
                    id=int(requirement_tuple[0])).first()
                if not software:
                    return (render_template(
                        "pyfarm/error.html", error="Software %s not found" %
                        requirement_tuple[0]), NOT_FOUND)
                requirement = JobTypeSoftwareRequirement()
                requirement.software = software
                requirement.jobtype_version = jobtype_version

                if requirement_tuple[1] != "":
                    minimum_version = SoftwareVersion.query.filter_by(
                        id=int(requirement_tuple[1])).first()
                    if not minimum_version:
                        return (render_template(
                            "pyfarm/error.html", error="Software version %s not "
                            "found" % requirement_tuple[1]), NOT_FOUND)
                    if minimum_version.software != software:
                        return (render_template(
                            "pyfarm/error.html", error="Software version %s "
                            "does not belong to software %s" %
                            (minimum_version.version, software.software)),
                            BAD_REQUEST)
                    requirement.min_version = minimum_version

                if requirement_tuple[2] != "":
                    maximum_version = SoftwareVersion.query.filter_by(
                        id=int(requirement_tuple[2])).first()
                    if not maximum_version:
                        return (render_template(
                            "pyfarm/error.html", error="Software version %s not "
                            "found" % requirement_tuple[2]), NOT_FOUND)
                    if maximum_version.software != software:
                        return (render_template(
                            "pyfarm/error.html", error="Software version %s "
                            "does not belong to software %s" %
                            (maximum_version.version, software.software)),
                            BAD_REQUEST)
                    requirement.max_version = maximum_version

                db.session.add(requirement)

            db.session.add(jobtype)
            db.session.add(jobtype_version)
            db.session.commit()

        flash("Jobtype %s created" % jobtype.name)

        return redirect(url_for('jobtypes_index_ui'), SEE_OTHER)
Beispiel #18
0
    def put(self, jobtype_name):
        """
        A ``PUT`` to this endpoint will create a new jobtype under the given URI.
        If a jobtype already exists under that URI, a new version will be created
        with the given data.

        You should only call this by id for updating an existing jobtype or if
        you have a reserved jobtype id. There is currently no way to reserve a
        jobtype id.

        .. http:put:: /api/v1/jobtypes/[<str:name>|<int:id>] HTTP/1.1

            **Request**

            .. sourcecode:: http

                PUT /api/v1/jobtypes/TestJobType HTTP/1.1
                Accept: application/json

                {
                    "name": "TestJobType",
                    "description": "Jobtype for testing inserts and queries",
                    "code": "\\nfrom pyfarm.jobtypes.core.jobtype import "
                            "JobType\\n\\nclass TestJobType(JobType):\\n"
                            "    def get_command(self):\\n"
                            "        return \"/usr/bin/touch\"\\n\\n"
                            "    def get_arguments(self):\\n"
                            "           return [os.path.join("
                            "self.assignment_data[\"job\"][\"data\"][\"path\"], "
                            "\"%04d\" % self.assignment_data[\"tasks\"]"
                            "[0][\"frame\"])]\\n"
                }

            **Response**

            .. sourcecode:: http

                HTTP/1.1 201 CREATED
                Content-Type: application/json

                {
                    "batch_contiguous": true,
                    "classname": null,
                    "code": "\\nfrom pyfarm.jobtypes.core.jobtype import "
                            "JobType\\n\\nclass TestJobType(JobType):\\n"
                            "    def get_command(self):\\n"
                            "        return \"/usr/bin/touch\"\\n\\n"
                            "    def get_arguments(self):\\n"
                            "           return [os.path.join("
                            "self.assignment_data[\"job\"][\"data\"][\"path\"], "
                            "\"%04d\" % self.assignment_data[\"tasks\"]"
                            "[0][\"frame\"])]\\n",
                    "id": 1,
                    "max_batch": 1,
                    "name": "TestJobType", 
                    "description": "Jobtype for testing inserts and queries",
                    "software_requirements": []
                }

        :statuscode 201:
            a new jobtype was created

        :statuscode 400:
            there was something wrong with the request (such as
            invalid columns being included)
        """
        if isinstance(jobtype_name, STRING_TYPES):
            jobtype = JobType.query.filter(JobType.name == jobtype_name).first()
        else:
            jobtype = JobType.query.filter_by(id=jobtype_name).first()

        max_version = None
        new = False if jobtype else True
        if jobtype:
            logger.debug("jobtype %s will get a new version with data %r on commit", jobtype.name, g.json)
            max_version, = db.session.query(func.max(JobTypeVersion.version)).filter_by(jobtype=jobtype).first()
        else:
            jobtype = JobType()

        if max_version is not None:
            version = max_version + 1
        else:
            version = 1

        try:
            jobtype.name = g.json.pop("name")
            jobtype.description = g.json.pop("description", None)
            jobtype_version = JobTypeVersion()
            jobtype_version.jobtype = jobtype
            jobtype_version.version = version
            jobtype_version.code = g.json.pop("code")
            jobtype_version.classname = g.json.pop("classname", None)
            jobtype_version.batch_contiguous = g.json.pop("batch_contiguous", None)
            jobtype_version.no_automatic_start_time = g.json.pop("no_automatic_start_time", None)
            if "max_batch" in g.json and g.json["max_batch"] is None:
                g.json.pop("max_batch")
                jobtype_version.max_batch = sql.null()
            else:
                jobtype_version.max_batch = g.json.pop("max_batch", None)
        except KeyError as e:
            return (jsonify(error="Missing key in input: %r" % e.args), BAD_REQUEST)

        if "software_requirements" in g.json:
            try:
                for r in parse_requirements(g.json["software_requirements"]):
                    r.jobtype_version = jobtype_version
                    db.session.add(r)
            except (TypeError, ValueError) as e:
                return jsonify(error=e.args), BAD_REQUEST
            except ObjectNotFound as e:
                return jsonify(error=e.args), NOT_FOUND
            del g.json["software_requirements"]
        elif not new:
            # If the user did not specify a list of software requirements and
            # this jobtype is not new, retain the requirements from the previous
            # version
            previous_version = (
                JobTypeVersion.query.filter(JobTypeVersion.jobtype == jobtype, JobTypeVersion.version != version)
                .order_by("version desc")
                .first()
            )

            if previous_version:
                for old_req in previous_version.software_requirements:
                    new_req = JobTypeSoftwareRequirement()
                    new_req.jobtype_version = jobtype_version
                    new_req.software_id = old_req.software_id
                    new_req.min_version_id = old_req.min_version_id
                    new_req.max_version_id = old_req.max_version_id
                    db.session.add(new_req)

        if g.json:
            return (jsonify(error="Unexpected keys in input: %s" % g.json.keys()), BAD_REQUEST)

        db.session.add_all([jobtype, jobtype_version])
        db.session.commit()
        jobtype_data = jobtype_version.to_dict(unpack_relationships=["software_requirements"])
        jobtype_data.update(jobtype.to_dict(unpack_relationships=False))
        del jobtype_data["jobtype_id"]
        logger.info("%s jobtype %s in put: %r", "created" if new else "updated", jobtype.name, jobtype_data)

        return jsonify(jobtype_data), CREATED
Beispiel #19
0
 def produce_jobtype(self):
     rnd_text = lambda: hexlify(urandom(4)).decode("utf-8")
     jobtype = JobType(name=rnd_text(), description=rnd_text())
     return jobtype
Beispiel #20
0
 def test_validate_mode(self):
     jobtype = JobType()
     with self.assertRaises(ValueError):
         jobtype.mode = -1
Beispiel #21
0
def create_jobtype():
    if request.method == "GET":
        return render_template("pyfarm/user_interface/jobtype_create.html",
                               jobtypes=JobType.query,
                               software_items=Software.query)
    else:
        with db.session.no_autoflush:
            jobtype = JobType()
            jobtype.name = request.form["name"]
            jobtype.description = request.form["description"]
            jobtype_version = JobTypeVersion()
            jobtype_version.jobtype = jobtype
            jobtype_version.version = 1
            jobtype_version.max_batch = request.form["max_batch"].strip() or\
                sql.null()
            jobtype_version.batch_contiguous =\
                ("batch_contiguous" in request.form and
                 request.form["batch_contiguous"] == "true")
            jobtype_version.no_automatic_start_time =\
                ("no_automatic_start_time" in request.form and
                 request.form["no_automatic_start_time"] == "true")
            jobtype_version.classname = request.form["classname"]
            jobtype_version.code = request.form["code"]

            requirements = zip(request.form.getlist("software"),
                               request.form.getlist("min_version"),
                               request.form.getlist("min_version"))

            for requirement_tuple in requirements:
                software = Software.query.filter_by(
                    id=int(requirement_tuple[0])).first()
                if not software:
                    return (render_template("pyfarm/error.html",
                                            error="Software %s not found" %
                                            requirement_tuple[0]), NOT_FOUND)
                requirement = JobTypeSoftwareRequirement()
                requirement.software = software
                requirement.jobtype_version = jobtype_version

                if requirement_tuple[1] != "":
                    minimum_version = SoftwareVersion.query.filter_by(
                        id=int(requirement_tuple[1])).first()
                    if not minimum_version:
                        return (render_template(
                            "pyfarm/error.html",
                            error="Software version %s not "
                            "found" % requirement_tuple[1]), NOT_FOUND)
                    if minimum_version.software != software:
                        return (render_template(
                            "pyfarm/error.html",
                            error="Software version %s "
                            "does not belong to software %s" %
                            (minimum_version.version, software.software)),
                                BAD_REQUEST)
                    requirement.min_version = minimum_version

                if requirement_tuple[2] != "":
                    maximum_version = SoftwareVersion.query.filter_by(
                        id=int(requirement_tuple[2])).first()
                    if not maximum_version:
                        return (render_template(
                            "pyfarm/error.html",
                            error="Software version %s not "
                            "found" % requirement_tuple[2]), NOT_FOUND)
                    if maximum_version.software != software:
                        return (render_template(
                            "pyfarm/error.html",
                            error="Software version %s "
                            "does not belong to software %s" %
                            (maximum_version.version, software.software)),
                                BAD_REQUEST)
                    requirement.max_version = maximum_version

                db.session.add(requirement)

            db.session.add(jobtype)
            db.session.add(jobtype_version)
            db.session.commit()

        flash("Jobtype %s created" % jobtype.name)

        return redirect(url_for('jobtypes_index_ui'), SEE_OTHER)
    def put(self, jobtype_name):
        """
        A ``PUT`` to this endpoint will create a new jobtype under the given URI.
        If a jobtype already exists under that URI, a new version will be created
        with the given data.

        You should only call this by id for updating an existing jobtype or if
        you have a reserved jobtype id. There is currently no way to reserve a
        jobtype id.

        .. http:put:: /api/v1/jobtypes/[<str:name>|<int:id>] HTTP/1.1

            **Request**

            .. sourcecode:: http

                PUT /api/v1/jobtypes/TestJobType HTTP/1.1
                Accept: application/json

                {
                    "name": "TestJobType",
                    "description": "Jobtype for testing inserts and queries",
                    "code": "\\nfrom pyfarm.jobtypes.core.jobtype import "
                            "JobType\\n\\nclass TestJobType(JobType):\\n"
                            "    def get_command(self):\\n"
                            "        return \"/usr/bin/touch\"\\n\\n"
                            "    def get_arguments(self):\\n"
                            "           return [os.path.join("
                            "self.assignment_data[\"job\"][\"data\"][\"path\"], "
                            "\"%04d\" % self.assignment_data[\"tasks\"]"
                            "[0][\"frame\"])]\\n"
                }

            **Response**

            .. sourcecode:: http

                HTTP/1.1 201 CREATED
                Content-Type: application/json

                {
                    "batch_contiguous": true,
                    "classname": null,
                    "code": "\\nfrom pyfarm.jobtypes.core.jobtype import "
                            "JobType\\n\\nclass TestJobType(JobType):\\n"
                            "    def get_command(self):\\n"
                            "        return \"/usr/bin/touch\"\\n\\n"
                            "    def get_arguments(self):\\n"
                            "           return [os.path.join("
                            "self.assignment_data[\"job\"][\"data\"][\"path\"], "
                            "\"%04d\" % self.assignment_data[\"tasks\"]"
                            "[0][\"frame\"])]\\n",
                    "id": 1,
                    "max_batch": 1,
                    "name": "TestJobType", 
                    "description": "Jobtype for testing inserts and queries",
                    "software_requirements": []
                }

        :statuscode 201:
            a new jobtype was created

        :statuscode 400:
            there was something wrong with the request (such as
            invalid columns being included)
        """
        if isinstance(jobtype_name, STRING_TYPES):
            jobtype = JobType.query.filter(
                JobType.name == jobtype_name).first()
        else:
            jobtype = JobType.query.filter_by(id=jobtype_name).first()

        max_version = None
        new = False if jobtype else True
        if jobtype:
            logger.debug(
                "jobtype %s will get a new version with data %r on commit",
                jobtype.name, g.json)
            max_version, = db.session.query(func.max(
                JobTypeVersion.version)).filter_by(jobtype=jobtype).first()
        else:
            jobtype = JobType()

        if max_version is not None:
            version = max_version + 1
        else:
            version = 1

        try:
            jobtype.name = g.json.pop("name")
            jobtype.description = g.json.pop("description", None)
            jobtype_version = JobTypeVersion()
            jobtype_version.jobtype = jobtype
            jobtype_version.version = version
            jobtype_version.code = g.json.pop("code")
            jobtype_version.classname = g.json.pop("classname", None)
            jobtype_version.batch_contiguous = g.json.pop(
                "batch_contiguous", None)
            jobtype_version.no_automatic_start_time =\
                g.json.pop("no_automatic_start_time", None)
            if "max_batch" in g.json and g.json["max_batch"] is None:
                g.json.pop("max_batch")
                jobtype_version.max_batch = sql.null()
            else:
                jobtype_version.max_batch = g.json.pop("max_batch", None)
        except KeyError as e:
            return (jsonify(error="Missing key in input: %r" % e.args),
                    BAD_REQUEST)

        if "software_requirements" in g.json:
            try:
                for r in parse_requirements(g.json["software_requirements"]):
                    r.jobtype_version = jobtype_version
                    db.session.add(r)
            except (TypeError, ValueError) as e:
                return jsonify(error=e.args), BAD_REQUEST
            except ObjectNotFound as e:
                return jsonify(error=e.args), NOT_FOUND
            del g.json["software_requirements"]
        elif not new:
            # If the user did not specify a list of software requirements and
            # this jobtype is not new, retain the requirements from the previous
            # version
            previous_version = JobTypeVersion.query.filter(
                JobTypeVersion.jobtype == jobtype, JobTypeVersion.version !=
                version).order_by("version desc").first()

            if previous_version:
                for old_req in previous_version.software_requirements:
                    new_req = JobTypeSoftwareRequirement()
                    new_req.jobtype_version = jobtype_version
                    new_req.software_id = old_req.software_id
                    new_req.min_version_id = old_req.min_version_id
                    new_req.max_version_id = old_req.max_version_id
                    db.session.add(new_req)

        if g.json:
            return (jsonify(error="Unexpected keys in input: %s" %
                            g.json.keys()), BAD_REQUEST)

        db.session.add_all([jobtype, jobtype_version])
        db.session.commit()
        jobtype_data = jobtype_version.to_dict(
            unpack_relationships=["software_requirements"])
        jobtype_data.update(jobtype.to_dict(unpack_relationships=False))
        del jobtype_data["jobtype_id"]
        logger.info("%s jobtype %s in put: %r",
                    "created" if new else "updated", jobtype.name,
                    jobtype_data)

        return jsonify(jobtype_data), CREATED
Beispiel #23
0
    def post(self):
        """
        A ``POST`` to this endpoint will create a new jobtype.

        .. http:post:: /api/v1/jobtypes/ HTTP/1.1

            **Request**

            .. sourcecode:: http

                POST /api/v1/jobtypes/ HTTP/1.1
                Accept: application/json

                {
                    "name": "TestJobType",
                    "classname": "TestJobType",
                    "description": "Jobtype for testing inserts and queries",
                    "code": "\\nfrom pyfarm.jobtypes.core.jobtype import "
                            "JobType\\n\\nclass TestJobType(JobType):\\n"
                            "    def get_command(self):\\n"
                            "        return \"/usr/bin/touch\"\\n\\n"
                            "    def get_arguments(self):\\n"
                            "           return [os.path.join("
                            "self.assignment_data[\"job\"][\"data\"][\"path\"], "
                            "\"%04d\" % self.assignment_data[\"tasks\"]"
                            "[0][\"frame\"])]\\n"
                }

            **Response**

            .. sourcecode:: http

                HTTP/1.1 200 OK
                Content-Type: application/json

                {
                    "id": 1,
                    "batch_contiguous": true,
                    "software_requirements": [],
                    "version": 1,
                    "max_batch": 1,
                    "name": "TestJobType",
                    "classname": "TestJobType",
                    "description": "Jobtype for testing inserts and queries",
                    "code": "\\nfrom pyfarm.jobtypes.core.jobtype import "
                            "JobType\\n\\nclass TestJobType(JobType):\\n"
                            "    def get_command(self):\\n"
                            "        return \"/usr/bin/touch\"\\n\\n"
                            "    def get_arguments(self):\\n"
                            "           return [os.path.join("
                            "self.assignment_data[\"job\"][\"data\"][\"path\"], "
                            "\"%04d\" % self.assignment_data[\"tasks\"]"
                            "[0][\"frame\"])]\\n"
                }

        :statuscode 201:
            a new jobtype item was created

        :statuscode 400:
            there was something wrong with the request (such as
            invalid columns being included)

        :statuscode 409:
            a conflicting jobtype already exists
        """
        if "name" not in g.json:
            return jsonify(error="Jobtype does not specify a name"), BAD_REQUEST
        jobtype = JobType.query.filter_by(name=g.json["name"]).first()

        if jobtype:
            return (jsonify(error="Jobtype %s already exixts" % g.json["name"]), CONFLICT)

        try:
            jobtype = JobType()
            jobtype.name = g.json.pop("name")
            jobtype.description = g.json.pop("description", None)
            jobtype_version = JobTypeVersion()
            jobtype_version.jobtype = jobtype
            jobtype_version.version = 1
            jobtype_version.code = g.json.pop("code")
            jobtype_version.classname = g.json.pop("classname", None)
            jobtype_version.batch_contiguous = g.json.pop("batch_contiguous", None)
            jobtype_version.no_automatic_start_time = g.json.pop("no_automatic_start_time", None)
            if "max_batch" in g.json and g.json["max_batch"] is None:
                g.json.pop("max_batch")
                jobtype_version.max_batch = sql.null()
            else:
                jobtype_version.max_batch = g.json.pop("max_batch", None)
        except KeyError as e:
            return (jsonify(error="Missing key in input: %r" % e.args), BAD_REQUEST)

        if "software_requirements" in g.json:
            try:
                for r in parse_requirements(g.json["software_requirements"]):
                    r.jobtype_version = jobtype_version
                    db.session.add(r)
            except (TypeError, ValueError) as e:
                return jsonify(error=e.args), BAD_REQUEST
            except ObjectNotFound as e:
                return jsonify(error=e.args), NOT_FOUND
            del g.json["software_requirements"]

        if g.json:
            return (jsonify(error="Unexpected keys in input: %r" % g.json.keys()), BAD_REQUEST)

        db.session.add_all([jobtype, jobtype_version])
        db.session.commit()
        jobtype_data = jobtype_version.to_dict(unpack_relationships=False)
        jobtype_data.update(jobtype.to_dict(unpack_relationships=["software_requirements"]))
        del jobtype_data["jobtype_id"]
        logger.info("created jobtype %s: %r", jobtype.name, jobtype_data)

        return jsonify(jobtype_data), CREATED