The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl
use strict;
use Getopt::Long;
use lib 'lib';
use MogileFS::Store;
use MogileFS::Config;

# Rename binary in process list to make init scripts saner
$0 = $_ = $0;

my %args = (
            dbhost => "localhost",
            dbport => undef,
            dbname => "mogilefs",
            dbrootuser => undef,
            dbrootpass => "",
            dbuser => "mogile",
            dbpass => "",
            );

my $opt_help;
my $opt_verbose = 0;
my $opt_yes = 0;
my $opt_noschemabump;
my $dbtype = "MySQL";
my $plugins;

usage()
    unless GetOptions(
                      "dbhost=s"         => \$args{dbhost},
                      "dbport=s"         => \$args{dbport},
                      "dbname=s"         => \$args{dbname},
                      "dbrootuser=s"     => \$args{dbrootuser},
                      "dbrootpassword:s" => \$args{dbrootpass},
                      "dbuser=s"         => \$args{dbuser},
                      "dbpassword:s"     => \$args{dbpass},
                      "help"             => \$opt_help,
                      "verbose"          => \$opt_verbose,
                      "yes"              => \$opt_yes,
                      "noschemabump"     => \$opt_noschemabump,
                      "type=s"           => \$dbtype,
                      "plugins=s"        => \$plugins,
                      );

usage() if $opt_help;

# Be nice about what the default admin user is called.
if(!defined($args{dbrootuser})) {
    $args{dbrootuser} = 'root' if $dbtype =~ /MySQL/i;
    $args{dbrootuser} = 'postgres' if $dbtype =~ /Postgres/i;
}
# Saner port management.
# This should default to the UNIX sockets on localhost
if(!defined($args{dbport}) and $args{dbhost} != "localhost" and $args{dbhost} != "127.0.0.1") {
    $args{dbport} = '3306' if $dbtype =~ /MySQL/i;
    $args{dbport} = '5432' if $dbtype =~ /Postgres/i;
}

sub usage {
    die <<USAGE;
Usage: mogdbsetup [opts]

Options:

                  Default      Description
                  ============ ===========================================
 --verbose        <off>        Be verbose about what\'s happening.

 --dbhost=        localhost    hostname or IP to database server.

 --dbport=        dbd default  port number to database server.

 --dbname=        mogilefs     database name to create/upgrade.

 --dbrootuser=    root         Database administrator username.  Only needed
                               for initial setup, not subsequent upgrades.

 --dbrootpass=    <blank>      Database administrator password.  Only needed
                               for initial setup, not subsequent upgrades.

 --dbuser=        mogile       Regular database user to create and/or use
                               for MogileFS database.  This is what the
                               mogilefsd trackers connect as.

 --dbpass=        <blank>      You should change this, especially if your
                               database servers are accessible to other users
                               on the network.  But they shouldn't be
                               if you're running MogileFS, because MogileFS
                               assumes your network is closed.

  --type=         MySQL        Which MogileFS::Store implementation to use.
                               Available: MySQL, Postgres

  --yes                        Run without questions.

USAGE
}

my $sclass = "MogileFS::Store::$dbtype";
eval "use $sclass; 1;" or die "Failed to load $sclass: $@";

foreach my $plugin (split /\s*,\s*/, $plugins) {
    eval "use MogileFS::Plugin::$plugin; 1;" or die "Failed to load plugin $plugin: $@";
}

confirm("This will attempt to setup or upgrade your MogileFS database.\nIt won't destroy existing data.\nRun with --help for more information.  Run with --yes to shut up these prompts.\n\nContinue?", 0);

$sclass->on_status(\&status);
$sclass->on_confirm(\&confirm);

MogileFS::Config->load_config;

my $sto = $sclass->new_from_mogdbsetup(
                                       map { $_ => $args{$_} }
                                       qw(dbhost dbport dbname
                                          dbrootuser dbrootpass
                                          dbuser dbpass)
                                       );
my $dbh = $sto->dbh;

$sto->setup_database
    or die "Database upgrade failed.\n";

my $latestver = MogileFS::Store->latest_schema_version;
if ($opt_noschemabump) {
    warn "\n*\n* Per your request, NOT UPGRADING to $latestver.  I assume you understand why.\n*\n";
} else {
    $sto->set_schema_vesion($latestver);
}


warn "Done.\n" if $opt_verbose;
exit 0;

############################################################################

sub confirm {
    my $q = shift;
    my $def = shift;
    $def = 1 unless defined $def;

    return 1 if $opt_yes;
    my $deftext = $def ? "[Y/n]" : "[N/y]";

    print "\n$q $deftext: ";
    my $ans = <STDIN>;
    if ($ans =~ /^\s*$/) {
        die "Stopped.\n" unless $def;
        return 0;
    }
    return 1 if $ans =~ /^y/i;
    die "Stopped.\n";
}

sub status {
    warn "$_[0]\n" if $opt_verbose;
}