diff --git a/src/fireedge/src/client/components/Forms/ButtonToTriggerForm.js b/src/fireedge/src/client/components/Forms/ButtonToTriggerForm.js index dc97988740..930fec2cdf 100644 --- a/src/fireedge/src/client/components/Forms/ButtonToTriggerForm.js +++ b/src/fireedge/src/client/components/Forms/ButtonToTriggerForm.js @@ -32,6 +32,7 @@ import SubmitButton, { } from 'client/components/FormControl/SubmitButton' import FormStepper from 'client/components/FormStepper' import { Translate } from 'client/components/HOC' +import { isDevelopment } from 'client/utils' const ButtonToTriggerForm = ({ buttonProps = {}, options = [] }) => { const buttonId = buttonProps['data-cy'] ?? 'main-button' @@ -59,6 +60,8 @@ const ButtonToTriggerForm = ({ buttonProps = {}, options = [] }) => { try { const data = transformBeforeSubmit?.(formData) ?? formData await handleSubmit?.(data) + } catch (error) { + isDevelopment() && console.error(error) } finally { hide() } diff --git a/src/fireedge/src/client/components/Forms/Vm/AttachDiskForm/ImageSteps/AdvancedOptions/schema.js b/src/fireedge/src/client/components/Forms/Vm/AttachDiskForm/ImageSteps/AdvancedOptions/schema.js index c2b5f00ae1..25145e8943 100644 --- a/src/fireedge/src/client/components/Forms/Vm/AttachDiskForm/ImageSteps/AdvancedOptions/schema.js +++ b/src/fireedge/src/client/components/Forms/Vm/AttachDiskForm/ImageSteps/AdvancedOptions/schema.js @@ -26,7 +26,7 @@ import { T, INPUT_TYPES, HYPERVISORS } from 'client/constants' import { Field, Section, - getValidationFromFields, + getObjectSchemaFromFields, filterFieldsByHypervisor, } from 'client/utils' @@ -90,6 +90,6 @@ const FIELDS = (hypervisor) => * @param {HYPERVISORS} hypervisor - Hypervisor * @returns {ObjectSchema} Advanced options schema */ -const SCHEMA = (hypervisor) => getValidationFromFields(FIELDS(hypervisor)) +const SCHEMA = (hypervisor) => getObjectSchemaFromFields(FIELDS(hypervisor)) export { SECTIONS, FIELDS, SCHEMA } diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/numa/index.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/numa/index.js index 41c8d9e786..1188a1f8f4 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/numa/index.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/numa/index.js @@ -15,6 +15,7 @@ * ------------------------------------------------------------------------- */ import PropTypes from 'prop-types' import { ElectronicsChip as NumaIcon } from 'iconoir-react' +import { useWatch } from 'react-hook-form' import FormWithSchema from 'client/components/Forms/FormWithSchema' import { STEP_ID as GENERAL_ID } from 'client/components/Forms/VmTemplate/CreateForm/Steps/General' @@ -23,25 +24,39 @@ import { TabType, } from 'client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration' import { VIRTUAL_CPU as VCPU_FIELD } from 'client/components/Forms/VmTemplate/CreateForm/Steps/General/capacitySchema' -import { FIELDS as NUMA_FIELDS } from 'client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/numa/schema' +import { + NUMA_FIELDS, + ENABLE_NUMA, +} from 'client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/numa/schema' import { T } from 'client/constants' export const TAB_ID = 'NUMA' -const Numa = ({ hypervisor }) => ( - <> - - - -) +const Numa = ({ hypervisor }) => { + const enableNuma = useWatch({ name: `${EXTRA_ID}.${ENABLE_NUMA.name}` }) + + return ( + <> + + + {enableNuma && ( + + )} + + ) +} Numa.propTypes = { data: PropTypes.any, diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/numa/schema.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/numa/schema.js index 95ce5bc971..ed13f3cf6e 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/numa/schema.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/numa/schema.js @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { string, number } from 'yup' +import { string, number, boolean, lazy } from 'yup' import { useGetHostsQuery } from 'client/features/OneApi/host' import { getHugepageSizes } from 'client/models/Host' @@ -37,6 +37,17 @@ const { vcenter, firecracker } = HYPERVISORS const threadsValidation = number().nullable().notRequired().integer() +const ENABLE_NUMA = { + name: 'TOPOLOGY.ENABLE_NUMA', + label: T.NumaTopology, + type: INPUT_TYPES.CHECKBOX, + tooltip: T.NumaTopologyConcept, + validation: lazy((_, { context }) => + boolean().default(() => !!context?.extra?.TOPOLOGY) + ), + grid: { md: 12 }, +} + /** * @param {HYPERVISORS} hypervisor - VM hypervisor * @returns {Field} Pin policy field @@ -61,7 +72,7 @@ const PIN_POLICY = (hypervisor) => { () => isFirecracker ? NUMA_PIN_POLICIES[2] // SHARED - : NUMA_PIN_POLICIES[0] // NONE + : undefined // NONE ), fieldProps: { disabled: isVCenter || isFirecracker }, } @@ -98,7 +109,7 @@ const SOCKETS = (hypervisor) => ({ validation: number() .notRequired() .integer() - .default(() => 1), + .default(() => undefined), fieldProps: { disabled: hypervisor === firecracker, }, @@ -177,10 +188,16 @@ const MEMORY_ACCESS = { * @param {string} [hypervisor] - VM hypervisor * @returns {Field[]} List of NUMA fields */ -const FIELDS = (hypervisor) => +const NUMA_FIELDS = (hypervisor) => filterFieldsByHypervisor( [PIN_POLICY, CORES, SOCKETS, THREADS, HUGEPAGES, MEMORY_ACCESS], hypervisor ) -export { FIELDS } +/** + * @param {string} [hypervisor] - VM hypervisor + * @returns {Field[]} List of NUMA fields + */ +const SCHEMA_FIELDS = (hypervisor) => [ENABLE_NUMA, ...NUMA_FIELDS(hypervisor)] + +export { NUMA_FIELDS, SCHEMA_FIELDS as FIELDS, ENABLE_NUMA } diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/index.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/index.js index f0a9644e56..15d776b979 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/index.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/index.js @@ -60,6 +60,7 @@ const Steps = createSteps([General, ExtraConfiguration, CustomVariables], { [CUSTOM_ID]: customVariables = {}, [EXTRA_ID]: { CONTEXT: { START_SCRIPT, ENCODE_START_SCRIPT, ...restOfContext }, + TOPOLOGY: { ENABLE_NUMA, ...restOfTopology }, ...extraTemplate } = {}, } = formData ?? {} @@ -72,6 +73,7 @@ const Steps = createSteps([General, ExtraConfiguration, CustomVariables], { ? btoa(unescape(encodeURIComponent(START_SCRIPT))) : START_SCRIPT, } + const topology = ENABLE_NUMA ? { TOPOLOGY: restOfTopology } : {} // add user inputs to context Object.keys(extraTemplate?.USER_INPUTS ?? {}).forEach((name) => { @@ -83,6 +85,7 @@ const Steps = createSteps([General, ExtraConfiguration, CustomVariables], { ...customVariables, ...extraTemplate, ...general, + ...topology, CONTEXT: context, }) }, diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/InstantiateForm/Steps/index.js b/src/fireedge/src/client/components/Forms/VmTemplate/InstantiateForm/Steps/index.js index b7f6b0cab0..1ffb53945f 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/InstantiateForm/Steps/index.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/InstantiateForm/Steps/index.js @@ -47,11 +47,20 @@ const Steps = createSteps( const { [TEMPLATE_ID]: [templateSelected] = [], [BASIC_ID]: { name, instances, hold, persistent, ...restOfConfig } = {}, - [EXTRA_ID]: extraTemplate = {}, + [EXTRA_ID]: { + TOPOLOGY: { ENABLE_NUMA, ...restOfTopology }, + ...extraTemplate + } = {}, } = formData ?? {} + const topology = ENABLE_NUMA ? { TOPOLOGY: restOfTopology } : {} + // merge with template disks to get TYPE attribute - const templateXML = jsonToXml({ ...extraTemplate, ...restOfConfig }) + const templateXML = jsonToXml({ + ...extraTemplate, + ...topology, + ...restOfConfig, + }) const data = { instances, hold, persistent, template: templateXML } const templates = [...new Array(instances)].map((_, idx) => ({ diff --git a/src/fireedge/src/client/components/Tables/MarketplaceApps/actions.js b/src/fireedge/src/client/components/Tables/MarketplaceApps/actions.js index 34f96fa01d..5063b4e948 100644 --- a/src/fireedge/src/client/components/Tables/MarketplaceApps/actions.js +++ b/src/fireedge/src/client/components/Tables/MarketplaceApps/actions.js @@ -76,7 +76,10 @@ const Actions = () => { icon: CloudDownload, options: [ { - dialogProps: { title: T.DownloadAppToOpenNebula }, + dialogProps: { + title: T.DownloadAppToOpenNebula, + dataCy: 'modal-export', + }, form: (rows) => { const app = rows?.map(({ original }) => original)[0] diff --git a/src/fireedge/src/client/components/Tables/MarketplaceApps/row.js b/src/fireedge/src/client/components/Tables/MarketplaceApps/row.js index 1c7e4d4dff..19300d950b 100644 --- a/src/fireedge/src/client/components/Tables/MarketplaceApps/row.js +++ b/src/fireedge/src/client/components/Tables/MarketplaceApps/row.js @@ -48,7 +48,7 @@ const Row = ({ original, value, ...props }) => { const timeAgo = `registered ${time.toRelative()}` return ( -
+
diff --git a/src/fireedge/src/client/constants/translates.js b/src/fireedge/src/client/constants/translates.js index 7ae685c3f3..12a0118bb8 100644 --- a/src/fireedge/src/client/constants/translates.js +++ b/src/fireedge/src/client/constants/translates.js @@ -580,6 +580,9 @@ module.exports = { Command: 'Command', Bus: 'BUS', /* VM Template schema - NUMA */ + NumaTopology: 'NUMA Topology', + NumaTopologyConcept: + 'These settings will help you to fine tune the performance of VMs', PinPolicy: 'Pin Policy', PinPolicyConcept: 'Virtual CPU pinning preference: %s', NumaSocketsConcept: 'Number of sockets or NUMA nodes', diff --git a/src/fireedge/src/client/features/OneApi/marketplaceApp.js b/src/fireedge/src/client/features/OneApi/marketplaceApp.js index 8d9ac74da1..729c825b31 100644 --- a/src/fireedge/src/client/features/OneApi/marketplaceApp.js +++ b/src/fireedge/src/client/features/OneApi/marketplaceApp.js @@ -347,7 +347,7 @@ const marketAppApi = oneApi.injectEndpoints({ * @returns {number} Marketplace app id * @throws Fails when response isn't code 200 */ - query: async (params) => { + query: (params) => { const name = ExtraActions.MARKETAPP_EXPORT const command = { name, ...ExtraCommands[name] }