Sahana Eden
===========

Overview
--------

Sahana Eden is a flexible and extensible humanitarian platform written in python, running on web2py platform and PostgreSQL with PostGIS extension. Sahana Eden is extremely highly customizable and configurable which unfortunately often leads to various bugs and misunderstandings in the configuration. For the description of the individual configuration options and their effect, see `Sahana Eden configuration usability report <sahana-configuration-report.html>`_. The application is usually configured via templates, which contain all the configuration, forms and logic customizations and some basic data relevant for the intended deployment.

The application supports various interfaces, protocols and formats for data exchange - CAP (Common Alerting Protocol), XML/Atom feeds, WMS, WFS, WCS and other map services, KML exports, XML and CSV tabular data etc. Maps can be configured and adjusted to use virtually any tile, layer and feature sets. See `map services <map-services.html>`_.

Upstream URL: https://github.com/sahana/eden

Setup module
------------

Sahana deployment functions are based on Ansible. Ansible is provisioning, configuration management, and application-deployment tool written in python. It uses YAML files to define the desired actions or states. These files are called *playbooks*. There is a whole separate sahana_deploy project focusing on rapid Sahana Eden deployment and parts of it are used also in the Setup module. The setup module allows to control Sahana instances and adjust their configuration in terms of setting simple values and enabling/disabling modules in ``000_config.py``. The module, as well as the Ansible playbooks for the whole deployment are a bit too strict when it comes to assumptions and discovery of Sahana's environment. E.g. the path to the instance is expected to be always under ``/home/prod``. The Setup module is enabled and can be used, however due to its limitations and expectations it sets, it can't be considered reliable in the environment of Alpine container.

Python 3.8 compatibility
------------------------

Sahana Eden is currently recommended to be run on web2py R2.18.5 (commit hash `59700b8 <https://github.com/web2py/web2py/commit/59700b8>`_). Recommended version is tracked in eden_deploy project in `main.yml for common playbook <https://github.com/sahana/eden_deploy/blob/master/roles/common/tasks/main.yml>`_. This version however doesn't fully support python 3.8, so a series of patches needs to applied to achieve the full support for python 3.8. This includes compatibility patches for gluon and pydal tracked in `_compat.patch <https://github.com/sahana/eden_deploy/blob/master/roles/common/files/_compat.patch>`_ and scheduler patch tracked separately in `scheduler.diff <https://github.com/sahana/eden_deploy/blob/master/roles/common/files/scheduler.diff>`_.

Localization
------------

Czech localization for Sahana Eden is currently not a part of upstream code. It is currently held in SpotterVM repository and there are currently no plans to submit a pull request with the translation.

The localization is done via translation export function of Sahana Eden found in the administration menu. The exported CSV or XLS file is then manually translated and fed back to ``sahana-lang-convert.py`` helper script which generated the appropriate python dictionary file used as translation. Some strings are not output by the translation function and are either hardcoded or composed, so there is also ``sahana-lang-compare.py`` helper script which traverses installed Sahana Eden instance and tries to locate and supply all missing strings from the previous translation file. Both helper scripts are also contained in the SpotterVM repository.

Local development
-----------------

Since Sahana Eden is the crown jewel of the whole environment and unfortunately also the most buggy application, it may be needed to work on some development tasks and bugfixes outsite of the VM environment. Following are a few tips to important tasks and gotchas you may encounter.

To enable debug mode for Sahana, set ``settings.base.debug = True`` in ``applications/eden/models/000_config.py``.

Database migration
^^^^^^^^^^^^^^^^^^

New commits (both upstream and local) can require a modification of database structure. If this is not done, Sahana may report internal server errors or corrupt the database. Migration to the up-to-date schema version can be achieved via following steps.

.. code-block:: bash

    # Change directory to web2py root
    cd /srv/web2py

    # Allow database migration (normally denied in prod)
    sed -i 's/settings.base.migrate = False/settings.base.migrate = True/g' applications/eden/models/000_config.py

    # Remove old cached bytecode
    rm -rf applications/eden/compiled

    # Run the migration task
    python web2py.py -S eden -M -R applications/eden/static/scripts/tools/noop.py

    # Deny database migration (improves performance)
    sed -i 's/settings.base.migrate = True/settings.base.migrate = False/g' applications/eden/models/000_config.py

    # Precompile fresh bytecode
    python web2py.py -S eden -M -R applications/eden/static/scripts/tools/compile.py

Factory reset
^^^^^^^^^^^^^

In case you'd like to wipe all data and restore your Sahana instance to pre-installation phase, stop all Sahana (uWSGI) processes and run the following.

.. code-block:: bash

    # Drop and recreate database
    cat <<EOF | sudo -u postgres psql
    DROP DATABASE sahana
    REVOKE ALL ON DATABASE sahana FROM public;
    ALTER DATABASE sahana OWNER TO sahana;
    \c sahana;
    CREATE EXTENSION postgis;
    GRANT ALL ON geometry_columns TO sahana;
    GRANT ALL ON spatial_ref_sys TO sahana;
    EOF

    # Change directory to web2py root
    cd /srv/web2py

    # Wipe file caches
    rm -rf applications/eden/compiled
    rm -rf applications/eden/databases/*
    rm -rf applications/eden/uploads/*
    rm -rf applications/eden/errors/*
    rm -f applications/eden/config/0000_update_check.py

    # Allow database migration and prepopulation
    sed -i 's/settings.base.migrate = True/settings.base.migrate = False/' applications/eden/models/000_config.py
    sed -i 's/#settings.base.prepopulate = 0/settings.base.prepopulate = 0/' applications/eden/models/000_config.py
