@xen-orchestra/rest-api 0.6.0 → 0.7.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/README.md CHANGED
@@ -48,6 +48,7 @@ class Foo extends Controller {
48
48
  @Example(['foo', 'bar'])
49
49
  @Get('{id}')
50
50
  @Security('*')
51
+ @Middlewares(json())
51
52
  @SuccessResponse(202)
52
53
  @Response(404)
53
54
  getFoo(@Path() id: string) {
@@ -1,5 +1,5 @@
1
1
  import { createLogger } from '@xen-orchestra/log';
2
- import { featureUnauthorized, forbiddenOperation, invalidCredentials, invalidParameters, noSuchObject, notImplemented, unauthorized, } from 'xo-common/api-errors.js';
2
+ import { featureUnauthorized, forbiddenOperation, incorrectState, invalidCredentials, invalidParameters, noSuchObject, notImplemented, objectAlreadyExists, unauthorized, } from 'xo-common/api-errors.js';
3
3
  const log = createLogger('xo:rest-api:error-handler');
4
4
  // must have 4 parameters to be recognized as an error middleware by express
5
5
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -19,12 +19,19 @@ export default function genericErrorHandler(error, req, res, _next) {
19
19
  else if (invalidCredentials.is(error)) {
20
20
  res.status(401);
21
21
  }
22
+ else if (objectAlreadyExists.is(error)) {
23
+ res.status(409);
24
+ }
22
25
  else if (invalidParameters.is(error)) {
23
26
  res.status(422);
24
27
  }
25
28
  else if (notImplemented.is(error)) {
26
29
  res.status(501);
27
30
  }
31
+ else if (incorrectState.is(error)) {
32
+ res.status(409);
33
+ responseError.data = error.data;
34
+ }
28
35
  else {
29
36
  if (error.name === 'XapiError') {
30
37
  responseError.info = 'This is a XenServer/XCP-ng error, not an XO error';
@@ -10,10 +10,10 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
10
10
  import { Example, Get, Path, Query, Response, Request, Route, Security, Tags } from 'tsoa';
11
11
  import { inject } from 'inversify';
12
12
  import { provide } from 'inversify-binding-decorators';
13
- import { network, networkIds, partialNetworks } from '../oa-examples/network.oa-example.mjs';
14
- import { notFoundResp, unauthorizedResp } from '../common/response.common.mjs';
15
- import { RestApi } from '../../rest-api/rest-api.mjs';
16
- import { XapiXoController } from '../../abstract-classes/xapi-xo-controller.mjs';
13
+ import { network, networkIds, partialNetworks } from '../open-api/oa-examples/network.oa-example.mjs';
14
+ import { notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
15
+ import { RestApi } from '../rest-api/rest-api.mjs';
16
+ import { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs';
17
17
  let NetworkController = class NetworkController extends XapiXoController {
18
18
  constructor(restApi) {
19
19
  super('network', restApi);
@@ -1,3 +1,7 @@
1
+ export const createdResp = {
2
+ status: 201,
3
+ description: 'Resource created',
4
+ };
1
5
  export const actionAsyncroneResp = {
2
6
  status: 202,
3
7
  description: 'Action executed asynchronously',
@@ -23,3 +27,11 @@ export const internalServerErrorResp = {
23
27
  status: 500,
24
28
  description: 'Internal server error, XenServer/XCP-ng error',
25
29
  };
30
+ export const resourceAlreadyExists = {
31
+ status: 409,
32
+ description: 'Resource already exists',
33
+ };
34
+ export const invalidParameters = {
35
+ status: 422,
36
+ description: 'Invalid parameters',
37
+ };
@@ -1,3 +1,4 @@
1
+ export const serverId = { id: '38068475-3a1d-4a64-95df-8782cdea02ac' };
1
2
  export const serverIds = [
2
3
  '/rest/v0/servers/f07ab729-c0e8-721c-45ec-f11276377030',
3
4
  '/rest/v0/servers/d5d1c4a3-4c5e-ca7b-6be8-33c824f87571',
@@ -26,7 +26,7 @@ import { ScheduleController } from './../../schedules/schedule.controller.mjs';
26
26
  // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
27
27
  import { PoolController } from './../../pools/pool.controller.mjs';
28
28
  // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
29
- import { NetworkController } from './../networks/network.controller.mjs';
29
+ import { NetworkController } from './../../networks/network.controller.mjs';
30
30
  // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
31
31
  import { AlarmController } from './../../alarms/alarm.controller.mjs';
32
32
  // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
@@ -281,6 +281,20 @@ const models = {
281
281
  "type": { "dataType": "nestedObjectLiteral", "nestedProperties": { "allowUnauthorized": { "dataType": "boolean", "required": true }, "enabled": { "dataType": "boolean", "required": true }, "error": { "dataType": "union", "subSchemas": [{ "ref": "Record_string.unknown_" }, { "dataType": "undefined" }] }, "host": { "dataType": "string", "required": true }, "httpProxy": { "dataType": "union", "subSchemas": [{ "dataType": "string" }, { "dataType": "undefined" }] }, "id": { "dataType": "string", "required": true }, "label": { "dataType": "union", "subSchemas": [{ "dataType": "string" }, { "dataType": "undefined" }] }, "poolId": { "dataType": "union", "subSchemas": [{ "dataType": "string" }, { "dataType": "undefined" }] }, "poolNameDescription": { "dataType": "union", "subSchemas": [{ "dataType": "string" }, { "dataType": "undefined" }] }, "poolNameLabel": { "dataType": "union", "subSchemas": [{ "dataType": "string" }, { "dataType": "undefined" }] }, "readOnly": { "dataType": "boolean", "required": true }, "status": { "dataType": "union", "subSchemas": [{ "dataType": "enum", "enums": ["connected"] }, { "dataType": "enum", "enums": ["disconnected"] }, { "dataType": "enum", "enums": ["connecting"] }], "required": true }, "username": { "dataType": "string", "required": true } }, "validators": {} },
282
282
  },
283
283
  // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
284
+ "InsertableXoServer": {
285
+ "dataType": "refObject",
286
+ "properties": {
287
+ "host": { "dataType": "string", "required": true },
288
+ "httpProxy": { "dataType": "union", "subSchemas": [{ "dataType": "string" }, { "dataType": "undefined" }] },
289
+ "label": { "dataType": "union", "subSchemas": [{ "dataType": "string" }, { "dataType": "undefined" }] },
290
+ "username": { "dataType": "string", "required": true },
291
+ "allowUnauthorized": { "dataType": "boolean" },
292
+ "password": { "dataType": "string", "required": true },
293
+ "readOnly": { "dataType": "boolean" },
294
+ },
295
+ "additionalProperties": false,
296
+ },
297
+ // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
284
298
  "Partial_Unbrand_XoSchedule__": {
285
299
  "dataType": "refAlias",
286
300
  "type": { "dataType": "nestedObjectLiteral", "nestedProperties": { "cron": { "dataType": "union", "subSchemas": [{ "dataType": "string" }, { "dataType": "undefined" }] }, "enable": { "dataType": "union", "subSchemas": [{ "dataType": "boolean" }, { "dataType": "undefined" }] }, "id": { "dataType": "union", "subSchemas": [{ "dataType": "string" }, { "dataType": "undefined" }] }, "jobId": { "dataType": "union", "subSchemas": [{ "dataType": "string" }, { "dataType": "undefined" }] }, "name": { "dataType": "union", "subSchemas": [{ "dataType": "string" }, { "dataType": "undefined" }] }, "timezone": { "dataType": "union", "subSchemas": [{ "dataType": "string" }, { "dataType": "undefined" }] } }, "validators": {} },
@@ -557,6 +571,118 @@ export function RegisterRoutes(app) {
557
571
  }
558
572
  });
559
573
  // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
574
+ const argsVmController_cleanShutdownVm = {
575
+ id: { "in": "path", "name": "id", "required": true, "dataType": "string" },
576
+ sync: { "in": "query", "name": "sync", "dataType": "boolean" },
577
+ };
578
+ app.post('/rest/v0/vms/:id/actions/clean_shutdown', authenticateMiddleware([{ "*": [] }]), ...(fetchMiddlewares(VmController)), ...(fetchMiddlewares(VmController.prototype.cleanShutdownVm)), async function VmController_cleanShutdownVm(request, response, next) {
579
+ // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
580
+ let validatedArgs = [];
581
+ try {
582
+ validatedArgs = templateService.getValidatedArgs({ args: argsVmController_cleanShutdownVm, request, response });
583
+ const container = typeof iocContainer === 'function' ? iocContainer(request) : iocContainer;
584
+ const controller = await container.get(VmController);
585
+ if (typeof controller['setStatus'] === 'function') {
586
+ controller.setStatus(undefined);
587
+ }
588
+ await templateService.apiHandler({
589
+ methodName: 'cleanShutdownVm',
590
+ controller,
591
+ response,
592
+ next,
593
+ validatedArgs,
594
+ successStatus: 202,
595
+ });
596
+ }
597
+ catch (err) {
598
+ return next(err);
599
+ }
600
+ });
601
+ // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
602
+ const argsVmController_cleanRebootVm = {
603
+ id: { "in": "path", "name": "id", "required": true, "dataType": "string" },
604
+ sync: { "in": "query", "name": "sync", "dataType": "boolean" },
605
+ };
606
+ app.post('/rest/v0/vms/:id/actions/clean_reboot', authenticateMiddleware([{ "*": [] }]), ...(fetchMiddlewares(VmController)), ...(fetchMiddlewares(VmController.prototype.cleanRebootVm)), async function VmController_cleanRebootVm(request, response, next) {
607
+ // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
608
+ let validatedArgs = [];
609
+ try {
610
+ validatedArgs = templateService.getValidatedArgs({ args: argsVmController_cleanRebootVm, request, response });
611
+ const container = typeof iocContainer === 'function' ? iocContainer(request) : iocContainer;
612
+ const controller = await container.get(VmController);
613
+ if (typeof controller['setStatus'] === 'function') {
614
+ controller.setStatus(undefined);
615
+ }
616
+ await templateService.apiHandler({
617
+ methodName: 'cleanRebootVm',
618
+ controller,
619
+ response,
620
+ next,
621
+ validatedArgs,
622
+ successStatus: undefined,
623
+ });
624
+ }
625
+ catch (err) {
626
+ return next(err);
627
+ }
628
+ });
629
+ // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
630
+ const argsVmController_hardShutdownVm = {
631
+ id: { "in": "path", "name": "id", "required": true, "dataType": "string" },
632
+ sync: { "in": "query", "name": "sync", "dataType": "boolean" },
633
+ };
634
+ app.post('/rest/v0/vms/:id/actions/hard_shutdown', authenticateMiddleware([{ "*": [] }]), ...(fetchMiddlewares(VmController)), ...(fetchMiddlewares(VmController.prototype.hardShutdownVm)), async function VmController_hardShutdownVm(request, response, next) {
635
+ // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
636
+ let validatedArgs = [];
637
+ try {
638
+ validatedArgs = templateService.getValidatedArgs({ args: argsVmController_hardShutdownVm, request, response });
639
+ const container = typeof iocContainer === 'function' ? iocContainer(request) : iocContainer;
640
+ const controller = await container.get(VmController);
641
+ if (typeof controller['setStatus'] === 'function') {
642
+ controller.setStatus(undefined);
643
+ }
644
+ await templateService.apiHandler({
645
+ methodName: 'hardShutdownVm',
646
+ controller,
647
+ response,
648
+ next,
649
+ validatedArgs,
650
+ successStatus: 202,
651
+ });
652
+ }
653
+ catch (err) {
654
+ return next(err);
655
+ }
656
+ });
657
+ // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
658
+ const argsVmController_hardRebootVm = {
659
+ id: { "in": "path", "name": "id", "required": true, "dataType": "string" },
660
+ sync: { "in": "query", "name": "sync", "dataType": "boolean" },
661
+ };
662
+ app.post('/rest/v0/vms/:id/actions/hard_reboot', authenticateMiddleware([{ "*": [] }]), ...(fetchMiddlewares(VmController)), ...(fetchMiddlewares(VmController.prototype.hardRebootVm)), async function VmController_hardRebootVm(request, response, next) {
663
+ // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
664
+ let validatedArgs = [];
665
+ try {
666
+ validatedArgs = templateService.getValidatedArgs({ args: argsVmController_hardRebootVm, request, response });
667
+ const container = typeof iocContainer === 'function' ? iocContainer(request) : iocContainer;
668
+ const controller = await container.get(VmController);
669
+ if (typeof controller['setStatus'] === 'function') {
670
+ controller.setStatus(undefined);
671
+ }
672
+ await templateService.apiHandler({
673
+ methodName: 'hardRebootVm',
674
+ controller,
675
+ response,
676
+ next,
677
+ validatedArgs,
678
+ successStatus: 202,
679
+ });
680
+ }
681
+ catch (err) {
682
+ return next(err);
683
+ }
684
+ });
685
+ // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
560
686
  const argsVmTemplateController_getVmTemplates = {
561
687
  req: { "in": "request", "name": "req", "required": true, "dataType": "object" },
562
688
  fields: { "in": "query", "name": "fields", "dataType": "string" },
@@ -1127,6 +1253,89 @@ export function RegisterRoutes(app) {
1127
1253
  }
1128
1254
  });
1129
1255
  // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
1256
+ const argsServerController_addServer = {
1257
+ body: { "in": "body", "name": "body", "required": true, "ref": "InsertableXoServer" },
1258
+ };
1259
+ app.post('/rest/v0/servers', authenticateMiddleware([{ "*": [] }]), ...(fetchMiddlewares(ServerController)), ...(fetchMiddlewares(ServerController.prototype.addServer)), async function ServerController_addServer(request, response, next) {
1260
+ // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
1261
+ let validatedArgs = [];
1262
+ try {
1263
+ validatedArgs = templateService.getValidatedArgs({ args: argsServerController_addServer, request, response });
1264
+ const container = typeof iocContainer === 'function' ? iocContainer(request) : iocContainer;
1265
+ const controller = await container.get(ServerController);
1266
+ if (typeof controller['setStatus'] === 'function') {
1267
+ controller.setStatus(undefined);
1268
+ }
1269
+ await templateService.apiHandler({
1270
+ methodName: 'addServer',
1271
+ controller,
1272
+ response,
1273
+ next,
1274
+ validatedArgs,
1275
+ successStatus: 201,
1276
+ });
1277
+ }
1278
+ catch (err) {
1279
+ return next(err);
1280
+ }
1281
+ });
1282
+ // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
1283
+ const argsServerController_connectServer = {
1284
+ id: { "in": "path", "name": "id", "required": true, "dataType": "string" },
1285
+ sync: { "in": "query", "name": "sync", "dataType": "boolean" },
1286
+ };
1287
+ app.post('/rest/v0/servers/:id/actions/connect', authenticateMiddleware([{ "*": [] }]), ...(fetchMiddlewares(ServerController)), ...(fetchMiddlewares(ServerController.prototype.connectServer)), async function ServerController_connectServer(request, response, next) {
1288
+ // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
1289
+ let validatedArgs = [];
1290
+ try {
1291
+ validatedArgs = templateService.getValidatedArgs({ args: argsServerController_connectServer, request, response });
1292
+ const container = typeof iocContainer === 'function' ? iocContainer(request) : iocContainer;
1293
+ const controller = await container.get(ServerController);
1294
+ if (typeof controller['setStatus'] === 'function') {
1295
+ controller.setStatus(undefined);
1296
+ }
1297
+ await templateService.apiHandler({
1298
+ methodName: 'connectServer',
1299
+ controller,
1300
+ response,
1301
+ next,
1302
+ validatedArgs,
1303
+ successStatus: 202,
1304
+ });
1305
+ }
1306
+ catch (err) {
1307
+ return next(err);
1308
+ }
1309
+ });
1310
+ // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
1311
+ const argsServerController_disconnectServer = {
1312
+ id: { "in": "path", "name": "id", "required": true, "dataType": "string" },
1313
+ sync: { "in": "query", "name": "sync", "dataType": "boolean" },
1314
+ };
1315
+ app.post('/rest/v0/servers/:id/actions/disconnect', authenticateMiddleware([{ "*": [] }]), ...(fetchMiddlewares(ServerController)), ...(fetchMiddlewares(ServerController.prototype.disconnectServer)), async function ServerController_disconnectServer(request, response, next) {
1316
+ // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
1317
+ let validatedArgs = [];
1318
+ try {
1319
+ validatedArgs = templateService.getValidatedArgs({ args: argsServerController_disconnectServer, request, response });
1320
+ const container = typeof iocContainer === 'function' ? iocContainer(request) : iocContainer;
1321
+ const controller = await container.get(ServerController);
1322
+ if (typeof controller['setStatus'] === 'function') {
1323
+ controller.setStatus(undefined);
1324
+ }
1325
+ await templateService.apiHandler({
1326
+ methodName: 'disconnectServer',
1327
+ controller,
1328
+ response,
1329
+ next,
1330
+ validatedArgs,
1331
+ successStatus: 202,
1332
+ });
1333
+ }
1334
+ catch (err) {
1335
+ return next(err);
1336
+ }
1337
+ });
1338
+ // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
1130
1339
  const argsScheduleController_getSchedules = {
1131
1340
  req: { "in": "request", "name": "req", "required": true, "dataType": "object" },
1132
1341
  fields: { "in": "query", "name": "fields", "dataType": "string" },
@@ -7,10 +7,12 @@ 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 { Body, Example, Get, Middlewares, Path, Post, Query, Request, Response, Route, Security, SuccessResponse, Tags, } from 'tsoa';
11
+ import { json } from 'express';
11
12
  import { provide } from 'inversify-binding-decorators';
12
- import { notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
13
- import { partialServers, server, serverIds } from '../open-api/oa-examples/server.oa-example.mjs';
13
+ import { actionAsyncroneResp, createdResp, invalidParameters, noContentResp, notFoundResp, resourceAlreadyExists, unauthorizedResp, } from '../open-api/common/response.common.mjs';
14
+ import { partialServers, server, serverId, serverIds } from '../open-api/oa-examples/server.oa-example.mjs';
15
+ import { taskLocation } from '../open-api/oa-examples/task.oa-example.mjs';
14
16
  import { XoController } from '../abstract-classes/xo-controller.mjs';
15
17
  let ServerController = class ServerController extends XoController {
16
18
  // --- abstract methods
@@ -34,6 +36,47 @@ let ServerController = class ServerController extends XoController {
34
36
  getServer(id) {
35
37
  return this.getObject(id);
36
38
  }
39
+ /**
40
+ * @example body {
41
+ * "allowUnauthorized": true,
42
+ * "host": "192.168.1.10",
43
+ * "label": "Example server",
44
+ * "username": "root",
45
+ * "password": "awes0meP4ssword"
46
+ * }
47
+ */
48
+ async addServer(body) {
49
+ const server = await this.restApi.xoApp.registerXenServer(body);
50
+ return { id: server.id };
51
+ }
52
+ /**
53
+ * @example id "f07ab729-c0e8-721c-45ec-f11276377030"
54
+ */
55
+ connectServer(id, sync) {
56
+ const serverId = id;
57
+ const action = async () => {
58
+ await this.restApi.xoApp.connectXenServer(serverId);
59
+ };
60
+ return this.createAction(action, {
61
+ statusCode: noContentResp.status,
62
+ sync,
63
+ taskProperties: { name: 'connect server', objectId: serverId },
64
+ });
65
+ }
66
+ /**
67
+ * @example id "f07ab729-c0e8-721c-45ec-f11276377030"
68
+ */
69
+ disconnectServer(id, sync) {
70
+ const serverId = id;
71
+ const action = async () => {
72
+ await this.restApi.xoApp.disconnectXenServer(serverId);
73
+ };
74
+ return this.createAction(action, {
75
+ statusCode: noContentResp.status,
76
+ sync,
77
+ taskProperties: { name: 'disconnect server', objectId: serverId },
78
+ });
79
+ }
37
80
  };
38
81
  __decorate([
39
82
  Example(serverIds),
@@ -50,6 +93,35 @@ __decorate([
50
93
  Response(notFoundResp.status, notFoundResp.description),
51
94
  __param(0, Path())
52
95
  ], ServerController.prototype, "getServer", null);
96
+ __decorate([
97
+ Example(serverId),
98
+ Post(''),
99
+ Middlewares(json()),
100
+ SuccessResponse(createdResp.status, createdResp.description),
101
+ Response(resourceAlreadyExists.status, resourceAlreadyExists.description),
102
+ Response(invalidParameters.status, invalidParameters.description),
103
+ __param(0, Body())
104
+ ], ServerController.prototype, "addServer", null);
105
+ __decorate([
106
+ Example(taskLocation),
107
+ Post('{id}/actions/connect'),
108
+ SuccessResponse(actionAsyncroneResp.status, actionAsyncroneResp.description, actionAsyncroneResp.produce),
109
+ Response(noContentResp.status, noContentResp.description),
110
+ Response(notFoundResp.status, notFoundResp.description),
111
+ Response(409, 'The server is already connected'),
112
+ __param(0, Path()),
113
+ __param(1, Query())
114
+ ], ServerController.prototype, "connectServer", null);
115
+ __decorate([
116
+ Example(taskLocation),
117
+ Post('{id}/actions/disconnect'),
118
+ SuccessResponse(actionAsyncroneResp.status, actionAsyncroneResp.description, actionAsyncroneResp.produce),
119
+ Response(noContentResp.status, noContentResp.description),
120
+ Response(notFoundResp.status, notFoundResp.description),
121
+ Response(409, 'The server is already disconnected'),
122
+ __param(0, Path()),
123
+ __param(1, Query())
124
+ ], ServerController.prototype, "disconnectServer", null);
53
125
  ServerController = __decorate([
54
126
  Route('servers'),
55
127
  Security('*'),
@@ -0,0 +1 @@
1
+ export {};
@@ -70,6 +70,76 @@ let VmController = class VmController extends XapiXoController {
70
70
  },
71
71
  });
72
72
  }
73
+ /**
74
+ * Requires guest tools to be installed
75
+ * @example id "f07ab729-c0e8-721c-45ec-f11276377030"
76
+ */
77
+ async cleanShutdownVm(id, sync) {
78
+ const vmId = id;
79
+ const action = async () => {
80
+ await this.getXapiObject(vmId).$callAsync('clean_shutdown');
81
+ };
82
+ return this.createAction(action, {
83
+ sync,
84
+ statusCode: noContentResp.status,
85
+ taskProperties: {
86
+ name: 'clean shutdown VM',
87
+ objectId: vmId,
88
+ },
89
+ });
90
+ }
91
+ /**
92
+ * Requires guest tools to be installed
93
+ * @example id "f07ab729-c0e8-721c-45ec-f11276377030"
94
+ */
95
+ async cleanRebootVm(id, sync) {
96
+ const vmId = id;
97
+ const action = async () => {
98
+ await this.getXapiObject(vmId).$callAsync('clean_reboot');
99
+ };
100
+ return this.createAction(action, {
101
+ sync,
102
+ statusCode: noContentResp.status,
103
+ taskProperties: {
104
+ name: 'clean reboot VM',
105
+ objectId: vmId,
106
+ },
107
+ });
108
+ }
109
+ /**
110
+ * @example id "f07ab729-c0e8-721c-45ec-f11276377030"
111
+ */
112
+ async hardShutdownVm(id, sync) {
113
+ const vmId = id;
114
+ const action = async () => {
115
+ await this.getXapiObject(vmId).$callAsync('hard_shutdown');
116
+ };
117
+ return this.createAction(action, {
118
+ sync,
119
+ statusCode: noContentResp.status,
120
+ taskProperties: {
121
+ name: 'hard shutdown VM',
122
+ objectId: vmId,
123
+ },
124
+ });
125
+ }
126
+ /**
127
+ * @example id "f07ab729-c0e8-721c-45ec-f11276377030"
128
+ */
129
+ async hardRebootVm(id, sync) {
130
+ const vmId = id;
131
+ const action = async () => {
132
+ await this.getXapiObject(vmId).$callAsync('hard_reboot');
133
+ };
134
+ return this.createAction(action, {
135
+ sync,
136
+ statusCode: noContentResp.status,
137
+ taskProperties: {
138
+ name: 'hard reboot VM',
139
+ objectId: vmId,
140
+ },
141
+ });
142
+ }
73
143
  };
74
144
  __decorate([
75
145
  Example(vmIds),
@@ -104,6 +174,42 @@ __decorate([
104
174
  __param(0, Path()),
105
175
  __param(1, Query())
106
176
  ], VmController.prototype, "startVm", null);
177
+ __decorate([
178
+ Example(taskLocation),
179
+ Post('{id}/actions/clean_shutdown'),
180
+ SuccessResponse(actionAsyncroneResp.status, actionAsyncroneResp.description, actionAsyncroneResp.produce),
181
+ Response(noContentResp.status, noContentResp.description),
182
+ Response(notFoundResp.status, notFoundResp.description),
183
+ Response(internalServerErrorResp.status, internalServerErrorResp.description),
184
+ __param(0, Path()),
185
+ __param(1, Query())
186
+ ], VmController.prototype, "cleanShutdownVm", null);
187
+ __decorate([
188
+ Example(taskLocation),
189
+ Post('{id}/actions/clean_reboot'),
190
+ __param(0, Path()),
191
+ __param(1, Query())
192
+ ], VmController.prototype, "cleanRebootVm", null);
193
+ __decorate([
194
+ Example(taskLocation),
195
+ Post('{id}/actions/hard_shutdown'),
196
+ SuccessResponse(actionAsyncroneResp.status, actionAsyncroneResp.description, actionAsyncroneResp.produce),
197
+ Response(noContentResp.status, noContentResp.description),
198
+ Response(notFoundResp.status, notFoundResp.description),
199
+ Response(internalServerErrorResp.status, internalServerErrorResp.description),
200
+ __param(0, Path()),
201
+ __param(1, Query())
202
+ ], VmController.prototype, "hardShutdownVm", null);
203
+ __decorate([
204
+ Example(taskLocation),
205
+ Post('{id}/actions/hard_reboot'),
206
+ SuccessResponse(actionAsyncroneResp.status, actionAsyncroneResp.description, actionAsyncroneResp.produce),
207
+ Response(noContentResp.status, noContentResp.description),
208
+ Response(notFoundResp.status, notFoundResp.description),
209
+ Response(internalServerErrorResp.status, internalServerErrorResp.description),
210
+ __param(0, Path()),
211
+ __param(1, Query())
212
+ ], VmController.prototype, "hardRebootVm", null);
107
213
  VmController = __decorate([
108
214
  Route('vms'),
109
215
  Security('*'),
@@ -4443,6 +4443,38 @@
4443
4443
  ],
4444
4444
  "type": "object"
4445
4445
  },
4446
+ "InsertableXoServer": {
4447
+ "properties": {
4448
+ "host": {
4449
+ "type": "string"
4450
+ },
4451
+ "httpProxy": {
4452
+ "type": "string"
4453
+ },
4454
+ "label": {
4455
+ "type": "string"
4456
+ },
4457
+ "username": {
4458
+ "type": "string"
4459
+ },
4460
+ "allowUnauthorized": {
4461
+ "type": "boolean"
4462
+ },
4463
+ "password": {
4464
+ "type": "string"
4465
+ },
4466
+ "readOnly": {
4467
+ "type": "boolean"
4468
+ }
4469
+ },
4470
+ "required": [
4471
+ "host",
4472
+ "username",
4473
+ "password"
4474
+ ],
4475
+ "type": "object",
4476
+ "additionalProperties": false
4477
+ },
4446
4478
  "Partial_Unbrand_XoSchedule__": {
4447
4479
  "properties": {
4448
4480
  "cron": {
@@ -6226,7 +6258,7 @@
6226
6258
  },
6227
6259
  "info": {
6228
6260
  "title": "@xen-orchestra/rest-api",
6229
- "version": "0.6.0",
6261
+ "version": "0.7.0",
6230
6262
  "description": "REST API to manage your XOA",
6231
6263
  "license": {
6232
6264
  "name": "AGPL-3.0-or-later"
@@ -7825,6 +7857,263 @@
7825
7857
  ]
7826
7858
  }
7827
7859
  },
7860
+ "/vms/{id}/actions/clean_shutdown": {
7861
+ "post": {
7862
+ "operationId": "CleanShutdownVm",
7863
+ "responses": {
7864
+ "202": {
7865
+ "description": "Action executed asynchronously",
7866
+ "content": {
7867
+ "text/plain": {
7868
+ "schema": {
7869
+ "anyOf": [
7870
+ {
7871
+ "type": "string"
7872
+ },
7873
+ {}
7874
+ ]
7875
+ },
7876
+ "examples": {
7877
+ "Example 1": {
7878
+ "value": "/rest/v0/tasks/0m7kl0j9l"
7879
+ }
7880
+ }
7881
+ }
7882
+ }
7883
+ },
7884
+ "204": {
7885
+ "description": "No content"
7886
+ },
7887
+ "401": {
7888
+ "description": "Authentication required"
7889
+ },
7890
+ "404": {
7891
+ "description": "Resource not found"
7892
+ },
7893
+ "500": {
7894
+ "description": "Internal server error, XenServer/XCP-ng error"
7895
+ }
7896
+ },
7897
+ "description": "Requires guest tools to be installed",
7898
+ "tags": [
7899
+ "vms"
7900
+ ],
7901
+ "security": [
7902
+ {
7903
+ "*": []
7904
+ }
7905
+ ],
7906
+ "parameters": [
7907
+ {
7908
+ "in": "path",
7909
+ "name": "id",
7910
+ "required": true,
7911
+ "schema": {
7912
+ "type": "string"
7913
+ },
7914
+ "example": "f07ab729-c0e8-721c-45ec-f11276377030"
7915
+ },
7916
+ {
7917
+ "in": "query",
7918
+ "name": "sync",
7919
+ "required": false,
7920
+ "schema": {
7921
+ "type": "boolean"
7922
+ }
7923
+ }
7924
+ ]
7925
+ }
7926
+ },
7927
+ "/vms/{id}/actions/clean_reboot": {
7928
+ "post": {
7929
+ "operationId": "CleanRebootVm",
7930
+ "responses": {
7931
+ "200": {
7932
+ "description": "Ok",
7933
+ "content": {
7934
+ "application/json": {
7935
+ "schema": {
7936
+ "anyOf": [
7937
+ {},
7938
+ {
7939
+ "type": "string"
7940
+ }
7941
+ ]
7942
+ },
7943
+ "examples": {
7944
+ "Example 1": {
7945
+ "value": "/rest/v0/tasks/0m7kl0j9l"
7946
+ }
7947
+ }
7948
+ }
7949
+ }
7950
+ },
7951
+ "401": {
7952
+ "description": "Authentication required"
7953
+ }
7954
+ },
7955
+ "description": "Requires guest tools to be installed",
7956
+ "tags": [
7957
+ "vms"
7958
+ ],
7959
+ "security": [
7960
+ {
7961
+ "*": []
7962
+ }
7963
+ ],
7964
+ "parameters": [
7965
+ {
7966
+ "in": "path",
7967
+ "name": "id",
7968
+ "required": true,
7969
+ "schema": {
7970
+ "type": "string"
7971
+ },
7972
+ "example": "f07ab729-c0e8-721c-45ec-f11276377030"
7973
+ },
7974
+ {
7975
+ "in": "query",
7976
+ "name": "sync",
7977
+ "required": false,
7978
+ "schema": {
7979
+ "type": "boolean"
7980
+ }
7981
+ }
7982
+ ]
7983
+ }
7984
+ },
7985
+ "/vms/{id}/actions/hard_shutdown": {
7986
+ "post": {
7987
+ "operationId": "HardShutdownVm",
7988
+ "responses": {
7989
+ "202": {
7990
+ "description": "Action executed asynchronously",
7991
+ "content": {
7992
+ "text/plain": {
7993
+ "schema": {
7994
+ "anyOf": [
7995
+ {
7996
+ "type": "string"
7997
+ },
7998
+ {}
7999
+ ]
8000
+ },
8001
+ "examples": {
8002
+ "Example 1": {
8003
+ "value": "/rest/v0/tasks/0m7kl0j9l"
8004
+ }
8005
+ }
8006
+ }
8007
+ }
8008
+ },
8009
+ "204": {
8010
+ "description": "No content"
8011
+ },
8012
+ "401": {
8013
+ "description": "Authentication required"
8014
+ },
8015
+ "404": {
8016
+ "description": "Resource not found"
8017
+ },
8018
+ "500": {
8019
+ "description": "Internal server error, XenServer/XCP-ng error"
8020
+ }
8021
+ },
8022
+ "tags": [
8023
+ "vms"
8024
+ ],
8025
+ "security": [
8026
+ {
8027
+ "*": []
8028
+ }
8029
+ ],
8030
+ "parameters": [
8031
+ {
8032
+ "in": "path",
8033
+ "name": "id",
8034
+ "required": true,
8035
+ "schema": {
8036
+ "type": "string"
8037
+ },
8038
+ "example": "f07ab729-c0e8-721c-45ec-f11276377030"
8039
+ },
8040
+ {
8041
+ "in": "query",
8042
+ "name": "sync",
8043
+ "required": false,
8044
+ "schema": {
8045
+ "type": "boolean"
8046
+ }
8047
+ }
8048
+ ]
8049
+ }
8050
+ },
8051
+ "/vms/{id}/actions/hard_reboot": {
8052
+ "post": {
8053
+ "operationId": "HardRebootVm",
8054
+ "responses": {
8055
+ "202": {
8056
+ "description": "Action executed asynchronously",
8057
+ "content": {
8058
+ "text/plain": {
8059
+ "schema": {
8060
+ "anyOf": [
8061
+ {},
8062
+ {
8063
+ "type": "string"
8064
+ }
8065
+ ]
8066
+ },
8067
+ "examples": {
8068
+ "Example 1": {
8069
+ "value": "/rest/v0/tasks/0m7kl0j9l"
8070
+ }
8071
+ }
8072
+ }
8073
+ }
8074
+ },
8075
+ "204": {
8076
+ "description": "No content"
8077
+ },
8078
+ "401": {
8079
+ "description": "Authentication required"
8080
+ },
8081
+ "404": {
8082
+ "description": "Resource not found"
8083
+ },
8084
+ "500": {
8085
+ "description": "Internal server error, XenServer/XCP-ng error"
8086
+ }
8087
+ },
8088
+ "tags": [
8089
+ "vms"
8090
+ ],
8091
+ "security": [
8092
+ {
8093
+ "*": []
8094
+ }
8095
+ ],
8096
+ "parameters": [
8097
+ {
8098
+ "in": "path",
8099
+ "name": "id",
8100
+ "required": true,
8101
+ "schema": {
8102
+ "type": "string"
8103
+ },
8104
+ "example": "f07ab729-c0e8-721c-45ec-f11276377030"
8105
+ },
8106
+ {
8107
+ "in": "query",
8108
+ "name": "sync",
8109
+ "required": false,
8110
+ "schema": {
8111
+ "type": "boolean"
8112
+ }
8113
+ }
8114
+ ]
8115
+ }
8116
+ },
7828
8117
  "/vm-templates": {
7829
8118
  "get": {
7830
8119
  "operationId": "GetVmTemplates",
@@ -9721,6 +10010,71 @@
9721
10010
  "example": 42
9722
10011
  }
9723
10012
  ]
10013
+ },
10014
+ "post": {
10015
+ "operationId": "AddServer",
10016
+ "responses": {
10017
+ "201": {
10018
+ "description": "Resource created",
10019
+ "content": {
10020
+ "application/json": {
10021
+ "schema": {
10022
+ "properties": {
10023
+ "id": {
10024
+ "type": "string"
10025
+ }
10026
+ },
10027
+ "required": [
10028
+ "id"
10029
+ ],
10030
+ "type": "object"
10031
+ },
10032
+ "examples": {
10033
+ "Example 1": {
10034
+ "value": {
10035
+ "id": "38068475-3a1d-4a64-95df-8782cdea02ac"
10036
+ }
10037
+ }
10038
+ }
10039
+ }
10040
+ }
10041
+ },
10042
+ "401": {
10043
+ "description": "Authentication required"
10044
+ },
10045
+ "409": {
10046
+ "description": "Resource already exists"
10047
+ },
10048
+ "422": {
10049
+ "description": "Invalid parameters"
10050
+ }
10051
+ },
10052
+ "tags": [
10053
+ "servers"
10054
+ ],
10055
+ "security": [
10056
+ {
10057
+ "*": []
10058
+ }
10059
+ ],
10060
+ "parameters": [],
10061
+ "requestBody": {
10062
+ "required": true,
10063
+ "content": {
10064
+ "application/json": {
10065
+ "schema": {
10066
+ "$ref": "#/components/schemas/InsertableXoServer"
10067
+ },
10068
+ "example": {
10069
+ "allowUnauthorized": true,
10070
+ "host": "192.168.1.10",
10071
+ "label": "Example server",
10072
+ "username": "root",
10073
+ "password": "awes0meP4ssword"
10074
+ }
10075
+ }
10076
+ }
10077
+ }
9724
10078
  }
9725
10079
  },
9726
10080
  "/servers/{id}": {
@@ -9781,6 +10135,138 @@
9781
10135
  ]
9782
10136
  }
9783
10137
  },
10138
+ "/servers/{id}/actions/connect": {
10139
+ "post": {
10140
+ "operationId": "ConnectServer",
10141
+ "responses": {
10142
+ "202": {
10143
+ "description": "Action executed asynchronously",
10144
+ "content": {
10145
+ "text/plain": {
10146
+ "schema": {
10147
+ "anyOf": [
10148
+ {},
10149
+ {
10150
+ "type": "string"
10151
+ }
10152
+ ]
10153
+ },
10154
+ "examples": {
10155
+ "Example 1": {
10156
+ "value": "/rest/v0/tasks/0m7kl0j9l"
10157
+ }
10158
+ }
10159
+ }
10160
+ }
10161
+ },
10162
+ "204": {
10163
+ "description": "No content"
10164
+ },
10165
+ "401": {
10166
+ "description": "Authentication required"
10167
+ },
10168
+ "404": {
10169
+ "description": "Resource not found"
10170
+ },
10171
+ "409": {
10172
+ "description": "The server is already connected"
10173
+ }
10174
+ },
10175
+ "tags": [
10176
+ "servers"
10177
+ ],
10178
+ "security": [
10179
+ {
10180
+ "*": []
10181
+ }
10182
+ ],
10183
+ "parameters": [
10184
+ {
10185
+ "in": "path",
10186
+ "name": "id",
10187
+ "required": true,
10188
+ "schema": {
10189
+ "type": "string"
10190
+ },
10191
+ "example": "f07ab729-c0e8-721c-45ec-f11276377030"
10192
+ },
10193
+ {
10194
+ "in": "query",
10195
+ "name": "sync",
10196
+ "required": false,
10197
+ "schema": {
10198
+ "type": "boolean"
10199
+ }
10200
+ }
10201
+ ]
10202
+ }
10203
+ },
10204
+ "/servers/{id}/actions/disconnect": {
10205
+ "post": {
10206
+ "operationId": "DisconnectServer",
10207
+ "responses": {
10208
+ "202": {
10209
+ "description": "Action executed asynchronously",
10210
+ "content": {
10211
+ "text/plain": {
10212
+ "schema": {
10213
+ "anyOf": [
10214
+ {},
10215
+ {
10216
+ "type": "string"
10217
+ }
10218
+ ]
10219
+ },
10220
+ "examples": {
10221
+ "Example 1": {
10222
+ "value": "/rest/v0/tasks/0m7kl0j9l"
10223
+ }
10224
+ }
10225
+ }
10226
+ }
10227
+ },
10228
+ "204": {
10229
+ "description": "No content"
10230
+ },
10231
+ "401": {
10232
+ "description": "Authentication required"
10233
+ },
10234
+ "404": {
10235
+ "description": "Resource not found"
10236
+ },
10237
+ "409": {
10238
+ "description": "The server is already disconnected"
10239
+ }
10240
+ },
10241
+ "tags": [
10242
+ "servers"
10243
+ ],
10244
+ "security": [
10245
+ {
10246
+ "*": []
10247
+ }
10248
+ ],
10249
+ "parameters": [
10250
+ {
10251
+ "in": "path",
10252
+ "name": "id",
10253
+ "required": true,
10254
+ "schema": {
10255
+ "type": "string"
10256
+ },
10257
+ "example": "f07ab729-c0e8-721c-45ec-f11276377030"
10258
+ },
10259
+ {
10260
+ "in": "query",
10261
+ "name": "sync",
10262
+ "required": false,
10263
+ "schema": {
10264
+ "type": "boolean"
10265
+ }
10266
+ }
10267
+ ]
10268
+ }
10269
+ },
9784
10270
  "/schedules": {
9785
10271
  "get": {
9786
10272
  "operationId": "GetSchedules",
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "main": "./dist/index.mjs",
7
7
  "name": "@xen-orchestra/rest-api",
8
8
  "homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@xen-orchestra/rest-api",
9
- "version": "0.6.0",
9
+ "version": "0.7.0",
10
10
  "description": "REST API to manage your XOA",
11
11
  "license": "AGPL-3.0-or-later",
12
12
  "private": false,
@@ -32,7 +32,7 @@
32
32
  "typescript-eslint": "^8.23.0"
33
33
  },
34
34
  "dependencies": {
35
- "@vates/types": "^1.2.0",
35
+ "@vates/types": "^1.3.0",
36
36
  "@xen-orchestra/log": "^0.7.1",
37
37
  "complex-matcher": "^0.7.1",
38
38
  "inversify": "^6.2.2",