Archived
1
0
Fork 0

gnu: mysql: Support custom data dir.

* gnu/services/databases.scm (mysql-configuration): Add datadir property.
* gnu/services/databases.scm (mysql-configuration-file): Replace hard coded
data dir with property from config.
* gnu/services/databases.scm (%mysql-activation): Remove activation, it runs
before PID 1. The data dir may reside on a file system not mounted at this
time.
* gnu/services/databases.scm (mysql-install-shepherd-service): Create service
which replaces the activation. Provide mysql-install.
* gnu/services/databases.scm (mysql-shepherd-service): Move invocation of
mysqld to mysql-start program-file, because the invocation gotten more
complex. Require mysql-install.
* gnu/services/databases.scm (mysql-start): Invoke mysqld only if a lock file
appears.
* gnu/services/databases.scm (mysql-shepherd-services): Prepend the install
service before the normal service.
* gnu/services/databases.scm (mysql-upgrade-wrapper): Increase timeout to
  20s to let the mysql install procedure finish.

Signed-off-by: Marius Bakke <marius@gnu.org>
This commit is contained in:
Ellen Papsch 2021-06-21 15:27:52 +02:00 committed by Marius Bakke
parent 96efebed24
commit c7b266fdf2
No known key found for this signature in database
GPG key ID: A2A06DF2A33A54FA

View file

@ -8,6 +8,7 @@
;;; Copyright © 2019 Robert Vollmert <rob@vllmrt.net> ;;; Copyright © 2019 Robert Vollmert <rob@vllmrt.net>
;;; Copyright © 2020 Marius Bakke <marius@gnu.org> ;;; Copyright © 2020 Marius Bakke <marius@gnu.org>
;;; Copyright © 2021 David Larsson <david.larsson@selfhosted.xyz> ;;; Copyright © 2021 David Larsson <david.larsson@selfhosted.xyz>
;;; Copyright © 2021 Aljosha Papsch <ep@stern-data.com>
;;; ;;;
;;; This file is part of GNU Guix. ;;; This file is part of GNU Guix.
;;; ;;;
@ -532,6 +533,7 @@ applications.")))
(bind-address mysql-configuration-bind-address (default "127.0.0.1")) (bind-address mysql-configuration-bind-address (default "127.0.0.1"))
(port mysql-configuration-port (default 3306)) (port mysql-configuration-port (default 3306))
(socket mysql-configuration-socket (default "/run/mysqld/mysqld.sock")) (socket mysql-configuration-socket (default "/run/mysqld/mysqld.sock"))
(datadir mysql-configuration-datadir (default "/var/lib/mysql"))
(extra-content mysql-configuration-extra-content (default "")) (extra-content mysql-configuration-extra-content (default ""))
(extra-environment mysql-configuration-extra-environment (default #~'())) (extra-environment mysql-configuration-extra-environment (default #~'()))
(auto-upgrade? mysql-configuration-auto-upgrade? (default #t))) (auto-upgrade? mysql-configuration-auto-upgrade? (default #t)))
@ -549,84 +551,132 @@ applications.")))
(define mysql-configuration-file (define mysql-configuration-file
(match-lambda (match-lambda
(($ <mysql-configuration> mysql bind-address port socket extra-content) (($ <mysql-configuration> mysql bind-address port socket datadir extra-content)
(mixed-text-file "my.cnf" "[mysqld] (mixed-text-file "my.cnf" "[mysqld]
datadir=/var/lib/mysql datadir=" datadir "
socket=" socket " socket=" socket "
bind-address=" bind-address " bind-address=" bind-address "
port=" (number->string port) " port=" (number->string port) "
" extra-content " " extra-content "
")))) "))))
(define (%mysql-activation config) (define (mysql-with-install-lock)
"Return an activation gexp for the MySQL or MariaDB database server." "Return a loop function which evals thunk when the install is locked."
(let ((mysql (mysql-configuration-mysql config)) #~(lambda (thunk)
(my.cnf (mysql-configuration-file config))) (let loop ((i 0))
#~(begin (let ((timeout 10)
(use-modules (ice-9 popen) (lock-stat (stat "/var/lib/mysql.lock" #f)))
(guix build utils)) (if (and (not (eq? lock-stat #f))
(let* ((mysqld (string-append #$mysql "/bin/mysqld")) (eq? (stat:type lock-stat) 'regular))
(user (getpwnam "mysql")) (apply thunk '())
(uid (passwd:uid user)) (if (< i timeout)
(gid (passwd:gid user)) (begin
(datadir "/var/lib/mysql") (sleep 1)
(rundir "/run/mysqld")) (loop (+ 1 i)))
(mkdir-p datadir) (throw 'timeout-error
(chown datadir uid gid) "MySQL installation not locked in time!")))))))
(mkdir-p rundir)
(chown rundir uid gid) (define (mysql-start config)
;; Initialize the database when it doesn't exist. "Start mysqld if install lock file appears"
(when (not (file-exists? (string-append datadir "/mysql"))) (program-file
(if (string-prefix? "mysql-" (strip-store-file-name #$mysql)) "mysql-start"
;; For MySQL. (let ((mysql (mysql-configuration-mysql config))
(system* mysqld (my.cnf (mysql-configuration-file config)))
(string-append "--defaults-file=" #$my.cnf) #~(let ((mysqld (string-append #$mysql "/bin/mysqld"))
"--initialize" (with-lock #$(mysql-with-install-lock)))
"--user=mysql") (with-lock (lambda ()
;; For MariaDB. (execl mysqld mysqld
;; XXX: The 'mysql_install_db' script doesn't work directly (string-append "--defaults-file=" #$my.cnf))))))))
;; due to missing 'mkdir' in PATH.
(let ((p (open-pipe* OPEN_WRITE mysqld (define (mysql-shepherd-service config)
(string-append (list (shepherd-service
"--defaults-file=" #$my.cnf) (provision '(mysql))
"--bootstrap" (requirement '(mysql-install))
"--user=mysql"))) (documentation "Run the MySQL server.")
;; Create the system database, as does by 'mysql_install_db'. (start (let ((mysql (mysql-configuration-mysql config))
(display "create database mysql;\n" p) (extra-env (mysql-configuration-extra-environment config))
(display "use mysql;\n" p) (my.cnf (mysql-configuration-file config)))
(for-each #~(make-forkexec-constructor
(lambda (sql) (list #$(mysql-start config))
(call-with-input-file #:user "mysql" #:group "mysql"
(string-append #$mysql:lib "/share/mysql/" sql) #:log-file "/var/log/mysqld.log"
(lambda (in) (dump-port in p)))) #:environment-variables #$extra-env)))
'("mysql_system_tables.sql" (stop #~(make-kill-destructor)))))
"mysql_performance_tables.sql"
"mysql_system_tables_data.sql" (define (mysql-install config)
"fill_help_tables.sql")) "Install MySQL system database and secure the installation."
;; Remove the anonymous user and disable root access from (let ((mysql (mysql-configuration-mysql config))
;; remote machines, as does by 'mysql_secure_installation'. (my.cnf (mysql-configuration-file config))
(display " (datadir (mysql-configuration-datadir config))
(extra-env (mysql-configuration-extra-environment config)))
(program-file
"mysql-install"
(with-imported-modules (source-module-closure
'((ice-9 popen)
(guix build utils)))
#~(begin
(use-modules (ice-9 popen)
(guix build utils))
(let* ((mysqld (string-append #$mysql "/bin/mysqld"))
(user (getpwnam "mysql"))
(uid (passwd:uid user))
(gid (passwd:gid user))
(datadir #$datadir)
(rundir "/run/mysqld"))
(mkdir-p datadir)
(chown datadir uid gid)
(mkdir-p rundir)
(chown rundir uid gid)
;; Initialize the database when it doesn't exist.
(when (not (file-exists? (string-append datadir "/mysql")))
(if (string-prefix? "mysql-" (strip-store-file-name #$mysql))
;; For MySQL.
(system* mysqld
(string-append "--defaults-file=" #$my.cnf)
"--initialize"
"--user=mysql")
;; For MariaDB.
;; XXX: The 'mysql_install_db' script doesn't work directly
;; due to missing 'mkdir' in PATH.
(let ((p (open-pipe* OPEN_WRITE mysqld
(string-append
"--defaults-file=" #$my.cnf)
"--bootstrap"
"--user=mysql")))
;; Create the system database, as does by 'mysql_install_db'.
(display "create database mysql;\n" p)
(display "use mysql;\n" p)
(for-each
(lambda (sql)
(call-with-input-file
(string-append #$mysql:lib "/share/mysql/" sql)
(lambda (in) (dump-port in p))))
'("mysql_system_tables.sql"
"mysql_performance_tables.sql"
"mysql_system_tables_data.sql"
"fill_help_tables.sql"))
;; Remove the anonymous user and disable root access from
;; remote machines, as does by 'mysql_secure_installation'.
(display "
DELETE FROM user WHERE User=''; DELETE FROM user WHERE User='';
DELETE FROM user WHERE User='root' AND DELETE FROM user WHERE User='root' AND
Host NOT IN ('localhost', '127.0.0.1', '::1'); Host NOT IN ('localhost', '127.0.0.1', '::1');
FLUSH PRIVILEGES; FLUSH PRIVILEGES;
" p) " p)
(close-pipe p)))))))) (close-pipe p))))
(call-with-output-file "/var/lib/mysql.lock"
(lambda (p)
(write #t p)))))))))
(define (mysql-shepherd-service config) (define (mysql-install-shepherd-service config)
(list (shepherd-service (list (shepherd-service
(provision '(mysql)) (provision '(mysql-install))
(documentation "Run the MySQL server.") (requirement '(file-systems))
(start (let ((mysql (mysql-configuration-mysql config)) (one-shot? #t)
(extra-env (mysql-configuration-extra-environment config)) (documentation "Install MySQL system database and secure installation.")
(my.cnf (mysql-configuration-file config))) (start #~(make-forkexec-constructor
#~(make-forkexec-constructor (list #$(mysql-install config))
(list (string-append #$mysql "/bin/mysqld") #:log-file "/var/log/mysqld-install.log")))))
(string-append "--defaults-file=" #$my.cnf))
#:user "mysql" #:group "mysql"
#:log-file "/var/log/mysqld.log"
#:environment-variables #$extra-env)))
(stop #~(make-kill-destructor)))))
(define (mysql-upgrade-wrapper mysql socket-file) (define (mysql-upgrade-wrapper mysql socket-file)
;; The MySQL socket and PID file may appear before the server is ready to ;; The MySQL socket and PID file may appear before the server is ready to
@ -636,7 +686,7 @@ FLUSH PRIVILEGES;
"mysql-upgrade-wrapper" "mysql-upgrade-wrapper"
#~(begin #~(begin
(let ((mysql-upgrade #$(file-append mysql "/bin/mysql_upgrade")) (let ((mysql-upgrade #$(file-append mysql "/bin/mysql_upgrade"))
(timeout 10)) (timeout 20))
(begin (begin
(let loop ((i 0)) (let loop ((i 0))
(catch 'system-error (catch 'system-error
@ -668,11 +718,14 @@ FLUSH PRIVILEGES;
(list #$(mysql-upgrade-wrapper mysql socket)) (list #$(mysql-upgrade-wrapper mysql socket))
#:user "mysql" #:group "mysql")))))) #:user "mysql" #:group "mysql"))))))
(define (mysql-shepherd-services config) (define (mysql-shepherd-services config)
(if (mysql-configuration-auto-upgrade? config) (let ((min-services (append (mysql-install-shepherd-service config)
(append (mysql-shepherd-service config) (mysql-shepherd-service config))))
(if (mysql-configuration-auto-upgrade? config)
(append min-services
(mysql-upgrade-shepherd-service config)) (mysql-upgrade-shepherd-service config))
(mysql-shepherd-service config))) min-services)))
(define mysql-service-type (define mysql-service-type
(service-type (service-type
@ -680,8 +733,6 @@ FLUSH PRIVILEGES;
(extensions (extensions
(list (service-extension account-service-type (list (service-extension account-service-type
(const %mysql-accounts)) (const %mysql-accounts))
(service-extension activation-service-type
%mysql-activation)
(service-extension shepherd-root-service-type (service-extension shepherd-root-service-type
mysql-shepherd-services))) mysql-shepherd-services)))
(default-value (mysql-configuration)) (default-value (mysql-configuration))