@xen-orchestra/rest-api 0.21.0 → 0.21.2
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 +2 -3
- package/dist/alarms/alarm.service.mjs +3 -3
- package/dist/backup-archives/backup-archive.controller.mjs +1 -0
- package/dist/backup-jobs/backup-job.controller.mjs +2 -3
- package/dist/helpers/error.helper.mjs +6 -1
- package/dist/helpers/utils.helper.mjs +15 -1
- package/dist/index.mjs +2 -1
- package/dist/messages/message.controller.mjs +2 -2
- package/dist/open-api/routes/routes.js +2 -2
- package/dist/rest-api/rest-api.mjs +2 -2
- package/dist/tasks/task.controller.mjs +2 -2
- package/dist/vms/vm.service.mjs +10 -7
- package/dist/xoa/xoa.controller.mjs +12 -4
- package/dist/xoa/xoa.service.mjs +0 -17
- package/open-api/spec/swagger.json +9 -4
- package/package.json +2 -2
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as CM from 'complex-matcher';
|
|
2
1
|
import { Controller } from 'tsoa';
|
|
3
2
|
import { createGzip } from 'node:zlib';
|
|
4
3
|
import { pipeline } from 'node:stream/promises';
|
|
@@ -6,7 +5,7 @@ import { Readable } from 'node:stream';
|
|
|
6
5
|
import { BASE_URL } from '../index.mjs';
|
|
7
6
|
import { makeNdJsonStream } from '../helpers/stream.helper.mjs';
|
|
8
7
|
import { makeObjectMapper } from '../helpers/object-wrapper.helper.mjs';
|
|
9
|
-
import { NDJSON_CONTENT_TYPE } from '../helpers/utils.helper.mjs';
|
|
8
|
+
import { NDJSON_CONTENT_TYPE, safeParseComplexMatcher } from '../helpers/utils.helper.mjs';
|
|
10
9
|
const noop = () => { };
|
|
11
10
|
export class BaseController extends Controller {
|
|
12
11
|
restApi;
|
|
@@ -34,7 +33,7 @@ export class BaseController extends Controller {
|
|
|
34
33
|
const objectFilter = (task) => task.properties.objectId === object.id || task.properties.params?.id === object.id;
|
|
35
34
|
let userFilter = () => true;
|
|
36
35
|
if (filter !== undefined) {
|
|
37
|
-
userFilter = typeof filter === 'string' ?
|
|
36
|
+
userFilter = typeof filter === 'string' ? safeParseComplexMatcher(filter).createPredicate() : filter;
|
|
38
37
|
}
|
|
39
38
|
for await (const task of this.restApi.tasks.list({ filter: objectFilter })) {
|
|
40
39
|
if (limit === 0) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import * as CM from 'complex-matcher';
|
|
2
1
|
import { BASE_URL } from '../index.mjs';
|
|
2
|
+
import { safeParseComplexMatcher } from '../helpers/utils.helper.mjs';
|
|
3
3
|
// E.g: 'value: 0.6\nconfig:\n<variable>\n<name value="cpu_usage"/>\n<alarm_trigger_level value="0.4"/>\n<alarm_trigger_period value ="60"/>\n</variable>';
|
|
4
4
|
const ALARM_BODY_REGEX = /^value:\s*(Infinity|NaN|-Infinity|\d+(?:\.\d+)?)\s*config:\s*<variable>\s*<name value="(.*?)"/;
|
|
5
5
|
const ALARM_NAMES = ['ALARM', 'BOND_STATUS_CHANGED', 'MULTIPATH_PERIODIC_ALERT'];
|
|
6
6
|
export const RAW_ALARM_FILTER = `name:|(${ALARM_NAMES.join(' ')})`;
|
|
7
|
-
export const alarmPredicate =
|
|
7
|
+
export const alarmPredicate = safeParseComplexMatcher(RAW_ALARM_FILTER).createPredicate();
|
|
8
8
|
export class AlarmService {
|
|
9
9
|
#restApi;
|
|
10
10
|
constructor(restApi) {
|
|
@@ -50,7 +50,7 @@ export class AlarmService {
|
|
|
50
50
|
});
|
|
51
51
|
let userFilter = () => true;
|
|
52
52
|
if (filter !== undefined) {
|
|
53
|
-
userFilter = typeof filter === 'string' ?
|
|
53
|
+
userFilter = typeof filter === 'string' ? safeParseComplexMatcher(filter).createPredicate() : filter;
|
|
54
54
|
}
|
|
55
55
|
const alarms = {};
|
|
56
56
|
for (const id in rawAlarms) {
|
|
@@ -30,6 +30,7 @@ let BackupArchiveController = class BackupArchiveController extends XoController
|
|
|
30
30
|
}
|
|
31
31
|
const backupArchivesByRemote = await this.restApi.xoApp.listVmBackupsNg(backupRepositoryIds);
|
|
32
32
|
const vmBackupArchives = Object.values(backupArchivesByRemote)
|
|
33
|
+
.filter(backupsByVm => backupsByVm !== undefined)
|
|
33
34
|
.map(backupsByVm => Object.values(backupsByVm))
|
|
34
35
|
.flat(2);
|
|
35
36
|
return vmBackupArchives;
|
|
@@ -7,7 +7,6 @@ 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 * as CM from 'complex-matcher';
|
|
11
10
|
import { createLogger } from '@xen-orchestra/log';
|
|
12
11
|
import { inject } from 'inversify';
|
|
13
12
|
import { noSuchObject } from 'xo-common/api-errors.js';
|
|
@@ -17,7 +16,7 @@ import { backupLog, backupLogIds, partialBackupLogs } from '../open-api/oa-examp
|
|
|
17
16
|
import { BackupLogService } from '../backup-logs/backup-log.service.mjs';
|
|
18
17
|
import { badRequestResp, notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
|
|
19
18
|
import { RestApi } from '../rest-api/rest-api.mjs';
|
|
20
|
-
import { limitAndFilterArray } from '../helpers/utils.helper.mjs';
|
|
19
|
+
import { limitAndFilterArray, safeParseComplexMatcher } from '../helpers/utils.helper.mjs';
|
|
21
20
|
import { XoController } from '../abstract-classes/xo-controller.mjs';
|
|
22
21
|
import { metadataBackupJob, metadataBackupJobIds, mirrorBackupJob, mirrorBackupJobIds, partialMetadataBackupJobs, partialMirrorBackupJobs, partialVmBackupJobs, vmBackupJob, vmBackupJobIds, } from '../open-api/oa-examples/backup-job.oa-example.mjs';
|
|
23
22
|
import { BASE_URL } from '../index.mjs';
|
|
@@ -171,7 +170,7 @@ let DeprecatedBackupController = class DeprecatedBackupController extends XoCont
|
|
|
171
170
|
* @example limit 42
|
|
172
171
|
*/
|
|
173
172
|
async getDeprecatedBackupLogs(req, fields, ndjson, filter, limit) {
|
|
174
|
-
const userFilter = filter === undefined ? () => true :
|
|
173
|
+
const userFilter = filter === undefined ? () => true : safeParseComplexMatcher(filter).createPredicate();
|
|
175
174
|
const predicate = (log) => {
|
|
176
175
|
if (!this.#backupLogService.isBackupLog(log)) {
|
|
177
176
|
return false;
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
export class ApiError extends Error {
|
|
2
2
|
#status;
|
|
3
|
-
|
|
3
|
+
#data;
|
|
4
|
+
constructor(message, status, opts = {}) {
|
|
4
5
|
super(message);
|
|
5
6
|
this.#status = status;
|
|
7
|
+
this.#data = opts.data;
|
|
6
8
|
}
|
|
7
9
|
get status() {
|
|
8
10
|
return this.#status;
|
|
9
11
|
}
|
|
12
|
+
get data() {
|
|
13
|
+
return this.#data;
|
|
14
|
+
}
|
|
10
15
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as CM from 'complex-matcher';
|
|
2
2
|
import { createLogger } from '@xen-orchestra/log';
|
|
3
3
|
import { isPromise } from 'node:util/types';
|
|
4
|
+
import { ApiError } from './error.helper.mjs';
|
|
4
5
|
export const NDJSON_CONTENT_TYPE = 'application/x-ndjson';
|
|
5
6
|
const log = createLogger('xo:rest-api:utils-helper');
|
|
6
7
|
export const isSrWritable = (sr) => isSrWritableOrIso(sr) && sr.content_type !== 'iso';
|
|
@@ -76,9 +77,22 @@ export function escapeUnsafeComplexMatcher(maybeString) {
|
|
|
76
77
|
}
|
|
77
78
|
return `(${maybeString})`;
|
|
78
79
|
}
|
|
80
|
+
export function safeParseComplexMatcher(string) {
|
|
81
|
+
try {
|
|
82
|
+
return CM.parse(string);
|
|
83
|
+
}
|
|
84
|
+
catch (_error) {
|
|
85
|
+
// CM.parse only throw errors that are instances of Error
|
|
86
|
+
const error = _error;
|
|
87
|
+
const apiError = new ApiError(error.message, 400, { data: { stringToParse: string } });
|
|
88
|
+
apiError.cause = error;
|
|
89
|
+
apiError.stack = error.stack;
|
|
90
|
+
throw apiError;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
79
93
|
export function limitAndFilterArray(array, { filter, limit = Infinity } = {}) {
|
|
80
94
|
if (filter !== undefined) {
|
|
81
|
-
const predicate = typeof filter === 'string' ?
|
|
95
|
+
const predicate = typeof filter === 'string' ? safeParseComplexMatcher(filter).createPredicate() : filter;
|
|
82
96
|
array = array.filter(predicate);
|
|
83
97
|
}
|
|
84
98
|
if (limit < array.length) {
|
package/dist/index.mjs
CHANGED
|
@@ -12,6 +12,7 @@ const swaggerOpenApiSpec = require('../open-api/spec/swagger.json');
|
|
|
12
12
|
export const BASE_URL = '/rest/v0';
|
|
13
13
|
const SWAGGER_UI_OPTIONS = {
|
|
14
14
|
swaggerOptions: {
|
|
15
|
+
url: `${BASE_URL}/docs/swagger.json`,
|
|
15
16
|
displayRequestDuration: true,
|
|
16
17
|
docExpansion: 'none', // collapse all tags by default
|
|
17
18
|
filter: true, // add a tags searchbar,
|
|
@@ -40,7 +41,7 @@ export default function setupRestApi(express, xoApp) {
|
|
|
40
41
|
});
|
|
41
42
|
// do not register the doc at the root level, or it may lead to unwanted behaviour
|
|
42
43
|
express.get('/rest/v0', (_req, res) => res.redirect('/rest/v0/docs'));
|
|
43
|
-
express.use(`${BASE_URL}/docs`, swaggerUi.
|
|
44
|
+
express.use(`${BASE_URL}/docs`, swaggerUi.serveFiles(undefined, SWAGGER_UI_OPTIONS), swaggerUi.setup(null, SWAGGER_UI_OPTIONS));
|
|
44
45
|
express.use(BASE_URL, tsoaToXoErrorHandler);
|
|
45
46
|
express.use(BASE_URL, genericErrorHandler);
|
|
46
47
|
}
|
|
@@ -7,7 +7,6 @@ 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 * as CM from 'complex-matcher';
|
|
11
10
|
import { Example, Get, Path, Query, Request, Response, Route, Security, Tags } from 'tsoa';
|
|
12
11
|
import { inject } from 'inversify';
|
|
13
12
|
import { noSuchObject } from 'xo-common/api-errors.js';
|
|
@@ -17,6 +16,7 @@ import { message, messageIds, partialMessages } from '../open-api/oa-examples/me
|
|
|
17
16
|
import { RestApi } from '../rest-api/rest-api.mjs';
|
|
18
17
|
import { badRequestResp, notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
|
|
19
18
|
import { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs';
|
|
19
|
+
import { safeParseComplexMatcher } from '../helpers/utils.helper.mjs';
|
|
20
20
|
let MessageController = class MessageController extends XapiXoController {
|
|
21
21
|
constructor(restapi) {
|
|
22
22
|
super('message', restapi);
|
|
@@ -27,7 +27,7 @@ let MessageController = class MessageController extends XapiXoController {
|
|
|
27
27
|
getObjects({ filter, limit = Infinity } = {}) {
|
|
28
28
|
let userfilter = () => true;
|
|
29
29
|
if (filter !== undefined) {
|
|
30
|
-
userfilter =
|
|
30
|
+
userfilter = safeParseComplexMatcher(filter).createPredicate();
|
|
31
31
|
}
|
|
32
32
|
const messagePredicate = (obj) => !alarmPredicate(obj) && userfilter(obj);
|
|
33
33
|
return super.getObjects({ filter: messagePredicate, limit });
|
|
@@ -105,7 +105,7 @@ const models = {
|
|
|
105
105
|
// 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
|
|
106
106
|
"XoGuiRoutes": {
|
|
107
107
|
"dataType": "refAlias",
|
|
108
|
-
"type": { "dataType": "nestedObjectLiteral", "nestedProperties": { "xo6": { "dataType": "
|
|
108
|
+
"type": { "dataType": "nestedObjectLiteral", "nestedProperties": { "xo6": { "dataType": "string" }, "xo5": { "dataType": "string" } }, "validators": {} },
|
|
109
109
|
},
|
|
110
110
|
// 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
|
|
111
111
|
"Record_string.string_": {
|
|
@@ -350,7 +350,7 @@ const models = {
|
|
|
350
350
|
// 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
|
|
351
351
|
"UnbrandedVmDashboard": {
|
|
352
352
|
"dataType": "refAlias",
|
|
353
|
-
"type": { "dataType": "nestedObjectLiteral", "nestedProperties": { "backupsInfo": { "dataType": "nestedObjectLiteral", "nestedProperties": { "backupArchives": { "dataType": "array", "array": { "dataType": "refAlias", "ref": "Unbrand_VmDashboardBackupArchive_" }, "required": true }, "replication": { "ref": "Unbrand_VmDashboard-at-backupsInfo_91_replication_93__" }, "
|
|
353
|
+
"type": { "dataType": "nestedObjectLiteral", "nestedProperties": { "backupsInfo": { "dataType": "nestedObjectLiteral", "nestedProperties": { "backupArchives": { "dataType": "array", "array": { "dataType": "refAlias", "ref": "Unbrand_VmDashboardBackupArchive_" }, "required": true }, "replication": { "ref": "Unbrand_VmDashboard-at-backupsInfo_91_replication_93__" }, "vmProtection": { "dataType": "union", "subSchemas": [{ "dataType": "enum", "enums": ["protected"] }, { "dataType": "enum", "enums": ["unprotected"] }, { "dataType": "enum", "enums": ["not-in-job"] }], "required": true }, "lastRuns": { "dataType": "array", "array": { "dataType": "refAlias", "ref": "Unbrand_VmDashboardRun_" }, "required": true } }, "required": true }, "alarms": { "dataType": "array", "array": { "dataType": "string" }, "required": true }, "quickInfo": { "dataType": "intersection", "subSchemas": [{ "ref": "Omit_Unbrand_VmDashboard-at-quickInfo_.creation_" }, { "dataType": "nestedObjectLiteral", "nestedProperties": { "creation": { "ref": "Unbrand_VmDashboard-at-quickInfo_91_creation_93__", "required": true } } }], "required": true } }, "validators": {} },
|
|
354
354
|
},
|
|
355
355
|
// 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
|
|
356
356
|
"Partial_Unbrand_XoVmTemplate__": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as CM from 'complex-matcher';
|
|
2
1
|
import { createLogger } from '@xen-orchestra/log';
|
|
3
2
|
import { invalidCredentials } from 'xo-common/api-errors.js';
|
|
3
|
+
import { safeParseComplexMatcher } from '../helpers/utils.helper.mjs';
|
|
4
4
|
const log = createLogger('xo:rest-api:error-handler');
|
|
5
5
|
export class RestApi {
|
|
6
6
|
#ioc;
|
|
@@ -34,7 +34,7 @@ export class RestApi {
|
|
|
34
34
|
}
|
|
35
35
|
getObjectsByType(type, { filter, ...opts } = {}) {
|
|
36
36
|
if (filter !== undefined && typeof filter === 'string') {
|
|
37
|
-
filter =
|
|
37
|
+
filter = safeParseComplexMatcher(filter).createPredicate();
|
|
38
38
|
}
|
|
39
39
|
return this.#xoApp.getObjectsByType(type, { filter, ...opts });
|
|
40
40
|
}
|
|
@@ -7,7 +7,6 @@ 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 * as CM from 'complex-matcher';
|
|
11
10
|
import { XoController } from '../abstract-classes/xo-controller.mjs';
|
|
12
11
|
import { Get, Path, Query, Request, Route, Security, Tags, Response, Example, Delete, Post, SuccessResponse, } from 'tsoa';
|
|
13
12
|
import { asynchronousActionResp, badRequestResp, noContentResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
|
|
@@ -17,6 +16,7 @@ import pDefer from 'promise-toolbox/defer';
|
|
|
17
16
|
import { ApiError } from '../helpers/error.helper.mjs';
|
|
18
17
|
import { Transform } from 'node:stream';
|
|
19
18
|
import { makeObjectMapper } from '../helpers/object-wrapper.helper.mjs';
|
|
19
|
+
import { safeParseComplexMatcher } from '../helpers/utils.helper.mjs';
|
|
20
20
|
let TaskController = class TaskController extends XoController {
|
|
21
21
|
async getAllCollectionObjects() {
|
|
22
22
|
const result = [];
|
|
@@ -41,7 +41,7 @@ let TaskController = class TaskController extends XoController {
|
|
|
41
41
|
if (!ndjson) {
|
|
42
42
|
throw new ApiError('watch=true requires ndjson=true', 400);
|
|
43
43
|
}
|
|
44
|
-
const userFilter = filter === undefined ? undefined :
|
|
44
|
+
const userFilter = filter === undefined ? undefined : safeParseComplexMatcher(filter).createPredicate();
|
|
45
45
|
const stream = new Transform({
|
|
46
46
|
objectMode: true,
|
|
47
47
|
transform([event, object], encoding, callback) {
|
package/dist/vms/vm.service.mjs
CHANGED
|
@@ -239,29 +239,32 @@ export class VmService {
|
|
|
239
239
|
status,
|
|
240
240
|
};
|
|
241
241
|
});
|
|
242
|
-
let
|
|
242
|
+
let vmProtection = 'not-in-job';
|
|
243
243
|
if (!vmContainsNoBakTag(vm)) {
|
|
244
244
|
const backupLogsByJob = groupBy(backupLogs, 'jobId');
|
|
245
245
|
for (const backupJob of relevantJobsWithSchedule) {
|
|
246
|
-
if (
|
|
246
|
+
if (vmProtection === 'protected') {
|
|
247
247
|
break;
|
|
248
248
|
}
|
|
249
|
+
vmProtection = 'unprotected';
|
|
249
250
|
// can be undefined if the backup did run for now
|
|
250
251
|
const jobLogs = backupLogsByJob[backupJob.id]
|
|
251
252
|
?.filter(log => log.status !== 'pending')
|
|
252
253
|
.slice(-3);
|
|
253
254
|
if (jobLogs !== undefined) {
|
|
254
|
-
|
|
255
|
+
vmProtection = jobLogs.every(log => {
|
|
255
256
|
if (log.status === 'success') {
|
|
256
257
|
return true;
|
|
257
258
|
}
|
|
258
259
|
const vmTaskLog = this.#backupLogService.getVmBackupTaskLog(log, id);
|
|
259
260
|
return vmTaskLog?.status === 'success';
|
|
260
|
-
})
|
|
261
|
+
})
|
|
262
|
+
? 'protected'
|
|
263
|
+
: 'unprotected';
|
|
261
264
|
}
|
|
262
265
|
}
|
|
263
266
|
}
|
|
264
|
-
return { lastRuns: lastBackupRuns,
|
|
267
|
+
return { lastRuns: lastBackupRuns, vmProtection };
|
|
265
268
|
}
|
|
266
269
|
async #getLastVmBackupArchives(id) {
|
|
267
270
|
const vm = this.#restApi.getObject(id, 'VM');
|
|
@@ -274,7 +277,7 @@ export class VmService {
|
|
|
274
277
|
.map(ba => ({ id: ba.id, timestamp: ba.timestamp, backupRepository: ba.backupRepository, size: ba.size }));
|
|
275
278
|
}
|
|
276
279
|
async getVmDashboard(id, { stream } = {}) {
|
|
277
|
-
const [quickInfo, alarms, lastReplication, { lastRuns,
|
|
280
|
+
const [quickInfo, alarms, lastReplication, { lastRuns, vmProtection }, lastBackupArchives] = await Promise.all([
|
|
278
281
|
promiseWriteInStream({ maybePromise: this.#getDashboardQuickInfo(id), path: 'quickInfo', stream }),
|
|
279
282
|
promiseWriteInStream({ maybePromise: Object.keys(this.getVmAlarms(id)), path: 'alarms', stream }),
|
|
280
283
|
promiseWriteInStream({ maybePromise: this.#getLastReplication(id), path: 'backupsInfo.replication', stream }),
|
|
@@ -290,7 +293,7 @@ export class VmService {
|
|
|
290
293
|
alarms: alarms,
|
|
291
294
|
backupsInfo: {
|
|
292
295
|
lastRuns,
|
|
293
|
-
|
|
296
|
+
vmProtection,
|
|
294
297
|
replication: lastReplication,
|
|
295
298
|
backupArchives: lastBackupArchives,
|
|
296
299
|
},
|
|
@@ -17,10 +17,13 @@ import { badRequestResp, unauthorizedResp } from '../open-api/common/response.co
|
|
|
17
17
|
import { xoaDashboard } from '../open-api/oa-examples/xoa.oa-example.mjs';
|
|
18
18
|
import { XoaService } from './xoa.service.mjs';
|
|
19
19
|
import { NDJSON_CONTENT_TYPE } from '../helpers/utils.helper.mjs';
|
|
20
|
+
import { RestApi } from '../rest-api/rest-api.mjs';
|
|
20
21
|
let XoaController = class XoaController extends Controller {
|
|
22
|
+
#restApi;
|
|
21
23
|
#xoaService;
|
|
22
|
-
constructor(xoaService) {
|
|
24
|
+
constructor(restApi, xoaService) {
|
|
23
25
|
super();
|
|
26
|
+
this.#restApi = restApi;
|
|
24
27
|
this.#xoaService = xoaService;
|
|
25
28
|
}
|
|
26
29
|
async getDashboard(req, ndjson) {
|
|
@@ -45,8 +48,12 @@ let XoaController = class XoaController extends Controller {
|
|
|
45
48
|
timestamp: Date.now(),
|
|
46
49
|
};
|
|
47
50
|
}
|
|
48
|
-
getGuiRoutes() {
|
|
49
|
-
|
|
51
|
+
async getGuiRoutes() {
|
|
52
|
+
const { xo5, xo6 } = await this.#restApi.xoApp.config.getGuiRoutes();
|
|
53
|
+
return {
|
|
54
|
+
xo5: xo5.url,
|
|
55
|
+
xo6: xo6.url,
|
|
56
|
+
};
|
|
50
57
|
}
|
|
51
58
|
};
|
|
52
59
|
__decorate([
|
|
@@ -72,6 +79,7 @@ XoaController = __decorate([
|
|
|
72
79
|
Security('*'),
|
|
73
80
|
Tags('xoa'),
|
|
74
81
|
provide(XoaController),
|
|
75
|
-
__param(0, inject(
|
|
82
|
+
__param(0, inject(RestApi)),
|
|
83
|
+
__param(1, inject(XoaService))
|
|
76
84
|
], XoaController);
|
|
77
85
|
export { XoaController };
|
package/dist/xoa/xoa.service.mjs
CHANGED
|
@@ -484,21 +484,4 @@ export class XoaService {
|
|
|
484
484
|
vmsStatus,
|
|
485
485
|
};
|
|
486
486
|
}
|
|
487
|
-
getGuiRoutes() {
|
|
488
|
-
const mounts = this.#restApi.xoApp.config.getOptional('http.mounts') ?? {};
|
|
489
|
-
let xo5Mount;
|
|
490
|
-
let xo6Mount;
|
|
491
|
-
for (const [key, value] of Object.entries(mounts)) {
|
|
492
|
-
if (value.includes('xo-web/dist')) {
|
|
493
|
-
xo5Mount = key;
|
|
494
|
-
}
|
|
495
|
-
else if (value.includes('@xen-orchestra/web/dist')) {
|
|
496
|
-
xo6Mount = key;
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
return {
|
|
500
|
-
xo5: xo5Mount,
|
|
501
|
-
xo6: xo6Mount,
|
|
502
|
-
};
|
|
503
|
-
}
|
|
504
487
|
}
|
|
@@ -2597,8 +2597,13 @@
|
|
|
2597
2597
|
"replication": {
|
|
2598
2598
|
"$ref": "#/components/schemas/Unbrand_VmDashboard-at-backupsInfo_91_replication_93__"
|
|
2599
2599
|
},
|
|
2600
|
-
"
|
|
2601
|
-
"type": "
|
|
2600
|
+
"vmProtection": {
|
|
2601
|
+
"type": "string",
|
|
2602
|
+
"enum": [
|
|
2603
|
+
"protected",
|
|
2604
|
+
"unprotected",
|
|
2605
|
+
"not-in-job"
|
|
2606
|
+
]
|
|
2602
2607
|
},
|
|
2603
2608
|
"lastRuns": {
|
|
2604
2609
|
"items": {
|
|
@@ -2609,7 +2614,7 @@
|
|
|
2609
2614
|
},
|
|
2610
2615
|
"required": [
|
|
2611
2616
|
"backupArchives",
|
|
2612
|
-
"
|
|
2617
|
+
"vmProtection",
|
|
2613
2618
|
"lastRuns"
|
|
2614
2619
|
],
|
|
2615
2620
|
"type": "object"
|
|
@@ -12004,7 +12009,7 @@
|
|
|
12004
12009
|
},
|
|
12005
12010
|
"info": {
|
|
12006
12011
|
"title": "@xen-orchestra/rest-api",
|
|
12007
|
-
"version": "0.21.
|
|
12012
|
+
"version": "0.21.2",
|
|
12008
12013
|
"description": "REST API to manage your XOA",
|
|
12009
12014
|
"license": {
|
|
12010
12015
|
"name": "AGPL-3.0-or-later"
|
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.21.
|
|
9
|
+
"version": "0.21.2",
|
|
10
10
|
"description": "REST API to manage your XOA",
|
|
11
11
|
"license": "AGPL-3.0-or-later",
|
|
12
12
|
"private": false,
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"@vates/async-each": "^1.0.1",
|
|
37
37
|
"@vates/task": "^0.6.1",
|
|
38
38
|
"@vates/types": "^1.15.0",
|
|
39
|
-
"@xen-orchestra/backups": "^0.67.
|
|
39
|
+
"@xen-orchestra/backups": "^0.67.1",
|
|
40
40
|
"@xen-orchestra/log": "^0.7.1",
|
|
41
41
|
"@xen-orchestra/xapi": "^8.6.1",
|
|
42
42
|
"complex-matcher": "^1.0.0",
|