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', ], ); $_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;