diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md
index 0619d9ea0..ebdad5d6c 100644
--- a/CHANGELOG.unreleased.md
+++ b/CHANGELOG.unreleased.md
@@ -9,6 +9,7 @@
- [New network] Ability for pool's admin to create a new network within the pool (PR [#5873](https://github.com/vatesfr/xen-orchestra/pull/5873))
- [Netbox] Synchronize primary IPv4 and IPv6 addresses [#5633](https://github.com/vatesfr/xen-orchestra/issues/5633) (PR [#5879](https://github.com/vatesfr/xen-orchestra/pull/5879))
+- [Host] Add warning in case of unmaintained host version [#5840](https://github.com/vatesfr/xen-orchestra/issues/5840) (PR [#5847](https://github.com/vatesfr/xen-orchestra/pull/5847))
### Bug fixes
diff --git a/packages/xo-web/src/common/intl/messages.js b/packages/xo-web/src/common/intl/messages.js
index c170a223f..ec2ba2908 100644
--- a/packages/xo-web/src/common/intl/messages.js
+++ b/packages/xo-web/src/common/intl/messages.js
@@ -838,6 +838,9 @@ const messages = {
addHostNotHomogeneousErrorMessage: 'Host patches could not be homogenized.',
disconnectServer: 'Disconnect',
+ // ----- Host item ------
+ noMoreMaintained: 'This host version is no longer maintained',
+
// ----- Host actions ------
disableMaintenanceMode: 'Disable maintenance mode',
enableMaintenanceMode: 'Enable maintenance mode',
diff --git a/packages/xo-web/src/common/xo/index.js b/packages/xo-web/src/common/xo/index.js
index 2f223a3e9..8dc589c2e 100644
--- a/packages/xo-web/src/common/xo/index.js
+++ b/packages/xo-web/src/common/xo/index.js
@@ -4,6 +4,7 @@ import fpSortBy from 'lodash/fp/sortBy'
import React from 'react'
import updater from 'xoa-updater'
import URL from 'url-parse'
+import * as xoaPlans from 'xoa-plans'
import Xo from 'xo-lib'
import { createBackoff } from 'jsonrpc-websocket-client'
import { get as getDefined } from '@xen-orchestra/defined'
@@ -166,9 +167,9 @@ export const resolveUrl = invoke(
)
// -------------------------------------------------------------------
-
-const createSubscription = cb => {
- const delay = 5e3 // 5s
+// Default subscription 5s
+const createSubscription = (cb, { polling = 5e3 } = {}) => {
+ const delay = polling
const clearCacheDelay = 6e5 // 10m
// contains active and lazy subscribers
@@ -300,6 +301,17 @@ export const subscribeCurrentUser = createSubscription(() => xo.refreshUser())
export const subscribeAcls = createSubscription(() => _call('acl.get'))
+export const subscribeHvSupportedVersions = createSubscription(
+ async () => {
+ try {
+ return await _call('xoa.getHVSupportedVersions')
+ } catch (error) {
+ console.error(error)
+ }
+ },
+ { polling: 1e3 * 60 * 60 } // 1h
+)
+
export const subscribeJobs = createSubscription(() => _call('job.getAll'))
export const subscribeJobsLogs = createSubscription(() => _call('log.get', { namespace: 'jobs' }))
diff --git a/packages/xo-web/src/xo-app/home/host-item.js b/packages/xo-web/src/xo-app/home/host-item.js
index d79ace186..6df7aa55c 100644
--- a/packages/xo-web/src/xo-app/home/host-item.js
+++ b/packages/xo-web/src/xo-app/home/host-item.js
@@ -7,13 +7,14 @@ import isEmpty from 'lodash/isEmpty'
import Link, { BlockLink } from 'link'
import map from 'lodash/map'
import React from 'react'
+import semver from 'semver'
import SingleLineRow from 'single-line-row'
import HomeTags from 'home-tags'
import Tooltip from 'tooltip'
import { Row, Col } from 'grid'
import { Text } from 'editable'
-import { addTag, editHost, fetchHostStats, removeTag, startHost, stopHost } from 'xo'
-import { connectStore, formatSizeShort, hasLicenseRestrictions, osFamily } from 'utils'
+import { addTag, editHost, fetchHostStats, removeTag, startHost, stopHost, subscribeHvSupportedVersions } from 'xo'
+import { addSubscriptions, connectStore, formatSizeShort, hasLicenseRestrictions, osFamily } from 'utils'
import {
createDoesHostNeedRestart,
createGetHostState,
@@ -26,6 +27,9 @@ import MiniStats from './mini-stats'
import LicenseWarning from '../host/license-warning'
import styles from './index.css'
+@addSubscriptions({
+ hvSupportedVersions: subscribeHvSupportedVersions,
+})
@connectStore(() => ({
container: createGetObject((_, props) => props.item.$pool),
needsRestart: createDoesHostNeedRestart((_, props) => props.item),
@@ -43,6 +47,16 @@ export default class HostItem extends Component {
return host && host.power_state === 'Running'
}
+ _isMaintained = createSelector(
+ () => this.props.hvSupportedVersions,
+ () => this.props.item,
+ (supportedVersions, host) =>
+ // If could not fetch the list of maintained versions, consider this host up to date
+ supportedVersions?.[host.productBrand] === undefined
+ ? true
+ : semver.satisfies(host.version, supportedVersions[host.productBrand])
+ )
+
_addTag = tag => addTag(this.props.item.id, tag)
_fetchStats = () => fetchHostStats(this.props.item.id)
_removeTag = tag => removeTag(this.props.item.id, tag)
@@ -97,6 +111,12 @@ export default class HostItem extends Component {
)}
+ {!this._isMaintained() && (
+
+
+
+ )}
+
{hasLicenseRestrictions(host) && }