From 710ef746644dbcce8ff56e8bffe4aaecf1db71f2 2013-06-07 10:40:52 From: Lance Edgar Date: 2013-06-07 10:40:52 Subject: [PATCH] Added proper init.d support to Linux dbsync daemon. * Added `--pidfile` argument to `dbsync` command. * Added `configure_dbsync` Fabric command. --- diff --git a/data/etc/init.d/rattail-dbsync_tmpl b/data/etc/init.d/rattail-dbsync_tmpl new file mode 100644 index 0000000000000000000000000000000000000000..fc54146542cc85eb8af20323f145c6ba8275add3 --- /dev/null +++ b/data/etc/init.d/rattail-dbsync_tmpl @@ -0,0 +1,19 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: %(name)s +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: %(desc)s +# Description: Manages the %(desc)s daemon. +### END INIT INFO + +DESC="%(desc)s" +NAME=%(name)s + +PYTHON=%(envdir)s/bin/python +RATTAIL=%(envdir)s/bin/rattail +RATTAIL_ARGS="--config=%(envdir)s/app/dbsync.ini" + +. /var/lib/rattail/init.d/dbsync diff --git a/data/var/lib/rattail/init.d/dbsync b/data/var/lib/rattail/init.d/dbsync new file mode 100644 index 0000000000000000000000000000000000000000..73d88fafe3cd946c95acd7c9a9e3057d8daba6ee --- /dev/null +++ b/data/var/lib/rattail/init.d/dbsync @@ -0,0 +1,132 @@ +#!/bin/sh +# -*- coding: utf-8 -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2012 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU Affero General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# Rattail 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 Affero General Public License for +# more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Rattail. If not, see . +# +################################################################################ + + +# This script is mostly based on the ``/etc/init.d/skeleton`` file from a +# Debian 6 system. + + +DESC=${DESC:-"Rattail Database Synchronizer"} +NAME=${NAME:-"rattail-dbsync"} +SCRIPTNAME=${SCRIPTNAME:-"/etc/init.d/$NAME"} +PIDFILE=${PIDFILE:-"/var/run/rattail/$NAME.pid"} + +PYTHON=${PYTHON:-"/usr/bin/python"} +RATTAIL=${RATTAIL:-"/usr/local/bin/rattail"} +RATTAIL_ARGS=${RATTAIL_ARGS:-""} +DBSYNC_ARGS=${DBSYNC_ARGS:-"--pidfile=$PIDFILE"} + +USER=${USER:-"rattail"} +GROUP=${GROUP:-"rattail"} + + +# Read configuration variable files if present. +[ -r /etc/default/rattail ] && . /etc/default/rattail +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Load the VERBOSE setting and other rcS variables. +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions + + +# +# Function that starts the daemon/service +# +do_start() +{ + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + start-stop-daemon --start --pidfile $PIDFILE --exec $PYTHON --user $USER --test --quiet > /dev/null \ + || return 1 + start-stop-daemon --start --pidfile $PIDFILE --exec $PYTHON --startas $RATTAIL --chuid $USER --group $GROUP --quiet -- \ + $RATTAIL_ARGS dbsync $DBSYNC_ARGS start \ + || return 2 +} + + +# +# Function that stops the daemon/service +# +do_stop() +{ + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + $RATTAIL $RATTAIL_ARGS dbsync $DBSYNC_ARGS stop > /dev/null 2>&1 +} + + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + restart|force-reload) + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac + +: diff --git a/fabfile.py b/fabfile.py index 4a4ba4961f88d3a3bfbdaf6daf8b157d40b65dcf..2fcda520bcd76276a590b6b9c32d110d0a55a469 100644 --- a/fabfile.py +++ b/fabfile.py @@ -96,6 +96,28 @@ def create_user(overwrite=None): sudo('usermod --home /var/lib/rattail --move-home --shell /bin/false rattail') +def configure_rattail_lib(overwrite=None): + """ + Configure basic Rattail "library" files. + """ + + overwrite = get_overwrite(overwrite) + + if not exists('/etc/default/rattail') or overwrite: + put('data/etc/default/rattail', '/etc/default', use_sudo=True) + sudo('chown root: /etc/default/rattail') + + if not exists('/var/lib/rattail'): + create_user(overwrite=True) + + if not exists('/var/lib/rattail/init.d'): + sudo('mkdir /var/lib/rattail/init.d', user='rattail') + + if not exists('/var/run/rattail'): + sudo('mkdir /var/run/rattail') + sudo('chown rattail: /var/run/rattail') + + @task def configure_filemon(name=None, desc=None, envdir=None, overwrite=None): """ @@ -120,16 +142,7 @@ def configure_filemon(name=None, desc=None, envdir=None, overwrite=None): envdir = envdir.strip() or default_envdir overwrite = get_overwrite(overwrite) - - if not exists('/etc/default/rattail') or overwrite: - put('data/etc/default/rattail', '/etc/default', use_sudo=True) - sudo('chown root: /etc/default/rattail') - - if not exists('/var/lib/rattail'): - create_user(overwrite=True) - - if not exists('/var/lib/rattail/init.d'): - sudo('mkdir /var/lib/rattail/init.d', user='rattail') + configure_rattail_lib(overwrite) if not exists('/var/lib/rattail/init.d/filemon') or overwrite: put('data/var/lib/rattail/init.d/filemon', '/var/lib/rattail/init.d', use_sudo=True) @@ -142,6 +155,40 @@ def configure_filemon(name=None, desc=None, envdir=None, overwrite=None): sudo('chown root: {0}'.format(script)) sudo('insserv {0}'.format(script)) - if not exists('/var/run/rattail'): - sudo('mkdir /var/run/rattail') - sudo('chown rattail: /var/run/rattail') + +@task +def configure_dbsync(name=None, desc=None, envdir=None, overwrite=None): + """ + Configure a Rattail Database Synchonizer daemon. + """ + + if name is None: + default_name = 'rattail-dbsync' + name = raw_input("Enter a name for the service [{0}]: ".format(default_name)) + name = name.strip() or default_name + + if desc is None: + default_desc = prettify(name.replace('dbsync', 'database-synchronizer')) + desc = raw_input("Enter a description [{0}]: ".format(default_desc)) + desc = desc.strip() or default_desc + + if envdir is None: + default_envdir = name.replace('-dbsync', '') + default_envdir = default_envdir.replace('-', '.') + default_envdir = '/srv/envs/{0}'.format(default_envdir) + envdir = raw_input("Enter a virtual environment path [{0}]: ".format(default_envdir)) + envdir = envdir.strip() or default_envdir + + overwrite = get_overwrite(overwrite) + configure_rattail_lib(overwrite) + + if not exists('/var/lib/rattail/init.d/dbsync') or overwrite: + put('data/var/lib/rattail/init.d/dbsync', '/var/lib/rattail/init.d', use_sudo=True) + sudo('chown rattail: /var/lib/rattail/init.d/dbsync') + + script = '/etc/init.d/{0}'.format(name) + if not exists(script) or overwrite: + upload_template('data/etc/init.d/rattail-dbsync_tmpl', script, + context=locals(), use_sudo=True, mode=0755) + sudo('chown root: {0}'.format(script)) + sudo('insserv {0}'.format(script)) diff --git a/rattail/commands.py b/rattail/commands.py index 8ebeb2d5d4e33d6ffd84232eed2a849633ea6783..791d01580371d4b944c412488d5b00d76abe70df 100644 --- a/rattail/commands.py +++ b/rattail/commands.py @@ -71,14 +71,18 @@ class DatabaseSyncCommand(commands.Subcommand): stop = subparsers.add_parser('stop', help="Stop service") stop.set_defaults(subcommand='stop') + if sys.platform == 'linux2': + parser.add_argument('-p', '--pidfile', + help="Path to PID file", metavar='PATH') + def run(self, args): from rattail.db.sync import linux as dbsync if args.subcommand == 'start': - dbsync.start_daemon() + dbsync.start_daemon(args.pidfile) elif args.subcommand == 'stop': - dbsync.stop_daemon() + dbsync.stop_daemon(args.pidfile) class FileMonitorCommand(commands.Subcommand): diff --git a/rattail/db/sync/linux.py b/rattail/db/sync/linux.py index 1fb7929e144d6d8a4dcf05ec78a703b5974772b5..ba13b31af0a4119ab2e01aeb6664287522f693ed 100644 --- a/rattail/db/sync/linux.py +++ b/rattail/db/sync/linux.py @@ -26,6 +26,7 @@ ``rattail.db.sync.linux`` -- Database Synchronization for Linux """ +import edbob from edbob.daemon import Daemon from rattail.db.sync import get_sync_engines, synchronize_changes @@ -39,13 +40,28 @@ class SyncDaemon(Daemon): synchronize_changes(engines) -def get_daemon(): - return SyncDaemon('/tmp/rattail_dbsync.pid') +def get_daemon(pidfile=None): + """ + Get a :class:`SyncDaemon` instance. + """ + if pidfile is None: + pidfile = edbob.config.get('rattail.db', 'sync.pid_path', + default='/var/run/rattail/dbsync.pid') + return SyncDaemon(pidfile) -def start_daemon(): - get_daemon().start() +def start_daemon(pidfile=None): + """ + Start the database synchronization daemon. + """ -def stop_daemon(): - get_daemon().stop() + get_daemon(pidfile).start() + + +def stop_daemon(pidfile=None): + """ + Stop the database synchronization daemon. + """ + + get_daemon(pidfile).stop()