From 6a186ee521b0663cf528646140e82dcb34370fd4 Mon Sep 17 00:00:00 2001 From: "Jingwei.Zhang" Date: Thu, 28 Sep 2023 17:18:39 +0800 Subject: [PATCH] feat: support create non-bfv instance support create non-bfv instance Closes-Bug: #2003057 Change-Id: If494648f4d42c6da54661400283968c7220bf2a4 --- ...From-Volume-Instance-09f802a7c0c53052.yaml | 10 ++ .../actions/StepCreate/BaseStep/index.jsx | 101 +++++++++++++++++- .../actions/StepCreate/ConfirmStep/index.jsx | 12 ++- .../Instance/actions/StepCreate/index.jsx | 49 +++++---- 4 files changed, 145 insertions(+), 27 deletions(-) create mode 100644 releasenotes/notes/Support-No-Boot-From-Volume-Instance-09f802a7c0c53052.yaml diff --git a/releasenotes/notes/Support-No-Boot-From-Volume-Instance-09f802a7c0c53052.yaml b/releasenotes/notes/Support-No-Boot-From-Volume-Instance-09f802a7c0c53052.yaml new file mode 100644 index 00000000..1fe9c8cc --- /dev/null +++ b/releasenotes/notes/Support-No-Boot-From-Volume-Instance-09f802a7c0c53052.yaml @@ -0,0 +1,10 @@ +--- +fixes: + - | + `Feature #2003057 `_: + + Support create No-BFV instance: + + * Support no-boot-from-volume selector when create instance by image or instance snapshot. + + * When create a no-boot-from-volume instance, you can not add data disk in the step forms, but you can attach volumes when the instance has been created. diff --git a/src/pages/compute/containers/Instance/actions/StepCreate/BaseStep/index.jsx b/src/pages/compute/containers/Instance/actions/StepCreate/BaseStep/index.jsx index cef6794b..78171947 100644 --- a/src/pages/compute/containers/Instance/actions/StepCreate/BaseStep/index.jsx +++ b/src/pages/compute/containers/Instance/actions/StepCreate/BaseStep/index.jsx @@ -82,6 +82,9 @@ export class BaseStep extends Base { project: this.currentProjectName, dataDisk: [], }; + if (source.value === 'image') { + values.bootFromVolume = true; + } return values; } @@ -272,7 +275,14 @@ export class BaseStep extends Base { }; get nameForStateUpdate() { - return ['source', 'image', 'instanceSnapshot', 'bootableVolume', 'flavor']; + return [ + 'source', + 'image', + 'instanceSnapshot', + 'bootableVolume', + 'flavor', + 'bootFromVolume', + ]; } getSystemDiskMinSize() { @@ -333,6 +343,17 @@ export class BaseStep extends Base { }); }; + onChangeBootFromVolume = (value) => { + const newData = { + bootFromVolume: value, + }; + if (!value) { + newData.dataDisk = []; + this.updateFormValue('dataDisk', []); + } + this.updateContext(newData); + }; + onInstanceSnapshotChange = async (value) => { const { min_disk, size, id } = value.selectedRows[0] || {}; if (!id) { @@ -357,14 +378,17 @@ export class BaseStep extends Base { instanceSnapshotDataVolumes = [], } = detail; if (!volumeDetail) { + this.updateFormValue('bootFromVolume', true); this.updateContext({ instanceSnapshotDisk: null, instanceSnapshotDataVolumes: [], + bootFromVolume: true, }); this.setState({ instanceSnapshotDisk: null, instanceSnapshotMinSize: 0, instanceSnapshotDataVolumes: [], + bootFromVolume: true, }); } const minSize = Math.max(min_disk, size, snapshotSize); @@ -544,6 +568,36 @@ export class BaseStep extends Base { ]; } + get supportNoBootFromVolume() { + return true; + } + + get showBootFromVolumeFormItem() { + if (!this.supportNoBootFromVolume) { + return false; + } + if (!this.enableCinder) { + return false; + } + if (this.sourceTypeIsImage) { + return true; + } + return this.showSystemDisk; + } + + get bootFromVolumeOptions() { + return [ + { + value: true, + label: t('Yes - Create a new system disk'), + }, + { + value: false, + label: t('No - Do not create a new system disk'), + }, + ]; + } + get showSystemDisk() { const snapshotDisk = this.getInstanceSnapshotDisk(); return ( @@ -553,6 +607,18 @@ export class BaseStep extends Base { ); } + get showSystemDiskByBootFromVolume() { + if (!this.showSystemDisk) { + return false; + } + if (!this.supportNoBootFromVolume) { + return true; + } + // support non-bfv and bootFromVolume = true + const { bootFromVolume = true } = this.state; + return !!bootFromVolume; + } + get hideInstanceSnapshotSystemDisk() { return this.showSystemDisk || this.sourceTypeIsVolume; } @@ -562,6 +628,17 @@ export class BaseStep extends Base { return this.getSnapshotDataDisks().length === 0; } + get hideDataDisk() { + if (!this.supportNoBootFromVolume) { + return false; + } + if (this.sourceTypeIsVolume) { + return false; + } + const { bootFromVolume = true } = this.state; + return !bootFromVolume; + } + getFlavorComponent() { return ; } @@ -683,13 +760,30 @@ export class BaseStep extends Base { { type: 'divider', }, + { + name: 'bootFromVolume', + label: t('Boot From Volume'), + type: 'radio', + required: this.showBootFromVolumeFormItem, + hidden: !this.showBootFromVolumeFormItem, + onChange: this.onChangeBootFromVolume, + wrapperCol: { + xs: { + span: 16, + }, + sm: { + span: 14, + }, + }, + options: this.bootFromVolumeOptions, + }, { name: 'systemDisk', label: t('System Disk'), type: 'instance-volume', options: this.volumeTypes, - required: this.showSystemDisk, - hidden: !this.showSystemDisk, + required: this.showSystemDiskByBootFromVolume, + hidden: !this.showSystemDiskByBootFromVolume, validator: this.checkSystemDisk, minSize: this.getSystemDiskMinSize(), extra: t('Disk size is limited by the min disk of flavor, image, etc.'), @@ -713,6 +807,7 @@ export class BaseStep extends Base { type: 'add-select', options: this.volumeTypes, defaultItemValue: this.defaultVolumeType, + hidden: this.hideDataDisk, itemComponent: InstanceVolume, minCount: 0, addTextTips: t('Data Disks'), diff --git a/src/pages/compute/containers/Instance/actions/StepCreate/ConfirmStep/index.jsx b/src/pages/compute/containers/Instance/actions/StepCreate/ConfirmStep/index.jsx index fd014cda..ec5924fc 100644 --- a/src/pages/compute/containers/Instance/actions/StepCreate/ConfirmStep/index.jsx +++ b/src/pages/compute/containers/Instance/actions/StepCreate/ConfirmStep/index.jsx @@ -36,7 +36,10 @@ export class ConfirmStep extends Base { allowed = () => Promise.resolve(); - getDisk(diskInfo) { + getDisk(diskInfo, bootFromVolume) { + if (!bootFromVolume) { + return null; + } const { size, typeOption, deleteTypeLabel } = diskInfo || {}; return `${typeOption.label} ${size}GiB ${deleteTypeLabel}`; } @@ -54,14 +57,15 @@ export class ConfirmStep extends Base { systemDisk, source: { value } = {}, instanceSnapshotDisk, + bootFromVolume = true, } = context; if (value === 'bootableVolume') { return this.getBootableVolumeDisk(); } if (value === 'instanceSnapshot' && instanceSnapshotDisk !== null) { - return this.getDisk(instanceSnapshotDisk); + return this.getDisk(instanceSnapshotDisk, bootFromVolume); } - return this.getDisk(systemDisk); + return this.getDisk(systemDisk, bootFromVolume); } getDataDisk() { @@ -79,7 +83,7 @@ export class ConfirmStep extends Base { ) { allDataDisks = getAllDataDisks({ dataDisk, instanceSnapshotDataVolumes }); } - return allDataDisks.map((it) => this.getDisk(it.value)); + return allDataDisks.map((it) => this.getDisk(it.value, true)); } getFlavor() { diff --git a/src/pages/compute/containers/Instance/actions/StepCreate/index.jsx b/src/pages/compute/containers/Instance/actions/StepCreate/index.jsx index 47f2fa9b..ad84dedb 100644 --- a/src/pages/compute/containers/Instance/actions/StepCreate/index.jsx +++ b/src/pages/compute/containers/Instance/actions/StepCreate/index.jsx @@ -301,6 +301,7 @@ export class StepCreate extends StepAction { source: { value: sourceValue } = {}, instanceSnapshotDisk = {}, instanceSnapshotDataVolumes = [], + bootFromVolume = true, } = data; const newCountMap = {}; const newSizeMap = {}; @@ -309,7 +310,7 @@ export class StepCreate extends StepAction { const isSnapshotType = sourceValue === 'instanceSnapshot'; if (isSnapshotType && instanceSnapshotDisk) { const { size, typeOption: { label } = {} } = instanceSnapshotDisk; - if (label) { + if (label && bootFromVolume) { newCountMap[label] = !newCountMap[label] ? 1 : newCountMap[label] + 1; newSizeMap[label] = !newSizeMap[label] ? size @@ -317,7 +318,7 @@ export class StepCreate extends StepAction { totalNewCount += 1 * count; totalNewSize += size * count; } - } else if (systemDisk.type) { + } else if (systemDisk.type && bootFromVolume) { const { size } = systemDisk; const { label } = systemDisk.typeOption || {}; newCountMap[label] = !newCountMap[label] ? 1 : newCountMap[label] + 1; @@ -577,6 +578,7 @@ export class StepCreate extends StepAction { instanceSnapshotDisk, source, systemDisk, + bootFromVolume = true, } = values; const { value: sourceValue } = source; const imageRef = @@ -592,21 +594,23 @@ export class StepCreate extends StepAction { } let rootVolume = {}; if (sourceValue !== 'bootableVolume') { - const { deleteType, type, size } = systemDisk || {}; - rootVolume = { - boot_index: 0, - uuid: imageRef, - source_type: 'image', - volume_size: size, - destination_type: 'volume', - volume_type: type, - delete_on_termination: deleteType === 1, - }; - if (sourceValue === 'instanceSnapshot') { - if (instanceSnapshotDisk) { - delete rootVolume.volume_size; - delete rootVolume.volume_type; - delete rootVolume.delete_on_termination; + if (bootFromVolume) { + const { deleteType, type, size } = systemDisk || {}; + rootVolume = { + boot_index: 0, + uuid: imageRef, + source_type: 'image', + volume_size: size, + destination_type: 'volume', + volume_type: type, + delete_on_termination: deleteType === 1, + }; + if (sourceValue === 'instanceSnapshot') { + if (instanceSnapshotDisk) { + delete rootVolume.volume_size; + delete rootVolume.volume_type; + delete rootVolume.delete_on_termination; + } } } } else { @@ -636,15 +640,19 @@ export class StepCreate extends StepAction { if ( sourceValue === 'image' && image.selectedRows[0].disk_format === 'iso' && - dataVolumes[0] + dataVolumes[0] && + bootFromVolume ) { dataVolumes[0].boot_index = 0; dataVolumes[0].device_type = 'disk'; rootVolume.boot_index = 1; rootVolume.device_type = 'cdrom'; } + const volumes = isEmpty(rootVolume) + ? [...dataVolumes] + : [rootVolume, ...dataVolumes]; return { - volumes: [rootVolume, ...dataVolumes], + volumes, imageRef, }; } @@ -695,6 +703,7 @@ export class StepCreate extends StepAction { serverGroup, name, count = 1, + bootFromVolume = true, } = values; if (hasIp && count > 1) { this.ipBatchError = true; @@ -714,7 +723,7 @@ export class StepCreate extends StepAction { if (this.enableCinder) { server.block_device_mapping_v2 = volumes; } - if (imageRef && !volumes) { + if (imageRef && (!volumes || !bootFromVolume)) { server.imageRef = imageRef; } if (loginType.value === 'keypair') {