Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BoundingBox input types cannot be serialised to submit to Slurm cluster #610

Closed
2 of 8 tasks
agstephens opened this issue May 28, 2021 · 4 comments
Closed
2 of 8 tasks

Comments

@agstephens
Copy link

Description

When sending a Bounding Box input type to the WPS server, it fails with an error:

<!-- PyWPS 4.4.0 -->
<ows:ExceptionReport xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd" version="1.0.0">
  <ows:Exception exceptionCode="SchedulerNotAvailable" locator="" >
      <ows:ExceptionText>Could not submit job: Object of type Crs is not JSON serializable</ows:ExceptionText>
  </ows:Exception>
</ows:ExceptionReport>

This seems to happen when trying to submit jobs to a Slurm cluster - so serialisation is required before submitting to Slurm, and it cannot do that.

Environment

  • operating system: CentOS7
  • Python version: Python 3.7.8
  • PyWPS version: 4.4.0
  • source/distribution
  • git clone
  • Debian
  • PyPI
  • zip/tar.gz
  • other (please specify):
  • web server
  • Apache/mod_wsgi
  • CGI
  • other (please specify): nginx

Steps to Reproduce

I am connecting from a GUI that posts the request, not sure how to reproduce.

Additional Information

I was able to fix if I make these two hacks to owslib and pywps:

owslib/ows.py
=========

    238 class BoundingBox(object):
    239     """Initialize an OWS BoundingBox construct"""
    240     def __init__(self, elem, namespace=DEFAULT_OWS_NAMESPACE):
    241         self.minx = None
    242         self.miny = None
    243         self.maxx = None
    244         self.maxy = None
    245         self.crs = None
    246         self.dimensions = 2
    247         if elem is None:
    248             return
    249         val = elem.attrib.get('crs') or elem.attrib.get('{{{}}}crs'.format(namespace))
    250         if val:
    251             try:
ADDED LINE:    252                 val = 'urn:ogc:def:crs:OGC:2:84'
    253                 self.crs = crs.Crs(val)
    254             except (AttributeError, ValueError):
    255                 LOGGER.warning('Invalid CRS %r. Expected integer' % val)

pywps/app/WPSRequest.py
==================

    444         # Using OWSlib BoundingBox
    445         from owslib.ows import BoundingBox
    446         bbox_datas = xpath_ns(input_el, './wps:Data/wps:BoundingBoxData')
    447         if bbox_datas:
    448             for bbox_data in bbox_datas:
    449                 bbox = BoundingBox(bbox_data)
    450                 LOGGER.debug("parse bbox: minx={}, miny={}, maxx={},maxy={}".format(
    451                     bbox.minx, bbox.miny, bbox.maxx, bbox.maxy))
    452                 inpt = {}
    453                 inpt['identifier'] = identifier_el.text
    454                 inpt['data'] = [bbox.minx, bbox.miny, bbox.maxx, bbox.maxy]
CHANGED LINE:    455                 inpt['crs'] = '' #bbox.crs
    456                 inpt['dimensions'] = bbox.dimensions
    457                 the_inputs[identifier].append(inpt)
    458     return the_inputs

I don't really know what these hacked lines do but it gets things working.

I'm happy to provide more info and test when I have more time.

@geotom
Copy link
Contributor

geotom commented Mar 21, 2022

I have the same problem now: First I had a general issue with getting the BBOX parameter work, but this was to my own mistake. But now I have the same problem with the CRS not being serializable.

It happens very randomly: I can submit a job with the following input:

<wps:Input>
    <ows:Identifier>area_of_interest</ows:Identifier>
    <wps:Data>
        <wps:BoundingBoxData crs="epsg:4326" dimensions="2">
            <ows:LowerCorner>-90.0 -45.0</ows:LowerCorner>
            <ows:UpperCorner>90.0 45.0</ows:UpperCorner>
        </wps:BoundingBoxData>
    </wps:Data>
</wps:Input>

It gets accepted and runs. After a few more executions I suddenly get this answer:

<?xml version="1.0" encoding="UTF-8"?>
<!-- PyWPS 4.5.1 -->
<ows:ExceptionReport xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd" version="1.0.0">
    <ows:Exception exceptionCode="NoApplicableCode" locator="" >
        <ows:ExceptionText>No applicable error code, please check error log.</ows:ExceptionText>
    </ows:Exception>
</ows:ExceptionReport>

and the log file tells me:

2022-03-21 08:57:37,137] [ERROR] file=/usr/local/lib/python3.8/dist-packages/pywps/exceptions.py line=48 module=exceptions function=__init__ Exception: code: 500, description: No applicable error code, please check error log., locator:
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/pywps/app/Service.py", line 314, in call
    raise e
  File "/usr/local/lib/python3.8/dist-packages/pywps/app/Service.py", line 304, in call
    response = self.execute(
  File "/usr/local/lib/python3.8/dist-packages/pywps/app/Service.py", line 82, in execute
    return self._parse_and_execute(process, wps_request, uuid)
  File "/usr/local/lib/python3.8/dist-packages/pywps/app/Service.py", line 145, in _parse_and_execute
    wps_response = process.execute(wps_request, uuid)
  File "/usr/local/lib/python3.8/dist-packages/pywps/app/Process.py", line 149, in execute
    wps_response = self._execute_process(self.async_, wps_request, wps_response)
  File "/usr/local/lib/python3.8/dist-packages/pywps/app/Process.py", line 215, in _execute_process
    dblog.store_process(self.uuid, wps_request)
  File "/usr/local/lib/python3.8/dist-packages/pywps/dblog.py", line 192, in store_process
    request_json = request.json
  File "/usr/local/lib/python3.8/dist-packages/pywps/app/WPSRequest.py", line 461, in json
    return json.dumps(obj, allow_nan=False, cls=ExtendedJSONEncoder)
  File "/usr/lib/python3.8/json/__init__.py", line 234, in dumps
    return cls(
  File "/usr/lib/python3.8/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.8/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/usr/local/lib/python3.8/dist-packages/pywps/app/WPSRequest.py", line 442, in default
    encoded_object = json.JSONEncoder.default(self, obj)
  File "/usr/lib/python3.8/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '

To make it execute again or at least not get an error is to remove the CRS from the BBox input like this:

<wps:Input>
    <ows:Identifier>area_of_interest</ows:Identifier>
    <wps:Data>
        <wps:BoundingBoxData dimensions="2">
            <ows:LowerCorner>-90.0 -45.0</ows:LowerCorner>
            <ows:UpperCorner>90.0 45.0</ows:UpperCorner>
        </wps:BoundingBoxData>
    </wps:Data>
</wps:Input>

I am calling the service asynchronously and have pyWPS integrated into a flask app that is run via gunicorn and exposed via nginx. The same as described in the Howtos for production system. I suspect it has to do if jobs are immediately executed by a worker or put into a local queue. It is all very sporadic and my feeling is that increasing the number of workers helped, but the whole pyWPS interface degrades over a time

@geotom
Copy link
Contributor

geotom commented Mar 21, 2022

Could it be a problem with the BBox input serialisation if it needs to be scheduled via a queue?

@geotom
Copy link
Contributor

geotom commented Mar 22, 2022

My further investigations
The object that is not JSON encodable is urn:ogc:def:crs:EPSG::4326.

It fails at: /pywps/app/WPSRequest.py", line 444, in default

cehbrecht pushed a commit that referenced this issue Mar 30, 2022
* Fixed the JSON encoding of the CRS type which crashed when the execution request was serialized

* Fixed the JSON encoding of the CRS type by making sure the CRS is always set as string when parsing input
Also added tests

* Changed converting the string conversion of the crs input to calling the getcodeurn() method directly

* Now setting bbox CRS handles None values properly
@cehbrecht
Copy link
Collaborator

fixed by PR #650

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants