feat(xo-web/new/metadata): ability to set the backup report when property (#4149)
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
### Enhancements
|
||||
|
||||
- [VM/general] Display 'Started... ago' instead of 'Halted... ago' for paused state [#3750](https://github.com/vatesfr/xen-orchestra/issues/3750) (PR [#4170](https://github.com/vatesfr/xen-orchestra/pull/4170))
|
||||
- [Metadata backup] Ability to define when the backup report will be sent (PR [#4149](https://github.com/vatesfr/xen-orchestra/pull/4149))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ const DEFAULTS = {
|
||||
concurrency: 0,
|
||||
fullInterval: 0,
|
||||
offlineSnapshot: false,
|
||||
reportWhen: 'failure',
|
||||
timeout: 0,
|
||||
}
|
||||
|
||||
|
||||
70
packages/xo-web/src/xo-app/backup-ng/new/_reportWhen.js
Normal file
70
packages/xo-web/src/xo-app/backup-ng/new/_reportWhen.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import _ from 'intl'
|
||||
import decorate from 'apply-decorators'
|
||||
import Icon from 'icon'
|
||||
import Link from 'link'
|
||||
import PropTypes from 'prop-types'
|
||||
import React from 'react'
|
||||
import Select from 'form/select'
|
||||
import Tooltip from 'tooltip'
|
||||
import { generateId } from 'reaclette-utils'
|
||||
import { injectState, provideState } from 'reaclette'
|
||||
|
||||
import { FormGroup } from './../utils'
|
||||
|
||||
const REPORT_WHEN_FILTER_OPTIONS = [
|
||||
{
|
||||
label: 'reportWhenAlways',
|
||||
value: 'always',
|
||||
},
|
||||
{
|
||||
label: 'reportWhenFailure',
|
||||
value: 'failure',
|
||||
},
|
||||
{
|
||||
label: 'reportWhenNever',
|
||||
value: 'never',
|
||||
},
|
||||
]
|
||||
|
||||
const getOptionRenderer = ({ label }) => <span>{_(label)}</span>
|
||||
|
||||
const ReportWhen = decorate([
|
||||
provideState({
|
||||
computed: {
|
||||
idInput: generateId,
|
||||
},
|
||||
}),
|
||||
injectState,
|
||||
({ state, onChange, value, ...props }) => (
|
||||
<FormGroup>
|
||||
<label htmlFor={state.idInput}>
|
||||
<strong>{_('reportWhen')}</strong>
|
||||
</label>{' '}
|
||||
<Tooltip content={_('pluginsWarning')}>
|
||||
<Link
|
||||
className='btn btn-primary btn-sm'
|
||||
target='_blank'
|
||||
to='/settings/plugins'
|
||||
>
|
||||
<Icon icon='menu-settings-plugins' />{' '}
|
||||
<strong>{_('pluginsSettings')}</strong>
|
||||
</Link>
|
||||
</Tooltip>
|
||||
<Select
|
||||
id={state.idInput}
|
||||
onChange={onChange}
|
||||
optionRenderer={getOptionRenderer}
|
||||
options={REPORT_WHEN_FILTER_OPTIONS}
|
||||
value={value}
|
||||
{...props}
|
||||
/>
|
||||
</FormGroup>
|
||||
),
|
||||
])
|
||||
|
||||
ReportWhen.propTypes = {
|
||||
onChange: PropTypes.func.isRequired,
|
||||
value: PropTypes.string,
|
||||
}
|
||||
|
||||
export { ReportWhen as default }
|
||||
@@ -7,7 +7,6 @@ import Icon from 'icon'
|
||||
import Link from 'link'
|
||||
import moment from 'moment-timezone'
|
||||
import React from 'react'
|
||||
import Select from 'form/select'
|
||||
import Tooltip from 'tooltip'
|
||||
import Upgrade from 'xoa-upgrade'
|
||||
import UserError from 'user-error'
|
||||
@@ -42,6 +41,7 @@ import {
|
||||
} from 'xo'
|
||||
|
||||
import NewSchedule from './new-schedule'
|
||||
import ReportWhen from './_reportWhen'
|
||||
import Schedules from './schedules'
|
||||
import SmartBackup from './smart-backup'
|
||||
import getSettingsWithNonDefaultValue from '../_getSettingsWithNonDefaultValue'
|
||||
@@ -115,23 +115,6 @@ const destructVmsPattern = pattern =>
|
||||
vms: destructPattern(pattern),
|
||||
}
|
||||
|
||||
const REPORT_WHEN_FILTER_OPTIONS = [
|
||||
{
|
||||
label: 'reportWhenAlways',
|
||||
value: 'always',
|
||||
},
|
||||
{
|
||||
label: 'reportWhenFailure',
|
||||
value: 'failure',
|
||||
},
|
||||
{
|
||||
label: 'reportWhenNever',
|
||||
value: 'never',
|
||||
},
|
||||
]
|
||||
|
||||
const getOptionRenderer = ({ label }) => <span>{_(label)}</span>
|
||||
|
||||
const createDoesRetentionExist = name => {
|
||||
const predicate = setting => setting[name] > 0
|
||||
return ({ propSettings, settings = propSettings }) => settings.some(predicate)
|
||||
@@ -541,7 +524,6 @@ export default decorate([
|
||||
formId: generateId,
|
||||
inputConcurrencyId: generateId,
|
||||
inputFullIntervalId: generateId,
|
||||
inputReportWhenId: generateId,
|
||||
inputTimeoutId: generateId,
|
||||
|
||||
vmsPattern: ({ _vmsPattern }, { job }) =>
|
||||
@@ -884,33 +866,13 @@ export default decorate([
|
||||
</ActionButton>
|
||||
</CardHeader>
|
||||
<CardBlock>
|
||||
<FormGroup>
|
||||
<label htmlFor={state.inputReportWhenId}>
|
||||
<strong>{_('reportWhen')}</strong>
|
||||
</label>{' '}
|
||||
<Tooltip content={_('pluginsWarning')}>
|
||||
<Link
|
||||
className='btn btn-primary btn-sm'
|
||||
target='_blank'
|
||||
to='/settings/plugins'
|
||||
>
|
||||
<Icon icon='menu-settings-plugins' />{' '}
|
||||
<strong>{_('pluginsSettings')}</strong>
|
||||
</Link>
|
||||
</Tooltip>
|
||||
<Select
|
||||
id={state.inputReportWhenId}
|
||||
labelKey='label'
|
||||
onChange={effects.setReportWhen}
|
||||
optionRenderer={getOptionRenderer}
|
||||
options={REPORT_WHEN_FILTER_OPTIONS}
|
||||
required
|
||||
// Handle improper value introduced by:
|
||||
// https://github.com/vatesfr/xen-orchestra/commit/753ee994f2948bbaca9d3161eaab82329a682773#diff-9c044ab8a42ed6576ea927a64c1ec3ebR105
|
||||
value={reportWhen === 'Never' ? 'never' : reportWhen}
|
||||
valueKey='value'
|
||||
/>
|
||||
</FormGroup>
|
||||
<ReportWhen
|
||||
onChange={effects.setReportWhen}
|
||||
required
|
||||
// Handle improper value introduced by:
|
||||
// https://github.com/vatesfr/xen-orchestra/commit/753ee994f2948bbaca9d3161eaab82329a682773#diff-9c044ab8a42ed6576ea927a64c1ec3ebR105
|
||||
value={reportWhen === 'Never' ? 'never' : reportWhen}
|
||||
/>
|
||||
{state.displayAdvancedSettings && (
|
||||
<div>
|
||||
<FormGroup>
|
||||
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
Ul,
|
||||
} from '../../utils'
|
||||
|
||||
import ReportWhen from '../_reportWhen'
|
||||
import Schedules from '../_schedules'
|
||||
|
||||
// A retention can be:
|
||||
@@ -51,6 +52,25 @@ const RETENTION_XO_METADATA = {
|
||||
valuePath: 'retentionXoMetadata',
|
||||
}
|
||||
|
||||
const GLOBAL_SETTING_KEY = ''
|
||||
|
||||
const setSettingsDefaultRetentions = (
|
||||
settings,
|
||||
{ modePoolMetadata, modeXoMetadata }
|
||||
) =>
|
||||
mapValues(settings, (setting, key) =>
|
||||
key !== GLOBAL_SETTING_KEY
|
||||
? {
|
||||
retentionPoolMetadata: modePoolMetadata
|
||||
? defined(setting.retentionPoolMetadata, DEFAULT_RETENTION)
|
||||
: undefined,
|
||||
retentionXoMetadata: modeXoMetadata
|
||||
? defined(setting.retentionXoMetadata, DEFAULT_RETENTION)
|
||||
: undefined,
|
||||
}
|
||||
: setting
|
||||
)
|
||||
|
||||
const getInitialState = () => ({
|
||||
_modePoolMetadata: undefined,
|
||||
_modeXoMetadata: undefined,
|
||||
@@ -79,28 +99,25 @@ export default decorate([
|
||||
return { showErrors: true }
|
||||
}
|
||||
|
||||
const {
|
||||
modePoolMetadata,
|
||||
modeXoMetadata,
|
||||
name,
|
||||
pools,
|
||||
remotes,
|
||||
schedules,
|
||||
settings,
|
||||
} = state
|
||||
await createMetadataBackupJob({
|
||||
name: state.name,
|
||||
pools: state.modePoolMetadata
|
||||
? constructPattern(state.pools)
|
||||
: undefined,
|
||||
remotes: constructPattern(state.remotes),
|
||||
xoMetadata: state.modeXoMetadata,
|
||||
schedules: mapValues(
|
||||
state.schedules,
|
||||
({ id, ...schedule }) => schedule
|
||||
),
|
||||
settings: mapValues(
|
||||
state.settings,
|
||||
({ retentionPoolMetadata, retentionXoMetadata }) => ({
|
||||
retentionPoolMetadata: state.modePoolMetadata
|
||||
? defined(retentionPoolMetadata, DEFAULT_RETENTION)
|
||||
: undefined,
|
||||
retentionXoMetadata: state.modeXoMetadata
|
||||
? defined(retentionXoMetadata, DEFAULT_RETENTION)
|
||||
: undefined,
|
||||
})
|
||||
),
|
||||
name,
|
||||
pools: modePoolMetadata ? constructPattern(pools) : undefined,
|
||||
remotes: constructPattern(remotes),
|
||||
schedules: mapValues(schedules, ({ id, ...schedule }) => schedule),
|
||||
settings: setSettingsDefaultRetentions(settings, {
|
||||
modePoolMetadata,
|
||||
modeXoMetadata,
|
||||
}),
|
||||
xoMetadata: modeXoMetadata,
|
||||
})
|
||||
},
|
||||
editJob: () => async (state, props) => {
|
||||
@@ -138,23 +155,17 @@ export default decorate([
|
||||
}),
|
||||
])
|
||||
|
||||
const { modePoolMetadata, modeXoMetadata, name, pools, remotes } = state
|
||||
await editMetadataBackupJob({
|
||||
id: props.job.id,
|
||||
name: state.name,
|
||||
pools: state.modePoolMetadata ? constructPattern(state.pools) : null,
|
||||
remotes: constructPattern(state.remotes),
|
||||
xoMetadata: state.modeXoMetadata,
|
||||
settings: mapValues(
|
||||
settings,
|
||||
({ retentionPoolMetadata, retentionXoMetadata }) => ({
|
||||
retentionPoolMetadata: state.modePoolMetadata
|
||||
? defined(retentionPoolMetadata, DEFAULT_RETENTION)
|
||||
: undefined,
|
||||
retentionXoMetadata: state.modeXoMetadata
|
||||
? defined(retentionXoMetadata, DEFAULT_RETENTION)
|
||||
: undefined,
|
||||
})
|
||||
),
|
||||
name,
|
||||
pools: modePoolMetadata ? constructPattern(pools) : null,
|
||||
remotes: constructPattern(remotes),
|
||||
settings: setSettingsDefaultRetentions(settings, {
|
||||
modePoolMetadata,
|
||||
modeXoMetadata,
|
||||
}),
|
||||
xoMetadata: modeXoMetadata,
|
||||
})
|
||||
},
|
||||
|
||||
@@ -169,6 +180,20 @@ export default decorate([
|
||||
setSettings: (_, _settings) => () => ({
|
||||
_settings,
|
||||
}),
|
||||
setGlobalSettings: ({ setSettings }, name, value) => ({
|
||||
settings = {},
|
||||
}) => {
|
||||
setSettings({
|
||||
...settings,
|
||||
[GLOBAL_SETTING_KEY]: {
|
||||
...settings[GLOBAL_SETTING_KEY],
|
||||
[name]: value,
|
||||
},
|
||||
})
|
||||
},
|
||||
setReportWhen({ setGlobalSettings }, { value }) {
|
||||
setGlobalSettings('reportWhen', value)
|
||||
},
|
||||
toggleMode: (_, { mode }) => state => ({
|
||||
[`_${mode}`]: !state[mode],
|
||||
}),
|
||||
@@ -265,6 +290,11 @@ export default decorate([
|
||||
missingSchedules,
|
||||
} = state.showErrors ? state : {}
|
||||
|
||||
const { reportWhen = 'failure' } = defined(
|
||||
() => state.settings[GLOBAL_SETTING_KEY],
|
||||
{}
|
||||
)
|
||||
|
||||
return (
|
||||
<form id={state.idForm}>
|
||||
<Container>
|
||||
@@ -357,6 +387,16 @@ export default decorate([
|
||||
)}
|
||||
</CardBlock>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader>{_('newBackupSettings')}</CardHeader>
|
||||
<CardBlock>
|
||||
<ReportWhen
|
||||
onChange={effects.setReportWhen}
|
||||
required
|
||||
value={reportWhen}
|
||||
/>
|
||||
</CardBlock>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col mediumSize={6}>
|
||||
{state.modePoolMetadata && (
|
||||
|
||||
Reference in New Issue
Block a user