Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const CreateVMWizardFooterComponent: React.FC<CreateVMWizardFooterComponentProps
const isLastStep = activeStepID === VMWizardTab.RESULT;

const isNextButtonDisabled = isLocked;
const isReviewButtonDisabled = isLocked;
const isBackButtonDisabled = isFirstStep || isLocked;

return (
Expand Down Expand Up @@ -85,6 +86,7 @@ const CreateVMWizardFooterComponent: React.FC<CreateVMWizardFooterComponentProps
{!isFinishingStep && (
<Button
variant={ButtonVariant.secondary}
isDisabled={isReviewButtonDisabled}
onClick={() => {
const jumpToStepID =
(isValid &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,15 @@ import {
} from '../../utils/immutable';
import { getTemplateOperatingSystems } from '../../selectors/vm-template/advanced';
import { ResultsWrapper } from '../../k8s/enhancedK8sMethods/types';
import { NetworkWrapper } from '../../k8s/wrapper/vm/network-wrapper';
import { NetworkInterfaceWrapper } from '../../k8s/wrapper/vm/network-interface-wrapper';
import {
ChangedCommonData,
CommonData,
CreateVMWizardComponentProps,
DetectCommonDataChanges,
VMSettingsField,
VMWizardNetwork,
VMWizardProps,
VMWizardTab,
} from './types';
Expand All @@ -47,14 +50,55 @@ import { vmWizardActions } from './redux/actions';
import { ActionType } from './redux/types';
import { iGetCommonData, iGetCreateVMWizardTabs } from './selectors/immutable/selectors';
import { isStepLocked, isStepPending, isStepValid } from './selectors/immutable/wizard-selectors';
import { VMSettingsTab } from './tabs/vm-settings-tab/vm-settings-tab';
import { ResourceLoadErrors } from './resource-load-errors';
import { CreateVMWizardFooter } from './create-vm-wizard-footer';
import { VMSettingsTab } from './tabs/vm-settings-tab/vm-settings-tab';
import { NetworkingTab } from './tabs/networking-tab/networking-tab';
import { ReviewTab } from './tabs/review-tab/review-tab';
import { ResultTab } from './tabs/result-tab/result-tab';

import './create-vm-wizard.scss';

// TODO remove after moving create functions from kubevirt-web-ui-components
/** *
* kubevirt-web-ui-components InterOP
*/
const kubevirtInterOP = ({ activeNamespace, vmSettings, networks, storages, templates }) => {
const clonedVMsettings = _.cloneDeep(vmSettings);
const clonedNetworks = _.cloneDeep(networks);
const clonedStorages = _.cloneDeep(storages);

clonedVMsettings.namespace = { value: activeNamespace };
const operatingSystems = getTemplateOperatingSystems(templates);
const osField = clonedVMsettings[VMSettingsField.OPERATING_SYSTEM];
const osID = osField.value;
osField.value = operatingSystems.find(({ id }) => id === osID);

const interOPNetworks = clonedNetworks.map(({ networkInterface, network }) => {
const networkInterfaceWrapper = NetworkInterfaceWrapper.initialize(networkInterface);
const networkWrapper = NetworkWrapper.initialize(network);

return {
name: networkInterfaceWrapper.getName(),
mac: networkInterfaceWrapper.getMACAddress(),
binding: networkInterfaceWrapper.getTypeValue(),
isBootable: networkInterfaceWrapper.isFirstBootableDevice(),
network: networkWrapper.getReadableName(),
networkType: networkWrapper.getTypeValue(),
templateNetwork: {
network,
interface: networkInterface,
},
};
});

return {
interOPVMSettings: clonedVMsettings,
interOPNetworks,
interOPStorages: clonedStorages,
};
};

export class CreateVMWizardComponent extends React.Component<CreateVMWizardComponentProps> {
private isClosed = false;

Expand Down Expand Up @@ -93,32 +137,33 @@ export class CreateVMWizardComponent extends React.Component<CreateVMWizardCompo

const enhancedK8sMethods = new EnhancedK8sMethods();
const vmSettings = iGetIn(this.props.stepData, [VMWizardTab.VM_SETTINGS, 'value']).toJS();
const networks = immutableListToShallowJS<VMWizardNetwork>(
iGetIn(this.props.stepData, [VMWizardTab.NETWORKING, 'value']),
);
const storages = immutableListToShallowJS(
iGetIn(this.props.stepData, [VMWizardTab.STORAGE, 'value']),
);
const templates = immutableListToShallowJS(
concatImmutableLists(
iGetLoadedData(this.props[VMWizardProps.commonTemplates]),
iGetLoadedData(this.props[VMWizardProps.userTemplates]),
),
);

// TODO remove after moving create functions from kubevirt-web-ui-components
/** *
* BEGIN kubevirt-web-ui-components InterOP
*/
vmSettings.namespace = { value: this.props.activeNamespace };
const operatingSystems = getTemplateOperatingSystems(templates);
const osField = vmSettings[VMSettingsField.OPERATING_SYSTEM];
const osID = osField.value;
osField.value = operatingSystems.find(({ id }) => id === osID);
/**
* END kubevirt-web-ui-components InterOP
*/
const { interOPVMSettings, interOPNetworks, interOPStorages } = kubevirtInterOP({
vmSettings,
networks,
storages,
templates,
activeNamespace: this.props.activeNamespace,
});

create(
enhancedK8sMethods,
templates,
vmSettings,
iGetIn(this.props.stepData, [VMWizardTab.NETWORKS, 'value']).toJS(),
iGetIn(this.props.stepData, [VMWizardTab.STORAGE, 'value']).toJS(),
interOPVMSettings,
interOPNetworks,
interOPStorages,
immutableListToShallowJS(iGetLoadedData(this.props[VMWizardProps.persistentVolumeClaims])),
units,
)
Expand Down Expand Up @@ -148,9 +193,15 @@ export class CreateVMWizardComponent extends React.Component<CreateVMWizardCompo
</>
),
},
// {
// id: VMWizardTab.NETWORKS,
// },
{
id: VMWizardTab.NETWORKING,
component: (
<>
<ResourceLoadErrors wizardReduxID={reduxID} />
<NetworkingTab wizardReduxID={reduxID} />
</>
),
},
// {
// id: VMWizardTab.STORAGE,
// },
Expand Down Expand Up @@ -276,7 +327,7 @@ export const CreateVMWizardPageComponent: React.FC<CreateVMWizardPageComponentPr
}),
getResource(NetworkAttachmentDefinitionModel, {
namespace: activeNamespace,
prop: VMWizardProps.networkConfigs,
prop: VMWizardProps.networkAttachmentDefinitions,
}),
getResource(StorageClassModel, { prop: VMWizardProps.storageClasses }),
getResource(PersistentVolumeClaimModel, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
CommonData,
DetectCommonDataChanges,
VMSettingsField,
VMWizardNetwork,
VMWizardTab,
} from '../types';
import { cleanup, updateAndValidateState } from './utils';
import { getTabInitialState } from './initial-state';
Expand All @@ -14,28 +16,40 @@ import { vmWizardInternalActions } from './internal-actions';

type VMWizardActions = { [key in ActionType]: WizardActionDispatcher };

export const vmWizardActions: VMWizardActions = {
[ActionType.Create]: (id, commonData: CommonData) => (dispatch, getState) => {
const prevState = getState(); // must be called before dispatch
const withUpdateAndValidateState = (
id: string,
resolveAction,
changedCommonData?: Set<ChangedCommonDataProp>,
) => (dispatch, getState) => {
const prevState = getState(); // must be called before dispatch in resolveAction

dispatch(
vmWizardInternalActions[InternalActionType.Create](id, {
tabs: ALL_VM_WIZARD_TABS.reduce((initial, tabKey) => {
initial[tabKey] = getTabInitialState(tabKey, commonData);
return initial;
}, {}),
commonData,
}),
);
resolveAction(dispatch, getState);

updateAndValidateState({
id,
dispatch,
changedCommonData: changedCommonData || new Set<ChangedCommonDataProp>(),
getState,
prevState,
});
};

updateAndValidateState({
export const vmWizardActions: VMWizardActions = {
[ActionType.Create]: (id, commonData: CommonData) =>
withUpdateAndValidateState(
id,
changedCommonData: new Set<ChangedCommonDataProp>(DetectCommonDataChanges),
dispatch,
getState,
prevState,
});
},
(dispatch) =>
dispatch(
vmWizardInternalActions[InternalActionType.Create](id, {
tabs: ALL_VM_WIZARD_TABS.reduce((initial, tabKey) => {
initial[tabKey] = getTabInitialState(tabKey, commonData);
return initial;
}, {}),
commonData,
}),
),
new Set<ChangedCommonDataProp>(DetectCommonDataChanges),
),
[ActionType.Dispose]: (id) => (dispatch, getState) => {
const prevState = getState(); // must be called before dispatch
cleanup({
Expand All @@ -48,34 +62,32 @@ export const vmWizardActions: VMWizardActions = {

dispatch(vmWizardInternalActions[InternalActionType.Dispose](id));
},
[ActionType.SetVmSettingsFieldValue]: (id, key: VMSettingsField, value: string) => (
dispatch,
getState,
) => {
const prevState = getState(); // must be called before dispatch
dispatch(vmWizardInternalActions[InternalActionType.SetVmSettingsFieldValue](id, key, value));

updateAndValidateState({
[ActionType.SetVmSettingsFieldValue]: (id, key: VMSettingsField, value: string) =>
withUpdateAndValidateState(id, (dispatch) =>
dispatch(vmWizardInternalActions[InternalActionType.SetVmSettingsFieldValue](id, key, value)),
),
[ActionType.UpdateCommonData]: (id, commonData: CommonData, changedProps: ChangedCommonData) =>
withUpdateAndValidateState(
id,
dispatch,
changedCommonData: new Set<ChangedCommonDataProp>(),
getState,
prevState,
});
},
[ActionType.UpdateCommonData]: (id, commonData: CommonData, changedProps: ChangedCommonData) => (
dispatch,
getState,
) => {
const prevState = getState(); // must be called before dispatch

dispatch(vmWizardInternalActions[InternalActionType.UpdateCommonData](id, commonData));

updateAndValidateState({ id, dispatch, changedCommonData: changedProps, getState, prevState });
},
[ActionType.SetNetworks]: (id, value: any, isValid: boolean, isLocked: boolean) => (dispatch) => {
dispatch(vmWizardInternalActions[InternalActionType.SetNetworks](id, value, isValid, isLocked));
(dispatch) =>
dispatch(vmWizardInternalActions[InternalActionType.UpdateCommonData](id, commonData)),
changedProps,
),
[ActionType.SetTabLocked]: (id, tab: VMWizardTab, isLocked: boolean) => (dispatch) => {
dispatch(vmWizardInternalActions[InternalActionType.SetTabLocked](id, tab, isLocked));
},
[ActionType.UpdateNIC]: (id, network: VMWizardNetwork) =>
withUpdateAndValidateState(id, (dispatch) =>
dispatch(vmWizardInternalActions[InternalActionType.UpdateNIC](id, network)),
),
[ActionType.RemoveNIC]: (id, networkID: string) =>
withUpdateAndValidateState(id, (dispatch) =>
dispatch(vmWizardInternalActions[InternalActionType.RemoveNIC](id, networkID)),
),
[ActionType.SetNetworks]: (id, networks: VMWizardNetwork[]) =>
withUpdateAndValidateState(id, (dispatch) =>
dispatch(vmWizardInternalActions[InternalActionType.SetNetworks](id, networks)),
),
[ActionType.SetStorages]: (id, value: any, isValid: boolean, isLocked: boolean) => (dispatch) => {
dispatch(vmWizardInternalActions[InternalActionType.SetStorages](id, value, isValid, isLocked));
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { getReviewInitialState } from './review-tab-initial-state';

const initialStateGetterResolver = {
[VMWizardTab.VM_SETTINGS]: getVmSettingsInitialState,
[VMWizardTab.NETWORKS]: getNetworksInitialState,
[VMWizardTab.NETWORKING]: getNetworksInitialState,
[VMWizardTab.STORAGE]: getStorageInitialState,
[VMWizardTab.REVIEW]: getReviewInitialState,
[VMWizardTab.RESULT]: getResultInitialState,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import { NetworkInterfaceType, NetworkType, POD_NETWORK } from '../../../../constants/vm';
import { VMWizardNetwork, VMWizardNetworkType } from '../../types';
import { NetworkInterfaceWrapper } from '../../../../k8s/wrapper/vm/network-interface-wrapper';
import { NetworkInterfaceModel, NetworkType } from '../../../../constants/vm/network';
import { NetworkWrapper } from '../../../../k8s/wrapper/vm/network-wrapper';
import { getSequenceName } from '../../../../utils/strings';

export const podNetwork = {
rootNetwork: {},
id: 0,
name: 'nic0',
mac: '',
network: POD_NETWORK,
editable: true,
edit: false,
networkType: NetworkType.POD,
binding: NetworkInterfaceType.MASQUERADE,
export const podNetwork: VMWizardNetwork = {
id: '0',
type: VMWizardNetworkType.UI_DEFAULT_POD_NETWORK,
networkInterface: NetworkInterfaceWrapper.initializeFromSimpleData({
name: getSequenceName('nic'),
model: NetworkInterfaceModel.VIRTIO,
interfaceType: NetworkType.POD.getDefaultInterfaceType(),
}).asResource(),
network: NetworkWrapper.initializeFromSimpleData({
name: getSequenceName('nic'),
type: NetworkType.POD,
}).asResource(),
};

export const getNetworksInitialState = () => ({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// left intentionally empty
import { ProvisionSource } from '../../../../types/vm';
import { StorageType } from '../../../../constants/vm/storage';

const rootDisk = {
rootStorage: {},
Expand All @@ -9,11 +8,11 @@ const rootDisk = {
};
export const rootContainerDisk = {
...rootDisk,
storageType: StorageType.CONTAINER,
// storageType: StorageType.CONTAINER, TODO!!
};
export const rootDataVolumeDisk = {
...rootDisk,
storageType: StorageType.DATAVOLUME,
// storageType: StorageType.DATAVOLUME, TODO!!
size: 10,
};
export const getInitialDisk = (provisionSource: ProvisionSource) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const getInitialVmSettings = (common: CommonData) => {
} = common;

const provisionSources = [
// ProvisionSource.PXE, // TODO: uncomment when storage tab is implemented
ProvisionSource.PXE,
ProvisionSource.URL,
ProvisionSource.CONTAINER,
// ProvisionSource.CLONED_DISK, // TODO: uncomment when storage tab is implemented
Expand Down
Loading