Compare commits
1 Commits
lite/rewor
...
lite/xapi-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb02eb3486 |
@@ -1,13 +1,12 @@
|
||||
import type {
|
||||
RawObjectType,
|
||||
RawXenApiRecord,
|
||||
XenApiHost,
|
||||
XenApiHostMetrics,
|
||||
XenApiRecord,
|
||||
XenApiVm,
|
||||
} from "@/libs/xen-api";
|
||||
import type { CollectionSubscription } from "@/stores/xapi-collection.store";
|
||||
import type { Filter } from "@/types/filter";
|
||||
import type { CollectionSubscription } from "@/types/xapi-collection";
|
||||
import { faSquareCheck } from "@fortawesome/free-regular-svg-icons";
|
||||
import { faFont, faHashtag, faList } from "@fortawesome/free-solid-svg-icons";
|
||||
import { utcParse } from "d3-time-format";
|
||||
@@ -183,15 +182,6 @@ export function parseRamUsage(
|
||||
export const getFirst = <T>(value: T | T[]): T | undefined =>
|
||||
Array.isArray(value) ? value[0] : value;
|
||||
|
||||
export function requireSubscription<T>(
|
||||
subscription: T | undefined,
|
||||
type: RawObjectType
|
||||
): asserts subscription is T {
|
||||
if (subscription === undefined) {
|
||||
throw new Error(`You need to provide a ${type} subscription`);
|
||||
}
|
||||
}
|
||||
|
||||
export const isOperationsPending = (
|
||||
obj: XenApiVm,
|
||||
operations: string[] | string
|
||||
|
||||
@@ -1,21 +1,28 @@
|
||||
import {
|
||||
isHostRunning,
|
||||
requireSubscription,
|
||||
sortRecordsByNameLabel,
|
||||
} from "@/libs/utils";
|
||||
import type { GRANULARITY } from "@/libs/xapi-stats";
|
||||
import type { XenApiHostMetrics } from "@/libs/xen-api";
|
||||
import {
|
||||
type CollectionSubscription,
|
||||
useXapiCollectionStore,
|
||||
} from "@/stores/xapi-collection.store";
|
||||
import { isHostRunning, sortRecordsByNameLabel } from "@/libs/utils";
|
||||
import type { GRANULARITY, XapiStatsResponse } from "@/libs/xapi-stats";
|
||||
import type { XenApiHost, XenApiHostMetrics } from "@/libs/xen-api";
|
||||
import { useXapiCollectionStore } from "@/stores/xapi-collection.store";
|
||||
import { useXenApiStore } from "@/stores/xen-api.store";
|
||||
import type { CollectionSubscription } from "@/types/xapi-collection";
|
||||
import { defineStore } from "pinia";
|
||||
import { computed } from "vue";
|
||||
import { computed, type ComputedRef } from "vue";
|
||||
|
||||
type SubscribeOptions = {
|
||||
hostMetricsSubscription?: CollectionSubscription<XenApiHostMetrics>;
|
||||
};
|
||||
type MetricsSubscription = CollectionSubscription<XenApiHostMetrics>;
|
||||
|
||||
interface HostSubscribeOptions<M extends undefined | MetricsSubscription> {
|
||||
hostMetricsSubscription?: M;
|
||||
}
|
||||
|
||||
interface HostSubscription extends CollectionSubscription<XenApiHost> {
|
||||
getStats: (
|
||||
hostUuid: string,
|
||||
granularity: GRANULARITY
|
||||
) => Promise<XapiStatsResponse<any>>;
|
||||
}
|
||||
|
||||
interface HostSubscriptionWithRunningHosts extends HostSubscription {
|
||||
runningHosts: ComputedRef<XenApiHost[]>;
|
||||
}
|
||||
|
||||
export const useHostStore = defineStore("host", () => {
|
||||
const xenApiStore = useXenApiStore();
|
||||
@@ -23,17 +30,19 @@ export const useHostStore = defineStore("host", () => {
|
||||
|
||||
hostCollection.setSort(sortRecordsByNameLabel);
|
||||
|
||||
const subscribe = ({ hostMetricsSubscription }: SubscribeOptions = {}) => {
|
||||
function subscribe(
|
||||
options?: HostSubscribeOptions<undefined>
|
||||
): HostSubscription;
|
||||
|
||||
function subscribe(
|
||||
options?: HostSubscribeOptions<MetricsSubscription>
|
||||
): HostSubscriptionWithRunningHosts;
|
||||
|
||||
function subscribe({
|
||||
hostMetricsSubscription,
|
||||
}: HostSubscribeOptions<undefined | MetricsSubscription> = {}) {
|
||||
const hostSubscription = hostCollection.subscribe();
|
||||
|
||||
const runningHosts = computed(() => {
|
||||
requireSubscription(hostMetricsSubscription, "host_metrics");
|
||||
|
||||
return hostSubscription.records.value.filter((host) =>
|
||||
isHostRunning(host, hostMetricsSubscription)
|
||||
);
|
||||
});
|
||||
|
||||
const getStats = (hostUuid: string, granularity: GRANULARITY) => {
|
||||
const host = hostSubscription.getByUuid(hostUuid);
|
||||
|
||||
@@ -52,12 +61,26 @@ export const useHostStore = defineStore("host", () => {
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
const subscription = {
|
||||
...hostSubscription,
|
||||
runningHosts,
|
||||
getStats,
|
||||
};
|
||||
};
|
||||
|
||||
if (hostMetricsSubscription === undefined) {
|
||||
return subscription;
|
||||
}
|
||||
|
||||
const runningHosts = computed(() =>
|
||||
hostSubscription.records.value.filter((host) =>
|
||||
isHostRunning(host, hostMetricsSubscription)
|
||||
)
|
||||
);
|
||||
|
||||
return {
|
||||
...subscription,
|
||||
runningHosts,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...hostCollection,
|
||||
|
||||
@@ -1,18 +1,30 @@
|
||||
import { requireSubscription, sortRecordsByNameLabel } from "@/libs/utils";
|
||||
import type { GRANULARITY } from "@/libs/xapi-stats";
|
||||
import { sortRecordsByNameLabel } from "@/libs/utils";
|
||||
import type { GRANULARITY, XapiStatsResponse } from "@/libs/xapi-stats";
|
||||
import type { XenApiHost, XenApiVm } from "@/libs/xen-api";
|
||||
import {
|
||||
type CollectionSubscription,
|
||||
useXapiCollectionStore,
|
||||
} from "@/stores/xapi-collection.store";
|
||||
import { useXapiCollectionStore } from "@/stores/xapi-collection.store";
|
||||
import { useXenApiStore } from "@/stores/xen-api.store";
|
||||
import type { CollectionSubscription } from "@/types/xapi-collection";
|
||||
import { defineStore } from "pinia";
|
||||
import { computed } from "vue";
|
||||
import { computed, type ComputedRef } from "vue";
|
||||
|
||||
type SubscribeOptions = {
|
||||
hostSubscription?: CollectionSubscription<XenApiHost>;
|
||||
type HostSubscription = CollectionSubscription<XenApiHost>;
|
||||
|
||||
type VmSubscribeOptions<H extends undefined | HostSubscription> = {
|
||||
hostSubscription?: H;
|
||||
};
|
||||
|
||||
interface VmSubscription extends CollectionSubscription<XenApiVm> {
|
||||
recordsByHostRef: ComputedRef<Map<string, XenApiVm[]>>;
|
||||
runningVms: ComputedRef<XenApiVm[]>;
|
||||
}
|
||||
|
||||
interface VmSubscriptionWithGetStats extends VmSubscription {
|
||||
getStats: (
|
||||
id: string,
|
||||
granularity: GRANULARITY
|
||||
) => Promise<XapiStatsResponse<any>>;
|
||||
}
|
||||
|
||||
export const useVmStore = defineStore("vm", () => {
|
||||
const vmCollection = useXapiCollectionStore().get("VM");
|
||||
|
||||
@@ -22,7 +34,15 @@ export const useVmStore = defineStore("vm", () => {
|
||||
|
||||
vmCollection.setSort(sortRecordsByNameLabel);
|
||||
|
||||
const subscribe = ({ hostSubscription }: SubscribeOptions = {}) => {
|
||||
function subscribe(options?: VmSubscribeOptions<undefined>): VmSubscription;
|
||||
|
||||
function subscribe(
|
||||
options?: VmSubscribeOptions<HostSubscription>
|
||||
): VmSubscriptionWithGetStats;
|
||||
|
||||
function subscribe({
|
||||
hostSubscription,
|
||||
}: VmSubscribeOptions<undefined | HostSubscription> = {}) {
|
||||
const vmSubscription = vmCollection.subscribe();
|
||||
|
||||
const recordsByHostRef = computed(() => {
|
||||
@@ -43,9 +63,17 @@ export const useVmStore = defineStore("vm", () => {
|
||||
vmSubscription.records.value.filter((vm) => vm.power_state === "Running")
|
||||
);
|
||||
|
||||
const getStats = (id: string, granularity: GRANULARITY) => {
|
||||
requireSubscription(hostSubscription, "host");
|
||||
const subscription = {
|
||||
...vmSubscription,
|
||||
recordsByHostRef,
|
||||
runningVms,
|
||||
};
|
||||
|
||||
if (hostSubscription === undefined) {
|
||||
return subscription;
|
||||
}
|
||||
|
||||
const getStats = (id: string, granularity: GRANULARITY) => {
|
||||
const xenApiStore = useXenApiStore();
|
||||
|
||||
if (!xenApiStore.isConnected) {
|
||||
@@ -72,12 +100,10 @@ export const useVmStore = defineStore("vm", () => {
|
||||
};
|
||||
|
||||
return {
|
||||
...vmSubscription,
|
||||
recordsByHostRef,
|
||||
...subscription,
|
||||
getStats,
|
||||
runningVms,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...vmCollection,
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
import type {
|
||||
RawObjectType,
|
||||
XenApiConsole,
|
||||
XenApiHost,
|
||||
XenApiHostMetrics,
|
||||
XenApiPool,
|
||||
XenApiRecord,
|
||||
XenApiSr,
|
||||
XenApiTask,
|
||||
XenApiVm,
|
||||
XenApiVmGuestMetrics,
|
||||
XenApiVmMetrics,
|
||||
} from "@/libs/xen-api";
|
||||
import type { RawObjectType, XenApiRecord } from "@/libs/xen-api";
|
||||
import { useXenApiStore } from "@/stores/xen-api.store";
|
||||
import type {
|
||||
CollectionSubscription,
|
||||
DeferredCollectionSubscription,
|
||||
RawTypeToObject,
|
||||
SubscribeOptions,
|
||||
} from "@/types/xapi-collection";
|
||||
import { tryOnUnmounted, whenever } from "@vueuse/core";
|
||||
import { defineStore } from "pinia";
|
||||
import { computed, type ComputedRef, readonly, type Ref, ref } from "vue";
|
||||
import { computed, readonly, ref } from "vue";
|
||||
|
||||
export const useXapiCollectionStore = defineStore("xapiCollection", () => {
|
||||
const collections = ref(
|
||||
@@ -35,18 +29,6 @@ export const useXapiCollectionStore = defineStore("xapiCollection", () => {
|
||||
return { get };
|
||||
});
|
||||
|
||||
export interface CollectionSubscription<T extends XenApiRecord> {
|
||||
records: ComputedRef<T[]>;
|
||||
getByOpaqueRef: (opaqueRef: string) => T | undefined;
|
||||
getByUuid: (uuid: string) => T | undefined;
|
||||
hasUuid: (uuid: string) => boolean;
|
||||
isReady: Readonly<Ref<boolean>>;
|
||||
isFetching: Readonly<Ref<boolean>>;
|
||||
isReloading: ComputedRef<boolean>;
|
||||
hasError: ComputedRef<boolean>;
|
||||
lastError: Readonly<Ref<string | undefined>>;
|
||||
}
|
||||
|
||||
const createXapiCollection = <T extends XenApiRecord>(type: RawObjectType) => {
|
||||
const isReady = ref(false);
|
||||
const isFetching = ref(false);
|
||||
@@ -123,16 +105,30 @@ const createXapiCollection = <T extends XenApiRecord>(type: RawObjectType) => {
|
||||
() => fetchAll()
|
||||
);
|
||||
|
||||
const subscribe = () => {
|
||||
function subscribe(
|
||||
options?: SubscribeOptions<true>
|
||||
): CollectionSubscription<T>;
|
||||
|
||||
function subscribe(
|
||||
options: SubscribeOptions<false>
|
||||
): DeferredCollectionSubscription<T>;
|
||||
|
||||
function subscribe(
|
||||
options: SubscribeOptions<boolean>
|
||||
): CollectionSubscription<T> | DeferredCollectionSubscription<T>;
|
||||
|
||||
function subscribe({ immediate = true }: SubscribeOptions<boolean> = {}) {
|
||||
const id = Symbol();
|
||||
|
||||
subscriptions.value.add(id);
|
||||
if (immediate) {
|
||||
subscriptions.value.add(id);
|
||||
}
|
||||
|
||||
tryOnUnmounted(() => {
|
||||
unsubscribe(id);
|
||||
});
|
||||
|
||||
return {
|
||||
const subscription = {
|
||||
records,
|
||||
getByOpaqueRef,
|
||||
getByUuid,
|
||||
@@ -143,7 +139,17 @@ const createXapiCollection = <T extends XenApiRecord>(type: RawObjectType) => {
|
||||
hasError,
|
||||
lastError: readonly(lastError),
|
||||
};
|
||||
};
|
||||
|
||||
if (immediate) {
|
||||
return subscription;
|
||||
}
|
||||
|
||||
return {
|
||||
...subscription,
|
||||
start: () => subscriptions.value.add(id),
|
||||
isStarted: computed(() => subscriptions.value.has(id)),
|
||||
};
|
||||
}
|
||||
|
||||
const unsubscribe = (id: symbol) => subscriptions.value.delete(id);
|
||||
|
||||
@@ -158,59 +164,3 @@ const createXapiCollection = <T extends XenApiRecord>(type: RawObjectType) => {
|
||||
setSort,
|
||||
};
|
||||
};
|
||||
|
||||
type RawTypeToObject = {
|
||||
Bond: never;
|
||||
Certificate: never;
|
||||
Cluster: never;
|
||||
Cluster_host: never;
|
||||
DR_task: never;
|
||||
Feature: never;
|
||||
GPU_group: never;
|
||||
PBD: never;
|
||||
PCI: never;
|
||||
PGPU: never;
|
||||
PIF: never;
|
||||
PIF_metrics: never;
|
||||
PUSB: never;
|
||||
PVS_cache_storage: never;
|
||||
PVS_proxy: never;
|
||||
PVS_server: never;
|
||||
PVS_site: never;
|
||||
SDN_controller: never;
|
||||
SM: never;
|
||||
SR: XenApiSr;
|
||||
USB_group: never;
|
||||
VBD: never;
|
||||
VBD_metrics: never;
|
||||
VDI: never;
|
||||
VGPU: never;
|
||||
VGPU_type: never;
|
||||
VIF: never;
|
||||
VIF_metrics: never;
|
||||
VLAN: never;
|
||||
VM: XenApiVm;
|
||||
VMPP: never;
|
||||
VMSS: never;
|
||||
VM_guest_metrics: XenApiVmGuestMetrics;
|
||||
VM_metrics: XenApiVmMetrics;
|
||||
VUSB: never;
|
||||
blob: never;
|
||||
console: XenApiConsole;
|
||||
crashdump: never;
|
||||
host: XenApiHost;
|
||||
host_cpu: never;
|
||||
host_crashdump: never;
|
||||
host_metrics: XenApiHostMetrics;
|
||||
host_patch: never;
|
||||
network: never;
|
||||
network_sriov: never;
|
||||
pool: XenApiPool;
|
||||
pool_patch: never;
|
||||
pool_update: never;
|
||||
role: never;
|
||||
secret: never;
|
||||
subject: never;
|
||||
task: XenApiTask;
|
||||
tunnel: never;
|
||||
};
|
||||
|
||||
91
@xen-orchestra/lite/src/types/xapi-collection.ts
Normal file
91
@xen-orchestra/lite/src/types/xapi-collection.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import type {
|
||||
XenApiConsole,
|
||||
XenApiHost,
|
||||
XenApiHostMetrics,
|
||||
XenApiPool,
|
||||
XenApiRecord,
|
||||
XenApiSr,
|
||||
XenApiTask,
|
||||
XenApiVm,
|
||||
XenApiVmGuestMetrics,
|
||||
XenApiVmMetrics,
|
||||
} from "@/libs/xen-api";
|
||||
import type { ComputedRef, Ref } from "vue";
|
||||
|
||||
export interface SubscribeOptions<Immediate extends boolean> {
|
||||
immediate?: Immediate;
|
||||
}
|
||||
|
||||
export interface CollectionSubscription<T extends XenApiRecord> {
|
||||
records: ComputedRef<T[]>;
|
||||
getByOpaqueRef: (opaqueRef: string) => T | undefined;
|
||||
getByUuid: (uuid: string) => T | undefined;
|
||||
hasUuid: (uuid: string) => boolean;
|
||||
isReady: Readonly<Ref<boolean>>;
|
||||
isFetching: Readonly<Ref<boolean>>;
|
||||
isReloading: ComputedRef<boolean>;
|
||||
hasError: ComputedRef<boolean>;
|
||||
lastError: Readonly<Ref<string | undefined>>;
|
||||
}
|
||||
|
||||
export interface DeferredCollectionSubscription<T extends XenApiRecord>
|
||||
extends CollectionSubscription<T> {
|
||||
start: () => void;
|
||||
isStarted: ComputedRef<boolean>;
|
||||
}
|
||||
|
||||
export type RawTypeToObject = {
|
||||
Bond: never;
|
||||
Certificate: never;
|
||||
Cluster: never;
|
||||
Cluster_host: never;
|
||||
DR_task: never;
|
||||
Feature: never;
|
||||
GPU_group: never;
|
||||
PBD: never;
|
||||
PCI: never;
|
||||
PGPU: never;
|
||||
PIF: never;
|
||||
PIF_metrics: never;
|
||||
PUSB: never;
|
||||
PVS_cache_storage: never;
|
||||
PVS_proxy: never;
|
||||
PVS_server: never;
|
||||
PVS_site: never;
|
||||
SDN_controller: never;
|
||||
SM: never;
|
||||
SR: XenApiSr;
|
||||
USB_group: never;
|
||||
VBD: never;
|
||||
VBD_metrics: never;
|
||||
VDI: never;
|
||||
VGPU: never;
|
||||
VGPU_type: never;
|
||||
VIF: never;
|
||||
VIF_metrics: never;
|
||||
VLAN: never;
|
||||
VM: XenApiVm;
|
||||
VMPP: never;
|
||||
VMSS: never;
|
||||
VM_guest_metrics: XenApiVmGuestMetrics;
|
||||
VM_metrics: XenApiVmMetrics;
|
||||
VUSB: never;
|
||||
blob: never;
|
||||
console: XenApiConsole;
|
||||
crashdump: never;
|
||||
host: XenApiHost;
|
||||
host_cpu: never;
|
||||
host_crashdump: never;
|
||||
host_metrics: XenApiHostMetrics;
|
||||
host_patch: never;
|
||||
network: never;
|
||||
network_sriov: never;
|
||||
pool: XenApiPool;
|
||||
pool_patch: never;
|
||||
pool_update: never;
|
||||
role: never;
|
||||
secret: never;
|
||||
subject: never;
|
||||
task: XenApiTask;
|
||||
tunnel: never;
|
||||
};
|
||||
Reference in New Issue
Block a user