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] }