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) && }