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))
|
- [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] 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))
|
- [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
|
### Bug fixes
|
||||||
|
|
||||||
@ -44,5 +45,6 @@
|
|||||||
|
|
||||||
- @xen-orchestra/fs patch
|
- @xen-orchestra/fs patch
|
||||||
- xo-vmdk-to-vhd patch
|
- xo-vmdk-to-vhd patch
|
||||||
|
- xo-server minor
|
||||||
- xo-web minor
|
- xo-web minor
|
||||||
- xo-server patch
|
- xo-server patch
|
||||||
|
@ -117,6 +117,7 @@ const TRANSFORMS = {
|
|||||||
pool(obj) {
|
pool(obj) {
|
||||||
const cpuInfo = obj.cpu_info
|
const cpuInfo = obj.cpu_info
|
||||||
return {
|
return {
|
||||||
|
current_operations: obj.current_operations,
|
||||||
default_SR: link(obj, 'default_SR'),
|
default_SR: link(obj, 'default_SR'),
|
||||||
HA_enabled: Boolean(obj.ha_enabled),
|
HA_enabled: Boolean(obj.ha_enabled),
|
||||||
master: link(obj, 'master'),
|
master: link(obj, 'master'),
|
||||||
@ -525,6 +526,7 @@ const TRANSFORMS = {
|
|||||||
physical_usage: +obj.physical_utilisation,
|
physical_usage: +obj.physical_utilisation,
|
||||||
|
|
||||||
allocationStrategy: ALLOCATION_BY_TYPE[srType],
|
allocationStrategy: ALLOCATION_BY_TYPE[srType],
|
||||||
|
current_operations: obj.current_operations,
|
||||||
name_description: obj.name_description,
|
name_description: obj.name_description,
|
||||||
name_label: obj.name_label,
|
name_label: obj.name_label,
|
||||||
size: +obj.physical_size,
|
size: +obj.physical_size,
|
||||||
@ -609,6 +611,7 @@ const TRANSFORMS = {
|
|||||||
tags: obj.tags,
|
tags: obj.tags,
|
||||||
usage: +obj.physical_utilisation,
|
usage: +obj.physical_utilisation,
|
||||||
VDI_type: obj.type,
|
VDI_type: obj.type,
|
||||||
|
current_operations: obj.current_operations,
|
||||||
|
|
||||||
$SR: link(obj, 'SR'),
|
$SR: link(obj, 'SR'),
|
||||||
$VBDs: link(obj, 'VBDs'),
|
$VBDs: link(obj, 'VBDs'),
|
||||||
@ -682,6 +685,7 @@ const TRANSFORMS = {
|
|||||||
return {
|
return {
|
||||||
automatic: obj.other_config?.automatic === 'true',
|
automatic: obj.other_config?.automatic === 'true',
|
||||||
bridge: obj.bridge,
|
bridge: obj.bridge,
|
||||||
|
current_operations: obj.current_operations,
|
||||||
defaultIsLocked: obj.default_locking_mode === 'disabled',
|
defaultIsLocked: obj.default_locking_mode === 'disabled',
|
||||||
MTU: +obj.MTU,
|
MTU: +obj.MTU,
|
||||||
name_description: obj.name_description,
|
name_description: obj.name_description,
|
||||||
@ -718,6 +722,7 @@ const TRANSFORMS = {
|
|||||||
progress: +obj.progress,
|
progress: +obj.progress,
|
||||||
result: obj.result,
|
result: obj.result,
|
||||||
status: obj.status,
|
status: obj.status,
|
||||||
|
xapiRef: obj.$ref,
|
||||||
|
|
||||||
$host: link(obj, 'resident_on'),
|
$host: link(obj, 'resident_on'),
|
||||||
}
|
}
|
||||||
|
@ -1546,6 +1546,7 @@ const messages = {
|
|||||||
destroyTask: 'Destroy',
|
destroyTask: 'Destroy',
|
||||||
cancelTasks: 'Cancel selected tasks',
|
cancelTasks: 'Cancel selected tasks',
|
||||||
destroyTasks: 'Destroy selected tasks',
|
destroyTasks: 'Destroy selected tasks',
|
||||||
|
objects: 'Objects',
|
||||||
pool: 'Pool',
|
pool: 'Pool',
|
||||||
task: 'Task',
|
task: 'Task',
|
||||||
progress: 'Progress',
|
progress: 'Progress',
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import _, { messages } from 'intl'
|
import _, { messages } from 'intl'
|
||||||
import Collapse from 'collapse'
|
import Collapse from 'collapse'
|
||||||
import Component from 'base-component'
|
import Component from 'base-component'
|
||||||
|
import defined from '@xen-orchestra/defined'
|
||||||
import Icon from 'icon'
|
import Icon from 'icon'
|
||||||
import Link from 'link'
|
import Link from 'link'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import renderXoItem, { Pool } from 'render-xo-item'
|
||||||
import SortedTable from 'sorted-table'
|
import SortedTable from 'sorted-table'
|
||||||
import { FormattedDate, injectIntl } from 'react-intl'
|
import { FormattedDate, injectIntl } from 'react-intl'
|
||||||
import { SelectPool } from 'select-objects'
|
import { SelectPool } from 'select-objects'
|
||||||
@ -13,12 +15,14 @@ import {
|
|||||||
differenceBy,
|
differenceBy,
|
||||||
flatMap,
|
flatMap,
|
||||||
flatten,
|
flatten,
|
||||||
|
forOwn,
|
||||||
|
groupBy,
|
||||||
isEmpty,
|
isEmpty,
|
||||||
keys,
|
keys,
|
||||||
|
map,
|
||||||
some,
|
some,
|
||||||
toArray,
|
toArray,
|
||||||
} from 'lodash'
|
} from 'lodash'
|
||||||
import { Pool } from 'render-xo-item'
|
|
||||||
import {
|
import {
|
||||||
createFilter,
|
createFilter,
|
||||||
createGetObject,
|
createGetObject,
|
||||||
@ -41,6 +45,16 @@ const HEADER = (
|
|||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const Ul = props => <ul {...props} style={{ listStyleType: 'none' }} />
|
||||||
|
const Li = props => (
|
||||||
|
<li
|
||||||
|
{...props}
|
||||||
|
style={{
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
|
||||||
const TASK_ITEM_STYLE = {
|
const TASK_ITEM_STYLE = {
|
||||||
// Remove all margin, otherwise it breaks vertical alignment.
|
// Remove all margin, otherwise it breaks vertical alignment.
|
||||||
margin: 0,
|
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 = [
|
const COLUMNS = [
|
||||||
{
|
{
|
||||||
default: true,
|
default: true,
|
||||||
@ -80,11 +121,7 @@ const COLUMNS = [
|
|||||||
return pool !== undefined && pool.name_label
|
return pool !== undefined && pool.name_label
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
...COMMON,
|
||||||
component: TaskItem,
|
|
||||||
name: _('task'),
|
|
||||||
sortCriteria: 'name_label',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
itemRenderer: task => (
|
itemRenderer: task => (
|
||||||
<progress
|
<progress
|
||||||
@ -104,10 +141,7 @@ const FINISHED_TASKS_COLUMNS = [
|
|||||||
itemRenderer: ({ $poolId }) => <Pool id={$poolId} link />,
|
itemRenderer: ({ $poolId }) => <Pool id={$poolId} link />,
|
||||||
name: _('pool'),
|
name: _('pool'),
|
||||||
},
|
},
|
||||||
{
|
...COMMON,
|
||||||
component: TaskItem,
|
|
||||||
name: _('task'),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
default: true,
|
default: true,
|
||||||
itemRenderer: task => (
|
itemRenderer: task => (
|
||||||
@ -168,7 +202,54 @@ const GROUPED_ACTIONS = [
|
|||||||
|
|
||||||
const getNPendingTasks = getPendingTasks.count()
|
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(
|
const getPools = createGetObjectsOfType('pool').pick(
|
||||||
createSelector(getPendingTasksByPool, keys)
|
createSelector(getPendingTasksByPool, keys)
|
||||||
|
Loading…
Reference in New Issue
Block a user