Skip to content

Commit

Permalink
Bug 1852473 - kubevirt: fix importing VMs with same vnicIDs for ovirt…
Browse files Browse the repository at this point in the history
… provider

- don't allow Pod networks for such nics
- allow only same network values for nics with same vnicID
  • Loading branch information
suomiy committed Jul 1, 2020
1 parent c3de608 commit 3d95ac0
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as _ from 'lodash';
import { alignWithDNS1123 } from '@console/shared/src';
import { alignWithDNS1123, joinGrammaticallyListOfItems } from '@console/shared/src';
import { InternalActionType, UpdateOptions } from '../../../types';
import {
OvirtProviderField,
Expand Down Expand Up @@ -90,15 +90,25 @@ export const getDisks = (vm: OvirtVM, storageClassConfigMap: ConfigMapKind): VMW

export const getNics = (vm: OvirtVM): VMWizardNetwork[] => {
const getUniqueName = createUniqueNameResolver(vm.nics);
const nics = (vm.nics || []).filter((n) => n);
const nics = (vm.nics || []).filter(
(nic) => nic && nic.name && nic.vnicid != null && nic.vnicid !== '',
);

const nicProfileMapping = {};

return nics.map((nic, idx) => {
const results: VMWizardNetwork[] = nics.map((nic, idx) => {
const name = alignWithDNS1123(getUniqueName(nic.name) || nic.id);

const nicNames = nicProfileMapping[nic.vnicid] || [];
nicNames.push(name);
nicProfileMapping[nic.vnicid] = nicNames;

const networkWrapper = new NetworkWrapper().init({ name });

if (nics.length === 1) {
networkWrapper.setType(NetworkType.POD); // default to POD
}

return {
id: `${nic.id}-${idx + 1}`,
type: VMWizardNetworkType.V2V_OVIRT_IMPORT,
Expand Down Expand Up @@ -126,6 +136,21 @@ export const getNics = (vm: OvirtVM): VMWizardNetwork[] => {
},
};
});

results.forEach((wizardNetwork) => {
const networksWithSameVnicID = nicProfileMapping[wizardNetwork.importData.vnicID].filter(
(nicName) => nicName !== wizardNetwork.networkInterface.name,
);
if (networksWithSameVnicID.length > 0) {
wizardNetwork.importData.networksWithSameVnicID = networksWithSameVnicID;
wizardNetwork.editConfig.allowPodNetworkOverride = false;
wizardNetwork.editConfig.warning = `This network interface has to use the same network as ${joinGrammaticallyListOfItems(
networksWithSameVnicID,
)}`;
}
});

return results;
};

const getWorkload = (vm: OvirtVM) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
VMSettingsField,
VMWizardProps,
VMWizardTab,
VMWizardNetwork,
} from '../../../../types';
import { InternalActionType, UpdateOptions } from '../../../types';
import { iGetCommonData, iGetLoadedCommonData } from '../../../../selectors/immutable/selectors';
Expand Down Expand Up @@ -45,6 +46,8 @@ import { getLoadedVm } from '../../../../selectors/provider/selectors';
import { cleanupOvirtProvider } from './ovirt-cleanup';
import { iGetCreateVMWizardTabs } from '../../../../selectors/immutable/common';
import { prefillUpdateCreator } from './ovirt-prefill-vm';
import { iGetNetworks } from '../../../../selectors/immutable/networks';
import { NetworkWrapper } from '../../../../../../k8s/wrapper/vm/network-wrapper';

const startControllerAndCleanup = (options: UpdateOptions) => {
const { id, prevState, getState } = options;
Expand Down Expand Up @@ -396,6 +399,73 @@ const secretUpdater = (options) => {
}
};

const networksNicProfileDuplicatesUpdater = (options: UpdateOptions) => {
const { id, prevState, dispatch, getState } = options;
const state = getState();

if (!isOvirtProvider(state, id)) {
return;
}

const prevINetworks = iGetNetworks(prevState, id);
const iNetworks = iGetNetworks(state, id);

if (!iNetworks) {
return;
}

const changedInetworks = !prevINetworks
? iNetworks
: iNetworks.filter((iNetwork, iNetworkIdx) => iNetwork !== prevINetworks.get(iNetworkIdx));

const changedInetworksWithMultipleVNics = changedInetworks.filter((iNetwork) =>
iGetIn(iNetwork, ['importData', 'networksWithSameVnicID']),
);

if (changedInetworksWithMultipleVNics.size === 0) {
return;
}

const changedNetworksVnicIDLookup = changedInetworksWithMultipleVNics.reduce(
(lookup, iNetwork) => {
const vnicID = iGetIn(iNetwork, ['importData', 'vnicID']);
if (vnicID) {
lookup[vnicID] = iNetwork;
}
return lookup;
},
{},
);

const updatedNetworks = iNetworks
.map((iNetwork) => {
const wizardNetwork: VMWizardNetwork = toShallowJS(iNetwork);
const changedPeerIwizardNetwork =
changedNetworksVnicIDLookup[wizardNetwork?.importData?.vnicID];

if (changedPeerIwizardNetwork && iNetwork !== changedPeerIwizardNetwork) {
const networkWrapper = new NetworkWrapper(wizardNetwork.network, true);
const changedPeerNetworkWrapper = new NetworkWrapper(
toShallowJS(changedPeerIwizardNetwork.get('network')),
);

networkWrapper.setType(
changedPeerNetworkWrapper.getType(),
changedPeerNetworkWrapper.getTypeData(),
);

return {
...wizardNetwork,
network: networkWrapper.asResource(),
};
}
return wizardNetwork;
})
.toArray();

dispatch(vmWizardInternalActions[InternalActionType.SetNetworks](id, updatedNetworks));
};

export const getOvirtProviderStateUpdater = (options: UpdateOptions) =>
[
updateExtraWSQueries,
Expand All @@ -405,6 +475,7 @@ export const getOvirtProviderStateUpdater = (options: UpdateOptions) =>
vmOrClusterChangedUpdater,
providerUpdater,
secretUpdater,
networksNicProfileDuplicatesUpdater,
].forEach((updater) => {
updater && updater(options);
});
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ export type VMWizardNetwork = {
importData?: {
id?: string;
vnicID?: string;
networksWithSameVnicID?: [];
};
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import * as React from 'react';
import { Form, FormSelect, FormSelectOption, TextInput } from '@patternfly/react-core';
import {
Alert,
AlertVariant,
Form,
FormSelect,
FormSelectOption,
TextInput,
} from '@patternfly/react-core';
import {
FirehoseResult,
HandlePromiseProps,
Expand Down Expand Up @@ -210,6 +217,9 @@ export const NICModal = withHandlePromise((props: NICModalProps) => {
<ModalTitle>{isEditing ? EDIT : ADD} Network Interface</ModalTitle>
<ModalBody>
<Form>
{editConfig?.warning && (
<Alert variant={AlertVariant.warning} isInline title={editConfig?.warning} />
)}
<FormRow
title="Name"
fieldId={asId('name')}
Expand Down Expand Up @@ -253,7 +263,11 @@ export const NICModal = withHandlePromise((props: NICModalProps) => {
network={resultNetwork}
onChange={onNetworkChoiceChange}
nads={nads}
allowPodNetwork={allowPodNetwork}
allowPodNetwork={
editConfig?.allowPodNetworkOverride != null
? editConfig?.allowPodNetworkOverride
: allowPodNetwork
}
acceptEmptyValues={editConfig?.acceptEmptyValuesOverride?.network}
/>
<FormRow title="Type" fieldId={asId('type')} isRequired>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const getNetworkMappings = (networks: VMWizardNetwork[]) => {
({ network, importData }) =>
SUPPORTED_NETWORK_TYPES.has(new NetworkWrapper(network).getType()) && importData?.vnicID,
),
(wizardNetwork) => wizardNetwork.importData?.vnicID, // should be mapped 1 to 1
(wizardNetwork) => wizardNetwork.importData?.vnicID, // should be mapped 1 to 1 - UI makes sure it duplicates contain the same network (type and data)
);

return networksToMap.map(({ network, importData: { vnicID } }) => {
Expand Down
2 changes: 2 additions & 0 deletions frontend/packages/kubevirt-plugin/src/types/ui/nic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ export type UINetworkEditConfig = {
acceptEmptyValuesOverride?: {
network?: boolean;
};
allowPodNetworkOverride?: boolean;
warning?: string;
};

0 comments on commit 3d95ac0

Please sign in to comment.