Subversion Repositories zfs_utils

Rev

Rev 7 | Rev 11 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 7 Rev 10
Line 13... Line 13...
13
   use lib dirname( abs_path( __FILE__ ) );
13
   use lib dirname( abs_path( __FILE__ ) );
14
}
14
}
15
 
15
 
16
use YAML::Tiny; # pkg install p5-YAML-Tiny-1.74
16
use YAML::Tiny; # pkg install p5-YAML-Tiny-1.74
17
use Data::Dumper;
17
use Data::Dumper;
18
use Email::Simple; # cpan install Email::Simple
18
#use Email::Simple; # cpan install Email::Simple
19
 
19
 
20
my $cwd = $FindBin::RealBin;
20
my $cwd = $FindBin::RealBin;
21
my $configFileName = $cwd . '/sync.yaml';
21
my $configFileName = $cwd . '/sync.yaml';
22
my $replicateScript = $cwd . '/replicate';
22
my $replicateScript = $cwd . '/replicate';
23
 
23
 
Line 34... Line 34...
34
      $yaml = YAML::Tiny->read( $filename );
34
      $yaml = YAML::Tiny->read( $filename );
35
   }
35
   }
36
   return $yaml->[0];
36
   return $yaml->[0];
37
}
37
}
38
 
38
 
-
 
39
sub logit {
-
 
40
   open LOG, ">>/tmp/replicate.log" or die "Could not open replicate.log: $!\n";
-
 
41
   print LOG join( "\n", @_ ) . "\n";
-
 
42
   close LOG;
-
 
43
}
39
 
44
 
40
 
45
 
41
# this calls gshred which will overwrite the file 3 times, then
46
# this calls gshred which will overwrite the file 3 times, then
42
# remove it.
47
# remove it.
43
# NOTE: this will not work on ZFS, since ZFS is CopyOnWrite (COW)
48
# NOTE: this will not work on ZFS, since ZFS is CopyOnWrite (COW)
Line 51... Line 56...
51
# runs a command, redirecting stderr to stdout (which it ignores)
56
# runs a command, redirecting stderr to stdout (which it ignores)
52
# then returns 0 on success.
57
# then returns 0 on success.
53
# if error, returns string describing error
58
# if error, returns string describing error
54
sub runCommand {
59
sub runCommand {
55
   my $command = shift;
60
   my $command = shift;
-
 
61
   #logit( $command );
56
   my $output = qx/$command 2>&1/;
62
   my $output = qx/$command 2>&1/;
57
   if ($? == -1) {
63
   if ($? == -1) {
58
      return (-1, "failed to execute: $!" );
64
      return (-1, "failed to execute: $!" );
59
   } elsif ($? & 127) {
65
   } elsif ($? & 127) {
60
      return (-1,sprintf "child died with signal %d, %s coredump",
66
      return (-1,sprintf "child died with signal %d, %s coredump",
Line 85... Line 91...
85
   # if we succeeded, we want to shred the keyfile
91
   # if we succeeded, we want to shred the keyfile
86
   &shredFile( $configuration->{localMachine}->{encryptionKeyPath} ) if -f $configuration->{localMachine}->{encryptionKeyPath};
92
   &shredFile( $configuration->{localMachine}->{encryptionKeyPath} ) if -f $configuration->{localMachine}->{encryptionKeyPath};
87
   return $error;
93
   return $error;
88
}
94
}
89
 
95
 
90
# a very simple mailer, using Email::Simple to just get status messages out
96
# a very simple mailer, just send information to sendmail
91
sub sendMail {
97
sub sendMail {
92
   my ($message, $configuration, $subject ) = @_;
98
   my ($message, $configuration, $subject ) = @_;
-
 
99
   if ( $message ) {
93
   $configuration->{'email'}->{'notify'} = 'root' unless $configuration->{'email'}->{'notify'};
100
      open MAIL,"|sendmail -t" or die "Could not open sendmail: $!\n";
94
   die "No message in outgoing message\n" unless $message;
101
      print MAIL "To: $configuration->{email}->{notify}\n";
95
   my $email = Email::Simple->create(
102
      print MAIL "From: $configuration->{email}->{from}\n";
96
      header => [
103
      print MAIL "Subject: " . 
97
         To     => $configuration->{'email'}->{'notify'},
-
 
98
         Subject=> $configuration->{'email'}->{'subject'} . ( $subject ? " - $subject" : '' ),
104
                 ($configuration->{'email'}->{'subject'} . ( $subject ? " - $subject" : '' ) ) .
99
         From   => $configuration->{'email'}->{'from'}
105
                 "\n\n";
100
      ],
-
 
101
      body => $message
106
      print MAIL $message;
102
   );
-
 
103
   $message = $email->as_string;
-
 
104
   if ( $configuration->{'testing'} > 1 ) {
-
 
105
      print "$message\n";
107
      close MAIL;
106
   } else {
108
   } else {
107
      `echo '$message' | sendmail $configuration->{'email'}->{'notify'}`;
109
      warn "no message in outgoing email\n";
108
   }
110
   }
-
 
111
#   $message =~ s/\(/\\(/g;
-
 
112
#   $message =~ s/\)/\\)/g;
-
 
113
#   $configuration->{'email'}->{'notify'} = 'root' unless $configuration->{'email'}->{'notify'};
-
 
114
#   die "No message in outgoing message\n" unless $message;
-
 
115
#   my $email = Email::Simple->create(
-
 
116
#      header => [
-
 
117
#         To     => $configuration->{'email'}->{'notify'},
-
 
118
#         Subject=> $configuration->{'email'}->{'subject'} . ( $subject ? " - $subject" : '' ),
-
 
119
#         From   => $configuration->{'email'}->{'from'}
-
 
120
#      ],
-
 
121
#      body => $message
-
 
122
#   );
-
 
123
#   $message = $email->as_string;
-
 
124
#   #warn "Message is\n$message\n\n";
-
 
125
#   if ( $configuration->{'testing'} > 1 ) {
-
 
126
#      print "$message\n";
-
 
127
#   } else {
-
 
128
#      `echo '$message' | sendmail $configuration->{'email'}->{'notify'}`;
-
 
129
#   }
109
}
130
}
110
 
131
 
111
# checks to see if we should be in maintenance mode
132
# checks to see if we should be in maintenance mode
112
# if $remoteMachine->{'maintenanceMode'} exists, set mode
133
# if $remoteMachine->{'maintenanceMode'} exists, set mode
113
# otherwise, wait localMachine->{'waittime'} minutes, then check
134
# otherwise, wait localMachine->{'waittime'} minutes, then check
Line 141... Line 162...
141
   return 0;
162
   return 0;
142
}
163
}
143
 
164
 
144
sub shutdownMachine {
165
sub shutdownMachine {
145
   my $configuration = shift;
166
   my $configuration = shift;
146
   my $subject = shift;
-
 
147
   push @_, "Shutting down" if $configuration->{'shutdown'};
-
 
148
   &sendMail( join( "\n", @_), $configuration, $subject );
-
 
149
   # do not actually shut down the server unless we are told to
-
 
150
   exit unless $configuration->{'shutdown'};
167
   exit unless $configuration->{'shutdown'};
151
   die "Shutting down machine now\n";
168
   # do not actually shut down the server unless we are told to
152
   &runCommand( "poweroff" ) unless $configuration->{'testing'};
169
   &runCommand( "poweroff" ) unless $configuration->{'testing'};
153
}
170
}
154
 
171
 
155
# returns the current time as a string
172
# returns the current time as a string
156
sub currentTime {
173
sub currentTime {
Line 192... Line 209...
192
 
209
 
193
# see if remote machine is up by sending one ping. Expect response in 5 seconds
210
# see if remote machine is up by sending one ping. Expect response in 5 seconds
194
( $error,$output) = &checkRemoteUp( $configuration );
211
( $error,$output) = &checkRemoteUp( $configuration );
195
$configuration->{'up'} = ! $error;
212
$configuration->{'up'} = ! $error;
196
push @status, "remote machine is " . ( $configuration->{'up'} ? 'Up' : 'Down' ) . "\n";
213
push @status, "remote machine is " . ( $configuration->{'up'} ? 'Up' : 'Down' ) . "\n";
-
 
214
if ( ! $configuration->{'up'} ) {
197
# we can not connect to the remote server, so just shut down
215
   # we can not connect to the remote server, so just shut down
198
&shutdownMachine( $configuration, "No connection to remote machine", @status ) unless $configuration->{'up'};
216
   sendMail( join( "\n", @status ), $configuration, "No connection to remote machine" );
-
 
217
   &shutdownMachine( $configuration );
-
 
218
}
199
 
219
 
200
# check for maintenance flags, exit if we should go into mainteance mode
220
# check for maintenance flags, exit if we should go into mainteance mode
201
if ( my $result = &checkMaintenance( $configuration ) ) {
221
if ( my $result = &checkMaintenance( $configuration ) ) {
202
   push @status,$result;
222
   push @status,$result;
203
   &sendMail( join( "\n", @status), $configuration, "Maintenance Mode" );
223
   &sendMail( join( "\n", @status), $configuration, "Maintenance Mode" );
Line 205... Line 225...
205
}
225
}
206
 
226
 
207
# try to mount the datasets if they are encrypted
227
# try to mount the datasets if they are encrypted
208
($error,$output) = &mountDrives( $configuration );
228
($error,$output) = &mountDrives( $configuration );
209
if ( $error ) { # could not mount datasets
229
if ( $error ) { # could not mount datasets
210
   push @status, $error;
230
   push @status, $output;
211
   &shutdownMachine( $configuration, "Mount Drive Error: [$output]", @status );
231
   &sendMail( join( "\n", @status ), $configuration, "Mount Drive Error: [$output]" );
-
 
232
   &shutdownMachine( $configuration );
212
}
233
}
213
 
234
 
214
&sendMail( "Backup has been started at " . &currentTime(), $configuration, "Backup Starting" );
235
#&sendMail( "Backup has been started at " . &currentTime(), $configuration, "Backup Starting" );
215
push @status, &currentTime() . ' Backup started';
236
push @status, &currentTime() . ' Backup started';
216
 
237
 
217
$configuration->{'source'}->{'server'} = $configuration->{'source'}->{'server'} ? $configuration->{'source'}->{'server'} . ':' : '';
238
$configuration->{'source'}->{'server'} = $configuration->{'source'}->{'server'} ? $configuration->{'source'}->{'server'} . ':' : '';
218
$configuration->{'target'}->{'server'} = $configuration->{'target'}->{'server'} ? $configuration->{'target'}->{'server'} . ':' : '';
239
$configuration->{'target'}->{'server'} = $configuration->{'target'}->{'server'} ? $configuration->{'target'}->{'server'} . ':' : '';
219
 
240
 
220
my @flags;
241
my @flags;
221
push @flags, '--dryrun' if $configuration->{'dryrun'};
242
push @flags, '--dryrun' if $configuration->{'dryrun'};
222
push @flags, '--recurse' if $configuration->{'recurse'};
243
push @flags, '--recurse' if $configuration->{'recurse'};
223
push @flags, '--verbose' if $configuration->{'verbose'};
244
push @flags, '--verbose' if $configuration->{'verbose'};
224
push @flags, '--verbose' if $configuration->{'verbose'} > 1;
245
push @flags, '--verbose' if $configuration->{'verbose'} > 1;
225
push @flags, "--bwlimit=$configuration->{bandwidth}" if $configuration->{'bandwidt'};
246
push @flags, "--bwlimit=$configuration->{bandwidth}" if $configuration->{'bandwidth'};
226
push @flags, "--filter='$configuration->{filter}'" if $configuration->{'filter'};
247
push @flags, "--filter='$configuration->{filter}'" if $configuration->{'filter'};
227
 
248
 
228
# For each dataset, let's find the snapshots we need
249
# For each dataset, let's find the snapshots we need
229
foreach my $sourceDir ( keys %{$configuration->{'source'}->{'dataset'}} ) {
250
foreach my $sourceDir ( keys %{$configuration->{'source'}->{'dataset'}} ) {
-
 
251
   #print "Working on $sourceDir\n";
230
   print "Looking for $sourceDir\n" if $configuration->{'testing'} > 2;
252
   print "Looking for $sourceDir\n" if $configuration->{'testing'} > 2;
231
   print "syncing to $configuration->{target}->{dataset}\n" if $configuration->{'testing'} > 2;
253
   print "syncing to $configuration->{target}->{dataset}\n" if $configuration->{'testing'} > 2;
232
   my $command = $replicateScript . ' ' . join( ' ', @flags ) . ' ' .
254
   my $command = $replicateScript . ' ' . join( ' ', @flags ) . ' ' .
233
                 '--source=' .
255
                 '--source=' .
234
                 $configuration->{'source'}->{'server'} . 
256
                 $configuration->{'source'}->{'server'} . 
235
                 $configuration->{'source'}->{'dataset'}->{$sourceDir} . '/' . $sourceDir . ' ' .
257
                 $configuration->{'source'}->{'dataset'}->{$sourceDir} . '/' . $sourceDir . ' ' .
236
                 '--target=' .
258
                 '--target=' .
237
                 $configuration->{'target'}->{'server'} . 
259
                 $configuration->{'target'}->{'server'} . 
238
                 $configuration->{'target'}->{'dataset'} . '/' . $sourceDir;
260
                 $configuration->{'target'}->{'dataset'} . '/' . $sourceDir;
-
 
261
   #print "Command is $command\n";
239
   push @status, &currentTime() . " Running $command";
262
   push @status, &currentTime() . " Running $command";
240
   if ( ! $configuration->{'testing'} ) {
263
   if ( ! $configuration->{'testing'} ) {
241
      ($error, $output) = &runCommand( $command );
264
      ($error, $output) = &runCommand( $command );
242
      push @status, $output;
265
      push @status, $output;
243
   }
266
   }
244
   push @status, &currentTime() . " Completed command, with status $error";
267
   push @status, &currentTime() . " Completed command, with status $error";
245
}
268
}
246
 
269
 
-
 
270
#print "Finished processing\n";
-
 
271
#print "testing is " . $configuration->{'testing'} . "\n";
-
 
272
 
247
push @status, &currentTime() . ' Backup finished';
273
push @status, &currentTime() . ' Backup finished';
248
 
274
 
249
if ($configuration->{'testing'}) {
275
if ($configuration->{'testing'}) {
250
   print join( "\n", @status ) . "\n";
276
   print join( "\n", @status ) . "\n";
251
} else {
277
} else {
-
 
278
   #print "Sending final email\n";
-
 
279
   &sendMail( join( "\n", @status ), $configuration, "Backup Complete" );
-
 
280
   #print "Running shutdown\n";
252
   &shutdownMachine( $configuration, "Backup Complete", @status );
281
   &shutdownMachine( $configuration ) if $configuration->{'shutdown'};
253
}
282
}
254
 
283
 
255
1;
284
1;