feat(xo-web/sr): show coalescing status (#7241)
This commit is contained in:
@@ -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-->
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user