feat(xo-web/host): ability to enable/disable multipathing (#3865)
See #3659
This commit is contained in:
parent
810c976d37
commit
e9fb37325d
@ -12,6 +12,7 @@
|
||||
- [Backup NG] Support zstd compression for full backups [#3773](https://github.com/vatesfr/xen-orchestra/issues/3773) (PR [#3883](https://github.com/vatesfr/xen-orchestra/pull/3883))
|
||||
- [VM] Ability to copy a VM with zstd compression [#3773](https://github.com/vatesfr/xen-orchestra/issues/3773) (PR [#3889](https://github.com/vatesfr/xen-orchestra/pull/3889))
|
||||
- [VM & Host] "Pool > Host" breadcrumb at the top of the page (PR [#3898](https://github.com/vatesfr/xen-orchestra/pull/3898))
|
||||
- [Hosts] Ability to enable/disable host multipathing [#3659](https://github.com/vatesfr/xen-orchestra/issues/3659) (PR [#3865](https://github.com/vatesfr/xen-orchestra/pull/3865))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
@ -173,6 +173,7 @@ const TRANSFORMS = {
|
||||
total: 0,
|
||||
}
|
||||
})(),
|
||||
multipathing: obj.multipathing,
|
||||
patches: patches || link(obj, 'patches'),
|
||||
powerOnMode: obj.power_on_mode,
|
||||
power_state: metrics ? (isRunning ? 'Running' : 'Halted') : 'Unknown',
|
||||
|
@ -67,7 +67,7 @@ export default class ActionButton extends Component {
|
||||
const { children, handler, tooltip } = props
|
||||
|
||||
let handlerParam
|
||||
if ('handlerParam' in props) {
|
||||
if (props.handlerParam !== undefined) {
|
||||
handlerParam = props.handlerParam
|
||||
} else {
|
||||
let empty = true
|
||||
|
@ -21,6 +21,11 @@ const messages = {
|
||||
showLogs: 'Show logs',
|
||||
noValue: 'None',
|
||||
compression: 'Compression',
|
||||
multipathing: 'Multipathing',
|
||||
enableMultipathing: 'Enable multipathing',
|
||||
disableMultipathing: 'Disable multipathing',
|
||||
enableAllHostsMultipathing: 'Enable all hosts multipathing',
|
||||
disableAllHostsMultipathing: 'Disable all hosts multipathing',
|
||||
|
||||
// ----- Modals -----
|
||||
alertOk: 'OK',
|
||||
@ -757,6 +762,9 @@ const messages = {
|
||||
hostStatus: 'Status',
|
||||
hostBuildNumber: 'Build number',
|
||||
hostIscsiName: 'iSCSI name',
|
||||
hostMultipathingSrs: 'Click to see concerned SRs',
|
||||
hostMultipathingWarning:
|
||||
'The host{nHosts, plural, one {} other {s}} will lose the connection to the SRs. Do you want to continue?',
|
||||
hostXenServerVersion: 'Version',
|
||||
hostStatusEnabled: 'Enabled',
|
||||
hostStatusDisabled: 'Disabled',
|
||||
|
@ -589,6 +589,22 @@ export const setPoolMaster = host =>
|
||||
export const editHost = (host, props) =>
|
||||
_call('host.set', { ...props, id: resolveId(host) })
|
||||
|
||||
import MultipathingModalBody from './multipathing-modal' // eslint-disable-line import/first
|
||||
export const setHostsMultipathing = ({
|
||||
host,
|
||||
hosts = [host],
|
||||
multipathing,
|
||||
}) => {
|
||||
const ids = resolveIds(hosts)
|
||||
return confirm({
|
||||
title: _(multipathing ? 'enableMultipathing' : 'disableMultipathing'),
|
||||
body: <MultipathingModalBody hostIds={ids} />,
|
||||
}).then(
|
||||
() => Promise.all(map(ids, id => editHost(id, { multipathing }))),
|
||||
noop
|
||||
)
|
||||
}
|
||||
|
||||
export const fetchHostStats = (host, granularity) =>
|
||||
_call('host.stats', { host: resolveId(host), granularity })
|
||||
|
||||
|
53
packages/xo-web/src/common/xo/multipathing-modal/index.js
Normal file
53
packages/xo-web/src/common/xo/multipathing-modal/index.js
Normal file
@ -0,0 +1,53 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import React, { Component } from 'react'
|
||||
|
||||
import _ from '../../intl'
|
||||
import Collapse from '../../collapse'
|
||||
import { connectStore } from '../../utils'
|
||||
import { createGetObjectsOfType, createSelector } from '../../selectors'
|
||||
import { Sr } from '../../render-xo-item'
|
||||
|
||||
@connectStore(
|
||||
{
|
||||
srIds: createSelector(
|
||||
createGetObjectsOfType('PBD').filter((_, { hostIds }) => pbd =>
|
||||
hostIds.includes(pbd.host)
|
||||
),
|
||||
pbds => {
|
||||
const srIds = new Set([])
|
||||
for (const id in pbds) {
|
||||
srIds.add(pbds[id].SR)
|
||||
}
|
||||
return [...srIds]
|
||||
}
|
||||
),
|
||||
},
|
||||
{ withRef: true }
|
||||
)
|
||||
export default class MultipathingModal extends Component {
|
||||
static propTypes = {
|
||||
hostIds: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { hostIds, srIds } = this.props
|
||||
return (
|
||||
<div>
|
||||
{_('hostMultipathingWarning', {
|
||||
nHosts: hostIds.length,
|
||||
})}
|
||||
<Collapse
|
||||
buttonText={_('hostMultipathingSrs')}
|
||||
size='small'
|
||||
className='mt-1'
|
||||
>
|
||||
{srIds.map(srId => (
|
||||
<div key={srId}>
|
||||
<Sr id={srId} link newTab />
|
||||
</div>
|
||||
))}
|
||||
</Collapse>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
@ -2,8 +2,9 @@ import _ from 'intl'
|
||||
import Component from 'base-component'
|
||||
import Copiable from 'copiable'
|
||||
import React from 'react'
|
||||
import TabButton from 'tab-button'
|
||||
import SelectFiles from 'select-files'
|
||||
import StateButton from 'state-button'
|
||||
import TabButton from 'tab-button'
|
||||
import Upgrade from 'xoa-upgrade'
|
||||
import { Text } from 'editable'
|
||||
import { Toggle } from 'form'
|
||||
@ -13,13 +14,14 @@ import { Container, Row, Col } from 'grid'
|
||||
import { forEach, map, noop } from 'lodash'
|
||||
import { createGetObjectsOfType, createSelector } from 'selectors'
|
||||
import {
|
||||
enableHost,
|
||||
detachHost,
|
||||
disableHost,
|
||||
enableHost,
|
||||
forgetHost,
|
||||
setRemoteSyslogHost,
|
||||
restartHost,
|
||||
installSupplementalPack,
|
||||
restartHost,
|
||||
setHostsMultipathing,
|
||||
setRemoteSyslogHost,
|
||||
} from 'xo'
|
||||
|
||||
const ALLOW_INSTALL_SUPP_PACK = process.env.XOA_PLAN > 1
|
||||
@ -183,6 +185,22 @@ export default class extends Component {
|
||||
<th>{_('hostIscsiName')}</th>
|
||||
<Copiable tagName='td'>{host.iSCSI_name}</Copiable>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{_('multipathing')}</th>
|
||||
<td>
|
||||
<StateButton
|
||||
className='mb-1'
|
||||
data-host={host}
|
||||
data-multipathing={!host.multipathing}
|
||||
disabledLabel={_('stateDisabled')}
|
||||
disabledTooltip={_('enableMultipathing')}
|
||||
enabledLabel={_('stateEnabled')}
|
||||
enabledTooltip={_('disableMultipathing')}
|
||||
handler={setHostsMultipathing}
|
||||
state={host.multipathing}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{_('hostRemoteSyslog')}</th>
|
||||
<td>
|
||||
|
@ -7,14 +7,15 @@ import Component from 'base-component'
|
||||
import renderXoItem from 'render-xo-item'
|
||||
import SelectFiles from 'select-files'
|
||||
import Upgrade from 'xoa-upgrade'
|
||||
import { map } from 'lodash'
|
||||
import { connectStore } from 'utils'
|
||||
import { injectIntl } from 'react-intl'
|
||||
import { createGetObjectsOfType } from 'selectors'
|
||||
import { Text, XoSelect } from 'editable'
|
||||
import { Container, Row, Col } from 'grid'
|
||||
import { createGetObjectsOfType, createGroupBy } from 'selectors'
|
||||
import { injectIntl } from 'react-intl'
|
||||
import { map } from 'lodash'
|
||||
import { Text, XoSelect } from 'editable'
|
||||
import {
|
||||
installSupplementalPackOnAllHosts,
|
||||
setHostsMultipathing,
|
||||
setPoolMaster,
|
||||
setRemoteSyslogHost,
|
||||
setRemoteSyslogHosts,
|
||||
@ -47,13 +48,19 @@ class PoolMaster extends Component {
|
||||
}
|
||||
|
||||
@injectIntl
|
||||
@connectStore({
|
||||
hosts: createGetObjectsOfType('host')
|
||||
@connectStore(() => {
|
||||
const getHosts = createGetObjectsOfType('host')
|
||||
.filter((_, { pool }) => ({ $pool: pool.id }))
|
||||
.sort(),
|
||||
gpuGroups: createGetObjectsOfType('gpuGroup')
|
||||
.filter((_, { pool }) => ({ $pool: pool.id }))
|
||||
.sort(),
|
||||
.sort()
|
||||
return {
|
||||
hosts: getHosts,
|
||||
hostsByMultipathing: createGroupBy(getHosts, () => ({ multipathing }) =>
|
||||
multipathing ? 'enabled' : 'disabled'
|
||||
),
|
||||
gpuGroups: createGetObjectsOfType('gpuGroup')
|
||||
.filter((_, { pool }) => ({ $pool: pool.id }))
|
||||
.sort(),
|
||||
}
|
||||
})
|
||||
export default class TabAdvanced extends Component {
|
||||
_setRemoteSyslogHosts = () =>
|
||||
@ -62,9 +69,13 @@ export default class TabAdvanced extends Component {
|
||||
)
|
||||
|
||||
render() {
|
||||
const { hosts, gpuGroups, pool } = this.props
|
||||
const { hosts, gpuGroups, pool, hostsByMultipathing } = this.props
|
||||
const { state } = this
|
||||
const { editRemoteSyslog } = state
|
||||
const {
|
||||
enabled: hostsEnabledMultipathing,
|
||||
disabled: hostsDisabledMultipathing,
|
||||
} = hostsByMultipathing
|
||||
return (
|
||||
<div>
|
||||
<Container>
|
||||
@ -159,6 +170,29 @@ export default class TabAdvanced extends Component {
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
<h3 className='mt-1 mb-1'>{_('multipathing')}</h3>
|
||||
<div>
|
||||
<ActionButton
|
||||
btnStyle='success'
|
||||
data-hosts={hostsDisabledMultipathing}
|
||||
data-multipathing
|
||||
disabled={hostsDisabledMultipathing === undefined}
|
||||
handler={setHostsMultipathing}
|
||||
icon='host'
|
||||
>
|
||||
{_('enableAllHostsMultipathing')}
|
||||
</ActionButton>{' '}
|
||||
<ActionButton
|
||||
btnStyle='danger'
|
||||
data-hosts={hostsEnabledMultipathing}
|
||||
data-multipathing={false}
|
||||
disabled={hostsEnabledMultipathing === undefined}
|
||||
handler={setHostsMultipathing}
|
||||
icon='host'
|
||||
>
|
||||
{_('disableAllHostsMultipathing')}
|
||||
</ActionButton>
|
||||
</div>
|
||||
<h3 className='mt-1 mb-1'>{_('supplementalPackPoolNew')}</h3>
|
||||
<Upgrade place='poolSupplementalPacks' required={2}>
|
||||
<SelectFiles
|
||||
|
Loading…
Reference in New Issue
Block a user