feat(xo-server,xo-web/host): get/set scheduler granularity (#5320)
Fixes #5291
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
|
||||
> Users must be able to say: “Nice enhancement, I'm eager to test it”
|
||||
|
||||
- [Host/Advanced] Ability to change the scheduler granularity. Only available on XCP-ng >= 8.2 [#5291](https://github.com/vatesfr/xen-orchestra/issues/5291) (PR [#5320](https://github.com/vatesfr/xen-orchestra/pull/5320))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
> Users must be able to say: “I had this issue, happy to know it's fixed”
|
||||
@@ -27,3 +29,6 @@
|
||||
> - major: if the change breaks compatibility
|
||||
>
|
||||
> In case of conflict, the highest (lowest in previous list) `$version` wins.
|
||||
|
||||
- xo-server minor
|
||||
- xo-web minor
|
||||
|
||||
@@ -2,6 +2,58 @@ import { format } from 'json-rpc-peer'
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export async function getSchedulerGranularity({ host }) {
|
||||
try {
|
||||
return await this.getXapi(host).getField(
|
||||
'host',
|
||||
host._xapiRef,
|
||||
'sched_gran'
|
||||
)
|
||||
} catch (e) {
|
||||
// This method is supported on XCP-ng >= 8.2 only.
|
||||
if (e.code === 'MESSAGE_METHOD_UNKNOWN') {
|
||||
return null
|
||||
}
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
getSchedulerGranularity.description = 'get the scheduler granularity of a host'
|
||||
|
||||
getSchedulerGranularity.params = {
|
||||
id: { type: 'string' },
|
||||
}
|
||||
|
||||
getSchedulerGranularity.resolve = {
|
||||
host: ['id', 'host', 'view'],
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export async function setSchedulerGranularity({ host, schedulerGranularity }) {
|
||||
await this.getXapi(host).setField(
|
||||
'host',
|
||||
host._xapiRef,
|
||||
'sched_gran',
|
||||
schedulerGranularity
|
||||
)
|
||||
}
|
||||
|
||||
setSchedulerGranularity.description = 'set scheduler granularity of a host'
|
||||
|
||||
setSchedulerGranularity.params = {
|
||||
id: { type: 'string' },
|
||||
schedulerGranularity: {
|
||||
enum: ['cpu', 'core', 'socket'],
|
||||
},
|
||||
}
|
||||
|
||||
setSchedulerGranularity.resolve = {
|
||||
host: ['id', 'host', 'operate'],
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export async function set({
|
||||
host,
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ const messages = {
|
||||
showLogs: 'Show logs',
|
||||
noValue: 'None',
|
||||
compression: 'Compression',
|
||||
core: 'Core',
|
||||
cpu: 'CPU',
|
||||
multipathing: 'Multipathing',
|
||||
multipathingDisabled: 'Multipathing disabled',
|
||||
enableMultipathing: 'Enable multipathing',
|
||||
@@ -42,6 +44,8 @@ const messages = {
|
||||
hasInactivePath: 'Has an inactive path',
|
||||
pools: 'Pools',
|
||||
remotes: 'Remotes',
|
||||
schedulerGranularity: 'Scheduler granularity',
|
||||
socket: 'Socket',
|
||||
type: 'Type',
|
||||
restore: 'Restore',
|
||||
delete: 'Delete',
|
||||
|
||||
@@ -443,6 +443,30 @@ export const subscribeNotifications = createSubscription(async () => {
|
||||
)
|
||||
})
|
||||
|
||||
const checkSchedulerGranularitySubscriptions = {}
|
||||
export const subscribeSchedulerGranularity = (host, cb) => {
|
||||
if (checkSchedulerGranularitySubscriptions[host] === undefined) {
|
||||
checkSchedulerGranularitySubscriptions[host] = createSubscription(() =>
|
||||
_call('host.getSchedulerGranularity', { host })
|
||||
)
|
||||
}
|
||||
|
||||
return checkSchedulerGranularitySubscriptions[host](cb)
|
||||
}
|
||||
subscribeSchedulerGranularity.forceRefresh = host => {
|
||||
if (host === undefined) {
|
||||
forEach(checkSchedulerGranularitySubscriptions, subscription =>
|
||||
subscription.forceRefresh()
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const subscription = checkSchedulerGranularitySubscriptions[host]
|
||||
if (subscription !== undefined) {
|
||||
subscription.forceRefresh()
|
||||
}
|
||||
}
|
||||
|
||||
const checkSrCurrentStateSubscriptions = {}
|
||||
export const subscribeCheckSrCurrentState = (pool, cb) => {
|
||||
const poolId = resolveId(pool)
|
||||
@@ -736,6 +760,12 @@ export const setPoolMaster = host =>
|
||||
|
||||
// Host --------------------------------------------------------------
|
||||
|
||||
export const setSchedulerGranularity = (host, schedulerGranularity) =>
|
||||
_call('host.setSchedulerGranularity', {
|
||||
host,
|
||||
schedulerGranularity,
|
||||
})::tap(() => subscribeSchedulerGranularity.forceRefresh(host))
|
||||
|
||||
export const editHost = (host, props) =>
|
||||
_call('host.set', { ...props, id: resolveId(host) })
|
||||
|
||||
|
||||
@@ -11,7 +11,12 @@ import StateButton from 'state-button'
|
||||
import TabButton from 'tab-button'
|
||||
import Tooltip from 'tooltip'
|
||||
import Upgrade from 'xoa-upgrade'
|
||||
import { compareVersions, connectStore, getIscsiPaths } from 'utils'
|
||||
import {
|
||||
addSubscriptions,
|
||||
compareVersions,
|
||||
connectStore,
|
||||
getIscsiPaths,
|
||||
} from 'utils'
|
||||
import { confirm } from 'modal'
|
||||
import { Container, Row, Col } from 'grid'
|
||||
import { createGetObjectsOfType, createSelector } from 'selectors'
|
||||
@@ -19,7 +24,7 @@ import { forEach, isEmpty, map, noop } from 'lodash'
|
||||
import { FormattedRelative, FormattedTime } from 'react-intl'
|
||||
import { Sr } from 'render-xo-item'
|
||||
import { Text } from 'editable'
|
||||
import { Toggle } from 'form'
|
||||
import { Toggle, Select } from 'form'
|
||||
import {
|
||||
detachHost,
|
||||
disableHost,
|
||||
@@ -34,12 +39,29 @@ import {
|
||||
restartHost,
|
||||
setHostsMultipathing,
|
||||
setRemoteSyslogHost,
|
||||
setSchedulerGranularity,
|
||||
subscribeSchedulerGranularity,
|
||||
} from 'xo'
|
||||
|
||||
import { installCertificate } from './install-certificate'
|
||||
|
||||
const ALLOW_INSTALL_SUPP_PACK = process.env.XOA_PLAN > 1
|
||||
|
||||
const SCHED_GRAN_TYPE_OPTIONS = [
|
||||
{
|
||||
label: _('core'),
|
||||
value: 'core',
|
||||
},
|
||||
{
|
||||
label: _('cpu'),
|
||||
value: 'cpu',
|
||||
},
|
||||
{
|
||||
label: _('socket'),
|
||||
value: 'socket',
|
||||
},
|
||||
]
|
||||
|
||||
const forceReboot = host => restartHost(host, true)
|
||||
|
||||
const formatPack = ({ name, author, description, version }, key) => (
|
||||
@@ -89,6 +111,9 @@ MultipathableSrs.propTypes = {
|
||||
hostId: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
@addSubscriptions(props => ({
|
||||
schedGran: cb => subscribeSchedulerGranularity(props.host.id, cb),
|
||||
}))
|
||||
@connectStore(() => {
|
||||
const getPgpus = createGetObjectsOfType('PGPU')
|
||||
.pick((_, { host }) => host.$PGPUs)
|
||||
@@ -139,6 +164,9 @@ export default class extends Component {
|
||||
}
|
||||
)
|
||||
|
||||
_setSchedulerGranularity = value =>
|
||||
setSchedulerGranularity(this.props.host.id, value)
|
||||
|
||||
_setHostIscsiIqn = iscsiIqn =>
|
||||
confirm({
|
||||
icon: 'alarm',
|
||||
@@ -168,7 +196,7 @@ export default class extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { host, pcis, pgpus } = this.props
|
||||
const { host, pcis, pgpus, schedGran } = this.props
|
||||
const {
|
||||
isHtEnabled,
|
||||
isNetDataPluginInstalledOnHost,
|
||||
@@ -349,6 +377,21 @@ export default class extends Component {
|
||||
{host.multipathing && <MultipathableSrs hostId={host.id} />}
|
||||
</td>
|
||||
</tr>
|
||||
{schedGran != null && (
|
||||
<tr>
|
||||
<th>{_('schedulerGranularity')}</th>
|
||||
<td>
|
||||
<Select
|
||||
onChange={this._setSchedulerGranularity}
|
||||
options={SCHED_GRAN_TYPE_OPTIONS}
|
||||
required
|
||||
simpleValue
|
||||
value={schedGran}
|
||||
/>
|
||||
<small>{_('rebootUpdateHostLabel')}</small>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
<tr>
|
||||
<th>{_('hostRemoteSyslog')}</th>
|
||||
<td>
|
||||
|
||||
Reference in New Issue
Block a user