@xen-orchestra/rest-api 0.2.0 → 0.4.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.
@@ -7,10 +7,10 @@ export class XapiXoController extends BaseController {
7
7
  this.#type = type;
8
8
  }
9
9
  getObjects({ filter, limit } = {}) {
10
- if (filter !== undefined) {
10
+ if (filter !== undefined && typeof filter === 'string') {
11
11
  filter = CM.parse(filter).createPredicate();
12
12
  }
13
- return this.restApi.getObjectsByType(this.#type, { filter, limit });
13
+ return this.restApi.getObjectsByType(this.#type, { filter: filter, limit });
14
14
  }
15
15
  getObject(id) {
16
16
  return this.restApi.getObject(id, this.#type);
@@ -0,0 +1,130 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
+ return function (target, key) { decorator(target, key, paramIndex); }
9
+ };
10
+ import * as CM from 'complex-matcher';
11
+ import { Example, Get, Path, Query, Request, Response, Route, Security, Tags } from 'tsoa';
12
+ import { inject } from 'inversify';
13
+ import { noSuchObject } from 'xo-common/api-errors.js';
14
+ import { provide } from 'inversify-binding-decorators';
15
+ import { alarm, alarmIds, partialAlarms } from '../open-api/oa-examples/alarm.oa-example.mjs';
16
+ import { BASE_URL } from '../index.mjs';
17
+ import { notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
18
+ import { RestApi } from '../rest-api/rest-api.mjs';
19
+ import { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs';
20
+ // 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>';
21
+ const ALARM_BODY_REGEX = /^value:\s*(Infinity|NaN|-Infinity|\d+(?:\.\d+)?)\s*config:\s*<variable>\s*<name value="(.*?)"/;
22
+ const ALARM_NAMES = ['ALARM', 'BOND_STATUS_CHANGED', 'MULTIPATH_PERIODIC_ALERT'];
23
+ export const alarmPredicate = CM.parse(`name:|(${ALARM_NAMES.join(' ')})`).createPredicate();
24
+ let AlarmController = class AlarmController extends XapiXoController {
25
+ constructor(restApi) {
26
+ super('message', restApi);
27
+ }
28
+ #parseAlarm({ $object, body, ...alarm }) {
29
+ let object;
30
+ try {
31
+ object = this.restApi.getObject($object);
32
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
33
+ }
34
+ catch (err) {
35
+ object = {
36
+ type: 'unknown',
37
+ uuid: $object,
38
+ };
39
+ }
40
+ let href;
41
+ if (object.type !== 'unknown') {
42
+ href = `${BASE_URL}/${object.type.toLowerCase() + 's'}/${object.uuid}`;
43
+ }
44
+ const [, value, name] = body.match(ALARM_BODY_REGEX) ?? [];
45
+ return {
46
+ ...alarm,
47
+ body: {
48
+ value, // Keep the value as a string because NaN, Infinity, -Infinity is not valid JSON
49
+ name: name ?? body, // for 'BOND_STATUS_CHANGED' and 'MULTIPATH_PERIODIC_ALERT', body is a non-xml string. ("body": "The status of the eth0+eth1 bond is: 1/2 up")
50
+ },
51
+ object: {
52
+ type: object.type,
53
+ uuid: object.uuid,
54
+ href,
55
+ },
56
+ };
57
+ }
58
+ /**
59
+ * Override parent getObjects in order to only get `ALARM` messages
60
+ */
61
+ getObjects({ filter, limit = Infinity } = {}) {
62
+ const rawAlarms = this.restApi.getObjectsByType('message', {
63
+ filter: alarmPredicate,
64
+ });
65
+ let userFilter = () => true;
66
+ if (filter !== undefined) {
67
+ userFilter = CM.parse(filter).createPredicate();
68
+ }
69
+ const alarms = {};
70
+ for (const id in rawAlarms) {
71
+ if (limit === 0) {
72
+ break;
73
+ }
74
+ const alarm = this.#parseAlarm(rawAlarms[id]);
75
+ if (userFilter(alarm)) {
76
+ alarms[id] = alarm;
77
+ limit--;
78
+ }
79
+ }
80
+ return alarms;
81
+ }
82
+ /**
83
+ * Override parent getObject in order to only get `ALARM` message
84
+ */
85
+ getObject(id) {
86
+ const maybeAlarm = this.restApi.getObject(id, 'message');
87
+ if (!alarmPredicate(maybeAlarm)) {
88
+ /* throw */ noSuchObject(id, 'alarm');
89
+ }
90
+ return this.#parseAlarm(maybeAlarm);
91
+ }
92
+ /**
93
+ * @example fields "body,id,object"
94
+ * @example filter "body:name:physical_utilisation"
95
+ * @example limit 42
96
+ */
97
+ getAlarms(req, fields, filter, limit) {
98
+ return this.sendObjects(Object.values(this.getObjects({ filter, limit })), req);
99
+ }
100
+ /**
101
+ * @example id "0c98c71c-2f9c-d5c2-b9b6-2c8371730eab"
102
+ */
103
+ getAlarm(id) {
104
+ return this.getObject(id);
105
+ }
106
+ };
107
+ __decorate([
108
+ Example(alarmIds),
109
+ Example(partialAlarms),
110
+ Get(''),
111
+ __param(0, Request()),
112
+ __param(1, Query()),
113
+ __param(2, Query()),
114
+ __param(3, Query())
115
+ ], AlarmController.prototype, "getAlarms", null);
116
+ __decorate([
117
+ Example(alarm),
118
+ Get('{id}'),
119
+ Response(notFoundResp.status, notFoundResp.description),
120
+ __param(0, Path())
121
+ ], AlarmController.prototype, "getAlarm", null);
122
+ AlarmController = __decorate([
123
+ Route('alarms'),
124
+ Security('*'),
125
+ Response(unauthorizedResp.status, unauthorizedResp.description),
126
+ Tags('alarms'),
127
+ provide(AlarmController),
128
+ __param(0, inject(RestApi))
129
+ ], AlarmController);
130
+ export { AlarmController };
package/dist/index.mjs CHANGED
@@ -9,13 +9,33 @@ import { setupContainer } from './ioc/ioc.mjs';
9
9
  const require = createRequire(import.meta.url);
10
10
  const swaggerOpenApiSpec = require('../open-api/spec/swagger.json');
11
11
  export const BASE_URL = '/rest/v0';
12
+ const SWAGGER_UI_OPTIONS = {
13
+ swaggerOptions: {
14
+ displayRequestDuration: true,
15
+ docExpansion: 'none', // collapse all tags by default
16
+ filter: true, // add a tags searchbar,
17
+ tagsSorter: 'alpha',
18
+ operationsSorter: (prev, next) => {
19
+ // sort endpoints inside a tag alphabetically > HTTP verb
20
+ const pathComparison = prev.get('path').localeCompare(next.get('path'));
21
+ if (pathComparison !== 0) {
22
+ return pathComparison;
23
+ }
24
+ const METHOD_ORDER = { get: 1, post: 2, put: 3, delete: 4, patch: 5 };
25
+ const prevMethod = METHOD_ORDER[prev.get('method')];
26
+ const nextMethod = METHOD_ORDER[next.get('method')];
27
+ return prevMethod - nextMethod;
28
+ },
29
+ requestSnippetsEnabled: true, // add more snippets (bash, PowerShell, CMD)
30
+ },
31
+ };
12
32
  export default function setupRestApi(express, xoApp) {
13
33
  setupContainer(xoApp);
14
34
  RegisterRoutes(express);
15
35
  // do not register the doc at the root level, or it may lead to unwated behaviour
16
36
  // uncomment when all endpoints are migrated to this API
17
37
  // express.get('/rest/v0', (_req, res) => res.redirect('/rest/v0/docs'))
18
- express.use(`${BASE_URL}/docs`, swaggerUi.serve, swaggerUi.setup(swaggerOpenApiSpec));
38
+ express.use(`${BASE_URL}/docs`, swaggerUi.serve, swaggerUi.setup(swaggerOpenApiSpec, SWAGGER_UI_OPTIONS));
19
39
  express.use(BASE_URL, tsoaToXoErrorHandler);
20
40
  express.use(BASE_URL, genericErrorHandler);
21
41
  }
@@ -0,0 +1,83 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
+ return function (target, key) { decorator(target, key, paramIndex); }
9
+ };
10
+ import * as CM from 'complex-matcher';
11
+ import { Example, Get, Path, Query, Request, Response, Route, Security, Tags } from 'tsoa';
12
+ import { inject } from 'inversify';
13
+ import { noSuchObject } from 'xo-common/api-errors.js';
14
+ import { provide } from 'inversify-binding-decorators';
15
+ import { alarmPredicate } from '../alarms/alarm.controller.mjs';
16
+ import { message, messageIds, partialMessages } from '../open-api/oa-examples/message.oa-example.mjs';
17
+ import { RestApi } from '../rest-api/rest-api.mjs';
18
+ import { notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
19
+ import { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs';
20
+ let MessageController = class MessageController extends XapiXoController {
21
+ constructor(restapi) {
22
+ super('message', restapi);
23
+ }
24
+ /**
25
+ * Override parent getObjects in order to exclude `ALARM` messages
26
+ */
27
+ getObjects({ filter, limit = Infinity } = {}) {
28
+ let userfilter = () => true;
29
+ if (filter !== undefined) {
30
+ userfilter = CM.parse(filter).createPredicate();
31
+ }
32
+ const messagePredicate = (obj) => !alarmPredicate(obj) && userfilter(obj);
33
+ return super.getObjects({ filter: messagePredicate, limit });
34
+ }
35
+ /**
36
+ * Override parent getObject in order to exclude`ALARM` message
37
+ */
38
+ getObject(id) {
39
+ const message = super.getObject(id);
40
+ if (alarmPredicate(message)) {
41
+ /* throw */ noSuchObject(id, 'message');
42
+ }
43
+ return message;
44
+ }
45
+ /**
46
+ * @example fields "name,body,id,$object"
47
+ * @example filter "name:VM_STARTED"
48
+ * @example limit 42
49
+ */
50
+ getMessages(req, fields, filter, limit) {
51
+ return this.sendObjects(Object.values(this.getObjects({ filter, limit })), req);
52
+ }
53
+ /**
54
+ * @example id "f775eaeb-abe5-94e0-9682-14c37c3a1dfe"
55
+ */
56
+ getMessage(id) {
57
+ return this.getObject(id);
58
+ }
59
+ };
60
+ __decorate([
61
+ Example(messageIds),
62
+ Example(partialMessages),
63
+ Get(''),
64
+ __param(0, Request()),
65
+ __param(1, Query()),
66
+ __param(2, Query()),
67
+ __param(3, Query())
68
+ ], MessageController.prototype, "getMessages", null);
69
+ __decorate([
70
+ Example(message),
71
+ Get('{id}'),
72
+ Response(notFoundResp.status, notFoundResp.description),
73
+ __param(0, Path())
74
+ ], MessageController.prototype, "getMessage", null);
75
+ MessageController = __decorate([
76
+ Route('messages'),
77
+ Security('*'),
78
+ Response(unauthorizedResp.status, unauthorizedResp.description),
79
+ Tags('message'),
80
+ provide(MessageController),
81
+ __param(0, inject(RestApi))
82
+ ], MessageController);
83
+ export { MessageController };
@@ -7,6 +7,10 @@ export const unauthorizedResp = {
7
7
  status: 401,
8
8
  description: 'Authentication required',
9
9
  };
10
+ export const featureUnauthorized = {
11
+ status: 403,
12
+ description: 'Feature unauthorized',
13
+ };
10
14
  export const notFoundResp = {
11
15
  status: 404,
12
16
  description: 'Resource not found',
@@ -0,0 +1,49 @@
1
+ export const alarmIds = [
2
+ '/rest/v0/alarms/0c98c71c-2f9c-d5c2-b9b6-2c8371730eab',
3
+ '/rest/v0/alarms/6a4cc401-6cba-0d41-3b02-b848c5017343',
4
+ ];
5
+ export const partialAlarms = [
6
+ {
7
+ body: {
8
+ value: '0.0',
9
+ name: 'physical_utilisation',
10
+ },
11
+ id: '0c98c71c-2f9c-d5c2-b9b6-2c8371730eab',
12
+ object: {
13
+ type: 'unknown',
14
+ uuid: '3f607494-26f1-b328-b626-d81cf007de37',
15
+ },
16
+ href: '/rest/v0/alarms/0c98c71c-2f9c-d5c2-b9b6-2c8371730eab',
17
+ },
18
+ {
19
+ body: {
20
+ value: '0.2',
21
+ name: 'physical_utilisation',
22
+ },
23
+ id: '6a4cc401-6cba-0d41-3b02-b848c5017343',
24
+ object: {
25
+ type: 'SR',
26
+ uuid: '8aa2fb4a-143e-c2bc-05d4-c68bbb101d41',
27
+ href: '/rest/v0/srs/8aa2fb4a-143e-c2bc-05d4-c68bbb101d41',
28
+ },
29
+ href: '/rest/v0/alarms/6a4cc401-6cba-0d41-3b02-b848c5017343',
30
+ },
31
+ ];
32
+ export const alarm = {
33
+ name: 'ALARM',
34
+ time: 1724862780,
35
+ type: 'message',
36
+ uuid: '0c98c71c-2f9c-d5c2-b9b6-2c8371730eab',
37
+ $pool: 'b7569d99-30f8-178a-7d94-801de3e29b5b',
38
+ $poolId: 'b7569d99-30f8-178a-7d94-801de3e29b5b',
39
+ _xapiRef: 'OpaqueRef:87ccf385-4197-11aa-3ca0-32213c4cb56d',
40
+ id: '0c98c71c-2f9c-d5c2-b9b6-2c8371730eab',
41
+ body: {
42
+ value: '0.0',
43
+ name: 'physical_utilisation',
44
+ },
45
+ object: {
46
+ type: 'unknown',
47
+ uuid: '3f607494-26f1-b328-b626-d81cf007de37',
48
+ },
49
+ };
@@ -0,0 +1,32 @@
1
+ export const messageIds = [
2
+ '/rest/v0/messages/f775eaeb-abe5-94e0-9682-14c37c3a1dfe',
3
+ '/rest/v0/messages/ed2d1623-3e65-8d39-7a14-4eb69274c5e3',
4
+ ];
5
+ export const partialMessages = [
6
+ {
7
+ name: 'VM_STARTED',
8
+ body: "VM 'Alpine MRA' (uuid: cef5f68c-61ae-3831-d2e6-1590d4934acf) started on host: XCP 8.3.0 master (uuid: b61a5c92-700e-4966-a13b-00633f03eea8)",
9
+ id: 'f775eaeb-abe5-94e0-9682-14c37c3a1dfe',
10
+ $object: 'cef5f68c-61ae-3831-d2e6-1590d4934acf',
11
+ href: '/rest/v0/messages/f775eaeb-abe5-94e0-9682-14c37c3a1dfe',
12
+ },
13
+ {
14
+ name: 'VM_STARTED',
15
+ body: "VM 'Alpine MRA' (uuid: cef5f68c-61ae-3831-d2e6-1590d4934acf) started on host: XCP 8.3.0 master (uuid: b61a5c92-700e-4966-a13b-00633f03eea8)",
16
+ id: 'ed2d1623-3e65-8d39-7a14-4eb69274c5e3',
17
+ $object: 'cef5f68c-61ae-3831-d2e6-1590d4934acf',
18
+ href: '/rest/v0/messages/ed2d1623-3e65-8d39-7a14-4eb69274c5e3',
19
+ },
20
+ ];
21
+ export const message = {
22
+ body: "VM 'Alpine MRA' (uuid: cef5f68c-61ae-3831-d2e6-1590d4934acf) started on host: XCP 8.3.0 master (uuid: b61a5c92-700e-4966-a13b-00633f03eea8)",
23
+ name: 'VM_STARTED',
24
+ time: 1709908890,
25
+ $object: 'cef5f68c-61ae-3831-d2e6-1590d4934acf',
26
+ id: 'f775eaeb-abe5-94e0-9682-14c37c3a1dfe',
27
+ type: 'message',
28
+ uuid: 'f775eaeb-abe5-94e0-9682-14c37c3a1dfe',
29
+ $pool: 'b7569d99-30f8-178a-7d94-801de3e29b5b',
30
+ $poolId: 'b7569d99-30f8-178a-7d94-801de3e29b5b',
31
+ _xapiRef: 'OpaqueRef:7544478e-84d3-2381-69e7-b0698ab45d9b',
32
+ };
@@ -0,0 +1,70 @@
1
+ export const poolIds = [
2
+ '/rest/v0/pools/b7569d99-30f8-178a-7d94-801de3e29b5b',
3
+ '/rest/v0/pools/355ee47d-ff4c-4924-3db2-fd86ae629676',
4
+ ];
5
+ export const partialPools = [
6
+ {
7
+ auto_poweron: true,
8
+ name_label: 'XCP 8.3.0 XO Team',
9
+ id: 'b7569d99-30f8-178a-7d94-801de3e29b5b',
10
+ href: '/rest/v0/pools/b7569d99-30f8-178a-7d94-801de3e29b5b',
11
+ },
12
+ {
13
+ auto_poweron: true,
14
+ name_label: 'XO Lab',
15
+ id: '355ee47d-ff4c-4924-3db2-fd86ae629676',
16
+ href: '/rest/v0/pools/355ee47d-ff4c-4924-3db2-fd86ae629676',
17
+ },
18
+ ];
19
+ export const pool = {
20
+ auto_poweron: true,
21
+ crashDumpSr: '86a9757d-9c05-9fe0-e79a-8243cb1f37f3',
22
+ current_operations: {},
23
+ default_SR: '86a9757d-9c05-9fe0-e79a-8243cb1f37f3',
24
+ HA_enabled: false,
25
+ haSrs: [],
26
+ master: '438aca0f-429c-4ae6-accc-93c306e636a0',
27
+ tags: [],
28
+ name_description: 'Main Lyon Lab',
29
+ name_label: 'XO Lab',
30
+ xosanPackInstallationTime: null,
31
+ otherConfig: {
32
+ 'xo:clientInfo:v9sc05bvrh': '{"lastConnected":1744102763392,"networkInterfaces":{"wlp58s0":[{"address":"192.168.1.22","netmask":"255.255.255.0","family":"IPv4","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"192.168.1.22/24"},{"address":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b/64","scopeid":0},{"address":"fe80::1d04:d88d:50de:799a","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"fe80::1d04:d88d:50de:799a/64","scopeid":2}],"wg-grenoble":[{"address":"10.200.205.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.205.115/24"}],"wg-lyon":[{"address":"10.200.200.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.200.115/24"}]}}',
33
+ 'xo:clientInfo:218b43e8-5622-4d81-adce-69be4252c4de': '{"lastConnected":1744102538271,"networkInterfaces":{"wlp0s20f3":[{"address":"10.234.213.181","netmask":"255.255.255.0","family":"IPv4","mac":"6a:8e:98:da:15:36","internal":false,"cidr":"10.234.213.181/24"},{"address":"2a0d:e487:319f:7520:16da:8a1a:c6fb:7fc3","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"6a:8e:98:da:15:36","internal":false,"cidr":"2a0d:e487:319f:7520:16da:8a1a:c6fb:7fc3/64","scopeid":0},{"address":"fe80::9400:57c5:e2d:94ff","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"6a:8e:98:da:15:36","internal":false,"cidr":"fe80::9400:57c5:e2d:94ff/64","scopeid":2}],"wg1":[{"address":"10.200.205.81","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.205.81/24"}],"wg0":[{"address":"10.200.200.81","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.200.81/24"}]}}',
34
+ 'xo:clientInfo:1gywgvavm02': '{"lastConnected":1744102486813,"networkInterfaces":{"wlp58s0":[{"address":"192.168.1.22","netmask":"255.255.255.0","family":"IPv4","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"192.168.1.22/24"},{"address":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b/64","scopeid":0},{"address":"fe80::1d04:d88d:50de:799a","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"fe80::1d04:d88d:50de:799a/64","scopeid":2}],"wg-grenoble":[{"address":"10.200.205.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.205.115/24"}],"wg-lyon":[{"address":"10.200.200.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.200.115/24"}]}}',
35
+ 'xo:clientInfo:5vtpi83kh8a': '{"lastConnected":1744102149901,"networkInterfaces":{"wlp58s0":[{"address":"192.168.1.22","netmask":"255.255.255.0","family":"IPv4","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"192.168.1.22/24"},{"address":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b/64","scopeid":0},{"address":"fe80::1d04:d88d:50de:799a","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"fe80::1d04:d88d:50de:799a/64","scopeid":2}],"wg-grenoble":[{"address":"10.200.205.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.205.115/24"}],"wg-lyon":[{"address":"10.200.200.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.200.115/24"}]}}',
36
+ 'xo:clientInfo:t0yxso5g6s': '{"lastConnected":1744101989898,"networkInterfaces":{"wlp58s0":[{"address":"192.168.1.22","netmask":"255.255.255.0","family":"IPv4","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"192.168.1.22/24"},{"address":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b/64","scopeid":0},{"address":"fe80::1d04:d88d:50de:799a","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"fe80::1d04:d88d:50de:799a/64","scopeid":2}],"wg-grenoble":[{"address":"10.200.205.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.205.115/24"}],"wg-lyon":[{"address":"10.200.200.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.200.115/24"}]}}',
37
+ 'xo:clientInfo:0w4we05jsnof': '{"lastConnected":1744101895389,"networkInterfaces":{"wlp58s0":[{"address":"192.168.1.22","netmask":"255.255.255.0","family":"IPv4","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"192.168.1.22/24"},{"address":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b/64","scopeid":0},{"address":"fe80::1d04:d88d:50de:799a","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"fe80::1d04:d88d:50de:799a/64","scopeid":2}],"wg-grenoble":[{"address":"10.200.205.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.205.115/24"}],"wg-lyon":[{"address":"10.200.200.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.200.115/24"}]}}',
38
+ 'xo:clientInfo:wp0r9dsmnbf': '{"lastConnected":1744101746158,"networkInterfaces":{"wlp58s0":[{"address":"192.168.1.22","netmask":"255.255.255.0","family":"IPv4","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"192.168.1.22/24"},{"address":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b/64","scopeid":0},{"address":"fe80::1d04:d88d:50de:799a","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"fe80::1d04:d88d:50de:799a/64","scopeid":2}],"wg-grenoble":[{"address":"10.200.205.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.205.115/24"}],"wg-lyon":[{"address":"10.200.200.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.200.115/24"}]}}',
39
+ 'xo:clientInfo:p7r15qcczse': '{"lastConnected":1744101242926,"networkInterfaces":{"wlp58s0":[{"address":"192.168.1.22","netmask":"255.255.255.0","family":"IPv4","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"192.168.1.22/24"},{"address":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b/64","scopeid":0},{"address":"fe80::1d04:d88d:50de:799a","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"fe80::1d04:d88d:50de:799a/64","scopeid":2}],"wg-grenoble":[{"address":"10.200.205.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.205.115/24"}],"wg-lyon":[{"address":"10.200.200.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.200.115/24"}]}}',
40
+ 'xo:clientInfo:1mnh07a7l2x': '{"lastConnected":1744101089247,"networkInterfaces":{"wlp58s0":[{"address":"192.168.1.22","netmask":"255.255.255.0","family":"IPv4","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"192.168.1.22/24"},{"address":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b/64","scopeid":0},{"address":"fe80::1d04:d88d:50de:799a","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"fe80::1d04:d88d:50de:799a/64","scopeid":2}],"wg-grenoble":[{"address":"10.200.205.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.205.115/24"}],"wg-lyon":[{"address":"10.200.200.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.200.115/24"}]}}',
41
+ 'xo:clientInfo:ou6a9jn1dxa': '{"lastConnected":1744100523539,"networkInterfaces":{"wlp58s0":[{"address":"192.168.1.22","netmask":"255.255.255.0","family":"IPv4","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"192.168.1.22/24"},{"address":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b/64","scopeid":0},{"address":"fe80::1d04:d88d:50de:799a","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"fe80::1d04:d88d:50de:799a/64","scopeid":2}],"wg-grenoble":[{"address":"10.200.205.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.205.115/24"}],"wg-lyon":[{"address":"10.200.200.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.200.115/24"}]}}',
42
+ 'xo:clientInfo:d6363a9d-03e5-f598-ebe6-b98b4fcf4ea6': '{"lastConnected":1744098018490,"networkInterfaces":{"eth0":[{"address":"172.16.210.100","netmask":"255.255.254.0","family":"IPv4","mac":"c2:f3:1b:b6:9f:b1","internal":false,"cidr":"172.16.210.100/23"},{"address":"2a01:240:ab08:4:c0f3:1bff:feb6:9fb1","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"c2:f3:1b:b6:9f:b1","internal":false,"cidr":"2a01:240:ab08:4:c0f3:1bff:feb6:9fb1/64","scopeid":0},{"address":"fe80::c0f3:1bff:feb6:9fb1","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"c2:f3:1b:b6:9f:b1","internal":false,"cidr":"fe80::c0f3:1bff:feb6:9fb1/64","scopeid":2}],"eth1":[{"address":"10.1.0.100","netmask":"255.255.0.0","family":"IPv4","mac":"1e:ba:68:4f:28:82","internal":false,"cidr":"10.1.0.100/16"},{"address":"2a01:240:ab08:5:1::100","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"1e:ba:68:4f:28:82","internal":false,"cidr":"2a01:240:ab08:5:1::100/64","scopeid":0},{"address":"fe80::1cba:68ff:fe4f:2882","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"1e:ba:68:4f:28:82","internal":false,"cidr":"fe80::1cba:68ff:fe4f:2882/64","scopeid":3}]}}',
43
+ 'xo:clientInfo:mz05bzlp2d9': '{"lastConnected":1744096801517,"networkInterfaces":{"wlp58s0":[{"address":"192.168.1.22","netmask":"255.255.255.0","family":"IPv4","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"192.168.1.22/24"},{"address":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b/64","scopeid":0},{"address":"fe80::1d04:d88d:50de:799a","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"fe80::1d04:d88d:50de:799a/64","scopeid":2}],"wg-grenoble":[{"address":"10.200.205.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.205.115/24"}],"wg-lyon":[{"address":"10.200.200.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.200.115/24"}]}}',
44
+ 'xo:clientInfo:vuy2k7qxs1d': '{"lastConnected":1744096735180,"networkInterfaces":{"wlp58s0":[{"address":"192.168.1.22","netmask":"255.255.255.0","family":"IPv4","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"192.168.1.22/24"},{"address":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"2a01:cb15:8411:4700:4aff:d5e9:6604:f90b/64","scopeid":0},{"address":"fe80::1d04:d88d:50de:799a","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"be:7b:03:70:e6:fe","internal":false,"cidr":"fe80::1d04:d88d:50de:799a/64","scopeid":2}],"wg-grenoble":[{"address":"10.200.205.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.205.115/24"}],"wg-lyon":[{"address":"10.200.200.115","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.200.115/24"}]}}',
45
+ 'xo:clientInfo:218b43e8-5622-4d81-adce-69be4252c4df': '{"lastConnected":1744096374953,"networkInterfaces":{"wlp2s0":[{"address":"192.168.0.18","netmask":"255.255.255.0","family":"IPv4","mac":"9c:b6:d0:94:f0:43","internal":false,"cidr":"192.168.0.18/24"},{"address":"fe80::c233:3934:9928:1120","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"9c:b6:d0:94:f0:43","internal":false,"cidr":"fe80::c233:3934:9928:1120/64","scopeid":2}],"wg0":[{"address":"10.200.200.9","netmask":"255.255.255.0","family":"IPv4","mac":"00:00:00:00:00:00","internal":false,"cidr":"10.200.200.9/24"}],"enx001cc25011b2":[{"address":"192.168.0.15","netmask":"255.255.255.0","family":"IPv4","mac":"00:1c:c2:50:11:b2","internal":false,"cidr":"192.168.0.15/24"},{"address":"fe80::2f62:2392:9f4d:ca13","netmask":"ffff:ffff:ffff:ffff::","family":"IPv6","mac":"00:1c:c2:50:11:b2","internal":false,"cidr":"fe80::2f62:2392:9f4d:ca13/64","scopeid":5}],"wg2":[{"address":"fdab:cdea:bcde:e7c8::9","netmask":"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff","family":"IPv6","mac":"00:00:00:00:00:00","internal":false,"cidr":"fdab:cdea:bcde:e7c8::9/128","scopeid":0}]}}',
46
+ auto_poweron: 'true',
47
+ migrationCompression: 'true',
48
+ 'xo:backupNetwork': '6c4e1cdc-9fe0-0603-e53d-4790d1fce8dd',
49
+ jft: 'test',
50
+ 'xo:355ee47d': '{"bar":1,"foo":1}',
51
+ 'memory-ratio-hvm': '0.25',
52
+ 'xo:appliance:218b43e8-5622-4d81-adce-69be4252c4df': '{"lastConnected":1644397147011}',
53
+ 'xscontainer-public-secret-uuid': 'd95d1d3c-29b9-e1b3-1c03-5d27ab82ef76',
54
+ 'memory-ratio-pv': '0.25',
55
+ 'xscontainer-private-secret-uuid': '68c7c1a0-eb42-f21a-e872-7a19468dbd6d',
56
+ },
57
+ cpus: {
58
+ cores: 120,
59
+ sockets: 6,
60
+ },
61
+ zstdSupported: true,
62
+ vtpmSupported: false,
63
+ platform_version: '3.2.1',
64
+ id: '355ee47d-ff4c-4924-3db2-fd86ae629676',
65
+ type: 'pool',
66
+ uuid: '355ee47d-ff4c-4924-3db2-fd86ae629676',
67
+ $pool: '355ee47d-ff4c-4924-3db2-fd86ae629676',
68
+ $poolId: '355ee47d-ff4c-4924-3db2-fd86ae629676',
69
+ _xapiRef: 'OpaqueRef:1c3f19c8-f80a-464d-9c48-a2c19d4e4fc3',
70
+ };
@@ -0,0 +1,29 @@
1
+ export const scheduleIds = [
2
+ '/rest/v0/schedules/ada358a4-1087-4ad4-9863-42b68bd711c2',
3
+ '/rest/v0/schedules/853864bd-b67e-425e-9880-86bb3bbf1bf1',
4
+ ];
5
+ export const partialSchedules = [
6
+ {
7
+ enabled: true,
8
+ jobId: 'a87827cf-57fc-48a6-aa77-a0a14771f8f3',
9
+ cron: '0 0 * * *',
10
+ id: 'cf7249f8-d20b-494f-97f4-b1f32f94e780',
11
+ href: '/rest/v0/schedules/cf7249f8-d20b-494f-97f4-b1f32f94e780',
12
+ },
13
+ {
14
+ enabled: true,
15
+ jobId: 'e7129e6b-84ba-439c-8b7e-34f7bc357dbd',
16
+ cron: '0 0 * * *',
17
+ id: 'd1f79c6b-90f7-49f4-9adb-bcb85f236dea',
18
+ href: '/rest/v0/schedules/d1f79c6b-90f7-49f4-9adb-bcb85f236dea',
19
+ },
20
+ ];
21
+ export const schedule = {
22
+ cron: '0 0 * * *',
23
+ enabled: true,
24
+ jobId: 'a87827cf-57fc-48a6-aa77-a0a14771f8f3',
25
+ name: 'job-schedule',
26
+ timezone: 'Europe/Paris',
27
+ userId: 'd558dd75-c928-45f6-b8e3-4375bdda59f8',
28
+ id: 'cf7249f8-d20b-494f-97f4-b1f32f94e780',
29
+ };
@@ -0,0 +1,37 @@
1
+ export const vifIds = [
2
+ '/rest/v0/vifs/f028c5d4-578a-332c-394e-087aaca32dd3',
3
+ '/rest/v0/vifs/9cc245bf-8dac-8550-e1ae-54bc679b68d9',
4
+ ];
5
+ export const partialVifs = [
6
+ {
7
+ attached: true,
8
+ id: 'f028c5d4-578a-332c-394e-087aaca32dd3',
9
+ device: '0',
10
+ href: '/rest/v0/vifs/f028c5d4-578a-332c-394e-087aaca32dd3',
11
+ },
12
+ {
13
+ attached: true,
14
+ id: '9cc245bf-8dac-8550-e1ae-54bc679b68d9',
15
+ device: '0',
16
+ href: '/rest/v0/vifs/9cc245bf-8dac-8550-e1ae-54bc679b68d9',
17
+ },
18
+ ];
19
+ export const vif = {
20
+ type: 'VIF',
21
+ allowedIpv4Addresses: [],
22
+ allowedIpv6Addresses: [],
23
+ attached: true,
24
+ device: '0',
25
+ lockingMode: 'network_default',
26
+ MAC: 'fe:2e:01:f9:75:38',
27
+ MTU: 1500,
28
+ other_config: {},
29
+ txChecksumming: true,
30
+ $network: '6b6ca0f5-6611-0636-4b0a-1fb1c8e96414',
31
+ $VM: '9c3842a5-d9e5-ab9c-958e-264fea958690',
32
+ id: 'f028c5d4-578a-332c-394e-087aaca32dd3',
33
+ uuid: 'f028c5d4-578a-332c-394e-087aaca32dd3',
34
+ $pool: 'b7569d99-30f8-178a-7d94-801de3e29b5b',
35
+ $poolId: 'b7569d99-30f8-178a-7d94-801de3e29b5b',
36
+ _xapiRef: 'OpaqueRef:ba0730b3-bd19-ff79-2e02-5c5a5338064f',
37
+ };
@@ -0,0 +1,71 @@
1
+ export const vmControllerIds = [
2
+ '/rest/v0/vm-controller/9b4775bd-9493-490a-9afa-f786a44caa4f',
3
+ '/rest/v0/vm-controller/e3fc847c-159a-48dc-bee4-cf2da216a795',
4
+ ];
5
+ export const partialVmControllers = [
6
+ {
7
+ type: 'VM-controller',
8
+ uuid: '9b4775bd-9493-490a-9afa-f786a44caa4f',
9
+ href: '/rest/v0/vm-controller/9b4775bd-9493-490a-9afa-f786a44caa4f',
10
+ },
11
+ {
12
+ type: 'VM-controller',
13
+ uuid: 'e3fc847c-159a-48dc-bee4-cf2da216a795',
14
+ href: '/rest/v0/vm-controller/e3fc847c-159a-48dc-bee4-cf2da216a795',
15
+ },
16
+ ];
17
+ export const vmController = {
18
+ type: 'VM-controller',
19
+ addresses: {},
20
+ affinityHost: 'b61a5c92-700e-4966-a13b-00633f03eea8',
21
+ auto_poweron: false,
22
+ bios_strings: {},
23
+ blockedOperations: {},
24
+ boot: {},
25
+ CPUs: {
26
+ max: 8,
27
+ number: 8,
28
+ },
29
+ current_operations: {},
30
+ expNestedHvm: false,
31
+ viridian: false,
32
+ high_availability: '',
33
+ isFirmwareSupported: true,
34
+ memory: {
35
+ dynamic: [2785017856, 2785017856],
36
+ static: [2785017856, 2785017856],
37
+ size: 2785017856,
38
+ },
39
+ installTime: null,
40
+ name_description: 'The domain which manages physical devices and manages other domains',
41
+ name_label: 'Control domain on host: localhost.localdomain',
42
+ needsVtpm: false,
43
+ other: {
44
+ storage_driver_domain: 'OpaqueRef:254474d5-77b7-0947-da0f-af869dd2ca82',
45
+ is_system_domain: 'true',
46
+ perfmon: '<config><variable><name value="fs_usage"/><alarm_trigger_level value="0.9"/><alarm_trigger_period value="60"/><alarm_auto_inhibit_period value="3600"/></variable><variable><name value="mem_usage"/><alarm_trigger_level value="0.95"/><alarm_trigger_period value="60"/><alarm_auto_inhibit_period value="3600"/></variable><variable><name value="log_fs_usage"/><alarm_trigger_level value="0.9"/><alarm_trigger_period value="60"/><alarm_auto_inhibit_period value="3600"/></variable></config>',
47
+ },
48
+ os_version: null,
49
+ power_state: 'Running',
50
+ hasVendorDevice: false,
51
+ snapshots: [],
52
+ startDelay: 0,
53
+ startTime: null,
54
+ secureBoot: false,
55
+ tags: [],
56
+ VIFs: [],
57
+ VTPMs: [],
58
+ virtualizationMode: 'pv',
59
+ xenTools: false,
60
+ $containe: 'b61a5c92-700e-4966-a13b-00633f03eea8',
61
+ $VBDs: [],
62
+ VGPUs: [],
63
+ $VGPUs: [],
64
+ xenStoreData: {},
65
+ PV_args: '',
66
+ id: '9b4775bd-9493-490a-9afa-f786a44caa4f',
67
+ uuid: '9b4775bd-9493-490a-9afa-f786a44caa4f',
68
+ $pool: 'b7569d99-30f8-178a-7d94-801de3e29b5b',
69
+ $poolId: 'b7569d99-30f8-178a-7d94-801de3e29b5b',
70
+ _xapiRef: 'OpaqueRef:ca27fcfc-5083-d039-e752-2e6c3364bde9',
71
+ };