Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Application and script abstract classes #78

Open
wants to merge 63 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
571f1bd
Working proof of concept.
Jun 1, 2017
94b7f3b
Now with amgrowingfile application.
Jun 1, 2017
bd31ada
Add amgrowingzip application.
Jun 1, 2017
47c7c2e
Add amopaquetree application.
Jun 1, 2017
b7fd4ac
Let application override Amanda localstatedir.
Jun 1, 2017
88b443f
Don't preserve times in capture_rsync_state.
Mar 24, 2017
191e70b
Drop use of --device in inner_restore.
Jun 15, 2016
b6b8cd1
Drop use of --device in inner_restore.
Jun 1, 2017
e6e1322
Add an amsvnmakehotcopy script.
Jun 5, 2017
d179dd7
First cut script to back up from an lvm snapshot.
Jun 5, 2017
d94ff56
Allow mount options for amlvmsnapshot.
May 18, 2017
f73a7d2
A script to freeze/thaw filesystems through libvirt.
Jun 5, 2017
009caf0
Allow amlibvirtfsfreeze without mountpoints.
May 18, 2017
3bc9ded
Add more stages where amlvmsnapshot can be run.
May 18, 2017
7fa8e8e
Add an am389bak script.
Jun 5, 2017
9141bd4
Fail amgrowingzip gracefully without Archive::Zip.
Jun 14, 2017
79209e0
Fail amopaquetree gracefully if no rsync.
Jun 16, 2017
2754e67
Merge abstract app and script base classes.
Aug 10, 2017
07ffd1f
In passing, drop stray script from list of apps.
Aug 10, 2017
2a635a2
Installchecks for the new applications.
Aug 10, 2017
64eb1db
Add amzfs-holdsend application.
Aug 25, 2017
f4ee4ff
Account for compression in estimate.
Aug 28, 2017
3711d90
Support faster estimates with send -nvP.
Aug 29, 2017
bb94326
Support compressed send streams.
Aug 29, 2017
4ff6a90
Add support for newfangled OpenZFS options.
Aug 29, 2017
4881c74
Merge new amzfs-holdsend application.
Aug 30, 2017
8671e3d
Use fdin/fdout consistently, not infd/outfd.
Sep 1, 2017
6a9fa04
Call write_local_state from command_backup.
Sep 1, 2017
ed7a7a0
Remember supports() is a class method.
Sep 1, 2017
476f403
Merge 9/1/2017 changes.
Sep 1, 2017
b76ff0b
Forgot to edit amanda-applications(7) in 4881c74.
Sep 5, 2017
5809c06
Admit level-to-snapshot map changes.
Sep 14, 2017
ba4165f
Better encapsulate option handling details.
Sep 15, 2017
ea29a69
Make max_level a class method.
Sep 15, 2017
f8069c7
Add properties for svn hotcopy options.
Sep 15, 2017
d7057ee
Implement 'support' and timestamp property.
Sep 17, 2017
31cd2b6
Merge timestamp support and other 9/16/2017 changes.
Sep 17, 2017
1c27753
Support --timestamp in applications.
Sep 21, 2017
22dff1f
Straggling option-handling changes.
Sep 27, 2017
335bfef
First stage refit to use exceptions.
Sep 28, 2017
65977d8
Refactor option checking.
Sep 28, 2017
c2710b0
Use exceptions, factor out BigInt conversions.
Sep 29, 2017
10464a7
More use of exceptions.
Oct 4, 2017
69cac79
Exceptions to handle out-of-sequence levels.
Oct 5, 2017
1490eb6
Let a retry exception be thrown by backup.
Oct 5, 2017
a666c64
More timestamps, levels, retries, exceptions.
Oct 5, 2017
ca46453
Have apps consistently use TARGET.
Oct 10, 2017
c86edde
Add exceptions to Amanda::Script::Abstract.
Oct 12, 2017
870b378
Support TARGET in apps, and exceptions in scripts.
Oct 13, 2017
4c643bf
Make use of backup success report from server.
Oct 23, 2017
941b9e5
Merge server backup result support.
Oct 23, 2017
7fe2b32
Correct handling of unrecognized exceptions.
Nov 1, 2017
762a11c
Check data_percent when removing snapshot.
Nov 2, 2017
794a544
Merge Abstract.pm bug fix.
Nov 2, 2017
e2d3df5
Add method to set property from script.
Nov 8, 2017
3075d8e
Merge LVM snapshot check, and properties from scripts.
Nov 10, 2017
dbc13dd
Pass FAILURE to print_to_server_and_die.
Dec 6, 2017
2085ef0
Document FAILURE as allowed print_to_server* status code.
Dec 6, 2017
b6d8288
Merge 6 December AppScriptAbstractClasses changes.
Dec 6, 2017
590d314
Allow amlibvirtfsfreeze to also trim.
Jan 3, 2018
7488567
Merge Jan 3 addition of trim for virtfs.
Jan 29, 2018
15eb57a
Skip trim/freeze/thaw for non-running domains
Nov 10, 2020
231f1d4
Merge non-running libvirt domain check
jcflack Nov 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions application-src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,17 @@ AM_LDFLAGS = $(AMANDA_STATIC_LDFLAGS) $(AS_NEEDED_FLAGS)
applicationexec_SCRIPTS_SHELL = script-fail

applicationexec_SCRIPTS_PERL = script-email \
am389bak \
amgrowingfile \
amgrowingzip \
amlibvirtfsfreeze \
amlog-script \
amlvmsnapshot \
amooraw \
amopaquetree \
ampgsql \
amsvnmakehotcopy \
amzfs-holdsend \
amzfs-sendrecv \
amzfs-snapshot \
amrandom \
Expand Down
95 changes: 95 additions & 0 deletions application-src/am389bak.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#!@PERL@
# This copyright apply to all codes written by authors that made contribution
# made under the BSD license. Read the AUTHORS file to know which authors made
# contribution made under the BSD license.
#
# The 3-Clause BSD License

# Copyright 2017 Purdue University
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

use lib '@amperldir@';
use strict;
use warnings;

package Amanda::Script::Am389Bak;

use base 'Amanda::Script::Abstract';

use File::Spec;
use File::Path qw(make_path remove_tree);
use IO::File;

sub new {
my ( $class, $execute_where, $refopthash ) = @_;
my $self = $class->SUPER::new($execute_where, $refopthash);

return $self;
}

sub check_properties {
my ( $self ) = @_;

$self->{'db2bakexecutable'} = $self->{'options'}->{'db2bakexecutable'};

$self->{'instance'} = $self->{'options'}->{'instance'};
if ( !defined $self->{'instance'} ) {
die Amanda::Script::InvocationError->transitionalError(
item => 'property', value => 'instance', problem => 'missing');
}
}

sub declare_options {
my ( $class, $refopthash, $refoptspecs ) = @_;
$class->SUPER::declare_options($refopthash, $refoptspecs);
push @$refoptspecs, ( 'db2bakexecutable=s', 'instance=s' );

$class->store_option($refopthash, 'db2bakexecutable', 'db2bak');
}

sub command_pre_dle_estimate {
my ( $self ) = @_;

my $repo = $self->{'instance'};
my $dst = $self->{'options'}->{'device'};

make_path($dst);
remove_tree($dst, {keep_root => 1});

my $rslt = system {$self->{'db2bakexecutable'}} (
'db2bak', $dst, '-qZ', $repo );

unless ( 0 == $rslt ) {
die Amanda::Script::CalledProcessError->transitionalError(
cmd => 'db2bak', returncode => $rslt);
}
}

package main;

Amanda::Script::Am389Bak->run();
204 changes: 204 additions & 0 deletions application-src/amgrowingfile.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
#!@PERL@
# This copyright apply to all codes written by authors that made contribution
# made under the BSD license. Read the AUTHORS file to know which authors made
# contribution made under the BSD license.
#
# The 3-Clause BSD License

# Copyright 2017 Purdue University
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

use lib '@amperldir@';
use strict;
use warnings;

package Amanda::Application::AmGrowingFile;

use base 'Amanda::Application::Abstract';

use Data::Dumper;
use File::Spec;
use File::Path qw(make_path);

sub supports_host { my ( $class ) = @_; return 1; }
sub supports_disk { my ( $class ) = @_; return 1; }
sub supports_index_line { my ( $class ) = @_; return 1; }
sub supports_message_line { my ( $class ) = @_; return 1; }
sub supports_record { my ( $class ) = @_; return 1; }
sub supports_client_estimate { my ( $class ) = @_; return 1; }
sub supports_multi_estimate { my ( $class ) = @_; return 1; }

sub max_level { my ( $class ) = @_; return 'DEFAULT'; }

sub new {
my ( $class, $refopthash ) = @_;
my $self = $class->SUPER::new($refopthash);
$self->{'localstate'} =
$self->read_local_state(['level=i', 'byteoffset=s', 'bytes=s']);
return $self;
}

sub declare_restore_options {
my ( $class, $refopthash, $refoptspecs ) = @_;
$class->SUPER::declare_restore_options($refopthash, $refoptspecs);
push @$refoptspecs, ( 'filename=s' );
}

sub inner_estimate {
my ( $self, $level ) = @_;
my $fn = $self->target();
my $sz = $self->int2big(-s $fn);
return $sz if 0 == $level;

my $mxl = $self->{'localstate'}->{'maxlevel'};

die Amanda::Application::DiscontiguousLevelError->transitionalError(
value => $level) if $level > $mxl;

my $lowerstate = $self->{'localstate'}->{$level - 1};
my $loweroffset = Math::BigInt->new($lowerstate->{'byteoffset'});
my $lowersize = Math::BigInt->new($lowerstate->{'bytes'});
return $sz->bsub($loweroffset)->bsub($lowersize);
}

sub inner_backup {
# XXX assert level==0 if no --record
my ( $self, $fdout ) = @_;
my $fn = $self->target();
my $level = $self->{'options'}->{'level'};
my $fdin = POSIX::open($fn, &POSIX::O_RDONLY);

if (!defined $fdin) {
die Amanda::Application::EnvironmentError->transitionalError(
item => 'target', value => $fn, errno => $!);
}

my $start;
if ( 0 == $level ) {
$start = Math::BigInt->bzero();
} else {
my $lowerstate = $self->{'localstate'}->{$level - 1};
die Amanda::Application::DiscontiguousLevelError->transitionalError(
value => $level) unless defined $lowerstate;
my $loweroffset = Math::BigInt->new($lowerstate->{'byteoffset'});
my $lowersize = Math::BigInt->new($lowerstate->{'bytes'});
$start = $loweroffset->copy()->badd($lowersize);
my $istart = $self->big2int($start);

die Amanda::Application::RetryDumpError->transitionalError(
delay => 0, level => 0, problem => 'growing file shrank')
if $istart > (POSIX::fstat($fdin))[7];

# Currently science fiction: optionally include in the state a digest
# of the file's past contents, to force a retry at level 0 in case of
# mismatch even if size does not catch it. Of course that would turn
# every incremental dump into a level-0 amount of I/O (well, I, anyway).

POSIX::lseek($fdin, $istart, &POSIX::SEEK_SET);

# sendbackup: HEADER, documented in the Application API/Operations wiki
# page, wasn't ever implemented, according to Jean-Louis. An option that
# becomes available in 3.3.8 is 'sendbackup: state' and retrieved with
# --recover-dump-state-file. The state file is kept on the server, not
# clear how /it/ is backed up. May not be available if recovering only
# from the tape.
#
# print {$self->{mesgout}} "sendbackup: HEADER startoffset=$start\n";
#
# Without doing this, can just /assume/ that the file is currently as
# the lower-level restore left it, and append to the end. Not ideal,
# but other incremental strategies also perform restores without
# rigorous verification of the state they are restoring onto, so when
# in Rome....
}
my $size = $self->shovel($fdin, $fdout);

die Amanda::Application::EnvironmentError->transitionalError(
item => 'target', value => $fn, problem => 'close', errno => $!)
unless defined POSIX::close($fdin);

$self->emit_index_entry('/');

if ( $self->{'options'}->{'record'} ) {
$self->update_local_state($self->{'localstate'}, $level, {
'byteoffset' => $start->bstr(), 'bytes' => $size->bstr() });
}

return $size;
}

sub inner_restore {
my $self = shift;
my $fdin = shift;
my $dsf = shift;
my $level = $self->{'options'}->{'level'};

if ( 1 != scalar(@_) or $_[0] ne '.' ) {
die Amanda::Application::InvocationError->transitionalError(
item => 'restore targets',
problem => 'Only one (.) supported');
}

my $fn = $self->target('amgrowingfile-restored');

my ( $volume, $directories, $file ) = File::Spec->splitpath($fn);
make_path(File::Spec->catpath($volume, $directories, ''));

# Where to begin writing if applying a level > 0 (incremental) dump?
# In a cautious world, save the starting offset at dump time, and verify
# at restore time that that's where the file ends. That could require either
# saving the offset in the dump stream somehow, or using the server-side
# state file that appears in 3.3.8 (which still might not be available in a
# restoration from only the tape). Short of that, just blindly open in
# append mode and write the increment. After all, does an incremental tar
# restore actually verify the current directory tree is exactly as the prior
# dump level left it? No, it just relies on restoration being done carefully
# and in sequence.
my $oflags = &POSIX::O_RDWR;
if ( $level > 0 ) {
$oflags |= &POSIX::O_APPEND;
} else {
$oflags |= ( &POSIX::O_CREAT | &POSIX::O_TRUNC );
}

my $fdout = POSIX::open($fn, $oflags, 0600);
if (!defined $fdout) {
die Amanda::Application::EnvironmentError->transitionalError(
item => 'target', value => $fn, errno => $!);
}

$self->shovel($fdin, $fdout);
die Amanda::Application::EnvironmentError->transitionalError(
item => 'target', value => $fn, problem => 'close', errno => $!)
unless defined POSIX::close($fdout);
POSIX::close($fdin);
}

package main;

Amanda::Application::AmGrowingFile->run();
Loading