Files
failnix/scripts/Mars.pm

182 lines
3.8 KiB
Perl

package Mars;
use strict;
use warnings;
use diagnostics;
use DBI;
use Net::OpenSSH;
use feature 'say';
my $local_root = '/home/christoph/Notes/TU/MastersThesis/FailNix';
my $_remote = undef;
my $remote_host = 'mars'; # smchurla@mars.cs.tu-dortmund.de
# The mars db is bound to local port 3306 over SSH.
# - This requires using the configured 'mars'
# remote_host instead of smchurla@mars
# or setting up another tunnel here
my $_db = undef;
my $db_host = "127.0.0.1";
my $db_port = "3306";
my $db_user = "smchurla";
my $_db_password = undef;
sub ssh_connect {
if ( !defined $_remote ) {
# Initialize SSH connection
# - This connection also sets up the database tunnel
$_remote = Net::OpenSSH->new(
$remote_host,
timeout => 30,
master_opts => [
-o => 'BatchMode=yes',
-o => 'StrictHostKeyChecking=accept-new',
-o => 'ServerAliveInterval=60',
],
);
$_remote->error and die 'SSH connection failed: ' . $_remote->error;
say 'Connected to mars.cs.tu-dortmund.de';
}
return $_remote;
}
sub ssh_system {
my (@cmd) = @_;
my $ssh = ssh_connect();
$ssh->system(@cmd);
$ssh->error and die "Remote command failed (@cmd): " . $ssh->error;
}
sub ssh_capture {
my (@cmd) = @_;
my $ssh = ssh_connect();
my $out = $ssh->capture(@cmd);
$ssh->error and die "Remote command failed (@cmd): " . $ssh->error;
return $out;
}
sub upload_dir {
my ( $source_dir, $target_dir ) = @_;
my $ssh = ssh_connect();
say " - Uploading $source_dir to $target_dir...";
$ssh->scp_put(
{
recursive => 1,
copy_attrs => 1
},
$source_dir,
$target_dir,
) or die "Failed to upload $source_dir: " . $ssh->error;
}
sub download_dir {
my ( $source_dir, $target_dir ) = @_;
my $ssh = ssh_connect();
say " - Downloading $source_dir to $target_dir...";
$ssh->scp_get(
{
recursive => 1,
copy_attrs => 1
},
$source_dir,
$target_dir,
) or die "Failed to download $source_dir: " . $ssh->error;
}
sub find_remote_subdirs {
my ($dir) = @_;
my $out = ssh_capture(
'find', $dir, '-mindepth', '1',
'-maxdepth', '1', '-type', 'd',
'-printf', '%f' . "\n",
);
my @subdirs = sort grep { length } split /\n/, $out;
return @subdirs;
}
sub read_db_password_file {
if ( !defined $_db_password ) {
open( my $fhandle, '<', "$local_root/mars-db.conf" )
or die "Failed to read mars-db.conf: $!";
chomp( $_db_password = <$fhandle> );
close($fhandle);
}
return $_db_password;
}
sub db_connect {
# Opens tunnel for db_port
my $ssh = ssh_connect();
if ( !defined $_db ) {
$_db = DBI->connect( "DBI:MariaDB:host=$db_host;port=$db_port",
$db_user, read_db_password_file() )
or die 'Failed to connect to database: ' . $DBI::errstr;
say 'Connected to database';
}
return $_db;
}
sub db_disconnect {
if ( defined $_db ) {
$_db->disconnect or warn $_db->errstr;
}
}
sub db_prefix {
return $db_user;
}
sub db_list {
my $db = db_connect();
my @db_names =
sort
map { s/DBI:MariaDB://r }
grep { !/information_schema|smchurla_ll/ } $db->data_sources();
return @db_names;
}
sub db_do {
my (@cmd) = @_;
my $db = db_connect();
$db->do(@cmd) or die "Database command failed (@cmd): " . $db->errstr;
}
sub db_create {
my ($db_name) = @_;
say " - Creating database $db_name...";
db_do("create database `$db_name`");
}
sub db_drop {
my ($db_name) = @_;
say " - Dropping database $db_name...";
db_do("drop database `$db_name`");
}
1;