diff --git a/org.jdrupes.vmoperator.vmconlet/src/org/jdrupes/vmoperator/vmconlet/VmConlet.java b/org.jdrupes.vmoperator.vmconlet/src/org/jdrupes/vmoperator/vmconlet/VmConlet.java index e8e274757..3e8d95105 100644 --- a/org.jdrupes.vmoperator.vmconlet/src/org/jdrupes/vmoperator/vmconlet/VmConlet.java +++ b/org.jdrupes.vmoperator.vmconlet/src/org/jdrupes/vmoperator/vmconlet/VmConlet.java @@ -18,8 +18,6 @@ package org.jdrupes.vmoperator.vmconlet; -import com.google.gson.Gson; -import com.google.gson.JsonObject; import freemarker.core.ParseException; import freemarker.template.MalformedTemplateNameException; import freemarker.template.Template; @@ -31,16 +29,19 @@ import java.math.BigInteger; import java.time.Duration; import java.time.Instant; +import java.util.Collections; import java.util.EnumSet; +import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import org.jdrupes.vmoperator.common.K8sObserver; -import org.jdrupes.vmoperator.common.VmDefinitionModel; +import org.jdrupes.vmoperator.common.VmDefinition; import org.jdrupes.vmoperator.manager.events.ChannelTracker; import org.jdrupes.vmoperator.manager.events.ModifyVm; import org.jdrupes.vmoperator.manager.events.VmChannel; import org.jdrupes.vmoperator.manager.events.VmDefChanged; -import org.jdrupes.vmoperator.util.GsonPtr; +import org.jdrupes.vmoperator.util.DataPath; import org.jgrapes.core.Channel; import org.jgrapes.core.Event; import org.jgrapes.core.Manager; @@ -62,13 +63,14 @@ /** * The Class VmConlet. */ -@SuppressWarnings("PMD.DataflowAnomalyAnalysis") +@SuppressWarnings({ "PMD.DataflowAnomalyAnalysis", + "PMD.CouplingBetweenObjects" }) public class VmConlet extends FreeMarkerConlet { private static final Set MODES = RenderMode.asSet( RenderMode.Preview, RenderMode.View); private final ChannelTracker channelTracker = new ChannelTracker<>(); + VmDefinition> channelTracker = new ChannelTracker<>(); private final TimeSeries summarySeries = new TimeSeries(Duration.ofDays(1)); private Summary cachedSummary; @@ -160,16 +162,40 @@ protected Set doRenderConlet(RenderConletRequestBase event, } if (sendVmInfos) { for (var item : channelTracker.values()) { - Gson gson = item.channel().client().getJSON().getGson(); - var def = gson.fromJson(item.associated().data(), Object.class); channel.respond(new NotifyConletView(type(), - conletId, "updateVm", def)); + conletId, "updateVm", + simplifiedVmDefinition(item.associated()))); } } return renderedAs; } + @SuppressWarnings("PMD.AvoidDuplicateLiterals") + private Map simplifiedVmDefinition(VmDefinition vmDef) { + // Convert RAM sizes to unitless numbers + var spec = DataPath.deepCopy(vmDef.spec()); + var vmSpec = DataPath.> get(spec, "vm").get(); + vmSpec.put("maximumRam", Quantity.fromString( + DataPath. get(vmSpec, "maximumRam").orElse("0")).getNumber() + .toBigInteger()); + vmSpec.put("currentRam", Quantity.fromString( + DataPath. get(vmSpec, "currentRam").orElse("0")).getNumber() + .toBigInteger()); + var status = DataPath.deepCopy(vmDef.status()); + status.put("ram", Quantity.fromString( + DataPath. get(status, "ram").orElse("0")).getNumber() + .toBigInteger()); + + // Build result + return Map.of("metadata", + Map.of("namespace", vmDef.namespace(), + "name", vmDef.name()), + "spec", spec, + "status", status, + "nodeName", vmDef.extra("nodeName")); + } + /** * Track the VM definitions. * @@ -184,7 +210,7 @@ protected Set doRenderConlet(RenderConletRequestBase event, "PMD.ConfusingArgumentToVarargsMethod" }) public void onVmDefChanged(VmDefChanged event, VmChannel channel) throws IOException { - var vmName = event.vmModel().getMetadata().getName(); + var vmName = event.vmDefinition().name(); if (event.type() == K8sObserver.ResponseType.DELETED) { channelTracker.remove(vmName); for (var entry : conletIdsByConsoleConnection().entrySet()) { @@ -194,15 +220,12 @@ public void onVmDefChanged(VmDefChanged event, VmChannel channel) } } } else { - var gson = channel.client().getJSON().getGson(); - var vmDef = new VmDefinitionModel(gson, - cleanup(event.vmModel().data())); + var vmDef = event.vmDefinition(); channelTracker.put(vmName, channel, vmDef); - var def = gson.fromJson(vmDef.data(), Object.class); for (var entry : conletIdsByConsoleConnection().entrySet()) { for (String conletId : entry.getValue()) { entry.getKey().respond(new NotifyConletView(type(), - conletId, "updateVm", def)); + conletId, "updateVm", simplifiedVmDefinition(vmDef))); } } } @@ -217,28 +240,6 @@ public void onVmDefChanged(VmDefChanged event, VmChannel channel) } } - @SuppressWarnings("PMD.AvoidDuplicateLiterals") - private JsonObject cleanup(JsonObject vmDef) { - // Clone and remove managed fields - var json = vmDef.deepCopy(); - GsonPtr.to(json).to("metadata").get(JsonObject.class) - .remove("managedFields"); - - // Convert RAM sizes to unitless numbers - var vmSpec = GsonPtr.to(json).to("spec", "vm"); - vmSpec.set("maximumRam", Quantity.fromString( - vmSpec.getAsString("maximumRam").orElse("0")).getNumber() - .toBigInteger()); - vmSpec.set("currentRam", Quantity.fromString( - vmSpec.getAsString("currentRam").orElse("0")).getNumber() - .toBigInteger()); - var status = GsonPtr.to(json).to("status"); - status.set("ram", Quantity.fromString( - status.getAsString("ram").orElse("0")).getNumber() - .toBigInteger()); - return json; - } - /** * Handle the periodic update event by sending {@link NotifyConletView} * events. @@ -267,10 +268,10 @@ public static class Summary { public int totalVms; /** The running vms. */ - public int runningVms; + public long runningVms; /** The used cpus. */ - public int usedCpus; + public long usedCpus; /** The used ram. */ public BigInteger usedRam = BigInteger.ZERO; @@ -289,7 +290,7 @@ public int getTotalVms() { * * @return the runningVms */ - public int getRunningVms() { + public long getRunningVms() { return runningVms; } @@ -298,7 +299,7 @@ public int getRunningVms() { * * @return the usedCpus */ - public int getUsedCpus() { + public long getUsedCpus() { return usedCpus; } @@ -313,7 +314,8 @@ public String getUsedRam() { } - @SuppressWarnings("PMD.AvoidLiteralsInIfCondition") + @SuppressWarnings({ "PMD.AvoidLiteralsInIfCondition", + "PMD.LambdaCanBeMethodReference" }) private Summary evaluateSummary(boolean force) { if (!force && cachedSummary != null) { return cachedSummary; @@ -321,18 +323,21 @@ private Summary evaluateSummary(boolean force) { Summary summary = new Summary(); for (var vmDef : channelTracker.associated()) { summary.totalVms += 1; - var status = GsonPtr.to(vmDef.data()).to("status"); - summary.usedCpus += status.getAsInt("cpus").orElse(0); - summary.usedRam = summary.usedRam.add(status.getAsString("ram") - .map(BigInteger::new).orElse(BigInteger.ZERO)); - for (var c : status.getAsListOf(JsonObject.class, "conditions")) { - if ("Running".equals(GsonPtr.to(c).getAsString("type") - .orElse(null)) - && "True".equals(GsonPtr.to(c).getAsString("status") - .orElse(null))) { - summary.runningVms += 1; - } - } + var status = vmDef.status(); + summary.usedCpus += DataPath. get(status, "cpus") + .map(Number::intValue).orElse(0); + summary.usedRam = summary.usedRam + .add(DataPath. get(status, "ram") + .map(r -> Quantity.fromString(r).getNumber().toBigInteger()) + .orElse(BigInteger.ZERO)); + summary.runningVms = DataPath + .>> get(vmDef.status(), "conditions") + .orElse(Collections.emptyList()).stream() + .filter(cond -> DataPath.get(cond, "type") + .map(t -> "Running".equals(t)).orElse(false) + && DataPath.get(cond, "status") + .map(s -> "True".equals(s)).orElse(false)) + .count(); } cachedSummary = summary; return summary;