Skip to content

Commit

Permalink
feat(lite,core,web): control domain store, refactor context access (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ByScripts authored Nov 15, 2024
1 parent 91bfdf5 commit a3340a7
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 33 deletions.
1 change: 1 addition & 0 deletions @xen-orchestra/lite/src/libs/xen-api/xen-api.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export interface XenApiHost extends XenApiRecord<'host'> {
resident_VMs: XenApiVm['$ref'][]
cpu_info: { cpu_count: string }
software_version: { product_version: string }
control_domain: XenApiVm['$ref']
}

export interface XenApiSr extends XenApiRecord<'sr'> {
Expand Down
21 changes: 21 additions & 0 deletions @xen-orchestra/lite/src/stores/xen-api/control-domain.store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useVmRawStore } from '@/stores/xen-api/vm-raw.store'
import { createSubscribableStoreContext } from '@core/utils/create-subscribable-store-context.util'
import { defineStore } from 'pinia'
import { computed } from 'vue'

export const useControlDomainStore = defineStore('xen-api-control-domain', () => {
const deps = {
vmRawStore: useVmRawStore(),
}

const vmRawContext = deps.vmRawStore.getContext()

const records = computed(() => vmRawContext.records.value.filter(vm => vm.is_control_domain))

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

return createSubscribableStoreContext({ context }, deps)
})
9 changes: 5 additions & 4 deletions @xen-orchestra/lite/src/stores/xen-api/host.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import { defineStore } from 'pinia'
import { computed } from 'vue'

export const useHostStore = defineStore('xen-api-host', () => {
const deps = { metrics: useHostMetricsStore() }
const deps = { metricsStore: useHostMetricsStore() }

const metricsContext = deps.metricsStore.getContext()

const xenApiStore = useXenApiStore()

const { context: baseContext, ...configRest } = createXapiStoreConfig('host')

const runningHosts = computed(() =>
baseContext.records.value.filter(host => deps.metrics.$context.isHostRunning(host))
)
const runningHosts = computed(() => baseContext.records.value.filter(host => metricsContext.isHostRunning(host)))

const getStats = ((hostUuid, granularity, ignoreExpired = false, { abortSignal }) => {
const host = baseContext.getByUuid(hostUuid)
Expand Down
12 changes: 12 additions & 0 deletions @xen-orchestra/lite/src/stores/xen-api/vm-raw.store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { createXapiStoreConfig } from '@/stores/xen-api/create-xapi-store-config'
import { createSubscribableStoreContext } from '@core/utils/create-subscribable-store-context.util'
import { sortByNameLabel } from '@core/utils/sort-by-name-label.util'
import { defineStore } from 'pinia'

export const useVmRawStore = defineStore('xen-api-vm-raw', () => {
const config = createXapiStoreConfig('vm', {
sortBy: (vm1, vm2) => sortByNameLabel(vm1, vm2),
})

return createSubscribableStoreContext(config, {})
})
40 changes: 20 additions & 20 deletions @xen-orchestra/lite/src/stores/xen-api/vm.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,35 @@ import type { GetStats } from '@/composables/fetch-stats.composable'
import type { VmStats } from '@/libs/xapi-stats'
import { VM_POWER_STATE } from '@/libs/xen-api/xen-api.enums'
import type { XenApiHost, XenApiVm } from '@/libs/xen-api/xen-api.types'
import { createXapiStoreConfig } from '@/stores/xen-api/create-xapi-store-config'
import { useHostStore } from '@/stores/xen-api/host.store'
import { useVmRawStore } from '@/stores/xen-api/vm-raw.store'
import { useXenApiStore } from '@/stores/xen-api.store'
import { createSubscribableStoreContext } from '@core/utils/create-subscribable-store-context.util'
import { sortByNameLabel } from '@core/utils/sort-by-name-label.util'
import { defineStore } from 'pinia'
import { computed } from 'vue'

export const useVmStore = defineStore('xen-api-vm', () => {
const deps = { host: useHostStore() }
const deps = {
hostStore: useHostStore(),
vmRawStore: useVmRawStore(),
}

const { context: baseContext, ...configRest } = createXapiStoreConfig('vm', {
beforeAdd(vm) {
if (vm.is_a_snapshot || vm.is_control_domain || vm.is_a_template) {
return undefined
}
const xenApiStore = useXenApiStore()

return vm
},
sortBy: (vm1, vm2) => sortByNameLabel(vm1, vm2),
})
const hostContext = deps.hostStore.getContext()

const runningVms = computed(() => baseContext.records.value.filter(vm => vm.power_state === VM_POWER_STATE.RUNNING))
const vmRawContext = deps.vmRawStore.getContext()

const records = computed(() =>
vmRawContext.records.value.filter(vm => !vm.is_a_snapshot && !vm.is_control_domain && !vm.is_a_template)
)

const runningVms = computed(() => records.value.filter(vm => vm.power_state === VM_POWER_STATE.RUNNING))

const recordsByHostRef = computed(() => {
const vmsByHostOpaqueRef = new Map<XenApiHost['$ref'], XenApiVm[]>()

baseContext.records.value.forEach(vm => {
records.value.forEach(vm => {
if (!vmsByHostOpaqueRef.has(vm.resident_on)) {
vmsByHostOpaqueRef.set(vm.resident_on, [])
}
Expand All @@ -41,19 +42,17 @@ export const useVmStore = defineStore('xen-api-vm', () => {
})

const getStats = ((id, granularity, ignoreExpired = false, { abortSignal }) => {
const xenApiStore = useXenApiStore()

if (!xenApiStore.isConnected) {
return undefined
}

const vm = baseContext.getByUuid(id)
const vm = vmRawContext.getByUuid(id)

if (vm === undefined) {
throw new Error(`VM ${id} could not be found.`)
}

const host = deps.host.$context.getByOpaqueRef(vm.resident_on)
const host = hostContext.getByOpaqueRef(vm.resident_on)

if (host === undefined) {
throw new Error(`VM ${id} is halted or host could not be found.`)
Expand All @@ -69,11 +68,12 @@ export const useVmStore = defineStore('xen-api-vm', () => {
}) as GetStats<XenApiVm>

const context = {
...baseContext,
...vmRawContext,
records,
runningVms,
recordsByHostRef,
getStats,
}

return createSubscribableStoreContext({ context, ...configRest }, deps)
return createSubscribableStoreContext({ context }, deps)
})
9 changes: 6 additions & 3 deletions @xen-orchestra/web-core/docs/stores/subscribable-stores.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The configuration object must have the following properties:
The function will return an object with the following properties:

- `subscribe(options?: { defer: boolean })`: a function which will register a subscription then return the `context`
- `$context`: a way to access the `context` object without subscribing (helpful for dependencies)
- `getContext()`: a way to access the `context` object without subscribing (helpful for dependencies)

## Basic store

Expand Down Expand Up @@ -71,8 +71,11 @@ export const useGreetingStore = defineStore('greeting', () => {
groupStore: useGroupStore(),
}

const userGreeting = computed(() => `Hello ${deps.userStore.$context.user.value.name}`)
const groupGreeting = computed(() => `Hello ${deps.groupStore.$context.group.value.name}`)
const userContext = deps.userStore.getContext()
const groupContext = deps.groupStore.getContext()

const userGreeting = computed(() => `Hello ${userContext.user.value.name}`)
const groupGreeting = computed(() => `Hello ${groupContext.group.value.name}`)

const context = {
userGreeting,
Expand Down
4 changes: 2 additions & 2 deletions @xen-orchestra/web-core/lib/types/subscribable-store.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export type Subscribe<TDefer extends boolean = false> = (options?: {

export type SubscribableStoreConfig<TContext> = {
context: TContext
onSubscribe: () => void
onUnsubscribe: () => void
onSubscribe?: () => void
onUnsubscribe?: () => void
isEnabled?: MaybeRefOrGetter<boolean>
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function createSubscribableStoreContext<TContext>(
}

return {
$context: config.context,
getContext: () => config.context,
subscribe,
}
}
4 changes: 2 additions & 2 deletions @xen-orchestra/web-core/lib/utils/if-else.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ export interface IfElseOptions extends Pick<WatchOptions, 'immediate'> {}

export function ifElse(
source: WatchSource<boolean>,
onTrue: MaybeArray<VoidFunction>,
onFalse: MaybeArray<VoidFunction>,
onTrue: MaybeArray<VoidFunction> | undefined,
onFalse: MaybeArray<VoidFunction> | undefined,
options?: IfElseOptions
) {
const onTrueFunctions = toArray(onTrue)
Expand Down
4 changes: 3 additions & 1 deletion @xen-orchestra/web/src/stores/xo-rest-api/host.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ export const useHostStore = defineStore('host', () => {
poolStore: usePoolStore(),
}

const poolContext = deps.poolStore.getContext()

const { context: baseContext, ...configRest } = createXoStoreConfig('host', {
sortBy: sortByNameLabel,
})

const isMasterHost = (hostId: XoHost['id']) => !!deps.poolStore.$context.records.find(pool => pool.master === hostId)
const isMasterHost = (hostId: XoHost['id']) => !!poolContext.records.value.find(pool => pool.master === hostId)

const hostsByPool = computed(() => {
const hostsByPoolMap = new Map<XoPool['id'], XoHost[]>()
Expand Down

0 comments on commit a3340a7

Please sign in to comment.