# Copyright 1999-2016. Parallels IP Holdings GmbH. All Rights Reserved. package Storage::ArchiveStorage; use strict; use warnings; use File::Basename qw(basename); use IPC::Run; use HelpFuncs; use Logging; use Storage::Storage; use vars qw|@ISA|; @ISA = qw|Storage::Storage|; sub _init { my ($self, %options) = @_; $self->SUPER::_init(%options); $self->{exportDir} = $options{'export-dir'}; $self->{ftp} = $options{'ftp'}; $self->{sessionPath} = $options{'session-path'}; $self->{verbose} = $options{'verbose'}; $self->{cmd} = undef; $self->{cmdInput} = ''; $self->{cmdOutput} = ''; Logging::debug("-" x 60); Logging::debug("ARCHIVE storage initialized."); Logging::debug("Base directory: $self->{output_dir}"); Logging::debug("Space reserved: $self->{space_reserved}"); Logging::debug("Gzip bundles: " . ($self->{gzip_bundle} ? "yes" : "no")); Logging::debug("Bundle split size: " . ($self->{split_size} || "do not split")); Logging::debug("-" x 60); $self->reserveSpace(); } sub finishExport { my $self = shift; my $mainDumpFile = $self->getMainDumpXmlRelativePath(); if ($mainDumpFile) { my $mainDumpFileName = basename($mainDumpFile); eval { Logging::debug("Add file $mainDumpFileName to archive"); $self->{cmdInput} .= "$mainDumpFileName\n"; IPC::Run::pump($self->_getCmd()); }; if ($@) { Logging::warning(sprintf('Unable to upload dump file %s to FTP storage: %s', $mainDumpFileName, $@)); } } $self->_finishCmd(); } sub createRepositoryIndex{ my ($self, $index) = @_; } sub writeDiscovered{ my $self = shift; $self->_writeDiscovered(@_); } sub moveFileToDiscovered { my $self = shift; $self->_moveFileToDiscovered(@_); } sub addTar { my $self = shift; my ($ret, $destDir, $files) = @{$self->_addTar(@_)}; return $ret unless $ret; my $file; eval { my $dumpStorage = $self->{mainDumpRootPath} ? sprintf('%s/%s', $self->{output_dir}, $self->{mainDumpRootPath}) : $self->{output_dir}; my $destDirRelativePath = substr($destDir, length($dumpStorage)); $destDirRelativePath =~ s/^\/+//; foreach my $fileInfo (@{$files}) { my ($fileName) = @{$fileInfo}; $file = $destDirRelativePath ? sprintf('%s/%s', $destDirRelativePath, $fileName) : $fileName; Logging::debug("Add file $file to archive"); $self->{cmdInput} .= "$file\n"; IPC::Run::pump($self->_getCmd()); } }; if ($@) { Logging::warning(sprintf('Unable to upload archive %s to FTP storage: %s', $file, $@)); $self->_finishCmd(); } return $ret; } sub _getCmd { my $self = shift; if (!$self->{cmd}) { my $command = [AgentConfig::pmmRasBin(), '--export-dump-as-file']; if ($self->{ftp}) { $ENV{'DUMP_STORAGE_PASSWD'} = $self->{ftp}->{password}; push(@{$command}, '--dump-file-specification', sprintf('%s/%s', HelpFuncs::getStorageUrlFromFtpSettings($self->{ftp}), $self->{exportFileName})); push(@{$command}, '--use-ftp-passive-mode') if exists($self->{ftp}->{'passive'}); } else { push(@{$command}, '--dump-file-specification', sprintf('%s/%s', $self->{exportDir}, $self->{exportFileName})); } push(@{$command}, '--dump-storage', sprintf('%s/%s', $self->{output_dir}, $self->{mainDumpRootPath})); push(@{$command}, '--split-size', $self->{split_size}) if $self->{split_size}; push(@{$command}, '--session-path', $self->{sessionPath}) if $self->{sessionPath}; push(@{$command}, '--debug', '--verbose') if $self->{verbose}; Logging::debug('Start: ' . join(' ', @{$command})); $self->{cmd} = IPC::Run::start($command, \$self->{cmdInput}, \$self->{cmdOutput}, '2>/dev/null'); } return $self->{cmd}; } sub _finishCmd { my $self = shift; if ($self->{cmd}) { my @createdVolumes = (); eval { $self->{cmd}->finish() or die(sprintf('%s command completed with non-zero exit code %s', basename(AgentConfig::pmmRasBin()), $self->{cmd}->result())); @createdVolumes = split("\n", $self->{cmdOutput}) if $self->{cmdOutput}; }; if ($@) { Logging::warning(sprintf("Unable to upload backup files to FTP storage: %s\nSTDOUT: %s", $@, $self->{cmdOutput})); } $self->{cmd} = undef; $self->{cmdInput} = ''; $self->{cmdOutput} = ''; $self->{createdVolumes} = \@createdVolumes; } } 1;