({ state, effects, log = {}, jobs }) => ( <span> {get(() => jobs[log.jobId].name) || 'Job'} ( {get(() => log.jobId.slice(4, 8))}){' '} <span style={{ fontSize: '0.5em' }} className='text-muted'> {log.id} </span>{' '} <ButtonGroup> <Tooltip content={_('copyToClipboard')}> <CopyToClipboard text={state.formattedLog}> <Button size='small'> <Icon icon='clipboard' /> </Button> </CopyToClipboard> </Tooltip> {CAN_REPORT_BUG && ( <ReportBugButton message={`\`\`\`json\n${state.formattedLog}\n\`\`\``} size='small' title='Backup job failed' /> )} {state.jobFailed && log.scheduleId !== undefined && ( <ActionButton handler={effects.restartFailedVms} icon='run' size='small' tooltip={_('backupRestartFailedVms')} /> )} </ButtonGroup> </span> ),
) => async (state, props) => { const schedule = get(() => props.schedules[id]) const setting = get(() => props.settings[id]) const { cron: newCron, name: newName, timezone: newTimezone, ...newSetting } = await form({ defaultValue: setDefaultRetentions( { cron, name, timezone, ...setting }, state.retentions ), render: props => ( <NewSchedule retentions={state.retentions} {...props} /> ), header: ( <span> <Icon icon='schedule' /> {_('schedule')} </span> ), size: 'large', handler: value => { if (areRetentionsMissing(value, state.retentions)) { throw new UserError(_('newScheduleError'), _('retentionNeeded')) } return value }, }) props.handlerSchedules({ ...props.schedules, [id]: { ...schedule, cron: newCron, id, name: newName, timezone: newTimezone, }, }) props.handlerSettings({ ...props.settings, [id]: { ...setting, ...newSetting, }, }) },
restartFailedVms: () => async ( _, { log: { jobId: id, scheduleId: schedule, tasks, infos } } ) => { let vms if (tasks !== undefined) { const scheduledVms = get( () => infos.find(({ message }) => message === 'vms').data.vms ) if (scheduledVms !== undefined) { vms = new Set(scheduledVms) tasks.forEach(({ status, data: { id } }) => { status === 'success' && vms.delete(id) }) vms = Array.from(vms) } else { vms = [] tasks.forEach(({ status, data: { id } }) => { status !== 'success' && vms.push(id) }) } } await runBackupNgJob({ id, schedule, vms, }) },
log.tasks.forEach((task, key) => { if (task.tasks === undefined || get(() => task.data.type) !== 'VM') { return } const subTaskWithIsFull = task.tasks.find( ({ data = {} }) => data.isFull !== undefined ) if (subTaskWithIsFull !== undefined) { if (newLog === undefined) { newLog = cloneDeep(log) } newLog.tasks[key].isFull = subTaskWithIsFull.data.isFull } })
itemRenderer: (pbd, hosts) => { if (!pbd.attached) { return _('pbdDisconnected') } if (!get(() => hosts[pbd.host].multipathing)) { return _('multipathingDisabled') } const [nActives, nPaths] = getIscsiPaths(pbd) return ( nActives !== undefined && nPaths !== undefined && _('hostMultipathingPaths', { nActives, nPaths, nSessions: pbd.otherConfig.iscsi_sessions, }) ) },
const TransferMergeTask = ({ task }) => { const size = get(() => task.result.size) return ( <div> <Icon icon='task' /> {task.message}{' '} <TaskStateInfos status={task.status} /> <Warnings warnings={task.warnings} /> <TaskStart task={task} /> <TaskEnd task={task} /> <TaskDuration task={task} /> <TaskError task={task} /> {size > 0 && ( <div> {_.keyValue(_('operationSize'), formatSize(size))} <br /> {_.keyValue( _('operationSpeed'), formatSpeed(size, task.end - task.start) )} </div> )} </div> ) }
({ state, effects, vms, pattern }) => ( <div> <FormGroup> <label> <strong>{_('editBackupSmartStatusTitle')}</strong> </label> <Select options={VMS_STATUSES_OPTIONS} onChange={effects.setPowerState} value={defined(pattern.power_state, 'All')} simpleValue required /> </FormGroup> <h3>{_('editBackupSmartPools')}</h3> <hr /> <FormGroup> <label> <strong>{_('editBackupSmartResidentOn')}</strong> </label> <SelectPool multi onChange={effects.setPoolValues} predicate={state.poolPredicate} value={state.pools.values} /> </FormGroup> <FormGroup> <label> <strong>{_('editBackupSmartNotResidentOn')}</strong> </label> <SelectPool multi onChange={effects.setPoolNotValues} value={state.pools.notValues} /> </FormGroup> <h3>{_('editBackupSmartTags')}</h3> <hr /> <FormGroup> <label> <strong>{_('editBackupSmartTagsTitle')}</strong> </label> <SelectTag multi onChange={effects.setTagValues} value={get(() => state.tags.values)} /> </FormGroup> <FormGroup> <label> <strong>{_('editBackupSmartExcludedTagsTitle')}</strong> </label>{' '} <Tooltip content={_('backupReplicatedVmsInfo')}> <Icon icon='info' /> </Tooltip> <SelectTag multi onChange={effects.setTagNotValues} value={get(() => state.tags.notValues)} /> </FormGroup> <SmartBackupPreview vms={vms} pattern={state.vmsSmartPattern} /> </div> ),
poolPredicate: (_, { deltaMode, hosts }) => pool => !deltaMode || canDeltaBackup(get(() => hosts[pool.master].version)),
sortCriteria: ({ data: { srId } }, { srs }) => get(() => srs[srId].name_label),
sortCriteria: ({ data: { jobId } }, { jobs }) => get(() => jobs[jobId].name),
itemRenderer: ({ data: { jobId } }, { jobs }) => get(() => jobs[jobId].name),
countByStatus: ({ log }) => ({ all: get(() => log.tasks.length), ...countBy(log.tasks, 'status'), }),
sortCriteria: (pbd, hosts) => get(() => hosts[pbd.host].multipathing),