diff --git a/src/fireedge/etc/sunstone/admin/vm-tab.yaml b/src/fireedge/etc/sunstone/admin/vm-tab.yaml index eeb9145a49..14f3d11c0d 100644 --- a/src/fireedge/etc/sunstone/admin/vm-tab.yaml +++ b/src/fireedge/etc/sunstone/admin/vm-tab.yaml @@ -87,6 +87,10 @@ info-tabs: actions: chown: true chgrp: true + capacity_panel: + enabled: true + actions: + resize_capacity: true vcenter_panel: enabled: true actions: @@ -113,11 +117,6 @@ info-tabs: edit: true delete: true - capacity: - enabled: true - actions: - resize_capacity: true - storage: enabled: true actions: diff --git a/src/fireedge/etc/sunstone/user/vm-tab.yaml b/src/fireedge/etc/sunstone/user/vm-tab.yaml index ac4cd8269d..2f7370b444 100644 --- a/src/fireedge/etc/sunstone/user/vm-tab.yaml +++ b/src/fireedge/etc/sunstone/user/vm-tab.yaml @@ -88,6 +88,10 @@ info-tabs: actions: chown: false chgrp: false + capacity_panel: + enabled: true + actions: + resize_capacity: true vcenter_panel: enabled: true actions: @@ -114,11 +118,6 @@ info-tabs: edit: false delete: false - capacity: - enabled: true - actions: - resize_capacity: true - storage: enabled: true actions: diff --git a/src/fireedge/src/client/components/Tabs/Vm/Capacity/index.js b/src/fireedge/src/client/components/Tabs/Vm/Capacity/index.js deleted file mode 100644 index 1913db4f19..0000000000 --- a/src/fireedge/src/client/components/Tabs/Vm/Capacity/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/* ------------------------------------------------------------------------- * - * Copyright 2002-2022, 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 { ReactElement, useMemo } from 'react' -import PropTypes from 'prop-types' - -import { useGetVmQuery, useResizeMutation } from 'client/features/OneApi/vm' -import InformationPanel from 'client/components/Tabs/Vm/Capacity/information' - -import { getHypervisor, isAvailableAction } from 'client/models/VirtualMachine' -import { getActionsAvailable, jsonToXml } from 'client/models/Helper' - -/** - * Renders capacity tab. - * - * @param {object} props - Props - * @param {object} props.tabProps - Tab information - * @param {string[]} props.tabProps.actions - Actions tab - * @param {string} props.id - Virtual Machine id - * @returns {ReactElement} Capacity tab - */ -const VmCapacityTab = ({ tabProps: { actions } = {}, id }) => { - const [resizeCapacity] = useResizeMutation() - const { data: vm = {} } = useGetVmQuery({ id }) - - const actionsAvailable = useMemo(() => { - const hypervisor = getHypervisor(vm) - const actionsByHypervisor = getActionsAvailable(actions, hypervisor) - const actionsByState = actionsByHypervisor.filter((action) => - isAvailableAction(action, vm) - ) - - return actionsByState - }, [vm]) - - const handleResizeCapacity = async (formData) => { - const { enforce, ...restOfData } = formData - const template = jsonToXml(restOfData) - - await resizeCapacity({ id: vm.ID, enforce, template }) - } - - return ( - - ) -} - -VmCapacityTab.propTypes = { - tabProps: PropTypes.object, - id: PropTypes.string, -} - -VmCapacityTab.displayName = 'VmCapacityTab' - -export default VmCapacityTab diff --git a/src/fireedge/src/client/components/Tabs/Vm/Capacity/information.js b/src/fireedge/src/client/components/Tabs/Vm/Capacity/information.js deleted file mode 100644 index 1849fe1148..0000000000 --- a/src/fireedge/src/client/components/Tabs/Vm/Capacity/information.js +++ /dev/null @@ -1,140 +0,0 @@ -/* ------------------------------------------------------------------------- * - * Copyright 2002-2022, 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 { useMemo, ReactElement } from 'react' -import PropTypes from 'prop-types' -import { Typography } from '@mui/material' - -import ButtonToTriggerForm from 'client/components/Forms/ButtonToTriggerForm' -import { ResizeCapacityForm } from 'client/components/Forms/Vm' -import { Tr, Translate } from 'client/components/HOC' -import useCapacityTabStyles from 'client/components/Tabs/Vm/Capacity/styles' - -import { isVCenter } from 'client/models/VirtualMachine' -import { formatNumberByCurrency } from 'client/models/Helper' -import { prettyBytes } from 'client/utils' -import { T, VM_ACTIONS, VM } from 'client/constants' - -/** - * Renders capacity information. - * - * @param {object} props - Props - * @param {string[]} props.actions - Actions tab - * @param {VM} props.vm - Virtual Machine id - * @param {string} props.handleResizeCapacity - Resize capacity - * @returns {ReactElement} Capacity information - */ -const InformationPanel = ({ actions, vm = {}, handleResizeCapacity }) => { - const classes = useCapacityTabStyles() - const { TEMPLATE } = vm - - const memory = TEMPLATE?.MEMORY - const memoryCost = useMemo(() => { - const cost = TEMPLATE?.MEMORY_COST || 0 - const monthCost = formatNumberByCurrency(memory * cost * 24 * 30) - - return - }, [memory, TEMPLATE?.MEMORY_COST]) - - const cpu = TEMPLATE?.CPU - const cpuCost = useMemo(() => { - const cost = TEMPLATE?.CPU_COST || 0 - const monthCost = formatNumberByCurrency(cpu * cost * 24 * 30) - - return - }, [cpu, TEMPLATE?.CPU_COST]) - - const capacity = [ - { - name: T.PhysicalCpu, - value: cpu, - dataCy: 'cpu', - }, - { - name: T.VirtualCpu, - value: TEMPLATE?.VCPU ?? '-', - dataCy: 'virtualcpu', - }, - isVCenter(vm) && { - name: T.VirtualCores, - value: ( - <> - {`${Tr(T.Cores)} x ${TEMPLATE?.TOPOLOGY?.CORES || '-'} | - ${Tr(T.Sockets)} ${TEMPLATE?.TOPOLOGY?.SOCKETS || '-'}`} - - ), - dataCy: 'virtualcores', - }, - { - name: T.Memory, - value: prettyBytes(+memory, 'MB'), - dataCy: 'memory', - }, - { - name: T.CostCpu, - value: cpuCost, - dataCy: 'cpucost', - }, - { - name: T.CostMemory, - value: memoryCost, - dataCy: 'memorycost', - }, - ].filter(Boolean) - - return ( -
-
- {actions?.includes?.(VM_ACTIONS.RESIZE_CAPACITY) && ( - ResizeCapacityForm({ initialValues: vm.TEMPLATE }), - onSubmit: handleResizeCapacity, - }, - ]} - /> - )} -
- {capacity.map(({ name, value, dataCy }) => ( -
- - {name} - - - {value} - -
- ))} -
- ) -} - -InformationPanel.propTypes = { - handleResizeCapacity: PropTypes.func, - actions: PropTypes.array, - vm: PropTypes.object, -} - -InformationPanel.displayName = 'InformationPanel' - -export default InformationPanel diff --git a/src/fireedge/src/client/components/Tabs/Vm/Capacity/styles.js b/src/fireedge/src/client/components/Tabs/Vm/Capacity/styles.js deleted file mode 100644 index 0061ffa29e..0000000000 --- a/src/fireedge/src/client/components/Tabs/Vm/Capacity/styles.js +++ /dev/null @@ -1,47 +0,0 @@ -/* ------------------------------------------------------------------------- * - * Copyright 2002-2022, 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 makeStyles from '@mui/styles/makeStyles' - -export default makeStyles((theme) => ({ - root: { - padding: '0.5em', - display: 'grid', - gap: '1em', - gridAutoFlow: 'column', - [theme.breakpoints.down('md')]: { - gridAutoFlow: 'initial', - }, - }, - item: { - [theme.breakpoints.down('md')]: { - display: 'flex', - gap: '1em', - '& > *': { - width: '50%', - }, - }, - }, - actions: { - [theme.breakpoints.down('md')]: { - borderBottom: `1px solid ${theme.palette.divider}`, - padding: '0 1em 1em 1em', - }, - [theme.breakpoints.up('md')]: { - order: 1, - textAlign: 'end', - }, - }, -})) diff --git a/src/fireedge/src/client/components/Tabs/Vm/Info/capacity.js b/src/fireedge/src/client/components/Tabs/Vm/Info/capacity.js new file mode 100644 index 0000000000..3c1ce55977 --- /dev/null +++ b/src/fireedge/src/client/components/Tabs/Vm/Info/capacity.js @@ -0,0 +1,169 @@ +/* ------------------------------------------------------------------------- * + * Copyright 2002-2022, 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 { ReactElement, useMemo } from 'react' +import PropTypes from 'prop-types' +import { Edit as EditIcon } from 'iconoir-react' +import { Stack, Typography } from '@mui/material' + +import { useResizeMutation } from 'client/features/OneApi/vm' +import ButtonToTriggerForm from 'client/components/Forms/ButtonToTriggerForm' +import { ResizeCapacityForm } from 'client/components/Forms/Vm' +import { List } from 'client/components/Tabs/Common' +import { Tr, Translate } from 'client/components/HOC' + +import { isVCenter, isAvailableAction } from 'client/models/VirtualMachine' +import { formatNumberByCurrency, jsonToXml } from 'client/models/Helper' +import { prettyBytes } from 'client/utils' +import { T, VM, VM_ACTIONS } from 'client/constants' + +/** + * Renders mainly capacity tab. + * + * @param {object} props - Props + * @param {VM} props.vm - Virtual machine + * @param {string[]} props.actions - Available actions to capacity tab + * @returns {ReactElement} Capacity tab + */ +const CapacityPanel = ({ vm = {}, actions }) => { + const { + CPU, + VCPU = '-', + MEMORY, + CPU_COST, + MEMORY_COST, + TOPOLOGY: { CORES = '-', SOCKETS = '-' } = {}, + } = vm?.TEMPLATE || {} + + const memoryCost = useMemo(() => { + const cost = MEMORY_COST || 0 + const monthCost = formatNumberByCurrency(MEMORY * cost * 24 * 30) + + return + }, [MEMORY, MEMORY_COST]) + + const cpuCost = useMemo(() => { + const cost = CPU_COST || 0 + const monthCost = formatNumberByCurrency(CPU * cost * 24 * 30) + + return + }, [CPU, CPU_COST]) + + const info = [ + { + name: T.PhysicalCpu, + value: CPU, + dataCy: 'cpu', + }, + { + name: T.VirtualCpu, + value: VCPU, + dataCy: 'vcpu', + }, + isVCenter(vm) && { + name: T.VirtualCores, + value: [ + `${Tr(T.Cores)} x ${CORES}`, + `${Tr(T.Sockets)} x ${SOCKETS}`, + ].join(' | '), + dataCy: 'virtualcores', + }, + { + name: T.Memory, + value: prettyBytes(+MEMORY, 'MB'), + dataCy: 'memory', + }, + { + name: T.CostCpu, + value: cpuCost, + dataCy: 'cpucost', + }, + { + name: T.CostMemory, + value: memoryCost, + dataCy: 'memorycost', + }, + ].filter(Boolean) + + return } list={info} /> +} + +CapacityPanel.propTypes = { + actions: PropTypes.arrayOf(PropTypes.string), + vm: PropTypes.object, +} + +CapacityPanel.displayName = 'CapacityPanel' + +/** + * Renders header of capacity panel. + * + * @param {object} props - Props + * @param {VM} props.vm - Virtual machine + * @param {string[]} props.actions - Available actions to capacity tab + * @returns {ReactElement} Capacity panel header + */ +const PanelHeader = ({ vm = {}, actions = [] }) => { + const [resizeCapacity] = useResizeMutation() + + const handleResizeCapacity = async (formData) => { + const { enforce, ...restOfData } = formData + const template = jsonToXml(restOfData) + + await resizeCapacity({ id: vm.ID, enforce, template }) + } + + const resizeIsAvailable = useMemo( + () => + actions + .filter((action) => isAvailableAction(action, vm)) + .includes?.(VM_ACTIONS.RESIZE_CAPACITY), + [vm] + ) + + return ( + + + + + {resizeIsAvailable && ( + , + tooltip: , + }} + options={[ + { + dialogProps: { title: T.ResizeCapacity }, + form: () => ResizeCapacityForm({ initialValues: vm.TEMPLATE }), + onSubmit: handleResizeCapacity, + }, + ]} + /> + )} + + ) +} + +PanelHeader.propTypes = { ...CapacityPanel.propTypes } +PanelHeader.displayName = 'PanelHeader' + +export default CapacityPanel diff --git a/src/fireedge/src/client/components/Tabs/Vm/Info/index.js b/src/fireedge/src/client/components/Tabs/Vm/Info/index.js index d86395d1a4..6ea5365fca 100644 --- a/src/fireedge/src/client/components/Tabs/Vm/Info/index.js +++ b/src/fireedge/src/client/components/Tabs/Vm/Info/index.js @@ -30,6 +30,7 @@ import { AttributePanel, } from 'client/components/Tabs/Common' import Information from 'client/components/Tabs/Vm/Info/information' +import Capacity from 'client/components/Tabs/Vm/Info/capacity' import { SubmitButton } from 'client/components/FormControl' import { Tr, Translate } from 'client/components/HOC' @@ -60,6 +61,7 @@ const HIDDEN_MONITORING_REG = const VmInfoTab = ({ tabProps = {}, id }) => { const { information_panel: informationPanel, + capacity_panel: capacityPanel, permissions_panel: permissionsPanel, ownership_panel: ownershipPanel, vcenter_panel: vcenterPanel, @@ -180,6 +182,9 @@ const VmInfoTab = ({ tabProps = {}, id }) => { groupName={GNAME} /> )} + {capacityPanel?.enabled && ( + + )} {attributesPanel?.enabled && attributes && ( ({ - capacity: Capacity, configuration: Configuration, info: Info, network: Network,