mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
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 <mls@apple.com>
This commit is contained in:
parent
2df6802176
commit
9f1b34aeb2
@ -85,7 +85,6 @@ import org.libvirt.DomainInfo;
|
|||||||
import org.libvirt.DomainInfo.DomainState;
|
import org.libvirt.DomainInfo.DomainState;
|
||||||
import org.libvirt.DomainInterfaceStats;
|
import org.libvirt.DomainInterfaceStats;
|
||||||
import org.libvirt.DomainSnapshot;
|
import org.libvirt.DomainSnapshot;
|
||||||
import org.libvirt.Library;
|
|
||||||
import org.libvirt.LibvirtException;
|
import org.libvirt.LibvirtException;
|
||||||
import org.libvirt.MemoryStatistic;
|
import org.libvirt.MemoryStatistic;
|
||||||
import org.libvirt.Network;
|
import org.libvirt.Network;
|
||||||
@ -3694,20 +3693,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupLibvirtEventListener() {
|
private void setupLibvirtEventListener() {
|
||||||
final Thread libvirtListenerThread = new Thread(() -> {
|
|
||||||
try {
|
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();
|
Connect conn = LibvirtConnection.getConnection();
|
||||||
conn.addLifecycleListener(this::onDomainLifecycleChange);
|
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
|
* 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 */
|
* initiated, and avoid pushing extra updates for actions we are initiating without a need for extra tracking */
|
||||||
DomainEventDetail detail = domainEvent.getDetail();
|
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");
|
s_logger.info("Triggering out of band status update due to completed self-shutdown or crash of VM");
|
||||||
_agentStatusUpdater.triggerUpdate();
|
_agentStatusUpdater.triggerUpdate();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import com.cloud.agent.properties.AgentProperties;
|
|||||||
import com.cloud.agent.properties.AgentPropertiesFileHandler;
|
import com.cloud.agent.properties.AgentPropertiesFileHandler;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.libvirt.Connect;
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.Library;
|
||||||
import org.libvirt.LibvirtException;
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
import com.cloud.hypervisor.Hypervisor;
|
import com.cloud.hypervisor.Hypervisor;
|
||||||
@ -34,6 +35,7 @@ public class LibvirtConnection {
|
|||||||
|
|
||||||
static private Connect s_connection;
|
static private Connect s_connection;
|
||||||
static private String s_hypervisorURI;
|
static private String s_hypervisorURI;
|
||||||
|
static private Thread libvirtEventThread;
|
||||||
|
|
||||||
static public Connect getConnection() throws LibvirtException {
|
static public Connect getConnection() throws LibvirtException {
|
||||||
return getConnection(s_hypervisorURI);
|
return getConnection(s_hypervisorURI);
|
||||||
@ -45,6 +47,8 @@ public class LibvirtConnection {
|
|||||||
|
|
||||||
if (conn == null) {
|
if (conn == null) {
|
||||||
s_logger.info("No existing libvirtd connection found. Opening a new one");
|
s_logger.info("No existing libvirtd connection found. Opening a new one");
|
||||||
|
|
||||||
|
setupEventListener();
|
||||||
conn = new Connect(hypervisorURI, false);
|
conn = new Connect(hypervisorURI, false);
|
||||||
s_logger.debug("Successfully connected to libvirt at: " + hypervisorURI);
|
s_logger.debug("Successfully connected to libvirt at: " + hypervisorURI);
|
||||||
s_connections.put(hypervisorURI, conn);
|
s_connections.put(hypervisorURI, conn);
|
||||||
@ -53,7 +57,15 @@ public class LibvirtConnection {
|
|||||||
conn.getVersion();
|
conn.getVersion();
|
||||||
} catch (LibvirtException e) {
|
} catch (LibvirtException e) {
|
||||||
s_logger.error("Connection with libvirtd is broken: " + e.getMessage());
|
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);
|
s_logger.debug("Opening a new libvirtd connection to: " + hypervisorURI);
|
||||||
|
setupEventListener();
|
||||||
conn = new Connect(hypervisorURI, false);
|
conn = new Connect(hypervisorURI, false);
|
||||||
s_connections.put(hypervisorURI, conn);
|
s_connections.put(hypervisorURI, conn);
|
||||||
}
|
}
|
||||||
@ -101,4 +113,33 @@ public class LibvirtConnection {
|
|||||||
|
|
||||||
return "qemu:///system";
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user