1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-13 13:17:39 +03:00

F #5422: Add state condition to VM actions (#1500)

This commit is contained in:
Sergio Betanzos 2021-10-01 12:54:07 +02:00 committed by GitHub
parent 3f9e4436ea
commit c1d57f17ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 246 additions and 40 deletions

View File

@ -73,7 +73,7 @@ const ActionItem = memo(({ item, selectedRows }) => {
const buttonProps = {
color,
'data-cy': accessor && `action.${accessor}`,
disabled,
disabled: typeof disabled === 'function' ? disabled(selectedRows) : disabled,
icon: Icon && <Icon size={18} />,
label: label && Tr(label),
title: tooltip && Tr(tooltip)
@ -85,11 +85,15 @@ const ActionItem = memo(({ item, selectedRows }) => {
<ButtonToTriggerForm
buttonProps={buttonProps}
options={options?.map(option => {
const { form, onSubmit, dialogProps } = option ?? {}
const { accessor, form, onSubmit, dialogProps, disabled: optionDisabled } = option ?? {}
const { title, children } = dialogProps ?? {}
return {
...option,
cy: accessor && `action.${accessor}`,
disabled: typeof optionDisabled === 'function'
? optionDisabled(selectedRows)
: optionDisabled,
dialogProps: {
...dialogProps,
title: typeof title === 'function' ? title(selectedRows) : title,
@ -101,7 +105,15 @@ const ActionItem = memo(({ item, selectedRows }) => {
})}
/>
)
}, (prev, next) => prev.selectedRows?.length === next.selectedRows?.length)
}, (prev, next) => {
const prevStates = prev.selectedRows?.map?.(({ values }) => values?.STATE)
const nextStates = next.selectedRows?.map?.(({ values }) => values?.STATE)
return (
prev.selectedRows?.length === next.selectedRows?.length &&
prevStates?.every(prevState => nextStates?.includes(prevState))
)
})
export const ActionPropTypes = PropTypes.shape({
accessor: PropTypes.string,
@ -121,7 +133,7 @@ export const ActionPropTypes = PropTypes.shape({
isConfirmDialog: PropTypes.bool,
options: PropTypes.arrayOf(
PropTypes.shape({
cy: PropTypes.string,
accessor: PropTypes.string,
name: PropTypes.string,
icon: PropTypes.any,
form: PropTypes.func,

View File

@ -80,11 +80,9 @@ export const createActions = ({ filters = {}, actions = [] }) => {
if (accessor) return action
const groupActions = options?.filter(({ cy }) => {
const [, actionName] = cy?.split('.')
return filters[String(actionName.toLowerCase())] === true
})
const groupActions = options?.filter(option =>
filters[String(option.accessor?.toLowerCase())] === true
)
return groupActions?.length > 0
? { ...action, options: groupActions }

View File

@ -36,7 +36,15 @@ import { Tr, Translate } from 'client/components/HOC'
// import { } from 'client/components/Forms/Vm'
import { createActions } from 'client/components/Tables/Enhanced/Utils'
import { PATH } from 'client/apps/sunstone/routesOne'
import { T, VM_ACTIONS, MARKETPLACE_APP_ACTIONS } from 'client/constants'
import { T, VM_ACTIONS, MARKETPLACE_APP_ACTIONS, VM_ACTIONS_BY_STATE } from 'client/constants'
const isDisabled = action => rows => {
if (VM_ACTIONS_BY_STATE[action]?.length === 0) return false
const states = rows?.map?.(({ values }) => values?.STATE)
return states.some(state => !VM_ACTIONS_BY_STATE[action]?.includes(state))
}
const MessageToConfirmAction = rows => {
const names = rows?.map?.(({ original }) => original?.NAME)
@ -106,18 +114,19 @@ const Actions = () => {
accessor: VM_ACTIONS.RESUME,
tooltip: Tr(T.Resume),
selected: true,
disabled: isDisabled(VM_ACTIONS.RESUME),
icon: PlayOutline,
action: async rows => {
const ids = rows?.map?.(({ original }) => original?.ID)
await Promise.all(ids.map(id => resume(id)))
await Promise.all(ids.map(id => getVm(id)))
ids?.length > 1 && await Promise.all(ids.map(id => getVm(id)))
}
},
{
accessor: VM_ACTIONS.SAVE_AS_TEMPLATE,
tooltip: Tr(T.SaveAsTemplate),
selected: { max: 1 },
disabled: true,
disabled: isDisabled(VM_ACTIONS.SAVE_AS_TEMPLATE),
icon: SaveFloppyDisk,
action: () => {}
},
@ -126,8 +135,9 @@ const Actions = () => {
icon: SystemShut,
selected: true,
options: [{
cy: `action.${VM_ACTIONS.SUSPEND}`,
accessor: VM_ACTIONS.SUSPEND,
name: T.Suspend,
disabled: isDisabled(VM_ACTIONS.SUSPEND),
isConfirmDialog: true,
dialogProps: {
title: T.Suspend,
@ -139,8 +149,9 @@ const Actions = () => {
await Promise.all(ids.map(id => getVm(id)))
}
}, {
cy: `action.${VM_ACTIONS.STOP}`,
accessor: VM_ACTIONS.STOP,
name: T.Stop,
disabled: isDisabled(VM_ACTIONS.STOP),
isConfirmDialog: true,
dialogProps: {
title: T.Stop,
@ -152,8 +163,9 @@ const Actions = () => {
await Promise.all(ids.map(id => getVm(id)))
}
}, {
cy: `action.${VM_ACTIONS.POWEROFF}`,
accessor: VM_ACTIONS.POWEROFF,
name: T.Poweroff,
disabled: isDisabled(VM_ACTIONS.POWEROFF),
isConfirmDialog: true,
dialogProps: {
title: T.Poweroff,
@ -165,8 +177,9 @@ const Actions = () => {
await Promise.all(ids.map(id => getVm(id)))
}
}, {
cy: `action.${VM_ACTIONS.POWEROFF_HARD}`,
accessor: VM_ACTIONS.POWEROFF_HARD,
name: T.PoweroffHard,
disabled: isDisabled(VM_ACTIONS.POWEROFF_HARD),
isConfirmDialog: true,
dialogProps: {
title: T.PoweroffHard,
@ -178,8 +191,9 @@ const Actions = () => {
await Promise.all(ids.map(id => getVm(id)))
}
}, {
cy: `action.${VM_ACTIONS.REBOOT}`,
accessor: VM_ACTIONS.REBOOT,
name: T.Reboot,
disabled: isDisabled(VM_ACTIONS.REBOOT),
isConfirmDialog: true,
dialogProps: {
title: T.Reboot,
@ -191,8 +205,9 @@ const Actions = () => {
await Promise.all(ids.map(id => getVm(id)))
}
}, {
cy: `action.${VM_ACTIONS.REBOOT_HARD}`,
accessor: VM_ACTIONS.REBOOT_HARD,
name: T.RebootHard,
disabled: isDisabled(VM_ACTIONS.REBOOT_HARD),
isConfirmDialog: true,
dialogProps: {
title: T.RebootHard,
@ -204,8 +219,9 @@ const Actions = () => {
await Promise.all(ids.map(id => getVm(id)))
}
}, {
cy: `action.${VM_ACTIONS.UNDEPLOY}`,
accessor: VM_ACTIONS.UNDEPLOY,
name: T.Undeploy,
disabled: isDisabled(VM_ACTIONS.UNDEPLOY),
isConfirmDialog: true,
dialogProps: {
title: T.Undeploy,
@ -217,8 +233,9 @@ const Actions = () => {
await Promise.all(ids.map(id => getVm(id)))
}
}, {
cy: `action.${VM_ACTIONS.UNDEPLOY_HARD}`,
accessor: VM_ACTIONS.UNDEPLOY_HARD,
name: T.UndeployHard,
disabled: isDisabled(VM_ACTIONS.UNDEPLOY_HARD),
isConfirmDialog: true,
dialogProps: {
title: T.UndeployHard,
@ -236,26 +253,27 @@ const Actions = () => {
icon: TransitionRight,
selected: true,
options: [{
cy: `action.${VM_ACTIONS.DEPLOY}`,
accessor: VM_ACTIONS.DEPLOY,
name: T.Deploy,
disabled: true,
disabled: isDisabled(VM_ACTIONS.DEPLOY),
isConfirmDialog: true,
onSubmit: () => undefined
}, {
cy: `action.${VM_ACTIONS.MIGRATE}`,
accessor: VM_ACTIONS.MIGRATE,
name: T.Migrate,
disabled: true,
disabled: isDisabled(VM_ACTIONS.MIGRATE),
isConfirmDialog: true,
onSubmit: () => undefined
}, {
cy: `action.${VM_ACTIONS.MIGRATE_LIVE}`,
accessor: VM_ACTIONS.MIGRATE_LIVE,
name: T.MigrateLive,
disabled: true,
disabled: isDisabled(VM_ACTIONS.MIGRATE_LIVE),
isConfirmDialog: true,
onSubmit: () => undefined
}, {
cy: `action.${VM_ACTIONS.HOLD}`,
accessor: VM_ACTIONS.HOLD,
name: T.Hold,
disabled: isDisabled(VM_ACTIONS.HOLD),
isConfirmDialog: true,
dialogProps: {
title: T.Hold,
@ -267,8 +285,9 @@ const Actions = () => {
await Promise.all(ids.map(id => getVm(id)))
}
}, {
cy: `action.${VM_ACTIONS.RELEASE}`,
accessor: VM_ACTIONS.RELEASE,
name: T.Release,
disabled: isDisabled(VM_ACTIONS.RELEASE),
isConfirmDialog: true,
dialogProps: {
title: T.Release,
@ -280,8 +299,9 @@ const Actions = () => {
await Promise.all(ids.map(id => getVm(id)))
}
}, {
cy: `action.${VM_ACTIONS.RESCHED}`,
accessor: VM_ACTIONS.RESCHED,
name: T.Reschedule,
disabled: isDisabled(VM_ACTIONS.RESCHED),
isConfirmDialog: true,
dialogProps: {
title: T.Reschedule,
@ -293,8 +313,9 @@ const Actions = () => {
await Promise.all(ids.map(id => getVm(id)))
}
}, {
cy: `action.${VM_ACTIONS.UNRESCHED}`,
accessor: VM_ACTIONS.UNRESCHED,
name: T.UnReschedule,
disabled: isDisabled(VM_ACTIONS.UNRESCHED),
isConfirmDialog: true,
dialogProps: {
title: T.UnReschedule,
@ -306,9 +327,9 @@ const Actions = () => {
await Promise.all(ids.map(id => getVm(id)))
}
}, {
cy: `action.${VM_ACTIONS.RECOVER}`,
accessor: VM_ACTIONS.RECOVER,
name: T.Recover,
disabled: true,
disabled: isDisabled(VM_ACTIONS.RECOVER),
isConfirmDialog: true,
onSubmit: () => undefined
}]
@ -318,15 +339,15 @@ const Actions = () => {
icon: Group,
selected: true,
options: [{
cy: `action.${VM_ACTIONS.CHANGE_OWNER}`,
accessor: VM_ACTIONS.CHANGE_OWNER,
name: T.ChangeOwner,
disabled: true,
disabled: isDisabled(VM_ACTIONS.CHANGE_OWNER),
isConfirmDialog: true,
onSubmit: () => undefined
}, {
cy: `action.${VM_ACTIONS.CHANGE_GROUP}`,
accessor: VM_ACTIONS.CHANGE_GROUP,
name: T.ChangeGroup,
disabled: true,
disabled: isDisabled(VM_ACTIONS.CHANGE_GROUP),
isConfirmDialog: true,
onSubmit: () => undefined
}]
@ -336,8 +357,9 @@ const Actions = () => {
icon: Lock,
selected: true,
options: [{
cy: `action.${VM_ACTIONS.LOCK}`,
accessor: VM_ACTIONS.LOCK,
name: T.Lock,
disabled: isDisabled(VM_ACTIONS.LOCK),
isConfirmDialog: true,
dialogProps: {
title: T.Lock,
@ -349,8 +371,9 @@ const Actions = () => {
await Promise.all(ids.map(id => getVm(id)))
}
}, {
cy: `action.${VM_ACTIONS.UNLOCK}`,
accessor: VM_ACTIONS.UNLOCK,
name: T.Unlock,
disabled: isDisabled(VM_ACTIONS.UNLOCK),
isConfirmDialog: true,
dialogProps: {
title: T.Unlock,
@ -368,8 +391,9 @@ const Actions = () => {
icon: Trash,
selected: true,
options: [{
cy: `action.${VM_ACTIONS.TERMINATE}`,
accessor: VM_ACTIONS.TERMINATE,
name: T.Terminate,
disabled: isDisabled(VM_ACTIONS.TERMINATE),
isConfirmDialog: true,
dialogProps: {
title: T.Terminate,
@ -381,9 +405,10 @@ const Actions = () => {
await Promise.all(ids.map(id => getVm(id)))
}
}, {
cy: `action.${VM_ACTIONS.TERMINATE_HARD}`,
accessor: VM_ACTIONS.TERMINATE_HARD,
name: T.TerminateHard,
isConfirmDialog: true,
disabled: isDisabled(VM_ACTIONS.TERMINATE_HARD),
dialogProps: {
title: T.TerminateHard,
children: MessageToConfirmAction

View File

@ -468,6 +468,7 @@ export const VM_ACTIONS = {
FILE_RDP: 'file_rdp',
FILE_VIRT_VIEWER: 'file_virt_viewer',
// INFORMATION
RENAME: ACTIONS.RENAME,
CHANGE_MODE: ACTIONS.CHANGE_MODE,
CHANGE_OWNER: ACTIONS.CHANGE_OWNER,
@ -505,6 +506,176 @@ export const VM_ACTIONS = {
UPDATE_CONF: 'update_configuration'
}
/** @enum {string} Virtual machine actions by state */
export const VM_ACTIONS_BY_STATE = {
[VM_ACTIONS.DEPLOY]: [
STATES.PENDING,
STATES.HOLD,
STATES.STOPPED,
STATES.UNDEPLOYED,
STATES.UNKNOWN
],
[VM_ACTIONS.HOLD]: [STATES.PENDING],
[VM_ACTIONS.LOCK]: [],
[VM_ACTIONS.MIGRATE_LIVE]: [STATES.RUNNING, STATES.UNKNOWN],
[VM_ACTIONS.MIGRATE_POFF_HARD]: [STATES.RUNNING, STATES.UNKNOWN],
[VM_ACTIONS.MIGRATE_POFF]: [STATES.RUNNING, STATES.UNKNOWN],
[VM_ACTIONS.MIGRATE]: [
STATES.SUSPENDED,
STATES.POWEROFF,
STATES.RUNNING,
STATES.UNKNOWN
],
[VM_ACTIONS.POWEROFF_HARD]: [STATES.RUNNING, STATES.UNKNOWN],
[VM_ACTIONS.POWEROFF]: [STATES.RUNNING, STATES.UNKNOWN],
[VM_ACTIONS.REBOOT_HARD]: [STATES.RUNNING],
[VM_ACTIONS.REBOOT]: [STATES.RUNNING],
[VM_ACTIONS.RECOVER]: [
STATES.INIT,
STATES.PENDING,
STATES.HOLD,
STATES.STOPPED,
STATES.SUSPENDED,
STATES.POWEROFF,
STATES.UNDEPLOYED,
STATES.CLONING,
STATES.CLONING_FAILURE
],
[VM_ACTIONS.RELEASE]: [STATES.HOLD],
[VM_ACTIONS.RESCHED]: [STATES.POWEROFF, STATES.RUNNING, STATES.UNKNOWN],
[VM_ACTIONS.RESUME]: [
STATES.STOPPED,
STATES.SUSPENDED,
STATES.POWEROFF,
STATES.UNDEPLOYED,
STATES.UNKNOWN
],
[VM_ACTIONS.SAVE_AS_TEMPLATE]: [STATES.POWEROFF],
[VM_ACTIONS.STOP]: [STATES.SUSPENDED, STATES.RUNNING],
[VM_ACTIONS.SUSPEND]: [STATES.RUNNING],
[VM_ACTIONS.TERMINATE_HARD]: [
STATES.INIT,
STATES.PENDING,
STATES.HOLD,
STATES.STOPPED,
STATES.SUSPENDED,
STATES.POWEROFF,
STATES.UNDEPLOYED,
STATES.CLONING,
STATES.CLONING_FAILURE,
STATES.RUNNING,
STATES.UNKNOWN
],
[VM_ACTIONS.TERMINATE]: [
STATES.RUNNING,
STATES.FAILURE,
STATES.BOOT_FAILURE,
STATES.BOOT_MIGRATE_FAILURE,
STATES.PROLOG_MIGRATE_FAILURE,
STATES.PROLOG_FAILURE,
STATES.EPILOG_FAILURE,
STATES.EPILOG_STOP_FAILURE,
STATES.EPILOG_UNDEPLOY_FAILURE,
STATES.PROLOG_MIGRATE_POWEROFF_FAILURE,
STATES.PROLOG_MIGRATE_SUSPEND_FAILURE,
STATES.BOOT_UNDEPLOY_FAILURE,
STATES.BOOT_STOPPED_FAILURE,
STATES.PROLOG_RESUME_FAILURE,
STATES.PROLOG_UNDEPLOY_FAILURE,
STATES.PROLOG_MIGRATE_UNKNOWN_FAILURE
],
[VM_ACTIONS.UNDEPLOY_HARD]: [STATES.POWEROFF, STATES.RUNNING, STATES.UNKNOWN],
[VM_ACTIONS.UNDEPLOY]: [STATES.POWEROFF, STATES.RUNNING, STATES.UNKNOWN],
[VM_ACTIONS.UNLOCK]: [],
[VM_ACTIONS.UNRESCHED]: [STATES.RUNNING, STATES.UNKNOWN],
// REMOTE
[VM_ACTIONS.VMRC]: [],
[VM_ACTIONS.SPICE]: [],
[VM_ACTIONS.VNC]: [],
[VM_ACTIONS.SSH]: [],
[VM_ACTIONS.RDP]: [],
[VM_ACTIONS.FILE_RDP]: [],
[VM_ACTIONS.FILE_VIRT_VIEWER]: [],
// INFORMATION
[VM_ACTIONS.RENAME]: [],
[VM_ACTIONS.CHANGE_MODE]: [],
[VM_ACTIONS.CHANGE_OWNER]: [],
[VM_ACTIONS.CHANGE_GROUP]: [],
// CAPACITY
[VM_ACTIONS.RESIZE_CAPACITY]: [
STATES.INIT,
STATES.PENDING,
STATES.HOLD,
STATES.ACTIVE,
STATES.POWEROFF,
STATES.UNDEPLOYED,
STATES.CLONING,
STATES.CLONING_FAILURE
],
// STORAGE
[VM_ACTIONS.ATTACH_DISK]: [STATES.POWEROFF, STATES.RUNNING],
[VM_ACTIONS.DETACH_DISK]: [STATES.POWEROFF, STATES.RUNNING],
[VM_ACTIONS.SNAPSHOT_DISK_CREATE]: [STATES.SUSPENDED, STATES.POWEROFF, STATES.RUNNING],
[VM_ACTIONS.SNAPSHOT_DISK_RENAME]: [],
[VM_ACTIONS.SNAPSHOT_DISK_REVERT]: [STATES.SUSPENDED, STATES.POWEROFF],
[VM_ACTIONS.SNAPSHOT_DISK_DELETE]: [STATES.SUSPENDED, STATES.POWEROFF, STATES.RUNNING],
[VM_ACTIONS.RESIZE_DISK]: [STATES.POWEROFF, STATES.RUNNING],
[VM_ACTIONS.DISK_SAVEAS]: [STATES.SUSPENDED, STATES.POWEROFF, STATES.RUNNING],
// NETWORK
[VM_ACTIONS.ATTACH_NIC]: [STATES.POWEROFF, STATES.RUNNING],
[VM_ACTIONS.DETACH_NIC]: [STATES.POWEROFF, STATES.RUNNING],
// SNAPSHOT
[VM_ACTIONS.SNAPSHOT_CREATE]: [],
[VM_ACTIONS.SNAPSHOT_REVERT]: [],
[VM_ACTIONS.SNAPSHOT_DELETE]: [STATES.POWEROFF],
// SCHEDULING ACTION
[VM_ACTIONS.SCHED_ACTION_CREATE]: [],
[VM_ACTIONS.SCHED_ACTION_UPDATE]: [],
[VM_ACTIONS.SCHED_ACTION_DELETE]: [],
[VM_ACTIONS.CHARTER_CREATE]: [],
// CONFIGURATION
[VM_ACTIONS.UPDATE_CONF]: [
STATES.PENDING,
STATES.HOLD,
STATES.ACTIVE,
STATES.POWEROFF,
STATES.UNDEPLOYED,
STATES.CLONING,
STATES.CLONING_FAILURE,
STATES.PROLOG,
STATES.EPILOG,
STATES.SHUTDOWN,
STATES.CLEANUP_RESUBMIT,
STATES.SHUTDOWN_POWEROFF,
STATES.CLEANUP_DELETE,
STATES.HOTPLUG_SAVEAS_POWEROFF,
STATES.SHUTDOWN_UNDEPLOY,
STATES.EPILOG_UNDEPLOY,
STATES.PROLOG_UNDEPLOY,
STATES.HOTPLUG_PROLOG_POWEROFF,
STATES.HOTPLUG_EPILOG_POWEROFF,
STATES.BOOT_FAILURE,
STATES.PROLOG_FAILURE,
STATES.EPILOG_FAILURE,
STATES.EPILOG_UNDEPLOY_FAILURE,
STATES.PROLOG_MIGRATE_POWEROFF,
STATES.PROLOG_MIGRATE_POWEROFF_FAILURE,
STATES.BOOT_UNDEPLOY_FAILURE,
STATES.PROLOG_UNDEPLOY_FAILURE,
STATES.DISK_SNAPSHOT_POWEROFF,
STATES.DISK_SNAPSHOT_REVERT_POWEROFF,
STATES.DISK_SNAPSHOT_DELETE_POWEROFF
]
}
/** @enum {string} Hypervisors */
export const HYPERVISORS = {
kvm: 'kvm',