Example #1
0
    def patch(self, job_id):
        try:
            """Update a job in the job database"""
            # TODO: Implement user specific database access
            job = request.get_json()
            if job_id in self.job_db:

                if "process" not in job:
                    return ErrorSchema(
                        id=uuid4(),
                        message="A process is required in the job request"
                    ).as_response(http_status=400)

                job_info = check_job(job=job, job_id=job_id)
                self.job_db[job_id] = job_info
                return make_response(job_id, 204)
            else:
                return ErrorSchema(
                    id="123456678",
                    code=404,
                    message=f"job with id {job_id} not found in database."
                ).as_response(http_status=404)
        except Exception:

            e_type, e_value, e_tb = sys.exc_info()
            traceback_model = dict(message=str(e_value),
                                   traceback=traceback.format_tb(e_tb),
                                   type=str(e_type))
            return ErrorSchema(
                id="1234567890", code=2,
                message=str(traceback_model)).as_response(http_status=400)
    def delete(self, job_id):
        """Cancel a running job

        https://open-eo.github.io/openeo-api/v/0.3.0/apireference/#tag/Job-Management/paths/~1jobs~1{job_id}~1results/delete
        """

        if job_id in self.job_db:

            # Check for the actinia id to get the latest actinia job
            # information
            if job_id in self.actinia_job_db:
                actinia_id = self.actinia_job_db[job_id]
                code, job_info = self.iface.delete_resource(
                    resource_id=actinia_id)
                del self.actinia_job_db[job_id]

            job: JobInformation = self.job_db[job_id]
            job.status = "cancelled"
            job.updated = str(datetime.now().isoformat())

            self.job_db[job_id] = job

            return make_response("The job has been successfully cancelled",
                                 204)
        else:
            return ErrorSchema(
                id="123456678",
                code=404,
                message=f"job with id {job_id} not found in database."
            ).as_response(http_status=404)
Example #3
0
    def get(self, job_id):
        """Return information about a single job

        https://api.openeo.org/#operation/debug-job
        """

        if job_id in self.job_db:
            job: JobInformation = self.job_db[job_id]
            job_logs = {'logs': [], 'links': []}

            # Check for the actinia id to get the latest actinia job
            # information
            if job_id in self.actinia_job_db:
                actinia_id = self.actinia_job_db[job_id]
                code, job_info = self.iface.resource_info(
                    resource_id=actinia_id)

                if code == 200:
                    # Add the actinia information to the openeo job
                    if job.additional_info != job_info:
                        job.additional_info = job_info
                        job.updated = job_info["datetime"]
                        if job_info["status"] == "finished":
                            job.status = "finished"
                        if job_info["status"] == "error":
                            job.status = "error"
                        if job_info["status"] == "accepted":
                            job.status = "queued"
                        if job_info["status"] == "terminated":
                            job.status = "canceled"
                        if job_info["status"] == "running":
                            job.status = "running"

                        # Store the updated job in the database
                        self.job_db[job_id] = job
                else:
                    if job.additional_info != job_info:
                        job.additional_info = job_info
                        self.job_db[job_id] = job

                links = []
                if (job.additional_info['urls'] and
                        "resources" in job.additional_info['urls']):
                    resource_links = job.additional_info['urls']['resources']

                    for link in resource_links:
                        eo_link = EoLink(href=link)
                        links.append(eo_link)

                job_logs['logs'] = job
                job_logs['links'] = links

            return make_response(jsonify(job_logs), 200)
        else:
            return ErrorSchema(
                id="123456678",
                code=404,
                message=f"job with id {job_id} not found in database.").as_response(
                http_status=404)
Example #4
0
    def post(self):
        """Run the job in an ephemeral mapset

        :return:
        """

        try:
            # Empty the process location
            ActiniaInterface.PROCESS_LOCATION = {}
            process_graph = request.get_json()

            g = Graph(graph_description=process_graph)
            result_name, process_list = g.to_actinia_process_list()

            if len(ActiniaInterface.PROCESS_LOCATION) == 0 or len(
                    ActiniaInterface.PROCESS_LOCATION) > 1:
                msg = "Processes can only be defined for a single location!"
                status = 400
                es = ErrorSchema(id=str(datetime.now().isoformat()),
                                 code=status,
                                 message=str(msg))
                return make_response(es.to_json(), status)

            location = ActiniaInterface.PROCESS_LOCATION.keys()
            location = list(location)[0]

            process_chain = dict(list=process_list, version="1")

            status, response = self.iface.sync_ephemeral_processing_validation(
                location=location, process_chain=process_chain)

            if status == 200:
                errors = {"errors": []}
                return make_response(errors, 200)
            else:
                return ErrorSchema(
                    id=str(datetime.now().isoformat()),
                    code=status,
                    message=str(response)).as_response(http_status=status)

        except Exception as e:
            return ErrorSchema(id=str(datetime.now().isoformat()),
                               code=400,
                               message=str(e)).as_response(http_status=400)
Example #5
0
    def post(self, job_id):
        """Start a processing job in the actinia backend

        https://open-eo.github.io/openeo-api/v/0.3.0/apireference/#tag/Job-Management/paths/~1jobs~1{job_id}~1results/post
        """
        try:
            if job_id in self.job_db:
                job: JobInformation = self.job_db[job_id]

                status, response = self.send_actinia_processing_request(
                    job=job)
                if "resource_id" not in response:
                    return make_response(
                        ErrorSchema(
                            id="12345678",
                            code=status,
                            message=f"Internal server error: {str(response)}").
                        to_json(), status)
                self.actinia_job_db[job_id] = response["resource_id"]

                job.additional_info = response
                job.status = "queued"
                job.updated = str(datetime.now().isoformat())

                self.job_db[job_id] = job

                return make_response(
                    "The creation of the resource has been queued successfully.",
                    202)
            else:
                return ErrorSchema(
                    id="123456678",
                    code=404,
                    message=f"job with id {job_id} not found in database."
                ).as_response(http_status=404)
        except Exception:

            e_type, e_value, e_tb = sys.exc_info()
            traceback_model = dict(message=str(e_value),
                                   traceback=traceback.format_tb(e_tb),
                                   type=str(e_type))
            return ErrorSchema(
                id="1234567890", code=2,
                message=str(traceback_model)).as_response(http_status=400)
    def delete(self, id):
        """Remove a single process graph from the database"""

        if id in self.graph_db:

            del self.graph_db[id]
            return make_response(
                f"Process graph {id} have been successfully deleted", 204)
        else:
            return ErrorSchema(
                id=str(uuid4()),
                code=400,
                message=f"Process graph id {id} not found").as_response(400)
    def __init__(self,
                 process_graph: ProcessGraphNode,
                 url: str,
                 type: str,
                 parameters: Dict,
                 attributes: Dict,
                 submitted: str = None,
                 title: str = None,
                 description: str = None,
                 enabled: bool = True,
                 plan: str = None,
                 costs: float = None,
                 budget: float = None):

        self.title = title
        self.description = description
        self.process_graph = process_graph
        self.url = url
        self.type = type
        self.enabled = enabled
        self.parameters = parameters
        self.attributes = attributes
        self.submitted = submitted
        self.plan = plan
        self.costs = costs
        self.budget = budget

        # Test id in pattern
        pattern = r"^[A-Za-z0-9_\-\.~]+$"
        x = re.search(pattern, id)
        if not x:
            es = ErrorSchema(
                id=str(datetime.now()),
                code=400,
                message="The id MUST match the following pattern: %s" %
                pattern)
            return make_response(es.to_json(), 400)
        self.id = id
    def get(self, id):
        """Return all jobs in the job database"""
        # TODO: Implement user specific database access

        if id in self.graph_db:

            graph = self.graph_db[id]
            graph["id"] = id
            return make_response(jsonify(graph), 200)
        else:
            return ErrorSchema(
                id=str(uuid4()),
                code=400,
                message=f"Process graph id {id} not found").as_response(400)
Example #9
0
    def delete(self, job_id):
        """Delete a single job

        https://open-eo.github.io/openeo-api/v/0.3.0/apireference/#tag/Job-Management/paths/~1jobs~1{job_id}/delete
        """

        if job_id in self.job_db:
            del self.job_db[job_id]
            return make_response("The job has been successfully deleted", 204)
        else:
            return ErrorSchema(
                id="123456678",
                code=404,
                message=f"job with id {job_id} not found in database."
            ).as_response(http_status=404)
Example #10
0
    def get(self, job_id):
        """Return information about a single job

        https://api.openeo.org/#operation/describe-job
        """

        if job_id in self.job_db:
            job: JobInformation = self.job_db[job_id]
            return job.as_response(http_status=200)
            # return make_response(job.to_json(), 200)
        else:
            return ErrorSchema(
                id="123456678",
                code=404,
                message=f"job with id {job_id} not found in database."
            ).as_response(http_status=404)
    def put(self, id):
        try:
            """Store and replace custom process-graphs"""
            # TODO: Implement user specific database access

            process_graph = request.get_json()
            self.graph_db[id] = process_graph
            return make_response(id, 200)
        except Exception:

            e_type, e_value, e_tb = sys.exc_info()
            traceback_model = dict(message=str(e_value),
                                   traceback=traceback.format_tb(e_tb),
                                   type=str(e_type))
            return ErrorSchema(id="1234567890",
                               code=2,
                               message=str(traceback_model)).as_response(400)
Example #12
0
    def get(self, job_id):
        """Return information about a single job

        https://api.openeo.org/#operation/estimate-job
        """

        # TODO
        # at least one of costs, duration, size must be specified
        # optional: downloads_included, expires
        if job_id in self.job_db:
            estimate = {"costs": 0}

            return make_response(jsonify(estimate), 200)
        else:
            return ErrorSchema(
                id="123456678",
                code=404,
                message=f"job with id {job_id} not found in database."
            ).as_response(http_status=404)
    def post(self):
        try:
            """Store a process graph in the graph database"""
            # TODO: Implement user specific database access

            process_graph_id = f"user-graph-{str(uuid4())}"

            process_graph = request.get_json()
            self.graph_db[process_graph_id] = process_graph

            return make_response(process_graph_id, 201)
        except Exception:

            e_type, e_value, e_tb = sys.exc_info()
            traceback_model = dict(message=str(e_value),
                                   traceback=traceback.format_tb(e_tb),
                                   type=str(e_type))
            return ErrorSchema(
                id="1234567890", code=2,
                message=str(traceback_model)).as_response(http_status=400)
def authenticate():
    resp = ErrorSchema(code=401,
                       message="Authorization failed").as_response(401)
    resp.headers['WWW-Authenticate'] = 'Bearer realm="Main"'
    return resp
 def get(self):
     return ErrorSchema(
         id="1234567890",
         code=204,
         message="OpenID Connect is not available").as_response(204)
Example #16
0
 def delete(self, path):
     # not possible because upload is not supported
     return ErrorSchema(id="1234567890",
                        code=404,
                        message="File <%s> not found" %
                        path).as_response(404)
Example #17
0
 def put(self, path):
     # upload is not allowed
     return ErrorSchema(
         id="1234567890", code=403,
         message="File upload is not supported").as_response(403)
Example #18
0
    def post(self):
        """Run the job in an ephemeral mapset synchronously for 10 seconds.
        After 10 seconds the running job
        will be killed on the actinia server and the response will be an
        termination report.
        """

        try:
            # Empty the process location
            ActiniaInterface.PROCESS_LOCATION = {}
            request_doc = request.get_json()
            g = Graph(graph_description=request_doc)
            result_name, process_list = g.to_actinia_process_list()

            if len(ActiniaInterface.PROCESS_LOCATION) == 0 or len(
                    ActiniaInterface.PROCESS_LOCATION) > 1:
                descr = "Processes can only be defined for a single location!"
                return make_response(jsonify({"description": descr}, 400))

            location = ActiniaInterface.PROCESS_LOCATION.keys()
            location = list(location)[0]

            if location == "stac":
                location = "latlong_wgs84"

            process_chain = dict(list=process_list, version="1")

            status, response = self.iface.async_ephemeral_processing_export(
                location=location, process_chain=process_chain)
            status, response = self.wait_until_finished(response=response,
                                                        max_time=1000)

            if status == 200:
                result_url = response["urls"]["resources"]
                if len(result_url) == 1:
                    # attempt to return an image
                    result_data = self.iface.get_resource(result_url[0])
                    if result_url[0][-4:] in ("tiff", ".tif"):
                        mimetype = "image/tiff"
                    else:
                        mimetype = "unknown"

                    return Response(result_data.content,
                                    mimetype=mimetype,
                                    direct_passthrough=True)

                return make_response(
                    jsonify({
                        "job_id": response["resource_id"],
                        "job_info": response
                    }), status)
            else:
                return ErrorSchema(
                    id="1234567890",
                    code=404,
                    message=str(response),
                    links=response["urls"]["status"]).as_response(status)
        except Exception:

            e_type, e_value, e_tb = sys.exc_info()
            traceback_model = dict(message=str(e_value),
                                   traceback=traceback.format_tb(e_tb),
                                   type=str(e_type))
            return ErrorSchema(id="1234567890",
                               code=404,
                               message=str(traceback_model)).as_response(404)
Example #19
0
    def get(self, job_id):
        """Return information about a single job

        https://open-eo.github.io/openeo-api/v/0.3.0/apireference/#tag/Job-Management/paths/~1jobs~1{job_id}/get
        """

        if job_id in self.job_db:
            job: JobInformation = self.job_db[job_id]

            job.stac_version = CAPABILITIES['stac_version']
            job.type = "Feature"
            job.geometry = "json:null"
            job.properties = dict()
            job.properties['datetime'] = None
            job.assets = dict()
            job.links = []

            # Check for the actinia id to get the latest actinia job
            # information
            if job_id in self.actinia_job_db:
                actinia_id = self.actinia_job_db[job_id]
                code, job_info = self.iface.resource_info(
                    resource_id=actinia_id)

                if code == 200:
                    # Add the actinia information to the openeo job
                    if job.additional_info != job_info:
                        job.additional_info = job_info
                        job.updated = job_info["datetime"].replace(
                            " ", "T").replace("'", "").replace('"', '')
                        if job_info["status"] == "finished":
                            job.status = "finished"
                        if job_info["status"] == "error":
                            job.status = "error"
                        if job_info["status"] == "accepted":
                            job.status = "queued"
                        if job_info["status"] == "terminated":
                            job.status = "canceled"
                        if job_info["status"] == "running":
                            job.status = "running"

                        # Store the updated job in the database
                        self.job_db[job_id] = job
                else:
                    if job.additional_info != job_info:
                        job.additional_info = job_info
                        self.job_db[job_id] = job

                if (job.additional_info['urls']
                        and "resources" in job.additional_info['urls']):
                    resource_links = job.additional_info['urls']['resources']

                    if job.links is None:
                        job.links = []

                    for link in resource_links:
                        eo_link = EoLink(href=link)
                        job.links.append(eo_link)

            return job.as_response(http_status=200)
        else:
            return ErrorSchema(
                id="123456678",
                code=404,
                message=f"job with id {job_id} not found in database."
            ).as_response(http_status=404)