Skip to content

Commit ac103e4

Browse files
committed
packing status
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
1 parent 52efe49 commit ac103e4

File tree

7 files changed

+106
-31
lines changed

7 files changed

+106
-31
lines changed

README.md

Lines changed: 62 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@
22

33
This App allows admin to create and store backup images of their Nextcloud
44

5-
65
- [Restoring Points](#restoring-point)
6+
- [Hardware Requirement](#hardware)
77
- [How the Backup App manage your data](#backup-manage-data)
8-
- [Upload to External Storages](#external-storages)
98
- [Important details about your data](#important)
9+
- [Upload to External Storages](#external-storages)
10+
- [AppData on External Storage](#external-appdata)
1011
- [Available `occ` commands](#occ)
1112

12-
1313
<a name="restoring-point"></a>
14+
1415
## Restoring Points
1516

1617
A restoring point is an image of your Nextcloud at a specific time. A restoring point can be:
@@ -64,37 +65,48 @@ The normal process is to re-create the `restoring-point.data` a new one, however
6465
- the restoring process will require some knowledge from the admin about the infrastructure from the
6566
original instance that generated the backup.
6667

68+
<a name="hardware"></a>
69+
70+
## Hardware requirement
71+
72+
- **Diskspace**: Creating and storing backups require a lot, **a lot**, of disk-space.
73+
74+
- **AES Hardware Acceleration**: If your processor does not
75+
include [AES instruction set](https://en.wikipedia.org/wiki/AES_instruction_set), the encryption
76+
process will _"downgrade"_ and use `aes-256-cbc`.
77+
This should only affect you when using the Backup App to migrate your instance from an AES-supporting
78+
CPU to a non-AES-supporting CPU. Enforcing the use of `aes-256-cbc` when creating the backup on the
79+
AES-supporting CPU will fix this:
80+
81+
- run: `./occ config:app:set backup force_cbc --value '1' `
82+
- create a new backup: `./occ backup:point:create`
83+
6784
<a name="backup-manage-data"></a>
85+
6886
## How the Backup App manage your data
6987

7088
### The timing
7189

7290
The settings available in the Admin Settings/Backup page, allow an admin to configure when the next
7391
backups will be run and at which rate:
74-
...
75-
### The first pass (the backup process)
76-
...
92+
...
7793

78-
### The second pass (the packing process)
79-
...
94+
### The first pass (the backup process)
8095

96+
...
8197

82-
<a name="external-storages"></a>
83-
## Upload to External Storages
98+
### The second pass (the packing process)
8499

100+
...
85101

86102
<a name="important"></a>
103+
87104
## Important details about your data
88105

89106
- **Disk-space**: The 1st pass does not compress anything, meaning that you will need at least the
90-
equivalent of currently used space by your Nextcloud as available disk-space.
91-
If you have no disk-space available, you can setup your instance to directly store your backup on an
92-
external storage:
93-
- the data generated during the 1st pass are not encrypted, Your data leaves the internal data folder
94-
from your instance and are now available on an external storage.
95-
- the 1st-pass will require more resource and your instance will stays in maintenance mode for a
96-
longer time.
97-
- If your external storage is not a local folder, huge network resources will be required.
107+
equivalent of currently used space by your Nextcloud as available disk-space. If you have no disk-space
108+
available, you can configure the app to use an external storage to store all its data.
109+
The configuration process is described in [this chapter](#external-appdata).
98110

99111

100112
- **Temporary Files**: during the 2nd pass (packing process), the compression and encryption require the
@@ -104,14 +116,40 @@ backups will be run and at which rate:
104116

105117

106118
- **Export your setup**: If the option is not disable, Backups are encrypted with a key that is stored in
107-
the database of your current instance of Nextcloud. The key is mandatory to recover any data from your backups.
108-
109-
You can export your setup from the Admin Settings/Backup page, or using `occ`. If encrypted, the export process will
110-
generate and returns its own key that will be required during the import when restoring your instance.
111-
As an admin, you will need to store the export file and its key, preferably in different location.
112-
119+
the database of your current instance of Nextcloud. The key is mandatory to recover any data from your
120+
backups.
121+
122+
You can export your setup from the Admin Settings/Backup page, or using `occ`. If encrypted, the export
123+
process will generate and returns its own key that will be required during the import when restoring
124+
your instance. As an admin, you will need to store the export file and its key, preferably in different
125+
location.
126+
127+
128+
- **.nobackup**: The presence of a `.nobackup` file in a folder will exclude all content from the current
129+
folder and its subfolders at the creation of the backup.
130+
131+
<a name="external-storages"></a>
132+
133+
## Upload to External Storages
134+
135+
<a name="external-appdata"></a>
136+
137+
## AppData on External Storage
138+
139+
If you have no disk-space available, you can configure the app to use an external storage to store all
140+
its data:
141+
142+
- the data generated during the 1st pass are not encrypted, Your data leaves the internal data folder
143+
from your instance and are now available on an external storage.
144+
- the 1st-pass will require more resources and your instance will stays in maintenance mode for a longer
145+
time.
146+
- If your external storage is not a local folder, huge network resources will be required.
147+
148+
run `./occ backup:external:appdata` and follow instruction to select the configured external storage, and
149+
configure the path to the right folder.
113150

114151
<a name="occ"></a>
152+
115153
## Available `occ` commands:
116154

117155
### Manage remote instance to store your backups remotely

lib/Cron/Manage.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ protected function run($argument) {
105105
return;
106106
}
107107

108+
// TODO: purge old restoring points.
109+
108110
// uploading
109111
foreach ($this->pointService->getLocalRestoringPoints() as $point) {
110112
if ($point->isArchive()) {

lib/Db/PointRequest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,19 @@ public function update(RestoringPoint $point, bool $updateMetadata = false): voi
9494
}
9595

9696

97+
/**
98+
* @param RestoringPoint $point
99+
*/
100+
public function updateStatus(RestoringPoint $point): void {
101+
$qb = $this->getPointUpdateSql();
102+
$qb->set('status', $qb->createNamedParameter($point->getStatus()));
103+
$qb->limitToUid($point->getId());
104+
$qb->limitToInstance($point->getInstance());
105+
106+
$qb->execute();
107+
}
108+
109+
97110
/**
98111
* @param string $pointId
99112
*/

lib/Model/RestoringPoint.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class RestoringPoint implements IDeserializable, INC23QueryRow, ISignedModel, Js
5959
public const STATUS_PACKED = 1;
6060
public const STATUS_COMPRESSED = 2;
6161
public const STATUS_ENCRYPTED = 4;
62+
public const STATUS_PACKING = 8;
6263

6364
public const LOCK_TIMEOUT = 3600 * 3;
6465

lib/Service/MetadataService.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,15 @@ public function globalUpdate(RestoringPoint $point) {
103103
}
104104

105105

106+
/**
107+
* @throws NotPermittedException
108+
* @throws NotFoundException
109+
*/
110+
public function updateStatus(RestoringPoint $point) {
111+
$this->pointRequest->updateStatus($point);
112+
$this->saveMetadata($point);
113+
}
114+
106115
/**
107116
* @param RestoringPoint $point
108117
*/
@@ -146,4 +155,5 @@ public function isLock(RestoringPoint $point): void {
146155
throw new RestoringPointLockException('point is locked');
147156
}
148157
}
158+
149159
}

lib/Service/PackService.php

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ public function __construct(
131131
* @throws RestoringPointLockException
132132
*/
133133
public function packPoint(RestoringPoint $point, bool $force = false): void {
134-
if ($point->isStatus(RestoringPoint::STATUS_PACKED)) {
134+
if ($point->isStatus(RestoringPoint::STATUS_PACKED)
135+
&& !$point->isStatus(RestoringPoint::STATUS_PACKING)) {
135136
throw new RestoringPointPackException('restoring point is already packed');
136137
}
137138

@@ -144,6 +145,9 @@ public function packPoint(RestoringPoint $point, bool $force = false): void {
144145
$this->metadataService->isLock($point);
145146
$this->metadataService->lock($point);
146147

148+
$point->addStatus(RestoringPoint::STATUS_PACKING);
149+
$this->metadataService->updateStatus($point);
150+
147151
$oldChunks = [];
148152
foreach ($point->getRestoringData() as $data) {
149153
foreach ($data->getChunks() as $chunk) {
@@ -156,6 +160,7 @@ public function packPoint(RestoringPoint $point, bool $force = false): void {
156160
$oldChunks[] = clone $chunk;
157161
$this->packChunk($point, $chunk);
158162
}
163+
159164
} catch (Throwable $t) {
160165
$point->setStatus(RestoringPoint::STATUS_ISSUE)
161166
->getNotes()
@@ -168,15 +173,19 @@ public function packPoint(RestoringPoint $point, bool $force = false): void {
168173
'issue on chunk ' . $chunk->getName() . ' - ' . $t->getMessage()
169174
);
170175
}
176+
177+
171178
}
172179
}
173180

174181
$this->removeOldChunkFiles($point, $oldChunks);
175182

176-
$point->addStatus(RestoringPoint::STATUS_PACKED)
177-
->getNotes()
178-
->u('pack_error')
179-
->u('pack_date');
183+
$point
184+
->removeStatus(RestoringPoint::STATUS_PACKING)
185+
->addStatus(RestoringPoint::STATUS_PACKED)
186+
->getNotes()
187+
->u('pack_error')
188+
->u('pack_date');
180189

181190
try {
182191
$this->remoteStreamService->signPoint($point);
@@ -577,7 +586,8 @@ public function getPartResource(
577586
* @throws Throwable
578587
*/
579588
public function unpackPoint(RestoringPoint $point): void {
580-
if (!$point->isStatus(RestoringPoint::STATUS_PACKED)) {
589+
if (!$point->isStatus(RestoringPoint::STATUS_PACKED)
590+
&& !$point->isStatus(RestoringPoint::STATUS_PACKING)) {
581591
throw new RestoringPointPackException('restoring point is not packed');
582592
}
583593

lib/Service/UploadService.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ public function __construct(
137137
* @throws RestoringPointLockException
138138
*/
139139
public function uploadPoint(RestoringPoint $point): void {
140-
if (!$point->isStatus(RestoringPoint::STATUS_PACKED)) {
140+
if (!$point->isStatus(RestoringPoint::STATUS_PACKED)
141+
|| $point->isStatus(RestoringPoint::STATUS_PACKING)) {
141142
throw new RestoringPointPackException('restoring point is not packed');
142143
}
143144

0 commit comments

Comments
 (0)