[Zope-Checkins] CVS: Zope/inst/in - make_instance.py.in:1.1.2.1

Chris McDonough chrism@zope.com
Sun, 29 Sep 2002 17:46:25 -0400


Update of /cvs-repository/Zope/inst/in
In directory cvs.zope.org:/tmp/cvs-serv12114/inst/in

Added Files:
      Tag: chrism-install-branch
	make_instance.py.in 
Log Message:
Updates to the chrism-install-branch:

  - Uses distutils (setup.py) to install all software kept in the
    'lib/python' directory.  This means that the setup.py file
    (which has moved into the inst directory) will need to be maintained
    as new packages, files, and directories are added.  This is
    painful, but it's "the right thing".  It is a departure from the
    past inasmuch as (if this branch is merged into the head at some
    point) when people add stuff to the Zope tree, they will need to
    be careful to update the setup.py file as well.  I know this will become
    incredibly problematic.  To make things easier, it might be
    a reasonable thing to autogenerate a setup.py file based on the
    current state of the Zope tree.  But this is not done yet.
    BTW, many thanks to Matt Hamilton for making the incredible setup.py file
    for all Zope packages.

  - No longer copies the build directory wholesale to create a
    ZOPE_HOME.  Instead 'make install' copies a 'skeleton' directory to the 
    target dir using a custom Python installer and writes out
    files that need post-processing (.in files) to places in the
    hierarchy as needed via the Makefile.  This prevents a lot of
    cruft from reaching the target directory (build directories,
    emacs backup files, etc.)

  - Has an improved 'make instance' implementation which also uses
    a skeleton directory and a similar install.

  - Does away with much cruft in the 'inst' directory lefover from
    band-aids that were produced in the past.

Concessions were made to the realities of moving directories in CVS
for this go-around.  It is desirable to move lots of the current
"top-level" directories (import, var, utilities, Extensions, pcgi, etc.)
into the "skeleton" directory for the kind of install strategy implemented
by this branch, but this is not reasonable as we would divorce these 
packages from updates received on the head if were were to do so now.
If we merge this branch into the head, we will do away with the workarounds
and move the directories.
  


=== Added File Zope/inst/in/make_instance.py.in ===
#!<<PYTHON>>
##############################################################################
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Make an INSTANCE_HOME."""

import sys, os, string, stat, getopt
import sha, binascii
import install, file_from_infile

def main(zopehome, insthome, skel_dir, in_dir, config_location, user, passwd):
    make_insthome(zopehome, insthome, skel_dir, in_dir, config_location)
    write_inituser(insthome, user, passwd)
    print 'Done!  Use "%s/zctl start" to start Zope.' % insthome

def usage():
    print ("""
%s [--insthome=dir] [--zopehome=dir] [--inituser=username:passwd]
      [--config-location=path] [--help]
""" % sys.argv[0])
    print "  Options:"
    print
    print "    --insthome         specifies instance home target directory"
    print "    --zopehome         specifies location of Zope software"
    print "    --inituser         specifies username and password for"
    print "                       inituser file written to insthome"
    print "    --config-location  specifies configuration file location"
    print "                       (default: 'zope.conf')"
    print "  If 'zopehome', 'insthome', or 'inituser' are not specified as"
    print "  options, they are gathered interactively."

def get_zopehome(default):
    print
    print "Please supply the directory which contains the base"
    print "Zope software (the 'ZOPE_HOME').  If you've installed Zope"
    print "via the ./configure, make, make install process, this should"
    print "be the directory you specified via the '--prefix' option to"
    print "'configure'.  If you are unsure, accept the default."
    while 1:
        print
        home = raw_input('Zope home [default: %s]: ' % default)
        if home == '':
            home = default
        else:
            home = os.path.abspath(os.path.expanduser(home))
        if not os.path.exists(home):
            print '%s does not exist.' % `home`
        elif not os.path.isdir(home):
            print '%s is not a directory.' % `home`
        else:
            return home
    
def get_insthome(zopehome):
    print
    print 'An instance home is a directory from which you will run Zope.'
    print 'Each instance home contains its own data and configuration but'
    print 'shares "base" Zope software from %s.' % zopehome
    while 1:
        print
        insthome = raw_input('Instance home [default: %s]: ' % zopehome)
        if insthome == '':
            insthome = zopehome
        else:
            insthome = os.path.abspath(os.path.expanduser(insthome))
        if not os.path.exists(insthome):
            print '%s does not exist.' % `insthome`
            make_insthome = raw_input('Shall I create it [y]? ')
            if make_insthome and make_insthome[0] not in 'yY': continue
            try:
                os.makedirs(insthome, 0775)
            except:
                print 'Unable to create %s' % `insthome`
            else:
                print 'Created.'
                return insthome
        elif not os.path.isdir(insthome):
            print '%s is not a directory.' % `insthome`
        else:
            print "%s exists, so I left it alone." % `insthome`
            return insthome

def make_insthome(zopehome, insthome, skel_dir, in_dir, config_location):
    try:
        if not os.path.exists(insthome):
            os.makedirs(insthome, 0775)
        elif not os.path.isdir(insthome) or os.path.isfile(insthome):
            print (
                '%s directory exists and is a file. Giving up.' % insthome
                )
            sys.exit(127)
    except:
        print 'Could not create directory %s!  Giving up.' % insthome
        sys.exit(127)
    # Make skeleton
    install.main(skel_dir, insthome, symlinks=0, omitpattern="^CVS$")
    # create files from .in files
    map = {'PYTHON':sys.executable,
           'BASE_DIR':zopehome,
           'CONFIG_LOCATION':config_location}
    file_from_infile.main(os.path.join(in_dir, 'zctl.in'),
                          os.path.join(insthome, 'zctl'), map, 0)

def write_inituser(insthome, username, passwd):
    ac_path=os.path.join(insthome, 'inituser')
    acfile=open(ac_path, 'w')
    acfile.write('%s:%s'%(username,generate_sha_passwd(passwd)))
    acfile.close()
    os.chmod(ac_path, 0644)

def get_inituser(home, insthome):
    import getpass
    print 'Please choose a username and password for the initial user.'
    print 'These will be the credentials you use to initially manage'
    print 'your %s Zope instance.' % insthome
    print
    user = raw_input("Username: ")
    if user == '':
        return

    while 1:
        passwd = getpass.getpass("Password: ")
        verify = getpass.getpass("Verify password: ")
        if verify == passwd:
            break
        else:
            passwd = verify = ''
            print "Password mismatch, please try again..."

    return user, passwd

def generate_sha_passwd(password,):
    return '{SHA}' + binascii.b2a_base64(sha.new(password).digest())[:-1]

if __name__=='__main__':
    zopehome = None
    insthome = None
    user = None
    passwd = None
    config_location = 'zope.conf'
    try:
        longopts = ["zopehome=", "insthome=", "inituser=", "help",
                    "config-location="]
        opts, args = getopt.getopt(sys.argv[1:], "h", longopts)
    except getopt.GetoptError, v:
        print v
        usage()
        sys.exit(0)
    for o, a in opts:
        if o in ('-h', '--help'):
            usage()
            sys.exit()
        if o == '--zopehome':
            zopehome = a
        if o == '--insthome':
            insthome = os.path.abspath(os.path.expanduser(a))
        if o == '--inituser':
            tup=a.split(':', 1)
            msg = ('--inituser must be specified in the format'
                   ' "username:password"')
            if len(tup) != 2:
                print msg
                usage()
                sys.exit(127)
            user, passwd = tup
            if not user or not passwd:
                print msg
                usage()
                sys.exit(127)
        if o == '--config-location':
            config_location = a
    abspath = os.path.abspath
    dirname = os.path.dirname
    split = os.path.split
    if zopehome is None:
        zopehome=get_zopehome(abspath(split(split(sys.argv[0])[0])[0]))
    if insthome is None:
        insthome = get_insthome(zopehome)
    if __name__ == '__main__':
        here = os.path.abspath(os.path.dirname(sys.argv[0]))
    else:
        here = os.path.abspath(os.path.dirname(__file__))
    if user is None or passwd is None:
        user, passwd = get_inituser(zopehome, insthome)
    # guess about skeleton and in directories.
    skel_dir = os.path.join(here, 'skel')
    in_dir = os.path.join(here, 'in')
    main(zopehome, insthome, skel_dir, in_dir, config_location, user, passwd)