#!/usr/bin/python
# -*- python -*-
# $Id: zope-make-instance,v 1.5 2003/03/13 03:46:06 david Exp $
#
# /usr/sbin/zope-make-instance
#
# Written by David Coe <davidc@debian.org> for the Debian Zope package.
#
# This is a front-end to Zope's inst/make_instance.py, to be used
# to add new instances to Debian Zope installations.
#
# License:
# Copyright 2003 by David Coe for the Debian project.
# Released under the terms of the GNU General Public License, version 2.1.
# Please see the file COPYING.
#

# from old postinst:
"""

		# make the Zope instance owned by www-data
		chown --recursive www-data:www-data /var/lib/zope/var

		if grep --quiet --no-messages "superuser:123" $access 2> /dev/null ; then
			rm --force $access
		fi
		if [ ! -f $access ] ; then
			db_get "zope/admin/username" || true
			username="$RET"
			db_get "zope/admin/password" || true
			password="$RET"
			db_get "zope/admin/password/encoding" || true
			encoding="$RET"
			db_get "zope/admin/restriction" || true
			domains="$RET"
			/usr/sbin/zope-zpasswd     \
				--username="$username" \
				--password="$password" \
				--encoding="$encoding" \
				--domains="$domains"   \
				$access
		fi

		# If we don't have an Data.fs, create one from the new template!
		if [ ! -f /var/lib/zope/var/Data.fs ]; then
			cp /var/lib/zope/var/Data.fs.in /var/lib/zope/var/Data.fs
            chmod 0600 /var/lib/zope/var/Data.fs
		fi


"""


import sys
import os
import getopt

NAME='zope-make-instance'

#
# (These defaults are
# valid for Debian's Zope installation):
#
CONFIGURATION_BASE=os.environ.get('_ZOPECTL__CONFIGURATION_BASE','/etc/zope')
DEFAULT_INSTANCE_BASE=os.environ.get('_ZOPECTL__DEFAULT_INSTANCE_BASE','/var/lib/zope')
LOG_BASE=os.environ.get('_ZOPECTL__LOG_BASE','/var/log/zope')

MANPAGE_ENVIRONMENT = [
    "ENVIRONMENT VARIABLES",
    "  The following environment variables determine where zope-make-instance",
    "  expects to find and put certain things. The default values are appropriate",
    "  for Debian systems, and do not normally need to be changed:",
    "",
    "  _ZOPECTL__CONFIGURATION_BASE  ",
    "    The default is /etc/zope. This tells zope-make-instance where to look",
    "    for the Zope instance definitions. Note that the references to /etc/zope",
    "    elsewhere in this document are implicitly changed when you change this.",
    "  _ZOPECTL__DEFAULT_INSTANCE_BASE  ",
    "    The default is /var/lib/zope. This specifies the directory to use for",
    "    any Zope INSTANCE_HOME that is not specified or not fully-qualified",
    "    in the instance's definition. The instance name or its",
    "    INSTANCE_HOME value will be joined to this path.",
    "  _ZOPECTL__LOG_BASE  ",
    "    The default is /var/log/zope. This specifies the directory to use",
    "    for instance log files that are not fully-qualified in the",
    "    instance's definition. The instance name and the log file name will",
    "    be joined to this path.",
    ]

# z2 does it this way, so I assume it works
here=os.path.join(os.getcwd(), os.path.split(sys.argv[0])[0])
sys.path.insert(0,here)

from zopectl import Logger

MANPAGE_NAME = [
    "NAME",
    "  zope-make-instance - A Zope instance-creation script",
    ]
MANPAGE_SYNOPSIS = [
    "SYNOPSIS",
    "  zope-make-instance [--help] | [option \\.\\.\\.] instance_name",
    ]
MANPAGE_DESCRIPTION = [
    "DESCRIPTION",
    "  zope-make-instance is a utility to create new instances for Zope, compatible",
    "  with zope-z2(8) and zopectl(8). The instance_name specifies the name of",
    "  the new instance's configuration, instance home, and log file directories,",
    "  which are placed under /etc/zope/, /var/lib/zope/, and /var/log/zope/",
    "  respectively (unless overridden; see ENVIRONMENT VARIABLES).",
    "",
    "  Specifically, zope-make-instance does the following things:",
    "",
    "  * creates the instance configuration directory and configuration files", 
    "    (/etc/zope/instance_name/options and /etc/zope/instance_name/environment).",
    "",
    "  * creates the instance's data and user files (it uses Zope's make_instance.py", 
    "    to accomplish those things).",
    "",
    "  * creates the instance's log file directory (/var/log/zope/instance_name/).",
    "",
    "  * if necessary, creates a system user for the new instance (it uses adduser(8)",
    "    to do that).",
    "",
    "  * if requested, adds the Zope-provided example applications to the newly-",
    "    created instance.",
    ]

def usage(logger):
    logger.VERBOSE = 1  # user must see this, and I call logger.info() just because I'm lazy -- no harm as long as we exit after calling usage(), which we do.
    logger.info(' '.join('$Id: zope-make-instance,v 1.5 2003/03/13 03:46:06 david Exp $'.split()[1:3]))
    logger.info('Usage: %s --help | %s instance_name' % (NAME, Logger.usage))
    logger.info('See zope-make-instance(8) for details.')

def help():
    # output the man page sections; suitable for input to txt2man
    for section in (
        MANPAGE_NAME,
        MANPAGE_SYNOPSIS,
        MANPAGE_DESCRIPTION,
        MANPAGE_OPTIONS,
        MANPAGE_SEE_ALSO,
        MANPAGE_EXIT_STATUS,
        MANPAGE_ENVIRONMENT,
        MANPAGE_BUGS,
        MANPAGE_AUTHOR,
        ):
        sys.stdout.write('\n')
        for line in section:
            sys.stdout.write('%s\n' % line)

def subdirectories_of(dir):
    # return a list of directory names (nonrecursive) in dir, excluding "." and ".."
    # no error (empty list) if dir does not exist
    try:
        names = os.listdir(dir) # listdir excludes . and ..
    except:
        names = []
    answer = []
    for name in names:
        if os.path.isdir(os.path.join(dir,name)):
            answer.append(name)
    # answer.sort()
    return answer


MANPAGE_OPTIONS = [
    "OPTIONS",
    "  The following options affect zope-make-instance's behavior:",
    "",
    "  --help  ",
    "    Show this help text; do nothing else, even if an instance_name is",
    "    specified.",
    ] + Logger.MANPAGE_OPTIONS + [
    "  --????  ",
    "    Other options here ???",
    ]
    
def main(argv):
    # we should be called with valid args (per usage())
    # this function returns 0 for success, nonzero for error, so its result can be passed back to sys.exit()
    argc = len(argv)
    global NAME
    if argc:
        NAME = argv[0]

    logger = Logger(NAME)

    try:
        opts, args = getopt.getopt(argv[1:], 'I:', ['help',] + Logger.getopt_options + ['????',])
    except getopt.GetoptError, err:
        logger.error(err)
        usage(logger)
        return 1

    for o,v in opts:
        if o == '--help':
            help()
            return 0
        elif o == '--????':
            logger.error('???? we don\'t yet know what other options we\'ll need.')
        else:
            if not logger.handle_getopt(o, v):
                logger.error('unhandled option "%s" -- please file a bug report')
                return 1

    logger.info(' '.join('$Id: zope-make-instance,v 1.5 2003/03/13 03:46:06 david Exp $'.split()[1:3]))

    if not args:
        usage(logger)
        return 1
    
    specific_instance_names = args[0:]

    if len(specific_instance_names) == 1:
        return try_to_create_instance(specific_instance_names[0], logger)

    if len(specific_instance_names):
        logger.error('You may create only one instance at a time.')
    else:
        logger.error('You must specify an instance name to create.')
    usage(logger)
    return 1


def try_to_create_instance(instance_name, logger):
    # (if it doesn't already exist), 
    # attempt to create the instance; back out if we encounter
    # an error.

    already_existing = []
    for dir in (
        CONFIGURATION_BASE,
        DEFAULT_INSTANCE_BASE,
        LOG_BASE,
        ):
        if instance_name in subdirectories_of(dir):
            already_existing.append(dir)
    if already_existing:
        logger.error('That instance directory already exists in %s.' % ', '.join(already_existing))
        return 1
    del already_existing

    steps_done = []
    for step in (
        create_directories,
        create_ih_data,
        ):
        error = step(instance_name,logger)
        if error:
            steps_done.reverse()
            for undostep in steps_done:
                undostep(instance_name, logger, undo=1)
                
            return error
        else:
            steps_done.append(step)

                
    return 0

def create_directories(instance_name, logger):
    logger.error('create_directories(%s) not not yet implemented' % instance_name)
    return 0

def create_ih_data(instance_name, logger):
    logger.error('create_ih_data(%s) not not yet implemented' % instance_name)
    return 0





#--------------------
MANPAGE_EXIT_STATUS = [
    "EXIT STATUS AND OUTPUT",
    "  zope-make-instance exits with error 0 if no errors were encountered, and",
    "  with error 1 if any errors were encountered. Normal output is written",
    "  to stdout; all error, warning, verbose information, and debugging",
    "  messages are written to stderr.",
    ]
MANPAGE_BUGS = [
    "BUGS",
    "  None known at this time; please report problems to the Debian bug",
    "  tracking system. (Use, e.g., Debian reportbug(1) to report them.)",
    ]
MANPAGE_SEE_ALSO = [
    "SEE ALSO",
    "  zopectl(8), zope-z2(8), zope-zpasswd(8)",
    ]
MANPAGE_AUTHOR = [
    "AUTHOR AND LICENSE",
    "  zope-make-instance was written by David Coe <davidc@debian.org> for the",
    "  Debian project. Feel free to use, copy and modify under the terms of the",
    "  GNU General Public License, version 2.1.",
    ]



if __name__ == '__main__':
    sys.exit(main(sys.argv))

