@xen-orchestra/backups 0.54.1 → 0.54.2

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.
@@ -79,8 +79,13 @@ export class ImportVmBackup {
79
79
  debug('found disks, wlll search its snapshots', { snapshots: xapiDisk.snapshots })
80
80
  for (const snapshotRef of xapiDisk.snapshots) {
81
81
  const snapshot = await this._xapi.getRecord('VDI', snapshotRef)
82
- debug('handling snapshot', { snapshot })
83
82
 
83
+ debug('handling snapshot', { snapshot })
84
+ if (snapshot.type === 'cbt_metadata') {
85
+ // disk without data can't be used as a base
86
+ debug('cbt metadata snapshot, skip')
87
+ continue
88
+ }
84
89
  // take only the first snapshot
85
90
  if (snapshotCandidate && snapshotCandidate.snapshot_time < snapshot.snapshot_time) {
86
91
  debug('already got a better candidate')
package/RemoteAdapter.mjs CHANGED
@@ -107,10 +107,13 @@ export class RemoteAdapter {
107
107
  async *_getLvmLogicalVolumes(devicePath, pvId, vgName) {
108
108
  yield this._getLvmPhysicalVolume(devicePath, pvId && (await this._findPartition(devicePath, pvId)))
109
109
 
110
+ debug('activate LVM volume group', { vgName })
110
111
  await fromCallback(execFile, 'vgchange', ['-ay', vgName])
111
112
  try {
113
+ debug('get LVM volume group name and path', { vgName })
112
114
  yield lvs(['lv_name', 'lv_path'], vgName)
113
115
  } finally {
116
+ debug('deactivate LVM volume group', { vgName })
114
117
  await fromCallback(execFile, 'vgchange', ['-an', vgName])
115
118
  }
116
119
  }
@@ -121,15 +124,22 @@ export class RemoteAdapter {
121
124
  args.push('-o', partition.start * 512, '--sizelimit', partition.size)
122
125
  }
123
126
  args.push('--show', '-f', devicePath)
127
+
128
+ debug('attach loop device', { devicePath, partition })
124
129
  const path = (await fromCallback(execFile, 'losetup', args)).trim()
125
130
  try {
131
+ debug('list LVM physical volume', { path })
126
132
  await fromCallback(execFile, 'pvscan', ['--cache', path])
133
+
127
134
  yield path
128
135
  } finally {
129
136
  try {
130
137
  const vgNames = await pvs('vg_name', path)
138
+
139
+ debug('deactivate LVM volume groups', { vgNames })
131
140
  await fromCallback(execFile, 'vgchange', ['-an', ...vgNames])
132
141
  } finally {
142
+ debug('detach loop device', { path })
133
143
  await fromCallback(execFile, 'losetup', ['-d', path])
134
144
  }
135
145
  }
@@ -150,6 +160,7 @@ export class RemoteAdapter {
150
160
 
151
161
  const path = yield getTmpDir()
152
162
  const mount = options => {
163
+ debug('mount device', { devicePath, mountPath: path })
153
164
  return fromCallback(execFile, 'mount', [
154
165
  `--options=${options.join(',')}`,
155
166
  `--source=${devicePath}`,
@@ -167,6 +178,7 @@ export class RemoteAdapter {
167
178
  try {
168
179
  yield path
169
180
  } finally {
181
+ debug('umount device', { devicePath, mountPath: path })
170
182
  await fromCallback(execFile, 'umount', ['--lazy', path])
171
183
  }
172
184
  }
@@ -336,6 +348,8 @@ export class RemoteAdapter {
336
348
 
337
349
  const diskPath = handler.getFilePath('/' + diskId)
338
350
  const mountDir = yield getTmpDir()
351
+
352
+ debug('mount VHD (vhdimount)', { diskPath, mountPath: mountDir })
339
353
  await fromCallback(execFile, 'vhdimount', [diskPath, mountDir])
340
354
  try {
341
355
  let max = 0
@@ -357,6 +371,7 @@ export class RemoteAdapter {
357
371
 
358
372
  yield `${mountDir}/${maxEntry}`
359
373
  } finally {
374
+ debug('umount VHD (fusermount)', { diskPath, mountPath: mountDir })
360
375
  await fromCallback(execFile, 'fusermount', ['-uz', mountDir])
361
376
  }
362
377
  }
package/_getTmpDir.mjs CHANGED
@@ -1,16 +1,23 @@
1
1
  import Disposable from 'promise-toolbox/Disposable'
2
+ import { createLogger } from '@xen-orchestra/log'
2
3
  import { join } from 'node:path'
3
4
  import { mkdir, rmdir } from 'node:fs/promises'
4
5
  import { tmpdir } from 'os'
5
6
 
7
+ const { debug } = createLogger('xo:backups:getTmpDir')
8
+
6
9
  const MAX_ATTEMPTS = 3
7
10
 
8
11
  export async function getTmpDir() {
9
12
  for (let i = 0; true; ++i) {
10
13
  const path = join(tmpdir(), Math.random().toString(36).slice(2))
11
14
  try {
15
+ debug('creating directory', { path })
12
16
  await mkdir(path)
13
- return new Disposable(() => rmdir(path), path)
17
+ return new Disposable(() => {
18
+ debug('removing directory', { path })
19
+ return rmdir(path)
20
+ }, path)
14
21
  } catch (error) {
15
22
  if (i === MAX_ATTEMPTS) {
16
23
  throw error
package/package.json CHANGED
@@ -8,13 +8,13 @@
8
8
  "type": "git",
9
9
  "url": "https://github.com/vatesfr/xen-orchestra.git"
10
10
  },
11
- "version": "0.54.1",
11
+ "version": "0.54.2",
12
12
  "engines": {
13
13
  "node": ">=14.18"
14
14
  },
15
15
  "scripts": {
16
16
  "postversion": "npm publish --access public",
17
- "test-integration": "node--test *.integ.mjs"
17
+ "test-integration": "node --test *.integ.mjs"
18
18
  },
19
19
  "dependencies": {
20
20
  "@iarna/toml": "^2.2.5",
@@ -28,7 +28,7 @@
28
28
  "@vates/nbd-client": "^3.1.1",
29
29
  "@vates/parse-duration": "^0.1.1",
30
30
  "@xen-orchestra/async-map": "^0.1.2",
31
- "@xen-orchestra/fs": "^4.2.0",
31
+ "@xen-orchestra/fs": "^4.2.1",
32
32
  "@xen-orchestra/log": "^0.7.0",
33
33
  "@xen-orchestra/template": "^0.1.0",
34
34
  "app-conf": "^3.0.0",
@@ -48,18 +48,17 @@
48
48
  "uuid": "^9.0.0",
49
49
  "value-matcher": "^0.2.0",
50
50
  "vhd-lib": "^4.11.1",
51
- "xen-api": "^4.4.0",
51
+ "xen-api": "^4.5.0",
52
52
  "yazl": "^2.5.1"
53
53
  },
54
54
  "devDependencies": {
55
55
  "fs-extra": "^11.1.0",
56
56
  "rimraf": "^5.0.1",
57
57
  "sinon": "^18.0.0",
58
- "test": "^3.2.1",
59
58
  "tmp": "^0.2.1"
60
59
  },
61
60
  "peerDependencies": {
62
- "@xen-orchestra/xapi": "^7.6.1"
61
+ "@xen-orchestra/xapi": "^7.7.0"
63
62
  },
64
63
  "license": "AGPL-3.0-or-later",
65
64
  "author": {