feat: support create non-bfv instance
support create non-bfv instance Closes-Bug: #2003057 Change-Id: If494648f4d42c6da54661400283968c7220bf2a4
This commit is contained in:
parent
12bc328c24
commit
6a186ee521
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
fixes:
|
||||
- |
|
||||
`Feature #2003057 <https://bugs.launchpad.net/skyline-apiserver/+bug/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.
|
|
@ -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 <FlavorSelectTable onChange={this.onFlavorChange} />;
|
||||
}
|
||||
|
@ -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'),
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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') {
|
||||
|
|
Loading…
Reference in New Issue