feat(backup-ng): ability to restart all failed VMs (#3420)

Fixes #3339
This commit is contained in:
badrAZ 2018-09-20 17:05:57 +02:00 committed by Julien Fontanet
parent 0215c19d1d
commit a71740d49a
5 changed files with 60 additions and 20 deletions

View File

@ -11,6 +11,7 @@
- [Backup NG Overview] Display transferred and merged data size for backup jobs [#3340](https://github.com/vatesfr/xen-orchestra/issues/3340) (PR [#3408](https://github.com/vatesfr/xen-orchestra/pull/3408))
- [VM] Display the PVHVM status [#3014](https://github.com/vatesfr/xen-orchestra/issues/3014) (PR [#3418](https://github.com/vatesfr/xen-orchestra/pull/3418))
- [Backup reports] Ability to test the plugin (PR [#3421](https://github.com/vatesfr/xen-orchestra/pull/3421))
- [Backup NG] Ability to restart failed VMs' backup [#3339](https://github.com/vatesfr/xen-orchestra/issues/3339) (PR [#3420](https://github.com/vatesfr/xen-orchestra/pull/3420))
### Bug fixes

View File

@ -118,8 +118,13 @@ getJob.params = {
},
}
export async function runJob ({ id, schedule, vm }) {
return this.runJobSequence([id], await this.getSchedule(schedule), vm)
export async function runJob ({
id,
schedule,
vm,
vms = vm !== undefined ? [vm] : undefined,
}) {
return this.runJobSequence([id], await this.getSchedule(schedule), vms)
}
runJob.permission = 'admin'
@ -135,6 +140,13 @@ runJob.params = {
type: 'string',
optional: true,
},
vms: {
type: 'array',
items: {
type: 'string',
},
optional: true,
},
}
// -----------------------------------------------------------------------------

View File

@ -433,7 +433,7 @@ export default class BackupNg {
app.on('start', () => {
const executor: Executor = async ({
cancelToken,
data: vmId,
data: vmsId,
job: job_,
logger,
runJobId,
@ -445,17 +445,20 @@ export default class BackupNg {
const job: BackupJob = (job_: any)
let vms: $Dict<Vm> | void
if (vmId === undefined) {
vms = app.getObjects({
filter: createPredicate({
type: 'VM',
...job.vms,
}),
})
if (isEmpty(vms)) {
throw new Error('no VMs match this pattern')
}
const vms: $Dict<Vm> = app.getObjects({
filter: createPredicate({
type: 'VM',
...(vmsId !== undefined
? {
id: {
__or: vmsId,
},
}
: job.vms),
}),
})
if (isEmpty(vms)) {
throw new Error('no VMs match this pattern')
}
const jobId = job.id
const srs = unboxIds(job.srs).map(id => {
@ -541,10 +544,6 @@ export default class BackupNg {
}
}
if (vms === undefined) {
return handleVm(await app.getObject(vmId))
}
const concurrency: number = getSetting(job.settings, 'concurrency', [
'',
])

View File

@ -1775,6 +1775,7 @@ const messages = {
reportBug: 'Report a bug',
unhealthyVdiChainError: 'Job canceled to protect the VDI chain',
backupRestartVm: "Restart VM's backup",
backupRestartFailedVms: "Restart failed VMs' backup",
clickForMoreInformation: 'Click for more information',
// ----- IPs ------

View File

@ -1,4 +1,5 @@
import _ from 'intl'
import ActionButton from 'action-button'
import addSubscriptions from 'add-subscriptions'
import Button from 'button'
import ButtonGroup from 'button-group'
@ -9,7 +10,10 @@ import ReportBugButton, { CAN_REPORT_BUG } from 'report-bug-button'
import Tooltip from 'tooltip'
import { get } from 'xo-defined'
import { injectState, provideState } from '@julien-f/freactal'
import { subscribeBackupNgLogs } from 'xo'
import { runBackupNgJob, subscribeBackupNgLogs } from 'xo'
const isFailureTask = ({ status }) =>
status !== 'success' && status !== 'pending'
export default [
addSubscriptions(({ id }) => ({
@ -19,12 +23,26 @@ export default [
}),
})),
provideState({
effects: {
restartFailedVms: () => async (
_,
{ log: { jobId: id, scheduleId: schedule, tasks } }
) => {
await runBackupNgJob({
id,
schedule,
vms:
tasks && tasks.filter(isFailureTask).map(vmTask => vmTask.data.id),
})
},
},
computed: {
formattedLog: (_, { log }) => JSON.stringify(log, null, 2),
jobFailed: (_, { log }) => log !== undefined && isFailureTask(log),
},
}),
injectState,
({ state, log = {}, jobs }) => (
({ state, effects, log = {}, jobs }) => (
<span>
{get(() => jobs[log.jobId].name) || 'Job'} (
{get(() => log.jobId.slice(4, 8))}){' '}
@ -46,6 +64,15 @@ export default [
title='Backup job failed'
/>
)}
{state.jobFailed &&
log.scheduleId !== undefined && (
<ActionButton
handler={effects.restartFailedVms}
icon='run'
size='small'
tooltip={_('backupRestartFailedVms')}
/>
)}
</ButtonGroup>
</span>
),