@xen-orchestra/backups 0.44.4 → 0.44.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/RemoteAdapter.mjs CHANGED
@@ -35,6 +35,8 @@ export const DIR_XO_CONFIG_BACKUPS = 'xo-config-backups'
35
35
 
36
36
  export const DIR_XO_POOL_METADATA_BACKUPS = 'xo-pool-metadata-backups'
37
37
 
38
+ const IMMUTABILTY_METADATA_FILENAME = '/immutability.json'
39
+
38
40
  const { debug, warn } = createLogger('xo:backups:RemoteAdapter')
39
41
 
40
42
  const compareTimestamp = (a, b) => a.timestamp - b.timestamp
@@ -749,10 +751,37 @@ export class RemoteAdapter {
749
751
  }
750
752
 
751
753
  async readVmBackupMetadata(path) {
754
+ let json
755
+ let isImmutable = false
756
+ let remoteIsImmutable = false
757
+ // if the remote is immutable, check if this metadatas are also immutables
758
+ try {
759
+ // this file is not encrypted
760
+ await this._handler._readFile(IMMUTABILTY_METADATA_FILENAME)
761
+ remoteIsImmutable = true
762
+ } catch (error) {
763
+ if (error.code !== 'ENOENT') {
764
+ throw error
765
+ }
766
+ }
767
+
768
+ try {
769
+ // this will trigger an EPERM error if the file is immutable
770
+ json = await this.handler.readFile(path, { flag: 'r+' })
771
+ // s3 handler don't respect flags
772
+ } catch (err) {
773
+ // retry without triggerring immutbaility check ,only on immutable remote
774
+ if (err.code === 'EPERM' && remoteIsImmutable) {
775
+ isImmutable = true
776
+ json = await this._handler.readFile(path, { flag: 'r' })
777
+ } else {
778
+ throw err
779
+ }
780
+ }
752
781
  // _filename is a private field used to compute the backup id
753
782
  //
754
783
  // it's enumerable to make it cacheable
755
- const metadata = { ...JSON.parse(await this._handler.readFile(path)), _filename: path }
784
+ const metadata = { ...JSON.parse(json), _filename: path, isImmutable }
756
785
 
757
786
  // backups created on XenServer < 7.1 via JSON in XML-RPC transports have boolean values encoded as integers, which make them unusable with more recent XAPIs
758
787
  if (typeof metadata.vm.is_a_template === 'number') {
@@ -6,7 +6,8 @@ function formatVmBackup(backup) {
6
6
 
7
7
  let differencingVhds
8
8
  let dynamicVhds
9
- const withMemory = vmSnapshot.suspend_VDI !== 'OpaqueRef:NULL'
9
+ // some backups don't use snapshots, therefore cannot be with memory
10
+ const withMemory = vmSnapshot !== undefined && vmSnapshot.suspend_VDI !== 'OpaqueRef:NULL'
10
11
  // isVhdDifferencing is either undefined or an object
11
12
  if (isVhdDifferencing !== undefined) {
12
13
  differencingVhds = Object.values(isVhdDifferencing).filter(t => t).length
@@ -30,6 +31,7 @@ function formatVmBackup(backup) {
30
31
  }),
31
32
 
32
33
  id: backup.id,
34
+ isImmutable: backup.isImmutable,
33
35
  jobId: backup.jobId,
34
36
  mode: backup.mode,
35
37
  scheduleId: backup.scheduleId,
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "type": "git",
9
9
  "url": "https://github.com/vatesfr/xen-orchestra.git"
10
10
  },
11
- "version": "0.44.4",
11
+ "version": "0.44.6",
12
12
  "engines": {
13
13
  "node": ">=14.18"
14
14
  },
@@ -28,7 +28,7 @@
28
28
  "@vates/nbd-client": "^3.0.0",
29
29
  "@vates/parse-duration": "^0.1.1",
30
30
  "@xen-orchestra/async-map": "^0.1.2",
31
- "@xen-orchestra/fs": "^4.1.3",
31
+ "@xen-orchestra/fs": "^4.1.4",
32
32
  "@xen-orchestra/log": "^0.6.0",
33
33
  "@xen-orchestra/template": "^0.1.0",
34
34
  "app-conf": "^2.3.0",