1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-02-02 09:47:00 +03:00

M #-: Add switches to bridge and physical device (#3086)

on vnet and vnet templates 

Signed-off-by: David Carracedo <dcarracedo@opennebula.io>
This commit is contained in:
David 2024-05-30 12:59:14 +02:00 committed by GitHub
parent c53e48565a
commit c064adf99c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 141 additions and 17 deletions

View File

@ -59,16 +59,46 @@ const DRIVER_FIELD = {
notNull: true,
}
/** @type {Field} Bridge switch linux field */
const BRIDGE_SWITCH = {
name: 'bridgeSwitch',
label: T.BridgeSwitch,
tooltip: T.BridgeSwitchConcept,
type: INPUT_TYPES.SWITCH,
validation: boolean().default(() => false),
grid: { md: 12 },
}
/** @type {Field} Bridge linux field */
const BRIDGE_FIELD = {
name: 'BRIDGE',
label: T.Bridge,
tooltip: T.BridgeConcept,
dependOf: BRIDGE_SWITCH.name,
htmlType: (bridgeSwitch) => !bridgeSwitch && INPUT_TYPES.HIDDEN,
type: INPUT_TYPES.TEXT,
validation: string()
.trim()
.notRequired()
.default(() => undefined),
.default(() => undefined)
.when(BRIDGE_SWITCH.name, {
is: (bridgeSwitch) => bridgeSwitch,
then: (schema) => schema.required(),
}),
grid: { md: 6 },
}
/** @type {Field} Bridge switch linux field */
const PHYDEV_SWITCH = {
name: 'phyDevSwitch',
label: T.PhysicalDeviceSwitch,
tooltip: T.PhysicalDeviceSwitchConcept,
dependOf: DRIVER_FIELD.name,
htmlType: (driver) =>
[dot1Q, vxlan, openVSwitchVXLAN].includes(driver) && INPUT_TYPES.HIDDEN,
type: INPUT_TYPES.SWITCH,
validation: boolean().default(() => false),
grid: { md: 12 },
}
/** @type {Field} Physical device field */
@ -76,14 +106,22 @@ const PHYDEV_FIELD = {
name: 'PHYDEV',
label: T.PhysicalDevice,
tooltip: T.PhysicalDeviceConcept,
dependOf: [PHYDEV_SWITCH.name, DRIVER_FIELD.name],
htmlType: ([phyDevSwitch, driver] = []) =>
phyDevSwitch &&
![dot1Q, vxlan, openVSwitchVXLAN].includes(driver) &&
INPUT_TYPES.HIDDEN,
type: INPUT_TYPES.TEXT,
validation: string()
.trim()
.default(() => undefined)
.when(DRIVER_FIELD.name, {
is: (driver) => [dot1Q, vxlan, openVSwitchVXLAN].includes(driver),
.when([DRIVER_FIELD.name, PHYDEV_SWITCH.name], {
is: (driver, phyDevSwitch) =>
[dot1Q, vxlan, openVSwitchVXLAN].includes(driver) || !phyDevSwitch,
then: (schema) => schema.required(),
otherwise: (schema) => schema.notRequired(),
}),
grid: { md: 6 },
}
/** @type {Field} Filter MAC spoofing field */
@ -169,9 +207,12 @@ const VLAN_ID_FIELD = {
validation: string()
.trim()
.default(() => undefined)
.when(AUTOMATIC_VLAN_FIELD.name, {
is: (automatic) => !automatic,
.when([DRIVER_FIELD.name, AUTOMATIC_VLAN_FIELD.name], {
is: (driver, automatic) =>
[dot1Q, vxlan, ovswitch, openVSwitchVXLAN].includes(driver) &&
!automatic,
then: (schema) => schema.required(),
otherwise: (schema) => schema.notRequired(),
}),
grid: { sm: 6 },
}
@ -212,9 +253,11 @@ const OUTER_VLAN_ID_FIELD = {
validation: string()
.trim()
.default(() => undefined)
.when(AUTOMATIC_OUTER_VLAN_ID_FIELD.name, {
is: (oAutomatic) => !oAutomatic,
.when([DRIVER_FIELD.name, AUTOMATIC_OUTER_VLAN_ID_FIELD.name], {
is: (driver, oAutomatic) =>
[openVSwitchVXLAN].includes(driver) && !oAutomatic,
then: (schema) => schema.required(),
otherwise: (schema) => schema.notRequired(),
}),
grid: { sm: 6 },
}
@ -240,8 +283,12 @@ const FIELDS = (oneConfig, adminGroup) =>
disableFields(
[
DRIVER_FIELD,
BRIDGE_FIELD,
PHYDEV_SWITCH,
PHYDEV_FIELD,
BRIDGE_SWITCH,
BRIDGE_FIELD,
FILTER_MAC_SPOOFING_FIELD,
FILTER_IP_SPOOFING_FIELD,
AUTOMATIC_VLAN_FIELD,

View File

@ -17,6 +17,7 @@ import { array, object, ObjectSchema } from 'yup'
import { SCHEMA as CONTEXT_SCHEMA } from 'client/components/Forms/VNTemplate/CreateForm/Steps/ExtraConfiguration/context/schema'
import { SCHEMA as QOS_SCHEMA } from 'client/components/Forms/VNTemplate/CreateForm/Steps/ExtraConfiguration/qos/schema'
import { SCHEMA as CONFIGURATION_SCHEMA } from 'client/components/Forms/VNTemplate/CreateForm/Steps/ExtraConfiguration/configuration/schema'
/**
* Map name attribute if not exists.
@ -46,6 +47,7 @@ const AR_SCHEMA = object({
*/
export const SCHEMA = (isUpdate, oneConfig, adminGroup) => {
const schema = object({ SECURITY_GROUPS: array().ensure() })
.concat(CONFIGURATION_SCHEMA(oneConfig, adminGroup))
.concat(CONTEXT_SCHEMA(oneConfig, adminGroup))
.concat(QOS_SCHEMA(oneConfig, adminGroup))

View File

@ -59,10 +59,17 @@ export const getUnknownVars = (fromAttributes = {}, schema) => {
const Steps = createSteps([General, ExtraConfiguration], {
transformInitialValue: ({ TEMPLATE, ...vnet } = {}, schema) => {
const { AR = {}, DESCRIPTION = '' } = TEMPLATE
// Init switches of physical device and bridge
const phyDevSwitch = !TEMPLATE.PHYDEV
const bridgeSwitch = !!(
TEMPLATE.BRIDGE && !TEMPLATE.BRIDGE.startsWith('onebr')
)
const initialValue = schema.cast(
{
[GENERAL_ID]: { ...vnet, DESCRIPTION },
[EXTRA_ID]: { ...TEMPLATE, AR, ...vnet },
[EXTRA_ID]: { ...TEMPLATE, AR, ...vnet, phyDevSwitch, bridgeSwitch },
},
{ stripUnknown: true, context: vnet }
)
@ -78,6 +85,14 @@ const Steps = createSteps([General, ExtraConfiguration], {
const { [GENERAL_ID]: general = {}, [EXTRA_ID]: extra = {} } =
formData ?? {}
// Delete values of physical device and bridge depending of the value of their switches
extra.phyDevSwitch && delete extra.PHYDEV
!extra.bridgeSwitch && delete extra.BRIDGE
// Ensure that switches of physical device and bridge are not sent to the API
delete extra.phyDevSwitch
delete extra.bridgeSwitch
return jsonToXml({ ...extra, ...general })
},
})

View File

@ -27,16 +27,46 @@ const {
ovswitch_vxlan: openVSwitchVXLAN,
} = VN_DRIVERS
/** @type {Field} Bridge switch linux field */
const BRIDGE_SWITCH = {
name: 'bridgeSwitch',
label: T.BridgeSwitch,
tooltip: T.BridgeSwitchConcept,
type: INPUT_TYPES.SWITCH,
validation: boolean().default(() => false),
grid: { md: 12 },
}
/** @type {Field} Bridge linux field */
const BRIDGE_FIELD = {
name: 'BRIDGE',
label: T.Bridge,
tooltip: T.BridgeConcept,
dependOf: BRIDGE_SWITCH.name,
htmlType: (bridgeSwitch) => !bridgeSwitch && INPUT_TYPES.HIDDEN,
type: INPUT_TYPES.TEXT,
validation: string()
.trim()
.notRequired()
.default(() => undefined),
.default(() => undefined)
.when(BRIDGE_SWITCH.name, {
is: (bridgeSwitch) => bridgeSwitch,
then: (schema) => schema.required(),
}),
grid: { md: 6 },
}
/** @type {Field} Bridge switch linux field */
const PHYDEV_SWITCH = {
name: 'phyDevSwitch',
label: T.PhysicalDeviceSwitch,
tooltip: T.PhysicalDeviceSwitchConcept,
dependOf: DRIVER_FIELD.name,
htmlType: (driver) =>
[dot1Q, vxlan, openVSwitchVXLAN].includes(driver) && INPUT_TYPES.HIDDEN,
type: INPUT_TYPES.SWITCH,
validation: boolean().default(() => false),
grid: { md: 12 },
}
/** @type {Field} Physical device field */
@ -44,14 +74,22 @@ const PHYDEV_FIELD = {
name: 'PHYDEV',
label: T.PhysicalDevice,
tooltip: T.PhysicalDeviceConcept,
dependOf: [PHYDEV_SWITCH.name, DRIVER_FIELD.name],
htmlType: ([phyDevSwitch, driver] = []) =>
phyDevSwitch &&
![dot1Q, vxlan, openVSwitchVXLAN].includes(driver) &&
INPUT_TYPES.HIDDEN,
type: INPUT_TYPES.TEXT,
validation: string()
.trim()
.default(() => undefined)
.when(DRIVER_FIELD.name, {
is: (driver) => [dot1Q, vxlan, openVSwitchVXLAN].includes(driver),
.when([DRIVER_FIELD.name, PHYDEV_SWITCH.name], {
is: (driver, phyDevSwitch) =>
[dot1Q, vxlan, openVSwitchVXLAN].includes(driver) || !phyDevSwitch,
then: (schema) => schema.required(),
otherwise: (schema) => schema.notRequired(),
}),
grid: { md: 6 },
}
/** @type {Field} Filter MAC spoofing field */
@ -98,7 +136,7 @@ const AUTOMATIC_VLAN_FIELD = {
.yesOrNo()
.default(() => context?.AUTOMATIC_VLAN_ID === '1')
),
grid: (self) => (self ? { md: 12 } : { sm: 6 }),
grid: { md: 12 },
}
/** @type {Field} VLAN ID field */
@ -204,8 +242,10 @@ const VXLAN_MC_FIELD = {
/** @type {Field[]} List of common fields */
export const FIELDS = [
BRIDGE_FIELD,
PHYDEV_SWITCH,
PHYDEV_FIELD,
BRIDGE_SWITCH,
BRIDGE_FIELD,
FILTER_MAC_SPOOFING_FIELD,
FILTER_IP_SPOOFING_FIELD,

View File

@ -58,9 +58,13 @@ export const getUnknownVars = (fromAttributes = {}, schema) => {
const Steps = createSteps([General, ExtraConfiguration], {
transformInitialValue: ({ TEMPLATE, AR_POOL, ...vnet } = {}, schema) => {
// Init switches of physical device and bridge
const phyDevSwitch = !vnet.PHYDEV
const bridgeSwitch = !!(vnet.BRIDGE && !vnet.BRIDGE.startsWith('onebr'))
const initialValue = schema.cast(
{
[GENERAL_ID]: { ...vnet },
[GENERAL_ID]: { ...vnet, phyDevSwitch, bridgeSwitch },
[EXTRA_ID]: { ...TEMPLATE, AR: AR_POOL.AR, ...vnet },
},
{ stripUnknown: true, context: vnet }
@ -77,6 +81,14 @@ const Steps = createSteps([General, ExtraConfiguration], {
const { [GENERAL_ID]: general = {}, [EXTRA_ID]: extra = {} } =
formData ?? {}
// Delete values of physical device and bridge depending of the value of their switches
general.phyDevSwitch && delete general.PHYDEV
!general.bridgeSwitch && delete general.BRIDGE
// Ensure that switches of physical device and bridge are not sent to the API
delete general.phyDevSwitch
delete general.bridgeSwitch
return jsonToXml({ ...extra, ...general })
},
})

View File

@ -1431,9 +1431,17 @@ module.exports = {
/* Virtual Network schema - driver configuration */
NetworkMode: 'Network mode',
Bridge: 'Bridge',
BridgeConcept: 'Name of the physical bridge in the nodes to attach VM NICs',
BridgeConcept:
'This lets you specify the name of the bridge to be created in the hosts.',
BridgeSwitch: 'Custom name for bridge',
BridgeSwitchConcept:
'If enabled, you have to define the name of the bridge. Otherwise, OpenNebula will create the name of the bridge with the "onebr" prefix.',
PhysicalDevice: 'Physical device',
PhysicalDeviceConcept: 'Node NIC to send/receive virtual network traffic',
PhysicalDeviceConcept:
'Device name of the physical network card in the host to route traffic to. Example: eth0',
PhysicalDeviceSwitch: 'Use only private host networking',
PhysicalDeviceSwitchConcept:
'If enabled, the Virtual Network will not connect to any physical device and hence the Virtual Machines will be able to communicate only with other Virtual Machines in the same virtual network and in the same host.',
MacSpoofingFilter: ' MAC spoofing filter',
IpSpoofingFilter: ' IP spoofing filter',
MTU: 'MTU of the interface',