wms - Web Map Service

Once installation and configuration are complete, you can start the Web Map Service application (provided you have forecast data to visualise). The file “mswms” is an executable Python script starting up a Paste HTTP server with the WMS WSGI module. A short description of how to start the program is given by the –help option. The file “wms.wsgi” is intended to be used with an Apache web server installation.

We have methods to use data for ECMWF, CLaMS, GWFC, EMAC, METEOSAT implemented. The data have to use for their parameters the CF attribute standard_name.

Per configuration you could register horizontal (register_horizontal_layers) or vertical layers (register_vertical_layers), give a basemap table for EPSG mapping (epsg_to_mpl_basemap_table) and at all how to access the data (nwpaccess).

A few notes:

  • If you run the Paste WMS on a remote machine (e.g. on your office computer which you access via ssh from a campaign site), consider the ssh-tunnel option. Create the ssh connection with the “-L” option and start the WMS with the tunneled port as option.
  • The Paste WMS currently cannot run multithreaded (Apache does support multiple processes). This is due to that a single instance of the WSGI application handler class MSS_WMSResponse can create only one plot at a time (otherwise you get messed up plots when simultaneous requests occur). In the current implementation, only a single instance is passed to PASTE (to do all the initialisation work only once. To extend the software to handle simultaneous requests would probably involve creating a “factory” of MSS_WMSResponse instances.. If you want to do this, check if/how PASTE handles “worker” factories.
  • Creating the capabilities document can take very long (> 1 min) if the forecast data files have to be read for the first time (the WMS program opens all files and tries to determine the available data and elevation ranges). Once the information used for the capabilities are in the cache, however, a GetCapabilities request should return a document within 1-2 seconds.
  • A typical bottleneck for plot generation is when the forecast data files are located on a different computer than the WMS server. In this case, large amounts of data have to be transferred over the network. Hence, when possible, try to make sure the WMS runs on the same computer on which the input data files are hosted.

Configuration file of the wms server

Configuration for the Mission Support System Web Map Service (wms).

In this module the data organisation structure of the available forecast data is described. The class NWPDataAccess is subclassed for each data type in the system and provides methods to determine which file needs to be accessed for a given variable and time. The classes also provide methods to query the available initialisation times for a given variable, and the available valid times for a variable and a given initialisation time. As the latter methods need to open the NetCDF data files to determine the contained time values, a caching system is used to avoid re-opening already searched files.

The configuration file have to become added to the /home/mss/config directory

/home/mss/config/mss_wms_settings.py

# -*- coding: utf-8 -*-
"""

    mss_wms_settings
    ~~~~~~~~~~~~~~~~

    Configuration module for programs accessing data on the MSS server.

    This file is part of mss.

    :copyright: 2008-2014 Deutsches Zentrum fuer Luft- und Raumfahrt e.V.
    :copyright: 2011-2014 Marc Rautenhaus
    :copyright: Copyright 2016-2017 by the mss team, see AUTHORS.
    :license: APACHE-2.0, see LICENSE for details.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
"""

import os
import sys

# Configuration of Python's code search path
# If you already have set up the PYTHONPATH environment variable for the
# stuff you see below, you don't need to do a1) and a2).

# a1) Path of the directory where the mss code package is located.
# sys.path.insert(0, '/home/mss/miniconda2/lib/python2.7/site-packages')

# a2) Path of the directory where mss_wms_settings.py is located
MSSCONFIGPATH = os.path.abspath(os.path.normpath(os.path.dirname(sys.argv[0])))
sys.path.insert(0, MSSCONFIGPATH)
os.chdir(MSSCONFIGPATH)

import mslib.mswms.dataaccess
from mslib.mswms import mpl_hsec_styles
from mslib.mswms import mpl_vsec_styles
import mslib.mswms




#
# SETTINGS                                  ###
#
# Valid time cache settings:
# Path to the cache directory. Set to None to disable cache.
# valid_time_cache = "./vt_cache"
mslib.mswms.dataaccess.valid_time_cache = os.path.join(os.environ["HOME"], ".mss", "mswms", "vt_cache")
if not os.path.exists(valid_time_cache):
    os.makedirs(valid_time_cache)
# Maximum size of the cache in bytes.
mslib.mswms.dataaccess.valid_time_cache_max_size_bytes = 10 * 1024 * 1024
# Maximum age of a cached file in seconds.
mslib.mswms.dataaccess.valid_time_cache_max_age_seconds = 10 * 86400

# Paths to data directories. Process callables (the functions that are
# executed by the dispatcher system) can access these paths, hence
# simply define the key/value pairs that are required.
datapath = {
    "ecmwf": "/path/to/data/mss/grid/ecmwf/netcdf",
    "emac": "/path/to/data/mss/grid/emac/netcdf",
    "meteosat": "/path/to/data/mss/grid/meteosat/netcdf",
    "camsglobal": "/path/to/data/mss/grid/camsglobal/netcdf",
}


# Objects that let the user query the filename in which a particular
# variable can be found. Objects are instances of subclasses of NWPDataAccess,
# which provides the methods fc_filename() and full_fc_path().
nwpaccess = {
    "ecmwf_NH_LL05": mslib.mswms.dataaccess.ECMWFDataAccess(datapath["ecmwf"], "NH_LL05")
    #    "ecmwf_EUR_LL015": mslib.mswms.dataaccess.ECMWFDataAccess(datapath["ecmwf"], "EUR_LL015"),
    #    "meteosat_EUR_LL05": mslib.mswms.dataaccess.MeteosatDataAccess(datapath["meteosat"], "EUR_LL05"),
    #    "emac_GLOBAL_LL1125": mslib.mswms.dataaccess.EMACDataAccess(datapath["emac"])

    #        The MSS-Chem project provides an easy way to download and prepare
    #        forecasts from a range of different CTMs.
    #        The MSSChemDataAccess class is meant to provide access to
    #        the chemistry forecasts prepared by MSS-Chem.  Therefore, it has
    #        to be more general than the other DataAccess classes.
    #        Its contstructor takes four arguments:
    #
    #        1. The path to the data files.  This directory has to contain one
    #           folder for each init_time, which is called "%Y-%m-%d_%H"
    #        2. The model name, to be displayed in plot titles
    #        3. The string with which the filenames start
    #        4. The vertical layer type of the model; one of
    #           - "pl" (pressure level)
    #           - "ml" (model level)
    #           - "tl" (potential temperature level)
    #           - "al" (altitude level) -> CAUTION <- Only use if absolutely necessary, for models without any pressure
    #             information.  For vertical sections, air_pressure will be determined on-the-fly, from the layer
    #             altitude alone, which is not very accurate
    #    "CAMSglb": mslib.mswms.dataaccess.MSSChemDataAccess(datapath["camsglobal"], "CAMSglobal", "cams-global", "ml"),
}

nwpaccess[nwpaccess.keys()[0]].serviceCache()

#
# HTTP Authentication                               ###
#

# If you require basic HTTP authentication, set the following variable
# to True. Add usernames in the list "allowed:users". Note that the
# passwords are not specified in plain text but by their md5 digest.
enable_basic_http_authentication = False


#
# Basemap cache                                     ###
#

# Plotting coastlines on horizontal cross-sections requires usually the parsing
# of the corresponding databases for each plot.
# A simple caching feature allows to reuse this data from previous plots using
# the same bounding box and projection parameters, dramatically speeding up
# the plotting. 'basemap_cache_size' determines hows many sets of coastlines shall
# be stored in memory and 'basemap_request_size' determines the length of history
# used to determine, which data shall be purged first if the cache exceeds its
# maximum size.
basemap_use_cache = False
basemap_request_size = 200
basemap_cache_size = 20

#
# Registration of horizontal layers.                     ###
#

# The following list contains tuples of the format (instance of
# visualisation classes, data set). The visualisation classes are
# defined in mpl_hsec.py and mpl_hsec_styles.py. Add only instances of
# visualisation products for which data files are available. The data
# sets must be defined in mss_config.py. The WMS will only offer
# products registered here.

register_horizontal_layers = [
    # ECMWF standard surface level products.
    (mpl_hsec_styles.MPLBasemapHorizontalSectionStyle, ["ecmwf_NH_LL05"]),
    (mpl_hsec_styles.HS_CloudsStyle_01, ["ecmwf_EUR_LL015", "ecmwf_NH_LL05"]),
    (mpl_hsec_styles.HS_MSLPStyle_01, ["ecmwf_EUR_LL015", "ecmwf_NH_LL05"]),
    (mpl_hsec_styles.HS_SEAStyle_01, ["ecmwf_NH_LL05"]),
    (mpl_hsec_styles.HS_SeaIceStyle_01, ["ecmwf_NH_LL05"]),
    (mpl_hsec_styles.HS_VIProbWCB_Style_01, ["ecmwf_EUR_LL015"]),

    # ECMWF standard pressure level products.
    (mpl_hsec_styles.HS_TemperatureStyle_PL_01, ["ecmwf_EUR_LL015"]),
    (mpl_hsec_styles.HS_GeopotentialWindStyle_PL, ["ecmwf_EUR_LL015"]),
    (mpl_hsec_styles.HS_RelativeHumidityStyle_PL_01, ["ecmwf_EUR_LL015"]),
    (mpl_hsec_styles.HS_EQPTStyle_PL_01, ["ecmwf_EUR_LL015"]),
    (mpl_hsec_styles.HS_WStyle_PL_01, ["ecmwf_EUR_LL015"]),
    (mpl_hsec_styles.HS_DivStyle_PL_01, ["ecmwf_EUR_LL015"]),

    # ECMWF standard model level products.
    (mpl_hsec_styles.HS_TemperatureStyle_ML_01, ["ecmwf_EUR_LL015"]),

    # ECMWF standard potential vorticity products.
    (mpl_hsec_styles.HS_PVTropoStyle_PV_01, ["ecmwf_EUR_LL015"]),

    # EMAC layers.
    # (mpl_hsec_styles.HS_EMAC_TracerStyle_ML_01, ["emac_GLOBAL_LL1125"]),
    # (mpl_hsec_styles.HS_EMAC_TracerStyle_SFC_01, ["emac_GLOBAL_LL1125"]),

    # Meteosat products.
    (mpl_hsec_styles.HS_Meteosat_BT108_01, ["meteosat_EUR_LL05"]),

    # MSS-Chem chemistry forecasts
    # (mpl_hsec_styles.HS_MSSChemStyle_ML_NO2_mfrac, ["CAMSglb"]),
]


#
# Registration of vertical layers.                       ###
#

# The same as above, but for vertical cross-sections.

register_vertical_layers = [
    # ECMWF standard vertical section styles.
    (mpl_vsec_styles.VS_CloudsStyle_01, ["ecmwf_EUR_LL015"]),
    (mpl_vsec_styles.VS_HorizontalVelocityStyle_01, ["ecmwf_EUR_LL015"]),
    (mpl_vsec_styles.VS_PotentialVorticityStyle_01, ["ecmwf_EUR_LL015"]),
    (mpl_vsec_styles.VS_ProbabilityOfWCBStyle_01, ["ecmwf_EUR_LL015"]),
    (mpl_vsec_styles.VS_VerticalVelocityStyle_01, ["ecmwf_EUR_LL015"]),
    (mpl_vsec_styles.VS_RelativeHumdityStyle_01, ["ecmwf_EUR_LL015"]),
    (mpl_vsec_styles.VS_SpecificHumdityStyle_01, ["ecmwf_EUR_LL015"]),
    (mpl_vsec_styles.VS_TemperatureStyle_01, ["ecmwf_EUR_LL015"]),

    # EMAC layers.
    # (mpl_vsec_styles.VS_EMACEyja_Style_01, ["emac_GLOBAL_LL1125"]),

    # MSS-Chem chemistry forecasts
    # (mpl_vsec_styles.VS_MSSChemStyle_ML_NO2_mfrac, ["CAMSglb"]),
]


#
# Server settings.                                ###
#

# Here you can define to which IP addresses and ports the PASTE HTTP
# server should bind on different machines. The WSGI program obtains
# the hostname of the machine it is running on. For each hostname (key
# in the following dictionary) you can specify its IP-address, port,
# and alias. The alias will be used as the GetMap-URL in the
# capabilities document. Note that this alias setting will be
# overridden if the WMS is started with the "--ssh" option (see
# docstring of mss_wms_wsgi.py).
paste_ip_bind = {
    "server-name": {"host": "insert-ip-number", "port": "8081", "alias": "mss.server.de"}
}

paste_use_threadpool = False

# xml_template directory is a sub directory of mswms

base_dir = os.path.abspath(os.path.dirname(mslib.mswms.__file__))
xml_template_location = os.path.join(base_dir, "xml_templates")

# get_capabilities.pt
service_name = "OGC:WMS"
service_title = "Mission Support System Web Map Service"
service_abstract = "Your Abstract"
service_contact_person = "Your Name"
service_contact_organisation = "Your Organization"
service_contact_position = "Your Position"
service_address_type = "postal"
service_address = "street"
service_city = "Your City"
service_state_or_province = ""
service_post_code = "12345"
service_country = "Germany"
service_email = "mail@example.com"
service_fees = "none"
service_access_constraints = "This service is intended for research purposes only."


#
# EPSG Code Definitions for Matplotlib basemap               ###
#

# In this section you can define how EPSG codes are interpreted in
# terms of Matplotlib basemap parameters. If you require a new EPSG
# code, define it here.

# Table to translate EPSG codes to Matplotlib basemap projection parameters.
# Extend this table to add further EPSG codes.
# Also see: http://external.opengeospatial.org/twiki_public/bin/view/
#                  MetOceanDWG/MetCoordinateReferenceSystemDefinition
epsg_to_mpl_basemap_table = {
    # EPSG:4326, the standard cylindrical lat/lon projection.
    4326: {"projection": "cyl"},

    # Non-standard EPSG codes, specifically defined for MSS pruposes.
    # EPSG:777llLLL, north polar stereographic projections with lat_0=ll and
    # lon_0=LLL.
    77790000: {"projection": "stere", "lat_0": 90., "lon_0": 0.},
    77790010: {"projection": "stere", "lat_0": 90., "lon_0": 10.},
    77790015: {"projection": "stere", "lat_0": 90., "lon_0": 15.},
    77790340: {"projection": "stere", "lat_0": 90., "lon_0": -20.},
    77790105: {"projection": "stere", "lat_0": 90., "lon_0": -105.},

    77890000: {"projection": "spstere", "lat_0": 90., "lon_0": 0.},
    77890010: {"projection": "spstere", "lat_0": 90., "lon_0": 10.},
    77890015: {"projection": "spstere", "lat_0": 90., "lon_0": 15.},
    77890340: {"projection": "spstere", "lat_0": 90., "lon_0": -20.},
    77890105: {"projection": "spstere", "lat_0": 90., "lon_0": -105.}

    # Feel free to add other projections, e.g. a south polar projection
    # EPSG:778llLLL.
}

You have to adopt this file to your data.

Standalone server setup

For the standalone server mswms you need the path of your mss_wms_settings.py added to the PYTHONPATH. E.g.:

export PYTHONPATH=/home/mss/config

demodata - simulated data

We provide demodata by executing the demodata programm. This creates in your home directory data files and also the needed server configuration file. The program creates 70MB of examples. This script does not overwrite an existing mss_wms_settings.py

mss
├── mss_wms_auth.py
├── mss_wms_settings.py
└── testdata
    ├── 20121017_12_ecmwf_forecast.ALTITUDE_LEVELS.EUR_LL015.036.ml.nc
    ├── 20121017_12_ecmwf_forecast.CC.EUR_LL015.036.ml.nc
    ├── 20121017_12_ecmwf_forecast.CIWC.EUR_LL015.036.ml.nc
    ├── 20121017_12_ecmwf_forecast.CLWC.EUR_LL015.036.ml.nc
    ├── 20121017_12_ecmwf_forecast.EMAC.EUR_LL015.036.ml.nc
    ├── 20121017_12_ecmwf_forecast.P_derived.EUR_LL015.036.ml.nc
    ├── 20121017_12_ecmwf_forecast.PRESSURE_LEVELS.EUR_LL015.036.pl.nc
    ├── 20121017_12_ecmwf_forecast.ProbWCB_LAGRANTO_derived.EUR_LL015.036.ml.nc
    ├── 20121017_12_ecmwf_forecast.ProbWCB_LAGRANTO_derived.EUR_LL015.036.sfc.nc
    ├── 20121017_12_ecmwf_forecast.PV_derived.EUR_LL015.036.ml.nc
    ├── 20121017_12_ecmwf_forecast.PVU.EUR_LL015.036.pv.nc
    ├── 20121017_12_ecmwf_forecast.Q.EUR_LL015.036.ml.nc
    ├── 20121017_12_ecmwf_forecast.SEA.EUR_LL015.036.sfc.nc
    ├── 20121017_12_ecmwf_forecast.SFC.EUR_LL015.036.sfc.nc
    ├── 20121017_12_ecmwf_forecast.T.EUR_LL015.036.ml.nc
    ├── 20121017_12_ecmwf_forecast.THETA_LEVELS.EUR_LL015.036.tl.nc
    ├── 20121017_12_ecmwf_forecast.U.EUR_LL015.036.ml.nc
    ├── 20121017_12_ecmwf_forecast.V.EUR_LL015.036.ml.nc
    └── 20121017_12_ecmwf_forecast.W.EUR_LL015.036.ml.nc

Before starting the standalone server you should add the path where the server config is to your python path. e.g.

$ export PYTHONPATH=~/mss

Detailed server configuration mss_wms_settings.py for this demodata

# -*- coding: utf-8 -*-
"""

    mss_wms_settings
    ~~~~~~~~~~~~~~~~

    Configuration module for programs accessing data on the MSS server.

    This file is part of mss.

    :copyright: 2008-2014 Deutsches Zentrum fuer Luft- und Raumfahrt e.V.
    :copyright: 2011-2014 Marc Rautenhaus
    :copyright: Copyright 2017 Jens-Uwe Grooss, Joern Ungermann, Reimar Bauer
    :copyright: Copyright 2017 by the mss team, see AUTHORS.
    :license: APACHE-2.0, see LICENSE for details.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
"""

import os
import sys

# Configuration of Python's code search path
# If you already have set up the PYTHONPATH environment variable for the
# stuff you see below, you don't need to do a1) and a2).

# a1) Path of the directory where the mss code package is located.
# sys.path.insert(0, '/home/mss/miniconda2/lib/python2.7/site-packages')

# a2) Path of the directory where mss_wms_settings.py is located
#MSSCONFIGPATH = os.path.abspath(os.path.normpath(os.path.dirname(sys.argv[0])))
#sys.path.insert(0, MSSCONFIGPATH)
#os.chdir(MSSCONFIGPATH)

import mslib.mswms.dataaccess
from mslib.mswms import mpl_hsec_styles
from mslib.mswms import mpl_vsec_styles
import mslib.mswms


# Configuration for mss_wms_settings accessing data on the MSS server.
# This is the data organisation structure of demodata.


#service_name = "OGC:WMS"
#service_title = "Mission Support System Web Map Service"
#service_abstract = "Your Abstract"
#service_contact_person = "Your Name"
#service_contact_organisation = "Your Organization"
#service_address_type = "postal"
#service_address = "street"
#service_city = "Your City"
#service_state_or_province = ""
#service_post_code = "12345"
#service_country = "Germany"
#service_fees = "none"
#service_access_constraints = "This service is intended for research purposes only."


#
# HTTP Authentication
#
# If you require basic HTTP authentication, set the following variable
# to True. Add usernames in the list "allowed:users". Note that the
# passwords are not specified in plain text but by their md5 digest.
#enable_basic_http_authentication = False


#xml_template directory is a sub directory of mswms
#base_dir = os.path.abspath(os.path.dirname(mslib.mswms.__file__))
#xml_template_location = os.path.join(base_dir, "xml_templates")


_vt_cache = r"/home/icg105/mss/vt_cache"
mslib.mswms.dataaccess.valid_time_cache = _vt_cache

_datapath = r"/home/icg105/mss/testdata"

nwpaccess = {
    "ecmwf_EUR_LL015": mslib.mswms.dataaccess.ECMWFDataAccess(_datapath, "EUR_LL015"),
}

epsg_to_mpl_basemap_table = {
    # EPSG:4326, the standard cylindrical lat/lon projection.
    4326: {"projection": "cyl"}
}

basemap_use_cache = True

#
# Registration of horizontal layers.
#

# The following list contains tuples of the format (instance of
# visualisation classes, data set). The visualisation classes are
# defined in mpl_hsec.py and mpl_hsec_styles.py. Add only instances of
# visualisation products for which data files are available. The data
# sets must be defined in mss_config.py. The WMS will only offer
# products registered here.
register_horizontal_layers = None
if mpl_hsec_styles is not None:
    register_horizontal_layers = [
        # ECMWF standard pressure level products.
        (mpl_hsec_styles.HS_TemperatureStyle_PL_01, ["ecmwf_EUR_LL015"]),
        (mpl_hsec_styles.HS_GeopotentialWindStyle_PL, ["ecmwf_EUR_LL015"]),
        (mpl_hsec_styles.HS_RelativeHumidityStyle_PL_01, ["ecmwf_EUR_LL015"]),
        (mpl_hsec_styles.HS_EQPTStyle_PL_01, ["ecmwf_EUR_LL015"]),
        (mpl_hsec_styles.HS_WStyle_PL_01, ["ecmwf_EUR_LL015"]),
        (mpl_hsec_styles.HS_DivStyle_PL_01, ["ecmwf_EUR_LL015"]),
    ]


#
# Registration of vertical layers.
#
# The same as above, but for vertical cross-sections.
register_vertical_layers = None
if mpl_vsec_styles is not None:
    register_vertical_layers = [
        # ECMWF standard vertical section styles.
        (mpl_vsec_styles.VS_CloudsStyle_01, ["ecmwf_EUR_LL015"]),
        (mpl_vsec_styles.VS_HorizontalVelocityStyle_01, ["ecmwf_EUR_LL015"]),
        (mpl_vsec_styles.VS_VerticalVelocityStyle_01, ["ecmwf_EUR_LL015"]),
        (mpl_vsec_styles.VS_RelativeHumdityStyle_01, ["ecmwf_EUR_LL015"]),
        (mpl_vsec_styles.VS_SpecificHumdityStyle_01, ["ecmwf_EUR_LL015"]),
        (mpl_vsec_styles.VS_TemperatureStyle_01, ["ecmwf_EUR_LL015"])
    ]

For setting authentication see mss_wms_auth.py

# -*- coding: utf-8 -*-
"""

    mss_wms_auth
    ~~~~~~~~~~~~

    Configuration module for authentication to the MSS server.

    This file is part of mss.

    :copyright: 2008-2014 Deutsches Zentrum fuer Luft- und Raumfahrt e.V.
    :copyright: 2011-2014 Marc Rautenhaus
    :copyright: Copyright 2016-2017 by the mss team, see AUTHORS.
    :license: APACHE-2.0, see LICENSE for details.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
"""

#
# HTTP Authentication                               ###
#
#
# Use the following code to create a new md5 digest of a password (e.g. in
# ipython):
#     import hashlib; hashlib.md5("my_new_password").hexdigest()
allowed_users = [("mswms", "add_md5_digest_of_PASSWORD_here"),
                 ("add_new_user_here", "add_md5_digest_of_PASSWORD_here")]

Apache server setup

One Instance

Our examples are based on the following directories located in the home directory of the mss user:

.
├── config
│   └── mss_wms_settings.py
|   └── mss_wms_auth.py
├── log
│   └── mss_error.log
├── miniconda2
│   ├── bin
│   ├── conda-bld
│   ├── conda-meta
│   ├── envs
│   ├── etc
│   ├── include
│   ├── lib
│   ├── LICENSE.txt
│   ├── pkgs
│   ├── share
│   ├── ssl
│   └── var
└── wsgi
    ├── auth.wsgi
    └── wms.wsgi

Create that mss user first.

Configuration of apache mod_wsgi.conf

One posibility to setup the PYTHONPATH environment variable is by adding it to your mod_wsgi.conf. Alternativly you could add it also to mss_wms_settings.py.

WSGIPythonPath /home/mss/config:/home/mss/miniconda2/lib/python2.7/site-packages

By this setting you override the PYTHONPATH environment variable. So you have also to add the site-packes directory of your miniconda or anaconda installation besides the config file path.

If your server hosts different instances by different users you want to setup this path in mss_wms_setting.py.

Configuration of wsgi for wms

You can setup a vhost for this service.

/home/mss/wsgi/wms.wsgi



import logging
from mslib.mswms.wms import application

Configuration of wsgi auth

As long as you have only one instance of the server running you can use this method to restrict access.

To restrict access to your data use this script.

/home/mss/wsgi/auth.wsgi

import sys
sys.path.extend(['/home/mss/config'])

import mss_wms_auth
import hashlib

def check_password(environ, username, password):
    for u, p in mss_wms_auth.allowed_users:
        if (u == username) and (p == hashlib.md5(password).hexdigest()):
           return True
    return False

This needs also a configuration /home/mss/config/mss_wms_auth.py script.

# -*- coding: utf-8 -*-
"""

    mss_wms_auth
    ~~~~~~~~~~~~

    Configuration module for authentication to the MSS server.

    This file is part of mss.

    :copyright: 2008-2014 Deutsches Zentrum fuer Luft- und Raumfahrt e.V.
    :copyright: 2011-2014 Marc Rautenhaus
    :copyright: Copyright 2016-2017 by the mss team, see AUTHORS.
    :license: APACHE-2.0, see LICENSE for details.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
"""

#
# HTTP Authentication                               ###
#
#
# Use the following code to create a new md5 digest of a password (e.g. in
# ipython):
#     import hashlib; hashlib.md5("my_new_password").hexdigest()
allowed_users = [("mswms", "add_md5_digest_of_PASSWORD_here"),
                 ("add_new_user_here", "add_md5_digest_of_PASSWORD_here")]

At the moment you have many different instances with different users or different versions of mss you have to use basic auth of your webserver configuration.

Configuration of your site as vhost

You have to setup a webserver server site configuration file

/etc/apache2/sites-available/mss.yourserver.de.conf


<VirtualHost *:80>
    ServerName mss.yourserver.de
    #ServerAlias localwms
    LogLevel debug
    ServerAdmin webmaster@yourserver.de
    ErrorLog /home/mss/log/mss_error.log
    TransferLog /var/log/apache2/mss_access.log
    CustomLog /var/log/apache2/mss_custom.log combined


    #all wsgi scripts are in /home/mss/wsgi
    <Directory /home/mss/wsgi>
        AuthType Basic
        AuthName "mss"
        AuthBasicProvider wsgi
        WSGIAuthUserScript /home/mss/wsgi/auth.wsgi
        AuthDigestDomain / http://mss.yourserver.de/
        Require valid-user
    </Directory>

    #alternative without authentication
    #<Directory /home/mss/wsgi>
    #    Require all granted
    #</Directory>

    WSGIScriptAlias / /home/mss/wsgi/wms.wsgi
    WSGIDaemonProcess MSS python-home=/home/mss/miniconda2/bin user=mss group=mss home=/home/mss/config processes=2 threads=1 deadlock-timeout=25 display-name=MSS
    # WSGI Options
    # python-home: path where your environment python bin is located
    # home: where your config scripts are located
    # Please see the documentation here : http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives
    WSGIProcessGroup MSS

    # Python Simplified GIL State API ( ISSUE ) 
    # http://code.google.com/p/modwsgi/wiki/ApplicationIssues
    WSGIApplicationGroup %{GLOBAL} 


    DocumentRoot /home/mss/htdocs

    # don't loose time with IP address lookups
    HostnameLookups Off

    # needed for named virtual hosts
    UseCanonicalName Off

    # configures the footer on server-generated documents
    ServerSignature On

</VirtualHost>

Enable it with a2ensite mss.yourserver.de.conf

Many Instances

If you want to setup many instances we suggest to use a similiar proxy based configuration

<VirtualHost *:80>

ProxyRequests Off
ProxyPreserveHost On
RewriteEngine On
RequestHeader add X-SSL off
RewriteRule ^/demo/(.*) http://127.0.0.1/demo/$1 [P,L]


ServerName proxy_demo.yourserver.de
DocumentRoot /var/www/html
ProxyPreserveHost On
ProxyPass /demo http://127.0.0.1/demo

</VirtualHost>

and if you need authentication then use a Location based AuthType Basic


<VirtualHost 127.0.0.1:80>
      <Location /demo>
        AuthType Basic
        AuthName "mss"
        AuthDigestDomain /
        AuthUserFile /home/mss/DEMO/config/apache_users 
        <Limit GET>
            Require valid-user
        </Limit>
      </Location>
    ServerName proxy_demo.yourserver.de
    RemoteIPHeader X-Forwarded-For
    RemoteIPInternalProxy 127.0.0.0/8
    LogLevel debug
    ServerAdmin admin@email

    # WSGI Options
    # home: Initial working directory of the script, make sure you change it.
    # python-path : Directories to search for Modules, make sure you change it as well.
    # Please see the documentation here : http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives
    WSGIScriptAlias /demo /home/mss/DEMO/wsgi/wms.wsgi

    WSGIDaemonProcess MSS python-home="/home/mss/miniconda2/envs/demo/bin" home="/home/mss/DEMO/config"  user=mss group=mss processes=2 threads=1 deadlock-timeout=25 display-name=MSS

    WSGIProcessGroup MSS

    # Python Simplified GIL State API ( ISSUE )
    # http://code.google.com/p/modwsgi/wiki/ApplicationIssues
    WSGIApplicationGroup %{GLOBAL}

    # don't loose time with IP address lookups
    HostnameLookups Off

    # needed for named virtual hosts
    UseCanonicalName Off

    # configures the footer on server-generated documents
    ServerSignature On

</VirtualHost>

For further informations on apache2 server setup read https://httpd.apache.org/docs/2.4/howto/