@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.
- package/dist/abstract-classes/base-controller.mjs +4 -2
- package/dist/abstract-classes/xapi-xo-controller.mjs +2 -6
- package/dist/alarms/alarm.service.mjs +2 -1
- package/dist/backup-jobs/backup-job.controller.mjs +284 -0
- package/dist/backup-jobs/backup-job.service.mjs +25 -0
- package/dist/backup-jobs/backup-job.type.mjs +1 -0
- package/dist/backup-logs/backup-log.controller.mjs +75 -0
- package/dist/backup-logs/backup-log.service.mjs +5 -0
- package/dist/groups/group.controller.mjs +37 -1
- package/dist/ioc/ioc.mjs +36 -0
- package/dist/open-api/common/response.common.mjs +4 -0
- package/dist/open-api/oa-examples/backup-job.oa-example.mjs +128 -0
- package/dist/open-api/oa-examples/backup-log.oa-example.mjs +93 -0
- package/dist/open-api/oa-examples/proxy.oa-example.mjs +25 -0
- package/dist/open-api/oa-examples/restore-log.oa-example.mjs +53 -0
- package/dist/open-api/oa-examples/user.oa-example.mjs +32 -0
- package/dist/open-api/oa-examples/vdi.oa-example.mjs +3 -0
- package/dist/open-api/routes/routes.js +1955 -513
- package/dist/proxies/proxy.controller.mjs +61 -0
- package/dist/rest-api/rest-api.mjs +6 -2
- package/dist/restore-logs/restore-log.controller.mjs +144 -0
- package/dist/srs/sr.controller.mjs +39 -2
- package/dist/tasks/task.controller.mjs +49 -3
- package/dist/tasks/task.service.mjs +24 -0
- package/dist/users/user.controller.mjs +91 -12
- package/dist/users/user.service.mjs +21 -0
- package/dist/vdi-snapshots/vdi-snapshot.controller.mjs +46 -4
- package/dist/vdis/vdi.controller.mjs +43 -4
- package/dist/vdis/vdi.service.mjs +21 -0
- package/dist/vm-snapshots/vm-snapshot.controller.mjs +72 -3
- package/dist/vm-templates/vm-template.controller.mjs +43 -2
- package/dist/vms/vm.controller.mjs +135 -5
- package/dist/vms/vm.service.mjs +18 -0
- package/open-api/spec/swagger.json +8373 -4057
- package/package.json +4 -4
- 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
|
-
|
|
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
|
-
|
|
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 };
|
package/dist/vms/vm.service.mjs
CHANGED
|
@@ -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
|
}
|