@xen-orchestra/rest-api 0.8.0 → 0.9.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 +2 -1
- package/dist/abstract-classes/base-controller.mjs +14 -2
- package/dist/alarms/alarm.controller.mjs +3 -2
- package/dist/groups/group.controller.mjs +3 -2
- package/dist/helpers/cache.helper.mjs +52 -0
- package/dist/helpers/stream.helper.mjs +5 -0
- package/dist/helpers/utils.helper.mjs +3 -0
- package/dist/hosts/host.controller.mjs +3 -2
- package/dist/index.mjs +1 -1
- package/dist/ioc/ioc.mjs +8 -0
- package/dist/messages/message.controller.mjs +3 -2
- package/dist/middlewares/generic-error-handler.middleware.mjs +5 -1
- package/dist/networks/network.controller.mjs +18 -4
- package/dist/open-api/common/response.common.mjs +1 -1
- package/dist/open-api/oa-examples/pci.oa-example.mjs +30 -0
- package/dist/open-api/oa-examples/pgpu.oa-example.mjs +36 -0
- package/dist/open-api/oa-examples/schedule.oa-example.mjs +3 -0
- package/dist/open-api/oa-examples/vm-controller.oa-example.mjs +1 -1
- package/dist/open-api/oa-examples/xoa.oa-example.mjs +61 -0
- package/dist/open-api/routes/routes.js +589 -23
- package/dist/pcis/pci.controller.mjs +60 -0
- package/dist/pgpus/pgpu.controller.mjs +60 -0
- package/dist/pifs/pif.controller.mjs +3 -2
- package/dist/pools/pool.controller.mjs +136 -4
- package/dist/pools/pool.type.mjs +1 -0
- package/dist/schedules/schedule.controller.mjs +5 -4
- package/dist/servers/server.controller.mjs +19 -6
- package/dist/srs/sr.controller.mjs +3 -2
- package/dist/users/user.controller.mjs +3 -2
- package/dist/vbds/vbd.controller.mjs +3 -2
- package/dist/vdi-snapshots/vdi-snapshot.controller.mjs +3 -2
- package/dist/vdis/vdi.controller.mjs +3 -2
- package/dist/vifs/vif.controller.mjs +3 -2
- package/dist/vm-controller/vm-controller.controller.mjs +3 -2
- package/dist/vm-snapshots/vm-snapshot.controller.mjs +3 -2
- package/dist/vm-templates/vm-template.controller.mjs +3 -2
- package/dist/vms/vm.controller.mjs +72 -9
- package/dist/xoa/xoa.controller.mjs +39 -0
- package/dist/xoa/xoa.service.mjs +407 -0
- package/dist/xoa/xoa.type.mjs +1 -0
- package/open-api/spec/swagger.json +4611 -2867
- package/package.json +10 -4
package/README.md
CHANGED
|
@@ -42,13 +42,14 @@ class Foo extends Controller {
|
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
|
-
* any jsdoc
|
|
45
|
+
* any jsdoc annotations
|
|
46
46
|
* @example id 1234
|
|
47
47
|
*/
|
|
48
48
|
@Example(['foo', 'bar'])
|
|
49
49
|
@Get('{id}')
|
|
50
50
|
@Security('*')
|
|
51
51
|
@Middlewares(json())
|
|
52
|
+
@Tags('foo')
|
|
52
53
|
@SuccessResponse(202)
|
|
53
54
|
@Response(404)
|
|
54
55
|
getFoo(@Path() id: string) {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { Controller } from 'tsoa';
|
|
2
|
+
import { Readable } from 'node:stream';
|
|
2
3
|
import { BASE_URL } from '../index.mjs';
|
|
4
|
+
import { makeNdJsonStream } from '../helpers/stream.helper.mjs';
|
|
3
5
|
import { makeObjectMapper } from '../helpers/object-wrapper.helper.mjs';
|
|
4
6
|
const noop = () => { };
|
|
7
|
+
const NDJSON_CONTENT_TYPE = 'application/x-ndjson';
|
|
5
8
|
export class BaseController extends Controller {
|
|
6
9
|
restApi;
|
|
7
10
|
constructor(restApi) {
|
|
@@ -11,7 +14,16 @@ export class BaseController extends Controller {
|
|
|
11
14
|
sendObjects(objects, req) {
|
|
12
15
|
const mapper = makeObjectMapper(req);
|
|
13
16
|
const mappedObjects = objects.map(mapper);
|
|
14
|
-
|
|
17
|
+
if (req.query.ndjson === 'true') {
|
|
18
|
+
const res = req.res;
|
|
19
|
+
res.setHeader('Content-Type', NDJSON_CONTENT_TYPE);
|
|
20
|
+
const stream = Readable.from(makeNdJsonStream(mappedObjects));
|
|
21
|
+
stream.pipe(res);
|
|
22
|
+
return stream;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
return mappedObjects;
|
|
26
|
+
}
|
|
15
27
|
}
|
|
16
28
|
/**
|
|
17
29
|
* statusCode must represent the status code in case of a synchronous request. Default 200
|
|
@@ -20,7 +32,7 @@ export class BaseController extends Controller {
|
|
|
20
32
|
taskProperties.name = 'REST API: ' + taskProperties.name;
|
|
21
33
|
taskProperties.type = 'xo:rest-api:action';
|
|
22
34
|
const task = this.restApi.tasks.create(taskProperties);
|
|
23
|
-
const pResult = task.run(cb);
|
|
35
|
+
const pResult = task.run(() => cb(task));
|
|
24
36
|
if (sync) {
|
|
25
37
|
this.setStatus(statusCode);
|
|
26
38
|
return pResult;
|
|
@@ -94,7 +94,7 @@ let AlarmController = class AlarmController extends XapiXoController {
|
|
|
94
94
|
* @example filter "body:name:physical_utilisation"
|
|
95
95
|
* @example limit 42
|
|
96
96
|
*/
|
|
97
|
-
getAlarms(req, fields, filter, limit) {
|
|
97
|
+
getAlarms(req, fields, ndjson, filter, limit) {
|
|
98
98
|
return this.sendObjects(Object.values(this.getObjects({ filter, limit })), req);
|
|
99
99
|
}
|
|
100
100
|
/**
|
|
@@ -111,7 +111,8 @@ __decorate([
|
|
|
111
111
|
__param(0, Request()),
|
|
112
112
|
__param(1, Query()),
|
|
113
113
|
__param(2, Query()),
|
|
114
|
-
__param(3, Query())
|
|
114
|
+
__param(3, Query()),
|
|
115
|
+
__param(4, Query())
|
|
115
116
|
], AlarmController.prototype, "getAlarms", null);
|
|
116
117
|
__decorate([
|
|
117
118
|
Example(alarm),
|
|
@@ -25,7 +25,7 @@ let GroupController = class GroupController extends XoController {
|
|
|
25
25
|
* @example filter "users:length:>0"
|
|
26
26
|
* @example limit 42
|
|
27
27
|
*/
|
|
28
|
-
async getGroups(req, fields, filter, limit) {
|
|
28
|
+
async getGroups(req, fields, ndjson, filter, limit) {
|
|
29
29
|
return this.sendObjects(Object.values(await this.getObjects({ filter, limit })), req);
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
@@ -42,7 +42,8 @@ __decorate([
|
|
|
42
42
|
__param(0, Request()),
|
|
43
43
|
__param(1, Query()),
|
|
44
44
|
__param(2, Query()),
|
|
45
|
-
__param(3, Query())
|
|
45
|
+
__param(3, Query()),
|
|
46
|
+
__param(4, Query())
|
|
46
47
|
], GroupController.prototype, "getGroups", null);
|
|
47
48
|
__decorate([
|
|
48
49
|
Example(group),
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* If the value is cached and not expired, it will return
|
|
4
|
+
* the cached value immediately. If expired or not present, it will invoke the provided
|
|
5
|
+
* function to fetch the value, cache it, and return it.
|
|
6
|
+
*
|
|
7
|
+
* The function also handles timeout for fetching the value, ensuring that if fetching
|
|
8
|
+
* takes too long, it resolves to `undefined` or returns the expired value based on the
|
|
9
|
+
* cache's state.
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
export async function getFromAsyncCache(cache, key, fn, { expiresIn = 60000, timeout = 5000, forceRefresh = false } = {}) {
|
|
13
|
+
if (forceRefresh) {
|
|
14
|
+
cache.delete(key);
|
|
15
|
+
}
|
|
16
|
+
const { current, expires } = cache.get(key) ?? {};
|
|
17
|
+
if (current === undefined || (expires ?? 0) < Date.now()) {
|
|
18
|
+
const _promise = fn();
|
|
19
|
+
const promise = _promise.then(result => {
|
|
20
|
+
cache.set(key, {
|
|
21
|
+
current: result,
|
|
22
|
+
expires: Date.now() + expiresIn,
|
|
23
|
+
previous: undefined,
|
|
24
|
+
});
|
|
25
|
+
return result;
|
|
26
|
+
});
|
|
27
|
+
cache.set(key, {
|
|
28
|
+
current: promise,
|
|
29
|
+
previous: current,
|
|
30
|
+
expires: undefined,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
let timeoutId;
|
|
34
|
+
const timeoutPromise = new Promise((resolve, reject) => (timeoutId = setTimeout(() => reject(new Error('Promise timed out', { cause: 'ERR_TIMEOUT' })), timeout)));
|
|
35
|
+
const result = {};
|
|
36
|
+
try {
|
|
37
|
+
result.value = await Promise.race([timeoutPromise, cache.get(key).current]);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
if (error instanceof Error && error.cause !== 'ERR_TIMEOUT') {
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
result.value = await cache.get(key).previous;
|
|
44
|
+
if (result.value !== undefined) {
|
|
45
|
+
result.isExpired = true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
clearTimeout(timeoutId);
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export const isSrWritable = (sr) => sr.content_type !== 'iso' && sr.size > 0;
|
|
2
|
+
export const isReplicaVm = (vm) => 'start' in vm.blockedOperations && vm.other['xo:backup:job'] !== undefined;
|
|
3
|
+
export const vmContainsNoBakTag = (vm) => vm.tags.some(t => t.split('=', 1)[0] === 'xo:no-bak');
|
|
@@ -23,7 +23,7 @@ let HostController = class HostController extends XapiXoController {
|
|
|
23
23
|
* @example filter "productBrand:XCP-ng"
|
|
24
24
|
* @example limit 42
|
|
25
25
|
*/
|
|
26
|
-
getHosts(req, fields, filter, limit) {
|
|
26
|
+
getHosts(req, fields, ndjson, filter, limit) {
|
|
27
27
|
return this.sendObjects(Object.values(this.getObjects({ filter, limit })), req);
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
@@ -47,7 +47,8 @@ __decorate([
|
|
|
47
47
|
__param(0, Request()),
|
|
48
48
|
__param(1, Query()),
|
|
49
49
|
__param(2, Query()),
|
|
50
|
-
__param(3, Query())
|
|
50
|
+
__param(3, Query()),
|
|
51
|
+
__param(4, Query())
|
|
51
52
|
], HostController.prototype, "getHosts", null);
|
|
52
53
|
__decorate([
|
|
53
54
|
Example(host),
|
package/dist/index.mjs
CHANGED
|
@@ -32,7 +32,7 @@ const SWAGGER_UI_OPTIONS = {
|
|
|
32
32
|
export default function setupRestApi(express, xoApp) {
|
|
33
33
|
setupContainer(xoApp);
|
|
34
34
|
RegisterRoutes(express);
|
|
35
|
-
// do not register the doc at the root level, or it may lead to
|
|
35
|
+
// do not register the doc at the root level, or it may lead to unwanted behaviour
|
|
36
36
|
// uncomment when all endpoints are migrated to this API
|
|
37
37
|
// express.get('/rest/v0', (_req, res) => res.redirect('/rest/v0/docs'))
|
|
38
38
|
express.use(`${BASE_URL}/docs`, swaggerUi.serve, swaggerUi.setup(swaggerOpenApiSpec, SWAGGER_UI_OPTIONS));
|
package/dist/ioc/ioc.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { buildProviderModule } from 'inversify-binding-decorators';
|
|
|
2
2
|
import { Container, decorate, injectable } from 'inversify';
|
|
3
3
|
import { Controller } from 'tsoa';
|
|
4
4
|
import { RestApi } from '../rest-api/rest-api.mjs';
|
|
5
|
+
import { XoaService } from '../xoa/xoa.service.mjs';
|
|
5
6
|
const iocContainer = new Container();
|
|
6
7
|
decorate(injectable(), Controller);
|
|
7
8
|
iocContainer.load(buildProviderModule());
|
|
@@ -13,5 +14,12 @@ export function setupContainer(xoApp) {
|
|
|
13
14
|
.bind(RestApi)
|
|
14
15
|
.toDynamicValue(() => new RestApi(xoApp))
|
|
15
16
|
.inSingletonScope();
|
|
17
|
+
iocContainer
|
|
18
|
+
.bind(XoaService)
|
|
19
|
+
.toDynamicValue(ctx => {
|
|
20
|
+
const restApi = ctx.container.get(RestApi);
|
|
21
|
+
return new XoaService(restApi);
|
|
22
|
+
})
|
|
23
|
+
.inSingletonScope();
|
|
16
24
|
}
|
|
17
25
|
export { iocContainer };
|
|
@@ -47,7 +47,7 @@ let MessageController = class MessageController extends XapiXoController {
|
|
|
47
47
|
* @example filter "name:VM_STARTED"
|
|
48
48
|
* @example limit 42
|
|
49
49
|
*/
|
|
50
|
-
getMessages(req, fields, filter, limit) {
|
|
50
|
+
getMessages(req, fields, ndjson, filter, limit) {
|
|
51
51
|
return this.sendObjects(Object.values(this.getObjects({ filter, limit })), req);
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
@@ -64,7 +64,8 @@ __decorate([
|
|
|
64
64
|
__param(0, Request()),
|
|
65
65
|
__param(1, Query()),
|
|
66
66
|
__param(2, Query()),
|
|
67
|
-
__param(3, Query())
|
|
67
|
+
__param(3, Query()),
|
|
68
|
+
__param(4, Query())
|
|
68
69
|
], MessageController.prototype, "getMessages", null);
|
|
69
70
|
__decorate([
|
|
70
71
|
Example(message),
|
|
@@ -13,9 +13,13 @@ export default function genericErrorHandler(error, req, res, _next) {
|
|
|
13
13
|
if (noSuchObject.is(error)) {
|
|
14
14
|
res.status(404);
|
|
15
15
|
}
|
|
16
|
-
else if (unauthorized.is(error) || forbiddenOperation.is(error)
|
|
16
|
+
else if (unauthorized.is(error) || forbiddenOperation.is(error)) {
|
|
17
17
|
res.status(403);
|
|
18
18
|
}
|
|
19
|
+
else if (featureUnauthorized.is(error)) {
|
|
20
|
+
res.status(403);
|
|
21
|
+
responseError.data = error.data;
|
|
22
|
+
}
|
|
19
23
|
else if (invalidCredentials.is(error)) {
|
|
20
24
|
res.status(401);
|
|
21
25
|
}
|
|
@@ -7,11 +7,11 @@ 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, Response, Request, Route, Security, Tags } from 'tsoa';
|
|
10
|
+
import { Example, Get, Path, Query, Response, Request, Route, Security, Tags, Delete, SuccessResponse } from 'tsoa';
|
|
11
11
|
import { inject } from 'inversify';
|
|
12
12
|
import { provide } from 'inversify-binding-decorators';
|
|
13
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';
|
|
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 { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs';
|
|
17
17
|
let NetworkController = class NetworkController extends XapiXoController {
|
|
@@ -23,7 +23,7 @@ let NetworkController = class NetworkController extends XapiXoController {
|
|
|
23
23
|
* @example filter "nbd?"
|
|
24
24
|
* @example limit 42
|
|
25
25
|
*/
|
|
26
|
-
getNetworks(req, fields, filter, limit) {
|
|
26
|
+
getNetworks(req, fields, ndjson, filter, limit) {
|
|
27
27
|
return this.sendObjects(Object.values(this.getObjects({ filter, limit })), req);
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
@@ -32,6 +32,13 @@ let NetworkController = class NetworkController extends XapiXoController {
|
|
|
32
32
|
getNetwork(id) {
|
|
33
33
|
return this.getObject(id);
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* @example id "593c39a5-9c56-28eb-969b-255b2f53791b"
|
|
37
|
+
*/
|
|
38
|
+
async deleteNetwork(id) {
|
|
39
|
+
const networkId = id;
|
|
40
|
+
await this.getXapiObject(networkId).$xapi.deleteNetwork(networkId);
|
|
41
|
+
}
|
|
35
42
|
};
|
|
36
43
|
__decorate([
|
|
37
44
|
Example(networkIds),
|
|
@@ -40,7 +47,8 @@ __decorate([
|
|
|
40
47
|
__param(0, Request()),
|
|
41
48
|
__param(1, Query()),
|
|
42
49
|
__param(2, Query()),
|
|
43
|
-
__param(3, Query())
|
|
50
|
+
__param(3, Query()),
|
|
51
|
+
__param(4, Query())
|
|
44
52
|
], NetworkController.prototype, "getNetworks", null);
|
|
45
53
|
__decorate([
|
|
46
54
|
Example(network),
|
|
@@ -48,6 +56,12 @@ __decorate([
|
|
|
48
56
|
Response(notFoundResp.status, notFoundResp.description),
|
|
49
57
|
__param(0, Path())
|
|
50
58
|
], NetworkController.prototype, "getNetwork", null);
|
|
59
|
+
__decorate([
|
|
60
|
+
Delete('{id}'),
|
|
61
|
+
SuccessResponse(noContentResp.status, noContentResp.description),
|
|
62
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
63
|
+
__param(0, Path())
|
|
64
|
+
], NetworkController.prototype, "deleteNetwork", null);
|
|
51
65
|
NetworkController = __decorate([
|
|
52
66
|
Route('networks'),
|
|
53
67
|
Security('*'),
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const pciIds = [
|
|
2
|
+
'/rest/v0/pcis/9377b642-cc71-8749-1e71-308898b652da',
|
|
3
|
+
'/rest/v0/pcis/9de8f35c-5b51-e8b6-5f48-0942231f8610',
|
|
4
|
+
];
|
|
5
|
+
export const partialPcis = [
|
|
6
|
+
{
|
|
7
|
+
class_name: 'Non-Volatile memory controller',
|
|
8
|
+
device_name: 'XG5 NVMe SSD Controller',
|
|
9
|
+
id: '9377b642-cc71-8749-1e71-308898b652da',
|
|
10
|
+
href: '/rest/v0/pcis/9377b642-cc71-8749-1e71-308898b652da',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
class_name: 'Non-Volatile memory controller',
|
|
14
|
+
device_name: 'XG5 NVMe SSD Controller',
|
|
15
|
+
id: '9de8f35c-5b51-e8b6-5f48-0942231f8610',
|
|
16
|
+
href: '/rest/v0/pcis/9de8f35c-5b51-e8b6-5f48-0942231f8610',
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
export const pci = {
|
|
20
|
+
type: 'PCI',
|
|
21
|
+
class_name: 'Non-Volatile memory controller',
|
|
22
|
+
device_name: 'XG5 NVMe SSD Controller',
|
|
23
|
+
pci_id: '0000:0d:00.0',
|
|
24
|
+
$host: '669df518-4e5d-4d84-b93a-9be2cdcdfca1',
|
|
25
|
+
id: '9377b642-cc71-8749-1e71-308898b652da',
|
|
26
|
+
uuid: '9377b642-cc71-8749-1e71-308898b652da',
|
|
27
|
+
$pool: 'b7569d99-30f8-178a-7d94-801de3e29b5b',
|
|
28
|
+
$poolId: 'b7569d99-30f8-178a-7d94-801de3e29b5b',
|
|
29
|
+
_xapiRef: 'OpaqueRef:783001df-4ab3-1c47-be37-7d9314337577',
|
|
30
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const pgpuIds = [
|
|
2
|
+
'/rest/v0/pgpus/838335fa-ee21-15e1-760a-a37a3a4ef1db',
|
|
3
|
+
'/rest/v0/pgpus/4062d698-50aa-c53a-9974-9806bb38bf8d',
|
|
4
|
+
];
|
|
5
|
+
export const partialPgpus = [
|
|
6
|
+
{
|
|
7
|
+
id: '838335fa-ee21-15e1-760a-a37a3a4ef1db',
|
|
8
|
+
dom0Access: 'enabled',
|
|
9
|
+
gpuGroup: '8f77aa2b-db69-a6b7-b36e-597aafe40f05',
|
|
10
|
+
href: '/rest/v0/pgpus/838335fa-ee21-15e1-760a-a37a3a4ef1db',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
id: '4062d698-50aa-c53a-9974-9806bb38bf8d',
|
|
14
|
+
dom0Access: 'enabled',
|
|
15
|
+
gpuGroup: '8f77aa2b-db69-a6b7-b36e-597aafe40f05',
|
|
16
|
+
href: '/rest/v0/pgpus/4062d698-50aa-c53a-9974-9806bb38bf8d',
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
export const pgpu = {
|
|
20
|
+
type: 'PGPU',
|
|
21
|
+
dom0Access: 'enabled',
|
|
22
|
+
enabledVgpuTypes: [],
|
|
23
|
+
gpuGroup: '8f77aa2b-db69-a6b7-b36e-597aafe40f05',
|
|
24
|
+
isSystemDisplayDevice: true,
|
|
25
|
+
pci: '8b515224-0c6c-c498-5ece-39f64d9b7b20',
|
|
26
|
+
supportedVgpuTypes: [],
|
|
27
|
+
host: '84e555d8-267a-4720-aa5f-fd19035aadae',
|
|
28
|
+
$host: '84e555d8-267a-4720-aa5f-fd19035aadae',
|
|
29
|
+
vgpus: [],
|
|
30
|
+
$vgpus: [],
|
|
31
|
+
id: '838335fa-ee21-15e1-760a-a37a3a4ef1db',
|
|
32
|
+
uuid: '838335fa-ee21-15e1-760a-a37a3a4ef1db',
|
|
33
|
+
$pool: 'b7569d99-30f8-178a-7d94-801de3e29b5b',
|
|
34
|
+
$poolId: 'b7569d99-30f8-178a-7d94-801de3e29b5b',
|
|
35
|
+
_xapiRef: 'OpaqueRef:c842190a-381d-1616-f363-c031a54c3526',
|
|
36
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export const xoaDashboard = {
|
|
2
|
+
nPools: 2,
|
|
3
|
+
nHosts: 5,
|
|
4
|
+
backupRepositories: {
|
|
5
|
+
s3: {
|
|
6
|
+
size: {
|
|
7
|
+
backups: 286295393792,
|
|
8
|
+
},
|
|
9
|
+
},
|
|
10
|
+
other: {
|
|
11
|
+
size: {
|
|
12
|
+
available: 62630354944,
|
|
13
|
+
backups: 20684251648,
|
|
14
|
+
other: 66875031040,
|
|
15
|
+
total: 150189637632,
|
|
16
|
+
used: 87559282688,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
resourcesOverview: {
|
|
21
|
+
nCpus: 52,
|
|
22
|
+
memorySize: 107374182400,
|
|
23
|
+
srSize: 751123595264,
|
|
24
|
+
},
|
|
25
|
+
poolsStatus: {
|
|
26
|
+
connected: 2,
|
|
27
|
+
unreachable: 7,
|
|
28
|
+
unknown: 0,
|
|
29
|
+
},
|
|
30
|
+
nHostsEol: 0,
|
|
31
|
+
missingPatches: {
|
|
32
|
+
hasAuthorization: true,
|
|
33
|
+
nHostsFailed: 1,
|
|
34
|
+
nHostsWithMissingPatches: 4,
|
|
35
|
+
nPoolsWithMissingPatches: 2,
|
|
36
|
+
},
|
|
37
|
+
storageRepositories: {
|
|
38
|
+
size: {
|
|
39
|
+
available: 628454834176,
|
|
40
|
+
other: 122641256960,
|
|
41
|
+
replicated: 27504128,
|
|
42
|
+
total: 751123595264,
|
|
43
|
+
used: 122668761088,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
backups: {
|
|
47
|
+
jobs: {
|
|
48
|
+
disabled: 8,
|
|
49
|
+
failed: 0,
|
|
50
|
+
skipped: 0,
|
|
51
|
+
successful: 0,
|
|
52
|
+
total: 8,
|
|
53
|
+
},
|
|
54
|
+
issues: [],
|
|
55
|
+
vmsProtection: {
|
|
56
|
+
protected: 0,
|
|
57
|
+
unprotected: 0,
|
|
58
|
+
notInJob: 20,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
};
|