Skip to content
Draft

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.kubernetes.cluster.utils;

import java.io.File;

import com.cloud.kubernetes.cluster.KubernetesCluster;
import com.cloud.kubernetes.cluster.KubernetesServiceHelper.KubernetesClusterNodeType;
import com.cloud.offering.ServiceOffering;
import com.cloud.uservm.UserVm;

/** Reconciles the guest and Kubernetes resource views after a live VM resize. */
public interface KubernetesClusterNodeCapacityReconciler {
NodeCapacitySnapshot captureBefore(KubernetesCluster cluster, UserVm vm, NodeAccess access) throws Exception;

Check warning on line 28 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconciler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace generic exceptions with specific library exceptions or a custom exception.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XyJBZ3696PvGsj&open=AaDJI_XyJBZ3696PvGsj&pullRequest=14223
boolean requiresKubeletRefresh(ServiceOffering oldOffering, ServiceOffering newOffering,
KubernetesClusterNodeType nodeType, KubernetesCluster.State originalState);
void cordonIfNeeded(KubernetesCluster cluster, UserVm vm, NodeCapacitySnapshot before, NodeAccess access, long deadline) throws Exception;

Check warning on line 31 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconciler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace generic exceptions with specific library exceptions or a custom exception.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XyJBZ3696PvGsk&open=AaDJI_XyJBZ3696PvGsk&pullRequest=14223
void onlineGuestResources(NodeAccess access) throws Exception;

Check warning on line 32 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconciler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace generic exceptions with specific library exceptions or a custom exception.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaFZz6HD9o_qlDAz5vrK&open=AaFZz6HD9o_qlDAz5vrK&pullRequest=14223
void verifyGuestResources(UserVm vm, ServiceOffering target, NodeCapacitySnapshot before, NodeAccess access, long deadline) throws Exception;

Check warning on line 33 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconciler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace generic exceptions with specific library exceptions or a custom exception.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XyJBZ3696PvGsl&open=AaDJI_XyJBZ3696PvGsl&pullRequest=14223
boolean isKubernetesResourcesCurrent(NodeCapacitySnapshot snapshot, ServiceOffering target);
void restartKubelet(UserVm vm, NodeAccess access, long deadline) throws Exception;

Check warning on line 35 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconciler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace generic exceptions with specific library exceptions or a custom exception.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XyJBZ3696PvGsm&open=AaDJI_XyJBZ3696PvGsm&pullRequest=14223
NodeCapacitySnapshot waitForKubernetesResources(KubernetesCluster cluster, UserVm vm, ServiceOffering target,
NodeCapacitySnapshot before, NodeAccess access, long deadline) throws Exception;

Check warning on line 37 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconciler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace generic exceptions with specific library exceptions or a custom exception.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XyJBZ3696PvGsn&open=AaDJI_XyJBZ3696PvGsn&pullRequest=14223
void restoreSchedulability(KubernetesCluster cluster, UserVm vm, NodeCapacitySnapshot before, NodeAccess access, long deadline) throws Exception;

Check warning on line 38 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconciler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace generic exceptions with specific library exceptions or a custom exception.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XyJBZ3696PvGso&open=AaDJI_XyJBZ3696PvGso&pullRequest=14223

final class NodeAccess {

Check warning on line 40 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconciler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Move this class out of this interface.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaFYA6DgMa5wDoWaOYd2&open=AaFYA6DgMa5wDoWaOYd2&pullRequest=14223
private final String controlAddress; private final int controlPort; private final String nodeAddress; private final int nodePort;

Check warning on line 41 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconciler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Declare "controlPort" and all following declarations on a separate line.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XyJBZ3696PvGsp&open=AaDJI_XyJBZ3696PvGsp&pullRequest=14223
private final String user; private final File sshKeyFile;

Check warning on line 42 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconciler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Declare "sshKeyFile" on a separate line.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XyJBZ3696PvGsq&open=AaDJI_XyJBZ3696PvGsq&pullRequest=14223
public NodeAccess(String controlAddress, int controlPort, String nodeAddress, int nodePort, String user, File sshKeyFile) {
this.controlAddress = controlAddress; this.controlPort = controlPort; this.nodeAddress = nodeAddress; this.nodePort = nodePort;
this.user = user; this.sshKeyFile = sshKeyFile;
}
public String getControlAddress() { return controlAddress; } public int getControlPort() { return controlPort; }
public String getNodeAddress() { return nodeAddress; } public int getNodePort() { return nodePort; }
public String getUser() { return user; } public File getSshKeyFile() { return sshKeyFile; }
}

final class NodeCapacitySnapshot {

Check warning on line 52 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconciler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Move this class out of this interface.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaFYA6DgMa5wDoWaOYd3&open=AaFYA6DgMa5wDoWaOYd3&pullRequest=14223
private final boolean unschedulable; private final boolean cloudStackResizeCordon; private final long guestOnlineCpuCount;

Check warning on line 53 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconciler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Declare "cloudStackResizeCordon" and all following declarations on a separate line.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XyJBZ3696PvGsr&open=AaDJI_XyJBZ3696PvGsr&pullRequest=14223
private final long guestMemoryKiB; private final long capacityCpuMillis; private final long capacityMemoryBytes;

Check warning on line 54 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconciler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Declare "capacityCpuMillis" and all following declarations on a separate line.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XyJBZ3696PvGss&open=AaDJI_XyJBZ3696PvGss&pullRequest=14223
private final long allocatableCpuMillis; private final long allocatableMemoryBytes; private final boolean ready;

Check warning on line 55 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconciler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Declare "allocatableMemoryBytes" and all following declarations on a separate line.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XyJBZ3696PvGst&open=AaDJI_XyJBZ3696PvGst&pullRequest=14223
public NodeCapacitySnapshot(boolean unschedulable, boolean cloudStackResizeCordon, long guestOnlineCpuCount, long guestMemoryKiB,

Check warning on line 56 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconciler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Constructor has 9 parameters, which is greater than 7 authorized.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XyJBZ3696PvGsu&open=AaDJI_XyJBZ3696PvGsu&pullRequest=14223
long capacityCpuMillis, long capacityMemoryBytes, long allocatableCpuMillis, long allocatableMemoryBytes, boolean ready) {
this.unschedulable = unschedulable; this.cloudStackResizeCordon = cloudStackResizeCordon; this.guestOnlineCpuCount = guestOnlineCpuCount;
this.guestMemoryKiB = guestMemoryKiB; this.capacityCpuMillis = capacityCpuMillis; this.capacityMemoryBytes = capacityMemoryBytes;
this.allocatableCpuMillis = allocatableCpuMillis; this.allocatableMemoryBytes = allocatableMemoryBytes; this.ready = ready;
}
public boolean isUnschedulable() { return unschedulable; } public boolean isCloudStackResizeCordon() { return cloudStackResizeCordon; }
public long getGuestOnlineCpuCount() { return guestOnlineCpuCount; } public long getGuestMemoryKiB() { return guestMemoryKiB; }
public long getCapacityCpuMillis() { return capacityCpuMillis; } public long getCapacityMemoryBytes() { return capacityMemoryBytes; }
public long getAllocatableCpuMillis() { return allocatableCpuMillis; } public long getAllocatableMemoryBytes() { return allocatableMemoryBytes; }
public boolean isReady() { return ready; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.kubernetes.cluster.utils;

import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.cloud.kubernetes.cluster.KubernetesCluster;
import com.cloud.kubernetes.cluster.KubernetesServiceHelper.KubernetesClusterNodeType;
import com.cloud.offering.ServiceOffering;
import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.ssh.SshHelper;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.commons.lang3.StringUtils;

/** SSH-backed implementation for a rolling CKS live-resize reconciliation. */
public class KubernetesClusterNodeCapacityReconcilerImpl implements KubernetesClusterNodeCapacityReconciler {
// KVM QA observes 4,568,788 KiB in a 4,608 MiB guest after memory hotplug
// (about 146 MiB below the offering), so keep a small margin above that
// platform overhead while still rejecting materially undersized guests.
static final long MINIMUM_MEMORY_OVERHEAD_BYTES = 160L * 1024L * 1024L;
static final long KUBERNETES_MEMORY_REPORTING_TOLERANCE_BYTES = 16L * 1024L * 1024L;
private static final int COMMAND_TIMEOUT_MS = 30000;
private static final int POLL_INTERVAL_MS = 5000;
private static final Pattern NODE_NAME = Pattern.compile("[A-Za-z0-9][A-Za-z0-9.-]{0,252}");
private static final Pattern MEMORY_QUANTITY = Pattern.compile("([0-9]+)(Ki|Mi|Gi|Ti|K|M|G|T)?");

Check warning on line 46 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconcilerImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use concise character class syntax '\\d' instead of '[0-9]'.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XoJBZ3696PvGsd&open=AaDJI_XoJBZ3696PvGsd&pullRequest=14223
private static final String RESIZE_ANNOTATION = "cloudstack.apache.org/cks-live-resize";
static final String ONLINE_HOTPLUGGED_RESOURCES = "sudo sh -c 'for cpu in /sys/devices/system/cpu/cpu[0-9]*; do "
+ "[ -e \"$cpu/online\" ] || continue; echo 1 > \"$cpu/online\"; done; "
+ "for memory in /sys/devices/system/memory/memory[0-9]*; do "
+ "[ -e \"$memory/online\" ] || continue; echo online > \"$memory/online\"; done'";

@Override
public boolean requiresKubeletRefresh(ServiceOffering oldOffering, ServiceOffering newOffering,
KubernetesClusterNodeType nodeType, KubernetesCluster.State originalState) {
return KubernetesCluster.State.Running == originalState
&& (KubernetesClusterNodeType.WORKER == nodeType || KubernetesClusterNodeType.CONTROL == nodeType)
&& capacityChanged(oldOffering, newOffering);
}

@Override
public NodeCapacitySnapshot captureBefore(KubernetesCluster cluster, UserVm vm, NodeAccess access) throws Exception {
return nodeSnapshot(cluster, vm, access, guestResources(access));
}

@Override
public void cordonIfNeeded(KubernetesCluster cluster, UserVm vm, NodeCapacitySnapshot before, NodeAccess access, long deadline) throws Exception {
if (before.isUnschedulable() && !before.isCloudStackResizeCordon()) return;
String node = nodeName(vm);
executeControl(access, "sudo /opt/bin/kubectl annotate node " + node + " " + RESIZE_ANNOTATION + "=" + cluster.getUuid() + " --overwrite");
executeControl(access, "sudo /opt/bin/kubectl cordon " + node);
while (System.currentTimeMillis() < deadline) {
if (nodeSnapshot(cluster, vm, access, null).isUnschedulable()) return;
sleep();
}
throw failure("CORDON", vm, "Kubernetes node did not become unschedulable");
}

@Override
public void onlineGuestResources(NodeAccess access) throws Exception {
executeNode(access, ONLINE_HOTPLUGGED_RESOURCES);
}

@Override
public void verifyGuestResources(UserVm vm, ServiceOffering target, NodeCapacitySnapshot before, NodeAccess access, long deadline) throws Exception {
while (System.currentTimeMillis() < deadline) {
if (guestMatchesTarget(guestResources(access), target)) return;
sleep();
}
throw failure("GUEST_VERIFY", vm, "guest CPU or memory did not reach the target offering");
}

@Override
public boolean isKubernetesResourcesCurrent(NodeCapacitySnapshot snapshot, ServiceOffering target) {
GuestResources guest = new GuestResources(snapshot.getGuestOnlineCpuCount(), snapshot.getGuestMemoryKiB());
return guestMatchesTarget(guest, target) && kubernetesMatchesGuest(snapshot, snapshot);
}

@Override
public void restartKubelet(UserVm vm, NodeAccess access, long deadline) throws Exception {
executeNode(access, "sudo systemctl restart kubelet");
while (System.currentTimeMillis() < deadline) {
if ("active".equals(executeNode(access, "sudo systemctl is-active kubelet").trim())) return;
sleep();
}
throw failure("KUBELET_RESTART", vm, "kubelet did not become active");
}

@Override
public NodeCapacitySnapshot waitForKubernetesResources(KubernetesCluster cluster, UserVm vm, ServiceOffering target,
NodeCapacitySnapshot before, NodeAccess access, long deadline) throws Exception {
while (System.currentTimeMillis() < deadline) {
GuestResources guest = guestResources(access);
NodeCapacitySnapshot observed = nodeSnapshot(cluster, vm, access, guest);
if (guestMatchesTarget(guest, target) && kubernetesMatchesGuest(observed, before)) return observed;
sleep();
}
throw failure("CAPACITY_VERIFY", vm, "Kubernetes capacity did not match the resized guest");
}

@Override
public void restoreSchedulability(KubernetesCluster cluster, UserVm vm, NodeCapacitySnapshot before, NodeAccess access, long deadline) throws Exception {
if (before.isUnschedulable() && !before.isCloudStackResizeCordon()) return;
String node = nodeName(vm);
executeControl(access, "sudo /opt/bin/kubectl uncordon " + node);
executeControl(access, "sudo /opt/bin/kubectl annotate node " + node + " " + RESIZE_ANNOTATION + "-");
while (System.currentTimeMillis() < deadline) {
if (!nodeSnapshot(cluster, vm, access, null).isUnschedulable()) return;
sleep();
}
throw failure("RESTORE_SCHEDULABILITY", vm, "Kubernetes node remained unschedulable");
}

public static boolean capacityChanged(ServiceOffering oldOffering, ServiceOffering targetOffering) {
return oldOffering != null && targetOffering != null
&& (!Objects.equals(oldOffering.getCpu(), targetOffering.getCpu())
|| !Objects.equals(oldOffering.getRamSize(), targetOffering.getRamSize()));
}

static long parseCpuMillis(String value) { return value.endsWith("m") ? Long.parseLong(value.substring(0, value.length() - 1)) : Long.parseLong(value) * 1000L; }
static long parseMemoryBytes(String value) {
Matcher matcher = MEMORY_QUANTITY.matcher(value);
if (!matcher.matches()) throw new IllegalArgumentException("Unsupported Kubernetes memory quantity");
long number = Long.parseLong(matcher.group(1)); String unit = matcher.group(2);

Check warning on line 144 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconcilerImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Declare "unit" on a separate line.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XoJBZ3696PvGse&open=AaDJI_XoJBZ3696PvGse&pullRequest=14223
if (unit == null) return number;
switch (unit) {
case "Ki": return number * 1024L; case "Mi": return number * 1024L * 1024L; case "Gi": return number * 1024L * 1024L * 1024L;
case "Ti": return number * 1024L * 1024L * 1024L * 1024L; case "K": return number * 1000L; case "M": return number * 1000L * 1000L;
case "G": return number * 1000L * 1000L * 1000L; case "T": return number * 1000L * 1000L * 1000L * 1000L;
default: throw new IllegalArgumentException("Unsupported Kubernetes memory quantity");
}
}

private NodeCapacitySnapshot nodeSnapshot(KubernetesCluster cluster, UserVm vm, NodeAccess access, GuestResources guest) throws Exception {
JsonObject node = new JsonParser().parse(executeControl(access, "sudo /opt/bin/kubectl get node " + nodeName(vm) + " -o json")).getAsJsonObject();
JsonObject annotations = node.getAsJsonObject("metadata").has("annotations") ? node.getAsJsonObject("metadata").getAsJsonObject("annotations") : null;
boolean cksCordon = annotations != null && annotations.has(RESIZE_ANNOTATION) && cluster.getUuid().equals(annotations.get(RESIZE_ANNOTATION).getAsString());
JsonObject spec = node.has("spec") ? node.getAsJsonObject("spec") : new JsonObject(); JsonObject status = node.getAsJsonObject("status");

Check warning on line 158 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconcilerImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Declare "status" on a separate line.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XoJBZ3696PvGsf&open=AaDJI_XoJBZ3696PvGsf&pullRequest=14223
JsonObject capacity = status.getAsJsonObject("capacity"); JsonObject allocatable = status.getAsJsonObject("allocatable");

Check warning on line 159 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconcilerImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Declare "allocatable" on a separate line.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XoJBZ3696PvGsg&open=AaDJI_XoJBZ3696PvGsg&pullRequest=14223
return new NodeCapacitySnapshot(spec.has("unschedulable") && spec.get("unschedulable").getAsBoolean(), cksCordon,
guest == null ? 0 : guest.cpu, guest == null ? 0 : guest.memoryKiB, parseCpuMillis(capacity.get("cpu").getAsString()),
parseMemoryBytes(capacity.get("memory").getAsString()), parseCpuMillis(allocatable.get("cpu").getAsString()),
parseMemoryBytes(allocatable.get("memory").getAsString()), isReady(status));
}

private boolean isReady(JsonObject status) {
JsonArray conditions = status.getAsJsonArray("conditions");
for (JsonElement condition : conditions) { JsonObject item = condition.getAsJsonObject(); if ("Ready".equals(item.get("type").getAsString()) && "True".equals(item.get("status").getAsString())) return true; }
return false;
}

private GuestResources guestResources(NodeAccess access) throws Exception {
String[] values = executeNode(access, "getconf _NPROCESSORS_ONLN; awk '/^MemTotal:/ {print $2}' /proc/meminfo").trim().split("\\s+");
if (values.length != 2) throw new CloudRuntimeException("Unable to read guest CPU and memory");
return new GuestResources(Long.parseLong(values[0]), Long.parseLong(values[1]));
}

private boolean guestMatchesTarget(GuestResources observed, ServiceOffering target) {
long targetMemory = target.getRamSize() * 1024L * 1024L; long observedMemory = observed.memoryKiB * 1024L;

Check warning on line 179 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconcilerImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Declare "observedMemory" on a separate line.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XoJBZ3696PvGsh&open=AaDJI_XoJBZ3696PvGsh&pullRequest=14223
long overhead = Math.max(targetMemory / 50L, MINIMUM_MEMORY_OVERHEAD_BYTES);
return observed.cpu == target.getCpu() && observedMemory <= targetMemory && targetMemory - observedMemory <= overhead;
}

private boolean kubernetesMatchesGuest(NodeCapacitySnapshot observed, NodeCapacitySnapshot before) {
return observed.isReady() && observed.getCapacityCpuMillis() == observed.getGuestOnlineCpuCount() * 1000L
&& Math.abs(observed.getCapacityMemoryBytes() - observed.getGuestMemoryKiB() * 1024L) <= KUBERNETES_MEMORY_REPORTING_TOLERANCE_BYTES
&& (observed.getGuestOnlineCpuCount() <= before.getGuestOnlineCpuCount() || observed.getAllocatableCpuMillis() > before.getAllocatableCpuMillis())
&& (observed.getGuestMemoryKiB() <= before.getGuestMemoryKiB() || observed.getAllocatableMemoryBytes() > before.getAllocatableMemoryBytes());
}

protected String executeControl(NodeAccess access, String command) throws Exception { return execute(access.getControlAddress(), access.getControlPort(), access, command); }
protected String executeNode(NodeAccess access, String command) throws Exception { return execute(access.getNodeAddress(), access.getNodePort(), access, command); }
private String execute(String address, int port, NodeAccess access, String command) throws Exception {
Pair<Boolean, String> result = SshHelper.sshExecute(address, port, access.getUser(), access.getSshKeyFile(), null, command, 10000, 10000, COMMAND_TIMEOUT_MS);
if (Boolean.TRUE.equals(result.first())) return StringUtils.defaultString(result.second());
throw new CloudRuntimeException("CKS live-resize command failed");
}
private String nodeName(UserVm vm) { String name = StringUtils.lowerCase(vm.getHostName()); if (!NODE_NAME.matcher(name).matches()) throw new CloudRuntimeException("Invalid Kubernetes node name for live resize"); return name; }

Check warning on line 198 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconcilerImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XoJBZ3696PvGsc&open=AaDJI_XoJBZ3696PvGsc&pullRequest=14223
private CloudRuntimeException failure(String phase, UserVm vm, String message) { return new CloudRuntimeException("CKS live resize " + phase + " failed for VM " + vm.getUuid() + ": " + message); }
private void sleep() throws InterruptedException { Thread.sleep(POLL_INTERVAL_MS); }
private static class GuestResources { private final long cpu; private final long memoryKiB; GuestResources(long cpu, long memoryKiB) { this.cpu = cpu; this.memoryKiB = memoryKiB; } }

Check warning on line 201 in plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterNodeCapacityReconcilerImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Declare "memoryKiB" on a separate line.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaDJI_XoJBZ3696PvGsi&open=AaDJI_XoJBZ3696PvGsi&pullRequest=14223
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
<bean id="kubernetesClusterVmMapDaoImpl" class="com.cloud.kubernetes.cluster.dao.KubernetesClusterVmMapDaoImpl" />
<bean id="kubernetesClusterAffinityGroupMapDaoImpl" class="com.cloud.kubernetes.cluster.dao.KubernetesClusterAffinityGroupMapDaoImpl" />
<bean id="kubernetesClusterManagerImpl" class="com.cloud.kubernetes.cluster.KubernetesClusterManagerImpl" />

<bean id="kubernetesServiceHelper" class="com.cloud.kubernetes.cluster.KubernetesServiceHelperImpl" >
<property name="name" value="KubernetesServiceHelper" />
</bean>
Expand Down
Loading
Loading