diff --git a/src/utils/resources/vm/utils/constants.ts b/src/utils/resources/vm/utils/constants.ts index deb24439a..13934fef6 100644 --- a/src/utils/resources/vm/utils/constants.ts +++ b/src/utils/resources/vm/utils/constants.ts @@ -31,3 +31,5 @@ export const MIGRATION__PROMETHEUS_DELAY = 15 * MILLISECONDS_TO_SECONDS_MULTIPLI export const DEFAULT_NETWORK_INTERFACE: V1Interface = { masquerade: {}, name: 'default' }; export const DEFAULT_NETWORK: V1Network = { name: 'default', pod: {} }; + +export const UDN_BINDING_NAME = 'l2bridge'; diff --git a/src/views/catalog/CreateFromInstanceTypes/components/CreateVMFooter/CreateVMFooter.tsx b/src/views/catalog/CreateFromInstanceTypes/components/CreateVMFooter/CreateVMFooter.tsx index 4cbe19c9b..28bfe158e 100644 --- a/src/views/catalog/CreateFromInstanceTypes/components/CreateVMFooter/CreateVMFooter.tsx +++ b/src/views/catalog/CreateFromInstanceTypes/components/CreateVMFooter/CreateVMFooter.tsx @@ -18,6 +18,7 @@ import { generateNewSysprepConfig, UNATTEND, } from '@kubevirt-utils/components/SysprepModal/sysprep-utils'; +import { DEFAULT_NAMESPACE } from '@kubevirt-utils/constants/constants'; import { VirtualMachineDetailsTab } from '@kubevirt-utils/constants/tabs-constants'; import { logITFlowEvent } from '@kubevirt-utils/extensions/telemetry/telemetry'; import { @@ -28,11 +29,13 @@ import { CUSTOMIZE_VM_BUTTON_CLICKED, VIEW_YAML_AND_CLI_CLICKED, } from '@kubevirt-utils/extensions/telemetry/utils/constants'; +import { ALL_NAMESPACES_SESSION_KEY } from '@kubevirt-utils/hooks/constants'; import { useFeatures } from '@kubevirt-utils/hooks/useFeatures/useFeatures'; import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation'; import useKubevirtUserSettings from '@kubevirt-utils/hooks/useKubevirtUserSettings/useKubevirtUserSettings'; import useRHELAutomaticSubscription from '@kubevirt-utils/hooks/useRHELAutomaticSubscription/useRHELAutomaticSubscription'; import { getResourceUrl } from '@kubevirt-utils/resources/shared'; +import useNamespaceUDN from '@kubevirt-utils/resources/udn/hooks/useNamespaceUDN'; import { vmSignal } from '@kubevirt-utils/store/customizeInstanceType'; import { createHeadlessService } from '@kubevirt-utils/utils/headless-service'; import { isEmpty } from '@kubevirt-utils/utils/utils'; @@ -68,6 +71,10 @@ const CreateVMFooter: FC = () => { const { subscriptionData } = useRHELAutomaticSubscription(); const [activeNamespace] = useActiveNamespace(); + const [isNamespaceManagedByUDN] = useNamespaceUDN( + activeNamespace === ALL_NAMESPACES_SESSION_KEY ? DEFAULT_NAMESPACE : activeNamespace, + ); + const { instanceTypeVMState, setStartVM, setVM, startVM, vmNamespaceTarget } = useInstanceTypeVMStore(); const { @@ -107,6 +114,7 @@ const CreateVMFooter: FC = () => { startVM, subscriptionData, targetNamespace: vmNamespaceTarget, + withUDN: isNamespaceManagedByUDN, }); logITFlowEvent(CREATE_VM_BUTTON_CLICKED, vmToCreate); @@ -170,6 +178,7 @@ const CreateVMFooter: FC = () => { startVM, subscriptionData, targetNamespace: vmNamespaceTarget, + withUDN: isNamespaceManagedByUDN, }), ); vmSignal.value = generateVM({ @@ -178,6 +187,7 @@ const CreateVMFooter: FC = () => { startVM, subscriptionData, targetNamespace: vmNamespaceTarget, + withUDN: isNamespaceManagedByUDN, }); logITFlowEvent(CUSTOMIZE_VM_BUTTON_CLICKED, vmSignal.value); @@ -266,6 +276,7 @@ const CreateVMFooter: FC = () => { startVM, subscriptionData, targetNamespace: vmNamespaceTarget, + withUDN: isNamespaceManagedByUDN, })} {...props} /> diff --git a/src/views/catalog/CreateFromInstanceTypes/utils/utils.ts b/src/views/catalog/CreateFromInstanceTypes/utils/utils.ts index 391b3d7a9..54e6b752d 100644 --- a/src/views/catalog/CreateFromInstanceTypes/utils/utils.ts +++ b/src/views/catalog/CreateFromInstanceTypes/utils/utils.ts @@ -3,7 +3,7 @@ import produce from 'immer'; import DataSourceModel from '@kubevirt-ui/kubevirt-api/console/models/DataSourceModel'; import VirtualMachineInstancetypeModel from '@kubevirt-ui/kubevirt-api/console/models/VirtualMachineInstancetypeModel'; import VirtualMachineModel from '@kubevirt-ui/kubevirt-api/console/models/VirtualMachineModel'; -import { V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt'; +import { V1Interface, V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt'; import { addDNFUpdateToRunCMD, addSubscriptionManagerToRunCMD, @@ -27,6 +27,7 @@ import { OS_NAME_TYPES, OS_NAME_TYPES_NOT_SUPPORTED } from '@kubevirt-utils/reso import { DEFAULT_NETWORK, DEFAULT_NETWORK_INTERFACE, + UDN_BINDING_NAME, } from '@kubevirt-utils/resources/vm/utils/constants'; import { OS_WINDOWS_PREFIX } from '@kubevirt-utils/resources/vm/utils/operation-system/operationSystem'; import { @@ -95,6 +96,7 @@ type GenerateVMArgs = { startVM: boolean; subscriptionData: RHELAutomaticSubscriptionData; targetNamespace: string; + withUDN: boolean; }; type GenerateVMCallback = (props: GenerateVMArgs) => V1VirtualMachine; @@ -104,6 +106,7 @@ export const generateVM: GenerateVMCallback = ({ startVM, subscriptionData, targetNamespace, + withUDN, }) => { const { folder, @@ -130,6 +133,10 @@ export const generateVM: GenerateVMCallback = ({ const storageClassName = instanceTypeState.selectedStorageClass || pvcSource?.spec?.storageClassName; + const defaultInterface = withUDN + ? ({ binding: { name: UDN_BINDING_NAME }, name: DEFAULT_NETWORK_INTERFACE.name } as V1Interface) + : DEFAULT_NETWORK_INTERFACE; + let emptyVM: V1VirtualMachine = { apiVersion: `${VirtualMachineModel.apiGroup}/${VirtualMachineModel.apiVersion}`, kind: VirtualMachineModel.kind, @@ -191,7 +198,7 @@ export const generateVM: GenerateVMCallback = ({ devices: { autoattachPodInterface: false, disks: [], - interfaces: [DEFAULT_NETWORK_INTERFACE], + interfaces: [defaultInterface], }, }, networks: [DEFAULT_NETWORK], diff --git a/src/views/catalog/templatescatalog/components/TemplatesCatalogDrawer/hooks/useCreateDrawerForm.tsx b/src/views/catalog/templatescatalog/components/TemplatesCatalogDrawer/hooks/useCreateDrawerForm.tsx index 2eef20029..37de0dd0f 100644 --- a/src/views/catalog/templatescatalog/components/TemplatesCatalogDrawer/hooks/useCreateDrawerForm.tsx +++ b/src/views/catalog/templatescatalog/components/TemplatesCatalogDrawer/hooks/useCreateDrawerForm.tsx @@ -46,7 +46,12 @@ import { LABEL_USED_TEMPLATE_NAME, LABEL_USED_TEMPLATE_NAMESPACE, } from '@kubevirt-utils/resources/template'; -import { getMemoryCPU } from '@kubevirt-utils/resources/vm'; +import useNamespaceUDN from '@kubevirt-utils/resources/udn/hooks/useNamespaceUDN'; +import { getInterfaces, getMemoryCPU } from '@kubevirt-utils/resources/vm'; +import { + DEFAULT_NETWORK_INTERFACE, + UDN_BINDING_NAME, +} from '@kubevirt-utils/resources/vm/utils/constants'; import { HEADLESS_SERVICE_LABEL, HEADLESS_SERVICE_NAME, @@ -67,6 +72,8 @@ const useCreateDrawerForm = ( authorizedSSHKey: string, ) => { const { updateTabsData, updateVM } = useWizardVMContext(); + + const [useUDN] = useNamespaceUDN(namespace); const [authorizedSSHKeys, updateAuthorizedSSHKeys] = useKubevirtUserSettings('ssh'); const { featureEnabled: autoUpdateEnabled } = useFeatures(AUTOMATIC_UPDATE_FEATURE_NAME); const { featureEnabled: isDisabledGuestSystemLogs } = useFeatures( @@ -175,6 +182,7 @@ const useCreateDrawerForm = ( name: nameField, namespace, subscriptionData, + useUDN, }, template: templateToProcess, uploadData: (processedTemplate) => @@ -253,6 +261,15 @@ const useCreateDrawerForm = ( vmDraft.spec.template.spec.volumes = isRHELTemplate(processedTemplate) ? updateCloudInitRHELSubscription(updatedVolumes, subscriptionData, autoUpdateEnabled) : updatedVolumes; + + const defaultInterface = getInterfaces(vmDraft)?.find( + (iface) => iface.name === DEFAULT_NETWORK_INTERFACE.name, + ); + + if (useUDN && defaultInterface) { + delete defaultInterface.masquerade; + defaultInterface.binding = { name: UDN_BINDING_NAME }; + } }); updateTabsData((tabsDataDraft) => { diff --git a/src/views/catalog/utils/quick-create-vm.ts b/src/views/catalog/utils/quick-create-vm.ts index 53e647877..aafe7f60a 100644 --- a/src/views/catalog/utils/quick-create-vm.ts +++ b/src/views/catalog/utils/quick-create-vm.ts @@ -12,6 +12,11 @@ import { LABEL_USED_TEMPLATE_NAMESPACE, replaceTemplateVM, } from '@kubevirt-utils/resources/template'; +import { getInterfaces } from '@kubevirt-utils/resources/vm'; +import { + DEFAULT_NETWORK_INTERFACE, + UDN_BINDING_NAME, +} from '@kubevirt-utils/resources/vm/utils/constants'; import { createHeadlessService } from '@kubevirt-utils/utils/headless-service'; import { k8sCreate, K8sModel } from '@openshift-console/dynamic-plugin-sdk'; @@ -25,6 +30,7 @@ type QuickCreateVMType = (inputs: { name: string; namespace: string; subscriptionData: RHELAutomaticSubscriptionData; + useUDN?: boolean; }; template: V1Template; uploadData: (processedTemplate: V1Template) => Promise; @@ -38,6 +44,7 @@ export const quickCreateVM: QuickCreateVMType = async ({ name, namespace = DEFAULT_NAMESPACE, subscriptionData, + useUDN, }, template, uploadData, @@ -72,6 +79,15 @@ export const quickCreateVM: QuickCreateVMType = async ({ draftVM.spec.template.spec.volumes = isRHELTemplate(processedTemplate) ? updateCloudInitRHELSubscription(updatedVolumes, subscriptionData, autoUpdateEnabled) : updatedVolumes; + + const defaultInterface = getInterfaces(draftVM)?.find( + (iface) => iface.name === DEFAULT_NETWORK_INTERFACE.name, + ); + + if (useUDN && defaultInterface) { + delete defaultInterface.masquerade; + defaultInterface.binding = { name: UDN_BINDING_NAME }; + } }); const { objects } = replaceTemplateVM(processedTemplate, overridedVM);