From f8463436880bdf5d4ccb1f59d703ec2f19a29809 Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Fri, 20 Aug 2021 09:57:06 -0300 Subject: [PATCH 1/2] Externalize config to increment or not VM metrics in memory --- .../main/java/com/cloud/server/StatsCollector.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/server/src/main/java/com/cloud/server/StatsCollector.java b/server/src/main/java/com/cloud/server/StatsCollector.java index fd59fb86c762..36c0372325dd 100644 --- a/server/src/main/java/com/cloud/server/StatsCollector.java +++ b/server/src/main/java/com/cloud/server/StatsCollector.java @@ -51,6 +51,7 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.BooleanUtils; import org.apache.log4j.Logger; import org.influxdb.BatchOptions; import org.influxdb.InfluxDB; @@ -221,6 +222,9 @@ public String toString() { private static final ConfigKey statsOutputUri = new ConfigKey("Advanced", String.class, "stats.output.uri", "", "URI to send StatsCollector statistics to. The collector is defined on the URI scheme. Example: graphite://graphite-hostaddress:port or influxdb://influxdb-hostaddress/dbname. Note that the port is optional, if not added the default port for the respective collector (graphite or influxdb) will be used. Additionally, the database name '/dbname' is also optional; default db name is 'cloudstack'. You must create and configure the database if using influxdb.", true); + private static final ConfigKey VM_STATS_INCREMENT_METRICS_IN_MEMORY = new ConfigKey("Advanced", Boolean.class, "vm.stats.increment.metrics.in.memory", "true", + "When set to 'true', VM metrics(NetworkReadKBs, NetworkWriteKBs, DiskWriteKBs, DiskReadKBs, DiskReadIOs and DiskWriteIOs) that are collected from the hypervisor are summed and stored in memory. " + + "On the other hand, when set to 'false', the VM metrics API will just display the latest metrics collected.", true); private static StatsCollector s_instance = null; @@ -1460,11 +1464,12 @@ private void prepareVmMetricsForGraphite(Map metrics, VmStatsEnt private void storeVirtualMachineStatsInMemory(VmStatsEntry statsForCurrentIteration) { VmStatsEntry statsInMemory = (VmStatsEntry)_VmStats.get(statsForCurrentIteration.getVmId()); - if (statsInMemory == null) { - //no stats exist for this vm, directly persist + boolean vmStatsIncrementMetrics = BooleanUtils.toBoolean(VM_STATS_INCREMENT_METRICS_IN_MEMORY.value()); + if (statsInMemory == null || !vmStatsIncrementMetrics) { _VmStats.put(statsForCurrentIteration.getVmId(), statsForCurrentIteration); } else { - //update each field + s_logger.debug(String.format("Increment saved values of NetworkReadKBs, NetworkWriteKBs, DiskWriteKBs, DiskReadKBs, DiskReadIOs, DiskWriteIOs, with current metrics for VM with ID [%s]. " + + "To change this process, check value of 'vm.stats.increment.metrics.in.memory' configuration.", statsForCurrentIteration.getVmId())); statsInMemory.setCPUUtilization(statsForCurrentIteration.getCPUUtilization()); statsInMemory.setNumCPUs(statsForCurrentIteration.getNumCPUs()); statsInMemory.setNetworkReadKBs(statsInMemory.getNetworkReadKBs() + statsForCurrentIteration.getNetworkReadKBs()); @@ -1625,7 +1630,7 @@ public String getConfigComponentName() { @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[] {vmDiskStatsInterval, vmDiskStatsIntervalMin, vmNetworkStatsInterval, vmNetworkStatsIntervalMin, StatsTimeout, statsOutputUri}; + return new ConfigKey[] {vmDiskStatsInterval, vmDiskStatsIntervalMin, vmNetworkStatsInterval, vmNetworkStatsIntervalMin, StatsTimeout, statsOutputUri, VM_STATS_INCREMENT_METRICS_IN_MEMORY}; } public double getImageStoreCapacityThreshold() { From 908a6249ad564b39619bf1e7071c3b6ff0464526 Mon Sep 17 00:00:00 2001 From: Bryan Lima Date: Mon, 31 Jan 2022 20:04:16 -0300 Subject: [PATCH 2/2] Fix scale up on KVM VMs --- ui/public/locales/en.json | 1 + ui/public/locales/pt_BR.json | 1 + ui/src/config/section/compute.js | 2 +- ui/src/views/compute/ScaleVM.vue | 22 ++++++++++++++++++- .../views/compute/wizard/ComputeSelection.vue | 5 +++++ 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 372cd3166d6c..9f367b8bb997 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -2987,6 +2987,7 @@ "message.error.zone.name": "Please enter zone name", "message.error.zone.type": "Please select zone type", "message.error.linstor.resourcegroup": "Please enter the Linstor Resource-Group", +"message.error.fixed.offering.kvm": "It's not possible to scale up VMs that utilize KVM hypervisor with a fixed compute offering.", "message.fail.to.delete": "Failed to delete.", "message.failed.to.add": "Failed to add", "message.failed.to.assign.vms": "Failed to assign VMs", diff --git a/ui/public/locales/pt_BR.json b/ui/public/locales/pt_BR.json index 9dd3c63000e6..1294c690ee3f 100644 --- a/ui/public/locales/pt_BR.json +++ b/ui/public/locales/pt_BR.json @@ -2144,6 +2144,7 @@ "message.enabling.zone.dots": "Habilitando Zona....", "message.enter.seperated.list.multiple.cidrs": "Por favor entre a de CIDRs separadas por v\u00edrgula, se houver mais de uma", "message.enter.token": "Por favor entre o token que voc\u00ea recebeu no e-mail privado.", +"message.error.fixed.offering.kvm": "Não é possível escalar VMs que utilizam o hipervisor KVM com oferta de computa\u00e7\u00e3o fixa.", "message.generate.keys": "Por favor confirme que voc\u00ea deseja gerar novas chaves para este usu\u00e1rio.", "message.gslb.delete.confirm": "Confirme que voc\u00ea deseja apagar este GSLB", "message.gslb.lb.remove.confirm": "Confirme que voc\u00ea deseja remover o balanceamento de carga deste GSLB", diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js index 835923d9f07e..f1f23405a08b 100644 --- a/ui/src/config/section/compute.js +++ b/ui/src/config/section/compute.js @@ -301,7 +301,7 @@ export default { label: 'label.scale.vm', docHelp: 'adminguide/virtual_machines.html#how-to-dynamically-scale-cpu-and-ram', dataView: true, - show: (record) => { return ['Stopped'].includes(record.state) || (['Running'].includes(record.state) && record.hypervisor !== 'KVM' && record.hypervisor !== 'LXC') }, + show: (record) => { return ['Stopped'].includes(record.state) || (['Running'].includes(record.state) && record.hypervisor !== 'LXC') }, disabled: (record) => { return record.state === 'Running' && !record.isdynamicallyscalable }, popup: true, component: () => import('@/views/compute/ScaleVM.vue') diff --git a/ui/src/views/compute/ScaleVM.vue b/ui/src/views/compute/ScaleVM.vue index a0cf5b197a1e..9c9934048fa1 100644 --- a/ui/src/views/compute/ScaleVM.vue +++ b/ui/src/views/compute/ScaleVM.vue @@ -23,6 +23,10 @@ + + + + offering.id === this.resource.serviceofferingid) + this.currentOffer = this.offerings[0] + if (this.currentOffer === undefined) { + this.fixedOfferingKvm = true + } + } this.offerings.map(i => { this.offeringsMap[i.id] = i }) }).finally(() => { this.loading = false @@ -131,6 +144,13 @@ export default { } return this.selectedOffering?.serviceofferingdetails?.minmemory * 1 || 32 }, + getCPUSpeed () { + // We can only scale up while a VM is running + if (this.resource.state === 'Running') { + return this.resource.cpuspeed + } + return this.selectedOffering?.serviceofferingdetails?.cpuspeed * 1 || 1 + }, getMessage () { if (this.resource.hypervisor === 'VMware') { return this.$t('message.read.admin.guide.scaling.up') diff --git a/ui/src/views/compute/wizard/ComputeSelection.vue b/ui/src/views/compute/wizard/ComputeSelection.vue index 5fe75d681780..d1bf992f3ef3 100644 --- a/ui/src/views/compute/wizard/ComputeSelection.vue +++ b/ui/src/views/compute/wizard/ComputeSelection.vue @@ -107,6 +107,10 @@ export default { type: Boolean, default: true }, + cpuSpeed: { + type: Number, + default: 0 + }, minCpu: { type: Number, default: 0 @@ -198,6 +202,7 @@ export default { fillValue () { this.cpuNumberInputValue = this.minCpu this.memoryInputValue = this.minMemory + this.cpuSpeedInputValue = this.cpuSpeed if (!this.preFillContent) { this.updateComputeCpuNumber(this.cpuNumberInputValue)