Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(xo-web): add server status component to xo6 dashboard #7800

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions @xen-orchestra/web/src/components/site/dashboard/PoolsStatus.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<template>
<UiCard>
<CardTitle>{{ $t('pools-status') }}</CardTitle>
<LoadingHero :disabled="isReady" type="card">
<DonutChartWithLegend :icon="faCity" :segments />
<CardNumbers :value="servers.length" class="total" label="Total" size="small" />
</LoadingHero>
</UiCard>
</template>

<script lang="ts" setup>
import { useServerStore } from '@/stores/xo-rest-api/server.store'
import { SERVER_STATUS } from '@/types/server.type'
import CardTitle from '@core/components/card/CardTitle.vue'
import CardNumbers from '@core/components/CardNumbers.vue'
import DonutChartWithLegend, {
type DonutChartWithLegendProps,
} from '@core/components/donut-chart-with-legend/DonutChartWithLegend.vue'
import LoadingHero from '@core/components/state-hero/LoadingHero.vue'
import UiCard from '@core/components/UiCard.vue'
import { useItemCounter } from '@core/composables/item-counter.composable'
import { faCity } from '@fortawesome/free-solid-svg-icons'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'

const { t } = useI18n()
const { records: servers, isReady } = useServerStore().subscribe()

const serversCount = useItemCounter(servers, {
connected: ({ status }) => status === SERVER_STATUS.CONNECTED,
unreachable: ({ status }) => status === SERVER_STATUS.DISCONNECTED,
})

const segments = computed<DonutChartWithLegendProps['segments']>(() => [
{
label: t('pools-status.connected'),
value: serversCount.value.connected,
color: 'success',
},
{
label: t('pools-status.unreachable'),
value: serversCount.value.unreachable,
color: 'warning',
tooltip: t('pools-status.unreachable.tooltip'),
},
{
label: t('pools-status.unknown'),
value: serversCount.value.$other,
color: 'disabled',
tooltip: t('pools-status.unknown.tooltip'),
},
])
</script>

<style lang="postcss" scoped>
.total {
margin-left: auto;
}
</style>
7 changes: 7 additions & 0 deletions @xen-orchestra/web/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
"n-hosts": "1 host | {n} hosts",
"no-results": "No results",

"pools-status": "Servers status",
"pools-status.connected": "Connected",
"pools-status.unreachable": "Unreachable",
"pools-status.unreachable.tooltip": "Configured servers that can not be reached",
"pools-status.unknown": "Unknown",
"pools-status.unknown.tooltip": "Servers currently connecting or in an unknown state",

"sidebar.search-tree-view": "Search in treeview",
"sidebar.vms-treeview": "VMs treeview",

Expand Down
7 changes: 7 additions & 0 deletions @xen-orchestra/web/src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
"n-hosts": "1 hôte | {n} hôtes",
"no-results": "Aucun résultat",

"pools-status": "Statut des pools",
"pools-status.connected": "Connectés",
"pools-status.unreachable": "Injoignables",
"pools-status.unreachable.tooltip": "Serveurs configurés mais non joignables",
"pools-status.unknown": "Inconnu",
"pools-status.unknown.tooltip": "Serveurs en cours de connexion ou dans un état inconnu",

"sidebar.search-tree-view": "Rechercher dans l'arborescence",
"sidebar.vms-treeview": "Arborescence des VMs",

Expand Down
6 changes: 6 additions & 0 deletions @xen-orchestra/web/src/pages/index.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
<template>
<div class="site-dashboard">
<PoolsStatus class="pools-status" />
<HostsStatus class="hosts-status" />
<VmsStatus class="vms-status" />
</div>
</template>

<script lang="ts" setup>
import HostsStatus from '@/components/site/dashboard/HostsStatus.vue'
import PoolsStatus from '@/components/site/dashboard/PoolsStatus.vue'
import VmsStatus from '@/components/site/dashboard/VmsStatus.vue'
</script>

Expand All @@ -23,6 +25,10 @@ import VmsStatus from '@/components/site/dashboard/VmsStatus.vue'
'alarms alarms alarms alarms alarms alarms alarms patches';
}

.pools-status {
grid-area: pools-status;
}

.hosts-status {
grid-area: hosts-status;
}
Expand Down
23 changes: 23 additions & 0 deletions @xen-orchestra/web/src/stores/xo-rest-api/server.store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { SERVER_STATUS } from '@/types/server.type'
import { createXoStoreConfig } from '@/utils/create-xo-store-config.util'
import { createSubscribableStoreContext } from '@core/utils/create-subscribable-store-context.util'
import { defineStore } from 'pinia'
import { computed } from 'vue'

export const useServerStore = defineStore('server', () => {
const { context: baseContext, ...configRest } = createXoStoreConfig('server')

const records = computed(() =>
// Filter out disconnected servers when there is a connected server in the same pool
baseContext.records.value.filter(
server => server.status !== SERVER_STATUS.DISCONNECTED || !server.error?.connectedServerId
)
)

const context = {
...baseContext,
records,
}

return createSubscribableStoreContext({ context, ...configRest }, {})
})
34 changes: 34 additions & 0 deletions @xen-orchestra/web/src/types/server.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type { RecordId } from '@/types/xo-object.type'

export enum SERVER_STATUS {
CONNECTED = 'connected',
CONNECTING = 'connecting',
DISCONNECTED = 'disconnected',
}

type BaseServer = {
allowUnauthorized: boolean
enabled: boolean
host: string
id: RecordId<'server'>
label: string | undefined
readOnly: boolean
type: 'server'
username: string
}

type ConnectedServer = BaseServer & {
status: SERVER_STATUS.CONNECTED
poolId: RecordId<'pool'>
}

type ConnectingServer = BaseServer & {
status: SERVER_STATUS.CONNECTING
}

type DisconnectedServer = BaseServer & {
status: SERVER_STATUS.DISCONNECTED
error?: any
}

export type Server = ConnectedServer | ConnectingServer | DisconnectedServer
3 changes: 2 additions & 1 deletion @xen-orchestra/web/src/types/xo-object.type.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Host } from '@/types/host.type'
import type { Pool } from '@/types/pool.type'
import type { Server } from '@/types/server.type'
import type { Task } from '@/types/task.type'
import type { Vm } from '@/types/vm.type'
import type { ComputedRef, Ref } from 'vue'
Expand All @@ -9,7 +10,7 @@ declare const __brand: unique symbol
// eslint-disable-next-line no-use-before-define
export type RecordId<Type extends XoObjectType> = string & { [__brand]: `${Type}Id` }

export type XoObject = Vm | Host | Pool | Task
export type XoObject = Vm | Host | Pool | Task | Server

export type XoObjectType = XoObject['type']

Expand Down
4 changes: 4 additions & 0 deletions @xen-orchestra/web/src/utils/rest-api-config.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ export const restApiConfig: Record<XoObjectType, { path: string; fields: string
path: 'tasks',
fields: 'id,start,end,properties,status,progress,tasks',
},
server: {
path: 'servers',
fields: 'allowUnauthorized,enabled,host,id,label,readOnly,type,username,status,poolId,error',
},
}
Loading