Python uses a built-in packaging system that allows packages to get installed in a specific folder called "site-packages", loaded at Python startup. Several installers exists for this. One of them being Python itself.
You can also specify arbitrary folders when a Python application starts, making it possible to group Python packages an application uses in a specific location.
To go further, virtualenv allows you to create a new Python interpreter copied from the main one. This creates an isolated Python environment somewhere on your system. In other words, every package that will be installed by a Python interpreter created by virtualenv, will be installed under a specific tree and not interfer with the main Python installation.
Ideally, the Weave application should be installed in a virtualenv-ed Python, in /var/sync for example.
- Apache 2.x
- Python 2.6.x
- mod_wsgi 3.2
- All Python extensions that are available as RPMs. ex: MySQl-python
Weave application structure
The Weave application we are building will be organized in three parts
- an .ini file used by the application to start up. It contains all the configuration needed by the weave server, like the location of the DB, etc.
- a .wsgi file (That's a Python module) used by Apache/mod_wsgi to run the application
- some Python packages. Right now just one called "weave.server"
Proposal 1 : release-based
One simple way to release the weave server is to create a source distribution with everything included, for each version.
This distribution can be installed by the Ops using a distutils-compatible installer like Pip, or the built-in installer Python provides.
The application is installed in the virtualenv-ed Python's site-packages, and the .ini file in /etc/sync.ini, so other apps can use it when needed.
This solution has several advantages:
- it removes the dependency the server to install has with the mercurial repositories: an installation is done with static files.
- it automates the deployment of data files and scripts on the target system.
- the releases can be pushed at PyPI and used by the community with standard installation tools.
- since repository != release, forces the developer to double-check what goes in the distribution
Steps to prepare a release:
- run "python setup.py test" to check all tests pass
- tag the version in HG
- run "python setup.py sdist mozupload"
These steps create a .tar.gz release (done by "sdist") and is placed into a shared folder all servers can see via NFS or HTTP (done by "mozupload".)
The dependencies are also placed into the shared folder, and the installer is configured in order to look for dependencies releases in that folder. This location acts as a vendor repository.
Before the first installation:
- mkdir /var/sync
- cd /var/sync
- virtualenv --no-site-packages --distribute .
Steps to install a release on a server:
- cd /var/sync
- bin/pip install /path/to/releases/dir/WeaveServer1.1.4.tgz --install-options="--find-links=/path/to/releases" --upgrade
What's the strategy to update a node ? Do we want to take it down during the upgrade or do we want to keep it available all the time ?
Ideally, the simplest way would be to have a small app to switch to, that would return X-Weave-Backoff to all requests (or maybe a new header X-Weave-Maintenance) while the real server is being updated.
Proposal 2 : repository-based, like Zamboni
Zamboni uses a repo-based strategy in a virtualenv-ed Python, where the production does "hg pull -rTheRightChangeset" to get everything in the local folder (the app code and the dependencies) and then runs a "pip install" in it.
Dependencies are pushed in a specific vendor repository: http://github.com/jbalogh/zamboni-lib and are pulled like the application.
See also http://jbalogh.github.com/zamboni/topics/packages for more details.
This strategy means that every node has to have an access to the repository, and run hg. The big advantage is that Sync will be like SUMO and AMO, from an OPs point of view.
Although, maintaining the vendor repository is a bit tedious, knowing that the dependencies we will use already have ready-to-install distributions.