Changeset - 710ef746644d
[Not reviewed]
0 3 2
Lance Edgar (lance) - 11 years ago 2013-06-07 10:40:52
lance@edbob.org
Added proper init.d support to Linux dbsync daemon.

* Added `--pidfile` argument to `dbsync` command.
* Added `configure_dbsync` Fabric command.
5 files changed with 239 insertions and 21 deletions:
0 comments (0 inline, 0 general)
data/etc/init.d/rattail-dbsync_tmpl
Show inline comments
 
new file 100644
 
#! /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
data/var/lib/rattail/init.d/dbsync
Show inline comments
 
new file 100644
 
#!/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 <http://www.gnu.org/licenses/>.
 
#
 
################################################################################
 

	
 

	
 
# 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
 

	
 
:
fabfile.py
Show inline comments
 
@@ -75,73 +75,120 @@ def release():
 
    put(os.path.join('dist', filename), '/srv/pypi/{0}'.format(filename))
 
    with cd('/srv/pypi'):
 
        run('rm --recursive --force simple')
 
        run('compoze index')
 

	
 

	
 
@task
 
def create_user(overwrite=None):
 
    """
 
    Create the 'rattail' user account.
 
    """
 

	
 
    overwrite = get_overwrite(overwrite)
 

	
 
    with settings(warn_only=True):
 
        result = run('id rattail')
 

	
 
    if result.return_code: # user doesn't exist
 
        sudo('adduser --system --home /var/lib/rattail --group rattail')
 

	
 
    elif overwrite:
 
        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):
 
    """
 
    Configure a Rattail File Monitor daemon.
 
    """
 

	
 
    if name is None:
 
        default_name = 'rattail-filemon'
 
        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('filemon', 'file-monitor'))
 
        desc = raw_input("Enter a description [{0}]: ".format(default_desc))
 
        desc = desc.strip() or default_desc
 

	
 
    if envdir is None:
 
        default_envdir = name.replace('-filemon', '')
 
        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)
 

	
 
    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)
 
        sudo('chown rattail: /var/lib/rattail/init.d/filemon')
 

	
 
    script = '/etc/init.d/{0}'.format(name)
 
    if not exists(script) or overwrite:
 
        upload_template('data/etc/init.d/rattail-filemon_tmpl', script,
 
                        context=locals(), use_sudo=True, mode=0755)
 
        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))
rattail/commands.py
Show inline comments
 
@@ -50,56 +50,60 @@ Copyright (c) 2010-2012 Lance Edgar <lance@edbob.org>
 

	
 
This program comes with ABSOLUTELY NO WARRANTY.  This is free software,
 
and you are welcome to redistribute it under certain conditions.
 
See the file COPYING.txt for more information.
 
"""
 

	
 

	
 
class DatabaseSyncCommand(commands.Subcommand):
 
    """
 
    Interacts with the database synchronization service; called as ``rattail
 
    dbsync``.
 
    """
 

	
 
    name = 'dbsync'
 
    description = "Manage the database synchronization service"
 

	
 
    def add_parser_args(self, parser):
 
        subparsers = parser.add_subparsers(title='subcommands')
 

	
 
        start = subparsers.add_parser('start', help="Start service")
 
        start.set_defaults(subcommand='start')
 
        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):
 
    """
 
    Interacts with the file monitor service; called as ``rattail filemon``.
 
    This command expects a subcommand; one of the following:
 

	
 
    * ``rattail filemon start``
 
    * ``rattail filemon stop``
 

	
 
    On Windows platforms, the following additional subcommands are available:
 

	
 
    * ``rattail filemon install``
 
    * ``rattail filemon uninstall`` (or ``rattail filemon remove``)
 

	
 
    .. note::
 
       The Windows Vista family of operating systems requires you to launch
 
       ``cmd.exe`` as an Administrator in order to have sufficient rights to
 
       run the above commands.
 

	
 
    .. See :doc:`howto.use_filemon` for more information.
 
    """
 

	
 
    name = 'filemon'
rattail/db/sync/linux.py
Show inline comments
 
@@ -5,47 +5,63 @@
 
#  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 <http://www.gnu.org/licenses/>.
 
#
 
################################################################################
 

	
 
"""
 
``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
 

	
 

	
 
class SyncDaemon(Daemon):
 

	
 
    def run(self):
 
        engines = get_sync_engines()
 
        if engines:
 
            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()
0 comments (0 inline, 0 general)