@xen-orchestra/rest-api 0.14.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/helpers/error.helper.mjs +10 -0
- package/dist/hosts/host.controller.mjs +24 -4
- package/dist/hosts/host.service.mjs +6 -7
- package/dist/hosts/host.type.mjs +1 -0
- package/dist/index.mjs +4 -0
- package/dist/ioc/ioc.mjs +36 -0
- package/dist/middlewares/generic-error-handler.middleware.mjs +5 -1
- package/dist/open-api/common/response.common.mjs +8 -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/host.oa-example.mjs +30 -0
- package/dist/open-api/oa-examples/pool.oa-example.mjs +30 -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/task.oa-example.mjs +46 -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 +2079 -490
- package/dist/pools/pool.controller.mjs +16 -1
- package/dist/pools/pool.service.mjs +18 -8
- 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 +167 -0
- 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/dist/xoa/xoa.service.mjs +14 -4
- package/open-api/spec/swagger.json +11733 -6660
- package/package.json +6 -5
- package/tsconfig.json +1 -0
- package/tsoa.json +27 -0
|
@@ -8,28 +8,35 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
8
8
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
9
|
};
|
|
10
10
|
import { Body, Delete, Example, Get, Middlewares, Patch, Path, Post, Query, Request, Response, Route, Security, SuccessResponse, Tags, } from 'tsoa';
|
|
11
|
+
import { inject } from 'inversify';
|
|
11
12
|
import { json } from 'express';
|
|
12
13
|
import { provide } from 'inversify-binding-decorators';
|
|
13
14
|
import { createdResp, forbiddenOperationResp, invalidParameters, noContentResp, notFoundResp, resourceAlreadyExists, unauthorizedResp, } from '../open-api/common/response.common.mjs';
|
|
14
15
|
import { forbiddenOperation } from 'xo-common/api-errors.js';
|
|
15
|
-
import { partialUsers, user, userId, userIds } from '../open-api/oa-examples/user.oa-example.mjs';
|
|
16
|
+
import { partialUsers, user, authenticationTokens, userId, userIds } from '../open-api/oa-examples/user.oa-example.mjs';
|
|
17
|
+
import { RestApi } from '../rest-api/rest-api.mjs';
|
|
18
|
+
import { limitAndFilterArray } from '../helpers/utils.helper.mjs';
|
|
19
|
+
import { UserService } from './user.service.mjs';
|
|
16
20
|
import { XoController } from '../abstract-classes/xo-controller.mjs';
|
|
21
|
+
import { groupIds, partialGroups } from '../open-api/oa-examples/group.oa-example.mjs';
|
|
17
22
|
let UserController = class UserController extends XoController {
|
|
23
|
+
#userService;
|
|
24
|
+
constructor(restApi, userService) {
|
|
25
|
+
super(restApi);
|
|
26
|
+
this.#userService = userService;
|
|
27
|
+
}
|
|
18
28
|
// --- abstract methods
|
|
19
29
|
async getAllCollectionObjects() {
|
|
20
|
-
|
|
21
|
-
return users.map(user => this.#sanitizeUser(user));
|
|
30
|
+
return this.#userService.getUsers();
|
|
22
31
|
}
|
|
23
32
|
async getCollectionObject(id) {
|
|
24
|
-
|
|
25
|
-
return this.#sanitizeUser(user);
|
|
33
|
+
return this.#userService.getUser(id);
|
|
26
34
|
}
|
|
27
|
-
#
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
return sanitizedUser;
|
|
35
|
+
#redirectCurrentUser(req) {
|
|
36
|
+
const currentUser = this.restApi.getCurrentUser();
|
|
37
|
+
const originalUrl = req.originalUrl;
|
|
38
|
+
const res = req.res;
|
|
39
|
+
res.redirect(307, originalUrl.replace(/\/users\/me(?=\/|$)/, `/users/${currentUser.id}`));
|
|
33
40
|
}
|
|
34
41
|
/**
|
|
35
42
|
* @example fields "permission,name,id"
|
|
@@ -40,6 +47,18 @@ let UserController = class UserController extends XoController {
|
|
|
40
47
|
const users = Object.values(await this.getObjects({ filter, limit }));
|
|
41
48
|
return this.sendObjects(users, req);
|
|
42
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Redirect to `/users/:id`
|
|
52
|
+
*/
|
|
53
|
+
redirectMe(req) {
|
|
54
|
+
this.#redirectCurrentUser(req);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Redirect to `/users/:id/<rest-of-your-path>`
|
|
58
|
+
*/
|
|
59
|
+
redirectMeWithPath(req) {
|
|
60
|
+
this.#redirectCurrentUser(req);
|
|
61
|
+
}
|
|
43
62
|
/**
|
|
44
63
|
* @example id "722d17b9-699b-49d2-8193-be1ac573d3de"
|
|
45
64
|
*/
|
|
@@ -87,6 +106,31 @@ let UserController = class UserController extends XoController {
|
|
|
87
106
|
async deleteUser(id) {
|
|
88
107
|
await this.restApi.xoApp.deleteUser(id);
|
|
89
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* @example id "722d17b9-699b-49d2-8193-be1ac573d3de"
|
|
111
|
+
* @example fields "name,id,users"
|
|
112
|
+
* @example filter "users:length:>0"
|
|
113
|
+
* @example limit 42
|
|
114
|
+
*/
|
|
115
|
+
async getUserGroups(req, id, fields, ndjson, filter, limit) {
|
|
116
|
+
const user = await this.getObject(id);
|
|
117
|
+
const groups = await Promise.all(user.groups.map(group => this.restApi.xoApp.getGroup(group)));
|
|
118
|
+
return this.sendObjects(limitAndFilterArray(groups, { filter, limit }), req, 'groups');
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* @example id "722d17b9-699b-49d2-8193-be1ac573d3de"
|
|
122
|
+
* @example filter "expiration:>1757371582496"
|
|
123
|
+
* @example limit 42
|
|
124
|
+
*/
|
|
125
|
+
async getAuthenticationTokens(req, id, filter, limit) {
|
|
126
|
+
const user = await this.getObject(id);
|
|
127
|
+
const me = this.restApi.getCurrentUser();
|
|
128
|
+
if (me.id !== user.id) {
|
|
129
|
+
throw forbiddenOperation('get authentication tokens', 'can only see own authentication tokens');
|
|
130
|
+
}
|
|
131
|
+
const tokens = await this.restApi.xoApp.getAuthenticationTokensForUser(user.id);
|
|
132
|
+
return limitAndFilterArray(tokens, { filter, limit });
|
|
133
|
+
}
|
|
90
134
|
};
|
|
91
135
|
__decorate([
|
|
92
136
|
Example(userIds),
|
|
@@ -98,6 +142,16 @@ __decorate([
|
|
|
98
142
|
__param(3, Query()),
|
|
99
143
|
__param(4, Query())
|
|
100
144
|
], UserController.prototype, "getUsers", null);
|
|
145
|
+
__decorate([
|
|
146
|
+
SuccessResponse(307, 'Temporary redirect'),
|
|
147
|
+
Get('me'),
|
|
148
|
+
__param(0, Request())
|
|
149
|
+
], UserController.prototype, "redirectMe", null);
|
|
150
|
+
__decorate([
|
|
151
|
+
SuccessResponse(307, 'Temporary redirect'),
|
|
152
|
+
Get('me/*'),
|
|
153
|
+
__param(0, Request())
|
|
154
|
+
], UserController.prototype, "redirectMeWithPath", null);
|
|
101
155
|
__decorate([
|
|
102
156
|
Example(user),
|
|
103
157
|
Get('{id}'),
|
|
@@ -129,11 +183,36 @@ __decorate([
|
|
|
129
183
|
Response(notFoundResp.status, notFoundResp.description),
|
|
130
184
|
__param(0, Path())
|
|
131
185
|
], UserController.prototype, "deleteUser", null);
|
|
186
|
+
__decorate([
|
|
187
|
+
Example(groupIds),
|
|
188
|
+
Example(partialGroups),
|
|
189
|
+
Get('{id}/groups'),
|
|
190
|
+
Tags('groups'),
|
|
191
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
192
|
+
__param(0, Request()),
|
|
193
|
+
__param(1, Path()),
|
|
194
|
+
__param(2, Query()),
|
|
195
|
+
__param(3, Query()),
|
|
196
|
+
__param(4, Query()),
|
|
197
|
+
__param(5, Query())
|
|
198
|
+
], UserController.prototype, "getUserGroups", null);
|
|
199
|
+
__decorate([
|
|
200
|
+
Example(authenticationTokens),
|
|
201
|
+
Get('{id}/authentication_tokens'),
|
|
202
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
203
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
204
|
+
__param(0, Request()),
|
|
205
|
+
__param(1, Path()),
|
|
206
|
+
__param(2, Query()),
|
|
207
|
+
__param(3, Query())
|
|
208
|
+
], UserController.prototype, "getAuthenticationTokens", null);
|
|
132
209
|
UserController = __decorate([
|
|
133
210
|
Route('users'),
|
|
134
211
|
Security('*'),
|
|
135
212
|
Response(unauthorizedResp.status, unauthorizedResp.description),
|
|
136
213
|
Tags('users'),
|
|
137
|
-
provide(UserController)
|
|
214
|
+
provide(UserController),
|
|
215
|
+
__param(0, inject(RestApi)),
|
|
216
|
+
__param(1, inject(UserService))
|
|
138
217
|
], UserController);
|
|
139
218
|
export { UserController };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export class UserService {
|
|
2
|
+
#restApi;
|
|
3
|
+
constructor(restApi) {
|
|
4
|
+
this.#restApi = restApi;
|
|
5
|
+
}
|
|
6
|
+
#sanitizeUser(user) {
|
|
7
|
+
const sanitizedUser = { ...user };
|
|
8
|
+
if (sanitizedUser.pw_hash !== undefined) {
|
|
9
|
+
sanitizedUser.pw_hash = '***obfuscated***';
|
|
10
|
+
}
|
|
11
|
+
return sanitizedUser;
|
|
12
|
+
}
|
|
13
|
+
async getUser(id) {
|
|
14
|
+
const user = await this.#restApi.xoApp.getUser(id);
|
|
15
|
+
return this.#sanitizeUser(user);
|
|
16
|
+
}
|
|
17
|
+
async getUsers() {
|
|
18
|
+
const users = await this.#restApi.xoApp.getAllUsers();
|
|
19
|
+
return users.map(user => this.#sanitizeUser(user));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -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 { escapeUnsafeComplexMatcher } from '../helpers/utils.helper.mjs';
|
|
14
|
-
import { notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
|
|
14
|
+
import { noContentResp, notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
|
|
15
15
|
import { RestApi } from '../rest-api/rest-api.mjs';
|
|
16
16
|
import { partialVdiSnapshots, vdiSnapshot, vdiSnapshotIds } from '../open-api/oa-examples/vdi-snapshot.oa-example.mjs';
|
|
17
17
|
import { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs';
|
|
18
18
|
import { genericAlarmsExample } from '../open-api/oa-examples/alarm.oa-example.mjs';
|
|
19
19
|
import { AlarmService } from '../alarms/alarm.service.mjs';
|
|
20
|
+
import { VdiService } from '../vdis/vdi.service.mjs';
|
|
20
21
|
let VdiSnapshotController = class VdiSnapshotController extends XapiXoController {
|
|
21
22
|
#alarmService;
|
|
22
|
-
|
|
23
|
+
#vdiService;
|
|
24
|
+
constructor(restApi, alarmService, vdiService) {
|
|
23
25
|
super('VDI-snapshot', restApi);
|
|
24
26
|
this.#alarmService = alarmService;
|
|
27
|
+
this.#vdiService = vdiService;
|
|
25
28
|
}
|
|
26
29
|
/**
|
|
27
30
|
* @example fields "uuid,snapshot_time,$snapshot_of"
|
|
@@ -31,6 +34,22 @@ let VdiSnapshotController = class VdiSnapshotController extends XapiXoController
|
|
|
31
34
|
getVdiSnapshots(req, fields, ndjson, filter, limit) {
|
|
32
35
|
return this.sendObjects(Object.values(this.getObjects({ filter, limit })), req);
|
|
33
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
*
|
|
39
|
+
* Export VDI-snapshot content
|
|
40
|
+
*
|
|
41
|
+
* @example id "d2727772-735b-478f-b6f9-11e7db56dfd0"
|
|
42
|
+
*/
|
|
43
|
+
async exportVdiSnapshotContent(req, id, format) {
|
|
44
|
+
const res = req.res;
|
|
45
|
+
const stream = await this.#vdiService.exportContent(id, 'VDI-snapshot', {
|
|
46
|
+
format,
|
|
47
|
+
response: res,
|
|
48
|
+
});
|
|
49
|
+
process.on('SIGTERM', () => req.destroy());
|
|
50
|
+
req.on('close', () => stream.destroy());
|
|
51
|
+
return stream;
|
|
52
|
+
}
|
|
34
53
|
/**
|
|
35
54
|
* @example id "d2727772-735b-478f-b6f9-11e7db56dfd0"
|
|
36
55
|
*/
|
|
@@ -51,6 +70,13 @@ let VdiSnapshotController = class VdiSnapshotController extends XapiXoController
|
|
|
51
70
|
});
|
|
52
71
|
return this.sendObjects(Object.values(alarms), req, 'alarms');
|
|
53
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* @example id "d2727772-735b-478f-b6f9-11e7db56dfd0"
|
|
75
|
+
*/
|
|
76
|
+
async deleteVdiSnapshot(id) {
|
|
77
|
+
const xapiVdiSnapshot = this.getXapiObject(id);
|
|
78
|
+
await xapiVdiSnapshot.$xapi.VDI_destroy(xapiVdiSnapshot.$ref);
|
|
79
|
+
}
|
|
54
80
|
};
|
|
55
81
|
__decorate([
|
|
56
82
|
Example(vdiSnapshotIds),
|
|
@@ -62,6 +88,15 @@ __decorate([
|
|
|
62
88
|
__param(3, Query()),
|
|
63
89
|
__param(4, Query())
|
|
64
90
|
], VdiSnapshotController.prototype, "getVdiSnapshots", null);
|
|
91
|
+
__decorate([
|
|
92
|
+
Get('{id}.{format}'),
|
|
93
|
+
SuccessResponse(200, 'Download started', 'application/octet-stream'),
|
|
94
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
95
|
+
Response(422, 'Invalid format'),
|
|
96
|
+
__param(0, Request()),
|
|
97
|
+
__param(1, Path()),
|
|
98
|
+
__param(2, Path())
|
|
99
|
+
], VdiSnapshotController.prototype, "exportVdiSnapshotContent", null);
|
|
65
100
|
__decorate([
|
|
66
101
|
Example(vdiSnapshot),
|
|
67
102
|
Get('{id}'),
|
|
@@ -80,6 +115,12 @@ __decorate([
|
|
|
80
115
|
__param(4, Query()),
|
|
81
116
|
__param(5, Query())
|
|
82
117
|
], VdiSnapshotController.prototype, "getVdiSnapshotAlarms", null);
|
|
118
|
+
__decorate([
|
|
119
|
+
Delete('{id}'),
|
|
120
|
+
SuccessResponse(noContentResp.status, noContentResp.description),
|
|
121
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
122
|
+
__param(0, Path())
|
|
123
|
+
], VdiSnapshotController.prototype, "deleteVdiSnapshot", null);
|
|
83
124
|
VdiSnapshotController = __decorate([
|
|
84
125
|
Route('vdi-snapshots'),
|
|
85
126
|
Security('*'),
|
|
@@ -87,6 +128,7 @@ VdiSnapshotController = __decorate([
|
|
|
87
128
|
Tags('vdis'),
|
|
88
129
|
provide(VdiSnapshotController),
|
|
89
130
|
__param(0, inject(RestApi)),
|
|
90
|
-
__param(1, inject(AlarmService))
|
|
131
|
+
__param(1, inject(AlarmService)),
|
|
132
|
+
__param(2, inject(VdiService))
|
|
91
133
|
], VdiSnapshotController);
|
|
92
134
|
export { VdiSnapshotController };
|
|
@@ -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'),
|