Skip to content

Commit

Permalink
* Fix: Nested volume check only for appdata paths
Browse files Browse the repository at this point in the history
* Fix: nested volume check with trailing slash!!!
* Fix: cron not working after reboot
  • Loading branch information
Commifreak committed Apr 24, 2023
1 parent f8660db commit dab8c4a
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 28 deletions.
15 changes: 10 additions & 5 deletions src/include/ABHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class ABHelper {
* @var array Store some temporary data about containers, which should skipped during start routine
*/
private static $skipStartContainers = [];
public static $currentContainerName;

public static $targetLogLevel = '';

Expand Down Expand Up @@ -96,10 +97,14 @@ public static function backupLog(string $msg, string $level = self::LOGLEVEL_INF
return;
}

$section = empty(self::$currentContainerName) ? 'Main' : self::$currentContainerName;

$logLine = ($skipDate ? '' : "[" . date("d.m.Y H:i:s") . "][$section][$level]") . " $msg" . ($newLine ? "\n" : '');

if ($level != self::LOGLEVEL_DEBUG) {
file_put_contents(ABSettings::$tempFolder . '/' . ABSettings::$logfile, ($skipDate ? '' : "[" . date("d.m.Y H:i:s") . "][$level]") . " $msg" . ($newLine ? "\n" : ''), FILE_APPEND);
file_put_contents(ABSettings::$tempFolder . '/' . ABSettings::$logfile, $logLine, FILE_APPEND);
}
file_put_contents(ABSettings::$tempFolder . '/' . ABSettings::$debugLogFile, ($skipDate ? '' : "[" . date("d.m.Y H:i:s") . "][$level]") . " $msg" . ($newLine ? "\n" : ''), FILE_APPEND);
file_put_contents(ABSettings::$tempFolder . '/' . ABSettings::$debugLogFile, $logLine, FILE_APPEND);

if ($level == self::LOGLEVEL_ERR && self::$targetLogLevel == self::LOGLEVEL_ERR) {
self::notify("Error occured!", "Please check the backup log tab!", $msg, 'alert');
Expand Down Expand Up @@ -425,7 +430,7 @@ public static function getContainerVolumes($container) {
continue;
}
if (in_array($hostPath, $abSettings->allowedSources)) {
self::backupLog("Removing container mapping \"$hostPath\" because it is a source path!", self::LOGLEVEL_WARN);
self::backupLog("Removing container mapping \"$hostPath\" because it is a source path!");
continue;
}
$volumes[] = rtrim($hostPath, '/');
Expand All @@ -441,8 +446,8 @@ public static function getContainerVolumes($container) {
*/
foreach ($volumes as $volume) {
foreach ($volumes as $key2 => $volume2) {
if (str_starts_with($volume2, $volume) && $volume !== $volume2) {
self::backupLog("'$volume2' is within mapped volume '$volume'! Ignoring!", self::LOGLEVEL_WARN);
if ($volume !== $volume2 && self::isVolumeWithinAppdata($volume) && str_starts_with($volume2, $volume . '/')) { // Trailing slash assures whole directory name => https://forums.unraid.net/topic/136995-pluginbeta-appdatabackup/?do=findComment&comment=1255260
self::backupLog("'$volume2' is within mapped volume '$volume'! Ignoring!");
unset($volumes[$key2]);
}
}
Expand Down
50 changes: 28 additions & 22 deletions src/include/ABSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class ABSettings {
public static $appName = 'appdata.backup';
public static $pluginDir = '/boot/config/plugins/appdata.backup';
public static $settingsFile = 'config.json';
public static $cronFile = '/etc/cron.d/appdata_backup';
public static $cronFile = 'appdata_backup.cron';
public static $supportUrl = 'https://forums.unraid.net/topic/137710-plugin-appdatabackup/';

public static $tempFolder = '/tmp/appdata.backup';
Expand Down Expand Up @@ -100,20 +100,25 @@ public function __construct() {
}
ABHelper::$targetLogLevel = $this->notification;

require_once("/usr/local/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php");

// Get containers and check if some of it is deleted but configured
$dockerClient = new \DockerClient();
foreach ($this->containerSettings as $name => $settings) {
if (!$dockerClient->doesContainerExist($name)) {
unset($this->containerSettings[$name]);
$sortKey = array_search($name, $this->containerOrder);
if ($sortKey) {
unset($this->containerOrder[$sortKey]);
/**
* Check obsolete containers only if array is online, socket error otherwise!
*/
if (ABHelper::isArrayOnline()) {

require_once("/usr/local/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php");

// Get containers and check if some of it is deleted but configured
$dockerClient = new \DockerClient();
foreach ($this->containerSettings as $name => $settings) {
if (!$dockerClient->doesContainerExist($name)) {
unset($this->containerSettings[$name]);
$sortKey = array_search($name, $this->containerOrder);
if ($sortKey) {
unset($this->containerOrder[$sortKey]);
}
}
}
}

}

public static function getConfigPath() {
Expand Down Expand Up @@ -149,31 +154,32 @@ public function getContainerSpecificSettings($name, $setEmptyToDefault = true) {
}

public function checkCron() {
$cronSettings = '# Appdata.Backup cron settings' . PHP_EOL;
switch ($this->backupFrequency) {
case 'custom':
$cronSettings = $this->backupFrequencyCustom;
$cronSettings .= $this->backupFrequencyCustom;
break;
case 'daily':
$cronSettings = $this->backupFrequencyMinute . " " . $this->backupFrequencyHour . " * * *";
$cronSettings .= $this->backupFrequencyMinute . " " . $this->backupFrequencyHour . " * * *";
break;
case 'weekly':
$cronSettings = $this->backupFrequencyMinute . " " . $this->backupFrequencyHour . " * * " . $this->backupFrequencyWeekday;
$cronSettings .= $this->backupFrequencyMinute . " " . $this->backupFrequencyHour . " * * " . $this->backupFrequencyWeekday;
break;
case 'monthly':
$cronSettings = $this->backupFrequencyMinute . " " . $this->backupFrequencyHour . " " . $this->backupFrequencyDayOfMonth . " * *";
$cronSettings .= $this->backupFrequencyMinute . " " . $this->backupFrequencyHour . " " . $this->backupFrequencyDayOfMonth . " * *";
break;
default:
$cronSettings = '';
$cronSettings .= '';
}

if (!empty($cronSettings)) {
$cronSettings .= ' php ' . dirname(__DIR__) . '/scripts/backup.php > /dev/null 2>&1';
file_put_contents(ABSettings::$cronFile, $cronSettings);
file_put_contents(ABSettings::$pluginDir . '/' . ABSettings::$cronFile, $cronSettings . PHP_EOL);

// Restart dcron, that forces a re-read of /etc/cron.d. Otherwise, we have to wait one hour, because dcron read cron.d files once an hour.
exec("/etc/rc.d/rc.crond restart");
} elseif (file_exists(ABSettings::$cronFile)) {
unlink(ABSettings::$cronFile);
// Let dcron know our changes via update_cron
exec("update_cron");
} elseif (file_exists(ABSettings::$pluginDir . '/' . ABSettings::$cronFile)) {
unlink(ABSettings::$pluginDir . '/' . ABSettings::$cronFile);
}
}

Expand Down
10 changes: 10 additions & 0 deletions src/scripts/backup.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,15 @@
if ($abSettings->backupMethod == 'stopAll') {
ABHelper::backupLog("Method: Stop all container before continuing.");
foreach ($sortedStopContainers as $container) {
ABHelper::$currentContainerName = $container['Name'];
ABHelper::stopContainer($container);

if (ABHelper::abortRequested()) {
goto abort;
}
}
ABHelper::$currentContainerName = null;

ABHelper::handlePrePostScript($abSettings->preBackupScript);

if (ABHelper::abortRequested()) {
Expand All @@ -150,6 +153,7 @@
}

foreach ($sortedStartContainers as $container) {
ABHelper::$currentContainerName = $container['Name'];
ABHelper::stopContainer($container);

if (ABHelper::abortRequested()) {
Expand All @@ -170,12 +174,14 @@
goto abort;
}
}
ABHelper::$currentContainerName = null;

goto continuationForAll;
}

ABHelper::backupLog("Starting backup for containers");
foreach ($sortedStartContainers as $container) {
ABHelper::$currentContainerName = $container['Name'];
if (!ABHelper::backupContainer($container, $abDestination)) {
$errorOccured = true;
}
Expand All @@ -185,6 +191,7 @@
}

}
ABHelper::$currentContainerName = null;

ABHelper::handlePrePostScript($abSettings->postBackupScript);

Expand All @@ -194,12 +201,14 @@

ABHelper::backupLog("Set containers to previous state");
foreach ($sortedStartContainers as $container) {
ABHelper::$currentContainerName = $container['Name'];
ABHelper::startContainer($container);

if (ABHelper::abortRequested()) {
goto abort;
}
}
ABHelper::$currentContainerName = null;


continuationForAll:
Expand Down Expand Up @@ -401,6 +410,7 @@
ABHelper::handlePrePostScript($abSettings->postRunScript);

abort:
ABHelper::$currentContainerName = null;
if (ABHelper::abortRequested()) {
$errorOccured = true;
ABHelper::backupLog("Backup cancelled! Executing final things. You will be left behind with the current state!", ABHelper::LOGLEVEL_WARN);
Expand Down
12 changes: 11 additions & 1 deletion src/scripts/checkCron.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,18 @@

echo "Checking cron." . PHP_EOL;

/**
* Old cron style remnants - ged rid of it
*/
if (file_exists('/etc/cron.d/appdata_backup')) {
@unlink('/etc/cron.d/appdata_backup');
}
if (file_exists('/etc/cron.d/appdata_backup_beta')) {
@unlink('/etc/cron.d/appdata_backup_beta');
}

if (($argv[1] ?? null) == '--remove') {
@unlink(ABSettings::$cronFile);
@unlink(ABSettings::$pluginDir . '/' . ABSettings::$cronFile);
echo "cronfile deleted!" . PHP_EOL;
exit;
}
Expand Down

0 comments on commit dab8c4a

Please sign in to comment.