CVS User Account cvsuser
Fri Oct 27 10:35:16 PDT 2006
Log Message:
-----------
Delete long-deprecated Slony-I setup script

Tags:
----
REL_1_2_STABLE

Removed Files:
-------------
    slony1-engine/tools:
        slony_setup.pl

-------------- next part --------------
--- tools/slony_setup.pl
+++ /dev/null
@@ -1,1236 +0,0 @@
-#!/usr/bin/env perl -w
-
-# Copyright (c) 2003-2004, PostgreSQL Global Development Group
-
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose, without fee, and without a written agreement
-# is hereby granted, provided that the above copyright notice and this
-# paragraph and the following two paragraphs appear in all copies.
-
-# IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
-# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
-# LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
-# DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-# THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
-# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-# AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-# ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
-# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-
-=head1 NAME
-
-slony_setup.pl - A script for setting up Slony-I PostgreSQL replication
-
-=head1 DESCRIPTION
-
-Slony-I setup is intended to facilitate the installation of the Slony-I
-replication engine.  Basically it asks a bunch of questions and creates
-a shell (bash) script which can then be run on the master and also
-provides the commands to be run on slaves.
-
-The initial goal for slony_setup.pl is to allow a PostgreSQL DBA to start
-with:
-
-1.  A PostgreSQL master host that needs replication.
-
-2.  N slaves hosts.
-
-3.  Every PostgreSQL host allows authenticated connections from all
-participating hosts over TCP/IP.
-
-4.  A "slony" PostgreSQL superuser and a "slony" system user on every
-participating host.
-
-Given the above, the setup script should then create the necessary
-script to effect complete Slony-I replication.
-
-=head1 BUGS
-
-Several, I'm sure...
-
-=head1 TODO
-
-Add support for running all commands to slaves over ssh.
-
-Allow the script to execute the commands in perl at the end of
-the script, thereby removing the 'feature' of writing out a bash
-script to be executed.
-
-Add more checking to see if databases, tables, users, groups, and
-languages are setup on each slave, that the sysids match, etc.
-
-Uninstall option for individual nodes.
-
-Figure out the dependencies when not all tables in a given database are
-selected.
-
-Cascading of slaves.
-
-Add support for generating failover scripts.
-
-Add support for detecting errors in piped commands in the shell script.
-Sometimes a "pg_dump | psql" will generate errors on the psql side.  These
-are not always fatal, but should be looked at.
-
-Add support for detecting pg_dump 8.0 on the master and disabling dollar
-quoting if the slave is less than 8.0.
-
-Add support for detecting version of slaves to see if they satisfy?
-
-=head1 CHANGELOG
-
-2004-06-18
-
-Aesthetic/maintainability fixes: change subroutines to take anon
-hashes, use here docs.
-
-by David Fetter
-
-2004-06-18
-
-Prompt for "working target directory" where setup script and dump scripts
-are written by slony_setup.pl.  This is also where the bash script and slon
-will write.
-Detect $TMP variables and use them if they're set.
-Added usage argument.
-More cosmetic fixes.
-
-2004-05-28
-
-Added support for replicating sequences.
-Made the queries that get the table names and sequence names use quote_ident()
-Fixed some cosmetic issues.
-
-2004-05-06
-
-Initial CVS import
-
-=head1 AUTHOR
-
-Thoughts?  Send them to Daniel Ceregatti (AKA Primer in #postgresql on
-irc.freenode.net) at vi at sh dot nu.
-
-=cut
-
-use strict;
-eval {
-    require Data::Dumper;
-};
-
-my $dumper = ($@) ? 0 : 1;
-
-$| = 1;
-
-$SIG{TERM} = \&clean_up;
-$SIG{INT} = \&clean_up;
-$SIG{KILL} = \&clean_up;
-
-##################################################
-#                                                #
-# Print out usage for variations of "-h" and "?" #
-#                                                #
-##################################################
-
-if (($ARGV[0]) && ($ARGV[0] =~ m/-h|--h|\?/)) {
-    print <<TEXT;
-usage: perl slony_setup.pl
-
-Run this as the user you plan to run Slony-I.  For now, this script
-takes no arguments.  Just run it.
-
-If you want to know more about it, run the following command:
-
-perldoc ./slony_setup.pl
-
-TEXT
-    exit -1;
-}
-
-###############################################################
-#                                                             #
-# Create a temporary working directory and set some variables #
-#                                                             #
-###############################################################
-
-my $exitcode = -1;
-my $tmpbase = $ENV{'TMPDIR'} || $ENV{'TEMP'} || $ENV{'TMP'} || "/tmp";
-my $tmpdir = "$tmpbase/slony.$$";
-my $targetdir = $ENV{'HOME'} || $tmpbase;
-mkdir $tmpdir,0700 or death(message => "Can't create temporary working directory: $!");
-my $pgpassfile = $ENV{'HOME'} . "/.pgpass";
-my $pgpassbackup = "$tmpdir/.pgpass.backup";
-
-#########################################
-#                                       #
-# Make sure we have the correct version #
-#                                       #
-#########################################
-
-chomp(my $psql = `which psql`);
-if (!$psql){
-  print "\n\n * * * pgsql not found in your path * * *\n\n";
-  clean_up();
-  exit;
-}
-my $pager = $ENV{'PAGER'} || 'less' || 'more';
-
-####################
-#                  #
-# Print the README #
-#                  #
-####################
-
-my $text = <<TEXT;
-Slony-I setup will guide you through the process of setting up the Slony-I
-replication system.  Some presumptions will be made in order to keep this
-installation process as simple as possible.  The default values may be over-
-ridden.  Slony-I requires, and the install process presumes that:
-
-1.  Your master server listens on TCP/IP.
-2.  At least one slave listens on TCP/IP.
-3.  You have a "slony" PostgreSQL superuser (createuser -a -d -P slony) as well
-   as a "slony" system user on all participating hosts.
-4.  Each host participating in replication allows every other host that is
-   participating in the replication to connect and authenticate to PostgreSQL
-   as the "slony" PostgreSQL user over TCP/IP.
-5.  Slony-I binaries have been installed on all participating hosts.
-
-Optional, but helpful:
-
-1.  The user that will run the Slony-I processes on all hosts has remote ssh
-   access from the host slony_setup.sh runs.
-
-You will be prompted for the following information:
-
-1.  The hostname of the master server.
-2.  The hostnames of slave servers.
-3.  Authentication credentials for all hosts.
-
-Once this information is obtained, the script will then check connectivity to
-these hosts, look for available databases, and prompt for addition of these
-databases and their tables into replication.
-
-When all the information needed to complete the setup is obtained, the process
-will then prompt the user to run the commands to finalize the installation.
-The user need not finalize the installation at that time, for that the process will
-write a shell script to a file that can then be run to create the replication
-without running slony_setup.pl again.
-TEXT
-
-pager(text => $text);
-
-print "\nAre you ready to proceed? (Y|n) ";
-clean_up() if ! get_one_bool();
-
-#############################
-#                           #
-# Set the working directory #
-#                           #
-#############################
-
-$text = <<TEXT;
-The working target directory is where this script will store files
-that it creates.  The working target directory is currently set to
-'$targetdir'.  If this directory should not be used, you should answer
-"no" to the following question and input a new directory.  This
-directory should be writable by the script.
-TEXT
-
-pager(text => $text);
-
-print "\nThe target directory is '$targetdir'.  Is this OK? (Y/n)";
-if (!get_one_bool()) {
-    $targetdir = "";
-    while (!$targetdir) {
-        print "\nEnter the full path to the working target directory: ";
-        my $temp = <>;
-        chomp ($temp);
-        $targetdir = $temp if $temp;
-        if (!$targetdir) {
-            print "No target directory specified.  Select another directory.\n";
-            $targetdir = "";
-        } elsif (! -d $targetdir) {
-            print "The target directory '$targetdir' is not a directory.  Select another directory.\n";
-            $targetdir = "";
-        } elsif (! -w $targetdir) {
-            print "The target directory '$targetdir' is not writable.  Select another directory.\n";
-            $targetdir = "";
-        }
-    }
-    print "\nThe target directory is now '$targetdir'.\n";
-}
-
-#######################################
-#                                     #
-# Global filenames                    #
-#                                     #
-#######################################
-
-my $slony_dump = "$targetdir/slony_dump";
-my $slony_master_setup = "$targetdir/slony_master_setup.sh";
-my $setup_log = "$targetdir/slony_setup.log";
-my $outlog = "$targetdir/slon-DATABASENAME.out";
-my $errlog = "$targetdir/slon-DATABASENAME.err";
-
-
-#######################################
-#                                     #
-# Back up the ~/.pgpass, if it exists #
-#                                     #
-#######################################
-
-if (-f $pgpassfile) {
-    backup_file(
-      orig => $pgpassfile
-    , backup => $pgpassbackup
-    );
-}
-
-########################################################
-#                                                      #
-# Check for a previous failed run and import that data #
-#                                                      #
-########################################################
-
-my %data;
-my $cache = 0;
-
-if (-f $slony_dump) {
-    print "\nA previous instance of slony_setup data was detected.\n";
-    print "Do you want to import this data? (Y|n) ";
-    if (get_one_bool()) {
-        open F, $slony_dump and do {
-            my $text = join ('', <F>);
-            close F;
-            my $VAR1;
-            eval $text;
-            %data = %{$VAR1};
-            $cache = 1;
-        }
-    }
-}
-
-##########################
-#                        #
-# Other global variables #
-#                        #
-##########################
-
-my $which = "master";
-my $slavenumber = 0;
-my $slave_commands = "";
-my $same = 0;
-
-#######################################
-#                                     #
-# Loop until we get good connections. #
-#                                     #
-#######################################
-
-while (1) {
-    if ($same == 0 && ($cache == 0 || !$data{$which})) {
-        $data{$which}{'hostname'} = "none";
-        $data{$which}{'port'} = 5432;
-        $data{$which}{'databasename'} = "template1";
-        $data{$which}{'username'} = "slony";
-        $data{$which}{'password'} = "";
-        $same=1
-    }
-
-    ##########################################
-    #                                        #
-    # Ask the user about the master database #
-    #                                        #
-    ##########################################
-
-    get_info(which => $which);
-
-    #######################
-    #                     #
-    # Test the connection #
-    #                     #
-    #######################
-    my ($ret) = test_conn(which => $which);
-
-    ####################################################
-    #                                                  #
-    # Prompt the user to retry if the connection fails #
-    #                                                  #
-    ####################################################
-
-    if ($ret != 0) {
-        print "\n\nConnection to $which failed.  Try again? (Answering NO will abort) (Y|n) ";
-        clean_up() if ! get_one_bool();
-    } else {
-        print "\n\n$which connection successful\n";
-	if (check_version(which => $which))
-        {
-          print "You need to upgrade PostgreSQL on $data{$which}{'hostname'}";
-	  clean_up();
-        }
-        get_databases(which => $which);
-        $slavenumber++;
-        $which = "slave_$slavenumber";
-        $same = 0;
-        if ($slavenumber > 1) {
-            print "\nAdd another slave? (Y|n) ";
-            last if (!get_one_bool());
-        }
-    }
-}
-
-#
-# Ask the user if all databases in the "instance" should be replicated
-#
-
-print "\nShould all databases on '$data{'master'}{'hostname'}' be replicated? (Y|n) ";
-
-#
-# Loop over the databases and prompt for addition into replication
-#
-
-if (!get_one_bool()) {
-    print "\nAdd databases to replication:\n";
-    foreach my $database (keys %{$data{'master'}{'databases'}}) {
-        print " Add $database? (Y|n) ";
-        if (!get_one_bool()) {
-            delete $data{'master'}{'databases'}{$database};
-        }
-    }
-}
-
-#
-# Loop over the databases and ask the user if all tables in the database
-# should be replicated.  We ask this here because the user may want to
-# replicate all databases but not all tables.
-#
-
-foreach my $database (keys %{$data{'master'}{'databases'}}) {
-    get_tables(which => 'master', database => $database);
-    get_sequences(which => 'master', database => $database);
-
-    #
-    # Loop over the tables and prompt for addition
-    #
-    
-    print "\nShould all tables in the '$database' database be replicated?
-(Note: the script cannot guarantee the schema will be properly
- installed on slaves if you choose No) (Y|n) ";
-    
-    if (get_one_bool()) {
-        $data{'master'}{'databases'}{$database}{'all_tables'} = 1;
-    } else {
-        print "\nAdd tables in database $database to replication:\n";
-        foreach my $table (keys %{$data{'master'}{'databases'}{$database}{'tables'}}) {
-            print " Add $database.$table? (Y|n) ";
-            delete $data{'master'}{'databases'}{$database}{'tables'}{$table} if ! get_one_bool();
-        }
-    }
-
-    #
-    # Loop over the sequences and prompt for addition
-    #
-    
-    print "\nShould all sequences in the '$database' database be replicated? (Y|n) ";
-    
-    if (get_one_bool()) {
-        $data{'master'}{'databases'}{$database}{'all_sequences'} = 1;
-    } else {
-        print "\nAdd sequences in database $database to replication:\n";
-        foreach my $sequence (keys %{$data{'master'}{'databases'}{$database}{'sequences'}}) {
-            print " Add $sequence? (Y|n) ";
-            delete $data{'master'}{'databases'}{$database}{'sequences'}{$sequence} if ! get_one_bool();
-        }
-    }
-}
-
-#
-# Ensure that if no tables were added manually that the database isn't replicated
-#
-
-foreach my $database (keys %{$data{'master'}{'databases'}}) {
-    delete $data{'master'}{'databases'}{$database} if ! keys %{$data{'master'}{'databases'}{$database}{'tables'}};
-}
-
-#
-# Check all tables for a "primary key" ?
-#
-
-my $summary = "\n\nSummary:";
-
-foreach my $datum (keys %data) {
-    
-    $summary .= <<TEXT;
-$datum Hostname: $data{$datum}{'hostname'}
-$datum Port:     $data{$datum}{'port'}
-$datum Username: $data{$datum}{'username'}
-$datum Password: VALIDATED
-
-TEXT
-
-}
-
-foreach my $database (keys %{$data{'master'}{'databases'}}) {
-    $summary .=  "\n\nThe following tables in database $database will be replicated:\n\n";
-    foreach my $table (keys %{$data{'master'}{'databases'}{$database}{'tables'}}) {
-        $summary .=  "    $table\n";
-    }
-    $summary .=  "\n\nThe following sequences in database $database will be replicated:\n\n";
-    foreach my $sequence (keys %{$data{'master'}{'databases'}{$database}{'sequences'}}) {
-        $summary .=  "    $sequence\n";
-    }
-    $summary .=  "\n";
-}
-
-pager(text => $summary);
-
-print "Save? (Y|n) ";
-
-#
-# Get the users on the master
-#
-
-get_users("master");
-
-get_groups("master");
-
-#
-# Create an array with slave info
-#
-
-foreach my $slave (keys %data) {
-    next if $slave eq "master";
-    $slave =~ m/slave_(\d+)/;
-    $data{'slaves'}{$1} = $data{$slave};
-}
-
-if (get_one_bool()) {
-
-    #
-    # Make this a variable!!  FIXME!!
-    #
-  open F, ">$slony_master_setup" or death( message => "Can't open $slony_master_setup: $!");
-    print F "#/bin/bash\n\n";
-    
-    #
-    # Start by adding the complete uninstall option
-    #
-
-    $data{'master'}{'coninfo'} = "'dbname=DATABASE_NAME_HOLDER host=" . $data{'master'}{'hostname'} .
-        " port=" . $data{'master'}{'port'} .
-        " user=" . $data{'master'}{'username'};
-    $data{'master'}{'coninfo'} .= " password=" . $data{'master'}{'password'} if $data{'master'}{'password'} !~ /(\s+|\*)/;
-    $data{'master'}{'coninfo'} .= "'";
-
-    my $all_conn = "slonik <<_EOF_ 2>> $setup_log 1>> $setup_log\n\tcluster name = T1;
-    node 1 admin conninfo = " . $data{'master'}{'coninfo'} . ";\n";
-
-    foreach my $slave (sort keys %{$data{'slaves'}}) {
-        $data{'slaves'}{$slave}{'coninfo'} = "'dbname=DATABASE_NAME_HOLDER host=" . $data{'slaves'}{$slave}{'hostname'} .
-            " port=" . $data{'slaves'}{$slave}{'port'} .
-            " user=" . $data{'slaves'}{$slave}{'username'};
-        $data{'slaves'}{$slave}{'coninfo'} .= " password=" . $data{'slaves'}{$slave}{'password'} if $data{'slaves'}{$slave}{'password'} !~ /(\s+|\*)/;
-        $data{'slaves'}{$slave}{'coninfo'} .= "'";
-        $all_conn .= "\tnode " . ($slave + 1) . " admin conninfo = " . $data{'slaves'}{$slave}{'coninfo'} . ";\n";
-    }
-    
-    print F "if [ x\$1 = \"xuninstall\" ]\nthen\n";
-    
-    foreach my $database (keys %{$data{'master'}{'databases'}}) {
-        my $conn = $all_conn;
-        $conn =~ s/DATABASE_NAME_HOLDER/$database/g;
-        print F $conn . "\ttry {
-        uninstall node (id = 1);
-    }
-    on error {
-        echo 'Could not uninstall Slony-I on node 1';
-        exit -1;
-    }
-";
-
-        foreach my $slave (sort keys %{$data{'slaves'}}) {
-            print F "\ttry {
-        uninstall node (id = " . ($slave + 1) . ");
-    }
-    on error {
-        echo 'Could not uninstall Slony-I on node " . ($slave + 1) . "';
-        exit -1;
-    }
-";
-        }
-    
-        print F "\techo 'Slony-I successfully uninstalled on database $database';
-_EOF_
-
-if [ \$? -ne 0 ]
-then
-    echo Errors were detected.  Please review $setup_log.  Uninstall halted.
-    exit -1
-fi
-
-";
-    
-    }
-
-    print F "exit 0
-fi
-
-rm -f ~/.pgpass
-rm -f $setup_log
-
-";
-
-    #
-    # Create the new ~/.pgpass
-    #
-    open FH, $pgpassfile or death( message => "Can't open $pgpassfile: $!");
-    while (<FH>) {
-        chomp;
-        print F "echo \"$_\" >> ~/.pgpass\n";
-    }
-    close FH;
-    print F "\nchmod 600 ~/.pgpass\n\n";
-
-    foreach my $slave (keys %{$data{'slaves'}}) {
-        #
-        # Create all the users that exist on the master database on each slave, except the
-        # PostgreSQL and Slony-I users
-        #
-        foreach my $user (sort keys %{$data{'master'}{'users'}}) {
-            print F "$psql" .
-                " -h " . $data{'slaves'}{$slave}{'hostname'} .
-                " -p " . $data{'slaves'}{$slave}{'port'} .
-                " -U " . $data{'slaves'}{$slave}{'username'} .
-                " -d template1" .
-                " -c \\\n\"insert into pg_shadow (usename, usesysid, usecreatedb, usesuper, usecatupd, passwd, valuntil, useconfig) values (\\\n" .
-                "'" . $data{'master'}{'users'}{$user}{'usename'} . "'," .
-#                "'" . $data{'master'}{'users'}{$user}{'usesysid'} . "'," .
-                "(select case when max (usesysid) + 1 < 100 then 100 else max (usesysid) + 1 end from pg_shadow),\\\n" .
-                "'" . $data{'master'}{'users'}{$user}{'usecreatedb'} . "'," .
-                "'" . $data{'master'}{'users'}{$user}{'usesuper'} . "'," .
-                "'" . $data{'master'}{'users'}{$user}{'usecatupd'} . "'," .
-                "'" . $data{'master'}{'users'}{$user}{'passwd'} . "'," .
-                (($data{'master'}{'users'}{$user}{'valuntil'}) ? "'" . $data{'master'}{'users'}{$user}{'valuntil'} . "'": "null") . "," .
-                (($data{'master'}{'users'}{$user}{'useconfig'}) ? "'" . $data{'master'}{'users'}{$user}{'useconfig'} . "'": "null") . ")\"" .
-                " 2>> $setup_log 1>> $setup_log\n";
-		generate_abend("Adding user $user on slave $slave");
-               }
-        #
-        # Create all the groups that exist on the master database on each slave
-        #
-        foreach my $group (sort keys %{$data{'master'}{'groups'}}) {
-            print F "$psql" .
-                " -h " . $data{'slaves'}{$slave}{'hostname'} .
-                " -p " . $data{'slaves'}{$slave}{'port'} .
-                " -U " . $data{'slaves'}{$slave}{'username'} .
-                " -d template1" .
-                " -c \\\n\"insert into pg_group (groname, grosysid, grolist) values (\\\n" .
-                "'" . $data{'master'}{'groups'}{$group}{'groname'} . "'," .
-                "'" . $data{'master'}{'groups'}{$group}{'grosysid'} . "'," .
-                "'" . $data{'master'}{'groups'}{$group}{'grolist'} . "')\"" .
-                " 2>> $setup_log 1>> $setup_log\n";
-		generate_abend("Creating group $group on slave $slave");
-        }
-        #
-        # Make sure plpgsql is created in template1 on all slaves
-        #
-        print F "createlang" .
-            " -h " . $data{'slaves'}{$slave}{'hostname'} .
-            " -p " . $data{'slaves'}{$slave}{'port'} .
-            " -U " . $data{'slaves'}{$slave}{'username'} .
-            " plpgsql template1" .
-            " 2>> $setup_log 1>> $setup_log\n";
-	generate_abend("Creating language plpgsql on slave $slave");
-        foreach my $database (keys %{$data{'master'}{'databases'}}) {
-            #
-            # Create the databases to be replicated on all slaves
-            #
-            print F "createdb" .
-                " -h " . $data{'slaves'}{$slave}{'hostname'} .
-                " -p " . $data{'slaves'}{$slave}{'port'} .
-                " -U " . $data{'slaves'}{$slave}{'username'} .
-                " -O " . $data{'master'}{'databases'}{$database}{'owner'} .
-                " $database 2>> $setup_log 1>> $setup_log\n";
-		 generate_abend("Create database $database on slave $slave");
-            #
-            # Use the command that copies the entire schema at once, as this assures us
-            # that dependencies will be done in order
-            #
-            if ($data{'master'}{'databases'}{$database}{'all_tables'} == 1) {
-                print F "pg_dump" .
-                    " -h " . $data{'master'}{'hostname'} .
-                    " -p " . $data{'master'}{'port'} .
-                    " -U " . $data{'master'}{'username'} .
-                    " -s " . $database .
-                    " 2>> $setup_log | \\\n" .
-                    "psql" .
-                    " -h " . $data{'slaves'}{$slave}{'hostname'} .
-                    " -p " . $data{'slaves'}{$slave}{'port'} .
-                    " -U " . $data{'slaves'}{$slave}{'username'} .
-                    " -d " . $database .
-                    " 2>> $setup_log 1>> $setup_log\n";
-		generate_abend("Create schema for $database on slave $slave");
-            #
-            # Else, do it the hard way, and hope no dependencies are broken
-            #
-            } else {
-                foreach my $table (keys %{$data{'master'}{'databases'}{$database}{'tables'}}) {
-                    my ($schema, $tablename) = split (/\./, $table);
-                    print F "pg_dump" .
-                        " -h " . $data{'master'}{'hostname'} .
-                        " -p " . $data{'master'}{'port'} .
-                        " -U " . $data{'master'}{'username'} .
-                        " -n " . $schema .
-                        " -t " . $tablename .
-                        " -s " . $database .
-                        " 2>> $setup_log | \\\n" .
-                        "psql" .
-                        " -h " . $data{'slaves'}{$slave}{'hostname'} .
-                        " -p " . $data{'slaves'}{$slave}{'port'} .
-                        " -U " . $data{'slaves'}{$slave}{'username'} .
-                        " -d " . $database .
-                        " 2>> $setup_log 1>> $setup_log\n";
-		generate_abend("Create table $table in schema $schema on slave $slave");
-                }
-            }
-        }
-    }
-    
-    foreach my $database (keys %{$data{'master'}{'databases'}}) {
-        my $conn = $all_conn;
-        $conn =~ s/DATABASE_NAME_HOLDER/$database/g;
-        print F "$conn\ttry {
-        echo 'Initializing the cluster';
-        init cluster (id = 1, comment = 'Node 1');
-    }
-    on error {
-        echo 'Could not initialize the cluster!';
-        exit -1;
-    }
-    echo 'Database cluster initialized as Node 1';";
-
-        foreach my $slave (sort keys %{$data{'slaves'}}) {
-            print F "
-    try {
-        echo 'Storing node " . ($slave + 1) . "';
-        store node (id = " . ($slave + 1) . ", comment = 'Node " . ($slave + 1) . "');
-    }
-    on error {
-        echo 'Could not create Node " . ($slave + 1) . "!';
-        exit -1;
-    }
-    echo 'Node " . ($slave + 1) . " created';";
-        }
-
-        print F "
-    try {
-        echo 'Creating store paths';\n";
-        foreach my $slave (keys %{$data{'slaves'}}) {
-            my $conn = $data{'master'}{'coninfo'};
-            $conn =~ s/DATABASE_NAME_HOLDER/$database/g;
-            print F "\t\tstore path (server = 1, client = " . ($slave + 1) . ", conninfo = " . $conn . ");\n";
-        }
-        
-        foreach my $slave (keys %{$data{'slaves'}}) {
-            my $conn = $data{'slaves'}{$slave}{'coninfo'};
-            $conn =~ s/DATABASE_NAME_HOLDER/$database/g;
-            print F "\t\tstore path (server = " . ($slave + 1) . ", client = 1, conninfo = " . $conn . ");\n";
-            foreach my $subslave (keys %{$data{'slaves'}}) {
-                next if $slave == $subslave;
-                print F "\t\tstore path (server = " . ($slave + 1) . ", client = " . ($subslave + 1) . ", conninfo = " . $data{'slaves'}{$slave}{'coninfo'} . ");\n";
-            }
-        }
-        print F "\t}
-    on error {
-        echo 'Could not create store paths!';
-        exit -1;
-    }
-    echo 'Store paths created';
-    try {
-        echo 'Storing listen network';
-";
-
-#<JanniCash> make it as I said.  As long as you don't support cascading in your script,
-#    let the master listen on all slaves for their events (origin=that_slave, provider=that_slave, receiver=master)
-#<JanniCash> and let every slave listen for (origin=all_other_nodes, provider=master, receiver=slave)
-
-        foreach my $slave (sort keys %{$data{'slaves'}}) {
-            print F "\t\tstore listen (origin = 1, provider = 1, receiver = " . ($slave + 1) . ");\n";
-        }
-
-        foreach my $slave (sort keys %{$data{'slaves'}}) {
-            print F "\t\tstore listen (origin = " . ($slave + 1) . ", provider = " . ($slave + 1) . ", receiver = 1);\n";
-            foreach my $subslave (sort keys %{$data{'slaves'}}) {
-                next if $slave == $subslave;
-                print F "\t\tstore listen (origin = " . ($subslave + 1) . ", provider = 1, receiver = " . ($slave + 1) . ");\n";
-            }
-        }
-
-        print F "\t}
-    on error {
-        echo 'Could not store listen network!';
-        exit -1;
-    }
-    echo 'listen network stored';
-    try {
-        create set (id = 1, origin = 1, comment = '$database tables');
-    }
-    on error {
-        echo 'Could not create subscription set!';
-        exit -1;
-    }
-    echo 'Subscription set created';
-    try {
-        echo 'Adding tables to the subscription set';\n";
-
-        my $count = 1;
-        foreach my $table (keys %{$data{'master'}{'databases'}{$database}{'tables'}}) {
-            print F "
-        echo '  Adding table $table...';
-        set add table (set id = 1, origin = 1, id = $count, full qualified name = '$table', comment = 'Table $table');
-        echo '    done';\n";
-            $count++;
-        }
-
-        $count = 1;
-        
-        print F "\n\t\techo 'Adding sequences to the subscription set';\n";
-        
-        foreach my $sequence (keys %{$data{'master'}{'databases'}{$database}{'sequences'}}) {
-            print F "
-        echo '  Adding sequence $sequence...';
-        set add sequence (set id = 1, origin = 1, id = $count, full qualified name = '$sequence', comment = 'Sequence $sequence');
-        echo '    done';\n";
-            $count++;
-        }
-
-        print F "
-    }
-    on error {
-        echo 'Could not add tables and sequences!';
-        exit -1;
-    }
-    echo 'All tables added';
-_EOF_
-
-if [ \$? -ne 0 ]
-then
-    echo Errors were detected.  Please review $setup_log and fix the errors.
-    exit -1
-else
-";
-        my $command = "slon T1 dbname=$database 2> $errlog 1> $outlog &\n";
-
-        $command =~ s/DATABASENAME/$database/g;
-        
-        $slave_commands .= $command;
-        
-        $command = "\t" . $command . "\techo slon has been started on the master and placed into the background.  It is
-    echo logging STDOUT to $outlog and STDERR to $errlog.
-    echo
-    echo Now start slon on all slaves by running the following command on all slaves as the
-    echo slony system user:
-    echo
-    echo \"slon T1 dbname=$database 2> $errlog 1> $outlog &\"
-    echo
-    echo Once slon is running on all slaves, hit any key to proceed with the installation
-    read -s -n1 a
-    echo
-fi
-
-$conn
-";
-        
-        $command =~ s/DATABASENAME/$database/g;
-        print F $command . "\ttry {\n";
-        foreach my $slave (sort keys %{$data{'slaves'}}) {
-            print F "\t\tsubscribe set (id = 1, provider = 1, receiver = " . ($slave + 1) . ", forward = no);\n";
-        }
-        print F "\t}
-    on error {
-        echo 'Could not subscribe the set to the slaves';
-        exit -1;
-    }
-    echo 'Database $database subscribed to slaves';
-_EOF_
-
-if [ \$? -ne 0 ]
-then
-    echo Errors were detected.  Please review $setup_log and fix the errors.
-    exit -1
-fi\n";
-        
-    }
-}
-
-print F "
-echo The installation has succeeded.  At this time the slaves should be receiving the data
-echo from the master.";
-
-close F;
-
-my $end = "
-The setup script was saved as '$slony_master_setup'.  This script must
-be executed on the master as the \"slony\" system user.  If all goes well, Slony-I
-will be setup.  If not, errors should be reported in '$setup_log'.
-
-Additionally, a data dump of all data collected by this script has been stored
-in the file '$slony_dump'.  You might want to save this file if you want to
-run this script again with many of the same values.  A subsequent run of
-slony_setup.pl looks for the dumpfile in the working target directory.  This dump
-file only contains the server names and login credentials for now.  Since it
-contains sensitive information, it should be safe-guarded.
-
-You must also run the following command(s) on each slave as the \"slony\" system
-user.  These commands should be also set to start and stop when PostgreSQL starts
-and stops:
-
-$slave_commands
-Good luck!
-";
-
-pager(text => $end);
-
-#
-# Backup all the collected data to a file for future use
-#
-
-dump_to_file();
-
-#
-# Clean up
-#
-
-$exitcode = 0;
-clean_up();
-
-#############
-#           #
-# Functions #
-#           #
-#############
-
-sub pager {
-    my %params = (
-      text => undef
-    , @_
-    );
-    open P, "| $pager" or death( message => "Can't open pipe to $pager: $!");
-    print P "$params{'text'}\n[This is the pager '$pager'.  Press 'q' to exit]\n";
-    close P;
-}
-    
-sub check_version {
-    my %params = (
-      which => undef
-    , database => undef
-    , @_
-    );
-    my ($major, $minor) = 0,0 ;
-    open P, "$psql -h " . $data{$params{'which'}}{'hostname'} .
-        " -p " . $data{$params{'which'}}{'port'} .
-        " -U " . $data{$params{'which'}}{'username'} .
-        " -t -c 'select version()'" .
-        " -d template1 | " 
-        || death( message => "Can't open pipe to $psql: $!");
-    while (<P>) {
-        if($_ =~ /postgresql\s+(\d+)\.(\d+)/i){
-	        ($major, $minor) = ($1, $2);
-	}
-    }
-    close P;
-    if ($major == 7 && $minor >= 3) {
-	return 0;
-    } elsif ($major == 8) {
-	return 0;
-    } else {
-	return 1;
-    }
-    return 2;
-}
-
-sub get_info {
-    my %params = (
-      which => undef
-    , @_
-    );
-    print "Enter the hostname or IP address of the $params{'which'} database ($data{$params{'which'}}{'hostname'}): ";
-    my $temp = <>;
-    chomp ($temp);
-    $data{$params{'which'}}{'hostname'} = $temp if $temp;
-    
-    print "Enter the port address of the $params{'which'} database ($data{$params{'which'}}{'port'}): ";
-    $temp = <>;
-    chomp ($temp);
-    $data{$params{'which'}}{'port'} = $temp if $temp;
-    
-    print "Enter the username of the $params{'which'} database (" . $data{$params{'which'}}{'username'} . "): ";
-    $temp = <>;
-    chomp ($temp);
-    $data{$params{'which'}}{'username'} = $temp if $temp;
-    
-    system "stty -echo";
-    if ($data{$params{'which'}}{'password'}) {
-        print "Enter the password (A password is cached.  Hit enter to use it): ";
-    } else {
-        print "Enter the password: ";
-    }
-    $temp = <>;
-    chomp ($temp);
-    system "stty echo";
-    $data{$params{'which'}}{'password'} = $temp if $temp;
-    
-    my $pgpass =
-        $data{$params{'which'}}{'hostname'} . ":" .
-        $data{$params{'which'}}{'port'} . ":" .
-        "*" . ":" .
-        $data{$params{'which'}}{'username'} . ":" .
-        $data{$params{'which'}}{'password'} . "\n";
-    open F, ">>$pgpassfile" or death( message => "Can't open file $pgpassfile: $!");
-    print F $pgpass;
-    close F;
-    chmod 0600, $pgpassfile or death( message => "Unable to chmod 600 $pgpassfile");
-}
-
-sub get_databases {
-    my %params = (
-      which => undef
-    , @_
-    );
-    open P, "$psql -h " . $data{$params{'which'}}{'hostname'} .
-        " -p " . $data{$params{'which'}}{'port'} .
-        " -U " . $data{$params{'which'}}{'username'} .
-        " -t -d template1" .
-        " -l |"
-        || death( message => "Can't open pipe to $psql: $!");
-    while (<P>) {
-        $_ =~ m/\s+(\S+)\s+\|\s+(\S+)\s+\|\s+(\S+)\s+/;
-        next if ! $3;
-        my $name = $1;
-        my $owner = $2;
-        my $encoding = $3;
-        if ($name !~ m/^template(0|1)$/) {
-            $data{$params{'which'}}{'databases'}{$name}{'owner'} = $owner;
-        }
-    }
-    close P;
-}
-
-sub get_tables {
-    my %params = (
-      which => undef
-    , database => undef
-    , @_
-    );
-    open P, "$psql -t -h " . $data{$params{'which'}}{'hostname'} .
-        " -p " . $data{$params{'which'}}{'port'} .
-        " -U " . $data{$params{'which'}}{'username'} .
-        " -d $params{'database'} " .
-        " -c " . qq("select "pg_catalog".quote_ident(schemaname), "pg_catalog".quote_ident(tablename), "pg_catalog".quote_ident(tableowner) from pg_tables where schemaname not in ('information_schema', 'pg_catalog')") . " |"
-        || death( message => "Can't open pipe to $psql: $!");
-    while (<P>) {
-        my ($schema, $table, $owner) = $_ =~ m/\s+(\S+)\s+\|\s+(\S+)\s+\|\s+(\S+)\s+/;
-	if ($schema && $table && $owner) {
-
-    	    $data{$params{'which'}}{'databases'}{$params{'database'}}{'tables'}{$schema . "." . $table} = 1;
-	}
-    }
-    close P;
-}
-
-sub get_sequences {
-    my %params = (
-      which => undef
-    , database => undef
-    , @_
-    );
-    open P, "$psql -h " . $data{$params{'which'}}{'hostname'} .
-        " -p " . $data{$params{'which'}}{'port'} .
-        " -U " . $data{$params{'which'}}{'username'} .
-        " -d $params{'database'} " .
-        " -t" .
-        " -c " . qq("select "pg_catalog".quote_ident(nspname) || '.' || "pg_catalog".quote_ident(relname) from pg_class c, pg_namespace n where c.relnamespace = n.oid and c.relkind = 'S'") . " |"
-        || death( message => "Can't open pipe to $psql: $!");
-    while (<P>) {
-        $_ =~ m/\s+(\S+)\s+/;
-        my $sequence_name = $1;
-        $data{$params{'which'}}{'databases'}{$params{'database'}}{'sequences'}{$sequence_name} = 1;
-    }
-    close P;
-}
-
-sub get_users {
-    my $which = shift;
-    open P, "$psql -h " . $data{$which}{'hostname'} .
-        " -p " . $data{$which}{'port'} .
-        " -U " . $data{$which}{'username'} .
-        " -d template1 " .
-        " -t" .
-        " -c 'select * from pg_shadow' |"
-        || death( message => "Can't open pipe to $psql: $!");
-    while (<P>) {
-        $_ =~ m/\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)$/;
-        my $usename = $1;
-        my $usesysid = $2;
-        my $usecreatedb = $3;
-        my $usesuper = $4;
-        my $usecatupd = $5;
-        my $passwd = $6;
-        my $valuntil = $7;
-        my $useconfig = $8;
-        if ($usename && $usename !~ m/^(postgres|slony)$/) {
-            $data{$which}{'users'}{$usesysid}{'usename'} = $usename;
-            $data{$which}{'users'}{$usesysid}{'usesysid'} = $usesysid;
-            $data{$which}{'users'}{$usesysid}{'usecreatedb'} = $usecreatedb;
-            $data{$which}{'users'}{$usesysid}{'usesuper'} = $usesuper;
-            $data{$which}{'users'}{$usesysid}{'usecatupd'} = $usecatupd;
-            $data{$which}{'users'}{$usesysid}{'passwd'} = $passwd;
-            $data{$which}{'users'}{$usesysid}{'valuntil'} = $valuntil;
-            $data{$which}{'users'}{$usesysid}{'useconfig'} = $useconfig;
-        }
-    }
-    close P;
-}
-
-sub get_groups {
-    my $which = shift;
-    open P, "$psql -h " . $data{$which}{'hostname'} .
-        " -p " . $data{$which}{'port'} .
-        " -U " . $data{$which}{'username'} .
-        " -d template1 " .
-        " -t" .
-        " -c 'select * from pg_group' |"
-        || death( message => "Can't open pipe to $psql: $!");
-    while (<P>) {
-        $_ =~ m/\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)$/;
-        my $groname = $1;
-        my $grosysid = $2;
-        my $grolist = $3;
-        if ($groname) {
-            $data{$which}{'groups'}{$grosysid}{'groname'} = $groname;
-            $data{$which}{'groups'}{$grosysid}{'grosysid'} = $grosysid;
-            $data{$which}{'groups'}{$grosysid}{'grolist'} = $grolist;
-        }
-    }
-    close P;
-}
-
-sub test_conn {
-    my %params = (
-      which => undef
-    , @_
-    );
-    my $ret = system "$psql -h " . $data{$params{'which'}}{'hostname'} .
-        " -p " . $data{$params{'which'}}{'port'} .
-        " -U " . $data{$params{'which'}}{'username'} .
-        " -d template1" .
-        " -t" .
-        " -c 'select current_timestamp' 1> $tmpdir/testpgconn 2> /dev/null";
-    if ($ret != 0) {
-        # Remove the failed attempt from ~/.pgpass
-        open F, "$pgpassfile" || death( message => "Can't open $pgpassfile: $!");
-        my @lines = <F>;
-        close F;
-        pop @lines;
-        open F, ">$pgpassfile" || death( message => "Can't open $pgpassfile: $!");
-        print F @lines;
-        close F;
-        return -1;
-    }
-  return 0;
-}
-
-sub get_one {
-    my $temp;
-    system "stty -echo";
-    system "stty raw";
-    sysread STDIN, $temp, 1;
-    system "stty sane";
-    system "stty echo";
-    return $temp;
-}
-
-sub get_one_bool {
-    my $temp = get_one();
-    if ($temp =~ m/n/i) {
-        print "N\n";
-        return 0;
-    } else {
-        print "Y\n";
-        return 1;
-    }
-}
-
-sub dump_to_file {
-    return if !$dumper;
-    open F, ">$slony_dump" or death( message => "Can't open $slony_dump: $!");
-    foreach my $host (keys %data) {
-        delete $data{$host}{'databases'};
-        delete $data{$host}{'users'};
-        delete $data{$host}{'groups'};
-        delete $data{$host}{'coninfo'};
-    }
-    delete $data{'slaves'};
-    print F Data::Dumper::Dumper (\%data);
-    close F;
-    chmod 0600, $slony_dump;
-}
-
-sub backup_file {
-    my %params = (
-      orig => undef
-    , backup => undef
-    , @_
-    );
-    open F, $params{'orig'} or death( message => "Could not open $params{'orig'}: $!");
-    open FH, ">$params{'backup'}" or death( message => "Could not open $params{'backup'}: $!");
-    while (<F>) {
-        print FH $_;
-    }
-    close FH;
-    close F;
-    unlink $params{'orig'} or death( message => "Cannot unlink $params{'orig'}: $!");
-}
-
-sub clean_up {
-    print "\n\nCleaning up\n";
-    unlink $pgpassfile;
-    if (-f $pgpassbackup) {
-        print "Restoring previous $pgpassfile\n";
-        backup_file (
-          orig => $pgpassbackup
-        , backup => $pgpassfile
-        );
-    }
-    if (-d $tmpdir) {
-        print "Removing temporary directory\n";
-        system("rm -rf $tmpdir");
-    }
-    print "\n";
-    system "stty echo";
-    exit $exitcode;
-}
-
-sub death {
-    my %params = (
-      message => undef
-    , @_
-    );
-    print "$params{'message'}\n";
-    clean_up();
-}
-
-sub generate_abend {
-  my %params = ( descr => undef , @_);
-
-  print F "if [ \$? -ne 0 ]\n";
-  print F "then\n";
-  if ($params{'descr'}) {
-    print F "\techo \"$params{'descr'}\"\n";  
-  }
-  print F "\techo Errors were detected. Please review $setup_log and fix the errors.\n";
-  print F "\texit -1;\n";
-  print F "fi\n\n";
-}



More information about the Slony1-commit mailing list