@xen-orchestra/rest-api 0.24.1 → 0.26.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.
@@ -8,11 +8,16 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
8
  return function (target, key) { decorator(target, key, paramIndex); }
9
9
  };
10
10
  import { Example, Get, Path, Query, Request, Response, Route, Security, Tags } from 'tsoa';
11
+ import { inject } from 'inversify';
11
12
  import { provide } from 'inversify-binding-decorators';
12
13
  import { badRequestResp, notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
13
14
  import { partialProxies, proxy, proxyIds } from '../open-api/oa-examples/proxy.oa-example.mjs';
14
15
  import { XoController } from '../abstract-classes/xo-controller.mjs';
16
+ import { RestApi } from '../rest-api/rest-api.mjs';
15
17
  let ProxyController = class ProxyController extends XoController {
18
+ constructor(restApi) {
19
+ super('proxy', restApi);
20
+ }
16
21
  getAllCollectionObjects() {
17
22
  return this.restApi.xoApp.getAllProxies();
18
23
  }
@@ -57,6 +62,7 @@ ProxyController = __decorate([
57
62
  Response(badRequestResp.status, badRequestResp.description),
58
63
  Response(unauthorizedResp.status, unauthorizedResp.description),
59
64
  Tags('proxies'),
60
- provide(ProxyController)
65
+ provide(ProxyController),
66
+ __param(0, inject(RestApi))
61
67
  ], ProxyController);
62
68
  export { ProxyController };
@@ -21,7 +21,7 @@ const log = createLogger('xo:rest-api:restoreLog-controller');
21
21
  let RestoreLogController = class RestoreLogController extends XoController {
22
22
  #backupLogService;
23
23
  constructor(restApi, backupLogService) {
24
- super(restApi);
24
+ super('restore-log', restApi);
25
25
  this.#backupLogService = backupLogService;
26
26
  }
27
27
  getAllCollectionObjects() {
@@ -81,7 +81,7 @@ export { RestoreLogController };
81
81
  let DeprecatedRestoreController = class DeprecatedRestoreController extends XoController {
82
82
  #backupLogService;
83
83
  constructor(restApi, backupLogService) {
84
- super(restApi);
84
+ super('restore', restApi);
85
85
  this.#backupLogService = backupLogService;
86
86
  }
87
87
  getAllCollectionObjects() {
@@ -8,12 +8,17 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
8
  return function (target, key) { decorator(target, key, paramIndex); }
9
9
  };
10
10
  import { Example, Get, Path, Post, Query, Request, Response, Route, Security, SuccessResponse, Tags } from 'tsoa';
11
+ import { inject } from 'inversify';
11
12
  import { provide } from 'inversify-binding-decorators';
12
13
  import { asynchronousActionResp, badRequestResp, featureUnauthorized, internalServerErrorResp, noContentResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
13
14
  import { partialSchedules, schedule, scheduleIds } from '../open-api/oa-examples/schedule.oa-example.mjs';
14
15
  import { taskLocation } from '../open-api/oa-examples/task.oa-example.mjs';
15
16
  import { XoController } from '../abstract-classes/xo-controller.mjs';
17
+ import { RestApi } from '../rest-api/rest-api.mjs';
16
18
  let ScheduleController = class ScheduleController extends XoController {
19
+ constructor(restApi) {
20
+ super('schedule', restApi);
21
+ }
17
22
  // --- abstract methods
18
23
  getAllCollectionObjects() {
19
24
  return this.restApi.xoApp.getAllSchedules();
@@ -86,6 +91,7 @@ ScheduleController = __decorate([
86
91
  Response(badRequestResp.status, badRequestResp.description),
87
92
  Response(unauthorizedResp.status, unauthorizedResp.description),
88
93
  Tags('schedules'),
89
- provide(ScheduleController)
94
+ provide(ScheduleController),
95
+ __param(0, inject(RestApi))
90
96
  ], ScheduleController);
91
97
  export { ScheduleController };
@@ -9,12 +9,17 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
9
9
  };
10
10
  import { Body, Delete, Example, Get, Middlewares, Path, Post, Query, Request, Response, Route, Security, SuccessResponse, Tags, } from 'tsoa';
11
11
  import { json } from 'express';
12
+ import { inject } from 'inversify';
12
13
  import { provide } from 'inversify-binding-decorators';
13
14
  import { asynchronousActionResp, badRequestResp, createdResp, invalidParameters, noContentResp, notFoundResp, resourceAlreadyExists, unauthorizedResp, } from '../open-api/common/response.common.mjs';
14
15
  import { partialServers, server, serverId, serverIds } from '../open-api/oa-examples/server.oa-example.mjs';
15
16
  import { partialTasks, taskIds, taskLocation } from '../open-api/oa-examples/task.oa-example.mjs';
16
17
  import { XoController } from '../abstract-classes/xo-controller.mjs';
18
+ import { RestApi } from '../rest-api/rest-api.mjs';
17
19
  let ServerController = class ServerController extends XoController {
20
+ constructor(restApi) {
21
+ super('server', restApi);
22
+ }
18
23
  // --- abstract methods
19
24
  getAllCollectionObjects() {
20
25
  return this.restApi.xoApp.getAllXenServers();
@@ -164,6 +169,7 @@ ServerController = __decorate([
164
169
  Response(badRequestResp.status, badRequestResp.description),
165
170
  Response(unauthorizedResp.status, unauthorizedResp.description),
166
171
  Tags('servers'),
167
- provide(ServerController)
172
+ provide(ServerController),
173
+ __param(0, inject(RestApi))
168
174
  ], ServerController);
169
175
  export { ServerController };
@@ -15,13 +15,13 @@ import { AlarmService } from '../alarms/alarm.service.mjs';
15
15
  import { BASE_URL } from '../index.mjs';
16
16
  import { escapeUnsafeComplexMatcher } from '../helpers/utils.helper.mjs';
17
17
  import { genericAlarmsExample } from '../open-api/oa-examples/alarm.oa-example.mjs';
18
- import { badRequestResp, createdResp, noContentResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
18
+ import { asynchronousActionResp, badRequestResp, createdResp, internalServerErrorResp, invalidParameters as invalidParametersResp, noContentResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
19
19
  import { partialSrs, sr, srIds } from '../open-api/oa-examples/sr.oa-example.mjs';
20
20
  import { vdiId } from '../open-api/oa-examples/vdi.oa-example.mjs';
21
21
  import { RestApi } from '../rest-api/rest-api.mjs';
22
22
  import { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs';
23
23
  import { messageIds, partialMessages } from '../open-api/oa-examples/message.oa-example.mjs';
24
- import { taskIds, partialTasks } from '../open-api/oa-examples/task.oa-example.mjs';
24
+ import { taskIds, partialTasks, taskLocation } from '../open-api/oa-examples/task.oa-example.mjs';
25
25
  let SrController = class SrController extends XapiXoController {
26
26
  #alarmService;
27
27
  constructor(restApi, alarmService) {
@@ -114,6 +114,42 @@ let SrController = class SrController extends XapiXoController {
114
114
  const sr = this.getXapiObject(id);
115
115
  await sr.$call('remove_tags', tag);
116
116
  }
117
+ /**
118
+ * @example id "b61a5c92-700e-4966-a13b-00633f03eea8"
119
+ */
120
+ async reclaimSpaceSr(id, sync) {
121
+ const srId = id;
122
+ const action = async () => {
123
+ const sr = this.getXapiObject(srId);
124
+ await sr.$xapi.SR_reclaimSpace(sr.$ref);
125
+ };
126
+ return this.createAction(action, {
127
+ sync,
128
+ statusCode: noContentResp.status,
129
+ taskProperties: {
130
+ name: 'SR reclaim space',
131
+ objectId: srId,
132
+ },
133
+ });
134
+ }
135
+ /**
136
+ * @example id "b61a5c92-700e-4966-a13b-00633f03eea8"
137
+ */
138
+ async scanSr(id, sync) {
139
+ const srId = id;
140
+ const action = async () => {
141
+ const sr = this.getXapiObject(srId);
142
+ await sr.$xapi.callAsync('SR.scan', sr.$ref);
143
+ };
144
+ return this.createAction(action, {
145
+ sync,
146
+ statusCode: noContentResp.status,
147
+ taskProperties: {
148
+ name: 'SR scan',
149
+ objectId: srId,
150
+ },
151
+ });
152
+ }
117
153
  };
118
154
  __decorate([
119
155
  Example(srIds),
@@ -195,6 +231,28 @@ __decorate([
195
231
  __param(0, Path()),
196
232
  __param(1, Path())
197
233
  ], SrController.prototype, "deleteSrTag", null);
234
+ __decorate([
235
+ Example(taskLocation),
236
+ Post('{id}/actions/reclaim_space'),
237
+ SuccessResponse(asynchronousActionResp.status, asynchronousActionResp.description),
238
+ Response(noContentResp.status, noContentResp.description),
239
+ Response(notFoundResp.status, notFoundResp.description),
240
+ Response(invalidParametersResp.status, invalidParametersResp.description),
241
+ Response(internalServerErrorResp.status, internalServerErrorResp.description),
242
+ __param(0, Path()),
243
+ __param(1, Query())
244
+ ], SrController.prototype, "reclaimSpaceSr", null);
245
+ __decorate([
246
+ Example(taskLocation),
247
+ Post('{id}/actions/scan'),
248
+ SuccessResponse(asynchronousActionResp.status, asynchronousActionResp.description),
249
+ Response(noContentResp.status, noContentResp.description),
250
+ Response(notFoundResp.status, notFoundResp.description),
251
+ Response(invalidParametersResp.status, invalidParametersResp.description),
252
+ Response(internalServerErrorResp.status, internalServerErrorResp.description),
253
+ __param(0, Path()),
254
+ __param(1, Query())
255
+ ], SrController.prototype, "scanSr", null);
198
256
  SrController = __decorate([
199
257
  Route('srs'),
200
258
  Security('*'),
@@ -10,6 +10,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
10
10
  import { XoController } from '../abstract-classes/xo-controller.mjs';
11
11
  import { Get, Path, Query, Request, Route, Security, Tags, Response, Example, Delete, Post, SuccessResponse, } from 'tsoa';
12
12
  import { asynchronousActionResp, badRequestResp, noContentResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
13
+ import { inject } from 'inversify';
13
14
  import { provide } from 'inversify-binding-decorators';
14
15
  import { partialTasks, task, taskIds, taskLocation } from '../open-api/oa-examples/task.oa-example.mjs';
15
16
  import pDefer from 'promise-toolbox/defer';
@@ -17,7 +18,11 @@ import { ApiError } from '../helpers/error.helper.mjs';
17
18
  import { Transform } from 'node:stream';
18
19
  import { makeObjectMapper } from '../helpers/object-wrapper.helper.mjs';
19
20
  import { safeParseComplexMatcher } from '../helpers/utils.helper.mjs';
21
+ import { RestApi } from '../rest-api/rest-api.mjs';
20
22
  let TaskController = class TaskController extends XoController {
23
+ constructor(restApi) {
24
+ super('task', restApi);
25
+ }
21
26
  async getAllCollectionObjects() {
22
27
  const result = [];
23
28
  for await (const task of this.restApi.tasks.list()) {
@@ -163,6 +168,7 @@ TaskController = __decorate([
163
168
  Response(badRequestResp.status, badRequestResp.description),
164
169
  Response(unauthorizedResp.status, unauthorizedResp.description),
165
170
  Tags('tasks'),
166
- provide(TaskController)
171
+ provide(TaskController),
172
+ __param(0, inject(RestApi))
167
173
  ], TaskController);
168
174
  export { TaskController };
@@ -26,7 +26,7 @@ const log = createLogger('xo:rest-api:user-controller');
26
26
  let UserController = class UserController extends XoController {
27
27
  #userService;
28
28
  constructor(restApi, userService) {
29
- super(restApi);
29
+ super('user', restApi);
30
30
  this.#userService = userService;
31
31
  }
32
32
  // --- abstract methods
@@ -14,7 +14,8 @@ import { json } from 'express';
14
14
  import { AlarmService } from '../alarms/alarm.service.mjs';
15
15
  import { escapeUnsafeComplexMatcher } from '../helpers/utils.helper.mjs';
16
16
  import { genericAlarmsExample } from '../open-api/oa-examples/alarm.oa-example.mjs';
17
- import { asynchronousActionResp, badRequestResp, internalServerErrorResp, noContentResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
17
+ import { asynchronousActionResp, badRequestResp, createdResp, internalServerErrorResp, noContentResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
18
+ import { BASE_URL } from '../index.mjs';
18
19
  import { RestApi } from '../rest-api/rest-api.mjs';
19
20
  import { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs';
20
21
  import { partialVdis, vdi, vdiId, vdiIds } from '../open-api/oa-examples/vdi.oa-example.mjs';
@@ -84,6 +85,25 @@ let VdiController = class VdiController extends XapiXoController {
84
85
  });
85
86
  return this.sendObjects(Object.values(alarms), req, 'alarms');
86
87
  }
88
+ /**
89
+ * Create an empty VDI on the given SR.
90
+ *
91
+ * @example body { "srId": "c4284e12-37c9-7967-b9e8-83ef229c3e03", "virtual_size": 10737418240, "name_label": "test VDI" }
92
+ */
93
+ async createVdi(body) {
94
+ const { srId, sm_config, ...rest } = body;
95
+ const xapiSr = this.restApi.getXapiObject(srId, 'SR');
96
+ const xapi = xapiSr.$xapi;
97
+ const vdiRef = await xapi.VDI_create({
98
+ ...rest,
99
+ SR: xapiSr.$ref,
100
+ }, {
101
+ sm_config,
102
+ });
103
+ const vdiUuid = await xapi.call('VDI.get_uuid', vdiRef);
104
+ this.setHeader('Location', `${BASE_URL}/vdis/${vdiUuid}`);
105
+ return { id: vdiUuid };
106
+ }
87
107
  /**
88
108
  * @example id "c77f9955-c1d2-4b39-aa1c-73cdb2dacb7e"
89
109
  */
@@ -196,6 +216,15 @@ __decorate([
196
216
  __param(4, Query()),
197
217
  __param(5, Query())
198
218
  ], VdiController.prototype, "getVdiAlarms", null);
219
+ __decorate([
220
+ Example(vdiId),
221
+ Post(''),
222
+ Middlewares(json()),
223
+ SuccessResponse(createdResp.status, createdResp.description),
224
+ Response(notFoundResp.status, notFoundResp.description),
225
+ Response(internalServerErrorResp.status, internalServerErrorResp.description),
226
+ __param(0, Body())
227
+ ], VdiController.prototype, "createVdi", null);
199
228
  __decorate([
200
229
  Delete('{id}'),
201
230
  SuccessResponse(noContentResp.status, noContentResp.description),
@@ -13,7 +13,7 @@ import { inject } from 'inversify';
13
13
  import { incorrectState, invalidParameters } from 'xo-common/api-errors.js';
14
14
  import { provide } from 'inversify-binding-decorators';
15
15
  import { PassThrough } from 'node:stream';
16
- import { asynchronousActionResp, badRequestResp, createdResp, forbiddenOperationResp, incorrectStateResp, internalServerErrorResp, noContentResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
16
+ import { asynchronousActionResp, badRequestResp, createdResp, forbiddenOperationResp, incorrectStateResp, internalServerErrorResp, invalidParameters as invalidParametersResp, noContentResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
17
17
  import { BASE_URL } from '../index.mjs';
18
18
  import { limitAndFilterArray, NDJSON_CONTENT_TYPE } from '../helpers/utils.helper.mjs';
19
19
  import { genericAlarmsExample } from '../open-api/oa-examples/alarm.oa-example.mjs';
@@ -419,6 +419,33 @@ let VmController = class VmController extends XapiXoController {
419
419
  stream?.end();
420
420
  }
421
421
  }
422
+ /**
423
+ * VIF mapping is not allowed for intra-pool migration
424
+ *
425
+ * Networks and SRs must belong to the same pool as the destination host
426
+ *
427
+ * @example id "613f541c-4bed-fc77-7ca8-2db6b68f079c"
428
+ * @example body { "hostId": "b61a5c92-700e-4966-a13b-00633f03eea8" }
429
+ */
430
+ migrateVm(id, body, sync) {
431
+ const vmId = id;
432
+ const hostId = body.hostId;
433
+ const action = async () => {
434
+ const { migrationNetworkId } = body;
435
+ const xapiVm = this.getXapiObject(vmId);
436
+ await xapiVm.$xapi.migrateVm(vmId, this.getXapi(hostId), hostId, {
437
+ mapVdisSrs: 'srIdByVdiId' in body ? body.srIdByVdiId : undefined,
438
+ mapVifsNetworks: 'networkIdByVifId' in body ? body.networkIdByVifId : undefined,
439
+ migrationNetworkId: migrationNetworkId,
440
+ sr: 'srId' in body ? body.srId : undefined,
441
+ });
442
+ };
443
+ return this.createAction(action, {
444
+ sync,
445
+ statusCode: 204,
446
+ taskProperties: { name: 'Migrate VM', objectId: vmId, params: body },
447
+ });
448
+ }
422
449
  };
423
450
  __decorate([
424
451
  Example(vmIds),
@@ -661,6 +688,19 @@ __decorate([
661
688
  __param(1, Path()),
662
689
  __param(2, Query())
663
690
  ], VmController.prototype, "getVmDashboard", null);
691
+ __decorate([
692
+ Example(taskLocation),
693
+ Post('{id}/actions/migrate'),
694
+ Middlewares(json()),
695
+ SuccessResponse(asynchronousActionResp.status, asynchronousActionResp.description),
696
+ Response(noContentResp.status, noContentResp.description),
697
+ Response(notFoundResp.status, notFoundResp.description),
698
+ Response(invalidParametersResp.status, invalidParametersResp.description),
699
+ Response(internalServerErrorResp.status, internalServerErrorResp.description),
700
+ __param(0, Path()),
701
+ __param(1, Body()),
702
+ __param(2, Query())
703
+ ], VmController.prototype, "migrateVm", null);
664
704
  VmController = __decorate([
665
705
  Route('vms'),
666
706
  Security('*'),