nixpkgs/nixos/modules/services/web-servers/zope2.nix
Eelco Dolstra 29027fd1e1 Rewrite ‘with pkgs.lib’ -> ‘with lib’
Using pkgs.lib on the spine of module evaluation is problematic
because the pkgs argument depends on the result of module
evaluation. To prevent an infinite recursion, pkgs and some of the
modules are evaluated twice, which is inefficient. Using ‘with lib’
prevents this problem.
2014-04-14 16:26:48 +02:00

258 lines
7.7 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.zope2;
zope2Opts = { name, config, ... }: {
options = {
name = mkOption {
default = "${name}";
type = types.string;
description = "The name of the zope2 instance. If undefined, the name of the attribute set will be used.";
};
threads = mkOption {
default = 2;
type = types.int;
description = "Specify the number of threads that Zope's ZServer web server will use to service requests. ";
};
http_address = mkOption {
default = "localhost:8080";
type = types.string;
description = "Give a port and adress for the HTTP server.";
};
user = mkOption {
default = "zope2";
type = types.string;
description = "The name of the effective user for the Zope process.";
};
clientHome = mkOption {
default = "/var/lib/zope2/${name}";
type = types.string;
description = "Home directory of zope2 instance.";
};
extra = mkOption {
default =
''
<zodb_db main>
mount-point /
cache-size 30000
<blobstorage>
blob-dir /var/lib/zope2/${name}/blobstorage
<filestorage>
path /var/lib/zope2/${name}/filestorage/Data.fs
</filestorage>
</blobstorage>
</zodb_db>
'';
type = types.string;
description = "Extra zope.conf";
};
packages = mkOption {
type = types.listOf types.package;
description = "The list of packages you want to make available to the zope2 instance.";
};
};
};
in
{
###### interface
options = {
services.zope2.instances = mkOption {
default = {};
type = types.loaOf types.optionSet;
example = {
plone01 = {
http_address = "127.0.0.1:8080";
extra =
''
<zodb_db main>
mount-point /
cache-size 30000
<blobstorage>
blob-dir /var/lib/zope2/plone01/blobstorage
<filestorage>
path /var/lib/zope2/plone01/filestorage/Data.fs
</filestorage>
</blobstorage>
</zodb_db>
'';
};
};
description = "zope2 instances to be created automaticaly by the system.";
options = [ zope2Opts ];
};
};
###### implementation
config = mkIf (cfg.instances != {}) {
users.extraUsers.zope2.uid = config.ids.uids.zope2;
systemd.services =
let
createZope2Instance = opts: name:
let
interpreter = pkgs.writeScript "interpreter"
''
import sys
_interactive = True
if len(sys.argv) > 1:
_options, _args = __import__("getopt").getopt(sys.argv[1:], 'ic:m:')
_interactive = False
for (_opt, _val) in _options:
if _opt == '-i':
_interactive = True
elif _opt == '-c':
exec _val
elif _opt == '-m':
sys.argv[1:] = _args
_args = []
__import__("runpy").run_module(
_val, {}, "__main__", alter_sys=True)
if _args:
sys.argv[:] = _args
__file__ = _args[0]
del _options, _args
execfile(__file__)
if _interactive:
del _interactive
__import__("code").interact(banner="", local=globals())
'';
env = pkgs.buildEnv {
name = "zope2-${name}-env";
paths = [
pkgs.python27
pkgs.python27Packages.recursivePthLoader
pkgs.python27Packages."plone.recipe.zope2instance"
] ++ attrValues pkgs.python27.modules
++ opts.packages;
postBuild =
''
echo "#!$out/bin/python" > $out/bin/interpreter
cat ${interpreter} >> $out/bin/interpreter
'';
};
conf = pkgs.writeText "zope2-${name}-conf"
''
%define INSTANCEHOME ${env}
instancehome $INSTANCEHOME
%define CLIENTHOME ${opts.clientHome}/${opts.name}
clienthome $CLIENTHOME
debug-mode off
security-policy-implementation C
verbose-security off
default-zpublisher-encoding utf-8
zserver-threads ${toString opts.threads}
effective-user ${opts.user}
pid-filename ${opts.clientHome}/${opts.name}/pid
lock-filename ${opts.clientHome}/${opts.name}/lock
python-check-interval 1000
enable-product-installation off
<environment>
zope_i18n_compile_mo_files false
</environment>
<eventlog>
level INFO
<logfile>
path /var/log/zope2/${name}.log
level INFO
</logfile>
</eventlog>
<logger access>
level WARN
<logfile>
path /var/log/zope2/${name}-Z2.log
format %(message)s
</logfile>
</logger>
<http-server>
address ${opts.http_address}
</http-server>
<zodb_db temporary>
<temporarystorage>
name temporary storage for sessioning
</temporarystorage>
mount-point /temp_folder
container-class Products.TemporaryFolder.TemporaryContainer
</zodb_db>
${opts.extra}
'';
ctlScript = pkgs.writeScript "zope2-${name}-ctl-script"
''
#!${env}/bin/python
import sys
import plone.recipe.zope2instance.ctl
if __name__ == '__main__':
sys.exit(plone.recipe.zope2instance.ctl.main(
["-C", "${conf}"]
+ sys.argv[1:]))
'';
ctl = pkgs.writeScript "zope2-${name}-ctl"
''
#!${pkgs.bash}/bin/bash -e
export PYTHONHOME=${env}
exec ${ctlScript} "$@"
'';
in {
#description = "${name} instance";
after = [ "network.target" ]; # with RelStorage also add "postgresql.service"
wantedBy = [ "multi-user.target" ];
path = opts.packages;
preStart =
''
mkdir -p /var/log/zope2/
touch /var/log/zope2/${name}.log
touch /var/log/zope2/${name}-Z2.log
chown ${opts.user} /var/log/zope2/${name}.log
chown ${opts.user} /var/log/zope2/${name}-Z2.log
mkdir -p ${opts.clientHome}/filestorage ${opts.clientHome}/blobstorage
mkdir -p ${opts.clientHome}/${opts.name}
chown ${opts.user} ${opts.clientHome} -R
${ctl} adduser admin admin
'';
serviceConfig.Type = "forking";
serviceConfig.ExecStart = "${ctl} start";
serviceConfig.ExecStop = "${ctl} stop";
serviceConfig.ExecReload = "${ctl} restart";
};
in listToAttrs (map (name: { name = "zope2-${name}"; value = createZope2Instance (builtins.getAttr name cfg.instances) name; }) (builtins.attrNames cfg.instances));
};
}