parent
d1db616d1e
commit
66ba05dcd0
@ -13,6 +13,7 @@
|
||||
- [Groups] Ability to delete multiple groups at once (PR [#5264](https://github.com/vatesfr/xen-orchestra/pull/5264))
|
||||
- [Backup/logs] Log's tasks pagination [#4406](https://github.com/vatesfr/xen-orchestra/issues/4406) (PR [#5209](https://github.com/vatesfr/xen-orchestra/pull/5209))
|
||||
- [Backup logs] Ability to filter by VM/pool name [#4406](https://github.com/vatesfr/xen-orchestra/issues/4406) (PR [#5208](https://github.com/vatesfr/xen-orchestra/pull/5208))
|
||||
- [Tasks] Show XO objects linked to pending/finished tasks [#4275](https://github.com/vatesfr/xen-orchestra/issues/4275) (PR [#5267](https://github.com/vatesfr/xen-orchestra/pull/5267))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
@ -44,5 +45,6 @@
|
||||
|
||||
- @xen-orchestra/fs patch
|
||||
- xo-vmdk-to-vhd patch
|
||||
- xo-server minor
|
||||
- xo-web minor
|
||||
- xo-server patch
|
||||
|
@ -117,6 +117,7 @@ const TRANSFORMS = {
|
||||
pool(obj) {
|
||||
const cpuInfo = obj.cpu_info
|
||||
return {
|
||||
current_operations: obj.current_operations,
|
||||
default_SR: link(obj, 'default_SR'),
|
||||
HA_enabled: Boolean(obj.ha_enabled),
|
||||
master: link(obj, 'master'),
|
||||
@ -525,6 +526,7 @@ const TRANSFORMS = {
|
||||
physical_usage: +obj.physical_utilisation,
|
||||
|
||||
allocationStrategy: ALLOCATION_BY_TYPE[srType],
|
||||
current_operations: obj.current_operations,
|
||||
name_description: obj.name_description,
|
||||
name_label: obj.name_label,
|
||||
size: +obj.physical_size,
|
||||
@ -609,6 +611,7 @@ const TRANSFORMS = {
|
||||
tags: obj.tags,
|
||||
usage: +obj.physical_utilisation,
|
||||
VDI_type: obj.type,
|
||||
current_operations: obj.current_operations,
|
||||
|
||||
$SR: link(obj, 'SR'),
|
||||
$VBDs: link(obj, 'VBDs'),
|
||||
@ -682,6 +685,7 @@ const TRANSFORMS = {
|
||||
return {
|
||||
automatic: obj.other_config?.automatic === 'true',
|
||||
bridge: obj.bridge,
|
||||
current_operations: obj.current_operations,
|
||||
defaultIsLocked: obj.default_locking_mode === 'disabled',
|
||||
MTU: +obj.MTU,
|
||||
name_description: obj.name_description,
|
||||
@ -718,6 +722,7 @@ const TRANSFORMS = {
|
||||
progress: +obj.progress,
|
||||
result: obj.result,
|
||||
status: obj.status,
|
||||
xapiRef: obj.$ref,
|
||||
|
||||
$host: link(obj, 'resident_on'),
|
||||
}
|
||||
|
@ -1546,6 +1546,7 @@ const messages = {
|
||||
destroyTask: 'Destroy',
|
||||
cancelTasks: 'Cancel selected tasks',
|
||||
destroyTasks: 'Destroy selected tasks',
|
||||
objects: 'Objects',
|
||||
pool: 'Pool',
|
||||
task: 'Task',
|
||||
progress: 'Progress',
|
||||
|
@ -1,9 +1,11 @@
|
||||
import _, { messages } from 'intl'
|
||||
import Collapse from 'collapse'
|
||||
import Component from 'base-component'
|
||||
import defined from '@xen-orchestra/defined'
|
||||
import Icon from 'icon'
|
||||
import Link from 'link'
|
||||
import React from 'react'
|
||||
import renderXoItem, { Pool } from 'render-xo-item'
|
||||
import SortedTable from 'sorted-table'
|
||||
import { FormattedDate, injectIntl } from 'react-intl'
|
||||
import { SelectPool } from 'select-objects'
|
||||
@ -13,12 +15,14 @@ import {
|
||||
differenceBy,
|
||||
flatMap,
|
||||
flatten,
|
||||
forOwn,
|
||||
groupBy,
|
||||
isEmpty,
|
||||
keys,
|
||||
map,
|
||||
some,
|
||||
toArray,
|
||||
} from 'lodash'
|
||||
import { Pool } from 'render-xo-item'
|
||||
import {
|
||||
createFilter,
|
||||
createGetObject,
|
||||
@ -41,6 +45,16 @@ const HEADER = (
|
||||
</Container>
|
||||
)
|
||||
|
||||
const Ul = props => <ul {...props} style={{ listStyleType: 'none' }} />
|
||||
const Li = props => (
|
||||
<li
|
||||
{...props}
|
||||
style={{
|
||||
whiteSpace: 'nowrap',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
const TASK_ITEM_STYLE = {
|
||||
// Remove all margin, otherwise it breaks vertical alignment.
|
||||
margin: 0,
|
||||
@ -70,6 +84,33 @@ export class TaskItem extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
const taskObjectsRenderer = ({ objects }) => (
|
||||
<Ul>
|
||||
{map(objects, obj => {
|
||||
const { id, type } = obj
|
||||
return type === 'VDI' || type === 'network' ? (
|
||||
<Li key={id}>{renderXoItem(obj)}</Li>
|
||||
) : (
|
||||
<Li key={id}>
|
||||
<Link to={`/${type}s/${id}`}>{renderXoItem(obj)}</Link>
|
||||
</Li>
|
||||
)
|
||||
})}
|
||||
</Ul>
|
||||
)
|
||||
|
||||
const COMMON = [
|
||||
{
|
||||
component: TaskItem,
|
||||
name: _('task'),
|
||||
sortCriteria: 'name_label',
|
||||
},
|
||||
{
|
||||
itemRenderer: taskObjectsRenderer,
|
||||
name: _('objects'),
|
||||
},
|
||||
]
|
||||
|
||||
const COLUMNS = [
|
||||
{
|
||||
default: true,
|
||||
@ -80,11 +121,7 @@ const COLUMNS = [
|
||||
return pool !== undefined && pool.name_label
|
||||
},
|
||||
},
|
||||
{
|
||||
component: TaskItem,
|
||||
name: _('task'),
|
||||
sortCriteria: 'name_label',
|
||||
},
|
||||
...COMMON,
|
||||
{
|
||||
itemRenderer: task => (
|
||||
<progress
|
||||
@ -104,10 +141,7 @@ const FINISHED_TASKS_COLUMNS = [
|
||||
itemRenderer: ({ $poolId }) => <Pool id={$poolId} link />,
|
||||
name: _('pool'),
|
||||
},
|
||||
{
|
||||
component: TaskItem,
|
||||
name: _('task'),
|
||||
},
|
||||
...COMMON,
|
||||
{
|
||||
default: true,
|
||||
itemRenderer: task => (
|
||||
@ -168,7 +202,54 @@ const GROUPED_ACTIONS = [
|
||||
|
||||
const getNPendingTasks = getPendingTasks.count()
|
||||
|
||||
const getPendingTasksByPool = getPendingTasks.sort().groupBy('$pool')
|
||||
const predicate = obj => !isEmpty(obj.current_operations)
|
||||
|
||||
const getLinkedObjectsByTaskRefOrId = createSelector(
|
||||
createGetObjectsOfType('pool').filter([predicate]),
|
||||
createGetObjectsOfType('host').filter([predicate]),
|
||||
createGetObjectsOfType('SR').filter([predicate]),
|
||||
createGetObjectsOfType('VDI').filter([predicate]),
|
||||
createGetObjectsOfType('VM').filter([predicate]),
|
||||
createGetObjectsOfType('network').filter([predicate]),
|
||||
(pools, hosts, srs, vdis, vms, networks) => {
|
||||
const linkedObjectsByTaskRefOrId = {}
|
||||
const resolveLinkedObjects = obj => {
|
||||
Object.keys(obj.current_operations).forEach(task => {
|
||||
if (linkedObjectsByTaskRefOrId[task] === undefined) {
|
||||
linkedObjectsByTaskRefOrId[task] = []
|
||||
}
|
||||
linkedObjectsByTaskRefOrId[task].push(obj)
|
||||
})
|
||||
}
|
||||
|
||||
forOwn(pools, resolveLinkedObjects)
|
||||
forOwn(hosts, resolveLinkedObjects)
|
||||
forOwn(srs, resolveLinkedObjects)
|
||||
forOwn(vdis, resolveLinkedObjects)
|
||||
forOwn(vms, resolveLinkedObjects)
|
||||
forOwn(networks, resolveLinkedObjects)
|
||||
|
||||
return linkedObjectsByTaskRefOrId
|
||||
}
|
||||
)
|
||||
|
||||
const getPendingTasksByPool = createSelector(
|
||||
getPendingTasks,
|
||||
getLinkedObjectsByTaskRefOrId,
|
||||
(tasks, linkedObjectsByTaskRefOrId) =>
|
||||
groupBy(
|
||||
map(tasks, task => ({
|
||||
...task,
|
||||
objects: [
|
||||
...defined(linkedObjectsByTaskRefOrId[task.xapiRef], []),
|
||||
// for VMs, the current_operations prop is
|
||||
// { taskId → operation } map instead of { taskRef → operation } map
|
||||
...defined(linkedObjectsByTaskRefOrId[task.id], []),
|
||||
],
|
||||
})),
|
||||
'$pool'
|
||||
)
|
||||
)
|
||||
|
||||
const getPools = createGetObjectsOfType('pool').pick(
|
||||
createSelector(getPendingTasksByPool, keys)
|
||||
|
Loading…
Reference in New Issue
Block a user