From 945721f48f74d5cfffef7c7cf3a3d6bc2521f5dd Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 15 Jul 2003 13:16:32 +0000 Subject: import of rt 3.0.4 --- rt/sbin/rt-setup-database | 585 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 585 insertions(+) create mode 100644 rt/sbin/rt-setup-database (limited to 'rt/sbin/rt-setup-database') diff --git a/rt/sbin/rt-setup-database b/rt/sbin/rt-setup-database new file mode 100644 index 000000000..f84f290b7 --- /dev/null +++ b/rt/sbin/rt-setup-database @@ -0,0 +1,585 @@ +#!/usr/bin/perl -w +# BEGIN LICENSE BLOCK +# +# Copyright (c) 1996-2003 Jesse Vincent +# +# (Except where explictly superceded by other copyright notices) +# +# This work is made available to you under the terms of Version 2 of +# the GNU General Public License. A copy of that license should have +# been provided with this software, but in any event can be snarfed +# from www.gnu.org. +# +# This work is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. +# +# +# END LICENSE BLOCK + +use strict; +use vars qw($PROMPT $VERSION $Handle $Nobody $SystemUser $item); +use vars + qw(@Groups @Users @ACL @Queues @ScripActions @ScripConditions @Templates @CustomFields @Scrips); + +use lib "/opt/rt3/lib"; + +#This drags in RT's config.pm +# We do it in a begin block because RT::Handle needs to know the type to do its +# inheritance +use RT; +use Carp; +use RT::User; +use RT::CurrentUser; +use RT::Template; +use RT::ScripAction; +use RT::ACE; +use RT::Group; +use RT::User; +use RT::Queue; +use RT::ScripCondition; +use RT::CustomField; +use RT::Scrip; + +RT::LoadConfig(); +use Term::ReadKey; +use Getopt::Long; + +my %args; + +GetOptions( + \%args, + 'prompt-for-dba-password', 'force', 'debug', + 'action=s', 'dba=s', 'dba-password=s', 'datafile=s', + 'datadir=s' +); + +$| = 1; #unbuffer that output. + +require RT::Handle; +my $Handle = RT::Handle->new($RT::DatabaseType); +$Handle->BuildDSN; +my $dbh; + +if ( $args{'prompt-for-dba-password'} ) { + $args{'dba-password'} = get_dba_password(); + chomp( $args{'dba-password'} ); +} + +unless ( $args{'action'} ) { + help(); + die; +} +if ( $args{'action'} eq 'init' ) { + $dbh = DBI->connect( get_system_dsn(), $args{'dba'}, $args{'dba-password'} ) + || die "Failed to connect to " . get_system_dsn() . " as $args{'dba'}: $DBI::errstr"; + print "Now creating a database for RT.\n"; + create_db(); + + $dbh->disconnect; + $dbh = DBI->connect( $Handle->DSN, $args{'dba'}, $args{'dba-password'} ) + || die $DBI::errstr; + + print "Now populating database schema.\n"; + insert_schema(); + print "Now inserting database ACLs\n"; + insert_acl(); + print "Now inserting RT core system objects\n"; + insert_initial_data(); + print "Now inserting RT data\n"; + insert_data( $RT::EtcPath . "/initialdata" ); +} +elsif ( $args{'action'} eq 'drop' ) { + unless ( $dbh = + DBI->connect( get_system_dsn(), $args{'dba'}, $args{'dba-password'} ) ) + { + warn $DBI::errstr; + warn "Database doesn't appear to exist. Aborting database drop."; + exit(0); + } + drop_db(); +} +elsif ( $args{'action'} eq 'insert' ) { + insert_data( $args{'datafile'} ); +} +elsif ($args{'action'} eq 'acl') { + $dbh = DBI->connect( $Handle->DSN, $args{'dba'}, $args{'dba-password'} ) + || die "Failed to connect to " . get_system_dsn() . " as $args{'dba'}: $DBI::errstr"; + insert_acl($args{'datadir'}); +} +elsif ($args{'action'} eq 'schema') { + $dbh = DBI->connect( $Handle->DSN, $args{'dba'}, $args{'dba-password'} ) + || die "Failed to connect to " . get_system_dsn() . " as $args{'dba'}: $DBI::errstr"; + insert_schema($args{'datadir'}); +} + +else { + print STDERR '$0 called with an invalid --action parameter'; + exit(-1); +} + +# {{{ sub insert_schema +sub insert_schema { + my $base_path = (shift || $RT::EtcPath); + my (@schema); + print "Creating database schema.\n"; + + if ( -f $base_path . "/schema." . $RT::DatabaseType ) { + no warnings 'unopened'; + + open( SCHEMA, "<" . $base_path . "/schema." . $RT::DatabaseType ); + open( SCHEMA_LOCAL, "<" . $RT::LocalEtcPath . "/schema." . $RT::DatabaseType ); + + my $statement = ""; + foreach my $line (, ) { + $line =~ s/\#.*//g; + $statement .= $line; + if ( $line =~ /;(\s*)$/ ) { + $statement =~ s/;(\s*)$//g; + push @schema, $statement; + $statement = ""; + } + } + + foreach my $statement (@schema) { + print STDERR $statement if $args{'debug'}; + my $sth = $dbh->prepare($statement) or die $dbh->errstr; + unless ( $sth->execute ) { + die "Problem with statement:\n $statement\n" . $sth->errstr; + } + } + + } + else { + die "Couldn't find schema file for " . $RT::DatabaseType . "\n"; + } + print "schema sucessfully inserted\n"; + +} + +# }}} + +# {{{ sub drop_db +sub drop_db { + return if ( $RT::DatabaseType eq 'SQLite' ); + unless ( $args{'force'} ) { + print <do("Drop DATABASE $RT::DatabaseName") or warn $DBI::errstr; +} + +# }}} + +# {{{ sub create_db +sub create_db { + print "Creating $RT::DatabaseType database $RT::DatabaseName.\n"; + if ( $RT::DatabaseType eq 'SQLite' ) { + return; + } + elsif ( $RT::DatabaseType eq 'Pg' ) { + $dbh->do("CREATE DATABASE $RT::DatabaseName WITH ENCODING='UNICODE'"); + if ($DBI::errstr) { + $dbh->do("CREATE DATABASE $RT::DatabaseName") || die $DBI::errstr; + } + } + else { + $dbh->do("CREATE DATABASE $RT::DatabaseName") or die $DBI::errstr; + } +} + +# }}} + +sub get_dba_password { + print +"In order to create a new database and grant RT access to that database,\n"; + print "this script needs to connect to your " + . $RT::DatabaseType + . " instance on " + . $RT::DatabaseHost . " as " + . $args{'dba'} . ".\n"; + print +"Please specify that user's database password below. If the user has no database\n"; + print "password, just press return.\n\n"; + print "Password: "; + ReadMode('noecho'); + my $password = ReadLine(0); + ReadMode('normal'); + return ($password); +} + +# {{{ sub _yesno +sub _yesno { + print "Proceed [y/N]:"; + my $x = scalar(); + $x =~ /^y/i; +} + +# }}} + +# {{{ insert_acls +sub insert_acl { + + my $base_path = (shift || $RT::EtcPath); + + if ( $RT::DatabaseType =~ /^oracle$/i ) { + do $base_path . "/acl.Oracle" + || die "Couldn't find ACLS for Oracle\n" . $@; + } + elsif ( $RT::DatabaseType =~ /^pg$/i ) { + do $base_path . "/acl.Pg" || die "Couldn't find ACLS for Pg\n" . $@; + } + elsif ( $RT::DatabaseType =~ /^mysql$/i ) { + do $base_path . "/acl.mysql" + || die "Couldn't find ACLS for mysql in " . $RT::EtcPath . "\n" . $@; + } + elsif ( $RT::DatabaseType =~ /^SQLite$/i ) { + return; + } + else { + die "Unknown RT database type"; + } + + my @acl = acl($dbh); + foreach my $statement (@acl) { + print STDERR $statement if $args{'debug'}; + my $sth = $dbh->prepare($statement) or die $dbh->errstr; + unless ( $sth->execute ) { + die "Problem with statement:\n $statement\n" . $sth->errstr; + } + } +} + +# }}} + +=head2 get_system_dsn + +Returns a dsn suitable for database creates and drops +and user creates and drops + +=cut + +sub get_system_dsn { + + my $dsn = $Handle->DSN; + + #with mysql, you want to connect sans database to funge things + if ( $RT::DatabaseType eq 'mysql' ) { + $dsn =~ s/dbname=$RT::DatabaseName//; + + # with postgres, you want to connect to database1 + } + elsif ( $RT::DatabaseType eq 'Pg' ) { + $dsn =~ s/dbname=$RT::DatabaseName/dbname=template1/; + } + return $dsn; +} + +sub insert_initial_data { + + RT::InitLogging(); + + #connect to the db, for actual RT work + require RT::Handle; + $RT::Handle = RT::Handle->new(); + $RT::Handle->Connect(); + + #Put together a current user object so we can create a User object + my $CurrentUser = new RT::CurrentUser(); + + print "Checking for existing system user..."; + my $test_user = RT::User->new($CurrentUser); + $test_user->Load('RT_System'); + if ( $test_user->id ) { + print "found!\n\nYou appear to have a functional RT database.\n" + . "Exiting, so as not to clobber your existing data.\n"; + exit(-1); + + } + else { + print "not found. This appears to be a new installation.\n"; + } + + print "Creating system user..."; + my $RT_System = new RT::User($CurrentUser); + + my ( $val, $msg ) = $RT_System->_BootstrapCreate( + Name => 'RT_System', + RealName => 'The RT System itself', + Comments => +'Do not delete or modify this user. It is integral to RT\'s internal database structures', + Creator => '1' ); + + unless ($val) { + print "$msg\n"; + exit(1); + } + print "done.\n"; + $RT::Handle->dbh->disconnect(); + +} + +# load some sort of data into the database + +sub insert_data { + my $datafile = shift; + + #Connect to the database and get RT::SystemUser and RT::Nobody loaded + RT::Init; + + my $CurrentUser = RT::CurrentUser->new(); + $CurrentUser->LoadByName('RT_System'); + + if ( $datafile eq $RT::EtcPath . "/initialdata" ) { + + print "Creating Superuser ACL..."; + + my $superuser_ace = RT::ACE->new($CurrentUser); + $superuser_ace->_BootstrapCreate( + PrincipalId => ACLEquivGroupId( $CurrentUser->Id ), + PrincipalType => 'Group', + RightName => 'SuperUser', + ObjectType => 'RT::System', + ObjectId => '1' ); + + } + + # Slurp in stuff to insert from the datafile. Possible things to go in here:- + # @groups, @users, @acl, @queues, @ScripActions, @ScripConditions, @templates + + require $datafile + || die "Couldn't find initial data for import\n" . $@; + + if (@Groups) { + print "Creating groups..."; + foreach $item (@Groups) { + my $new_entry = RT::Group->new($CurrentUser); + my ( $return, $msg ) = $new_entry->_Create(%$item); + print "(Error: $msg)" unless ($return); + print $return. "."; + } + print "done.\n"; + } + if (@Users) { + print "Creating users..."; + foreach $item (@Users) { + my $new_entry = new RT::User($CurrentUser); + my ( $return, $msg ) = $new_entry->Create(%$item); + print "(Error: $msg)" unless ($return); + print $return. "."; + } + print "done.\n"; + } + if (@Queues) { + print "Creating queues..."; + for $item (@Queues) { + my $new_entry = new RT::Queue($CurrentUser); + my ( $return, $msg ) = $new_entry->Create(%$item); + print "(Error: $msg)" unless ($return); + print $return. "."; + } + print "done.\n"; + } + if (@ACL) { + print "Creating ACL..."; + for my $item (@ACL) { + + my ($princ, $object); + + # Global rights or Queue rights? + if ($item->{'Queue'}) { + $object = RT::Queue->new($CurrentUser); + $object->Load( $item->{'Queue'} ); + } else { + $object = $RT::System; + } + + # Group rights or user rights? + if ($item->{'GroupDomain'}) { + $princ = RT::Group->new($CurrentUser); + if ($item->{'GroupDomain'} eq 'UserDefined') { + $princ->LoadUserDefinedGroup( $item->{'GroupId'} ); + } elsif ($item->{'GroupDomain'} eq 'SystemInternal') { + $princ->LoadSystemInternalGroup( $item->{'GroupType'} ); + } elsif ($item->{'GroupDomain'} eq 'RT::Queue-Role' && + $item->{'Queue'}) { + $princ->LoadQueueRoleGroup( Type => $item->{'GroupType'}, + Queue => $object->id); + } else { + $princ->Load( $item->{'GroupId'} ); + } + } else { + $princ = RT::User->new($CurrentUser); + $princ->Load( $item->{'UserId'} ); + } + + # Grant it + my ( $return, $msg ) = $princ->PrincipalObj->GrantRight( + Right => $item->{'Right'}, + Object => $object ); + + if ($return) { + print $return. "."; + } + else { + print $msg . "."; + + } + + } + print "done.\n"; + } + if (@CustomFields) { + print "Creating custom fields..."; + for $item (@CustomFields) { + my $new_entry = new RT::CustomField($CurrentUser); + my $values = $item->{'Values'}; + delete $item->{'Values'}; + my $q = $item->{'Queue'}; + my $q_obj = RT::Queue->new($CurrentUser); + $q_obj->Load($q); + if ( $q_obj->Id ) { + $item->{'Queue'} = $q_obj->Id; + } + elsif ( $q == 0 ) { + $item->{'Queue'} = 0; + } + else { + print "(Error: Could not find queue " . $q . ")\n" + unless ( $q_obj->Id ); + next; + } + my ( $return, $msg ) = $new_entry->Create(%$item); + + foreach my $value ( @{$values} ) { + my ( $eval, $emsg ) = $new_entry->AddValue(%$value); + print "(Error: $emsg)\n" unless ($eval); + } + + print "(Error: $msg)\n" unless ($return); + print $return. "."; + } + + print "done.\n"; + } + + if (@ScripActions) { + print "Creating ScripActions..."; + + for $item (@ScripActions) { + my $new_entry = RT::ScripAction->new($CurrentUser); + my $return = $new_entry->Create(%$item); + print $return. "."; + } + + print "done.\n"; + } + + if (@ScripConditions) { + print "Creating ScripConditions..."; + + for $item (@ScripConditions) { + my $new_entry = RT::ScripCondition->new($CurrentUser); + my $return = $new_entry->Create(%$item); + print $return. "."; + } + + print "done.\n"; + } + + if (@Templates) { + print "Creating templates..."; + + for $item (@Templates) { + my $new_entry = new RT::Template($CurrentUser); + my $return = $new_entry->Create(%$item); + print $return. "."; + } + print "done.\n"; + } + if (@Scrips) { + print "Creating scrips..."; + + for $item (@Scrips) { + my $new_entry = new RT::Scrip($CurrentUser); + my ( $return, $msg ) = $new_entry->Create(%$item); + if ($return) { + print $return. "."; + } + else { + print "(Error: $msg)\n"; + } + } + print "done.\n"; + } + $RT::Handle->Disconnect(); + +} + +=head2 ACLEquivGroupId + +Given a userid, return that user's acl equivalence group + +=cut + +sub ACLEquivGroupId { + my $username = shift; + my $user = RT::User->new($RT::SystemUser); + $user->Load($username); + my $equiv_group = RT::Group->new($RT::SystemUser); + $equiv_group->LoadACLEquivalenceGroup($user); + return ( $equiv_group->Id ); +} + +sub help { + + print < Date: Thu, 11 Mar 2004 02:05:38 +0000 Subject: import of rt 3.0.9 --- rt/sbin/rt-setup-database | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) (limited to 'rt/sbin/rt-setup-database') diff --git a/rt/sbin/rt-setup-database b/rt/sbin/rt-setup-database index f84f290b7..58f882f6e 100644 --- a/rt/sbin/rt-setup-database +++ b/rt/sbin/rt-setup-database @@ -80,7 +80,12 @@ if ( $args{'action'} eq 'init' ) { $dbh = DBI->connect( get_system_dsn(), $args{'dba'}, $args{'dba-password'} ) || die "Failed to connect to " . get_system_dsn() . " as $args{'dba'}: $DBI::errstr"; print "Now creating a database for RT.\n"; + if ($RT::DatabaseType ne 'Oracle' || + $args{'dba'} ne $RT::DatabaseUser) { create_db(); + } else { + print "...skipped as ".$args{'dba'} ." is not " . $RT::DatabaseUser . " or we're working with Oracle.\n"; + } $dbh->disconnect; $dbh = DBI->connect( $Handle->DSN, $args{'dba'}, $args{'dba-password'} ) @@ -89,7 +94,7 @@ if ( $args{'action'} eq 'init' ) { print "Now populating database schema.\n"; insert_schema(); print "Now inserting database ACLs\n"; - insert_acl(); + insert_acl() unless ($RT::DatabaseType eq 'Oracle'); print "Now inserting RT core system objects\n"; insert_initial_data(); print "Now inserting RT data\n"; @@ -137,8 +142,9 @@ sub insert_schema { open( SCHEMA_LOCAL, "<" . $RT::LocalEtcPath . "/schema." . $RT::DatabaseType ); my $statement = ""; - foreach my $line (, ) { + foreach my $line (, ($_ = ';;'), ) { $line =~ s/\#.*//g; + $line =~ s/--.*//g; $statement .= $line; if ( $line =~ /;(\s*)$/ ) { $statement =~ s/;(\s*)$//g; @@ -147,10 +153,13 @@ sub insert_schema { } } + local $SIG{__WARN__} = sub {}; + my $is_local = 0; # local/etc/schema needs to be nonfatal. foreach my $statement (@schema) { - print STDERR $statement if $args{'debug'}; + if ($statement =~ /^\s*;$/) { $is_local = 1; next; } + print STDERR "SQL: $statement\n" if defined $args{'debug'}; my $sth = $dbh->prepare($statement) or die $dbh->errstr; - unless ( $sth->execute ) { + unless ( $sth->execute or $is_local ) { die "Problem with statement:\n $statement\n" . $sth->errstr; } } @@ -168,6 +177,16 @@ sub insert_schema { # {{{ sub drop_db sub drop_db { return if ( $RT::DatabaseType eq 'SQLite' ); + if ( $RT::DatabaseType eq 'Oracle' ) { + print <do("CREATE DATABASE $RT::DatabaseName") || die $DBI::errstr; } } + elsif ($RT::DatabaseType eq 'Oracle') { + insert_acl(); + } + elsif ( $RT::DatabaseType eq 'Informix' ) { + $ENV{DB_LOCALE} = 'en_us.utf8'; + $dbh->do("CREATE DATABASE $RT::DatabaseName WITH BUFFERED LOG"); + } else { $dbh->do("CREATE DATABASE $RT::DatabaseName") or die $DBI::errstr; } @@ -248,6 +274,10 @@ sub insert_acl { do $base_path . "/acl.mysql" || die "Couldn't find ACLS for mysql in " . $RT::EtcPath . "\n" . $@; } + elsif ( $RT::DatabaseType =~ /^informix$/i ) { + do $base_path . "/acl.Informix" + || die "Couldn't find ACLS for Informix in " . $RT::EtcPath . "\n" . $@; + } elsif ( $RT::DatabaseType =~ /^SQLite$/i ) { return; } @@ -287,6 +317,10 @@ sub get_system_dsn { elsif ( $RT::DatabaseType eq 'Pg' ) { $dsn =~ s/dbname=$RT::DatabaseName/dbname=template1/; } + elsif ( $RT::DatabaseType eq 'Informix' ) { + # with Informix, you want to connect sans database: + $dsn =~ s/Informix:$RT::DatabaseName/Informix:/; + } return $dsn; } @@ -302,7 +336,7 @@ sub insert_initial_data { #Put together a current user object so we can create a User object my $CurrentUser = new RT::CurrentUser(); - print "Checking for existing system user..."; + print "Checking for existing system user ($CurrentUser)..."; my $test_user = RT::User->new($CurrentUser); $test_user->Load('RT_System'); if ( $test_user->id ) { @@ -330,7 +364,7 @@ sub insert_initial_data { exit(1); } print "done.\n"; - $RT::Handle->dbh->disconnect(); + $RT::Handle->Disconnect(); } -- cgit v1.2.1 From ae11d16db998c044e523030cc026b2d0c0bc981b Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 16 Mar 2004 06:43:15 +0000 Subject: initial (hopefully rather unobtrusive) patch --- rt/sbin/rt-setup-database | 3 +++ 1 file changed, 3 insertions(+) (limited to 'rt/sbin/rt-setup-database') diff --git a/rt/sbin/rt-setup-database b/rt/sbin/rt-setup-database index 58f882f6e..83e08270a 100644 --- a/rt/sbin/rt-setup-database +++ b/rt/sbin/rt-setup-database @@ -110,6 +110,9 @@ elsif ( $args{'action'} eq 'drop' ) { } drop_db(); } +elsif ( $args{'action'} eq 'insert_initial' ) { + insert_initial_data(); +} elsif ( $args{'action'} eq 'insert' ) { insert_data( $args{'datafile'} ); } -- cgit v1.2.1 From ce41102169513f44c89a1e9bddfb250b29f239bb Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 8 Apr 2004 12:00:05 +0000 Subject: beginning of RT integration --- rt/sbin/rt-setup-database | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'rt/sbin/rt-setup-database') diff --git a/rt/sbin/rt-setup-database b/rt/sbin/rt-setup-database index 83e08270a..434e68671 100644 --- a/rt/sbin/rt-setup-database +++ b/rt/sbin/rt-setup-database @@ -592,6 +592,10 @@ $0: Set up RT's database --action init Initialize the database drop Drop the database. This will ERASE ALL YOUR DATA + insert_initial + Insert RT's core system objects + insert_initial + Insert RT's core system objects insert Insert data into RT's database. By default, will use RT's installation data. To use a local or supplementary datafile, specify it -- cgit v1.2.1 From b57bf99761751466c5b9a5d35df9e00b407c6f64 Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 8 Apr 2004 12:05:04 +0000 Subject: remove accidentally doubled lines in usage inst --- rt/sbin/rt-setup-database | 2 -- 1 file changed, 2 deletions(-) (limited to 'rt/sbin/rt-setup-database') diff --git a/rt/sbin/rt-setup-database b/rt/sbin/rt-setup-database index 434e68671..17819886c 100644 --- a/rt/sbin/rt-setup-database +++ b/rt/sbin/rt-setup-database @@ -594,8 +594,6 @@ $0: Set up RT's database This will ERASE ALL YOUR DATA insert_initial Insert RT's core system objects - insert_initial - Insert RT's core system objects insert Insert data into RT's database. By default, will use RT's installation data. To use a local or supplementary datafile, specify it -- cgit v1.2.1