install_python.rst 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204
  1. .. _extensions_wps_remote_install_python:
  2. Deployment And Setup Of The XMPP Python Wrappers
  3. ================================================
  4. Remote WPS Python Wrapper Framework
  5. +++++++++++++++++++++++++++++++++++
  6. The Remote WPS Python framework source code is available on a public GitHub Repository of GeoSolutions S.A.S.
  7. Users can install the "wps-remote" Python package by using the PyPi distribution ::
  8. pip install wps-remote==2.11.0
  9. The source code repository is available at the following address:
  10. https://github.com/geoserver/wps-remote
  11. The source code is available on the main development (**main**) branch.
  12. How The System Works
  13. ++++++++++++++++++++
  14. This setup will configure the Remote WPS Python Wrapper to launch a Python executable called ``test.py`` that performs a ``gdal_contour`` on a GeoTIFF DEM.
  15. The ``test.py`` executable takes in input just two parameters:
  16. * ``-i``; "--interval", nargs='?', default="10", help="Elevation interval between contours."
  17. * ``-w``; "--workdir", nargs='?', default="", help="Remote process sandbox working directory."
  18. The paths of the command line and GeoTIFF to process (provided with the source code as sample data), are hard-coded into the Python code and must be changed accordingly to the system settings as explained later in the docs:
  19. * ``gdalContour = r'/usr/bin/gdal_contour'``
  20. * ``src = r'/share/xmpp_data/resource_dir/srtm_39_04/srtm_39_04_c.tif'``
  21. The assumptions are that during the execution, the algorithms send logging and progress info to the standard output in a form similar to the following one:
  22. .. code-block:: bash
  23. 2016-02-15 15:18:03,594 - main.create_logger - [INFO] ProgressInfo:100%
  24. The log format has been configured through the ``logger_test.properties`` file:
  25. .. code-block:: bash
  26. [loggers]
  27. keys=root
  28. [handlers]
  29. keys=consoleHandler
  30. [formatters]
  31. keys=simpleFormatter
  32. [logger_root]
  33. level=DEBUG
  34. handlers=consoleHandler
  35. [handler_consoleHandler]
  36. class=StreamHandler
  37. level=DEBUG
  38. formatter=simpleFormatter
  39. args=(sys.stdout,)
  40. [formatter_simpleFormatter]
  41. format=%(asctime)s - %(name)s - [%(levelname)s] %(message)s
  42. datefmt=
  43. The role of the Remote WPS Python wrapper is to take care of the communication between GeoServer WPS and the ``test.py`` executable.
  44. The Python wrapper must be configured by specifying the number and type of input and output parameters of the executable, other than the connection parameter of the remote XMPP Server.
  45. The Python wrapper knows how to invoke the executables from the command line and how to parse and interpret the logging information thanks to some properties files containing a set of regular expressions which will be presented in details further in this document.
  46. There must be a running instance of the Python wrapper for each executable, every one with its own specific configuration and XMPP user.
  47. The wrapper instances will connect automatically to the XMPP Server and GeoServer will send an **"invite"** message as soon it recognizes a new authenticated user appearing on the XMPP communication channels.
  48. In order to register the WPS Process into the GeoServer through the Remote Process Factory, the Python wrapper must reply to the invitation with a **"register"** message containing all the details about the I/O params of the executable.
  49. All those passages are managed automatically and transparently to the users by the Remote WPS Python framework.
  50. Every time a user issues a new GeoServer WPS execute request, the Python wrapper starts a new thread calling the executables with the input parameters coming from GeoServer itself.
  51. The two running instances are connected through a unique “process execution ID” generated by GeoServer Remote Process Factory.
  52. From now on, the Python wrapper thread follows the entire execution and takes care of sending feedbacks and logging information to the GeoServer Remote Process Factory, which are translated and forwarded to the GeoServer WPS Execution Manager.
  53. From the outside the users will experience a standard execution of an OGC WPS compliant process.
  54. Summary Of The Configuration Steps
  55. ++++++++++++++++++++++++++++++++++
  56. Connecting a new executable instance to GeoServer through the Python wrapper requires few configuration steps summarized here below:
  57. 1. **Clone a structure of** ``.properties`` **files containing:**
  58. - The connection parameter to the XMPP Server
  59. - The descriptor of the executable command line
  60. - The descriptor of the process I/O parameters
  61. - The logging informations
  62. 2. **Update the** ``remote.config`` **file with the correct XMPP Server information:**
  63. - Provide remote host and port parameters
  64. - Provide domain and XMPP communication secured channels details
  65. - Provide pointers to the shared folder
  66. 3. **Update the** ``logger.properties`` **file with the full path to the** ``service.log`` **file.**
  67. 4. **Update the** ``service.config`` **file with the executables parameters:**
  68. - The service name and the namespace
  69. .. note::
  70. there must exist an user on the XMPP Server named as ``namespace.serviceName`` and a communication channel with the same identified of the service namespace.
  71. e.g.:
  72. - service = gdalContour
  73. - namespace = default
  74. means that on the XMPP Server we are looking for a communication channel named ``default`` and we will try to connect with the username ``default.gdalContour``.
  75. Both of them must be defined before running the Python wrapper daemon.
  76. - The description of the service and the full path to the main executable
  77. - Other secondary parameters like the local output folder (where to store temporary results of the execution) and the max running time
  78. - The description of the Inputs and the actions to be taken
  79. - The description of the Outputs and the actions to be taken
  80. - The description of the logging information and the actions to be taken
  81. Installation and Configuration Steps
  82. ====================================
  83. Basic Environment Preparation
  84. +++++++++++++++++++++++++++++
  85. The following commands will prepare a MS Windows 7+, Windows 2008+ Server ISO machine for the deployment of:
  86. 1. Remote WPS Python wrapper
  87. 2. Sample configuration and testing of a sample executable ``test.py`` running the ``gdal_contour`` on a GeoTIFF DEM
  88. **Preparation of the system: standard and basic OS packages**
  89. *Python*
  90. The system requires Python 2.7.9+ with few packages in order to work correctly. The installation of Python on a Windows system is quite fast
  91. .. code-block:: bash
  92. # as administrator
  93. #.1 Download the Python 2.7.9 installation package from the browser, choosing the best suitable distribution accordingly to the OS
  94. https://www.python.org/downloads/release/python-279/
  95. #.2 Define the following System Environment Variables
  96. PATH=%PATH%;C:\Python27;C:\Python27\Scripts
  97. PYTHONPATH=.\;C:\Python27;C:\work\RemoteWPS
  98. *Other Mandatory Python Packages*
  99. .. code-block:: bash
  100. # as administrator
  101. # From a Command Line prompt
  102. $> pip install wps-remote==2.11.0
  103. **Configure the RemoteWPS Environment**
  104. *NFS Shared Folder*
  105. Link the shared folder to the ``C:/share`` through the NFS protocol. This is possible simply by turning on the NFS Services of the MS Windows functionalities and creating a client NFS connection to the NFS server.
  106. .. warning:: "Services for NFS" have been removed on Windows 10. They are available only on Windows 10 Enterprise edition. For older Windows versions you can use the following procedure in order to enable NFS Client
  107. **Installing the client**
  108. 1. Go to Control Panel → Programs → Programs and Features
  109. 2. Select: Turn Windows features on or off" from the left hand navigation.
  110. 3. Scroll down to "Services for NFS" and click the "plus" on the left
  111. 4. Check "Client for NFS"
  112. 5. Select "Ok"
  113. 6. Windows should install the client. Once the client package is install you will have the "mount" command available.
  114. **Mounting the export**
  115. This assumes the following:
  116. * You know and can ping the hostname of the machine with the NFS exports
  117. * The name of the exported filesystem ( eg. /export, /home/users, /some/cool/file/path )
  118. * The file systems are properly exported and accessible
  119. - Open a command prompt. ( ``Win`` + ``R``, enter "cmd" and press OK )
  120. - Type:
  121. ``mount \\{machinename}\{filesystem} {driveletter}``
  122. Examples::
  123. mount \\filehost\home\users H:
  124. mount \\server1234\long\term\file\storage S:
  125. mount \\nas324\exports E:
  126. .. note:: It is important that the shared folder structure is fully replicated on the Windows machine and the folder writable by the Windows processes.
  127. .. code-block:: bash
  128. | /share
  129. |
  130. |-- xmpp_data
  131. |
  132. |-- -- output
  133. |
  134. |-- -- resource_dir
  135. First Deploy Of The RemoteWPS Python Framework
  136. ++++++++++++++++++++++++++++++++++++++++++++++
  137. The wps-remote WHL archive contains a folder with a sample configuration ::
  138. xmpp_data
  139. Extract this folder and proceed with the next steps.
  140. The files can also be downloaded from the GitHub source repository.
  141. To clone the RemoteWPS Python Framework into a working folder, e.g.:
  142. .. code-block:: bash
  143. $> cd C:\work
  144. $> git clone https://github.com/geoserver/wps-remote RemoteWPS
  145. **Setting Up The** ``remote.config``
  146. .. code-block:: bash
  147. # Edit the file xmpp_data/configs/remote.config
  148. [DEFAULT]
  149. bus_class_name = xmppBus.XMPPBus
  150. port = 5223
  151. address = 127.0.0.1
  152. domain = geoserver.org
  153. # . Those are the connection parameters to the XMPP Server.
  154. # . The user must exists on the Server and its name must be
  155. # . equal to the service name.
  156. user = default.GdalContour
  157. password = R3m0T3wP5
  158. mucService = conference.%(domain)s
  159. mucServicePassword = admin
  160. resource_file_dir = /share/xmpp_data/resource_dir
  161. # . Configure this option (along with 'backup_on_wps_execution_shared_dir'
  162. # . on single outputs of 'service.config') in order to make a copy
  163. # . of the results into a shared folder before sending messages to XMPP
  164. # . WARNING: this option takes precedence on "UPLOADER" option
  165. # wps_execution_shared_dir = /share/xmpp_data/share
  166. # . This section is used to configure the uploader class and connection
  167. # . parameters.
  168. # . This is necessary in order to let the 'upload_data' option work on
  169. # . single outputs of 'service.config'
  170. [UPLOADER]
  171. # There are different implementations of the FTP Uploader available right now:
  172. # . Plain standard FTP Protocol (based on ftplib)
  173. # ftpUpload.FtpUpload
  174. # . FTP over TLS (FTPS) Protocol (based on ftplib)
  175. # ftpsUpload.FtpsUpload
  176. # . S-FTP Protocol (based on paramiko Python lib)
  177. # sftpUpload.SFtpUpload
  178. uploader_class_name = ftpUpload.FtpUpload
  179. uploader_host = ftp.<your_host_here>:<your_port_here_default_21>
  180. uploader_username = <ftp_username>
  181. uploader_password = <ftp_password_encrypted>
  182. # . "encryptor" you can use encrypted passwords with a private/public key couple
  183. #
  184. # . To generate a new private key use the following command:
  185. # openssl genrsa -out myTestKey.pem -passout pass:"f00bar" -des3 2048
  186. #
  187. # . To generate a new public key use the following command:
  188. # openssl rsa -pubout -in myTestKey.pem -passin pass:"f00bar" -out myTestKey.pub
  189. #
  190. # . To encrypt your password use the following utility
  191. # python encrypt.py password path/to/rsakey.pub passphrase
  192. #
  193. # . To double check the password is correct use the following utility
  194. # python decrypt.py password path/to/rsakey.pem passphrase
  195. uploader_private_rsa_key = /share/xmpp_data/ssl/myTestKey.pem
  196. uploader_passphrase = f00bar
  197. The requisites for this configuration to work properly are:
  198. 1. Make sure the ``<XMPP_server_ip_address>`` is reachable and the port **5223** is allowed by the Firewall
  199. 2. Make sure the ``default.GdalContour`` user exists into the XMPP Server and that the password is correct
  200. .. figure:: images/python001.jpg
  201. :align: center
  202. 3. The MUC Service and the MUC Service Password are correct
  203. 4. The resource dir and the shared folder exists and are writable
  204. **Setting Up The** ``logger.properties``
  205. .. code-block:: bash
  206. # Edit the file xmpp_data/configs/logger.properties
  207. [loggers]
  208. keys=root
  209. [handlers]
  210. keys=consoleHandler,file
  211. [formatters]
  212. keys=simpleFormatter,consoleFormatter
  213. [logger_root]
  214. level=DEBUG
  215. handlers=file, consoleHandler
  216. [handler_consoleHandler]
  217. class=StreamHandler
  218. level=DEBUG
  219. formatter=consoleFormatter
  220. args=(sys.stdout,)
  221. filter=
  222. [handler_file]
  223. class=handlers.TimedRotatingFileHandler
  224. interval=midnight
  225. backupCount=5
  226. formatter=simpleFormatter
  227. level=DEBUG
  228. args=('/share/xmpp_data/service.log',)
  229. [formatter_simpleFormatter]
  230. format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
  231. datefmt=
  232. [formatter_consoleFormatter]
  233. format=%(asctime)s [%(levelname)s] %(message)s
  234. datefmt=
  235. The requisites for this configuration to work properly are:
  236. 1. Make sure the “C:/share/xmpp_data/” exists and is writable
  237. **Setting Up The** ``service.config``
  238. .. code-block:: bash
  239. # Edit the file xmpp_data/configs/myservice/service.config
  240. # This is a INI file to be read with python ConfigParser (https://docs.python.org/2/library/configparser.html)
  241. # Is possible to reference another variable in the ini file using the format %(<variable name>)s (note the 's' at the end)
  242. # ########################################### #
  243. # Default Service Params #
  244. # ########################################### #
  245. [DEFAULT]
  246. service = GdalContour
  247. namespace = default
  248. description = GDAL Contour Remote Service
  249. executable_path = /share/xmpp_data/configs/myservice/code
  250. executable_cmd = python %(executable_path)s/test.py
  251. output_dir = /share/xmpp_data/output/
  252. unique_execution_id = %(unique_exe_id)s
  253. workdir = %(output_dir)s/%(unique_execution_id)s
  254. active = True
  255. max_running_time_seconds = 300
  256. # . This option allows you to set the CPU and Memory average load scan time.
  257. # . It is espressed in 'minutes' and if disabled here it will be set by default
  258. # . to 15 minutes.
  259. load_average_scan_minutes = 1
  260. # . Use this option to completely avoid using this host (and prevent starting a new
  261. # . 'processbot') whenever one of the following process names are running.
  262. # . In other words, if one of the following processes are currently running on this machine,
  263. # . GeoServer won't send any WPS execute request until they are finished.
  264. process_blacklist = [resource consuming process name1, resource consuming process name2]
  265. # ########################################### #
  266. # Inputs and Actions Declaration #
  267. # ########################################### #
  268. [Input1]
  269. class = param
  270. name = interval
  271. title = Elevation Interval
  272. type = int
  273. description = Elevation interval between contours.
  274. min = 1
  275. max = 1
  276. default = 200
  277. [Action1]
  278. class = cmdline
  279. input_ref = interval
  280. alias = i
  281. template = -name value
  282. [Const1]
  283. class = const
  284. name = workdir
  285. type = string
  286. description = Remote process sandbox working directory
  287. value = %(workdir)s
  288. [Action2]
  289. class = cmdline
  290. input_ref = workdir
  291. alias = w
  292. template = -name value
  293. # ########################################### #
  294. # Output Parameters Declaration #
  295. # ########################################### #
  296. [Output1]
  297. name = result1
  298. type = application/zip
  299. description = WPS Resource Binary File
  300. title = SRTM
  301. filepath = %(workdir)s/contour.zip
  302. publish_as_layer = true
  303. publish_default_style = polygon
  304. publish_target_workspace = it.geosolutions
  305. publish_layer_name = contour
  306. # . Enable this option in order to perform a backup of this output
  307. # . before sending it to GeoServer.
  308. # . WARNING: This option works only along with 'wps_execution_shared_dir'
  309. # . option on 'remote.config', and takes precedence on 'upload_data'
  310. # backup_on_wps_execution_shared_dir = true
  311. # . Enable this option if you want the output to be uploaded on remote host.
  312. # . Notice that you must also configure uploader parameters on 'remote.config'
  313. # upload_data = true
  314. # . Optionally it is possible to specify a root folder if the uploader class supports it.
  315. # upload_data_root = /remote-wps/default
  316. [Output2]
  317. name = result2
  318. type = application/x-netcdf
  319. description = NetCDF Binary File
  320. title = flexpart
  321. filepath = %(output_dir)s/flexpart.nc
  322. publish_as_layer = true
  323. publish_default_style = raster
  324. publish_target_workspace = it.geosolutions
  325. publish_layer_name = flexpart
  326. # . Enable this option in order to perform a backup of this output
  327. # . before sending it to GeoServer.
  328. # . WARNING: This option works only along with 'wps_execution_shared_dir'
  329. # . option on 'remote.config', and takes precedence on 'upload_data'
  330. # backup_on_wps_execution_shared_dir = true
  331. # . Enable this option if you want the output to be uploaded on remote host.
  332. # . Notice that you must also configure uploader parameters on 'remote.config'
  333. # upload_data = true
  334. # . Optionally it is possible to specify a root folder if the uploader class supports it.
  335. # upload_data_root = /remote-wps/default
  336. [Output3]
  337. name = result3
  338. type = application/owc
  339. description = WPS OWC Json MapContext
  340. layers_to_publish = result2
  341. publish_as_layer = true
  342. publish_layer_name = owc_json_ctx
  343. publish_metadata = /share/xmpp_data/resource_dir/owc_json_ctx.json
  344. # ########################################### #
  345. # Logging Options Declaration #
  346. # ########################################### #
  347. [Logging]
  348. stdout_parser = [.*\[DEBUG\](.*), .*\[INFO\] ProgressInfo\:([-+]?[0-9]*\.?[0-9]*)\%, .*\[(INFO)\](.*), .*\[(WARN)\](.*), .*\[(ERROR)\](.*), .*\[(CRITICAL)\](.*)]
  349. stdout_action = [ignore, progress, log, log, abort, abort]
  350. The requisites for this configuration to work properly are:
  351. 1. Make sure the ``default.GdalContour`` user exists into the XMPP Server and that the password is correct
  352. 2. Make sure the ``default`` channel exists on the XMPP Server
  353. 3. Make sure the executable path and command are correct
  354. 4. Make sure the ``output_dir`` exists and is writable
  355. 5. Make sure the ``max_running_time_seconds`` have been set to a value high enough to allow the executables to complete the jobs.
  356. The GeoServer instance must also respect the WPS execution timings which must be configured accordingly. In order to do that access to the GeoServer Web Admin GUI.
  357. http://host:8080/geoserver/web/
  358. login as administrator (default credentials are admin/geoserver which should be changed anyway).
  359. From the Web Processing Service settings page
  360. .. figure:: images/python002.png
  361. :align: center
  362. .. figure:: images/python003.png
  363. :align: center
  364. The timeouts and the number of parallel executions (both async and sync) must be tuned accordingly to the execution needs.
  365. 6. Make sure the inputs have been configured correctly for the command line execution
  366. .. code-block:: bash
  367. [Input1]
  368. class = param
  369. name = interval
  370. title = Elevation Interval
  371. type = int
  372. description = Elevation interval between contours.
  373. min = 1
  374. max = 1
  375. default = 200
  376. [Action1]
  377. class = cmdline
  378. input_ref = interval
  379. alias = i
  380. template = -name value
  381. The configuration above sets an input of type ``int`` (the expected value will be interpreted as text and declared as Literal to the WPS), which is mandatory (**min = 1**) and can have a single value (**max = 1**).
  382. The ``[Action1]`` is connected to the input through the ``input_ref`` which is equal to the ``[Input1].name``.
  383. In the example above the action simply gets the input value specified by the user and forward it to the command line.
  384. The final result will be something lihe this::
  385. $> /work/RemoteWPS/xmpp_data/configs/myservice/code/test.py <input_value_here>
  386. The ``[Action1].template`` property allows to specify the name of the option if required by the executable.
  387. As an instance the following value for the ``[Action1].template``::
  388. alias = i
  389. template = -name value
  390. will result in something like this::
  391. $> /work/RemoteWPS/xmpp_data/configs/myservice/code/test.py -i <input_value>
  392. There exists other types of input and actions.
  393. As an instance it is possible to specify ``constant`` input types like the following one::
  394. [Const1]
  395. class = const
  396. name = workdir
  397. type = string
  398. description = Remote process sandbox working directory
  399. value = %(workdir)s
  400. [Action2]
  401. class = cmdline
  402. input_ref = workdir
  403. alias = w
  404. template = -name value
  405. The ``[Const1].value`` can be a constant value or a reference to the configuration file properties.
  406. In the example above we are going to pass to the command line the full path of the process workind directory, which is a unique folder created at runtime where the RemoteWPS framework stores temporary and intermediate results of the process execution.
  407. Enabling the constant input above, the resulting command line will be something like the following one::
  408. $> /work/RemoteWPS/xmpp_data/configs/myservice/code/test.py -i <input_value> -w /share/xmpp_data/output/<exec_id>
  409. .. note:: The **<exec_id>** is known at runtime only.
  410. 7. Make sure the outputs have been configured correctly for the command line execution
  411. .. code-block:: bash
  412. [Output1]
  413. name = result1
  414. type = application/zip
  415. description = WPS Resource Binary File
  416. title = SRTM
  417. filepath = %(workdir)s/contour.zip
  418. publish_as_layer = true
  419. publish_default_style = polygon
  420. publish_target_workspace = it.geosolutions
  421. publish_layer_name = contour
  422. In the example above we declare to the WPS only **one** output of type ``application/zip``.
  423. In this case the RemoteWPS framework expects to find a ``contour.zip`` file at the end of the execution into the working directory (see above).
  424. There are many kind of possible outputs which can be defined here. As an instance it is possible to define an output of type ``string`` which can read the outcome from a file and stream it out as plain text.
  425. It is also possible to define several kind of binary outputs depending on the executable outcomes.
  426. For more details please refer to the Remote WPS Python framework specific documentation at the end of this section.
  427. 8. Make sure the regular expressions of the “stdout_parser” are correct and valid accordingly to the output of the executable
  428. .. code-block:: bash
  429. [Logging]
  430. stdout_parser = [.*\[DEBUG\](.*), .*\[INFO\] ProgressInfo\:([-+]?[0-9]*\.?[0-9]*)\%, .*\[(INFO)\](.*), .*\[(WARN)\](.*), .*\[(ERROR)\](.*), .*\[(CRITICAL)\](.*)]
  431. stdout_action = [ignore, progress, log, log, log, abort]
  432. The example configuration above:
  433. - Ignores all ``STDOUT`` debug logs received from ``test.py``
  434. - Translates **as** *progress info message* any number parsed by the regex from ``STDOUT`` and sends it to GeoServer WPS.
  435. - Logs all ``STDOUT`` info, warn and error logs received from ``test.py``
  436. - Translates **as** *abort message* any keyword **CRITICAL** parsed by the regex from ``STDOUT`` and sends it to GeoServer WPS.
  437. At least **progress** and **abort** messages are mandatory in order to take track of the process execution progress and fault state.
  438. A Running Example
  439. +++++++++++++++++
  440. In the section :ref:`extensions_wps_remote_install_example` will show how to run the example and how to parse the results in GeoServer.
  441. ANNEX A: Remote WPS Python Wrapper Reference
  442. ============================================
  443. This section is meant to be a summary of the current possible options for the RemoteWPS Python Wrapper ``service.config`` configuration.
  444. Default Section
  445. +++++++++++++++
  446. .. code-block:: bash
  447. # ########################################### #
  448. # Default Service Params #
  449. # ########################################### #
  450. [DEFAULT]
  451. service = GdalContour
  452. namespace = default
  453. description = GDAL Contour Remote Service
  454. executable_path = /work/RemoteWPS/xmpp_data/configs/myservice/code
  455. executable_cmd = python %(executable_path)s/test.py
  456. output_dir = /share/xmpp_data/output/
  457. unique_execution_id = %(unique_exe_id)s
  458. workdir = %(output_dir)s/%(unique_execution_id)s
  459. sharedir = /home/myproc/repository/default
  460. active = True
  461. max_running_time_seconds = 300
  462. load_average_scan_minutes = 1
  463. process_blacklist = [resource consuming process name1, resource consuming process name2]
  464. * **service**; The name of the WPS service. On GeoServer the WPS Process will be represented as ``namespace.service``
  465. .. note:: The XMPP Server *must* have a registered user named like the fully qualified service name ``namespace.service``
  466. * **namespace**; The namespace (or prefix) of the service. Along with the *service* parameter, it represents the fully qualified name of the service.
  467. * **description**; This contains the textual description of the GeoServer WPS Process.
  468. * **executable_path**; Full path of the executable to wrap.
  469. * **executable_cmd**; Executable command.
  470. * **output_dir**; The base output folder where the Python wrapper stores logs and temporary files.
  471. * **unique_execution_id**; The unique ID generated by GeoServer and sent to the process via the *REQUEST* command message.
  472. * **workdir**; Temporary folder where to store the outcomes and log files.
  473. * **sharedir**; Shared folder where to **backup** outcomes with ``backup_on_wps_execution_shared_dir`` property equal *true*
  474. * **active**; *Boolean* which enables or disables the service.
  475. * **max_running_time_seconds**; After this time the Python Wrapper tries to shutdown the process and send a *FAILED* message to GeoServer.
  476. * **load_average_scan_minutes**; This option allows you to set the CPU and Memory average load scan time. It is espressed in 'minutes' and if disabled here it will be set by default to 15 minutes.
  477. * **process_blacklist**; Use this option to completely avoid using this host (and prevent starting a new 'processbot') whenever one of the following process names are running. In other words, if one of the following processes are currently running on this machine, GeoServer won't send any WPS execute request until they are finished.
  478. Inputs Section
  479. ++++++++++++++
  480. .. code-block:: bash
  481. # ########################################### #
  482. # Inputs and Actions Declaration #
  483. # ########################################### #
  484. [Input1]
  485. class = param
  486. name = interval
  487. title = Elevation Interval
  488. type = int
  489. description = Elevation interval between contours.
  490. min = 1
  491. max = 1
  492. default = 200
  493. [Action1]
  494. class = cmdline
  495. input_ref = interval
  496. alias = i
  497. template = -name value
  498. [Const1]
  499. class = const
  500. name = workdir
  501. type = string
  502. description = Remote process sandbox working directory
  503. value = %(workdir)s
  504. [Action2]
  505. class = cmdline
  506. input_ref = workdir
  507. alias = w
  508. template = -name value
  509. The *Inputs Section* can contain three type of objects:
  510. 1. ``[Input#]``; Descriptor of the corresponding GeoServer WPS Input parameter.
  511. 2. ``[Action#]``; ``1..n`` actions of the Python Wrapper associated to an ``[Input]``. The reference is done through the **input_ref** property.
  512. 3. ``[Const#]``; Constant values passed to the executable and transparent to the GeoServer WPS.
  513. **[Input#]**
  514. * **class**; Uses introspection to instantiate an Input parameter. Currently the only value admitted is ``param``
  515. * **name**; The name of the input parameter. This will be also the name of the GeoServer Input parameter.
  516. * **title**; The title of the input parameter. To be used as internal descriptor.
  517. * **description**; The description of the input parameter. This will be also the description of the GeoServer Input parameter.
  518. * **type**; The type of the input parameter. Allowed types are:
  519. 1. ``string``; Simple text input. Invalid characters will be automatically removed.
  520. 2. ``int``; Integer numeric input value.
  521. 3. ``float``; Float numeric input value.
  522. 4. ``url``; Must contain a valid URL. Invalid characters will be automatically removed.
  523. 5. ``application/json``; Threated as a JSON string. It will be parsed by the Python Wrapper and converted into a complex object.
  524. 6. ``datetime``; Converted into a Python ``datetime`` object accordingly to the **formatter** property containing the date pattern and which must also be provided.
  525. * **min**; Optional parameter which sets the minimum set of inputs of this type allowed by the GeoServer WPS. *0* by default.
  526. * **max**; Optional parameter which sets the maximum set of inputs of this type allowed by the GeoServer WPS. *0* (alias infinite) by default.
  527. * **default**; Optional parameter for setting the default value of this input if a value has not provided.
  528. * **formatter**; Optional parameter to be used along with ``datetime`` inputs. Defines the date pattern to be applied to the input string (e.g.: %Y-%m-%d %H:%M:%S)
  529. **[Action#]**
  530. * **class**; Uses introspection to instantiate the type of Action.
  531. 1. ``cmdline``; The value of the associated input will be passed to the executable as a key-value pair accordingly to the ``template`` specified (e.g.: --name=value).
  532. - ``template``; Template of the key-value pair format (e.g.: template = -name value)
  533. - ``alias``; Alias of the key (e.g.: alias = i will be translated as -i value)
  534. 2. ``createJSONfile``; The value of the associated input will be dumped to a JSON file and the reference to the file passed to the executable.
  535. - ``target_filepath``; PATH Where to store the JSON file.
  536. - ``json_schema``; The PATH to the JSON Schema to be used to validate the input values.
  537. 3. ``updateJSONfile``; The value of the associated input will be substituted into a target template JSON file, which then will be passed to the executbale as reference.
  538. - ``source_filepath``; PATH of the source JSON template file.
  539. - ``target_filepath``; PATH of the target JSON file.
  540. - ``json_path_expr``; JSON path expression used to subsitute the values.
  541. 4. ``copyfile``; The value of the associated input will be interpreted as a path to a source file. The content of the file will be copied into a temporary file and then passed to the executbale as reference.
  542. - ``source_filepath``; PATH of the source JSON template file.
  543. - ``target_filepath``; PATH of the target JSON file.
  544. 5. ``updateINIfile``; The value of the associated input will be substituted into a target template INI file, which then will be passed to the executbale as reference.
  545. - ``source_filepath``; PATH of the source JSON template file.
  546. - ``target_filepath``; PATH of the target JSON file.
  547. - ``section``; Section of the INI file where to store key-value pair entries.
  548. 6. ``updateINIfileList``; The value of the associated input will be parsed as a ``list`` and substituted into a target template INI file, which then will be passed to the executbale as reference.
  549. - ``source_filepath``; PATH of the source JSON template file.
  550. - ``target_filepath``; PATH of the target JSON file.
  551. - ``section``; Section of the INI file where to store key-value pair entries.
  552. * **input_ref**; ``name`` of the input parameter referenced by this Action.
  553. **[Const#]**
  554. * **class = const**
  555. * **name**; Name of the input parameter, used by an action as reference.
  556. * **type**; May be one of the **[Input#].type** ones.
  557. * **description**; Internal description of the parameter.
  558. * **value**; Fixed value parsed by the referencing Action.
  559. Outputs Section
  560. +++++++++++++++
  561. .. code-block:: bash
  562. # ########################################### #
  563. # Output Parameters Declaration #
  564. # ########################################### #
  565. # WARNING: the name must start with the keyword "result"
  566. [Output1]
  567. name = result1
  568. type = string
  569. description = WPS Resource Plain Text
  570. filepath = %(workdir)s/geoserverLayerOutput.xml
  571. [Output2]
  572. name = result2
  573. type = image/geotiff
  574. description = WPS Resource Binary File
  575. title = SRTM
  576. filepath = %(workdir)s/srtm_39_04_c.tif
  577. backup_on_wps_execution_shared_dir = true
  578. publish_as_layer = true
  579. publish_default_style = raster
  580. publish_target_workspace = it.geosolutions
  581. publish_layer_name = srtm_39_04_c
  582. # Such metadata is a JSON snippet itself (/tmp/resource_dir/result2.json) with a small particularity.
  583. # Since you cannot know a-priori some of the final Layer properties,
  584. # you can use inside the json (/tmp/resource_dir/result2.json) some keywords which will be updated
  585. # automatically by the RemoteWPS which are the following ones:
  586. #
  587. # ${type}
  588. # ${name}
  589. # ${title}
  590. # ${description}
  591. # ${lastUpdated}
  592. # ${getMapBaseUrl}
  593. # ${srs}
  594. # ${bbox}
  595. # ${workspace}
  596. # ${layers}
  597. # ${styles}
  598. publish_metadata = /<path_to>/resource_dir/result2.json
  599. [Output3]
  600. name = result3
  601. type = image/geotiff;stream
  602. description = WPS Resource Binary Stream
  603. title = This Is A GeoTIFF Layer
  604. filepath = %(workdir)s/srtm_39_04_c.tif
  605. publish_as_layer = true
  606. publish_default_style = raster
  607. publish_target_workspace = it.geosolutions
  608. publish_layer_name = srtm_39_04_c
  609. [Output4]
  610. name = result4
  611. type = application/x-netcdf
  612. description = NetCDF Binary File
  613. title = Wind
  614. filepath = %(workdir)s/RS1_STB_1FSCLS20111003_175545_00000018xS2x_16bxx_83066_29447_wind.nc
  615. backup_on_wps_execution_shared_dir = true
  616. publish_as_layer = true
  617. publish_default_style = raster
  618. publish_target_workspace = it.geosolutions
  619. publish_layer_name = wind
  620. # Such metadata is a JSON snippet itself (/tmp/resource_dir/result3.json) with a small particularity.
  621. # Since you cannot know a-priori some of the final Layer properties,
  622. # you can use inside the json (/tmp/resource_dir/result4.json) some keywords which will be updated
  623. # automatically by the RemoteWPS which are the following ones:
  624. #
  625. # ${type}
  626. # ${name}
  627. # ${title}
  628. # ${description}
  629. # ${lastUpdated}
  630. # ${getMapBaseUrl}
  631. # ${srs}
  632. # ${bbox}
  633. # ${workspace}
  634. # ${layers}
  635. # ${styles}
  636. publish_metadata = /<path_to>/resource_dir/result4.json
  637. # ########################################### #
  638. # GML Possible type values are #
  639. # text/xml;subtype=gml/3.1.1 #
  640. # text/xml;subtype=gml/2.1.2 #
  641. # application/gml-3.1.1 #
  642. # application/gml-2.1.2 #
  643. # ########################################### #
  644. [Output5]
  645. name = result5
  646. type = text/xml;subtype=gml/3.1.1
  647. description = WPS Resource GML
  648. filepath = %(workdir)s/geoserverLoadLayerOutput.xml
  649. [Output6]
  650. name = result6
  651. type = video/mp4
  652. description = Video MP4 Binary File
  653. title = Wind
  654. filepath = %(workdir)s/RS1_STB_1FSCLS20111003_175545_00000018xS2x_16bxx_83066_29447_wind.mp4
  655. backup_on_wps_execution_shared_dir = false
  656. [Output7]
  657. name = result7
  658. type = application/owc
  659. description = WPS OWC Json MapContext
  660. layers_to_publish = result2;result4
  661. publish_as_layer = true
  662. publish_layer_name = owc_json_ctx
  663. publish_metadata = /<path_to>/resource_dir/owc_json_ctx.json
  664. The examples above represents all the possible types of Outputs currently supported by the Remote WPS Wrapper.
  665. * **type = string**
  666. The content of the file specified by the ``filepath`` is read and sent to the WPS. The GeoServer WPS declares this as a ``text/plain`` output type.
  667. * **type = image/geotiff**
  668. The content of the binary GeoTIFF specified by the ``filepath`` is read and sent to the WPS. The GeoServer WPS declares this as a ``otput binary`` RAW FILE output type.
  669. * **type = image/geotiff;stream**
  670. The content of the binary GeoTIFF specified by the ``filepath`` is read and sent to the WPS. The GeoServer WPS declares this as a ``otput binary`` RAW STREAM output type.
  671. * **type = application/x-netcdf**
  672. The content of the binary NetCDF specified by the ``filepath`` is read and sent to the WPS. The GeoServer WPS declares this as a ``otput binary`` RAW FILE output type.
  673. * **type = text/xml;subtype=gml/3.1.1**
  674. The content of the file specified by the ``filepath`` is read and sent to the WPS. The GeoServer WPS declares this as a ``text/xml`` output type.
  675. * **type = video/mp4**
  676. The content of the binary MPEG-4 specified by the ``filepath`` is read and sent to the WPS. The GeoServer WPS declares this as a ``otput binary`` RAW FILE output type.
  677. * **type = application/owc**
  678. This is a particular type of output. From the GeoServer WPS point of view is a ``text/plain`` JSON output type describing a Web Mapping Context.
  679. The Remote WPS Plugin on GeoServer side takes care of publishing the layers specified by ``layers_to_publish = result2;result4`` and render the templates specified by ``publish_metadata`` of each output.
  680. The outcome will be a complex JSON WMC describing the map to publish.
  681. In order to activate this funcionality, update the GeoServer ``remoteProcess.properties`` on the ``GEOSERVER_DATA_DIR`` with a new option:
  682. .. code-block:: bash
  683. # full path to the template used to generate the OWS WMC Json output
  684. owc_wms_json_template = /tmp/resource_dir/wmc_template.json
  685. *Sample* ``wmc_template.json``
  686. .. code-block:: text
  687. {
  688. "type": "FeatureCollection",
  689. "id": "GeoServer OWC Map Context: version of 2015-07-14",
  690. "geometry": {
  691. "type":"Polygon",
  692. "coordinates": ${renderingArea}
  693. },
  694. "features" : [
  695. <#list featureList?keys as key>
  696. {
  697. "type": "Feature",
  698. "id": "${featureList[key].name}",
  699. "geometry":
  700. {
  701. "type" : "Polygon",
  702. "coordinates" : ${featureList[key].geometryCoords}
  703. },
  704. "properties": {
  705. <#if featureList[key].owcProperties != "">${featureList[key].owcProperties},</#if>
  706. "offerings" : [
  707. {
  708. "code" : "http://www.opengis.net/spec/owc-atom/1.0/req/wms",
  709. "operations" : [{
  710. "code" : "GetCapabilities",
  711. "method" : "GET",
  712. "type" : "application/xml",
  713. "href" : "${featureList[key].getMapBaseUrl}?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities",
  714. "request":{},
  715. "result":{}
  716. },{
  717. "code" : "GetMap",
  718. "method" : "GET",
  719. "type" : "image/png",
  720. "href" : "${featureList[key].getMapBaseUrl}?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&SRS=${featureList[key].srs}&BBOX=${featureList[key].bbox}&WIDTH=500&HEIGHT=500&LAYERS=${featureList[key].layers}&STYLES=${featureList[key].styles}&FORMAT=image/png&BGCOLOR=0xffffff&TRANSPARENT=TRUE&EXCEPTIONS=application/vnd.ogc.se_xml",
  721. "request":{},
  722. "result":{}
  723. }],
  724. "contents" : []
  725. }
  726. <#if featureList[key].type == "VECTOR">
  727. ,{
  728. "code" : "http://www.opengis.net/spec/owc-atom/1.0/req/wfs",
  729. "operations" : [{
  730. "code" : "DescribeFeatureType",
  731. "method" : "GET",
  732. "type" : "application/xml",
  733. "href" : "${featureList[key].getMapBaseUrl}?SERVICE=WFS&VERSION=1.1.0&REQUEST=DescribeFeatureType&TYPENAME=${featureList[key].layers}",
  734. "request":{},
  735. "result":{}
  736. },{
  737. "code" : "GetFeature",
  738. "method" : "GET",
  739. "type" : "application/xml",
  740. "href" : "${featureList[key].getMapBaseUrl}?SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&TYPENAME=${featureList[key].layers}",
  741. "request":{},
  742. "result":{}
  743. }],
  744. "contents" : []
  745. }
  746. <#elseif featureList[key].type == "RASTER">
  747. ,{
  748. "code" : "http://www.opengis.net/spec/owc-atom/1.0/req/wcs",
  749. "operations" : [{
  750. "code" : "DescribeCoverage",
  751. "method" : "GET",
  752. "type" : "application/xml",
  753. "href" : "${featureList[key].getMapBaseUrl}?SERVICE=WCS&VERSION=1.1.0&REQUEST=GetCapabilities&IDENTIFIER=${featureList[key].layers}",
  754. "request":{},
  755. "result":{}
  756. },{
  757. "code" : "GetCoverage",
  758. "method" : "GET",
  759. "type" : "image/tiff",
  760. "href" : "${featureList[key].getMapBaseUrl}?SERVICE=WCS&VERSION=1.1.0&REQUEST=GetCoverage&IDENTIFIER=${featureList[key].layers}&BOUNDINGBOX=${featureList[key].bbox}&FORMAT=GeoTIFF",
  761. "request":{},
  762. "result":{}
  763. }],
  764. "contents" : []
  765. }
  766. </#if>
  767. ]
  768. }
  769. }<#if key_has_next>,</#if>
  770. </#list>
  771. ]
  772. ,
  773. "properties" : {
  774. ${owcProperties}
  775. }
  776. }
  777. *Sample* ``owc_json_ctx.json``
  778. .. code-block:: text
  779. "lang" : "en",
  780. "title" : "Sample Title goes here",
  781. "subtitle" : "Sample sub-title goes here",
  782. "generator" : "Sample generator",
  783. "rights" : "Sample Legal Constraints and CopyRights (C)",
  784. "authors" : [{"name" : "Author1 Name"}, {"name" : "Author2 Name"}],
  785. "contributors" : [{"name" : "Contrib1 Name"}, {"name" : "Contrib2 Name"}],
  786. "categories" : [{
  787. "term" : "wms",
  788. "label" : "This file is compliant with version 1.0 of OGC Context"
  789. },{
  790. "term" : "maps",
  791. "label" : "This file contains maps"
  792. }],
  793. "links" : [{
  794. "rel" : "profile",
  795. "href" : "http://www.opengis.net/spec/owc-atom/1.0/req/core",
  796. "title" : "This file is compliant with version 1.0 of OGC Context"
  797. },{
  798. "rel" : "via",
  799. "type" : "application/xml",
  800. "href" : "http://www.opengis.uab.cat/wms/satcat/metadades/EPSG_23031/Cat_20110301.htm",
  801. "title" : "HMTL metadata in Catalan"
  802. }]
  803. *Sample* ``result#.json``
  804. .. code-block:: text
  805. "title" : "Result 2",
  806. "updated" : "${lastUpdated}",
  807. "content" : "Sample Content Description for result 2 goes here",
  808. "authors" : [
  809. {
  810. "name" : "GeoServer Administrator",
  811. "email" : "info@sample.author.com"
  812. }
  813. ],
  814. "authors" : [{"name" : "Author2.1 Name"}, {"name" : "Author2.2 Name"}],
  815. "contributors" : [{"name" : "Contrib2.1 Name"}, {"name" : "Contrib2.2 Name"}],
  816. "categories" : [{"name" : "Category2.1 Name"}, {"name" : "Category2.2 Name"}],
  817. "links" : [
  818. {
  819. "rel" : "enclosure",
  820. "type" : "image/png",
  821. "title" : "WMS output for ${title}",
  822. "href" : "${getMapBaseUrl}?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&SRS=${srs}&BBOX=${bbox}&WIDTH=500&HEIGHT=500&LAYERS=${layers}&FORMAT=image/png&BGCOLOR=0xffffff&TRANSPARENT=TRUE&EXCEPTIONS=application/vnd.ogc.se_xml"
  823. },
  824. {
  825. "rel" : "icon",
  826. "type" : "image/png",
  827. "title" : "Preview for ${title}",
  828. "href" : "${getMapBaseUrl}?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&SRS=${srs}&BBOX=${bbox}&WIDTH=100&HEIGHT=100&LAYERS=${layers}&STYLES=${styles}&FORMAT=image/png&BGCOLOR=0xffffff&TRANSPARENT=TRUE&EXCEPTIONS=application/vnd.ogc.se_xml"
  829. },
  830. {
  831. "rel" : "via",
  832. "type" : "application/vnd.ogc.wms_xml",
  833. "title" : "Original GetCapabilities document",
  834. "href" : "${getMapBaseUrl}?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetCapabilities"
  835. }
  836. ]
  837. **Other options for the Outputs**
  838. * **backup_on_wps_execution_shared_dir**; This is a boolean which tells to the Remote WPS to store first the outcome into the **sharedir** defined into the ``[DEFAULT]`` section before streaming out to GeoServer. This allows the Remote WPS to preserve the outcomes even when the resources are cleaned out.
  839. * **upload_data**; This is a boolean which tells to the Remote WPS to upload first the outcome into the **host** defined into the ``[UPLOADER]`` section before streaming out to GeoServer. This allows the Remote WPS to preserve the outcomes even when the resources are cleaned out.
  840. .. warning:: If both enabled for a certain output, the **backup_on_wps_execution_shared_dir** takes precedence to the **upload_data** one.
  841. * **publish_as_layer**; A boolean to instruct GeoServer Remote WPS to *try* to automatically publish the outcome as a new Layer through the GeoServer **Importer** Plugin.
  842. * **publish_default_style**; The default style to use when publishing the Layer.
  843. * **publish_target_workspace**; The default workspace to use when publishing the Layer.
  844. * **publish_layer_name**; The default name to use when publishing the Layer.
  845. Logging Section
  846. +++++++++++++++
  847. .. code-block:: bash
  848. # ########################################### #
  849. # Logging RegEx and Levels #
  850. # ########################################### #
  851. [Logging]
  852. stdout_parser = [.*\[DEBUG\](.*), .*\[INFO\] ProgressInfo\:([-+]?[0-9]*\.?[0-9]*)\%, .*\[(INFO)\](.*), .*\[(WARN)\](.*), .*\[(ERROR)\](.*), .*\[(CRITICAL)\](.*)]
  853. stdout_action = [ignore, progress, log, log, log, abort]
  854. * **stdout_parser**
  855. This property must contain a *list* of regular expressions matching the possible executable ``STDOUT`` logging messages the user wants to forward to GeoServer.
  856. As an instance
  857. .. code-block:: text
  858. .*\[DEBUG\](.*)
  859. Matches all the messages containing the keyword ``[DEBUG]`` and forwards to the corresponding **stdout_action** (*see below*) the content of the first matching group ``(.*)``
  860. In this case everything after ``[DEBUG]`` is forwarded to the action.
  861. Another example
  862. .. code-block:: text
  863. .*\[INFO\] ProgressInfo\:([-+]?[0-9]*\.?[0-9]*)\%
  864. Matches all the messages containing the keyword ``[INFO] ProgressInfo:<any_number>%`` and forwards to the corresponding **stdout_action** (*see below*) the content of the first matching group ``([-+]?[0-9]*\.?[0-9]*)``
  865. In this case the expression extracts a float number form the text along with the sign ``[-+]``
  866. * **stdout_action**
  867. This property must contain a *list* of keywords associated to a *particular action* which will take the content of the corresponding regular expression and forwards it to GeoServer packaged ad a specific XMPP message.
  868. As an instance
  869. * *progress*; gets the content of the match and sends a **PROGRESS** XMPP message to GeoServer. The **PROGRESS** messgae must always contain a number.
  870. * *abort*; gets the content of the match and sends a **ABORT** XMPP message to GeoServer. This will cause GeoServer to mark the WPS Process as **FAILED**.
  871. * *ignore*; simply throws out everything matching the corresponding regular expression.
  872. * *log*; sends a **LOG** message to GeoServer with the content of the match. This will appear into the GeoServer Log file.