Fri Oct 27 10:35:16 PDT 2006
- Previous message: [Slony1-commit] By cbbrowne: Delete long-decrepit replication setup script
- Next message: [Slony1-commit] By cbbrowne: The version detection code in configure has trouble
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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";
-}
- Previous message: [Slony1-commit] By cbbrowne: Delete long-decrepit replication setup script
- Next message: [Slony1-commit] By cbbrowne: The version detection code in configure has trouble
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Slony1-commit mailing list