mirror of
https://github.com/OpenNebula/one.git
synced 2025-01-05 09:17:41 +03:00
F OpenNebula/one#6053: Add VM restore action to FireEdge (#3113)
Signed-off-by: Victor Hansson <vhansson@opennebula.io>
This commit is contained in:
parent
02e993a456
commit
b1c92d811e
@ -40,6 +40,7 @@ actions:
|
||||
rdp: true
|
||||
edit_labels: true
|
||||
backup: true
|
||||
restore: true
|
||||
|
||||
# Filters - List of criteria to filter the resources
|
||||
|
||||
|
@ -40,6 +40,7 @@ actions:
|
||||
rdp: true
|
||||
edit_labels: false
|
||||
backup: true
|
||||
restore: false
|
||||
|
||||
# Filters - List of criteria to filter the resources
|
||||
|
||||
|
@ -23,12 +23,10 @@ import {
|
||||
ReactElement,
|
||||
} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { BaseSchema } from 'yup'
|
||||
import { useForm, FormProvider, useFormContext } from 'react-hook-form'
|
||||
import { yupResolver } from '@hookform/resolvers/yup'
|
||||
import { useMediaQuery } from '@mui/material'
|
||||
|
||||
import {
|
||||
useGeneral,
|
||||
updateDisabledSteps,
|
||||
@ -99,6 +97,7 @@ const DisableStepContext = createContext(() => {})
|
||||
* disableStep('step1', true); // This will disable 'step1'
|
||||
*/
|
||||
export const useDisableStep = () => useContext(DisableStepContext)
|
||||
|
||||
/**
|
||||
* Represents a form with one or more steps.
|
||||
* Finally, it submit the result.
|
||||
@ -123,8 +122,12 @@ const FormStepper = ({
|
||||
formState: { errors },
|
||||
setError,
|
||||
} = useFormContext()
|
||||
|
||||
const { setModifiedFields } = useGeneralApi()
|
||||
const { isLoading } = useGeneral()
|
||||
const [steps, setSteps] = useState(initialSteps)
|
||||
const [disabledSteps, setDisabledSteps] = useState({})
|
||||
const dispatch = useDispatch()
|
||||
const currentState = useSelector((state) => state)
|
||||
|
||||
// Used to control the default visibility of a step
|
||||
useEffect(() => {
|
||||
@ -151,29 +154,22 @@ const FormStepper = ({
|
||||
},
|
||||
{}
|
||||
)
|
||||
|
||||
// Set the initial state of the steps accessible from redux
|
||||
dispatch(updateDisabledSteps(newState))
|
||||
setDisabledSteps(newState)
|
||||
}, [])
|
||||
|
||||
const { isLoading } = useGeneral()
|
||||
const [steps, setSteps] = useState(initialSteps)
|
||||
const [disabledSteps, setDisabledSteps] = useState({})
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const currentState = useSelector((state) => state)
|
||||
|
||||
const disableStep = useCallback((stepIds, shouldDisable) => {
|
||||
const ids = Array.isArray(stepIds) ? stepIds : [stepIds]
|
||||
|
||||
setDisabledSteps((prev) => {
|
||||
let newDisabledSteps = { ...prev }
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
ids.forEach((stepId) => {
|
||||
ids.forEach((sId) => {
|
||||
newDisabledSteps = shouldDisable
|
||||
? { ...newDisabledSteps, [stepId]: true }
|
||||
: (({ [stepId]: _, ...rest }) => rest)(newDisabledSteps)
|
||||
? { ...newDisabledSteps, [sId]: true }
|
||||
: (({ [sId]: _, ...rest }) => rest)(newDisabledSteps)
|
||||
})
|
||||
|
||||
return newDisabledSteps
|
||||
@ -300,12 +296,12 @@ const FormStepper = ({
|
||||
Number.isInteger(stepToBack) ? stepToBack : prevStep - 1
|
||||
)
|
||||
},
|
||||
[activeStep]
|
||||
[activeStep, steps]
|
||||
)
|
||||
|
||||
const { id: stepId, content: Content } = useMemo(
|
||||
() => steps[activeStep] || { id: null, content: null },
|
||||
[formData, activeStep]
|
||||
[steps, activeStep]
|
||||
)
|
||||
|
||||
return (
|
||||
@ -358,5 +354,4 @@ FormStepper.propTypes = {
|
||||
}
|
||||
|
||||
export { DefaultFormStepper, SkeletonStepsForm }
|
||||
|
||||
export default FormStepper
|
||||
|
@ -0,0 +1,82 @@
|
||||
/* ------------------------------------------------------------------------- *
|
||||
* Copyright 2002-2023, OpenNebula Project, OpenNebula Systems *
|
||||
* *
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
|
||||
* not use this file except in compliance with the License. You may obtain *
|
||||
* a copy of the License at *
|
||||
* *
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 *
|
||||
* *
|
||||
* Unless required by applicable law or agreed to in writing, software *
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, *
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
|
||||
* See the License for the specific language governing permissions and *
|
||||
* limitations under the License. *
|
||||
* ------------------------------------------------------------------------- */
|
||||
import PropTypes from 'prop-types'
|
||||
import { useFormContext } from 'react-hook-form'
|
||||
|
||||
import { BackupsTable } from 'client/components/Tables'
|
||||
import { SCHEMA } from 'client/components/Forms/Backup/RestoreForm/Steps/BackupsTable/schema'
|
||||
|
||||
import { Step } from 'client/utils'
|
||||
import { T } from 'client/constants'
|
||||
|
||||
export const STEP_ID = 'image'
|
||||
|
||||
const Content = ({ data, app: { backupIds = [] } = {} }) => {
|
||||
const { ID } = data?.[0] ?? {}
|
||||
|
||||
const { setValue } = useFormContext()
|
||||
|
||||
const handleSelectedRows = (rows) => {
|
||||
const { original = {} } = rows?.[0] ?? {}
|
||||
|
||||
setValue(STEP_ID, original.ID !== undefined ? [original] : [])
|
||||
}
|
||||
|
||||
return (
|
||||
<BackupsTable
|
||||
singleSelect
|
||||
disableGlobalSort
|
||||
displaySelectedRows
|
||||
pageSize={5}
|
||||
getRowId={(row) => String(row.ID)}
|
||||
filter={(images) =>
|
||||
images?.filter(({ ID: imgId }) => backupIds?.includes(imgId)) ?? []
|
||||
}
|
||||
initialState={{
|
||||
selectedRowIds: { [ID]: true },
|
||||
}}
|
||||
onSelectedRowsChange={handleSelectedRows}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Step to select the Image.
|
||||
*
|
||||
* @param {object} app - Marketplace App resource
|
||||
* @returns {Step} Image step
|
||||
*/
|
||||
const ImageStep = (app) => {
|
||||
const { disableImageSelection } = app
|
||||
|
||||
return {
|
||||
id: STEP_ID,
|
||||
label: T.SelectBackupImage,
|
||||
resolver: SCHEMA,
|
||||
content: (props) => Content({ ...props, app }),
|
||||
defaultDisabled: {
|
||||
condition: () => disableImageSelection,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Content.propTypes = {
|
||||
data: PropTypes.any,
|
||||
setFormData: PropTypes.func,
|
||||
app: PropTypes.object,
|
||||
}
|
||||
|
||||
export default ImageStep
|
@ -0,0 +1,24 @@
|
||||
/* ------------------------------------------------------------------------- *
|
||||
* Copyright 2002-2023, OpenNebula Project, OpenNebula Systems *
|
||||
* *
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
|
||||
* not use this file except in compliance with the License. You may obtain *
|
||||
* a copy of the License at *
|
||||
* *
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 *
|
||||
* *
|
||||
* Unless required by applicable law or agreed to in writing, software *
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, *
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
|
||||
* See the License for the specific language governing permissions and *
|
||||
* limitations under the License. *
|
||||
* ------------------------------------------------------------------------- */
|
||||
import { array, ArraySchema } from 'yup'
|
||||
|
||||
/** @type {ArraySchema} Image backups table schema */
|
||||
export const SCHEMA = array()
|
||||
.min(1)
|
||||
.max(1)
|
||||
.required()
|
||||
.ensure()
|
||||
.default(() => [])
|
@ -18,11 +18,17 @@ import { timeFromMilliseconds } from 'client/models/Helper'
|
||||
import { Field, arrayToOptions, getValidationFromFields } from 'client/utils'
|
||||
import { ObjectSchema, boolean, object, string } from 'yup'
|
||||
import { STEP_ID as VM_DISK_ID } from 'client/components/Forms/Backup/RestoreForm/Steps/VmDisksTable'
|
||||
import { STEP_ID as BACKUP_IMG_ID } from 'client/components/Forms/Backup/RestoreForm/Steps/BackupsTable'
|
||||
|
||||
const NO_NIC = {
|
||||
name: 'no_nic',
|
||||
label: T.DoNotRestoreNICAttributes,
|
||||
type: INPUT_TYPES.SWITCH,
|
||||
htmlType: (deps) => {
|
||||
const selectedImage = deps?.[BACKUP_IMG_ID]?.[0]
|
||||
|
||||
return selectedImage ? INPUT_TYPES.HIDDEN : INPUT_TYPES.SWITCH
|
||||
},
|
||||
validation: boolean().yesOrNo(),
|
||||
grid: { md: 12 },
|
||||
}
|
||||
@ -31,6 +37,11 @@ const NO_IP = {
|
||||
name: 'no_ip',
|
||||
label: T.DoNotRestoreIPAttributes,
|
||||
type: INPUT_TYPES.SWITCH,
|
||||
htmlType: (deps) => {
|
||||
const selectedImage = deps?.[BACKUP_IMG_ID]?.[0]
|
||||
|
||||
return selectedImage ? INPUT_TYPES.HIDDEN : INPUT_TYPES.SWITCH
|
||||
},
|
||||
validation: boolean().yesOrNo(),
|
||||
grid: { md: 12 },
|
||||
}
|
||||
@ -61,19 +72,37 @@ const INCREMENT_ID = ({ increments = [] }) => ({
|
||||
name: 'increment_id',
|
||||
label: T.IncrementId,
|
||||
type: INPUT_TYPES.SELECT,
|
||||
values: arrayToOptions(increments, {
|
||||
addEmpty: true,
|
||||
getText: (increment) =>
|
||||
`${increment.id}: ${timeFromMilliseconds(increment.date)
|
||||
.toFormat('ff')
|
||||
.replace(',', '')} (${increment.source})`,
|
||||
getValue: (increment) => increment.id,
|
||||
}),
|
||||
values: (deps) => {
|
||||
const selectedImage = deps?.[BACKUP_IMG_ID]?.[0]
|
||||
let backupIncrements = [].concat(
|
||||
selectedImage?.BACKUP_INCREMENTS?.INCREMENT ?? []
|
||||
)
|
||||
|
||||
backupIncrements = backupIncrements.map((increment) => ({
|
||||
id: increment.ID,
|
||||
date: increment.DATE,
|
||||
source: increment.SOURCE,
|
||||
}))
|
||||
|
||||
return arrayToOptions(
|
||||
backupIncrements?.length > 0 ? backupIncrements : increments,
|
||||
{
|
||||
addEmpty: true,
|
||||
getText: (increment) =>
|
||||
`${increment.id}: ${timeFromMilliseconds(increment.date)
|
||||
.toFormat('ff')
|
||||
.replace(',', '')} (${increment.source})`,
|
||||
getValue: (increment) => increment.id,
|
||||
}
|
||||
)
|
||||
},
|
||||
validation: string(),
|
||||
grid: { md: 6 },
|
||||
fieldProps: {
|
||||
disabled: increments.length === 0,
|
||||
},
|
||||
fieldProps: (deps) => ({
|
||||
disabled:
|
||||
deps?.[BACKUP_IMG_ID]?.[0]?.BACKUP_INCRMENETS?.INCREMENT?.length === 0 &&
|
||||
increments.length === 0,
|
||||
}),
|
||||
})
|
||||
|
||||
/**
|
||||
|
@ -63,12 +63,20 @@ const Content = ({ data, app }) => {
|
||||
* @param {object} app - Marketplace App resource
|
||||
* @returns {Step} Datastore step
|
||||
*/
|
||||
const DatastoreStep = (app) => ({
|
||||
id: STEP_ID,
|
||||
label: T.SelectDatastoreImage,
|
||||
resolver: SCHEMA,
|
||||
content: (props) => Content({ ...props, app }),
|
||||
})
|
||||
const DatastoreStep = (app) => {
|
||||
const { disableImageSelection } = app
|
||||
|
||||
return {
|
||||
id: STEP_ID,
|
||||
label: T.SelectDatastoreImage,
|
||||
resolver: SCHEMA,
|
||||
content: (props) => Content({ ...props, app }),
|
||||
defaultDisabled: {
|
||||
// Disabled when image selection is enabled, aka when in restore operation
|
||||
condition: () => !disableImageSelection,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Content.propTypes = {
|
||||
data: PropTypes.any,
|
||||
|
@ -49,6 +49,8 @@ const Content = ({ data, app: { backupDiskIds = [], vmsId = [] } = {} }) => {
|
||||
selectedRowIds: { [selectedRow]: true },
|
||||
}}
|
||||
filter={(disks) =>
|
||||
disks &&
|
||||
disks?.length > 0 &&
|
||||
disks?.filter((disk) => backupDiskIds?.includes(disk?.DISK_ID))
|
||||
}
|
||||
/>
|
||||
|
@ -13,6 +13,9 @@
|
||||
* See the License for the specific language governing permissions and *
|
||||
* limitations under the License. *
|
||||
* ------------------------------------------------------------------------- */
|
||||
import BackupsTable, {
|
||||
STEP_ID as BACKUP_IMG_ID,
|
||||
} from 'client/components/Forms/Backup/RestoreForm/Steps/BackupsTable'
|
||||
import BasicConfiguration, {
|
||||
STEP_ID as BASIC_ID,
|
||||
} from 'client/components/Forms/Backup/RestoreForm/Steps/BasicConfiguration'
|
||||
@ -24,37 +27,42 @@ import VmDisksTable, {
|
||||
} from 'client/components/Forms/Backup/RestoreForm/Steps/VmDisksTable'
|
||||
import { createSteps } from 'client/utils'
|
||||
|
||||
const Steps = createSteps([BasicConfiguration, VmDisksTable, DatastoresTable], {
|
||||
transformInitialValue: (initialValues, schema) => {
|
||||
const { increments } = initialValues
|
||||
const castedValuesBasic = schema.cast(
|
||||
{ [BASIC_ID]: { increments } },
|
||||
{ stripUnknown: true }
|
||||
)
|
||||
const Steps = createSteps(
|
||||
[BackupsTable, BasicConfiguration, VmDisksTable, DatastoresTable],
|
||||
{
|
||||
transformInitialValue: (initialValues, schema) => {
|
||||
const { increments } = initialValues
|
||||
const castedValuesBasic = schema.cast(
|
||||
{ [BASIC_ID]: { increments } },
|
||||
{ stripUnknown: true }
|
||||
)
|
||||
|
||||
const castedValuesDatastore = schema.cast(
|
||||
{ [DATASTORE_ID]: {} },
|
||||
{ stripUnknown: true }
|
||||
)
|
||||
const castedValuesDatastore = schema.cast(
|
||||
{ [DATASTORE_ID]: {} },
|
||||
{ stripUnknown: true }
|
||||
)
|
||||
|
||||
return {
|
||||
[BASIC_ID]: castedValuesBasic[BASIC_ID],
|
||||
[DATASTORE_ID]: castedValuesDatastore[DATASTORE_ID],
|
||||
}
|
||||
},
|
||||
transformBeforeSubmit: (formData) => {
|
||||
const {
|
||||
[BASIC_ID]: configuration,
|
||||
[VM_DISK_ID]: individualDisk = [],
|
||||
[DATASTORE_ID]: [datastore] = [],
|
||||
} = formData
|
||||
return {
|
||||
[BASIC_ID]: castedValuesBasic[BASIC_ID],
|
||||
[DATASTORE_ID]: castedValuesDatastore[DATASTORE_ID],
|
||||
}
|
||||
},
|
||||
transformBeforeSubmit: (formData) => {
|
||||
const {
|
||||
[BACKUP_IMG_ID]: backupImgId = [],
|
||||
[BASIC_ID]: configuration,
|
||||
[VM_DISK_ID]: individualDisk = [],
|
||||
[DATASTORE_ID]: [datastore] = [],
|
||||
} = formData
|
||||
|
||||
return {
|
||||
datastore: datastore?.ID,
|
||||
individualDisk: individualDisk?.[0] ?? [],
|
||||
...configuration,
|
||||
}
|
||||
},
|
||||
})
|
||||
return {
|
||||
datastore: datastore?.ID,
|
||||
individualDisk: individualDisk?.[0] ?? [],
|
||||
backupImgId: backupImgId?.[0] ?? [],
|
||||
...configuration,
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
export default Steps
|
||||
|
@ -114,7 +114,12 @@ const Actions = () => {
|
||||
}))
|
||||
|
||||
return RestoreForm({
|
||||
stepProps: { increments, backupDiskIds, vmsId },
|
||||
stepProps: {
|
||||
increments,
|
||||
backupDiskIds,
|
||||
vmsId,
|
||||
disableImageSelection: true,
|
||||
},
|
||||
initialValues: {
|
||||
increments: increments,
|
||||
backupDiskIds: backupDiskIds,
|
||||
|
@ -35,6 +35,7 @@ const BackupsTable = (props) => {
|
||||
searchProps = {},
|
||||
vm,
|
||||
refetchVm,
|
||||
filter,
|
||||
isFetchingVm,
|
||||
...rest
|
||||
} = props ?? {}
|
||||
@ -54,11 +55,13 @@ const BackupsTable = (props) => {
|
||||
: [vm?.BACKUPS?.BACKUP_IDS?.ID]
|
||||
: []
|
||||
|
||||
const backupData = result?.data?.filter((backup) =>
|
||||
vm ? backupsIds?.includes(backup.ID) : true
|
||||
)
|
||||
|
||||
return {
|
||||
...result,
|
||||
data: result?.data?.filter((backup) =>
|
||||
vm ? backupsIds?.includes(backup.ID) : true
|
||||
),
|
||||
data: typeof filter === 'function' ? filter(backupData) : backupData,
|
||||
}
|
||||
},
|
||||
})
|
||||
@ -76,10 +79,13 @@ const BackupsTable = (props) => {
|
||||
* Refetch vms and backups. If a new backup is created, the id of the backup will be in the data of a vm, so we need to refetch also the vms query.
|
||||
*/
|
||||
const refetchAll = () => {
|
||||
refetchVm()
|
||||
refetchVm && refetchVm()
|
||||
refetch()
|
||||
}
|
||||
|
||||
const isFetchingAll = () =>
|
||||
isFetchingVm ? !!(isFetchingVm && isFetching) : isFetching
|
||||
|
||||
return (
|
||||
<EnhancedTable
|
||||
columns={columns}
|
||||
@ -87,7 +93,7 @@ const BackupsTable = (props) => {
|
||||
rootProps={rootProps}
|
||||
searchProps={searchProps}
|
||||
refetch={refetchAll}
|
||||
isLoading={isFetching && isFetchingVm}
|
||||
isLoading={isFetchingAll()}
|
||||
getRowId={(row) => String(row.ID)}
|
||||
RowComponent={BackupRow}
|
||||
{...rest}
|
||||
|
@ -41,7 +41,7 @@ const VmDisksTable = (props) => {
|
||||
const { data, isFetching, refetch } = useGetVmQuery({ id: vmId })
|
||||
|
||||
const disks =
|
||||
typeof filter === 'function'
|
||||
typeof filter === 'function' && Array.isArray(data?.TEMPLATE?.DISK)
|
||||
? filter(data?.TEMPLATE?.DISK ?? [])
|
||||
: data?.TEMPLATE?.DISK ?? []
|
||||
|
||||
|
@ -35,6 +35,7 @@ import { useGetDatastoresQuery } from 'client/features/OneApi/datastore'
|
||||
import {
|
||||
useActionVmMutation,
|
||||
useBackupMutation,
|
||||
useRestoreMutation,
|
||||
useChangeVmOwnershipMutation,
|
||||
useDeployMutation,
|
||||
useLockVmMutation,
|
||||
@ -52,6 +53,7 @@ import {
|
||||
RecoverForm,
|
||||
SaveAsTemplateForm,
|
||||
} from 'client/components/Forms/Vm'
|
||||
import { RestoreForm } from 'client/components/Forms/Backup'
|
||||
import {
|
||||
GlobalAction,
|
||||
createActions,
|
||||
@ -124,6 +126,7 @@ const Actions = () => {
|
||||
const [actionVm] = useActionVmMutation()
|
||||
const [recover] = useRecoverMutation()
|
||||
const [backup] = useBackupMutation()
|
||||
const [restore] = useRestoreMutation()
|
||||
const [changeOwnership] = useChangeVmOwnershipMutation()
|
||||
const [deploy] = useDeployMutation()
|
||||
const [migrate] = useMigrateMutation()
|
||||
@ -522,6 +525,41 @@ const Actions = () => {
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
accessor: VM_ACTIONS.RESTORE,
|
||||
disabled: isDisabled(VM_ACTIONS.RESTORE),
|
||||
name: T.Restore,
|
||||
selected: { max: 1 },
|
||||
dialogProps: {
|
||||
title: T.RestoreVm,
|
||||
subheader: SubHeader,
|
||||
},
|
||||
form: (row) => {
|
||||
const vm = row?.[0]?.original
|
||||
const vmId = vm?.ID
|
||||
const backupIds = [].concat(vm?.BACKUPS?.BACKUP_IDS?.ID ?? [])
|
||||
|
||||
return RestoreForm({
|
||||
stepProps: {
|
||||
disableImageSelection: false,
|
||||
vmsId: [vmId],
|
||||
backupIds,
|
||||
},
|
||||
})
|
||||
},
|
||||
onSubmit: (rows) => async (formData) => {
|
||||
const vmId = rows?.[0]?.id
|
||||
const imageId = formData?.backupImgId?.ID
|
||||
const incrementId = formData?.increment_id
|
||||
const diskId = formData?.individualDisk
|
||||
await restore({
|
||||
id: vmId,
|
||||
imageId,
|
||||
incrementId,
|
||||
diskId,
|
||||
})
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -123,6 +123,7 @@ export const PROLOG_RESUME_FAILURE = 'PROLOG_RESUME_FAILURE'
|
||||
export const PROLOG_UNDEPLOY = 'PROLOG_UNDEPLOY'
|
||||
export const PROLOG_UNDEPLOY_FAILURE = 'PROLOG_UNDEPLOY_FAILURE'
|
||||
export const READY = 'READY'
|
||||
export const RESTORE = 'RESTORE'
|
||||
export const RUNNING = 'RUNNING'
|
||||
export const SAVE_MIGRATE = 'SAVE_MIGRATE'
|
||||
export const SAVE_STOP = 'SAVE_STOP'
|
||||
|
@ -611,6 +611,7 @@ module.exports = {
|
||||
IncrementMode: 'Increment Mode',
|
||||
IncrementId: 'Increment ID',
|
||||
RestoreBackup: 'Restore backup',
|
||||
RestoreVm: 'Restore VM',
|
||||
BackupJobs: 'BackupJobs',
|
||||
BackupJob: 'BackupJob',
|
||||
|
||||
@ -1689,6 +1690,7 @@ module.exports = {
|
||||
ImportAssociateApp: 'Import associated VM templates/images',
|
||||
SelectResourceToCreateTheApp: 'Select the resource to create the App',
|
||||
SelectImageToCreateTheApp: 'Select the Image to create the App',
|
||||
SelectBackupImage: 'Select backup image',
|
||||
SelectVmToCreateTheApp: 'Select the VM to create the App',
|
||||
SelectVmTemplateToCreateTheApp: 'Select the VM Template to create the App',
|
||||
|
||||
|
@ -724,11 +724,18 @@ export const VM_LCM_STATES = [
|
||||
color: COLOR.info.main,
|
||||
meaning: '',
|
||||
},
|
||||
{
|
||||
// 71
|
||||
name: STATES.RESTORE,
|
||||
color: COLOR.info.main,
|
||||
meaning: '',
|
||||
},
|
||||
]
|
||||
|
||||
/** @enum {string} Virtual machine actions */
|
||||
export const VM_ACTIONS = {
|
||||
BACKUP: 'backup',
|
||||
RESTORE: 'restore',
|
||||
CREATE_DIALOG: 'create_dialog',
|
||||
CREATE_APP_DIALOG: 'create_app_dialog',
|
||||
DEPLOY: 'deploy',
|
||||
@ -846,6 +853,7 @@ export const DEFAULT_VM_ACTIONS_BY_STATE = {
|
||||
STATES.PROLOG_UNDEPLOY_FAILURE,
|
||||
STATES.UPDATE_FAILURE,
|
||||
],
|
||||
[VM_ACTIONS.RESTORE]: [STATES.POWEROFF],
|
||||
[VM_ACTIONS.TERMINATE_HARD]: [
|
||||
STATES.INIT,
|
||||
STATES.PENDING,
|
||||
@ -972,6 +980,7 @@ export const DUMMY_VM_ACTIONS_BY_STATE = {
|
||||
STATES.PROLOG_UNDEPLOY_FAILURE,
|
||||
STATES.UPDATE_FAILURE,
|
||||
],
|
||||
[VM_ACTIONS.RESTORE]: [STATES.POWEROFF],
|
||||
[VM_ACTIONS.RELEASE]: [STATES.HOLD],
|
||||
[VM_ACTIONS.RESCHED]: [STATES.POWEROFF, STATES.RUNNING, STATES.UNKNOWN],
|
||||
[VM_ACTIONS.RESUME]: [
|
||||
@ -1203,6 +1212,7 @@ export const KVM_VM_ACTIONS_BY_STATE = {
|
||||
STATES.PROLOG_UNDEPLOY_FAILURE,
|
||||
STATES.UPDATE_FAILURE,
|
||||
],
|
||||
[VM_ACTIONS.RESTORE]: [STATES.POWEROFF],
|
||||
[VM_ACTIONS.RELEASE]: [STATES.HOLD],
|
||||
[VM_ACTIONS.RESCHED]: [STATES.POWEROFF, STATES.RUNNING, STATES.UNKNOWN],
|
||||
[VM_ACTIONS.RESUME]: [
|
||||
@ -1433,6 +1443,7 @@ export const VCENTER_VM_ACTIONS_BY_STATE = {
|
||||
STATES.PROLOG_UNDEPLOY_FAILURE,
|
||||
STATES.UPDATE_FAILURE,
|
||||
],
|
||||
[VM_ACTIONS.RESTORE]: [STATES.POWEROFF],
|
||||
[VM_ACTIONS.RELEASE]: [STATES.HOLD],
|
||||
[VM_ACTIONS.RESCHED]: [STATES.POWEROFF, STATES.RUNNING, STATES.UNKNOWN],
|
||||
[VM_ACTIONS.RESUME]: [
|
||||
@ -1648,6 +1659,7 @@ export const FIRECRACKER_VM_ACTIONS_BY_STATE = {
|
||||
STATES.PROLOG_UNDEPLOY_FAILURE,
|
||||
STATES.UPDATE_FAILURE,
|
||||
],
|
||||
[VM_ACTIONS.RESTORE]: [STATES.POWEROFF],
|
||||
[VM_ACTIONS.RELEASE]: [STATES.HOLD],
|
||||
[VM_ACTIONS.RESCHED]: [STATES.POWEROFF, STATES.RUNNING, STATES.UNKNOWN],
|
||||
[VM_ACTIONS.RESUME]: [
|
||||
@ -1863,6 +1875,7 @@ export const LXC_VM_ACTIONS_BY_STATE = {
|
||||
STATES.PROLOG_UNDEPLOY_FAILURE,
|
||||
STATES.UPDATE_FAILURE,
|
||||
],
|
||||
[VM_ACTIONS.RESTORE]: [STATES.POWEROFF],
|
||||
[VM_ACTIONS.RELEASE]: [STATES.HOLD],
|
||||
[VM_ACTIONS.RESCHED]: [STATES.POWEROFF, STATES.RUNNING, STATES.UNKNOWN],
|
||||
[VM_ACTIONS.RESUME]: [
|
||||
|
@ -959,6 +959,26 @@ const vmApi = oneApi.injectEndpoints({
|
||||
},
|
||||
invalidatesTags: (_, __, { id }) => [{ type: VM, id }],
|
||||
}),
|
||||
restore: builder.mutation({
|
||||
/**
|
||||
* Restore the VM.
|
||||
*
|
||||
* @param {object} params - Request parameters
|
||||
* @param {string} params.id - Virtual machine id
|
||||
* @param {number} params.imageId - Image backup id
|
||||
* @param {boolean} params.incrementId - Backup increment ID
|
||||
* @param {number} params.diskId - Individual disk id
|
||||
* @returns {number} Virtual machine id
|
||||
* @throws Fails when response isn't code 200
|
||||
*/
|
||||
query: (params) => {
|
||||
const name = Actions.VM_RESTORE
|
||||
const command = { name, ...Commands[name] }
|
||||
|
||||
return { params, command }
|
||||
},
|
||||
invalidatesTags: (_, __, { id }) => [{ type: VM, id }],
|
||||
}),
|
||||
lockVm: builder.mutation({
|
||||
/**
|
||||
* Locks a Virtual Machine. Lock certain actions depending on blocking level.
|
||||
@ -1191,6 +1211,7 @@ export const {
|
||||
useUpdateConfigurationMutation,
|
||||
useRecoverMutation,
|
||||
useBackupMutation,
|
||||
useRestoreMutation,
|
||||
useLockVmMutation,
|
||||
useUnlockVmMutation,
|
||||
useAddScheduledActionMutation,
|
||||
|
@ -31,6 +31,7 @@ const VM_RESIZE = 'vm.resize'
|
||||
const VM_UPDATE = 'vm.update'
|
||||
const VM_CONF_UPDATE = 'vm.updateconf'
|
||||
const VM_RECOVER = 'vm.recover'
|
||||
const VM_RESTORE = 'vm.restore'
|
||||
const VM_INFO = 'vm.info'
|
||||
const VM_MONITORING = 'vm.monitoring'
|
||||
const VM_LOCK = 'vm.lock'
|
||||
@ -75,6 +76,7 @@ const Actions = {
|
||||
VM_UPDATE,
|
||||
VM_CONF_UPDATE,
|
||||
VM_RECOVER,
|
||||
VM_RESTORE,
|
||||
VM_INFO,
|
||||
VM_MONITORING,
|
||||
VM_LOCK,
|
||||
@ -606,6 +608,28 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
},
|
||||
[VM_RESTORE]: {
|
||||
// inspected
|
||||
httpMethod: POST,
|
||||
params: {
|
||||
id: {
|
||||
from: postBody,
|
||||
default: -1,
|
||||
},
|
||||
imageId: {
|
||||
from: postBody,
|
||||
default: -1,
|
||||
},
|
||||
incrementId: {
|
||||
from: postBody,
|
||||
default: -1,
|
||||
},
|
||||
diskId: {
|
||||
from: postBody,
|
||||
default: -1,
|
||||
},
|
||||
},
|
||||
},
|
||||
[VM_INFO]: {
|
||||
// inspected
|
||||
httpMethod: GET,
|
||||
|
Loading…
Reference in New Issue
Block a user