mirror of
https://github.com/PhyreApps/PhyrePanel.git
synced 2024-11-25 00:50:32 +00:00
update
This commit is contained in:
parent
33adbec9e4
commit
fc6aac0f53
8 changed files with 81 additions and 107 deletions
|
@ -9,40 +9,9 @@ use Illuminate\Support\Str;
|
||||||
|
|
||||||
class BackupStorage
|
class BackupStorage
|
||||||
{
|
{
|
||||||
public static function getDomainPath($domainId)
|
|
||||||
{
|
|
||||||
$findDomain = Domain::where('id', $domainId)->first();
|
|
||||||
if ($findDomain) {
|
|
||||||
return $findDomain->domain_root . '/backups';
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public static function getDomainInstance($domainId)
|
|
||||||
{
|
|
||||||
$domainPath = self::getDomainPath($domainId);
|
|
||||||
|
|
||||||
if ($domainPath) {
|
|
||||||
$storageBuild = Storage::build([
|
|
||||||
'driver' => 'local',
|
|
||||||
'root' => $domainPath,
|
|
||||||
]);
|
|
||||||
$storageBuild->buildTemporaryUrlsUsing(function ($path, $expiration, $options) {
|
|
||||||
return URL::temporarySignedRoute(
|
|
||||||
'backup.download',
|
|
||||||
$expiration,
|
|
||||||
array_merge($options, ['path' => $path])
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return $storageBuild;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getPath()
|
public static function getPath()
|
||||||
{
|
{
|
||||||
$rootPath = storage_path('app');
|
$rootPath = '/var/lib/phyre/backups/system';
|
||||||
$customBackupPath = setting('general.backup_path');
|
$customBackupPath = setting('general.backup_path');
|
||||||
if (!empty($customBackupPath)) {
|
if (!empty($customBackupPath)) {
|
||||||
$rootPath = $customBackupPath;
|
$rootPath = $customBackupPath;
|
||||||
|
|
|
@ -4,11 +4,16 @@ namespace App\Console\Commands;
|
||||||
|
|
||||||
use App\Models\Backup;
|
use App\Models\Backup;
|
||||||
use App\Models\HostingSubscription;
|
use App\Models\HostingSubscription;
|
||||||
|
use App\Models\HostingSubscriptionBackup;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CreateDailyFullHostingSubscriptionsBackup extends Command
|
class CreateDailyFullHostingSubscriptionsBackup extends Command
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -30,7 +35,27 @@ class CreateDailyFullHostingSubscriptionsBackup extends Command
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
// Find Hosting Subscriptions
|
||||||
|
$findHostingSubscriptions = HostingSubscription::limit(1)->get();
|
||||||
|
if ($findHostingSubscriptions->count() > 0) {
|
||||||
|
foreach ($findHostingSubscriptions as $hostingSubscription) {
|
||||||
|
|
||||||
|
$findBackup = HostingSubscriptionBackup::where('hosting_subscription_id', $hostingSubscription->id)
|
||||||
|
->where('backup_type', 'full')
|
||||||
|
->where('created_at', '>=', Carbon::now()->subHours(24))
|
||||||
|
->first();
|
||||||
|
if (! $findBackup) {
|
||||||
|
$backup = new HostingSubscriptionBackup();
|
||||||
|
$backup->hosting_subscription_id = $hostingSubscription->id;
|
||||||
|
$backup->backup_type = 'full';
|
||||||
|
$backup->save();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$this->error('Backup already exists for ' . $hostingSubscription->domain);
|
||||||
|
$this->error('Created before: ' . $findBackup->created_at->diffForHumans());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,28 +37,6 @@ class RunHostingSubscriptionsBackupChecks extends Command
|
||||||
$backup->delete();
|
$backup->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Find Hosting Subscriptions
|
|
||||||
// $findHostingSubscriptions = HostingSubscription::all();
|
|
||||||
// if ($findHostingSubscriptions->count() > 0) {
|
|
||||||
// foreach ($findHostingSubscriptions as $hostingSubscription) {
|
|
||||||
//
|
|
||||||
// $findBackup = HostingSubscriptionBackup::where('hosting_subscription_id', $hostingSubscription->id)
|
|
||||||
// ->where('backup_type', 'full')
|
|
||||||
// ->where('created_at', '>=', Carbon::now()->subHours(24))
|
|
||||||
// ->first();
|
|
||||||
// if (! $findBackup) {
|
|
||||||
// $backup = new HostingSubscriptionBackup();
|
|
||||||
// $backup->hosting_subscription_id = $hostingSubscription->id;
|
|
||||||
// $backup->backup_type = 'full';
|
|
||||||
// $backup->save();
|
|
||||||
// } else {
|
|
||||||
// $this->error('Backup already exists for ' . $hostingSubscription->domain);
|
|
||||||
// $this->error('Created before: ' . $findBackup->created_at->diffForHumans());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// Check for pending backups
|
// Check for pending backups
|
||||||
$getPendingBackups = HostingSubscriptionBackup::where('status', 'pending')
|
$getPendingBackups = HostingSubscriptionBackup::where('status', 'pending')
|
||||||
->get();
|
->get();
|
||||||
|
|
|
@ -102,6 +102,9 @@ class BackupResource extends Resource
|
||||||
->actions([
|
->actions([
|
||||||
Tables\Actions\Action::make('download')
|
Tables\Actions\Action::make('download')
|
||||||
->icon('heroicon-o-arrow-down-tray')
|
->icon('heroicon-o-arrow-down-tray')
|
||||||
|
->hidden(function (Backup $backup) {
|
||||||
|
return $backup->status !== BackupStatus::Completed;
|
||||||
|
})
|
||||||
->action(function (Backup $backup) {
|
->action(function (Backup $backup) {
|
||||||
|
|
||||||
$backupStorage = BackupStorage::getInstance($backup->root_path);
|
$backupStorage = BackupStorage::getInstance($backup->root_path);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\BackupStorage;
|
||||||
use App\Filament\Enums\BackupStatus;
|
use App\Filament\Enums\BackupStatus;
|
||||||
use App\Helpers;
|
use App\Helpers;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
@ -33,16 +34,16 @@ class HostingSubscriptionBackup extends Model
|
||||||
'status' => BackupStatus::class,
|
'status' => BackupStatus::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
protected static function booted(): void
|
// protected static function booted(): void
|
||||||
{
|
// {
|
||||||
static::addGlobalScope('customer', function (Builder $query) {
|
// static::addGlobalScope('customer', function (Builder $query) {
|
||||||
if (auth()->check() && auth()->guard()->name == 'web_customer') {
|
// if (auth()->check() && auth()->guard()->name == 'web_customer') {
|
||||||
$query->whereHas('hostingSubscription', function ($query) {
|
// $query->whereHas('hostingSubscription', function ($query) {
|
||||||
$query->where('customer_id', auth()->user()->id);
|
// $query->where('customer_id', auth()->user()->id);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
public static function boot()
|
public static function boot()
|
||||||
{
|
{
|
||||||
parent::boot();
|
parent::boot();
|
||||||
|
@ -57,9 +58,9 @@ class HostingSubscriptionBackup extends Model
|
||||||
});
|
});
|
||||||
|
|
||||||
static::deleting(function ($model) {
|
static::deleting(function ($model) {
|
||||||
if (is_file($model->filepath)) {
|
// if (is_file($model->filepath)) {
|
||||||
shell_exec('rm -rf ' . $model->filepath);
|
// shell_exec('rm -rf ' . $model->filepath);
|
||||||
}
|
// }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +68,7 @@ class HostingSubscriptionBackup extends Model
|
||||||
{
|
{
|
||||||
$cronJobCommand = 'phyre-php /usr/local/phyre/web/artisan phyre:run-hosting-subscriptions-backup-checks';
|
$cronJobCommand = 'phyre-php /usr/local/phyre/web/artisan phyre:run-hosting-subscriptions-backup-checks';
|
||||||
$findCronJob = CronJob::where('command', $cronJobCommand)->first();
|
$findCronJob = CronJob::where('command', $cronJobCommand)->first();
|
||||||
|
|
||||||
if (! $findCronJob) {
|
if (! $findCronJob) {
|
||||||
$cronJob = new CronJob();
|
$cronJob = new CronJob();
|
||||||
$cronJob->schedule = '*/5 * * * *';
|
$cronJob->schedule = '*/5 * * * *';
|
||||||
|
@ -170,25 +172,20 @@ class HostingSubscriptionBackup extends Model
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$storagePath = storage_path('backups');
|
$backupStorageRootPath = '/var/lib/phyre/backups/hosting_subscriptions';
|
||||||
$backupPath = $storagePath.'/hosting_subscriptions/'.$this->backup_type.'/'.$this->id;
|
$backupPath = $backupStorageRootPath . '/' . $findHostingSubscription->customer_id;
|
||||||
|
|
||||||
$backupTempPath = $backupPath.'/temp';
|
$backupTempPath = $backupPath.'/temp';
|
||||||
shell_exec('mkdir -p ' . $backupTempPath);
|
shell_exec('mkdir -p ' . $backupTempPath);
|
||||||
|
|
||||||
|
$backupFileName = Str::slug($findHostingSubscription->system_username .'-'. date('Ymd-His')) . '.zip';
|
||||||
|
$backupFilePath = $backupStorageRootPath.'/'.$backupFileName;
|
||||||
|
|
||||||
$backupFileName = Str::slug($findHostingSubscription->system_username .'-'. date('Ymd-His')) . '.tar.gz';
|
$backupLogFilePath = $backupPath.'/backup.log';
|
||||||
$backupFilePath = $backupPath.'/'.$backupFileName;
|
|
||||||
|
|
||||||
$backupLogFileName = 'backup.log';
|
|
||||||
$backupLogFilePath = $backupPath.'/'.$backupLogFileName;
|
|
||||||
|
|
||||||
$backupTargetPath = $findMainDomain->domain_root . '/backups';
|
|
||||||
$backupTargetFilePath = $backupTargetPath.'/'.$backupFileName;
|
|
||||||
|
|
||||||
$backupTempScript = '/tmp/backup-script-'.$this->id.'.sh';
|
$backupTempScript = '/tmp/backup-script-'.$this->id.'.sh';
|
||||||
$shellFileContent = '';
|
$shellFileContent = '';
|
||||||
$shellFileContent .= 'mkdir -p '. $backupTargetPath.PHP_EOL;
|
$shellFileContent .= 'echo "Backup up user: '.$findHostingSubscription->system_username .'"'. PHP_EOL;
|
||||||
$shellFileContent .= 'echo "Backup up domain: '.$findHostingSubscription->domain .'"'. PHP_EOL;
|
|
||||||
$shellFileContent .= 'echo "Backup filename: '.$backupFileName.'"' . PHP_EOL;
|
$shellFileContent .= 'echo "Backup filename: '.$backupFileName.'"' . PHP_EOL;
|
||||||
|
|
||||||
if ($this->backup_type == 'full') {
|
if ($this->backup_type == 'full') {
|
||||||
|
@ -205,30 +202,23 @@ class HostingSubscriptionBackup extends Model
|
||||||
|
|
||||||
if ($getDatabases->count() > 0) {
|
if ($getDatabases->count() > 0) {
|
||||||
foreach ($getDatabases as $database) {
|
foreach ($getDatabases as $database) {
|
||||||
// $findDatabaseUser = DatabaseUser::where('database_id', $database->id)
|
|
||||||
// ->first();
|
|
||||||
// if (!$findDatabaseUser) {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
$databaseName = $database->database_name_prefix . $database->database_name;
|
$databaseName = $database->database_name_prefix . $database->database_name;
|
||||||
// $databaseUser = $findDatabaseUser->username_prefix . $findDatabaseUser->username;
|
|
||||||
// $databaseUserPassword = $findDatabaseUser->password;
|
|
||||||
|
|
||||||
$shellFileContent .= 'echo "Backup up database: ' . $databaseName .'" '. PHP_EOL;
|
$shellFileContent .= 'echo "Backup up database: ' . $databaseName .'" '. PHP_EOL;
|
||||||
// $shellFileContent .= 'echo "Backup up database user: ' . $databaseUser .'" '. PHP_EOL;
|
$shellFileContent .= 'mkdir -p '.$backupTempPath . '/databases' . PHP_EOL;
|
||||||
$databaseBackupPath = $backupTempPath . '/' . $databaseName . '.sql';
|
$databaseBackupPath = $backupTempPath . '/databases/' . $databaseName . '.sql';
|
||||||
$shellFileContent .= 'mysqldump -u "'.env('MYSQl_ROOT_USERNAME').'" -p"'.env('MYSQL_ROOT_PASSWORD').'" "'.$databaseName.'" > '.$databaseBackupPath . PHP_EOL;
|
$shellFileContent .= 'mysqldump -u "'.env('MYSQl_ROOT_USERNAME').'" -p"'.env('MYSQL_ROOT_PASSWORD').'" "'.$databaseName.'" > '.$databaseBackupPath . PHP_EOL;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$shellFileContent .= 'cd '.$backupTempPath .' && tar -czvf '.$backupFilePath.' ./* '. PHP_EOL;
|
// With find, we can search for all files,directories (including hidden) in the current directory and zip them
|
||||||
|
$shellFileContent .= 'cd '.$backupTempPath .' && find . -exec zip -r '.$backupFilePath.' {} \;'. PHP_EOL;
|
||||||
|
|
||||||
$shellFileContent .= 'rm -rf '.$backupTempPath.PHP_EOL;
|
$shellFileContent .= 'rm -rf '.$backupTempPath.PHP_EOL;
|
||||||
$shellFileContent .= 'echo "Backup complete"' . PHP_EOL;
|
$shellFileContent .= 'echo "Backup complete"' . PHP_EOL;
|
||||||
$shellFileContent .= 'touch ' . $backupTargetPath. '/backup-'.$this->id.'.done' . PHP_EOL;
|
$shellFileContent .= 'touch ' . $backupPath. '/backup.done' . PHP_EOL;
|
||||||
$shellFileContent .= 'mv '.$backupFilePath.' '. $backupTargetFilePath.PHP_EOL;
|
|
||||||
$shellFileContent .= 'rm -rf ' . $backupTempScript . PHP_EOL;
|
$shellFileContent .= 'rm -rf ' . $backupTempScript . PHP_EOL;
|
||||||
|
|
||||||
file_put_contents($backupTempScript, $shellFileContent);
|
file_put_contents($backupTempScript, $shellFileContent);
|
||||||
|
@ -238,8 +228,12 @@ class HostingSubscriptionBackup extends Model
|
||||||
|
|
||||||
if ($processId > 0 && is_numeric($processId)) {
|
if ($processId > 0 && is_numeric($processId)) {
|
||||||
|
|
||||||
$this->path = $findMainDomain->domain_root . '/backups';
|
$this->path = $backupPath;
|
||||||
$this->filepath = $backupTargetFilePath;
|
$this->root_path = $backupStorageRootPath;
|
||||||
|
$this->temp_path = $backupTempPath;
|
||||||
|
$this->file_path = $backupFilePath;
|
||||||
|
$this->file_name = $backupFileName;
|
||||||
|
|
||||||
$this->status = 'processing';
|
$this->status = 'processing';
|
||||||
$this->queued = true;
|
$this->queued = true;
|
||||||
$this->queued_at = now();
|
$this->queued_at = now();
|
||||||
|
|
|
@ -17,8 +17,13 @@ return new class extends Migration
|
||||||
$table->bigInteger('hosting_subscription_id')->nullable();
|
$table->bigInteger('hosting_subscription_id')->nullable();
|
||||||
$table->string('backup_type')->nullable();
|
$table->string('backup_type')->nullable();
|
||||||
$table->string('status')->nullable();
|
$table->string('status')->nullable();
|
||||||
|
|
||||||
$table->string('path')->nullable();
|
$table->string('path')->nullable();
|
||||||
$table->string('filepath')->nullable();
|
$table->string('root_path')->nullable();
|
||||||
|
$table->string('temp_path')->nullable();
|
||||||
|
$table->string('file_path')->nullable();
|
||||||
|
$table->string('file_name')->nullable();
|
||||||
|
|
||||||
$table->string('size')->nullable();
|
$table->string('size')->nullable();
|
||||||
$table->string('disk')->nullable();
|
$table->string('disk')->nullable();
|
||||||
$table->string('process_id')->nullable();
|
$table->string('process_id')->nullable();
|
||||||
|
|
|
@ -40,8 +40,8 @@ class BackupTest extends ActionTestCase
|
||||||
}
|
}
|
||||||
$this->assertTrue($backupFinished);
|
$this->assertTrue($backupFinished);
|
||||||
$this->assertSame($findLastBackup->status, BackupStatus::Completed);
|
$this->assertSame($findLastBackup->status, BackupStatus::Completed);
|
||||||
$this->assertNotEmpty($findLastBackup->filepath);
|
$this->assertNotEmpty($findLastBackup->file_path);
|
||||||
$this->assertTrue(file_exists(Storage::disk('backups')->path($findLastBackup->filepath)));
|
$this->assertTrue(file_exists($findLastBackup->file_path));
|
||||||
|
|
||||||
$backup = new Backup();
|
$backup = new Backup();
|
||||||
$checkCronJob = $backup->checkCronJob();
|
$checkCronJob = $backup->checkCronJob();
|
||||||
|
@ -91,14 +91,14 @@ class BackupTest extends ActionTestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->assertTrue($backupCompleted);
|
$this->assertTrue($backupCompleted);
|
||||||
$this->assertNotEmpty($findBackup->filepath);
|
$this->assertNotEmpty($findBackup->file_path);
|
||||||
$this->assertTrue(file_exists(Storage::disk('backups')->path($findBackup->filepath)));
|
$this->assertTrue(file_exists($findBackup->file_path));
|
||||||
|
|
||||||
$getFilesize = filesize(Storage::disk('backups')->path($findBackup->filepath));
|
$getFilesize = filesize($findBackup->file_path);
|
||||||
$this->assertGreaterThan(0, $getFilesize);
|
$this->assertGreaterThan(0, $getFilesize);
|
||||||
$this->assertSame($getFilesize, $findBackup->size);
|
$this->assertSame($getFilesize, $findBackup->size);
|
||||||
|
|
||||||
Helpers::extractTar(Storage::disk('backups')->path($findBackup->filepath), $findBackup->path . '/unit-test');
|
Helpers::extractTar($findBackup->file_path, $findBackup->path . '/unit-test');
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ class HostingSubscriptionBackupTest extends ActionTestCase
|
||||||
|
|
||||||
$chs = $this->_createHostingSubscription();
|
$chs = $this->_createHostingSubscription();
|
||||||
|
|
||||||
Artisan::call('phyre:run-hosting-subscriptions-backup');
|
Artisan::call('phyre:create-daily-full-hosting-subscriptions-backup');
|
||||||
|
|
||||||
$findLastBackup = HostingSubscriptionBackup::where('hosting_subscription_id', $chs['hostingSubscriptionId'])
|
$findLastBackup = HostingSubscriptionBackup::where('hosting_subscription_id', $chs['hostingSubscriptionId'])
|
||||||
->first();
|
->first();
|
||||||
|
@ -51,8 +51,8 @@ class HostingSubscriptionBackupTest extends ActionTestCase
|
||||||
|
|
||||||
$this->assertTrue($backupFinished);
|
$this->assertTrue($backupFinished);
|
||||||
$this->assertSame($findLastBackup->status, BackupStatus::Completed);
|
$this->assertSame($findLastBackup->status, BackupStatus::Completed);
|
||||||
$this->assertNotEmpty($findLastBackup->filepath);
|
$this->assertNotEmpty($findLastBackup->file_path);
|
||||||
$this->assertTrue(file_exists($findLastBackup->filepath));
|
$this->assertTrue(file_exists($findLastBackup->file_path));
|
||||||
|
|
||||||
$backup = new HostingSubscriptionBackup();
|
$backup = new HostingSubscriptionBackup();
|
||||||
$checkCronJob = $backup->checkCronJob();
|
$checkCronJob = $backup->checkCronJob();
|
||||||
|
@ -82,14 +82,14 @@ class HostingSubscriptionBackupTest extends ActionTestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->assertTrue($backupCompleted);
|
$this->assertTrue($backupCompleted);
|
||||||
$this->assertNotEmpty($findBackup->filepath);
|
$this->assertNotEmpty($findBackup->file_path);
|
||||||
$this->assertTrue(file_exists($findBackup->filepath));
|
$this->assertTrue(file_exists($findBackup->file_path));
|
||||||
|
|
||||||
$getFilesize = filesize($findBackup->filepath);
|
$getFilesize = filesize($findBackup->file_path);
|
||||||
$this->assertGreaterThan(0, $getFilesize);
|
$this->assertGreaterThan(0, $getFilesize);
|
||||||
$this->assertSame(Helpers::checkPathSize($findBackup->path), $findBackup->size);
|
$this->assertSame(Helpers::checkPathSize($findBackup->path), $findBackup->size);
|
||||||
|
|
||||||
Helpers::extractTar($findBackup->filepath, $findBackup->path . '/unit-test');
|
Helpers::extractTar($findBackup->file_path, $findBackup->path . '/unit-test');
|
||||||
//
|
//
|
||||||
// dd($chs);
|
// dd($chs);
|
||||||
$findDatabase = Database::where('id', $chs['databaseId'])->first();
|
$findDatabase = Database::where('id', $chs['databaseId'])->first();
|
||||||
|
|
Loading…
Reference in a new issue