Skip to content

Commit

Permalink
feat(xo-server,xo-web/host): set control domain memory (#5437)
Browse files Browse the repository at this point in the history
Fixes #2218
  • Loading branch information
pdonias committed Dec 10, 2020
1 parent 8bcd9de commit cf9f6c1
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Expand Up @@ -12,6 +12,7 @@
- [Proxy] Ability to delete VM backups (PR [#5428](https://github.com/vatesfr/xen-orchestra/pull/5428))
- [Home] Ability to sort VMs by total disks physical usage (PR [#5418](https://github.com/vatesfr/xen-orchestra/pull/5418))
- [Home/VM] Ability to choose network for bulk migration within a pool (PR [#5427](https://github.com/vatesfr/xen-orchestra/pull/5427))
- [Host] Ability to set host control domain memory [#2218](https://github.com/vatesfr/xen-orchestra/issues/2218) (PR [#5437](https://github.com/vatesfr/xen-orchestra/pull/5437))

### Bug fixes

Expand Down
24 changes: 24 additions & 0 deletions packages/xo-server/src/api/host.js
@@ -1,3 +1,4 @@
import assert from 'assert'
import { format } from 'json-rpc-peer'

// ===================================================================
Expand Down Expand Up @@ -373,3 +374,26 @@ installCertificate.params = {
installCertificate.resolve = {
host: ['id', 'host', 'administrate'],
}

// -------------------------------------------------------------------

export async function setControlDomainMemory({ host, memory }) {
assert(!host.enabled)

const controlDomain = this.getXapiObject(host.controlDomain, 'VM-controller')

const xapi = controlDomain.$xapi
await xapi.call('VM.set_memory_limits', controlDomain.$ref, controlDomain.memory_static_min, memory, memory, memory)
await xapi.rebootHost(host._xapiId)
}

setControlDomainMemory.description = "Set host's control domain memory and restart the host"

setControlDomainMemory.params = {
id: { type: 'string' },
memory: { type: 'number' },
}

setControlDomainMemory.resolve = {
host: ['id', 'host', 'administrate'],
}
1 change: 1 addition & 0 deletions packages/xo-server/src/xapi-object-to-xo.js
Expand Up @@ -176,6 +176,7 @@ const TRANSFORMS = {
iommu: obj.chipset_info.iommu !== undefined ? obj.chipset_info.iommu === 'true' : undefined,
},
enabled: Boolean(obj.enabled),
controlDomain: link(obj, 'control_domain'),
cpus: {
cores: cpuInfo && +cpuInfo.cpu_count,
sockets: cpuInfo && +cpuInfo.socket_count,
Expand Down
5 changes: 5 additions & 0 deletions packages/xo-web/src/common/intl/messages.js
Expand Up @@ -886,6 +886,11 @@ const messages = {
hostStatusEnabled: 'Enabled',
hostStatusDisabled: 'Disabled',
hostPowerOnMode: 'Power on mode',
hostControlDomainMemory: 'Control domain memory',
setControlDomainMemory: 'Set control domain memory',
setControlDomainMemoryMessage:
'Editing the control domain memory will immediately restart the host in order to apply the changes.',
maintenanceModeRequired: 'The host needs to be in maintenance mode',
hostStartedSince: 'Host uptime',
hostStackStartedSince: 'Toolstack uptime',
hostCpusModel: 'CPU model',
Expand Down
2 changes: 2 additions & 0 deletions packages/xo-web/src/common/xo/index.js
Expand Up @@ -828,6 +828,8 @@ export const isHyperThreadingEnabledHost = host =>

export const installCertificateOnHost = (id, props) => _call('host.installCertificate', { id, ...props })

export const setControlDomainMemory = (id, memory) => _call('host.setControlDomainMemory', { id, memory })

// for XCP-ng now
export const installAllPatchesOnHost = ({ host }) =>
confirm({
Expand Down
60 changes: 55 additions & 5 deletions packages/xo-web/src/xo-app/host/tab-advanced.js
Expand Up @@ -11,16 +11,16 @@ import StateButton from 'state-button'
import TabButton from 'tab-button'
import Tooltip from 'tooltip'
import Upgrade from 'xoa-upgrade'
import { addSubscriptions, compareVersions, connectStore, getIscsiPaths } from 'utils'
import { confirm } from 'modal'
import { addSubscriptions, compareVersions, connectStore, formatSize, getIscsiPaths } from 'utils'
import { confirm, form } from 'modal'
import { Container, Row, Col } from 'grid'
import { CustomFields } from 'custom-fields'
import { createGetObjectsOfType, createSelector } from 'selectors'
import { createGetObject, createGetObjectsOfType, createSelector } from 'selectors'
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, Select } from 'form'
import { Toggle, Select, SizeInput } from 'form'
import {
detachHost,
disableHost,
Expand All @@ -33,6 +33,7 @@ import {
isNetDataInstalledOnHost,
getPlugin,
restartHost,
setControlDomainMemory,
setHostsMultipathing,
setRemoteSyslogHost,
setSchedulerGranularity,
Expand Down Expand Up @@ -70,6 +71,22 @@ const formatPack = ({ name, author, description, version }, key) => (

const getPackId = ({ author, name }) => `${author}\0${name}`

const SetControlDomainMemory = ({ value, onChange }) => (
<Container>
<Row className='mb-1'>
<Col>
<Icon icon='error' /> {_('setControlDomainMemoryMessage')}
</Col>
</Row>
<Row>
<Col size={6}>{_('vmMemory')}</Col>
<Col size={6}>
<SizeInput required value={value} onChange={onChange} />
</Col>
</Row>
</Container>
)

const MultipathableSrs = decorate([
connectStore({
pbds: createGetObjectsOfType('PBD').filter((_, { hostId }) => pbd =>
Expand Down Expand Up @@ -111,13 +128,16 @@ MultipathableSrs.propTypes = {
schedGran: cb => subscribeSchedulerGranularity(props.host.id, cb),
}))
@connectStore(() => {
const getControlDomain = createGetObject((_, { host }) => host.controlDomain)

const getPgpus = createGetObjectsOfType('PGPU')
.pick((_, { host }) => host.$PGPUs)
.sort()

const getPcis = createGetObjectsOfType('PCI').pick(createSelector(getPgpus, pgpus => map(pgpus, 'pci')))

return {
controlDomain: getControlDomain,
pcis: getPcis,
pgpus: getPgpus,
}
Expand Down Expand Up @@ -174,6 +194,17 @@ export default class extends Component {

_setRemoteSyslogHost = value => setRemoteSyslogHost(this.props.host, value)

_setControlDomainMemory = () =>
form({
component: SetControlDomainMemory,
defaultValue: this.props.controlDomain.memory.size,
header: (
<span>
<Icon icon='memory' /> {_('setControlDomainMemory')}
</span>
),
}).then(memory => setControlDomainMemory(this.props.host.id, memory), noop)

_accessAdvancedLiveTelemetry = () => window.open(`/netdata/host/${encodeURIComponent(this.props.host.hostname)}/`)

_enableAdvancedLiveTelemetry = async host => {
Expand All @@ -184,7 +215,7 @@ export default class extends Component {
}

render() {
const { host, pcis, pgpus, schedGran } = this.props
const { controlDomain, host, pcis, pgpus, schedGran } = this.props
const { isHtEnabled, isNetDataPluginInstalledOnHost, isNetDataPluginCorrectlySet } = this.state

const _isXcpNgHost = host.productBrand === 'XCP-ng'
Expand Down Expand Up @@ -290,6 +321,25 @@ export default class extends Component {
<Toggle disabled onChange={noop} value={Boolean(host.powerOnMode)} />
</td>
</tr>
<tr>
<th>{_('hostControlDomainMemory')}</th>
<td>
{controlDomain !== undefined && (
<span>
{formatSize(controlDomain.memory.size)}{' '}
<Tooltip content={host.enabled ? _('maintenanceModeRequired') : _('setControlDomainMemory')}>
<ActionButton
btnStyle='primary'
disabled={host.enabled}
handler={this._setControlDomainMemory}
icon='edit'
size='small'
/>
</Tooltip>
</span>
)}
</td>
</tr>
<tr>
<th>{_('hostStartedSince')}</th>
<td>
Expand Down

0 comments on commit cf9f6c1

Please sign in to comment.