feat(xo-web/sr): show coalescing status (#7241)

This commit is contained in:
Florent BEAUCHAMP
2023-12-21 11:29:32 +01:00
committed by GitHub
parent 2c298ef47a
commit 213eb6a56a
4 changed files with 30 additions and 7 deletions
+3
View File
@@ -6,6 +6,7 @@
### Enhancements ### Enhancements
> Users must be able to say: “Nice enhancement, I'm eager to test it” > Users must be able to say: “Nice enhancement, I'm eager to test it”
- [SR] show an icon on SR during VDI coalescing (with XCP-ng 8.3+) (PR [#7241](https://github.com/vatesfr/xen-orchestra/pull/7241))
### Bug fixes ### Bug fixes
@@ -27,4 +28,6 @@
<!--packages-start--> <!--packages-start-->
- xo-web minor
<!--packages-end--> <!--packages-end-->
+4
View File
@@ -136,6 +136,10 @@
@extend .fa; @extend .fa;
@extend .fa-caret-up; @extend .fa-caret-up;
} }
&-coalesce {
@extend .fa;
@extend .fa-cog;
}
&-loading { &-loading {
@extend .fa; @extend .fa;
@extend .fa-spinner; @extend .fa-spinner;
+11 -1
View File
@@ -17,6 +17,11 @@ import { connectStore, formatSizeShort, getIscsiPaths } from 'utils'
import styles from './index.css' import styles from './index.css'
@connectStore({ @connectStore({
coalesceTask: createSelector(
(_, props) => props.item,
createGetObjectsOfType('task').groupBy('applies_to'),
(sr, tasks) => tasks[sr.uuid]?.[0]
),
container: createGetObject((_, props) => props.item.$container), container: createGetObject((_, props) => props.item.$container),
isHa: createSelector( isHa: createSelector(
(_, props) => props.item, (_, props) => props.item,
@@ -102,7 +107,7 @@ export default class SrItem extends Component {
} }
render() { render() {
const { container, expandAll, isDefaultSr, isHa, isShared, item: sr, selected } = this.props const { coalesceTask, container, expandAll, isDefaultSr, isHa, isShared, item: sr, selected } = this.props
return ( return (
<div className={styles.item}> <div className={styles.item}>
@@ -123,6 +128,11 @@ export default class SrItem extends Component {
<span className='tag tag-pill tag-info ml-1'>{_('ha')}</span> <span className='tag tag-pill tag-info ml-1'>{_('ha')}</span>
</Tooltip> </Tooltip>
)} )}
{coalesceTask !== undefined && (
<Tooltip content={`${coalesceTask.name_label} ${Math.round(coalesceTask.progress * 100)}%`}>
<Icon icon='coalesce' fixedWidth />
</Tooltip>
)}
{sr.inMaintenanceMode && <span className='tag tag-pill tag-warning ml-1'>{_('maintenanceMode')}</span>} {sr.inMaintenanceMode && <span className='tag tag-pill tag-warning ml-1'>{_('maintenanceMode')}</span>}
</EllipsisContainer> </EllipsisContainer>
</Col> </Col>
+12 -6
View File
@@ -1,4 +1,5 @@
import _ from 'intl' import _ from 'intl'
import Icon from 'icon'
import Link from 'link' import Link from 'link'
import map from 'lodash/map' import map from 'lodash/map'
import React from 'react' import React from 'react'
@@ -29,9 +30,14 @@ const forgetSrs = pbds =>
const SR_COLUMNS = [ const SR_COLUMNS = [
{ {
name: _('srName'), name: _('srName'),
itemRenderer: storage => ( itemRenderer: ({ id, nameLabel, coalesceTask }) => (
<Link to={`/srs/${storage.id}`}> <Link to={`/srs/${id}`}>
<Text onChange={nameLabel => editSr(storage.id, { nameLabel })} useLongClick value={storage.nameLabel} /> <Text onChange={nameLabel => editSr(id, { nameLabel })} useLongClick value={nameLabel} />
{coalesceTask !== undefined && (
<Tooltip content={`${coalesceTask.name_label} ${Math.round(coalesceTask.progress * 100)}%`}>
<Icon icon='coalesce' />
</Tooltip>
)}
</Link> </Link>
), ),
sortCriteria: 'nameLabel', sortCriteria: 'nameLabel',
@@ -113,14 +119,13 @@ const SR_ACTIONS = [
export default connectStore(() => { export default connectStore(() => {
const pbds = createGetObjectsOfType('PBD').pick((_, props) => props.host.$PBDs) const pbds = createGetObjectsOfType('PBD').pick((_, props) => props.host.$PBDs)
const srs = createGetObjectsOfType('SR').pick(createSelector(pbds, pbds => map(pbds, pbd => pbd.SR))) const srs = createGetObjectsOfType('SR').pick(createSelector(pbds, pbds => map(pbds, pbd => pbd.SR)))
const coalesceTasks = createGetObjectsOfType('task').groupBy('applies_to')
const storages = createSelector(pbds, srs, (pbds, srs) => const storages = createSelector(pbds, srs, coalesceTasks, (pbds, srs, coalesceTasks) =>
map( map(
filter(pbds, pbd => srs[pbd.SR] !== undefined), filter(pbds, pbd => srs[pbd.SR] !== undefined),
pbd => { pbd => {
const sr = srs[pbd.SR] const sr = srs[pbd.SR]
const { physical_usage: usage, size } = sr const { physical_usage: usage, size } = sr
return { return {
attached: pbd.attached, attached: pbd.attached,
pbdDeviceConfig: pbd.device_config, pbdDeviceConfig: pbd.device_config,
@@ -132,6 +137,7 @@ export default connectStore(() => {
shared: isSrShared(sr), shared: isSrShared(sr),
size: size > 0 ? size : 0, size: size > 0 ? size : 0,
usagePercentage: size > 0 && Math.round((100 * usage) / size), usagePercentage: size > 0 && Math.round((100 * usage) / size),
coalesceTask: coalesceTasks[pbd.SR]?.[0], // there can be only one coalesce task by SR
} }
} }
) )