From c2348004683bc4384601aec7521e274f840c20d4 Mon Sep 17 00:00:00 2001 From: Joris K <43381087+J0ris-K@users.noreply.github.com> Date: Tue, 27 Oct 2026 14:21:44 +0100 Subject: [PATCH] feat(lite): add host side panel in pool page (#10580) --- @xen-orchestra/lite/CHANGELOG.md | 1 + .../host/dashboard/HostDashboardQuickInfo.vue | 34 ++-- .../system/HostSystemGeneralInformation.vue | 9 +- .../HostSystemHardwareSpecifications.vue | 16 +- .../host/system/HostSystemSoftwareTooling.vue | 7 +- .../lite/src/components/pif/PifRow.vue | 5 +- .../vm/dashboard/VmDashboardQuickInfo.vue | 13 +- .../composables/host-patches.composable.ts | 4 +- .../host/components/list/HostsTable.vue | 145 ++++++++++++++++ .../components/list/panel/HostSidePanel.vue | 29 ++++ .../cards/HostHardwareSpecificationsCard.vue | 52 ++++++ .../list/panel/cards/HostInfosCard.vue | 160 ++++++++++++++++++ .../list/panel/cards/HostNetworkCard.vue | 78 +++++++++ .../list/panel/cards/HostSoftwareCard.vue | 39 +++++ .../list/panel/cards/HostSrsCard.vue | 61 +++++++ .../host/composables/host-utils.composable.ts | 60 +++++-- .../lite/src/modules/host/utils/host.util.ts | 18 +- .../lite/src/modules/pif/utils/pif.util.ts | 7 + .../cards/StorageRepositoryHostsCard.vue | 9 +- .../composables/sr-utils.composable.ts | 11 ++ .../storage-repository/utils/pbd.util.ts | 14 ++ .../lite/src/pages/host/[uuid]/storage.vue | 18 +- .../lite/src/pages/pool/[uuid]/hosts.vue | 66 ++------ .../src/stores/xen-api/host-metrics.store.ts | 4 +- .../lite/src/stores/xen-api/pif.store.ts | 16 +- .../lite/src/stores/xen-api/sr.store.ts | 6 +- .../dashboard/HostDashboardQuickInfo.vue | 20 +-- .../host/components/list/HostsTable.vue | 14 +- .../list/panel/card/HostInfoCard.vue | 22 ++- .../list/panel/card/HostNetworkCard.vue | 6 +- .../composables/xo-host-utils.composable.ts | 20 ++- .../xo-host-utils.composable.unit.test.ts | 32 ++-- 32 files changed, 798 insertions(+), 198 deletions(-) create mode 100644 @xen-orchestra/lite/src/modules/host/components/list/HostsTable.vue create mode 100644 @xen-orchestra/lite/src/modules/host/components/list/panel/HostSidePanel.vue create mode 100644 @xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostHardwareSpecificationsCard.vue create mode 100644 @xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostInfosCard.vue create mode 100644 @xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostNetworkCard.vue create mode 100644 @xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostSoftwareCard.vue create mode 100644 @xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostSrsCard.vue create mode 100644 @xen-orchestra/lite/src/modules/pif/utils/pif.util.ts create mode 100644 @xen-orchestra/lite/src/modules/storage-repository/utils/pbd.util.ts diff --git a/@xen-orchestra/lite/CHANGELOG.md b/@xen-orchestra/lite/CHANGELOG.md index 65e2eb2d1b..4a3227dccc 100644 --- a/@xen-orchestra/lite/CHANGELOG.md +++ b/@xen-orchestra/lite/CHANGELOG.md @@ -17,6 +17,7 @@ - [New/VM] Fix `MAP_DUPLICATE_KEY` error that could randomly prevent the VM creation (PR [#10552](https://github.com/vatesfr/xen-orchestra/pull/10552)) - [Host/Network] Add the possibility to forget a PIF (PR [#10239](https://github.com/vatesfr/xen-orchestra/pull/10239)) - [Lite] Display dates and times as `YYYY-MM-DD HH:mm:ss` (PR [#10547](https://github.com/vatesfr/xen-orchestra/pull/10547)) +- [Pool/Hosts] Add a side panel displaying the selected host's details, and a search bar to filter the hosts table (PR [#10580](https://github.com/vatesfr/xen-orchestra/pull/10580)) ## **0.26.0** (2026-10-01) diff --git a/@xen-orchestra/lite/src/components/host/dashboard/HostDashboardQuickInfo.vue b/@xen-orchestra/lite/src/components/host/dashboard/HostDashboardQuickInfo.vue index 2bb49638eb..34a3ae4478 100644 --- a/@xen-orchestra/lite/src/components/host/dashboard/HostDashboardQuickInfo.vue +++ b/@xen-orchestra/lite/src/components/host/dashboard/HostDashboardQuickInfo.vue @@ -30,16 +30,10 @@ - + - + @@ -54,10 +48,11 @@ diff --git a/@xen-orchestra/lite/src/components/host/system/HostSystemHardwareSpecifications.vue b/@xen-orchestra/lite/src/components/host/system/HostSystemHardwareSpecifications.vue index 0d37d0abab..586aaff85c 100644 --- a/@xen-orchestra/lite/src/components/host/system/HostSystemHardwareSpecifications.vue +++ b/@xen-orchestra/lite/src/components/host/system/HostSystemHardwareSpecifications.vue @@ -4,19 +4,13 @@ {{ t('hardware-specifications') }} - + - + @@ -33,6 +27,7 @@ diff --git a/@xen-orchestra/lite/src/components/pif/PifRow.vue b/@xen-orchestra/lite/src/components/pif/PifRow.vue index 547b60589a..2f7754b156 100644 --- a/@xen-orchestra/lite/src/components/pif/PifRow.vue +++ b/@xen-orchestra/lite/src/components/pif/PifRow.vue @@ -23,6 +23,7 @@ + + diff --git a/@xen-orchestra/lite/src/modules/host/components/list/panel/HostSidePanel.vue b/@xen-orchestra/lite/src/modules/host/components/list/panel/HostSidePanel.vue new file mode 100644 index 0000000000..64a840dc4e --- /dev/null +++ b/@xen-orchestra/lite/src/modules/host/components/list/panel/HostSidePanel.vue @@ -0,0 +1,29 @@ + + + + + + + + + + + + + diff --git a/@xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostHardwareSpecificationsCard.vue b/@xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostHardwareSpecificationsCard.vue new file mode 100644 index 0000000000..26944a579f --- /dev/null +++ b/@xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostHardwareSpecificationsCard.vue @@ -0,0 +1,52 @@ + + + + + + {{ t('manufacturer-info') }} + {{ manufacturerInfo }} + + + + + + {{ t('core-socket') }} + {{ coreSocketInfo }} + + + + + + + + + + + diff --git a/@xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostInfosCard.vue b/@xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostInfosCard.vue new file mode 100644 index 0000000000..70d8673bcb --- /dev/null +++ b/@xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostInfosCard.vue @@ -0,0 +1,160 @@ + + + + + + {{ t('state') }} + + + + {{ powerState.text }} + + + + + {{ t('description') }} + {{ host.name_description }} + + + + + + {{ t('tags') }} + + + + + + + + + + + {{ t('status') }} + + + + + + {{ t('pool') }} + + + + {{ pool.name_label }} + + + + + + + + + {{ t('master') }} + + + + {{ t('this-host') }} + + + + {{ masterHost.name_label }} + + + + + + + + + {{ t('started') }} + {{ relativeStartTime }} + + + + + + {{ t('patches') }} + + {{ t('patches-up-to-date') }} + {{ t('n-missing', nMissingPatches) }} + + + + + + + + + + + + diff --git a/@xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostNetworkCard.vue b/@xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostNetworkCard.vue new file mode 100644 index 0000000000..09e530ed20 --- /dev/null +++ b/@xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostNetworkCard.vue @@ -0,0 +1,78 @@ + + + + + + {{ t('management-ip') }} + {{ host.address }} + + + + + + + + {{ t('ipv4-addresses') }} + + {{ ip }} + + + + + + + + {{ t('ipv4-addresses') }} + + + + + {{ t('ipv6-addresses') }} + + {{ ip }} + + + + + + + + {{ t('ipv6-addresses') }} + + + + + + + + diff --git a/@xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostSoftwareCard.vue b/@xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostSoftwareCard.vue new file mode 100644 index 0000000000..80f1d1d77d --- /dev/null +++ b/@xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostSoftwareCard.vue @@ -0,0 +1,39 @@ + + + + + + {{ t('version') }} + {{ host.software_version.product_version }} + + + + + + + + + + + diff --git a/@xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostSrsCard.vue b/@xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostSrsCard.vue new file mode 100644 index 0000000000..026882a673 --- /dev/null +++ b/@xen-orchestra/lite/src/modules/host/components/list/panel/cards/HostSrsCard.vue @@ -0,0 +1,61 @@ + + + + + + {{ t('error-no-data') }} + + + + + {{ sr.name_label }} + + + + + {{ t('no-sr-connected') }} + + + + + diff --git a/@xen-orchestra/lite/src/modules/host/composables/host-utils.composable.ts b/@xen-orchestra/lite/src/modules/host/composables/host-utils.composable.ts index b7d87cc416..62cc625957 100644 --- a/@xen-orchestra/lite/src/modules/host/composables/host-utils.composable.ts +++ b/@xen-orchestra/lite/src/modules/host/composables/host-utils.composable.ts @@ -2,8 +2,13 @@ import { HOST_OPERATION } from '@/libs/xen-api/xen-api.enums.ts' import type { XenApiHost } from '@/libs/xen-api/xen-api.types.ts' import { getHostPendingStateOperation, getHostState, type HostState } from '@/modules/host/utils/host.util.ts' import { useHostMetricsStore } from '@/stores/xen-api/host-metrics.store.ts' +import { usePoolStore } from '@/stores/xen-api/pool.store.ts' +import type { IconName } from '@core/icons' +import { useTimeAgo } from '@core/composables/locale-time-ago.composable.ts' import { useMapper } from '@core/packages/mapper' +import { parseDateTime } from '@core/utils/time.util.ts' import { toComputed } from '@core/utils/to-computed.util.ts' +import { HOST_POWER_STATE } from '@vates/types' import { computed, type MaybeRefOrGetter } from 'vue' import { useI18n } from 'vue-i18n' @@ -12,22 +17,53 @@ export function useHostUtils(rawHost: MaybeRefOrGetter) const host = toComputed(rawHost) - const { isHostRunning, getHostPowerState } = useHostMetricsStore().subscribe() + const { getHostPowerState } = useHostMetricsStore().subscribe() + + const { isMasterHost } = usePoolStore().subscribe() + + const isMaster = computed(() => { + if (host.value === undefined) { + return false + } + + return isMasterHost(host.value.$ref) + }) + + const hostPowerState = computed(() => getHostPowerState(host.value)) + + const isRunning = computed(() => hostPowerState.value === HOST_POWER_STATE.RUNNING) + + const hostState = computed(() => getHostState(host.value, hostPowerState.value)) + + const powerState = useMapper( + hostState, + () => ({ + running: { text: t('host:status:running'), icon: 'status:running-circle' }, + halted: { text: t('host:status:halted'), icon: 'status:halted-circle' }, + disabled: { text: t('host:status:disabled'), icon: 'status:host-disabled-circle' }, + unknown: { text: t('host:status:unknown'), icon: undefined }, + }), + 'unknown' + ) + + const bootTime = computed(() => Number(host.value?.other_config.boot_time)) + + const hostTimeAgo = useTimeAgo(() => new Date(parseDateTime((bootTime.value || 0) * 1000))) + + const relativeStartTime = computed(() => { + if (!bootTime.value) { + return undefined + } + + return hostTimeAgo.value + }) const pendingStateOperation = computed(() => { if (host.value === undefined) { return undefined } - return getHostPendingStateOperation(host.value, isHostRunning(host.value)) - }) - - const hostState = computed(() => { - if (host.value === undefined) { - return 'unknown' - } - - return getHostState(host.value, getHostPowerState(host.value)) + return getHostPendingStateOperation(host.value, isRunning.value) }) const isChangingState = computed(() => pendingStateOperation.value !== undefined) @@ -46,8 +82,12 @@ export function useHostUtils(rawHost: MaybeRefOrGetter) ) return { + isMaster, + isRunning, hostState, + powerState, isChangingState, currentOperation, + relativeStartTime, } } diff --git a/@xen-orchestra/lite/src/modules/host/utils/host.util.ts b/@xen-orchestra/lite/src/modules/host/utils/host.util.ts index c39312e1f3..4d770c8146 100644 --- a/@xen-orchestra/lite/src/modules/host/utils/host.util.ts +++ b/@xen-orchestra/lite/src/modules/host/utils/host.util.ts @@ -1,5 +1,6 @@ import { HOST_OPERATION } from '@/libs/xen-api/xen-api.enums.ts' import type { XenApiHost } from '@/libs/xen-api/xen-api.types.ts' +import { objectIcon } from '@core/icons' import { HOST_POWER_STATE } from '@vates/types' import { castArray } from 'lodash-es' @@ -32,8 +33,8 @@ export const getHostPendingStateOperation = (host: XenApiHost, isHostRunning: bo isHostRunning ? RUNNING_CHANGING_STATE_OPERATIONS : NOT_RUNNING_CHANGING_STATE_OPERATIONS ) -export const getHostState = (host: XenApiHost, powerState: HOST_POWER_STATE): HostState => { - if (powerState === HOST_POWER_STATE.UNKNOWN) { +export const getHostState = (host: XenApiHost | undefined, powerState: HOST_POWER_STATE): HostState => { + if (host === undefined || powerState === HOST_POWER_STATE.UNKNOWN) { return 'unknown' } @@ -43,3 +44,16 @@ export const getHostState = (host: XenApiHost, powerState: HOST_POWER_STATE): Ho return host.enabled ? 'running' : 'disabled' } + +export const getHostIcon = (host: XenApiHost | undefined, powerState: HOST_POWER_STATE) => + objectIcon('host', getHostState(host, powerState)) + +export const getHostCoreSocketInfo = (host: XenApiHost): string => + `${host.cpu_info.cpu_count} (${host.cpu_info.socket_count})` + +export const getHostManufacturerInfo = (host: XenApiHost): string => { + const manufacturer = host.bios_strings['system-manufacturer'] ?? '' + const productName = host.bios_strings['system-product-name'] + + return manufacturer + (productName ? ` (${productName})` : '') +} diff --git a/@xen-orchestra/lite/src/modules/pif/utils/pif.util.ts b/@xen-orchestra/lite/src/modules/pif/utils/pif.util.ts new file mode 100644 index 0000000000..ef4a4afbb3 --- /dev/null +++ b/@xen-orchestra/lite/src/modules/pif/utils/pif.util.ts @@ -0,0 +1,7 @@ +import type { XenApiPif } from '@/libs/xen-api/xen-api.types.ts' + +export function getHostIpAddresses(managementIp: string, pifs: XenApiPif[] = []): string[] { + const others = pifs.flatMap(pif => [pif.IP, ...pif.IPv6]).filter(ip => ip && ip !== managementIp) + + return managementIp ? [managementIp, ...others] : others +} diff --git a/@xen-orchestra/lite/src/modules/storage-repository/components/list/panel/cards/StorageRepositoryHostsCard.vue b/@xen-orchestra/lite/src/modules/storage-repository/components/list/panel/cards/StorageRepositoryHostsCard.vue index 1300aff8e0..cb1a14a553 100644 --- a/@xen-orchestra/lite/src/modules/storage-repository/components/list/panel/cards/StorageRepositoryHostsCard.vue +++ b/@xen-orchestra/lite/src/modules/storage-repository/components/list/panel/cards/StorageRepositoryHostsCard.vue @@ -5,7 +5,7 @@ {{ host.name_label }} @@ -20,6 +20,7 @@ diff --git a/@xen-orchestra/lite/src/modules/storage-repository/composables/sr-utils.composable.ts b/@xen-orchestra/lite/src/modules/storage-repository/composables/sr-utils.composable.ts index 278f88a893..306871973e 100644 --- a/@xen-orchestra/lite/src/modules/storage-repository/composables/sr-utils.composable.ts +++ b/@xen-orchestra/lite/src/modules/storage-repository/composables/sr-utils.composable.ts @@ -1,5 +1,6 @@ import type { XenApiPbd, XenApiSr } from '@/libs/xen-api/xen-api.types.ts' import { usePbdUtils } from '@/modules/storage-repository/composables/pbd-utils.composable.ts' +import { getPbdsConnectionStatus } from '@/modules/storage-repository/utils/pbd.util.ts' import { usePbdStore } from '@/stores/xen-api/pbd.store.ts' import { type IconName, objectIcon } from '@core/icons' import { SR_SCOPE_TYPE, type SrScope } from '@core/types/storage-repository.type.ts' @@ -25,6 +26,10 @@ export function useGetPbdsInScope() { return getPbdsInScope(sr, scope).filter(pbd => pbd.currently_attached) } + function isConnectedInScope(sr: XenApiSr, scope: SrScope) { + return getPbdsInScope(sr, scope).some(pbd => pbd.currently_attached) + } + function getDetachedPbdsInScope(sr: XenApiSr, scope: SrScope): XenApiPbd[] { return getPbdsInScope(sr, scope).filter(pbd => !pbd.currently_attached) } @@ -50,6 +55,7 @@ export function useGetPbdsInScope() { getAttachedPbdsInScope, getDetachedPbdsInScope, getSrPbdsSignature, + isConnectedInScope, isPartiallyConnectedInScope, } } @@ -83,10 +89,15 @@ export function useSrUtils( const srStatusIcon = computed(() => objectIcon('sr', allPbdsConnectionStatus.value)) + function getSrStatusIcon(sr: XenApiSr): IconName { + return objectIcon('sr', getPbdsConnectionStatus(getPbdsInScope(sr, scope.value))) + } + return { pbdsInScope, srConnectionStatus: allPbdsConnectionStatus, isPartiallyConnectedInScope, srStatusIcon, + getSrStatusIcon, } } diff --git a/@xen-orchestra/lite/src/modules/storage-repository/utils/pbd.util.ts b/@xen-orchestra/lite/src/modules/storage-repository/utils/pbd.util.ts new file mode 100644 index 0000000000..d9e5eb4c5f --- /dev/null +++ b/@xen-orchestra/lite/src/modules/storage-repository/utils/pbd.util.ts @@ -0,0 +1,14 @@ +import type { XenApiPbd } from '@/libs/xen-api/xen-api.types.ts' +import { CONNECTION_STATUS } from '@core/types/connection.ts' + +export const getPbdsConnectionStatus = (pbds: XenApiPbd[]) => { + if (pbds.length === 0 || pbds.every(pbd => !pbd.currently_attached)) { + return CONNECTION_STATUS.DISCONNECTED + } + + if (pbds.some(pbd => !pbd.currently_attached)) { + return CONNECTION_STATUS.PARTIALLY_CONNECTED + } + + return CONNECTION_STATUS.CONNECTED +} diff --git a/@xen-orchestra/lite/src/pages/host/[uuid]/storage.vue b/@xen-orchestra/lite/src/pages/host/[uuid]/storage.vue index 0b1f4ddbf9..158eff4da2 100644 --- a/@xen-orchestra/lite/src/pages/host/[uuid]/storage.vue +++ b/@xen-orchestra/lite/src/pages/host/[uuid]/storage.vue @@ -40,8 +40,8 @@ usePageTitleStore().setTitle(t('storage')) const route = useRoute<'/host/[uuid]/storage'>() const { getByUuid: getHostByUuid } = useHostStore().subscribe() -const { getByOpaqueRef: getSrByOpaqueRef, isReady: areSrsReady, hasError } = useSrStore().subscribe() -const { getPbdsForHost, isReady: arePbdsReady } = usePbdStore().subscribe() +const { getSrsForHost, isReady: areSrsReady, hasError } = useSrStore().subscribe() +const { isReady: arePbdsReady } = usePbdStore().subscribe() const { pool } = usePoolStore().subscribe() const uiStore = useUiStore() @@ -65,19 +65,7 @@ const srs = computed((): XenApiSr[] => { return [] } - const hostPbds = getPbdsForHost(host.value.$ref) - - return hostPbds - .reduce((acc, pbd) => { - const sr = getSrByOpaqueRef(pbd.SR) - - if (sr !== undefined) { - acc.push(sr) - } - - return acc - }, []) - .sort(sortByNameLabel) + return getSrsForHost(host.value.$ref).sort(sortByNameLabel) }) const selectedSr = useRouteQuery('id', { diff --git a/@xen-orchestra/lite/src/pages/pool/[uuid]/hosts.vue b/@xen-orchestra/lite/src/pages/pool/[uuid]/hosts.vue index dbf846e1dd..2d4bcbea3e 100644 --- a/@xen-orchestra/lite/src/pages/pool/[uuid]/hosts.vue +++ b/@xen-orchestra/lite/src/pages/pool/[uuid]/hosts.vue @@ -1,71 +1,41 @@ - - - {{ t('hosts') }} - - - - - - - - - - - - - - + + + + + + diff --git a/@xen-orchestra/lite/src/stores/xen-api/host-metrics.store.ts b/@xen-orchestra/lite/src/stores/xen-api/host-metrics.store.ts index d2206e10f5..be9a2dbd8d 100644 --- a/@xen-orchestra/lite/src/stores/xen-api/host-metrics.store.ts +++ b/@xen-orchestra/lite/src/stores/xen-api/host-metrics.store.ts @@ -19,8 +19,8 @@ export const useHostMetricsStore = defineStore('xen-api-host-metrics', () => { } } - const getHostPowerState = (host: XenApiHost): HOST_POWER_STATE => { - const live = baseContext.getByOpaqueRef(host.metrics)?.live + const getHostPowerState = (host: XenApiHost | undefined): HOST_POWER_STATE => { + const live = host === undefined ? undefined : baseContext.getByOpaqueRef(host.metrics)?.live if (live === undefined) { return HOST_POWER_STATE.UNKNOWN diff --git a/@xen-orchestra/lite/src/stores/xen-api/pif.store.ts b/@xen-orchestra/lite/src/stores/xen-api/pif.store.ts index 209ffea686..35622aa18f 100644 --- a/@xen-orchestra/lite/src/stores/xen-api/pif.store.ts +++ b/@xen-orchestra/lite/src/stores/xen-api/pif.store.ts @@ -1,4 +1,4 @@ -import type { XenApiNetwork, XenApiPif } from '@/libs/xen-api/xen-api.types.ts' +import type { XenApiHost, XenApiNetwork, XenApiPif } from '@/libs/xen-api/xen-api.types.ts' import { useBondStore } from '@/stores/xen-api/bond.store.ts' import { createXapiStoreConfig } from '@/stores/xen-api/create-xapi-store-config.ts' import { usePifMetricsStore } from '@/stores/xen-api/pif-metrics.store.ts' @@ -35,6 +35,19 @@ export const usePifStore = defineStore('xen-api-pif', () => { return hostMasterPifsByNetworkMap }) + const pifsByHost = computed(() => { + const pifsByHostMap = new Map() + + baseContext.records.value.forEach(pif => { + if (!pifsByHostMap.has(pif.host)) { + pifsByHostMap.set(pif.host, []) + } + pifsByHostMap.get(pif.host)?.push(pif) + }) + + return pifsByHostMap + }) + const getPifsByNetworkRef = (networkRef: XenApiNetwork['$ref']) => { return baseContext.records.value.filter(pif => pif.network === networkRef) } @@ -69,6 +82,7 @@ export const usePifStore = defineStore('xen-api-pif', () => { const context = { ...baseContext, hostMasterPifsByNetwork, + pifsByHost, getPifsByNetworkRef, getPifStatus, getBondsDevices, diff --git a/@xen-orchestra/lite/src/stores/xen-api/sr.store.ts b/@xen-orchestra/lite/src/stores/xen-api/sr.store.ts index 7c298376c5..0bf8443eb3 100644 --- a/@xen-orchestra/lite/src/stores/xen-api/sr.store.ts +++ b/@xen-orchestra/lite/src/stores/xen-api/sr.store.ts @@ -1,5 +1,5 @@ import { getAllocationStrategy as getAllocationStrategyFromSrType } from '@/libs/sr.ts' -import type { XenApiPool, XenApiSr, XenApiVdi } from '@/libs/xen-api/xen-api.types.ts' +import type { XenApiHost, XenApiPool, XenApiSr, XenApiVdi } from '@/libs/xen-api/xen-api.types.ts' import { createXapiStoreConfig } from '@/stores/xen-api/create-xapi-store-config.ts' import { usePbdStore } from '@/stores/xen-api/pbd.store.ts' import { useVdiStore } from '@/stores/xen-api/vdi.store.ts' @@ -36,6 +36,9 @@ export const useSrStore = defineStore('xen-api-sr', () => { // TODO remove when the select component is ready to use const getSrName = (ref: XenApiSr['$ref']) => baseContext.getByOpaqueRef(ref)?.name_label + const getSrsForHost = (hostRef: XenApiHost['$ref']) => + baseContext.getByOpaqueRefs(pbdContext.getPbdsForHost(hostRef).map(pbd => pbd.SR)) + const isDefaultSr = (sr: XenApiSr, pool: XenApiPool) => pool.default_SR !== 'OpaqueRef:NULL' && pool.default_SR === sr.$ref @@ -68,6 +71,7 @@ export const useSrStore = defineStore('xen-api-sr', () => { const context = { ...baseContext, getAllocationStrategy, + getSrsForHost, isDefaultSr, isHaSr, vdiIsosBySrName, diff --git a/@xen-orchestra/web/src/modules/host/components/dashboard/HostDashboardQuickInfo.vue b/@xen-orchestra/web/src/modules/host/components/dashboard/HostDashboardQuickInfo.vue index 6073952b10..7c99334236 100644 --- a/@xen-orchestra/web/src/modules/host/components/dashboard/HostDashboardQuickInfo.vue +++ b/@xen-orchestra/web/src/modules/host/components/dashboard/HostDashboardQuickInfo.vue @@ -1,11 +1,11 @@ - + - - {{ powerState.text }} + + {{ hostStateDisplay.text }} @@ -55,10 +55,8 @@ import VtsKeyValueRow from '@core/components/key-value-row/VtsKeyValueRow.vue' import VtsQuickInfoCard from '@core/components/quick-info-card/VtsQuickInfoCard.vue' import VtsTag from '@core/components/tag/VtsTag.vue' import UiTagsList from '@core/components/ui/tag/UiTagsList.vue' -import { getRelativeTime } from '@core/composables/relative-time.composable.ts' import { vTooltip } from '@core/directives/tooltip.directive.ts' import { formatSizeRaw } from '@core/utils/size.util.ts' -import { parseDateTime } from '@core/utils/time.util.ts' import { HOST_POWER_STATE } from '@vates/types' import { computed } from 'vue' import { useI18n } from 'vue-i18n' @@ -67,18 +65,12 @@ const { host } = defineProps<{ host: FrontXoHost }>() -const { t, locale } = useI18n() +const { t } = useI18n() const { getMasterHostByPoolId, isMasterHost, areHostsReady } = useXoHostCollection() -const { getHostStatus } = useXoHostUtils(() => host) +const { getHostStateDisplay, relativeStartTime } = useXoHostUtils(() => host) -const powerState = computed(() => getHostStatus(getHostState(host))) - -const date = computed(() => (host.startTime === null ? undefined : new Date(parseDateTime(host.startTime * 1000)))) - -const relativeStartTime = computed(() => - date.value === undefined ? undefined : getRelativeTime(date.value, locale.value) -) +const hostStateDisplay = computed(() => getHostStateDisplay(getHostState(host))) const isMaster = computed(() => isMasterHost(host.id)) diff --git a/@xen-orchestra/web/src/modules/host/components/list/HostsTable.vue b/@xen-orchestra/web/src/modules/host/components/list/HostsTable.vue index bf49f751db..71a3819504 100644 --- a/@xen-orchestra/web/src/modules/host/components/list/HostsTable.vue +++ b/@xen-orchestra/web/src/modules/host/components/list/HostsTable.vue @@ -3,7 +3,7 @@ {{ t('hosts') }} - + @@ -17,7 +17,7 @@ - -