From 41dc1cdb109960fc52b4ea73fb6bc2005650edfc Mon Sep 17 00:00:00 2001 From: Jeff Puzzo Date: Tue, 11 Feb 2025 10:32:16 -0500 Subject: [PATCH] [MTV-2052] Plan create wizard - auto calculated mapping for a plan is not displayed in 2nd step page anymore Signed-off-by: Jeff Puzzo --- .../views/migrate/reducer/actions.ts | 33 +++++++++ .../views/migrate/reducer/reducer.ts | 74 ++++++++++++++++++- .../views/migrate/useFetchEffects.ts | 42 ++++++++--- 3 files changed, 136 insertions(+), 13 deletions(-) diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/migrate/reducer/actions.ts b/packages/forklift-console-plugin/src/modules/Providers/views/migrate/reducer/actions.ts index 8cf37f852..d3c67485c 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/views/migrate/reducer/actions.ts +++ b/packages/forklift-console-plugin/src/modules/Providers/views/migrate/reducer/actions.ts @@ -24,6 +24,8 @@ export const DEFAULT_NAMESPACE = 'default'; // action type names export const SET_NAME = 'SET_NAME'; export const SET_PROJECT_NAME = 'SET_PROJECT_NAME'; +export const SET_SOURCE_PROVIDER = 'SET_SOURCE_PROVIDER'; +export const SET_SELECTED_VMS = 'SET_SELECTED_VMS'; export const SET_DESCRIPTION = 'SET_DESCRIPTION'; export const SET_TARGET_PROVIDER = 'SET_TARGET_PROVIDER'; export const SET_TARGET_NAMESPACE = 'SET_TARGET_NAMESPACE'; @@ -52,6 +54,8 @@ export const INIT = 'INIT'; export type CreateVmMigration = | typeof SET_NAME | typeof SET_PROJECT_NAME + | typeof SET_SOURCE_PROVIDER + | typeof SET_SELECTED_VMS | typeof SET_DESCRIPTION | typeof SET_TARGET_PROVIDER | typeof SET_TARGET_NAMESPACE @@ -92,6 +96,15 @@ export interface ProjectName { name: string; } +export type SourceProvider = { + sourceProvider: V1beta1Provider; +}; + +export type SelectedVms = { + vms: VmData[]; + sourceProvider: V1beta1Provider; +}; + export interface PlanDescription { description: string; } @@ -220,6 +233,26 @@ export const setProjectName = (name: string): PageAction => ({ + type: 'SET_SOURCE_PROVIDER', + payload: { + sourceProvider, + }, +}); + +export const setSelectedVms = ( + vms: VmData[], + sourceProvider: V1beta1Provider, +): PageAction => ({ + type: 'SET_SELECTED_VMS', + payload: { + vms, + sourceProvider, + }, +}); + export const setAvailableProviders = ( availableProviders: V1beta1Provider[], loaded?: boolean, diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/migrate/reducer/reducer.ts b/packages/forklift-console-plugin/src/modules/Providers/views/migrate/reducer/reducer.ts index 678c1dba8..9e51ef22e 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/views/migrate/reducer/reducer.ts +++ b/packages/forklift-console-plugin/src/modules/Providers/views/migrate/reducer/reducer.ts @@ -1,8 +1,16 @@ import { Draft } from 'immer'; import { isProviderLocalOpenshift } from 'src/utils/resources'; +import { ProviderType } from '@kubev2v/types'; + import { getIsTarget } from '../../../utils'; -import { CreateVmMigrationPageState, Mapping, MULTIPLE_NICS_ON_THE_SAME_NETWORK } from '../types'; +import { toId } from '../../details'; +import { + CreateVmMigrationPageState, + Mapping, + MULTIPLE_NICS_ON_THE_SAME_NETWORK, + OVIRT_NICS_WITH_EMPTY_PROFILE, +} from '../types'; import { ADD_NETWORK_MAPPING, @@ -31,9 +39,11 @@ import { PlanTargetNamespace, PlanTargetProvider, POD_NETWORK, + ProjectName, REMOVE_ALERT, REPLACE_NETWORK_MAPPING, REPLACE_STORAGE_MAPPING, + SelectedVms, SET_API_ERROR, SET_AVAILABLE_PROVIDERS, SET_AVAILABLE_SOURCE_NETWORKS, @@ -48,22 +58,29 @@ import { SET_NAME, SET_NICK_PROFILES, SET_PROJECT_NAME, + SET_SELECTED_VMS, + SET_SOURCE_PROVIDER, SET_TARGET_NAMESPACE, SET_TARGET_PROVIDER, + SourceProvider, START_CREATE, } from './actions'; import { addMapping, deleteMapping, replaceMapping } from './changeMapping'; import { createInitialState, InitialStateParameters } from './createInitialState'; +import { getNamespacesUsedBySelectedVms } from './getNamespacesUsedBySelectedVms'; import { getNetworksUsedBySelectedVms } from './getNetworksUsedBySelectedVMs'; import { getStoragesUsedBySelectedVms } from './getStoragesUsedBySelectedVMs'; import { hasMultipleNicsOnTheSameNetwork } from './hasMultipleNicsOnTheSameNetwork'; +import { hasNicWithEmptyProfile } from './hasNicWithEmptyProfile'; import { addIfMissing, alreadyInUseBySelectedVms, executeNetworkMappingValidation, executeStorageMappingValidation, + getObjectRef, recalculateNetworks, recalculateStorages, + resourceFieldsForType, reTestNetworks, reTestStorages, setTargetNamespace, @@ -83,7 +100,7 @@ const handlers: { draft.underConstruction.plan.metadata.name = name; draft.validation.planName = validatePlanName(name, draft.existingResources.plans); }, - [SET_PROJECT_NAME](draft, { payload: { name } }: PageAction) { + [SET_PROJECT_NAME](draft, { payload: { name } }: PageAction) { draft.underConstruction.projectName = name; draft.validation.projectName = name ? 'success' : 'error'; }, @@ -471,6 +488,59 @@ const handlers: { } }); }, + [SET_SOURCE_PROVIDER]( + draft, + { payload: { sourceProvider } }: PageAction, + ) { + const sourceProviderRef = getObjectRef(sourceProvider); + const sourceProviderGenName = `${sourceProvider.metadata.name}-`; + + draft.underConstruction.plan.spec.provider.source = sourceProviderRef; + draft.underConstruction.netMap.spec.provider.source = sourceProviderRef; + draft.underConstruction.storageMap.spec.provider.source = sourceProviderRef; + + draft.underConstruction.netMap.metadata.generateName = sourceProviderGenName; + draft.underConstruction.storageMap.metadata.generateName = sourceProviderGenName; + + draft.receivedAsParams.sourceProvider = sourceProvider; + draft.calculatedOnce.vmFieldsFactory = resourceFieldsForType( + sourceProvider?.spec?.type as ProviderType, + ); + draft.flow.initialLoading = { + [SET_DISKS]: !['ovirt', 'openstack'].includes(sourceProvider.spec?.type), + [SET_NICK_PROFILES]: sourceProvider.spec?.type !== 'ovirt', + }; + }, + [SET_SELECTED_VMS]( + draft, + { payload: { vms, sourceProvider } }: PageAction, + ) { + const hasVmNicWithEmptyProfile = hasNicWithEmptyProfile(sourceProvider, vms); + + draft.underConstruction.plan.spec.vms = vms.map((data) => ({ + name: data.name, + namespace: data.namespace, + id: toId(data), + })); + + draft.receivedAsParams.selectedVms = vms; + draft.validation.networkMappings = hasVmNicWithEmptyProfile ? 'error' : 'default'; + draft.alerts.networkMappings = { + errors: hasVmNicWithEmptyProfile ? [OVIRT_NICS_WITH_EMPTY_PROFILE] : [], + warnings: hasMultipleNicsOnTheSameNetwork(vms) ? [MULTIPLE_NICS_ON_THE_SAME_NETWORK] : [], + }; + + draft.calculatedOnce = { + ...draft.calculatedOnce, + networkIdsUsedBySelectedVms: + sourceProvider.spec?.type !== 'ovirt' ? getNetworksUsedBySelectedVms(vms, []) : [], + storageIdsUsedBySelectedVms: ['ovirt', 'openstack'].includes(sourceProvider.spec?.type) + ? [] + : getStoragesUsedBySelectedVms({}, vms, []), + namespacesUsedBySelectedVms: + sourceProvider.spec?.type === 'openshift' ? getNamespacesUsedBySelectedVms(vms) : [], + }; + }, [INIT]( draft, { diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/migrate/useFetchEffects.ts b/packages/forklift-console-plugin/src/modules/Providers/views/migrate/useFetchEffects.ts index 52b4d6812..24cc27723 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/views/migrate/useFetchEffects.ts +++ b/packages/forklift-console-plugin/src/modules/Providers/views/migrate/useFetchEffects.ts @@ -35,6 +35,8 @@ import { setExistingPlans, setExistingStorageMaps, setNicProfiles, + setSelectedVms, + setSourceProvider, } from './reducer/actions'; import { createInitialState } from './reducer/createInitialState'; import { reducer } from './reducer/reducer'; @@ -85,6 +87,18 @@ export const useFetchEffects = ( [], ); + useEffect(() => { + if (!editingDone && selectedVms?.length) { + dispatch(setSelectedVms(selectedVms, sourceProvider)); + } + }, [editingDone, selectedVms, sourceProvider]); + + useEffect(() => { + if (!editingDone && sourceProvider) { + dispatch(setSourceProvider(sourceProvider)); + } + }, [editingDone, sourceProvider]); + const [providers, providersLoaded, providerError] = useK8sWatchResource({ groupVersionKind: ProviderModelGroupVersionKind, namespaced: true, @@ -95,7 +109,7 @@ export const useFetchEffects = ( () => !editingDone && dispatchWithFallback(setAvailableProviders(providers), !providersLoaded, providerError), - [editingDone, providersLoaded, providerError?.message], + [editingDone, providersLoaded, providerError?.message, selectedVms], ); const [plans, plansLoaded, plansError] = useK8sWatchResource({ @@ -106,7 +120,7 @@ export const useFetchEffects = ( }); useEffect( () => !editingDone && dispatchWithFallback(setExistingPlans(plans), !plansLoaded, plansError), - [editingDone, plansLoaded, plansError?.message], + [editingDone, plansLoaded, plansError?.message, selectedVms], ); const [netMaps, netMapsLoaded, netMapsError] = useK8sWatchResource({ @@ -119,7 +133,7 @@ export const useFetchEffects = ( () => !editingDone && dispatchWithFallback(setExistingNetMaps(netMaps), !netMapsLoaded, netMapsError), - [editingDone, netMapsLoaded, netMapsError?.message], + [editingDone, netMapsLoaded, netMapsError?.message, selectedVms], ); const [stMaps, stMapsLoaded, stMapsError] = useK8sWatchResource({ @@ -132,7 +146,7 @@ export const useFetchEffects = ( () => !editingDone && dispatchWithFallback(setExistingStorageMaps(stMaps), !stMapsLoaded, stMapsError), - [editingDone, stMapsLoaded, stMapsError?.message], + [editingDone, stMapsLoaded, stMapsError?.message, selectedVms], ); const [namespaces, nsLoading, nsError] = useNamespaces(targetProvider); @@ -141,7 +155,7 @@ export const useFetchEffects = ( targetProviderName && !editingDone && dispatchWithFallback(setAvailableTargetNamespaces(namespaces), nsLoading, nsError), - [editingDone, nsLoading, nsError?.message, targetProviderName], + [editingDone, nsLoading, nsError?.message, targetProviderName, selectedVms], ); const [targetNetworks, targetNetworksLoading, targetNetworksError] = @@ -155,7 +169,13 @@ export const useFetchEffects = ( targetNetworksLoading, targetNetworksError, ), - [editingDone, targetNetworksLoading, targetNetworksError?.message, targetProviderName], + [ + editingDone, + targetNetworksLoading, + targetNetworksError?.message, + targetProviderName, + selectedVms, + ], ); const [sourceStorages, sourceStoragesLoading, sourceStoragesError] = @@ -168,7 +188,7 @@ export const useFetchEffects = ( sourceStoragesLoading, sourceStoragesError, ), - [editingDone, sourceStoragesLoading, sourceStoragesError?.message], + [editingDone, sourceStoragesLoading, sourceStoragesError?.message, selectedVms], ); const [targetStorages, targetStoragesLoading, targetStoragesError] = @@ -182,7 +202,7 @@ export const useFetchEffects = ( targetStoragesLoading, targetStoragesError, ), - [editingDone, targetStoragesLoading, targetProviderName], + [editingDone, targetStoragesLoading, targetProviderName, selectedVms], ); const [sourceNetworks, sourceNetworksLoading, sourceNetworksError] = @@ -195,7 +215,7 @@ export const useFetchEffects = ( sourceNetworksLoading, sourceNetworksError, ), - [editingDone, sourceNetworksLoading, sourceNetworksError?.message], + [editingDone, sourceNetworksLoading, sourceNetworksError?.message, selectedVms], ); const [nicProfiles, nicProfilesLoading, nicProfilesError] = useNicProfiles(sourceProvider); @@ -203,13 +223,13 @@ export const useFetchEffects = ( () => !editingDone && dispatchWithFallback(setNicProfiles(nicProfiles), nicProfilesLoading, nicProfilesError), - [editingDone, nicProfilesLoading, nicProfilesError?.message], + [editingDone, nicProfilesLoading, nicProfilesError?.message, selectedVms], ); const [disks, disksLoading, disksError] = useDisks(sourceProvider); useEffect( () => !editingDone && dispatchWithFallback(setDisks(disks), disksLoading, disksError), - [editingDone, disksLoading, disksError?.message], + [editingDone, disksLoading, disksError?.message, selectedVms], ); return [state, dispatch, emptyContext];