feat(xo-server/backup-ng): consolidation of the restore logs (#3537)
This commit is contained in:
@@ -50,10 +50,16 @@ const taskTimeComparator = ({ start: s1, end: e1 }, { start: s2, end: e2 }) => {
|
||||
|
||||
export default {
|
||||
async getBackupNgLogs (runId?: string) {
|
||||
const { runningJobs } = this
|
||||
const [jobLogs, restoreLogs] = await Promise.all([
|
||||
this.getLogs('jobs'),
|
||||
this.getLogs('restore'),
|
||||
])
|
||||
|
||||
const { runningJobs, runningRestores } = this
|
||||
const consolidated = {}
|
||||
const started = {}
|
||||
forEach(await this.getLogs('jobs'), ({ data, time, message }, id) => {
|
||||
|
||||
const handleLog = ({ data, time, message }, id) => {
|
||||
const { event } = data
|
||||
if (event === 'job.start') {
|
||||
if (
|
||||
@@ -83,17 +89,26 @@ export default {
|
||||
)
|
||||
}
|
||||
} else if (event === 'task.start') {
|
||||
const parent = started[data.parentId]
|
||||
if (parent !== undefined) {
|
||||
;(parent.tasks || (parent.tasks = [])).push(
|
||||
(started[id] = {
|
||||
data: data.data,
|
||||
id,
|
||||
message,
|
||||
start: time,
|
||||
status: parent.status,
|
||||
})
|
||||
)
|
||||
const task = {
|
||||
data: data.data,
|
||||
id,
|
||||
message,
|
||||
start: time,
|
||||
}
|
||||
const { parentId } = data
|
||||
let parent
|
||||
if (parentId === undefined && (runId === undefined || runId === id)) {
|
||||
// top level task
|
||||
task.status =
|
||||
message === 'restore' && !runningRestores.has(id)
|
||||
? 'interrupted'
|
||||
: 'pending'
|
||||
consolidated[id] = started[id] = task
|
||||
} else if ((parent = started[parentId]) !== undefined) {
|
||||
// sub-task for which the parent exists
|
||||
task.status = parent.status
|
||||
started[id] = task
|
||||
;(parent.tasks || (parent.tasks = [])).push(task)
|
||||
}
|
||||
} else if (event === 'task.end') {
|
||||
const { taskId } = data
|
||||
@@ -141,7 +156,11 @@ export default {
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
forEach(jobLogs, handleLog)
|
||||
forEach(restoreLogs, handleLog)
|
||||
|
||||
return runId === undefined ? consolidated : consolidated[runId]
|
||||
},
|
||||
}
|
||||
|
||||
@@ -23,7 +23,12 @@ import {
|
||||
sum,
|
||||
values,
|
||||
} from 'lodash'
|
||||
import { CancelToken, pFromEvent, ignoreErrors } from 'promise-toolbox'
|
||||
import {
|
||||
CancelToken,
|
||||
ignoreErrors,
|
||||
pFinally,
|
||||
pFromEvent,
|
||||
} from 'promise-toolbox'
|
||||
import Vhd, {
|
||||
chainVhd,
|
||||
createSyntheticStream as createVhdReadStream,
|
||||
@@ -479,10 +484,16 @@ export default class BackupNg {
|
||||
worker: $Dict<any>,
|
||||
}
|
||||
_logger: Logger
|
||||
_runningRestores: Set<string>
|
||||
|
||||
get runningRestores () {
|
||||
return this._runningRestores
|
||||
}
|
||||
|
||||
constructor (app: any) {
|
||||
this._app = app
|
||||
this._logger = undefined
|
||||
this._runningRestores = new Set()
|
||||
|
||||
app.on('start', async () => {
|
||||
this._logger = await app.getLogger('restore')
|
||||
@@ -723,8 +734,9 @@ export default class BackupNg {
|
||||
logger,
|
||||
message: 'restore',
|
||||
},
|
||||
taskId =>
|
||||
importer(
|
||||
taskId => {
|
||||
this._runningRestores.add(taskId)
|
||||
return importer(
|
||||
handler,
|
||||
metadataFilename,
|
||||
metadata,
|
||||
@@ -732,7 +744,10 @@ export default class BackupNg {
|
||||
xapi.getObject(srId),
|
||||
taskId,
|
||||
logger
|
||||
)
|
||||
)::pFinally(() => {
|
||||
this._runningRestores.delete(taskId)
|
||||
})
|
||||
}
|
||||
)()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import _, { FormattedDuration } from 'intl'
|
||||
import addSubscriptions from 'add-subscriptions'
|
||||
import defined, { get } from '@xen-orchestra/defined'
|
||||
import Icon from 'icon'
|
||||
import NoObjects from 'no-objects'
|
||||
import React from 'react'
|
||||
@@ -8,8 +9,7 @@ import { alert } from 'modal'
|
||||
import { Card, CardHeader, CardBlock } from 'card'
|
||||
import { formatSize } from 'utils'
|
||||
import { FormattedDate } from 'react-intl'
|
||||
import { get } from '@xen-orchestra/defined'
|
||||
import { isEmpty, keyBy } from 'lodash'
|
||||
import { isEmpty, groupBy, keyBy } from 'lodash'
|
||||
import { subscribeBackupNgJobs, subscribeBackupNgLogs } from 'xo'
|
||||
|
||||
import LogAlertBody from './log-alert-body'
|
||||
@@ -185,7 +185,15 @@ const LOG_FILTERS = {
|
||||
|
||||
export default [
|
||||
addSubscriptions({
|
||||
logs: subscribeBackupNgLogs,
|
||||
logs: cb =>
|
||||
subscribeBackupNgLogs(logs =>
|
||||
cb(
|
||||
groupBy(
|
||||
logs,
|
||||
log => (log.message === 'restore' ? 'restore' : 'backup')
|
||||
)
|
||||
)
|
||||
),
|
||||
jobs: cb => subscribeBackupNgJobs(jobs => cb(keyBy(jobs, 'id'))),
|
||||
}),
|
||||
({ logs, jobs }) => (
|
||||
@@ -195,7 +203,7 @@ export default [
|
||||
</CardHeader>
|
||||
<CardBlock>
|
||||
<NoObjects
|
||||
collection={logs}
|
||||
collection={defined(() => logs.backup, [])}
|
||||
columns={LOG_COLUMNS}
|
||||
component={SortedTable}
|
||||
data-jobs={jobs}
|
||||
|
||||
Reference in New Issue
Block a user