@xen-orchestra/rest-api 0.15.0 → 0.16.0

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.
Files changed (36) hide show
  1. package/dist/abstract-classes/base-controller.mjs +4 -2
  2. package/dist/abstract-classes/xapi-xo-controller.mjs +2 -6
  3. package/dist/alarms/alarm.service.mjs +2 -1
  4. package/dist/backup-jobs/backup-job.controller.mjs +284 -0
  5. package/dist/backup-jobs/backup-job.service.mjs +25 -0
  6. package/dist/backup-jobs/backup-job.type.mjs +1 -0
  7. package/dist/backup-logs/backup-log.controller.mjs +75 -0
  8. package/dist/backup-logs/backup-log.service.mjs +5 -0
  9. package/dist/groups/group.controller.mjs +37 -1
  10. package/dist/ioc/ioc.mjs +36 -0
  11. package/dist/open-api/common/response.common.mjs +4 -0
  12. package/dist/open-api/oa-examples/backup-job.oa-example.mjs +128 -0
  13. package/dist/open-api/oa-examples/backup-log.oa-example.mjs +93 -0
  14. package/dist/open-api/oa-examples/proxy.oa-example.mjs +25 -0
  15. package/dist/open-api/oa-examples/restore-log.oa-example.mjs +53 -0
  16. package/dist/open-api/oa-examples/user.oa-example.mjs +32 -0
  17. package/dist/open-api/oa-examples/vdi.oa-example.mjs +3 -0
  18. package/dist/open-api/routes/routes.js +1955 -513
  19. package/dist/proxies/proxy.controller.mjs +61 -0
  20. package/dist/rest-api/rest-api.mjs +6 -2
  21. package/dist/restore-logs/restore-log.controller.mjs +144 -0
  22. package/dist/srs/sr.controller.mjs +39 -2
  23. package/dist/tasks/task.controller.mjs +49 -3
  24. package/dist/tasks/task.service.mjs +24 -0
  25. package/dist/users/user.controller.mjs +91 -12
  26. package/dist/users/user.service.mjs +21 -0
  27. package/dist/vdi-snapshots/vdi-snapshot.controller.mjs +46 -4
  28. package/dist/vdis/vdi.controller.mjs +43 -4
  29. package/dist/vdis/vdi.service.mjs +21 -0
  30. package/dist/vm-snapshots/vm-snapshot.controller.mjs +72 -3
  31. package/dist/vm-templates/vm-template.controller.mjs +43 -2
  32. package/dist/vms/vm.controller.mjs +135 -5
  33. package/dist/vms/vm.service.mjs +18 -0
  34. package/open-api/spec/swagger.json +8373 -4057
  35. package/package.json +4 -4
  36. package/tsoa.json +15 -0
@@ -7,21 +7,24 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  var __param = (this && this.__param) || function (paramIndex, decorator) {
8
8
  return function (target, key) { decorator(target, key, paramIndex); }
9
9
  };
10
- import { Example, Get, Path, Query, Request, Response, Route, Security, Tags } from 'tsoa';
10
+ import { Delete, Example, Get, Path, Query, Request, Response, Route, Security, SuccessResponse, Tags } from 'tsoa';
11
11
  import { inject } from 'inversify';
12
12
  import { provide } from 'inversify-binding-decorators';
13
13
  import { AlarmService } from '../alarms/alarm.service.mjs';
14
14
  import { escapeUnsafeComplexMatcher } from '../helpers/utils.helper.mjs';
15
15
  import { genericAlarmsExample } from '../open-api/oa-examples/alarm.oa-example.mjs';
16
- import { notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
16
+ import { noContentResp, notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
17
17
  import { RestApi } from '../rest-api/rest-api.mjs';
18
18
  import { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs';
19
19
  import { partialVdis, vdi, vdiIds } from '../open-api/oa-examples/vdi.oa-example.mjs';
20
+ import { VdiService } from './vdi.service.mjs';
20
21
  let VdiController = class VdiController extends XapiXoController {
21
22
  #alarmService;
22
- constructor(restApi, alarmService) {
23
+ #vdiService;
24
+ constructor(restApi, alarmService, vdiService) {
23
25
  super('VDI', restApi);
24
26
  this.#alarmService = alarmService;
27
+ this.#vdiService = vdiService;
25
28
  }
26
29
  /**
27
30
  * @example fields "*"
@@ -31,6 +34,19 @@ let VdiController = class VdiController extends XapiXoController {
31
34
  getVdis(req, fields, ndjson, filter, limit) {
32
35
  return this.sendObjects(Object.values(this.getObjects({ filter, limit })), req);
33
36
  }
37
+ /**
38
+ *
39
+ * Export VDI content
40
+ *
41
+ * @example id "c77f9955-c1d2-4b39-aa1c-73cdb2dacb7e"
42
+ */
43
+ async exportVdiContent(req, id, format) {
44
+ const res = req.res;
45
+ const stream = await this.#vdiService.exportContent(id, 'VDI', { format, response: res });
46
+ process.on('SIGTERM', () => req.destroy());
47
+ req.on('close', () => stream.destroy());
48
+ return stream;
49
+ }
34
50
  /**
35
51
  * @example id "c77f9955-c1d2-4b39-aa1c-73cdb2dacb7e"
36
52
  */
@@ -51,6 +67,13 @@ let VdiController = class VdiController extends XapiXoController {
51
67
  });
52
68
  return this.sendObjects(Object.values(alarms), req, 'alarms');
53
69
  }
70
+ /**
71
+ * @example id "c77f9955-c1d2-4b39-aa1c-73cdb2dacb7e"
72
+ */
73
+ async deleteVdi(id) {
74
+ const xapiVdi = this.getXapiObject(id);
75
+ await xapiVdi.$xapi.VDI_destroy(xapiVdi.$ref);
76
+ }
54
77
  };
55
78
  __decorate([
56
79
  Example(vdiIds),
@@ -62,6 +85,15 @@ __decorate([
62
85
  __param(3, Query()),
63
86
  __param(4, Query())
64
87
  ], VdiController.prototype, "getVdis", null);
88
+ __decorate([
89
+ Get('{id}.{format}'),
90
+ SuccessResponse(200, 'Download started', 'application/octet-stream'),
91
+ Response(notFoundResp.status, notFoundResp.description),
92
+ Response(422, 'Invalid format'),
93
+ __param(0, Request()),
94
+ __param(1, Path()),
95
+ __param(2, Path())
96
+ ], VdiController.prototype, "exportVdiContent", null);
65
97
  __decorate([
66
98
  Example(vdi),
67
99
  Get('{id}'),
@@ -80,6 +112,12 @@ __decorate([
80
112
  __param(4, Query()),
81
113
  __param(5, Query())
82
114
  ], VdiController.prototype, "getVdiAlarms", null);
115
+ __decorate([
116
+ Delete('{id}'),
117
+ SuccessResponse(noContentResp.status, noContentResp.description),
118
+ Response(notFoundResp.status, notFoundResp.description),
119
+ __param(0, Path())
120
+ ], VdiController.prototype, "deleteVdi", null);
83
121
  VdiController = __decorate([
84
122
  Route('vdis'),
85
123
  Security('*'),
@@ -87,6 +125,7 @@ VdiController = __decorate([
87
125
  Tags('vdis'),
88
126
  provide(VdiController),
89
127
  __param(0, inject(RestApi)),
90
- __param(1, inject(AlarmService))
128
+ __param(1, inject(AlarmService)),
129
+ __param(2, inject(VdiService))
91
130
  ], VdiController);
92
131
  export { VdiController };
@@ -0,0 +1,21 @@
1
+ export class VdiService {
2
+ #restApi;
3
+ constructor(restApi) {
4
+ this.#restApi = restApi;
5
+ }
6
+ async exportContent(id, type, { format, response }) {
7
+ const xapiVdi = this.#restApi.getXapiObject(id, type);
8
+ const stream = await xapiVdi.$xapi.VDI_exportContent(xapiVdi.$ref, { format });
9
+ if (response !== undefined) {
10
+ const headers = new Headers({
11
+ 'content-disposition': `attachment; filename=${id}.${format}`,
12
+ 'content-type': 'application/octet-stream',
13
+ });
14
+ if (stream.length !== undefined) {
15
+ headers.append('content-length', stream.length.toString());
16
+ }
17
+ response.setHeaders(headers);
18
+ }
19
+ return stream;
20
+ }
21
+ }
@@ -7,17 +7,18 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  var __param = (this && this.__param) || function (paramIndex, decorator) {
8
8
  return function (target, key) { decorator(target, key, paramIndex); }
9
9
  };
10
- import { Example, Get, Path, Query, Request, Response, Route, Security, Tags } from 'tsoa';
10
+ import { Delete, Example, Get, Path, Query, Request, Response, Route, Security, SuccessResponse, Tags } from 'tsoa';
11
11
  import { inject } from 'inversify';
12
- import { AlarmService } from '../alarms/alarm.service.mjs';
12
+ import { AlarmService, RAW_ALARM_FILTER } from '../alarms/alarm.service.mjs';
13
13
  import { escapeUnsafeComplexMatcher, limitAndFilterArray } from '../helpers/utils.helper.mjs';
14
14
  import { genericAlarmsExample } from '../open-api/oa-examples/alarm.oa-example.mjs';
15
- import { notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
15
+ import { forbiddenOperationResp, incorrectStateResp, noContentResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
16
16
  import { RestApi } from '../rest-api/rest-api.mjs';
17
17
  import { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs';
18
18
  import { provide } from 'inversify-binding-decorators';
19
19
  import { partialVmSnapshots, vmSnapshot, vmSnapshotIds, vmSnapshotVdis, } from '../open-api/oa-examples/vm-snapshot.oa-example.mjs';
20
20
  import { VmService } from '../vms/vm.service.mjs';
21
+ import { messageIds, partialMessages } from '../open-api/oa-examples/message.oa-example.mjs';
21
22
  let VmSnapshotController = class VmSnapshotController extends XapiXoController {
22
23
  #alarmService;
23
24
  #vmService;
@@ -35,12 +36,35 @@ let VmSnapshotController = class VmSnapshotController extends XapiXoController {
35
36
  getVmSnapshots(req, fields, ndjson, filter, limit) {
36
37
  return this.sendObjects(Object.values(this.getObjects({ filter, limit })), req);
37
38
  }
39
+ /**
40
+ *
41
+ * Export VM-snapshot. Compress is only used for XVA format
42
+ *
43
+ * @example id "d68fca2c-41e6-be87-d790-105c1642a090"
44
+ */
45
+ async exportVmSnapshot(req, id, format, compress) {
46
+ const stream = await this.#vmService.export(id, 'VM-snapshot', {
47
+ compress,
48
+ format,
49
+ response: req.res,
50
+ });
51
+ process.on('SIGTERM', () => req.destroy());
52
+ req.on('close', () => stream.destroy());
53
+ return stream;
54
+ }
38
55
  /**
39
56
  * @example id "d68fca2c-41e6-be87-d790-105c1642a090"
40
57
  */
41
58
  getVmSnapshot(id) {
42
59
  return this.getObject(id);
43
60
  }
61
+ /**
62
+ * @example id "d68fca2c-41e6-be87-d790-105c1642a090"
63
+ */
64
+ async deleteVmSnapshot(id) {
65
+ const xapiVmSnapshot = this.getXapiObject(id);
66
+ await xapiVmSnapshot.$xapi.VM_destroy(xapiVmSnapshot.$ref);
67
+ }
44
68
  /**
45
69
  * @example id "d68fca2c-41e6-be87-d790-105c1642a090"
46
70
  * @example fields "id,time"
@@ -65,6 +89,20 @@ let VmSnapshotController = class VmSnapshotController extends XapiXoController {
65
89
  const vdis = this.#vmService.getVmVdis(id, 'VM-snapshot');
66
90
  return this.sendObjects(limitAndFilterArray(vdis, { filter, limit }), req, obj => obj.type.toLowerCase() + 's');
67
91
  }
92
+ /**
93
+ * @example id "d68fca2c-41e6-be87-d790-105c1642a090"
94
+ * @example fields "name,id,$object"
95
+ * @example filter "name:VM_STARTED"
96
+ * @example limit 42
97
+ */
98
+ getVmSnapshotsMessages(req, id, fields, ndjson, filter, limit) {
99
+ const vm = this.getObject(id);
100
+ const messages = this.restApi.getObjectsByType('message', {
101
+ filter: `${escapeUnsafeComplexMatcher(filter) ?? ''} $object:${vm.uuid} !${RAW_ALARM_FILTER}`,
102
+ limit,
103
+ });
104
+ return this.sendObjects(Object.values(messages), req, 'messages');
105
+ }
68
106
  };
69
107
  __decorate([
70
108
  Example(vmSnapshotIds),
@@ -76,12 +114,30 @@ __decorate([
76
114
  __param(3, Query()),
77
115
  __param(4, Query())
78
116
  ], VmSnapshotController.prototype, "getVmSnapshots", null);
117
+ __decorate([
118
+ Get('{id}.{format}'),
119
+ SuccessResponse(200, 'Download started', 'application/octet-stream'),
120
+ Response(notFoundResp.status, notFoundResp.description),
121
+ Response(422, 'Invalid format, Invalid compress'),
122
+ __param(0, Request()),
123
+ __param(1, Path()),
124
+ __param(2, Path()),
125
+ __param(3, Query())
126
+ ], VmSnapshotController.prototype, "exportVmSnapshot", null);
79
127
  __decorate([
80
128
  Example(vmSnapshot),
81
129
  Get('{id}'),
82
130
  Response(notFoundResp.status, notFoundResp.description),
83
131
  __param(0, Path())
84
132
  ], VmSnapshotController.prototype, "getVmSnapshot", null);
133
+ __decorate([
134
+ Delete('{id}'),
135
+ SuccessResponse(noContentResp.status, noContentResp.description),
136
+ Response(notFoundResp.status, notFoundResp.description),
137
+ Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
138
+ Response(incorrectStateResp.status, incorrectStateResp.description),
139
+ __param(0, Path())
140
+ ], VmSnapshotController.prototype, "deleteVmSnapshot", null);
85
141
  __decorate([
86
142
  Example(genericAlarmsExample),
87
143
  Get('{id}/alarms'),
@@ -106,6 +162,19 @@ __decorate([
106
162
  __param(4, Query()),
107
163
  __param(5, Query())
108
164
  ], VmSnapshotController.prototype, "getVmSnapshotVdis", null);
165
+ __decorate([
166
+ Example(messageIds),
167
+ Example(partialMessages),
168
+ Get('{id}/messages'),
169
+ Tags('messages'),
170
+ Response(notFoundResp.status, notFoundResp.description),
171
+ __param(0, Request()),
172
+ __param(1, Path()),
173
+ __param(2, Query()),
174
+ __param(3, Query()),
175
+ __param(4, Query()),
176
+ __param(5, Query())
177
+ ], VmSnapshotController.prototype, "getVmSnapshotsMessages", null);
109
178
  VmSnapshotController = __decorate([
110
179
  Route('vm-snapshots'),
111
180
  Security('*'),
@@ -7,13 +7,13 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  var __param = (this && this.__param) || function (paramIndex, decorator) {
8
8
  return function (target, key) { decorator(target, key, paramIndex); }
9
9
  };
10
- import { Example, Get, Security, Query, Request, Response, Route, Tags, Path } from 'tsoa';
10
+ import { Example, Get, Security, Query, Request, Response, Route, Tags, Path, Delete, SuccessResponse } from 'tsoa';
11
11
  import { inject } from 'inversify';
12
12
  import { provide } from 'inversify-binding-decorators';
13
13
  import { AlarmService } from '../alarms/alarm.service.mjs';
14
14
  import { escapeUnsafeComplexMatcher, limitAndFilterArray } from '../helpers/utils.helper.mjs';
15
15
  import { genericAlarmsExample } from '../open-api/oa-examples/alarm.oa-example.mjs';
16
- import { notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
16
+ import { forbiddenOperationResp, incorrectStateResp, noContentResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
17
17
  import { RestApi } from '../rest-api/rest-api.mjs';
18
18
  import { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs';
19
19
  import { partialVmTemplates, vmTemplate, vmTemplateIds, vmTemplateVdis, } from '../open-api/oa-examples/vm-template.oa-example.mjs';
@@ -34,12 +34,35 @@ let VmTemplateController = class VmTemplateController extends XapiXoController {
34
34
  getVmTemplates(req, fields, ndjson, filter, limit) {
35
35
  return this.sendObjects(Object.values(this.getObjects({ filter, limit })), req);
36
36
  }
37
+ /**
38
+ *
39
+ * Export VM-template. Compress is only used for XVA format
40
+ *
41
+ * @example id "b7569d99-30f8-178a-7d94-801de3e29b5b-f873abe0-b138-4995-8f6f-498b423d234d"
42
+ */
43
+ async exportVmTemplate(req, id, format, compress) {
44
+ const stream = await this.#vmService.export(id, 'VM-template', {
45
+ compress,
46
+ format,
47
+ response: req.res,
48
+ });
49
+ process.on('SIGTERM', () => req.destroy());
50
+ req.on('close', () => stream.destroy());
51
+ return stream;
52
+ }
37
53
  /**
38
54
  * @example id "b7569d99-30f8-178a-7d94-801de3e29b5b-f873abe0-b138-4995-8f6f-498b423d234d"
39
55
  * */
40
56
  getVmTemplate(id) {
41
57
  return this.getObject(id);
42
58
  }
59
+ /**
60
+ * @example id "6d50ba76-0f11-1ff1-4f6a-b502afc31b8e"
61
+ */
62
+ async deleteVmTemplate(id) {
63
+ const xapiVmTemplate = this.getXapiObject(id);
64
+ await xapiVmTemplate.$xapi.VM_destroy(xapiVmTemplate.$ref);
65
+ }
43
66
  /**
44
67
  * @example id "b7569d99-30f8-178a-7d94-801de3e29b5b-f873abe0-b138-4995-8f6f-498b423d234d"
45
68
  * @example fields "id,time"
@@ -75,12 +98,30 @@ __decorate([
75
98
  __param(3, Query()),
76
99
  __param(4, Query())
77
100
  ], VmTemplateController.prototype, "getVmTemplates", null);
101
+ __decorate([
102
+ Get('{id}.{format}'),
103
+ SuccessResponse(200, 'Download started', 'application/octet-stream'),
104
+ Response(notFoundResp.status, notFoundResp.description),
105
+ Response(422, 'Invalid format, Invalid compress'),
106
+ __param(0, Request()),
107
+ __param(1, Path()),
108
+ __param(2, Path()),
109
+ __param(3, Query())
110
+ ], VmTemplateController.prototype, "exportVmTemplate", null);
78
111
  __decorate([
79
112
  Example(vmTemplate),
80
113
  Get('{id}'),
81
114
  Response(notFoundResp.status, notFoundResp.description),
82
115
  __param(0, Path())
83
116
  ], VmTemplateController.prototype, "getVmTemplate", null);
117
+ __decorate([
118
+ Delete('{id}'),
119
+ SuccessResponse(noContentResp.status, noContentResp.description),
120
+ Response(notFoundResp.status, notFoundResp.description),
121
+ Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
122
+ Response(incorrectStateResp.status, incorrectStateResp.description),
123
+ __param(0, Path())
124
+ ], VmTemplateController.prototype, "deleteVmTemplate", null);
84
125
  __decorate([
85
126
  Example(genericAlarmsExample),
86
127
  Get('{id}/alarms'),
@@ -11,24 +11,32 @@ import { Example, Get, Path, Post, Query, Request, Response, Route, Security, Ta
11
11
  import { inject } from 'inversify';
12
12
  import { incorrectState, invalidParameters } from 'xo-common/api-errors.js';
13
13
  import { provide } from 'inversify-binding-decorators';
14
- import { AlarmService } from '../alarms/alarm.service.mjs';
15
- import { asynchronousActionResp, createdResp, internalServerErrorResp, noContentResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
14
+ import { AlarmService, RAW_ALARM_FILTER } from '../alarms/alarm.service.mjs';
15
+ import { asynchronousActionResp, createdResp, forbiddenOperationResp, incorrectStateResp, internalServerErrorResp, noContentResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
16
16
  import { BASE_URL } from '../index.mjs';
17
17
  import { escapeUnsafeComplexMatcher, limitAndFilterArray } from '../helpers/utils.helper.mjs';
18
18
  import { genericAlarmsExample } from '../open-api/oa-examples/alarm.oa-example.mjs';
19
19
  import { partialVms, vm, vmIds, vmStatsExample, vmVdis } from '../open-api/oa-examples/vm.oa-example.mjs';
20
20
  import { RestApi } from '../rest-api/rest-api.mjs';
21
- import { taskLocation } from '../open-api/oa-examples/task.oa-example.mjs';
21
+ import { partialTasks, taskIds, taskLocation } from '../open-api/oa-examples/task.oa-example.mjs';
22
22
  import { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs';
23
23
  import { VmService } from './vm.service.mjs';
24
+ import { TaskService } from '../tasks/task.service.mjs';
25
+ import { BackupJobService } from '../backup-jobs/backup-job.service.mjs';
26
+ import { partialVmBackupJobs, vmBackupJobIds } from '../open-api/oa-examples/backup-job.oa-example.mjs';
27
+ import { messageIds, partialMessages } from '../open-api/oa-examples/message.oa-example.mjs';
24
28
  const IGNORED_VDIS_TAG = '[NOSNAP]';
25
29
  let VmController = class VmController extends XapiXoController {
26
30
  #alarmService;
27
31
  #vmService;
28
- constructor(restApi, alarmService, vmService) {
32
+ #taskService;
33
+ #backupJobService;
34
+ constructor(restApi, alarmService, vmService, taskService, backupJobService) {
29
35
  super('VM', restApi);
30
36
  this.#alarmService = alarmService;
31
37
  this.#vmService = vmService;
38
+ this.#taskService = taskService;
39
+ this.#backupJobService = backupJobService;
32
40
  }
33
41
  /**
34
42
  *
@@ -39,6 +47,18 @@ let VmController = class VmController extends XapiXoController {
39
47
  getVms(req, fields, ndjson, filter, limit) {
40
48
  return this.sendObjects(Object.values(this.getObjects({ filter, limit })), req);
41
49
  }
50
+ /**
51
+ *
52
+ * Export VM. Compress is only used for XVA format
53
+ *
54
+ * @example id "f07ab729-c0e8-721c-45ec-f11276377030"
55
+ */
56
+ async exportVm(req, id, format, compress) {
57
+ const stream = await this.#vmService.export(id, 'VM', { compress, format, response: req.res });
58
+ process.on('SIGTERM', () => req.destroy());
59
+ req.on('close', () => stream.destroy());
60
+ return stream;
61
+ }
42
62
  /**
43
63
  *
44
64
  * @example id "f07ab729-c0e8-721c-45ec-f11276377030"
@@ -46,6 +66,13 @@ let VmController = class VmController extends XapiXoController {
46
66
  getVm(id) {
47
67
  return this.getObject(id);
48
68
  }
69
+ /**
70
+ * @example id "f07ab729-c0e8-721c-45ec-f11276377030"
71
+ */
72
+ async deleteVm(id) {
73
+ const xapiVm = this.getXapiObject(id);
74
+ await xapiVm.$xapi.VM_destroy(xapiVm.$ref);
75
+ }
49
76
  /**
50
77
  *
51
78
  * VM must be running
@@ -326,6 +353,50 @@ let VmController = class VmController extends XapiXoController {
326
353
  const vdis = this.#vmService.getVmVdis(id, 'VM');
327
354
  return this.sendObjects(limitAndFilterArray(vdis, { filter, limit }), req, obj => obj.type.toLowerCase() + 's');
328
355
  }
356
+ /**
357
+ * @example id "f07ab729-c0e8-721c-45ec-f11276377030"
358
+ * @example fields "mode,name,type,id"
359
+ * @example filter "mode:full"
360
+ * @example limit 42
361
+ */
362
+ async vmGetVmBackupJobs(req, id, fields, ndjson, filter, limit) {
363
+ const backupJobs = await this.restApi.xoApp.getAllJobs('backup');
364
+ const vmBackupJobs = [];
365
+ for (const backupJob of backupJobs) {
366
+ if (await this.#backupJobService.isVmInBackupJob(backupJob.id, id)) {
367
+ vmBackupJobs.push(backupJob);
368
+ }
369
+ }
370
+ return this.sendObjects(limitAndFilterArray(vmBackupJobs, { filter, limit }), req, '/backup-jobs');
371
+ }
372
+ /**
373
+ * @example id "cef5f68c-61ae-3831-d2e6-1590d4934acf"
374
+ * @example fields "name,id,$object"
375
+ * @example filter "name:VM_STARTED"
376
+ * @example limit 42
377
+ */
378
+ getVmMessages(req, id, fields, ndjson, filter, limit) {
379
+ const vm = this.getObject(id);
380
+ const messages = this.restApi.getObjectsByType('message', {
381
+ filter: `${escapeUnsafeComplexMatcher(filter) ?? ''} $object:${vm.uuid} !${RAW_ALARM_FILTER}`,
382
+ limit,
383
+ });
384
+ return this.sendObjects(Object.values(messages), req, 'messages');
385
+ }
386
+ /**
387
+ * @example id "613f541c-4bed-fc77-7ca8-2db6b68f079c"
388
+ * @example fields "id,status,properties"
389
+ * @example filter "status:failure"
390
+ * @example limit 42
391
+ */
392
+ async getVmTasks(req, id, fields, ndjson, filter, limit) {
393
+ const vm = this.getObject(id);
394
+ const tasks = await this.#taskService.getTasks({
395
+ filter: `${escapeUnsafeComplexMatcher(filter) ?? ''} |(properties:objectId:${vm.id} properties:params:id:${vm.id})`,
396
+ limit,
397
+ });
398
+ return this.sendObjects(tasks, req, 'tasks');
399
+ }
329
400
  };
330
401
  __decorate([
331
402
  Example(vmIds),
@@ -337,12 +408,30 @@ __decorate([
337
408
  __param(3, Query()),
338
409
  __param(4, Query())
339
410
  ], VmController.prototype, "getVms", null);
411
+ __decorate([
412
+ Get('{id}.{format}'),
413
+ SuccessResponse(200, 'Download started', 'application/octet-stream'),
414
+ Response(notFoundResp.status, notFoundResp.description),
415
+ Response(422, 'Invalid format, Invalid compress'),
416
+ __param(0, Request()),
417
+ __param(1, Path()),
418
+ __param(2, Path()),
419
+ __param(3, Query())
420
+ ], VmController.prototype, "exportVm", null);
340
421
  __decorate([
341
422
  Example(vm),
342
423
  Get('{id}'),
343
424
  Response(notFoundResp.status, notFoundResp.description),
344
425
  __param(0, Path())
345
426
  ], VmController.prototype, "getVm", null);
427
+ __decorate([
428
+ Delete('{id}'),
429
+ SuccessResponse(noContentResp.status, noContentResp.description),
430
+ Response(notFoundResp.status, notFoundResp.description),
431
+ Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
432
+ Response(incorrectStateResp.status, incorrectStateResp.description),
433
+ __param(0, Path())
434
+ ], VmController.prototype, "deleteVm", null);
346
435
  __decorate([
347
436
  Example(vmStatsExample),
348
437
  Get('{id}/stats'),
@@ -489,6 +578,45 @@ __decorate([
489
578
  __param(4, Query()),
490
579
  __param(5, Query())
491
580
  ], VmController.prototype, "getVmVdis", null);
581
+ __decorate([
582
+ Example(vmBackupJobIds),
583
+ Example(partialVmBackupJobs),
584
+ Get('{id}/backup-jobs'),
585
+ Tags('backup-jobs'),
586
+ Response(notFoundResp.status, notFoundResp.description),
587
+ __param(0, Request()),
588
+ __param(1, Path()),
589
+ __param(2, Query()),
590
+ __param(3, Query()),
591
+ __param(4, Query()),
592
+ __param(5, Query())
593
+ ], VmController.prototype, "vmGetVmBackupJobs", null);
594
+ __decorate([
595
+ Example(messageIds),
596
+ Example(partialMessages),
597
+ Get('{id}/messages'),
598
+ Tags('messages'),
599
+ Response(notFoundResp.status, notFoundResp.description),
600
+ __param(0, Request()),
601
+ __param(1, Path()),
602
+ __param(2, Query()),
603
+ __param(3, Query()),
604
+ __param(4, Query()),
605
+ __param(5, Query())
606
+ ], VmController.prototype, "getVmMessages", null);
607
+ __decorate([
608
+ Example(taskIds),
609
+ Example(partialTasks),
610
+ Get('{id}/tasks'),
611
+ Tags('tasks'),
612
+ Response(notFoundResp.status, notFoundResp.description),
613
+ __param(0, Request()),
614
+ __param(1, Path()),
615
+ __param(2, Query()),
616
+ __param(3, Query()),
617
+ __param(4, Query()),
618
+ __param(5, Query())
619
+ ], VmController.prototype, "getVmTasks", null);
492
620
  VmController = __decorate([
493
621
  Route('vms'),
494
622
  Security('*'),
@@ -500,6 +628,8 @@ VmController = __decorate([
500
628
  provide(VmController),
501
629
  __param(0, inject(RestApi)),
502
630
  __param(1, inject(AlarmService)),
503
- __param(2, inject(VmService))
631
+ __param(2, inject(VmService)),
632
+ __param(3, inject(TaskService)),
633
+ __param(4, inject(BackupJobService))
504
634
  ], VmController);
505
635
  export { VmController };
@@ -97,4 +97,22 @@ export class VmService {
97
97
  }
98
98
  return vdis;
99
99
  }
100
+ async export(id, vmType, { compress, format, response }) {
101
+ const xapiVm = this.#restApi.getXapiObject(id, vmType);
102
+ let stream;
103
+ if (format === 'xva') {
104
+ stream = (await xapiVm.$xapi.VM_export(xapiVm.$ref, { compress })).body;
105
+ }
106
+ else {
107
+ stream = await xapiVm.$xapi.exportVmOva(xapiVm.$ref);
108
+ }
109
+ if (response !== undefined) {
110
+ const headers = new Headers({
111
+ 'content-disposition': `attachment; filename=${id}.${format}`,
112
+ 'content-type': 'application/octet-stream',
113
+ });
114
+ response.setHeaders(headers);
115
+ }
116
+ return stream;
117
+ }
100
118
  }