diff --git a/dev-example/vmop-agent/99-vmop-agent.rules b/dev-example/vmop-agent/99-vmop-agent.rules new file mode 100644 index 0000000..4a18472 --- /dev/null +++ b/dev-example/vmop-agent/99-vmop-agent.rules @@ -0,0 +1,2 @@ +SUBSYSTEM=="virtio-ports", ATTR{name}=="org.jdrupes.vmop_agent.0", \ + TAG+="systemd" ENV{SYSTEMD_WANTS}="vmop-agent.service" diff --git a/dev-example/vmop-agent/vmop-agent b/dev-example/vmop-agent/vmop-agent new file mode 100755 index 0000000..b3157b9 --- /dev/null +++ b/dev-example/vmop-agent/vmop-agent @@ -0,0 +1,19 @@ +#!/usr/bin/bash + +hostSerial="/dev/virtio-ports/org.jdrupes.vmop_agent.0" + +if [ ! -w "$hostSerial" ]; then + echo >&2 "Device $hostSerial not writable" + exit 1 +fi + +if ! exec {con}<>"$hostSerial"; then + echo >&2 "Cannot open device $hostSerial" + exit 1 +fi + +echo >&${con} "220 Hello" + +while read line <&${con}; do + true +done diff --git a/dev-example/vmop-agent/vmop-agent.service b/dev-example/vmop-agent/vmop-agent.service new file mode 100644 index 0000000..11c64f2 --- /dev/null +++ b/dev-example/vmop-agent/vmop-agent.service @@ -0,0 +1,15 @@ +[Unit] +Description=VM-Operator (Guest) Agent +BindsTo=dev-virtio\x2dports-org.jdrupes.vmop_agent.0.device +After=dev-virtio\x2dports-org.jdrupes.vmop_agent.0.device multi-user.target +IgnoreOnIsolate=True + +[Service] +UMask=0077 +#EnvironmentFile=/etc/sysconfig/vmop-agent +ExecStart=/usr/local/libexec/vmop-agent +Restart=always +RestartSec=0 + +[Install] +WantedBy=dev-virtio\x2dports-org.jdrupes.vmop_agent.0.device diff --git a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/StatusUpdater.java b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/StatusUpdater.java index f9644c8..fa0e3ab 100644 --- a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/StatusUpdater.java +++ b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/StatusUpdater.java @@ -47,6 +47,7 @@ import org.jdrupes.vmoperator.runner.qemu.events.OsinfoEvent; import org.jdrupes.vmoperator.runner.qemu.events.RunnerStateChange; import org.jdrupes.vmoperator.runner.qemu.events.RunnerStateChange.RunState; import org.jdrupes.vmoperator.runner.qemu.events.ShutdownEvent; +import org.jdrupes.vmoperator.runner.qemu.events.VmopAgentConnected; import org.jdrupes.vmoperator.util.GsonPtr; import org.jgrapes.core.Channel; import org.jgrapes.core.annotation.Handler; @@ -192,20 +193,21 @@ public class StatusUpdater extends VmDefUpdater { status.addProperty("ram", GsonPtr.to(from.data()) .getAsString("spec", "vm", "maximumRam").orElse("0")); status.addProperty("cpus", 1); - - // In case we had an irregular shutdown - status.remove("osinfo"); } else if (event.runState() == RunState.STOPPED) { status.addProperty("ram", "0"); status.addProperty("cpus", 0); - status.remove("osinfo"); } - // In case console connection was still present if (!running) { + // In case console connection was still present status.addProperty("consoleClient", ""); updateCondition(from, status, "ConsoleConnected", false, - "VmStopped", "The VM has been shut down"); + "VmStopped", "The VM is not running"); + + // In case we had an irregular shutdown + status.remove("osinfo"); + updateCondition(vmDef, vmDef.statusJson(), "VmopAgentConnected", + false, "VmStopped", "The VM is not running"); } return status; }); @@ -322,4 +324,24 @@ public class StatusUpdater extends VmDefUpdater { }); } + + /** + * @param event the event + * @throws ApiException + */ + @Handler + @SuppressWarnings("PMD.AssignmentInOperand") + public void onVmopAgentConnected(VmopAgentConnected event) + throws ApiException { + VmDefinition vmDef; + if (vmStub == null || (vmDef = vmStub.model().orElse(null)) == null) { + return; + } + vmStub.updateStatus(from -> { + JsonObject status = from.statusJson(); + updateCondition(vmDef, status, "VmopAgentConnected", + true, "VmopAgentStarted", "The VM operator agent is running"); + return status; + }); + } } diff --git a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/VmopAgentClient.java b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/VmopAgentClient.java index a74432b..89fdaa2 100644 --- a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/VmopAgentClient.java +++ b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/VmopAgentClient.java @@ -19,6 +19,7 @@ package org.jdrupes.vmoperator.runner.qemu; import java.io.IOException; +import org.jdrupes.vmoperator.runner.qemu.events.VmopAgentConnected; import org.jgrapes.core.Channel; /** @@ -42,7 +43,9 @@ public class VmopAgentClient extends AgentConnector { @Override protected void processInput(String line) throws IOException { - // TODO Auto-generated method stub + if (line.startsWith("220 ")) { + rep().fire(new VmopAgentConnected()); + } } } diff --git a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/events/VmopAgentConnected.java b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/events/VmopAgentConnected.java new file mode 100644 index 0000000..dc13569 --- /dev/null +++ b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/events/VmopAgentConnected.java @@ -0,0 +1,27 @@ +/* + * VM-Operator + * Copyright (C) 2025 Michael N. Lipp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jdrupes.vmoperator.runner.qemu.events; + +import org.jgrapes.core.Event; + +/** + * Signals information about the guest OS. + */ +public class VmopAgentConnected extends Event { +}