feat: CPU / Memory hotplug support (#413)

* feat: add maxCPU and maxMemory

Signed-off-by: Andy Lee <andy.lee@suse.com>

* feat: add hotplug dialog

Signed-off-by: Andy Lee <andy.lee@suse.com>

* feat: add restart message

Signed-off-by: Andy Lee <andy.lee@suse.com>

* feat: let VM template support cpuMemoryHotplug

Signed-off-by: Andy Lee <andy.lee@suse.com>

* feat: add feature flag

Signed-off-by: Andy Lee <andy.lee@suse.com>

* feat: add max-hotplug-ratio setting

Signed-off-by: Andy Lee <andy.lee@suse.com>

---------

Signed-off-by: Andy Lee <andy.lee@suse.com>
This commit is contained in:
Andy Lee
2025-07-23 14:08:59 +08:00
committed by GitHub
parent e294f4c00f
commit be9311dc0c
16 changed files with 564 additions and 92 deletions
@@ -13,6 +13,7 @@ import { parseVolumeClaimTemplates } from '@pkg/utils/vm';
import { BACKUP_TYPE } from '../config/types';
import { HCI } from '../types';
import HarvesterResource from './harvester';
import { getVmCPUMemoryValues } from '../utils/cpuMemory';
export const OFF = 'Off';
@@ -169,6 +170,12 @@ export default class VirtVm extends HarvesterResource {
icon: 'icon icon-storage',
label: this.t('harvester.action.editVMQuota')
},
{
action: 'cpuMemoryHotplug',
enabled: !!this.actions?.cpuAndMemoryHotplug,
icon: 'icon icon-os-management',
label: this.t('harvester.action.cpuAndMemoryHotplug')
},
{
action: 'createSchedule',
enabled: this.schedulingVMBackupFeatureEnabled,
@@ -476,6 +483,13 @@ export default class VirtVm extends HarvesterResource {
});
}
cpuMemoryHotplug(resources = this) {
this.$dispatch('promptModal', {
resources,
component: 'HarvesterCPUMemoryHotPlugDialog'
});
}
abortMigrationVM() {
this.doActionGrowl('abortMigration', {});
}
@@ -1091,19 +1105,6 @@ export default class VirtVm extends HarvesterResource {
maxLength: 63,
translationKey: 'harvester.fields.name'
},
{
nullable: false,
path: 'spec.template.spec.domain.cpu.cores',
min: 1,
required: true,
translationKey: 'harvester.fields.cpu'
},
{
nullable: false,
path: 'spec.template.spec.domain.resources.limits.memory',
required: true,
translationKey: 'harvester.fields.memory'
},
{
nullable: false,
path: 'spec.template.spec',
@@ -1127,12 +1128,11 @@ export default class VirtVm extends HarvesterResource {
}
get memorySort() {
const memory =
this?.spec?.template?.spec?.domain?.resources?.requests?.memory || 0;
const memory = getVmCPUMemoryValues(this).memory;
const formatSize = parseSi(memory);
return parseInt(formatSize);
return parseInt(formatSize, 10);
}
get ingoreVMMessage() {
@@ -1158,14 +1158,22 @@ export default class VirtVm extends HarvesterResource {
}
get stateDescription() {
const conditions = get(this, 'status.conditions');
const restartRequired = findBy(conditions, 'type', 'RestartRequired');
if (restartRequired && restartRequired.status === 'True') {
return this.t('harvester.virtualMachine.hotplug.restartVMMessage');
}
return this.ingoreVMMessage ? '' : super.stateDescription;
}
get displayCPU() {
return getVmCPUMemoryValues(this).cpu;
}
get displayMemory() {
return (
this.spec.template.spec.domain.resources?.limits?.memory ||
this.spec.template.spec.domain.resources?.requests?.memory
);
return getVmCPUMemoryValues(this).memory;
}
get isQemuInstalled() {