diff options
Diffstat (limited to 'rt/sbin/rt-setup-database')
| -rw-r--r-- | rt/sbin/rt-setup-database | 707 | 
1 files changed, 0 insertions, 707 deletions
| diff --git a/rt/sbin/rt-setup-database b/rt/sbin/rt-setup-database deleted file mode 100644 index 49af151e7..000000000 --- a/rt/sbin/rt-setup-database +++ /dev/null @@ -1,707 +0,0 @@ -#!/usr/bin/perl -w -# BEGIN BPS TAGGED BLOCK {{{ -#  -# COPYRIGHT: -#   -# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC  -#                                          <jesse@bestpractical.com> -#  -# (Except where explicitly superseded by other copyright notices) -#  -#  -# LICENSE: -#  -# 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. -#  -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 or visit their web page on the internet at -# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. -#  -#  -# CONTRIBUTION SUBMISSION POLICY: -#  -# (The following paragraph is not intended to limit the rights granted -# to you to modify and distribute this software under the terms of -# the GNU General Public License and is only of importance to you if -# you choose to contribute your changes and enhancements to the -# community by submitting them to Best Practical Solutions, LLC.) -#  -# By intentionally submitting any modifications, corrections or -# derivatives to this work, or any other work intended for use with -# Request Tracker, to Best Practical Solutions, LLC, you confirm that -# you are the copyright holder for those contributions and you grant -# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable, -# royalty-free, perpetual, license to use, copy, create derivative -# works based on those contributions, and sublicense and distribute -# those contributions and any derivatives thereof. -#  -# END BPS TAGGED BLOCK }}} -use strict; -use vars qw($PROMPT $VERSION $Handle $Nobody $SystemUser $item); -use vars -  qw(@Groups @Users @ACL @Queues @ScripActions @ScripConditions @Templates @CustomFields @Scrips @Attributes); - -use lib "/opt/rt3/local/lib"; -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' -); - -unless ( $args{'action'} ) { -    help(); -    exit(-1); -} - -$| = 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'} ); -} - -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"; -    } - -    if ( $RT::DatabaseType eq "mysql" ) { -        # Check which version we're running -        my ($version) = $dbh->selectrow_hashref("show variables like 'version'")->{Value} =~ /^(\d\.\d+)/; -        print "*** Warning: RT is unsupported on MySQL versions before 4.0.x\n" if $version < 4; - -        # MySQL must have InnoDB support -        my $innodb = $dbh->selectrow_hashref("show variables like 'have_innodb'")->{Value}; -        if ( $innodb eq "NO" ) { -            die "RT requires that MySQL be compiled with InnoDB table support.\n". -              "See http://dev.mysql.com/doc/mysql/en/InnoDB.html\n"; -        } elsif ( $innodb eq "DISABLED" ) { -            die "RT requires that MySQL InnoDB table support be enabled.\n". -              ($version < 4 -               ? "Add 'innodb_data_file_path=ibdata1:10M:autoextend' to the [mysqld] section of my.cnf\n" -               : "Remove the 'skip-innodb' line from your my.cnf file, restart MySQL, and try again.\n"); -        } -    } - -    # SQLite can't deal with the disconnect/reconnect -    unless ( $RT::DatabaseType eq 'SQLite' ) { - -        $dbh->disconnect; - -        if ( $RT::DatabaseType eq "Oracle" ) { -            $RT::DatabasePassword = $RT::DatabasePassword; #Warning avidance -            $dbh = DBI->connect( $Handle->DSN, ${RT::DatabaseUser}, ${RT::DatabasePassword} ) || die $DBI::errstr; -        } else {	 -            $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() unless $RT::DatabaseType eq 'Oracle'; -    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; -    } -    drop_db(); -} -elsif ( $args{'action'} eq 'insert' ) { -    insert_data( $args{'datafile'} || ($args{'datadir'}."/content") ); -} -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\n"; -    exit(-1); -} - -# {{{ sub insert_schema -sub insert_schema { -    my $base_path = (shift || $RT::EtcPath); -    my (@schema); -    print "Creating database schema.\n"; - -    my $schema_file = $base_path . "/schema." . $RT::DatabaseType; -    if ( -f $schema_file ) { -        open( SCHEMA, "<$schema_file"  ) or die "Can't open $schema_file: $!"; -	my @lines = <SCHEMA>; - -	my $local_schema_file = $RT::LocalEtcPath . "/schema." . $RT::DatabaseType; -	if (-f $local_schema_file) { -	    open( SCHEMA_LOCAL, "<$local_schema_file" ) -		or die "Can't open $local_schema_file: $!"; -	    push @lines, ';;', <SCHEMA_LOCAL>; -	} - -        my $statement = ""; -        foreach my $line (@lines) { -            $line =~ s/\#.*//g; -            $line =~ s/--.*//g; -            $statement .= $line; -            if ( $line =~ /;(\s*)$/ ) { -                $statement =~ s/;(\s*)$//g; -                push @schema, $statement; -                $statement = ""; -            } -        } - -        local $SIG{__WARN__} = sub {}; -        my $is_local = 0; # local/etc/schema needs to be nonfatal. -        $dbh->begin_work or die $dbh->errstr; -        foreach my $statement (@schema) { -            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 or $is_local ) { -                die "Problem with statement:\n $statement\n" . $sth->errstr; -            } -        } -        $dbh->commit or die $dbh->errstr; -    } -    else { -        die "Couldn't find schema file for " . $RT::DatabaseType . "\n"; -    } -    print "Done setting up database schema.\n"; -} - -# }}} - -# {{{ sub drop_db -sub drop_db { -    if ( $RT::DatabaseType eq 'Oracle' ) { -        print <<END; - -To delete the tables and sequences of the RT Oracle database by running -    \@etc/drop.Oracle -through SQLPlus. - -END -        return; -    } -    unless ( $args{'force'} ) { -        print <<END; - -About to drop $RT::DatabaseType database $RT::DatabaseName on $RT::DatabaseHost. -WARNING: This will erase all data in $RT::DatabaseName. - -END -        exit unless _yesno(); - -    } - -    print "Dropping $RT::DatabaseType database $RT::DatabaseName.\n"; - -    if ( $RT::DatabaseType eq 'SQLite' ) { -        unlink $RT::DatabaseName or warn $!; -        return; -    } -    $dbh->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; -        } -    } -    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; -    } -} - -# }}} - -sub get_dba_password { -    print "In order to create or update your RT database,"; -    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'); -    print "\n"; -    return ($password); -} - -# {{{ sub _yesno -sub _yesno { -    print "Proceed [y/N]:"; -    my $x = scalar(<STDIN>); -    $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 $base_path\n" . $@; -    } -    elsif ( $RT::DatabaseType =~ /^Sybase$/i ) { -        do $base_path . "/acl.Sybase" -          || die "Couldn't find ACLS for Sybase in $base_path\n" . $@; -    } -    elsif ( $RT::DatabaseType =~ /^informix$/i ) { -        do $base_path . "/acl.Informix" -          || die "Couldn't find ACLS for Informix in $base_path\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; -        } -    } -    print "Done setting up database ACLs.\n"; -} - -# }}} - -=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/; -    } -    elsif ( $RT::DatabaseType eq 'Informix' ) { -        # with Informix, you want to connect sans database: -        $dsn =~ s/Informix:$RT::DatabaseName/Informix:/; -    } -    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', -        LastUpdatedBy => '1', -    ); - -    unless ( $val ) { -        print "$msg\n"; -        exit(-1); -    } -    print "done.\n"; -    $RT::Handle->Disconnect() unless $RT::DatabaseType eq 'SQLite'; - -} - -# 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' ); - -        print "done.\n"; -    } - -    # 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::System-Role' ) { -                  $princ->LoadSystemRoleGroup( $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 ( $return, $msg ) = $new_entry->Create(%$item); -            unless( $return ) { -                print "(Error: $msg)\n"; -                next; -            } - -            foreach my $value ( @{$values} ) { -                my ( $eval, $emsg ) = $new_entry->AddValue(%$value); -                print "(Error: $emsg)\n" unless $eval; -            } - -            if ( $item->{LookupType} && !exists $item->{'Queue'} ) { # enable by default -                my $ocf = RT::ObjectCustomField->new($CurrentUser); -                $ocf->Create( CustomField => $new_entry->Id ); -            } - -            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,$msg) = $new_entry->Create(%$item); -            unless ($return) { -                print "(Error: $msg)\n"; -                next; -            } -            print $return. "."; -        } - -        print "done.\n"; -    } - -    if ( @ScripConditions ) { -        print "Creating ScripConditions..."; - -        for $item (@ScripConditions) { -            my $new_entry = RT::ScripCondition->new($CurrentUser); -            my ($return,$msg) = $new_entry->Create(%$item); -            unless ($return) { -                print "(Error: $msg)\n"; -                next; -            } -            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"; -    } -    if ( @Attributes ) { -        print "Creating predefined searches..."; -        my $sys = RT::System->new($CurrentUser); - -        for $item (@Attributes) { -            my $obj = delete $item->{Object}; # XXX: make this something loadable -            $obj ||= $sys; -            my ( $return, $msg ) = $obj->AddAttribute (%$item); -            if ( $return ) { -                print $return. "."; -            } -            else { -                print "(Error: $msg)\n"; -            } -        } -        print "done.\n"; -    } -    $RT::Handle->Disconnect() unless $RT::DatabaseType eq 'SQLite'; -    print "Done setting up database content.\n"; -} - -=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 <<EOF; - -$0: Set up RT's database - ---action        init    Initialize the database -                drop    Drop the database. -                        This will ERASE ALL YOUR DATA -                insert  Insert data into RT's database. -                        By default, will use RT's installation data. -                        To use a local or supplementary datafile, specify it -                        using the '--datafile' option below. - -                acl     Initialize only the database ACLs -                        To use a local or supplementary datafile, specify it -                        using the '--datadir' option below. - -                schema  Initialize only the database schema -                        To use a local or supplementary datafile, specify it -                        using the '--datadir' option below. - ---datafile /path/to/datafile ---datadir /path/to/              Used to specify a path to find the local -                                database schema and acls to be installed. - - ---dba                           dba's username ---dba-password                  dba's password ---prompt-for-dba-password       Ask for the database administrator's password interactively - - -EOF - -} - -1; | 
