mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2026-10-04 05:06:05 +08:00
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:
@@ -3,10 +3,9 @@ import jsyaml from 'js-yaml';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import difference from 'lodash/difference';
|
||||
|
||||
import { sortBy } from '@shell/utils/sort';
|
||||
import { set } from '@shell/utils/object';
|
||||
|
||||
import { getVmCPUMemoryValues } from '../../utils/cpuMemory';
|
||||
import { allHash } from '@shell/utils/promise';
|
||||
import { randomStr } from '@shell/utils/string';
|
||||
import { base64Decode } from '@shell/utils/crypto';
|
||||
@@ -164,6 +163,9 @@ export default {
|
||||
deleteAgent: true,
|
||||
memory: null,
|
||||
cpu: '',
|
||||
maxMemory: null,
|
||||
maxCpu: '',
|
||||
cpuMemoryHotplugEnabled: false,
|
||||
reservedMemory: null,
|
||||
accessCredentials: [],
|
||||
efiEnabled: false,
|
||||
@@ -348,8 +350,11 @@ export default {
|
||||
const runStrategy = spec.runStrategy || 'RerunOnFailure';
|
||||
const machineType = spec.template.spec.domain?.machine?.type || this.machineTypes[0];
|
||||
|
||||
const cpu = spec.template.spec.domain?.cpu?.cores;
|
||||
const memory = spec.template.spec.domain.resources.limits.memory;
|
||||
const {
|
||||
cpu, memory, maxCpu, maxMemory, isHotplugEnabled
|
||||
} = getVmCPUMemoryValues(vm);
|
||||
const cpuMemoryHotplugEnabled = isHotplugEnabled;
|
||||
|
||||
const reservedMemory = vm.metadata?.annotations?.[HCI_ANNOTATIONS.VM_RESERVED_MEMORY];
|
||||
const terminationGracePeriodSeconds = spec.template.spec?.terminationGracePeriodSeconds || this.defaultTerminationSetting;
|
||||
|
||||
@@ -409,6 +414,9 @@ export default {
|
||||
|
||||
this['cpu'] = cpu;
|
||||
this['memory'] = memory;
|
||||
this['maxCpu'] = maxCpu;
|
||||
this['maxMemory'] = maxMemory;
|
||||
this['cpuMemoryHotplugEnabled'] = cpuMemoryHotplugEnabled;
|
||||
this['reservedMemory'] = reservedMemory;
|
||||
this['machineType'] = machineType;
|
||||
this['terminationGracePeriodSeconds'] = terminationGracePeriodSeconds;
|
||||
@@ -633,20 +641,26 @@ export default {
|
||||
this.spec.template.spec.domain.machine['type'] = this.machineType;
|
||||
}
|
||||
|
||||
this.spec.template.spec.domain.cpu.cores = this.cpu;
|
||||
this.spec.template.spec.domain.resources.limits.cpu = this.cpu ? this.cpu.toString() : this.cpu;
|
||||
this.spec.template.spec.domain.resources.limits.memory = this.memory;
|
||||
this.setCPUAndMemory();
|
||||
// update terminationGracePeriodSeconds
|
||||
this.spec.template.spec.terminationGracePeriodSeconds = this.terminationGracePeriodSeconds;
|
||||
|
||||
// parse reserved memory
|
||||
const vm = this.resourceType === HCI.VM ? this.value : this.value.spec.vm;
|
||||
|
||||
// parse reserved memory
|
||||
if (!this.reservedMemory) {
|
||||
delete vm.metadata.annotations[HCI_ANNOTATIONS.VM_RESERVED_MEMORY];
|
||||
} else {
|
||||
vm.metadata.annotations[HCI_ANNOTATIONS.VM_RESERVED_MEMORY] = this.reservedMemory;
|
||||
}
|
||||
|
||||
// add or remove cpu memory hotplug annotation
|
||||
if (this.cpuMemoryHotplugEnabled) {
|
||||
vm.metadata.annotations[HCI_ANNOTATIONS.VM_CPU_MEMORY_HOTPLUG] = this.cpuMemoryHotplugEnabled.toString();
|
||||
} else {
|
||||
delete vm.metadata.annotations[HCI_ANNOTATIONS.VM_CPU_MEMORY_HOTPLUG];
|
||||
}
|
||||
|
||||
if (this.maintenanceStrategy === 'Migrate') {
|
||||
delete vm.metadata.labels[HCI_ANNOTATIONS.VM_MAINTENANCE_MODE_STRATEGY];
|
||||
} else {
|
||||
@@ -654,6 +668,36 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
setCPUAndMemory() {
|
||||
if (this.cpuMemoryHotplugEnabled) {
|
||||
// set CPU
|
||||
this.spec.template.spec.domain.cpu.sockets = this.cpu;
|
||||
this.spec.template.spec.domain.cpu.cores = 1;
|
||||
|
||||
// set max CPU
|
||||
set(this.spec.template.spec, 'domain.cpu.maxSockets', this.maxCpu);
|
||||
// domain.resources.limits.cpu and memory are defined by k8s which requires string values
|
||||
// see https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/
|
||||
set(this.spec.template.spec, 'domain.resources.limits.cpu', this.maxCpu?.toString());
|
||||
|
||||
// set memory
|
||||
set(this.spec.template.spec, 'domain.memory.guest', this.memory);
|
||||
|
||||
// set max memory
|
||||
set(this.spec.template.spec, 'domain.memory.maxGuest', this.maxMemory);
|
||||
set(this.spec.template.spec, 'domain.resources.limits.memory', this.maxMemory);
|
||||
} else {
|
||||
this.spec.template.spec.domain.cpu.sockets = 1;
|
||||
this.spec.template.spec.domain.cpu.cores = this.cpu;
|
||||
this.spec.template.spec.domain.resources.limits.cpu = this.cpu?.toString();
|
||||
this.spec.template.spec.domain.resources.limits.memory = this.memory;
|
||||
// clean
|
||||
delete this.spec.template.spec.resources;
|
||||
delete this.spec.template.spec.domain.memory;
|
||||
delete this.spec.template.spec.domain.cpu.maxSockets;
|
||||
}
|
||||
},
|
||||
|
||||
parseDiskRows(disk) {
|
||||
const disks = [];
|
||||
const volumes = [];
|
||||
@@ -952,9 +996,12 @@ export default {
|
||||
this['sshKey'] = neu;
|
||||
},
|
||||
|
||||
updateCpuMemory(cpu, memory) {
|
||||
updateCpuMemory(cpu, memory, maxCpu = '', maxMemory = null, cpuMemoryHotplugEnabled = false) {
|
||||
this['cpu'] = cpu;
|
||||
this['memory'] = memory;
|
||||
this['maxCpu'] = maxCpu;
|
||||
this['maxMemory'] = maxMemory;
|
||||
this['cpuMemoryHotplugEnabled'] = cpuMemoryHotplugEnabled;
|
||||
},
|
||||
|
||||
parseDisk(R, index) {
|
||||
@@ -1311,6 +1358,21 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
getCPUMemoryValidation() {
|
||||
const errors = [];
|
||||
const { cpu, memory } = this;
|
||||
|
||||
if ((!cpu)) {
|
||||
errors.push(this.t('validation.required', { key: this.t('harvester.virtualMachine.input.cpu') }, true));
|
||||
}
|
||||
|
||||
if ((!memory)) {
|
||||
errors.push(this.t('validation.required', { key: this.t('harvester.virtualMachine.input.memory') }, true));
|
||||
}
|
||||
|
||||
return errors;
|
||||
},
|
||||
|
||||
getAccessCredentialsValidation() {
|
||||
const errors = [];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user