diff --git a/org.jdrupes.vmoperator.manager/build.gradle b/org.jdrupes.vmoperator.manager/build.gradle index a4c302e..ab41391 100644 --- a/org.jdrupes.vmoperator.manager/build.gradle +++ b/org.jdrupes.vmoperator.manager/build.gradle @@ -17,7 +17,7 @@ dependencies { implementation 'org.jgrapes:org.jgrapes.io:[2.12.1,3)' implementation 'org.jgrapes:org.jgrapes.http:[3.5.0,4)' - implementation 'org.jgrapes:org.jgrapes.webconsole.base:[1.8.0,2)' + implementation 'org.jgrapes:org.jgrapes.webconsole.base:[2.1.0,3)' implementation 'org.jgrapes:org.jgrapes.webconsole.vuejs:[1.5.0,2)' implementation 'org.jgrapes:org.jgrapes.webconsole.rbac:[1.4.0,2)' implementation 'org.jgrapes:org.jgrapes.webconlet.oidclogin:[1.7.0,2)' diff --git a/org.jdrupes.vmoperator.manager/test/org/jdrupes/vmoperator/manager/BasicTests.java b/org.jdrupes.vmoperator.manager/test/org/jdrupes/vmoperator/manager/BasicTests.java index bd5fb54..bd479d0 100644 --- a/org.jdrupes.vmoperator.manager/test/org/jdrupes/vmoperator/manager/BasicTests.java +++ b/org.jdrupes.vmoperator.manager/test/org/jdrupes/vmoperator/manager/BasicTests.java @@ -3,22 +3,18 @@ package org.jdrupes.vmoperator.manager; import io.kubernetes.client.Discovery.APIResource; import io.kubernetes.client.openapi.ApiException; import io.kubernetes.client.util.generic.options.ListOptions; - import java.io.FileReader; import java.io.IOException; import java.util.Map; - import static org.jdrupes.vmoperator.common.Constants.APP_NAME; import static org.jdrupes.vmoperator.common.Constants.VM_OP_GROUP; import static org.jdrupes.vmoperator.common.Constants.VM_OP_KIND_VM; import static org.jdrupes.vmoperator.common.Constants.VM_OP_NAME; - import org.jdrupes.vmoperator.common.K8s; import org.jdrupes.vmoperator.common.K8sClient; import org.jdrupes.vmoperator.common.K8sDynamicStub; import org.jdrupes.vmoperator.common.K8sV1ConfigMapStub; import org.jdrupes.vmoperator.common.K8sV1DeploymentStub; -import org.jdrupes.vmoperator.common.K8sV1PodStub; import org.jdrupes.vmoperator.common.K8sV1PvcStub; import org.junit.jupiter.api.AfterAll; import static org.junit.jupiter.api.Assertions.*; diff --git a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/QemuMonitor.java b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/QemuMonitor.java index f59375c..7cac734 100644 --- a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/QemuMonitor.java +++ b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/QemuMonitor.java @@ -238,6 +238,8 @@ public class QemuMonitor extends Component { * @param event the event */ @Handler + @SuppressWarnings({ "PMD.AvoidSynchronizedStatement", + "PMD.AvoidDuplicateLiterals" }) public void onClosed(Closed event, SocketIOChannel channel) { channel.associated(QemuMonitor.class).ifPresent(qm -> { monitorChannel = null; @@ -259,7 +261,8 @@ public class QemuMonitor extends Component { * @param event the event */ @Handler - @SuppressWarnings("PMD.AvoidLiteralsInIfCondition") + @SuppressWarnings({ "PMD.AvoidLiteralsInIfCondition", + "PMD.AvoidSynchronizedStatement" }) public void onExecQmpCommand(MonitorCommand event) { var command = event.command(); logger.fine(() -> "monitor(out): " + command.toString()); @@ -290,6 +293,7 @@ public class QemuMonitor extends Component { * @param event the event */ @Handler(priority = 100) + @SuppressWarnings("PMD.AvoidSynchronizedStatement") public void onStop(Stop event) { if (monitorChannel != null) { // We have a connection to Qemu, attempt ACPI shutdown. @@ -321,6 +325,7 @@ public class QemuMonitor extends Component { * @param event the event */ @Handler + @SuppressWarnings("PMD.AvoidSynchronizedStatement") public void onPowerdownEvent(PowerdownEvent event) { synchronized (this) { // Cancel confirmation timeout @@ -349,6 +354,7 @@ public class QemuMonitor extends Component { * @param event the event */ @Handler + @SuppressWarnings("PMD.AvoidSynchronizedStatement") public void onConfigureQemu(ConfigureQemu event) { int newTimeout = event.configuration().vm.powerdownTimeout; if (powerdownTimeout != newTimeout) { diff --git a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Runner.java b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Runner.java index c837537..0b6e22e 100644 --- a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Runner.java +++ b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Runner.java @@ -41,8 +41,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.time.Instant; import java.util.Comparator; +import java.util.EnumSet; import java.util.HashMap; -import java.util.HashSet; import java.util.Optional; import java.util.Set; import java.util.logging.Level; @@ -227,7 +227,7 @@ public class Runner extends Component { CloudInit } - private final Set qemuLatch = new HashSet<>(); + private final Set qemuLatch = EnumSet.noneOf(QemuPreps.class); /** * Instantiates a new runner. @@ -483,6 +483,7 @@ public class Runner extends Component { mayBeStartQemu(QemuPreps.Config); } + @SuppressWarnings("PMD.AvoidSynchronizedStatement") private void mayBeStartQemu(QemuPreps done) { synchronized (qemuLatch) { if (qemuLatch.isEmpty()) { diff --git a/org.jdrupes.vmoperator.vmconlet/build.gradle b/org.jdrupes.vmoperator.vmconlet/build.gradle index 3f1f18e..4056256 100644 --- a/org.jdrupes.vmoperator.vmconlet/build.gradle +++ b/org.jdrupes.vmoperator.vmconlet/build.gradle @@ -5,7 +5,7 @@ plugins { dependencies { implementation project(':org.jdrupes.vmoperator.manager.events') - implementation 'org.jgrapes:org.jgrapes.webconsole.base:[1.8.0,2)' + implementation 'org.jgrapes:org.jgrapes.webconsole.base:[2.0.0.3)' implementation 'org.jgrapes:org.jgrapes.webconsole.provider.vue:[1,2)' implementation 'org.jgrapes:org.jgrapes.webconsole.provider.jgwcvuecomponents:[1.2,2)' implementation 'org.jgrapes:org.jgrapes.webconsole.provider.chartjs:[1.2,2)' 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 b8ff79f..ea59767 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,6 +18,7 @@ package org.jdrupes.vmoperator.vmconlet; +import com.google.gson.Gson; import com.google.gson.JsonObject; import freemarker.core.ParseException; import freemarker.template.MalformedTemplateNameException; @@ -33,8 +34,6 @@ import java.time.Instant; import java.util.EnumSet; import java.util.Optional; import java.util.Set; -import org.jdrupes.json.JsonBeanDecoder; -import org.jdrupes.json.JsonDecodeException; import org.jdrupes.vmoperator.common.K8sObserver; import org.jdrupes.vmoperator.common.VmDefinitionModel; import org.jdrupes.vmoperator.manager.events.ChannelTracker; @@ -160,10 +159,9 @@ public class VmConlet extends FreeMarkerConlet { sendVmInfos = true; } if (sendVmInfos) { - for (var vmDef : channelTracker.associated()) { - var def - = JsonBeanDecoder.create(vmDef.data().toString()) - .readObject(); + 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)); } @@ -185,7 +183,7 @@ public class VmConlet extends FreeMarkerConlet { "PMD.AvoidInstantiatingObjectsInLoops", "PMD.AvoidDuplicateLiterals", "PMD.ConfusingArgumentToVarargsMethod" }) public void onVmDefChanged(VmDefChanged event, VmChannel channel) - throws JsonDecodeException, IOException { + throws IOException { var vmName = event.vmDefinition().getMetadata().getName(); if (event.type() == K8sObserver.ResponseType.DELETED) { channelTracker.remove(vmName); @@ -196,11 +194,11 @@ public class VmConlet extends FreeMarkerConlet { } } } else { - var vmDef = new VmDefinitionModel(channel.client().getJSON() - .getGson(), cleanup(event.vmDefinition().data())); + var gson = channel.client().getJSON().getGson(); + var vmDef = new VmDefinitionModel(gson, + cleanup(event.vmDefinition().data())); channelTracker.put(vmName, channel, vmDef); - var def = JsonBeanDecoder.create(vmDef.data().toString()) - .readObject(); + var def = gson.fromJson(vmDef.data(), Object.class); for (var entry : conletIdsByConsoleConnection().entrySet()) { for (String conletId : entry.getValue()) { entry.getKey().respond(new NotifyConletView(type(), @@ -346,7 +344,7 @@ public class VmConlet extends FreeMarkerConlet { ConsoleConnection channel, VmsModel conletState) throws Exception { event.stop(); - var vmName = event.params().asString(0); + String vmName = event.param(0); var vmChannel = channelTracker.channel(vmName).orElse(null); if (vmChannel == null) { return; @@ -360,12 +358,12 @@ public class VmConlet extends FreeMarkerConlet { break; case "cpus": fire(new ModifyVm(vmName, "currentCpus", - new BigDecimal(event.params().asDouble(1)).toBigInteger(), + new BigDecimal(event.param(1).toString()).toBigInteger(), vmChannel)); break; case "ram": fire(new ModifyVm(vmName, "currentRam", - new Quantity(new BigDecimal(event.params().asDouble(1)), + new Quantity(new BigDecimal(event.param(1).toString()), Format.BINARY_SI).toSuffixedString(), vmChannel)); break; diff --git a/org.jdrupes.vmoperator.vmviewer/build.gradle b/org.jdrupes.vmoperator.vmviewer/build.gradle index 3f1f18e..b5faf7c 100644 --- a/org.jdrupes.vmoperator.vmviewer/build.gradle +++ b/org.jdrupes.vmoperator.vmviewer/build.gradle @@ -5,7 +5,7 @@ plugins { dependencies { implementation project(':org.jdrupes.vmoperator.manager.events') - implementation 'org.jgrapes:org.jgrapes.webconsole.base:[1.8.0,2)' + implementation 'org.jgrapes:org.jgrapes.webconsole.base:[2.0.0,3)' implementation 'org.jgrapes:org.jgrapes.webconsole.provider.vue:[1,2)' implementation 'org.jgrapes:org.jgrapes.webconsole.provider.jgwcvuecomponents:[1.2,2)' implementation 'org.jgrapes:org.jgrapes.webconsole.provider.chartjs:[1.2,2)' diff --git a/org.jdrupes.vmoperator.vmviewer/src/org/jdrupes/vmoperator/vmviewer/VmViewer.java b/org.jdrupes.vmoperator.vmviewer/src/org/jdrupes/vmoperator/vmviewer/VmViewer.java index db89b81..59cc98f 100644 --- a/org.jdrupes.vmoperator.vmviewer/src/org/jdrupes/vmoperator/vmviewer/VmViewer.java +++ b/org.jdrupes.vmoperator.vmviewer/src/org/jdrupes/vmoperator/vmviewer/VmViewer.java @@ -25,6 +25,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSyntaxException; import freemarker.core.ParseException; import freemarker.template.MalformedTemplateNameException; import freemarker.template.Template; @@ -47,8 +48,6 @@ import java.util.ResourceBundle; import java.util.Set; import java.util.logging.Level; import org.bouncycastle.util.Objects; -import org.jdrupes.json.JsonBeanDecoder; -import org.jdrupes.json.JsonDecodeException; import org.jdrupes.vmoperator.common.K8sDynamicModel; import org.jdrupes.vmoperator.common.K8sObserver; import org.jdrupes.vmoperator.common.VmDefinitionModel; @@ -153,7 +152,7 @@ public class VmViewer extends FreeMarkerConlet { * * @param event the event */ - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "PMD.AvoidDuplicateLiterals" }) @Handler public void onConfigurationUpdate(ConfigurationUpdate event) { event.structured(componentPath()).ifPresent(c -> { @@ -419,16 +418,19 @@ public class VmViewer extends FreeMarkerConlet { if (Strings.isNullOrEmpty(model.vmName())) { return; } - channelTracker.associated(model.vmName()).ifPresent(vmDef -> { + channelTracker.value(model.vmName()).ifPresent(item -> { try { - var def = JsonBeanDecoder.create(vmDef.data().toString()) - .readObject(); - def.setField("userPermissions", + var vmDef = item.associated(); + @SuppressWarnings("unchecked") + var def = (Map) item.channel().client() + .getJSON().getGson() + .fromJson(vmDef.data().toString(), Map.class); + def.put("userPermissions", permissions(vmDef, channel.session()).stream() .map(Permission::toString).toList()); channel.respond(new NotifyConletView(type(), model.getConletId(), "updateVmDefinition", def)); - } catch (JsonDecodeException e) { + } catch (JsonSyntaxException e) { logger.log(Level.SEVERE, e, () -> "Failed to serialize VM definition"); } @@ -458,7 +460,7 @@ public class VmViewer extends FreeMarkerConlet { "PMD.AvoidInstantiatingObjectsInLoops", "PMD.AvoidDuplicateLiterals", "PMD.ConfusingArgumentToVarargsMethod" }) public void onVmDefChanged(VmDefChanged event, VmChannel channel) - throws JsonDecodeException, IOException { + throws IOException { var vmDef = new VmDefinitionModel(channel.client().getJSON() .getGson(), event.vmDefinition().data()); GsonPtr.to(vmDef.data()).to("metadata").get(JsonObject.class) @@ -547,7 +549,7 @@ public class VmViewer extends FreeMarkerConlet { private void selectVm(NotifyConletModel event, ConsoleConnection channel, ViewerModel model) throws JsonProcessingException { - model.setVmName(event.params().asString(0)); + model.setVmName(event.param(0)); String jsonState = objectMapper.writeValueAsString(model); channel.respond(new KeyValueStoreUpdate().update(storagePath( channel.session(), model.getConletId()), jsonState));