;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2018 Adriano Peluso
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see .
(define-module (gnu services trytond)
#:use-module (gnu services)
#:use-module (gnu services shepherd)
#:use-module (gnu system shadow)
#:use-module (gnu packages admin)
#:use-module (gnu packages databases)
#:use-module (gnu packages tryton)
#:use-module (guix modules)
#:use-module (guix records)
#:use-module (guix build utils)
#:use-module (guix gexp)
#:use-module (ice-9 match)
#:export (trytond-service-type
trytond-configuration
trytond-configuration?
trytond-configuration-trytond
trytond-configuration-postgresql
trytond-configuration-config-file
trytond-configuration-data-directory
trytond-configuration-postgres-role
trytond-configuration-database-name))
;;; Commentary:
;;;
;;; Trytond based services. Mainly Trytond and GNUHealth for now
;;;
;;; Code:
(define %default-trytond-path
"/var/lib/trytond")
(define %default-postgres-role
"tryton")
(define %default-database-name
"tryton")
(define %default-trytond-config
(mixed-text-file "trytond.conf"
"[database]\n"
;; XXX which postgres user shold we use here ?
(string-append "uri = postgresql://"
%default-postgres-role
"@127.0.0.1\n")
"path = " %default-trytond-path))
(define %default-passfile
(mixed-text-file "passfile"
"tryton"))
(define-record-type*
trytond-configuration make-trytond-configuration
trytond-configuration?
(trytond trytond-configuration-trytond ;
(default python-trytond))
(postgresql trytond-configuration-postgresql
(default postgresql))
(locale trytond-configuration-locale
(default "en_US.utf8"))
(config-file trytond-configuration-file
(default %default-trytond-config))
(passfile trytond-passfile
(default %default-passfile))
;; Default: The db folder under the user home directory running trytond.
(data-directory trytond-configuration-data-directory
(default %default-trytond-path))
(postgres-role trytond-configuration-postgres-role
(default %default-postgres-role))
(database-name trytond-configuration-database-name
(default %default-database-name)))
(define %trytond-accounts
(list (user-group (name "trytond") (system? #t))
(user-account
(name "trytond")
(group "trytond")
(system? #t)
(comment "Trytond server user")
(home-directory "/var/empty")
(shell (file-append shadow "/sbin/nologin")))))
(define (setup-role.sql role)
(plain-file "setup-role.sql" (format #f "
DO
$body$
BEGIN
IF NOT EXISTS (
SELECT *
FROM pg_catalog.pg_user
WHERE usename = '~A') THEN
CREATE ROLE \"~A\" LOGIN;
END IF;
END
$body$;
" role role)))
(define (setup-database.sql database role)
(plain-file "setup-database.sql"
(format #f "CREATE DATABASE \"~A\" WITH OWNER = \"~A\";" database role)))
(define (trytond-activation config)
(let* ((postgresql (trytond-configuration-postgresql config))
(role (trytond-configuration-postgres-role config))
(database (trytond-configuration-database-name config))
(data-directory (trytond-configuration-data-directory config)))
#~(begin
(let ((trytond-user (getpwnam "trytond")))
(mkdir-p #$data-directory)
(chown #$data-directory
(passwd:uid trytond-user)
(passwd:gid trytond-user))))))
(define trytond-shepherd-service
(match-lambda
(($ trytond
postgresql
locale
config-file
passfile
data-directory
postgres-role
database-name)
(let* ((setup-role.sql (setup-role.sql postgres-role))
(setup-database.sql (setup-database.sql database-name postgres-role))
(start-script
(program-file "start-trytond"
(with-imported-modules '((guix build utils))
#~(begin
(use-modules (guix build utils))
;; Set up postgres database.
(let ((psql (string-append #$postgresql
"/bin/psql")))
(invoke psql "-U" "postgres"
"-f" #$setup-role.sql)
(system* psql "-U" "postgres"
"-f" #$setup-database.sql))
;; Set up tables.
(let ((trytond-admin (string-append #$trytond
"/bin/trytond-admin"))
(args (append (list "-c" #$config-file
"-d" #$database-name
"--all")
(if #$locale
(list "-l" #$locale)
'()))))
(setenv "TRYTONPASSFILE" #$passfile)
(apply invoke trytond-admin args))
;; Start daemon.
(execl (string-append #$trytond
"/bin/trytond")
(string-append #$trytond
"/bin/trytond")
"-c" #$config-file))))))
(list (shepherd-service
(provision '(trytond))
(documentation "Trytond daemon.")
(requirement '(user-processes loopback postgres))
; TODO #:pid-file
(start #~(make-forkexec-constructor #$start-script
#:log-file "/tmp/QQ"
#:user "trytond"
#:group "trytond"))
(stop #~(make-kill-destructor))))))))
(define trytond-service-type
(service-type (name 'trytond)
(extensions
(list (service-extension shepherd-root-service-type
trytond-shepherd-service)
(service-extension activation-service-type
trytond-activation)
(service-extension account-service-type
(const %trytond-accounts))))
(default-value (trytond-configuration))))