Skip to content

Commit 7dfa708

Browse files
committed
* Fixed default setting issue
* Do not backup external volumes for now
1 parent 3125d11 commit 7dfa708

File tree

4 files changed

+108
-45
lines changed

4 files changed

+108
-45
lines changed

src/include/ABHelper.php

+69-27
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class ABHelper {
1212
const LOGLEVEL_ERR = 'error';
1313

1414
private static $skipStartContainers = [];
15+
private static $dockerCfg = null;
1516

1617
public static $targetLogLevel = '';
1718

@@ -76,6 +77,13 @@ public static function backupLog(string $msg, string $level = self::LOGLEVEL_INF
7677
mkdir(ABSettings::$tempFolder);
7778
}
7879

80+
/**
81+
* Do not log, if the script is not running
82+
*/
83+
if (!self::scriptRunning()) {
84+
return;
85+
}
86+
7987
if ($level != self::LOGLEVEL_DEBUG) {
8088
file_put_contents(ABSettings::$tempFolder . '/' . ABSettings::$logfile, ($skipDate ? '' : "[" . date("d.m.Y H:i:s") . "][$level]") . " $msg" . ($newLine ? "\n" : ''), FILE_APPEND);
8189
}
@@ -227,33 +235,25 @@ public static function sortContainers($containers, $order, $reverse = false, $re
227235
public static function backupContainer($container, $destination) {
228236
global $abSettings, $dockerClient;
229237

230-
self::backupLog("Backup {$container['Name']} - Container Volumeinfo: " . print_r($container['Volumes'], true), self::LOGLEVEL_DEBUG);
238+
$containerSettings = $abSettings->getContainerSpecificSettings($container['Name']);
231239

232-
$stripAppdataPath = '';
240+
self::backupLog("Backup {$container['Name']} - Container Volumeinfo: " . print_r($container['Volumes'], true), self::LOGLEVEL_DEBUG);
233241

234-
// Get default docker storage path
235-
$dockerCfgFile = ABSettings::$dockerIniFile;
236-
if (file_exists($dockerCfgFile)) {
237-
self::backupLog("Parsing $dockerCfgFile", self::LOGLEVEL_DEBUG);
238-
$dockerCfg = parse_ini_file($dockerCfgFile);
239-
if ($dockerCfg) {
240-
if (isset($dockerCfg['DOCKER_APP_CONFIG_PATH'])) {
241-
$stripAppdataPath = $dockerCfg['DOCKER_APP_CONFIG_PATH'];
242-
self::backupLog("Got default appdataPath: $stripAppdataPath", self::LOGLEVEL_DEBUG);
243-
}
244-
} else {
245-
self::backupLog("Could not parse $dockerCfgFile", self::LOGLEVEL_DEBUG);
246-
}
242+
$volumes = self::examineContainerVolumes($container);
243+
$dockerAppdataPath = self::getDockerAppdataPath();
244+
if (empty($dockerAppdataPath)) {
245+
ABHelper::backupLog("Docker appdata path could not be examined!", self::LOGLEVEL_ERR);
246+
return false;
247247
}
248248

249-
250-
$volumes = [];
251-
foreach ($container['Volumes'] ?? [] as $volume) {
252-
$hostPath = explode(":", $volume)[0];
253-
if (!empty($stripAppdataPath) && strpos($volume, $stripAppdataPath) === 0) {
254-
$hostPath = ltrim(str_replace($stripAppdataPath, '', $hostPath), '/');
249+
if (true || $containerSettings['backupExtVolumes'] == 'no') {
250+
self::backupLog("Should NOT backup ext volumes, sanitizing...", self::LOGLEVEL_DEBUG);
251+
foreach ($volumes as $index => $volume) {
252+
if (str_starts_with($volume, '/')) {
253+
self::backupLog("Removing volume " . $volume . " because ext volumes should be skipped", self::LOGLEVEL_DEBUG);
254+
unset($volumes[$index]);
255+
}
255256
}
256-
$volumes[] = $hostPath;
257257
}
258258

259259
if (empty($volumes)) {
@@ -265,14 +265,10 @@ public static function backupContainer($container, $destination) {
265265

266266
$destination = $destination . "/" . $container['Name'] . '.tar';
267267

268-
$containerSettings = $abSettings->getContainerSpecificSettings($container['Name']);
269-
270268
$tarVerifyOptions = ['--diff'];
271269
$tarOptions = ['-c'];
272270

273-
if (!empty($stripAppdataPath)) {
274-
$tarOptions[] = $tarVerifyOptions[] = '-C ' . escapeshellarg($stripAppdataPath);
275-
}
271+
$tarOptions[] = $tarVerifyOptions[] = '-C ' . escapeshellarg($dockerAppdataPath);
276272

277273
switch ($abSettings->compression) {
278274
case 'yes':
@@ -337,6 +333,7 @@ public static function backupContainer($container, $destination) {
337333
/**
338334
* Special debug: The creation was ok but verification failed: Something is accessing docker files! List docker info for this container
339335
*/
336+
$output = null; // Reset exec lines
340337
exec("ps aux | grep docker", $output);
341338
self::backupLog("ps aux docker:" . PHP_EOL . print_r($output, true), self::LOGLEVEL_DEBUG);
342339
$nowRunning = $dockerClient->getDockerContainers();
@@ -371,4 +368,49 @@ public static function scriptRunning($externalCmd = false) {
371368
public static function abortRequested() {
372369
return file_exists(ABSettings::$tempFolder . '/' . ABSettings::$stateFileAbort);
373370
}
371+
372+
public static function getDockerAppdataPath() {
373+
$dockerAppdataPath = '';
374+
375+
// Get default docker storage path
376+
if (empty(self::$dockerCfg)) {
377+
$dockerCfgFile = ABSettings::$dockerIniFile;
378+
if (file_exists($dockerCfgFile)) {
379+
self::backupLog("Parsing $dockerCfgFile", self::LOGLEVEL_DEBUG);
380+
$dockerCfg = parse_ini_file($dockerCfgFile);
381+
ABHelper::backupLog("dockerCfg: " . PHP_EOL . print_r($dockerCfg, true), self::LOGLEVEL_DEBUG);
382+
if ($dockerCfg) {
383+
self::$dockerCfg = $dockerCfg;
384+
} else {
385+
self::backupLog("Could not parse $dockerCfgFile", self::LOGLEVEL_ERR);
386+
return false;
387+
}
388+
}
389+
} else {
390+
ABHelper::backupLog("Got dockerCfg from cache.", ABHelper::LOGLEVEL_DEBUG);
391+
$dockerCfg = self::$dockerCfg;
392+
}
393+
394+
if (isset($dockerCfg['DOCKER_APP_CONFIG_PATH'])) {
395+
$dockerAppdataPath = $dockerCfg['DOCKER_APP_CONFIG_PATH'];
396+
} else {
397+
self::backupLog("dockerCfg is there but no Appdata path iset set??", self::LOGLEVEL_ERR);
398+
}
399+
return $dockerAppdataPath;
400+
}
401+
402+
public static function examineContainerVolumes($container) {
403+
404+
$dockerAppdataPath = self::getDockerAppdataPath();
405+
406+
$volumes = [];
407+
foreach ($container['Volumes'] ?? [] as $volume) {
408+
$hostPath = explode(":", $volume)[0];
409+
if (!empty($dockerAppdataPath) && str_starts_with($volume, $dockerAppdataPath)) {
410+
$hostPath = ltrim(str_replace($dockerAppdataPath, '', $hostPath), '/');
411+
}
412+
$volumes[] = rtrim($hostPath, '/');
413+
}
414+
return $volumes;
415+
}
374416
}

src/include/ABSettings.php

+18-4
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,17 @@ class ABSettings {
3636
public string|int $keepMinBackups = '3';
3737
public string $destination = '';
3838
public string $compression = 'yes';
39-
public array $defaults = ['verifyBackup' => 'yes', 'ignoreBackupErrors' => 'no', 'updateContainer' => 'no'];
39+
public array $defaults = [
40+
'verifyBackup' => 'yes',
41+
'ignoreBackupErrorss' => 'no',
42+
'updateContainer' => 'no',
43+
44+
// The following are hidden, container special default settings
45+
'skip' => 'no',
46+
'exclude' => '',
47+
'dontStop' => 'no',
48+
'backupExtVolumes' => 'no'
49+
];
4050
public string $flashBackup = 'yes';
4151
public string $notification = 'errors';
4252
public string $backupFrequency = 'disabled';
@@ -61,7 +71,11 @@ public function __construct() {
6171
if ($config) {
6272
foreach ($config as $key => $value) {
6373
if (property_exists($this, $key)) {
64-
$this->$key = $value;
74+
if ($key == 'defaults') {
75+
$this->$key = array_merge($this->defaults, $value);
76+
} else {
77+
$this->$key = $value;
78+
}
6579
}
6680
}
6781
}
@@ -103,10 +117,10 @@ public function getContainerSpecificSettings($name, $setEmptyToDefault = true) {
103117
foreach ($defaultSettings as $setting => $value) {
104118
$defaultSettings[$setting] = '';
105119
}
106-
return array_merge($defaultSettings, ['skip' => 'no', 'exclude' => '', 'dontStop' => 'no']);
120+
return $defaultSettings;
107121
}
108122

109-
$settings = $this->containerSettings[$name];
123+
$settings = array_merge($this->defaults, $this->containerSettings[$name]);
110124

111125
if ($setEmptyToDefault) {
112126
foreach ($settings as $setting => $value) {

src/pages/content/settings.php

+12-5
Original file line numberDiff line numberDiff line change
@@ -295,14 +295,15 @@ class="fa fa-clock-o title"></i>Notifications, scheduling and retention</span>
295295

296296
foreach ($allContainers as $container) {
297297
$image = empty($container['Icon']) ? '/plugins/dynamix.docker.manager/images/question.png' : $container['Icon'];
298-
$volumes = [];
299-
foreach ($container['Volumes'] ?? [] as $volume) {
300-
$volumes[] = explode(":", $volume)[0];
301-
}
302-
$volumes = implode("<br />", $volumes);
298+
$volumes = ABHelper::examineContainerVolumes($container);
303299

304300
if (empty($volumes)) {
305301
$volumes = "<b>No volumes - container will NOT being backed up!</b>";
302+
} else {
303+
foreach ($volumes as $index => $volume) {
304+
$volumes[$index] = '<span class="fa ' . (str_starts_with($volume, '/') ? 'fa-external-link' : 'fa-folder') . '"> <code>' . $volume . '</code></span>';
305+
}
306+
$volumes = implode('<br />', $volumes);
306307
}
307308

308309
$containerSetting = $abSettings->getContainerSpecificSettings($container['Name'], false);
@@ -323,6 +324,12 @@ class="fa fa-clock-o title"></i>Notifications, scheduling and retention</span>
323324
<dt>Configured volumes</dt>
324325
<dd><div style="display: table">$volumes</div></dd>
325326
327+
<!--<dt>Save external volumes? <small>Those with an <i class="fa fa-external-link"></i></small></dt>
328+
<dd><select id='{$container['Name']}_backupExtVolumes' name="containerSettings[{$container['Name']}][backupExtVolumes]" data-setting="{$containerSetting['backupExtVolumes']}" >
329+
<option value='no'>No</option>
330+
<option value='yes'>Yes</option>
331+
</select></dd>-->
332+
326333
<dt>Verify Backup?</dt>
327334
<dd><select id='{$container['Name']}_verifyBackup' name="containerSettings[{$container['Name']}][verifyBackup]" data-setting="{$containerSetting['verifyBackup']}" >
328335
<option value=''>Use standard</option>

src/scripts/backup.php

+9-9
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use unraid\plugins\AppdataBackup\ABSettings;
99

1010
require_once("/usr/local/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php");
11-
require_once __DIR__ . '/../include/ABHelper.php';
11+
require_once dirname(__DIR__) . '/include/ABHelper.php';
1212

1313
/**
1414
* Helper for later renaming of the backup folder to suffix -failed
@@ -29,13 +29,13 @@
2929
exec("rm " . ABSettings::$tempFolder . '/*.log');
3030
} // Creation of tempFolder is handled by backupLog
3131

32-
ABHelper::backupLog("👋 WELCOME TO APPDATA.BACKUP!! :D");
33-
3432
$unraidVersion = parse_ini_file('/etc/unraid-version');
35-
ABHelper::backupLog("unraid-version: " . print_r($unraidVersion, true), ABHelper::LOGLEVEL_DEBUG);
3633

3734
file_put_contents(ABSettings::$tempFolder . '/' . ABSettings::$stateFileScriptRunning, getmypid());
3835

36+
ABHelper::backupLog("👋 WELCOME TO APPDATA.BACKUP!! :D");
37+
ABHelper::backupLog("unraid-version: " . print_r($unraidVersion, true), ABHelper::LOGLEVEL_DEBUG);
38+
3939
/**
4040
* Some basic checks
4141
*/
@@ -362,7 +362,7 @@
362362
$correctedItem = array_reverse(explode("/", $backupItem))[0];
363363
$backupDate = date_create_from_format("??_Ymd_His", $correctedItem);
364364
if (!$backupDate) {
365-
ABHelper::backupLog("Cannot create date from " . $correctedItem, ABHelper::LOGLEVEL_ERR);
365+
ABHelper::backupLog("Cannot create date from " . $correctedItem, ABHelper::LOGLEVEL_DEBUG);
366366
continue;
367367
}
368368
if ($backupDate >= $nowDate && !in_array($backupItem, $toKeep)) {
@@ -402,11 +402,11 @@
402402
ABHelper::backupLog("❤️");
403403

404404
if (!empty($abDestination)) {
405+
copy(ABSettings::$tempFolder . '/' . ABSettings::$logfile, $abDestination . '/backup.log');
406+
copy(ABSettings::getConfigPath(), $abDestination . '/' . ABSettings::$settingsFile);
405407
if ($errorOccured) {
406-
exec('rm -rf ' . escapeshellarg($abDestination));
407-
} else {
408-
copy(ABSettings::$tempFolder . '/' . ABSettings::$logfile, $abDestination . '/backup.log');
409-
copy(ABSettings::getConfigPath(), $abDestination . '/' . ABSettings::$settingsFile);
408+
copy(ABSettings::$tempFolder . '/' . ABSettings::$debugLogFile, $abDestination . '/backup.debug.log');
409+
rename($abDestination, $abDestination . '-failed');
410410
}
411411
}
412412
if (file_exists(ABSettings::$tempFolder . '/' . ABSettings::$stateFileAbort)) {

0 commit comments

Comments
 (0)