Line 27... |
Line 27... |
27 |
|
27 |
|
28 |
# load Configuration File
|
28 |
# load Configuration File
|
29 |
# read the config file and return it
|
29 |
# read the config file and return it
|
30 |
sub readConfig {
|
30 |
sub readConfig {
|
31 |
my $filename = shift;
|
31 |
my $filename = shift;
|
- |
|
32 |
die "Config file $filename not found: $!" unless -f $filename;
|
32 |
my $yaml = YAML::Tiny->new( {} );
|
33 |
my $yaml = YAML::Tiny->new( {} );
|
33 |
if ( -f $filename ) {
|
34 |
if ( -f $filename ) {
|
34 |
$yaml = YAML::Tiny->read( $filename );
|
35 |
$yaml = YAML::Tiny->read( $filename );
|
35 |
}
|
36 |
}
|
36 |
return $yaml->[0];
|
37 |
return $yaml->[0];
|
Line 51... |
Line 52... |
51 |
# runs a command, redirecting stderr to stdout (which it ignores)
|
52 |
# runs a command, redirecting stderr to stdout (which it ignores)
|
52 |
# then returns 0 on success.
|
53 |
# then returns 0 on success.
|
53 |
# if error, returns string describing error
|
54 |
# if error, returns string describing error
|
54 |
sub runCommand {
|
55 |
sub runCommand {
|
55 |
my $command = shift;
|
56 |
my $command = shift;
|
56 |
qx/$command 2>&1/;
|
57 |
my $output = qx/$command 2>&1/;
|
57 |
if ($? == -1) {
|
58 |
if ($? == -1) {
|
58 |
return "failed to execute: $!";
|
59 |
return (-1, "failed to execute: $!" );
|
59 |
} elsif ($? & 127) {
|
60 |
} elsif ($? & 127) {
|
60 |
return sprintf "child died with signal %d, %s coredump",
|
61 |
return (-1,sprintf "child died with signal %d, %s coredump",
|
61 |
($? & 127), ($? & 128) ? 'with' : 'without';
|
62 |
($? & 127), ($? & 128) ? 'with' : 'without');
|
62 |
} else {
|
63 |
} else {
|
63 |
return sprintf "child exited with value %d", $? >> 8 if $? >> 8;
|
64 |
return ( $?>>8, sprintf "child exited with value %d", $? >> 8 ) if $? >> 8;
|
64 |
}
|
65 |
}
|
65 |
return 0;
|
66 |
return (0, $output);
|
66 |
}
|
67 |
}
|
67 |
|
68 |
|
68 |
# grabs the encryption key from the remote server, and uses it to unlock the
|
69 |
# grabs the encryption key from the remote server, and uses it to unlock the
|
69 |
# datasets, then mount the drives.
|
70 |
# datasets, then mount the drives.
|
70 |
# a return of '' is success, anything else is an error
|
71 |
# a return of '' is success, anything else is an error
|
Line 74... |
Line 75... |
74 |
&runCommand( "scp $config->{remoteMachine}->{ip}:$config->{remoteMachine}->{encryptionKeyPath} $config->{localMachine}->{encryptionKeyPath}" );
|
75 |
&runCommand( "scp $config->{remoteMachine}->{ip}:$config->{remoteMachine}->{encryptionKeyPath} $config->{localMachine}->{encryptionKeyPath}" );
|
75 |
# If we do not have the encryption key, we need to abort
|
76 |
# If we do not have the encryption key, we need to abort
|
76 |
return "Could not copy file $config->{remoteMachine}->{ip}:$config->{remoteMachine}->{encryptionKeyPath}, aborting"
|
77 |
return "Could not copy file $config->{remoteMachine}->{ip}:$config->{remoteMachine}->{encryptionKeyPath}, aborting"
|
77 |
unless -f $config->{'localMachine'}->{'encryptionKeyPath'};
|
78 |
unless -f $config->{'localMachine'}->{'encryptionKeyPath'};
|
78 |
my $error = '';
|
79 |
my $error = '';
|
- |
|
80 |
my $output = '';
|
79 |
# load the key into zfs and unlock all volumes
|
81 |
# load the key into zfs and unlock all volumes
|
80 |
$error = &runCommand( "zfs load-key -a" );
|
82 |
($error,$output) = &runCommand( "zfs load-key -a" );
|
81 |
# finally, remount all of the zfs shares which need the key
|
83 |
# finally, remount all of the zfs shares which need the key
|
82 |
$error = &runCommand( "zfs mount -a" ) unless $error;
|
84 |
($error,$output) = &runCommand( "zfs mount -a" ) unless $error;
|
83 |
# if we succeeded, we want to shred the keyfile
|
85 |
# if we succeeded, we want to shred the keyfile
|
84 |
&shredFile( $config->{localMachine}->{encryptionKeyPath} ) if -f $config->{localMachine}->{encryptionKeyPath};
|
86 |
&shredFile( $config->{localMachine}->{encryptionKeyPath} ) if -f $config->{localMachine}->{encryptionKeyPath};
|
85 |
return $error;
|
87 |
return $error;
|
86 |
}
|
88 |
}
|
87 |
|
89 |
|
Line 109... |
Line 111... |
109 |
# if neither exists, begin sync
|
111 |
# if neither exists, begin sync
|
110 |
sub checkMaintenance {
|
112 |
sub checkMaintenance {
|
111 |
my $config = shift;
|
113 |
my $config = shift;
|
112 |
# see if maintenance is set on remote. If so, simply return the message
|
114 |
# see if maintenance is set on remote. If so, simply return the message
|
113 |
if ( $config->{'remoteMachine'}->{'up'} ) {
|
115 |
if ( $config->{'remoteMachine'}->{'up'} ) {
|
114 |
if ( ! &runCommand( "ssh $configuration->{remoteMachine}->{ip} 'ls $configuration->{remoteMachine}->{maintenanceFlag}'" ) ) {
|
116 |
my ($error, $output) = &runCommand( "ssh $configuration->{remoteMachine}->{ip} 'ls $configuration->{remoteMachine}->{maintenanceFlag}'" );
|
- |
|
117 |
if ( ! $error ) {
|
115 |
# remove the file from the remote server
|
118 |
# remove the file from the remote server
|
116 |
&runCommand( "ssh $configuration->{remoteMachine}->{ip} 'rm $configuration->{remoteMachine}->{maintenanceFlag}'" );
|
119 |
&runCommand( "ssh $configuration->{remoteMachine}->{ip} 'rm $configuration->{remoteMachine}->{maintenanceFlag}'" );
|
117 |
# create a valid return, which will exit the program
|
120 |
# create a valid return, which will exit the program
|
118 |
return "Maintenance Flag found on remote machine";
|
121 |
return "Maintenance Flag found on remote machine";
|
119 |
}
|
122 |
}
|
Line 153... |
Line 156... |
153 |
|
156 |
|
154 |
$configuration = &readConfig($configFileName);
|
157 |
$configuration = &readConfig($configFileName);
|
155 |
|
158 |
|
156 |
&sendMail( "mc-009 has been started, " . ¤tTime() . " checking for maintenance mode", $configuration );
|
159 |
&sendMail( "mc-009 has been started, " . ¤tTime() . " checking for maintenance mode", $configuration );
|
157 |
# see if remote machine is up by sending one ping. Expect response in 5 seconds
|
160 |
# see if remote machine is up by sending one ping. Expect response in 5 seconds
|
158 |
$configuration->{'remoteMachine'}->{'up'} =
|
161 |
my ( $error,$output) = &runCommand( "ping -c 1 -t 5 " . $configuration->{'remoteMachine'}->{'ip'} );
|
159 |
! &runCommand( "ping -c 1 -t 5 " . $configuration->{'remoteMachine'}->{'ip'} );
|
162 |
$configuration->{'remoteMachine'}->{'up'} = ! $error;
|
160 |
|
163 |
|
161 |
push @status, "remote machine ($configuration->{'remoteMachine'}->{'ip'}) is " . ( $configuration->{'remoteMachine'}->{'up'} ? 'Up' : 'Down' ) . "\n";
|
164 |
push @status, "remote machine ($configuration->{'remoteMachine'}->{'ip'}) is " . ( $configuration->{'remoteMachine'}->{'up'} ? 'Up' : 'Down' ) . "\n";
|
162 |
# check for maintenance flags, exit if we should go into mainteannce mode
|
165 |
# check for maintenance flags, exit if we should go into mainteannce mode
|
163 |
#if ( my $result = &checkMaintenance( $configuration ) ) {
|
166 |
#if ( my $result = &checkMaintenance( $configuration ) ) {
|
164 |
# push @status,$result;
|
167 |
# push @status,$result;
|
Line 168... |
Line 171... |
168 |
|
171 |
|
169 |
# we can not connect to the remote server, so just shut down
|
172 |
# we can not connect to the remote server, so just shut down
|
170 |
&shutdownMachine( $configuration, "No connection to remote machine", @status ) unless $configuration->{'remoteMachine'}->{'up'};
|
173 |
&shutdownMachine( $configuration, "No connection to remote machine", @status ) unless $configuration->{'remoteMachine'}->{'up'};
|
171 |
|
174 |
|
172 |
# try to mount the datasets
|
175 |
# try to mount the datasets
|
173 |
my $error = &mountDrives( $configuration );
|
176 |
($error,$output) = &mountDrives( $configuration );
|
174 |
if ( $error ) { # could not mount datasets
|
177 |
if ( $error ) { # could not mount datasets
|
175 |
push @status, $error;
|
178 |
push @status, $error;
|
176 |
&shutdownMachine( $configuration, "Mount Drive Error", @status );
|
179 |
&shutdownMachine( $configuration, "Mount Drive Error: [$output]", @status );
|
177 |
}
|
180 |
}
|
178 |
|
181 |
|
179 |
&sendMail( "Backup has been started at " . ¤tTime(), $configuration, "Backup Starting" );
|
182 |
&sendMail( "Backup has been started at " . ¤tTime(), $configuration, "Backup Starting" );
|
180 |
push @status, "Backup started at: " . ¤tTime();
|
183 |
push @status, "Backup started at: " . ¤tTime();
|
181 |
|
184 |
|
Line 184... |
Line 187... |
184 |
foreach my $sourceDir ( keys %{$configuration->{'remoteMachine'}->{'dataset'}} ) {
|
187 |
foreach my $sourceDir ( keys %{$configuration->{'remoteMachine'}->{'dataset'}} ) {
|
185 |
my $command = $replicateScript . ' ' .
|
188 |
my $command = $replicateScript . ' ' .
|
186 |
$configuration->{'remoteMachine'}->{'ip'} . ':' .
|
189 |
$configuration->{'remoteMachine'}->{'ip'} . ':' .
|
187 |
$configuration->{'remoteMachine'}->{'dataset'}->{$sourceDir} . '/' . $sourceDir . ' ' .
|
190 |
$configuration->{'remoteMachine'}->{'dataset'}->{$sourceDir} . '/' . $sourceDir . ' ' .
|
188 |
$configuration->{'localMachine'}->{'targetDataset'} . '/' . $sourceDir;
|
191 |
$configuration->{'localMachine'}->{'targetDataset'} . '/' . $sourceDir;
|
189 |
push @status, "Running $command at " . ¤tTime();
|
192 |
push @status, "=== Running $command at " . ¤tTime();
|
190 |
push @status, &runCommand( $command );
|
193 |
my ($error, $output) = &runCommand( $command );
|
- |
|
194 |
push @status, $output;
|
191 |
push @status, "Completed $command at " . ¤tTime();
|
195 |
push @status, "=== Completed $command with status $error at " . ¤tTime();
|
192 |
}
|
196 |
}
|
193 |
|
197 |
|
194 |
push @status, "Backup finished at: " . ¤tTime();
|
198 |
push @status, "==== Backup finished at: " . ¤tTime();
|
195 |
|
199 |
|
196 |
&shutdownMachine( $configuration, "Backup Complete", @status );
|
200 |
&shutdownMachine( $configuration, "Backup Complete", @status );
|
197 |
|
201 |
|
198 |
1;
|
202 |
1;
|