This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch 4.19
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.19 by this push:
new 9f1b34aeb22 Fix libvirt domain event listener by properly processing
events (#8437)
9f1b34aeb22 is described below
commit 9f1b34aeb22f497dd65b2097ff970997a64a1a22
Author: Marcus Sorensen <[email protected]>
AuthorDate: Mon Feb 5 01:00:10 2024 -0700
Fix libvirt domain event listener by properly processing events (#8437)
* Fix libvirt domain event listener by properly processing events
* Add javadoc for setupEventListener
---------
Co-authored-by: Marcus Sorensen <[email protected]>
---
.../kvm/resource/LibvirtComputingResource.java | 16 +--------
.../hypervisor/kvm/resource/LibvirtConnection.java | 41 ++++++++++++++++++++++
2 files changed, 42 insertions(+), 15 deletions(-)
diff --git
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
index 60e6bcffeb6..fef5d4aa6de 100644
---
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
+++
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
@@ -85,7 +85,6 @@ import org.libvirt.DomainInfo;
import org.libvirt.DomainInfo.DomainState;
import org.libvirt.DomainInterfaceStats;
import org.libvirt.DomainSnapshot;
-import org.libvirt.Library;
import org.libvirt.LibvirtException;
import org.libvirt.MemoryStatistic;
import org.libvirt.Network;
@@ -3694,20 +3693,7 @@ public class LibvirtComputingResource extends
ServerResourceBase implements Serv
}
private void setupLibvirtEventListener() {
- final Thread libvirtListenerThread = new Thread(() -> {
- try {
- Library.runEventLoop();
- } catch (LibvirtException e) {
- s_logger.error("LibvirtException was thrown in event loop: ",
e);
- } catch (InterruptedException e) {
- s_logger.error("Libvirt event loop was interrupted: ", e);
- }
- });
-
try {
- libvirtListenerThread.setDaemon(true);
- libvirtListenerThread.start();
-
Connect conn = LibvirtConnection.getConnection();
conn.addLifecycleListener(this::onDomainLifecycleChange);
@@ -3727,7 +3713,7 @@ public class LibvirtComputingResource extends
ServerResourceBase implements Serv
* Checking for this helps us differentiate between
events where cloudstack or admin stopped the VM vs guest
* initiated, and avoid pushing extra updates for
actions we are initiating without a need for extra tracking */
DomainEventDetail detail = domainEvent.getDetail();
- if (StoppedDetail.SHUTDOWN.equals(detail) ||
StoppedDetail.CRASHED.equals(detail)) {
+ if (StoppedDetail.SHUTDOWN.equals(detail) ||
StoppedDetail.CRASHED.equals(detail) || StoppedDetail.FAILED.equals(detail)) {
s_logger.info("Triggering out of band status
update due to completed self-shutdown or crash of VM");
_agentStatusUpdater.triggerUpdate();
} else {
diff --git
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtConnection.java
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtConnection.java
index 7563f964759..1f4ab23a43f 100644
---
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtConnection.java
+++
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtConnection.java
@@ -23,6 +23,7 @@ import com.cloud.agent.properties.AgentProperties;
import com.cloud.agent.properties.AgentPropertiesFileHandler;
import org.apache.log4j.Logger;
import org.libvirt.Connect;
+import org.libvirt.Library;
import org.libvirt.LibvirtException;
import com.cloud.hypervisor.Hypervisor;
@@ -34,6 +35,7 @@ public class LibvirtConnection {
static private Connect s_connection;
static private String s_hypervisorURI;
+ static private Thread libvirtEventThread;
static public Connect getConnection() throws LibvirtException {
return getConnection(s_hypervisorURI);
@@ -45,6 +47,8 @@ public class LibvirtConnection {
if (conn == null) {
s_logger.info("No existing libvirtd connection found. Opening a
new one");
+
+ setupEventListener();
conn = new Connect(hypervisorURI, false);
s_logger.debug("Successfully connected to libvirt at: " +
hypervisorURI);
s_connections.put(hypervisorURI, conn);
@@ -53,7 +57,15 @@ public class LibvirtConnection {
conn.getVersion();
} catch (LibvirtException e) {
s_logger.error("Connection with libvirtd is broken: " +
e.getMessage());
+
+ try {
+ conn.close();
+ } catch (LibvirtException closeEx) {
+ s_logger.debug("Ignoring error while trying to close
broken connection:" + closeEx.getMessage());
+ }
+
s_logger.debug("Opening a new libvirtd connection to: " +
hypervisorURI);
+ setupEventListener();
conn = new Connect(hypervisorURI, false);
s_connections.put(hypervisorURI, conn);
}
@@ -101,4 +113,33 @@ public class LibvirtConnection {
return "qemu:///system";
}
+
+ /**
+ * Set up Libvirt event handling and polling. This is not specific to a
connection object instance, but needs
+ * to be done prior to creating connections. See the Libvirt documentation
for virEventRegisterDefaultImpl and
+ * virEventRunDefaultImpl or the libvirt-java Library Javadoc for more
information.
+ * @throws LibvirtException
+ */
+ private static synchronized void setupEventListener() throws
LibvirtException {
+ if (libvirtEventThread == null || !libvirtEventThread.isAlive()) {
+ // Registers a default event loop, must be called before
connecting to hypervisor
+ Library.initEventLoop();
+ libvirtEventThread = new Thread(() -> {
+ while (true) {
+ try {
+ // This blocking call contains a loop of its own that
will process events until the event loop is stopped or exception is thrown.
+ Library.runEventLoop();
+ } catch (LibvirtException e) {
+ s_logger.error("LibvirtException was thrown in event
loop: ", e);
+ } catch (InterruptedException e) {
+ s_logger.error("Libvirt event loop was interrupted: ",
e);
+ }
+ }
+ });
+
+ // Process events in separate thread. Failure to run event loop
regularly will cause connections to close due to keepalive timeout.
+ libvirtEventThread.setDaemon(true);
+ libvirtEventThread.start();
+ }
+ }
}