Restore.php

This commit is contained in:
fogelito
2023-08-14 20:06:00 +03:00
parent 302e0f6341
commit 90e8395578
2 changed files with 89 additions and 118 deletions
+19 -21
View File
@@ -31,8 +31,6 @@ class Backup extends Action
*/
public function __construct()
{
$this->checkEnvVariables();
$this
->desc('Backup a database')
->param('database', null, new Text(20), 'Database name, for example db_fra1_01')
@@ -50,6 +48,8 @@ class Backup extends Action
*/
public function action(string $database, Group $pools): void
{
$this->checkEnvVariables();
$this->database = $database;
$this->dsn = $this->getDsn($database);
if (is_null($this->dsn)) {
@@ -88,8 +88,8 @@ class Backup extends Action
}
} while ($attempts < $max);
$this->setProcessors();
$this->setContainerId();
$this->setProcessors();
//sleep(20);
@@ -151,7 +151,6 @@ class Backup extends Action
'--compress=' . self::COMPRESS_ALGORITHM,
'--compress-threads=' . $this->processors,
'--parallel=' . intval($this->processors / 2),
//'--rsync', // https://docs.percona.com/percona-xtrabackup/8.0/accelerate-backup-process.html
'> ' . $file,
'2> ' . $log,
];
@@ -234,22 +233,6 @@ class Backup extends Action
return null;
}
public function setProcessors()
{
$stdout = '';
$stderr = '';
Console::execute('nproc', '', $stdout, $stderr);
if (!empty($stderr)) {
Console::error('Error setting processors: ' . $stderr);
Console::exit();
}
$processors = str_replace(PHP_EOL, '', $stdout);
$processors = intval($processors);
$processors = $processors === 0 ? 1 : $processors;
$this->processors = $processors;
}
public function setContainerId()
{
$stdout = '';
@@ -261,7 +244,6 @@ class Backup extends Action
}
$containerId = str_replace(PHP_EOL, '', $stdout);
if (empty($containerId)) {
Console::error('Xtrabackup Container ID not found');
Console::exit();
@@ -269,4 +251,20 @@ class Backup extends Action
$this->xtrabackupContainerId = $containerId;
}
public function setProcessors()
{
$stdout = '';
$stderr = '';
Console::execute('docker exec -i ' . $this->xtrabackupContainerId . ' nproc', '', $stdout, $stderr);
if (!empty($stderr)) {
Console::error('Error setting processors: ' . $stderr);
Console::exit();
}
$processors = str_replace(PHP_EOL, '', $stdout);
$processors = intval($processors);
$processors = $processors === 0 ? 1 : $processors;
$this->processors = $processors;
}
}
+70 -97
View File
@@ -25,10 +25,6 @@ class Restore extends Action
public function __construct()
{
$this->checkEnvVariables();
$this->setProcessors();
$this->setContainerId();
$this
->desc('Restore a DB')
->param('id', '', new Text(20), 'The backup identification')
@@ -44,6 +40,10 @@ class Restore extends Action
public function action(string $id, string $cloud, string $database): void
{
$this->checkEnvVariables();
$this->setContainerId();
$this->setProcessors();
$this->database = $database;
$datadir = self::DATADIR;
$this->dsn = $this->getDsn($database);
@@ -65,47 +65,45 @@ class Restore extends Action
Console::exit();
}
if (file_exists($datadir . '/sys') || file_exists($datadir . '/appwrite')) {
Console::error('Datadir ' . $datadir . ' must be empty!');
Console::exit();
}
// if (file_exists($datadir . '/sys') || file_exists($datadir . '/appwrite')) {
// Console::error('Datadir ' . $datadir . ' must be empty!');
// Console::exit();
// }
$this->log('--- Restore Start ' . $id . ' --- ');
$filename = $id . '.tar.gz';
$filename = $id . '.xbstream';
$start = microtime(true);
$cloud = $cloud === 'true' || $cloud === '1';
$destination = new Local(self::BACKUPS_PATH . '/restore/' . $id);
$files = $destination->getRoot() . '/files';
if ($cloud) {
$local = new Local(self::BACKUPS_PATH . '/downloads/' . $id);
$files = $local->getRoot() . '/files';
if (!file_exists($files) && !mkdir($files, 0755, true)) {
Console::error('Error creating directory: ' . $files);
Console::exit();
}
$file = $local->getPath($filename);
if (!file_exists($file)) {
$this->download($file, $local);
}
$this->untar($file, $files);
} else {
$local = new Local(self::BACKUPS_PATH . '/' . $database . '/full/' . $id);
$files = $local->getRoot() . '/files';
}
if (!file_exists($files)) {
Console::error('Directory not found: ' . $files);
if (file_exists($files)) {
Console::error('Directory exist: ' . $files);
Console::exit();
}
$this->decompress($files);
if (!file_exists($files) && !mkdir($files, 0755, true)) {
Console::error('Error creating directory: ' . $files);
Console::exit();
}
if ($cloud) {
$stream = $destination->getPath($filename);
if (!file_exists($stream)) {
$this->download($stream, $destination);
}
} else {
$stream = self::BACKUPS_PATH . '/' . $database . '/full/' . $filename;
}
if (!file_exists($stream)) {
Console::error('File not found: ' . $stream);
Console::exit();
}
$this->decompress($stream, $files);
$this->prepare($files);
$this->restore($files, $cloud, $datadir);
$this->restore($files, $datadir);
$this->log('Restore Finish in ' . (microtime(true) - $start) . ' seconds');
}
@@ -133,52 +131,24 @@ class Restore extends Action
}
}
public function untar(string $file, string $directory)
public function decompress(string $file, string $target)
{
$this->log('Untar Start');
$this->log('Xbstream start');
$args = [
'xbstream -x < ' . $file,
'--decompress',
'--parallel=' . $this->processors,
'-C ' . $target,
];
$stdout = '';
$stderr = '';
$cmd = 'tar -xzf ' . $file . ' -C ' . $directory;
$cmd = 'docker exec -i ' . $this->xtrabackupContainerId . ' ' . implode(' ', $args);
Console::success($cmd);
Console::execute($cmd, '', $stdout, $stderr);
if (!empty($stderr)) {
Console::error($stderr);
Console::exit();
}
if (!file_exists($file)) {
Console::error('Restore file not found: ' . $file);
Console::exit();
}
}
public function decompress(string $target)
{
$this->log('Decompress start');
$logfile = $target . '/../log.txt';
$args = [
'xtrabackup',
'--user=' . $this->dsn->getUser(),
'--password=' . $this->dsn->getPassword(),
'--host=' . $this->dsn->getHost(),
'--decompress',
'--strict',
'--remove-original', // Removes *.lz4 compressed files
'--parallel=' . $this->processors,
'--compress-threads=' . $this->processors,
'--target-dir=' . $target,
'2> ' . $logfile,
];
$cmd = 'docker exec ' . $this->xtrabackupContainerId . ' ' . implode(' ', $args);
shell_exec($cmd);
$stderr = shell_exec('tail -1 ' . $logfile);
if (!str_contains($stderr, 'completed OK!')) {
Console::error('Decompress failed');
Console::error('Xbstream Error: ' . $stderr);
Console::exit();
}
}
@@ -192,7 +162,7 @@ class Restore extends Action
Console::exit();
}
$logfile = $target . '/../log.txt';
$logfile = $target . '/../prepare.txt';
$args = [
'xtrabackup',
@@ -211,12 +181,12 @@ class Restore extends Action
$stderr = shell_exec('tail -1 ' . $logfile);
if (!str_contains($stderr, 'completed OK!')) {
Console::error(date('Y-m-d H:i:s') . ' Prepare failed:' . $stderr);
Console::error('Prepare error: ' . $stderr);
Console::exit();
}
}
public function restore(string $target, bool $cloud, string $datadir)
public function restore(string $target, string $datadir)
{
$this->log('Restore start');
@@ -225,14 +195,14 @@ class Restore extends Action
Console::exit();
}
$logfile = $target . '/../log.txt';
$logfile = $target . '/../restore.txt';
$args = [
'xtrabackup',
'--user=' . $this->dsn->getUser(),
'--password=' . $this->dsn->getPassword(),
'--host=' . $this->dsn->getHost(),
$cloud ? '--move-back' : '--copy-back',
'--move-back',
'--strict',
'--target-dir=' . $target,
'--datadir=' . $datadir,
@@ -253,6 +223,9 @@ class Restore extends Action
public function checkEnvVariables(): void
{
var_dump(self::getName());
foreach (
[
'_APP_CONNECTIONS_BACKUPS_STORAGE',
@@ -284,22 +257,6 @@ class Restore extends Action
return null;
}
public function setProcessors()
{
$stdout = '';
$stderr = '';
Console::execute('nproc', '', $stdout, $stderr);
if (!empty($stderr)) {
Console::error('Error setting processors: ' . $stderr);
Console::exit();
}
$processors = str_replace(PHP_EOL, '', $stdout);
$processors = intval($processors);
$processors = $processors === 0 ? 1 : $processors;
$this->processors = $processors;
}
public function setContainerId()
{
$stdout = '';
@@ -318,4 +275,20 @@ class Restore extends Action
$this->xtrabackupContainerId = $containerId;
}
public function setProcessors()
{
$stdout = '';
$stderr = '';
Console::execute('docker exec -i ' . $this->xtrabackupContainerId . ' nproc', '', $stdout, $stderr);
if (!empty($stderr)) {
Console::error('Error setting processors: ' . $stderr);
Console::exit();
}
$processors = str_replace(PHP_EOL, '', $stdout);
$processors = intval($processors);
$processors = $processors === 0 ? 1 : $processors;
$this->processors = $processors;
}
}