[libvirt] [libvirt-java] [PATCH 00/12] event support

Hi. This patch series is for early review. Please comment. It's not everything set in stone already. For one, names of methods are subject to change. Claudio Bley (12): Introduce event loop support Wrap virConnectIsAlive Wrap virConnectSetKeepAlive Prepare to define proper domain event callback support. Rename method domainEventDeregisterAny to domainEventDeregister Add an internal domainEventRegister forwarding method Add constants for enum virDomainEventID Connect: overload domainEventRegister method for IOError events Connect: overload domainEventRegister method for Reboot events Connect: overload domainEventRegister method for Lifecycle events Connect: overload domainEventRegister for PMWakeup events Connect: overload domainEventRegister method for PMSuspend events src/main/java/org/libvirt/Connect.java | 367 +++++++++++++++++++++-- src/main/java/org/libvirt/Domain.java | 85 ++++++ src/main/java/org/libvirt/jna/Libvirt.java | 53 +++- src/test/java/org/libvirt/TestJavaBindings.java | 1 + 4 files changed, 482 insertions(+), 24 deletions(-) -- 1.7.9.5

Add initEventLoop() and processEvent() static methods to the Connect class. Signed-off-by: Claudio Bley <cbley@av-test.de> --- src/main/java/org/libvirt/Connect.java | 36 ++++++++++++++++++++++++++++ src/main/java/org/libvirt/jna/Libvirt.java | 4 ++++ 2 files changed, 40 insertions(+) diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index b3e29be..8da83f3 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -342,6 +342,42 @@ public class Connect { } /** + * Registers a default event implementation based on the poll() + * system call. + * <p> + * Once registered, the application has to invoke + * {@link #processEvent} in a loop to process events. + * <p> + * Note: You must call this function before connecting to the + * hypervisor. + * + * @see #processEvent + */ + public static void initEventLoop() throws LibvirtException { + if (libvirt.virEventRegisterDefaultImpl() == -1) + ErrorHandler.processError(libvirt); + } + + /** + * Run one iteration of the event loop. + * <p> + * Applications will generally want to have a thread which invokes + * this method in an infinite loop: + * <pre> + * {@code while (true) connection.processEvent(); } + * </pre> + * <p> + * Failure to do so may result in connections being closed + * unexpectedly as a result of keepalive timeout. + * + * @see #initEventLoop() + */ + public void processEvent() throws LibvirtException { + if (libvirt.virEventRunDefaultImpl() == -1) + ErrorHandler.processError(Libvirt.INSTANCE); + } + + /** * Finds a domain based on the hypervisor ID number. * * @param id diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java index 87979cd..b5e7503 100644 --- a/src/main/java/org/libvirt/jna/Libvirt.java +++ b/src/main/java/org/libvirt/jna/Libvirt.java @@ -176,6 +176,10 @@ public interface Libvirt extends Library { void virResetLastError(); void virSetErrorFunc(Pointer userData, VirErrorCallback callback); + // Event loop functions. + int virEventRegisterDefaultImpl(); + int virEventRunDefaultImpl(); + // Domain functions int virDomainAbortJob(DomainPointer virDomainPtr); int virDomainAttachDevice(DomainPointer virDomainPtr, String deviceXML); -- 1.7.9.5

This adds the isAlive() method to the Connect class. Signed-off-by: Claudio Bley <cbley@av-test.de> --- src/main/java/org/libvirt/Connect.java | 12 ++++++++++++ src/main/java/org/libvirt/jna/Libvirt.java | 1 + src/test/java/org/libvirt/TestJavaBindings.java | 1 + 3 files changed, 14 insertions(+) diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index 8da83f3..69d59b6 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -1431,4 +1431,16 @@ public class Connect { public boolean isConnected() throws LibvirtException { return ( ( VCP != null ) ? true : false ); } + + /** + * Determine if the connection to the hypervisor is still alive. + * <p> + * A connection will be classed as alive if it is either local, + * or running over a channel (TCP or UNIX socket) which is not closed. + * + * @return {@code true} if alive, {@code false} otherwise. + */ + public boolean isAlive() throws LibvirtException { + return (1 == processError(libvirt.virConnectIsAlive(VCP))); + } } diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java index b5e7503..c82ad24 100644 --- a/src/main/java/org/libvirt/jna/Libvirt.java +++ b/src/main/java/org/libvirt/jna/Libvirt.java @@ -120,6 +120,7 @@ public interface Libvirt extends Library { int virConnectDomainEventRegisterAny(ConnectionPointer virConnectPtr, DomainPointer virDomainPtr, int eventID, Libvirt.VirConnectDomainEventGenericCallback cb, Pointer opaque, Libvirt.VirFreeCallback freecb); int virConnectDomainEventDeregisterAny(ConnectionPointer virConnectPtr, int callbackID) ; void virConnSetErrorFunc(ConnectionPointer virConnectPtr, Pointer userData, VirErrorCallback callback); + int virConnectIsAlive(ConnectionPointer virConnectPtr); int virConnectIsEncrypted(ConnectionPointer virConnectPtr) ; int virConnectIsSecure(ConnectionPointer virConnectPtr) ; String virConnectFindStoragePoolSources(ConnectionPointer virConnectPtr, String type, String srcSpec, int flags); diff --git a/src/test/java/org/libvirt/TestJavaBindings.java b/src/test/java/org/libvirt/TestJavaBindings.java index bba4cdb..5e07333 100644 --- a/src/test/java/org/libvirt/TestJavaBindings.java +++ b/src/test/java/org/libvirt/TestJavaBindings.java @@ -41,6 +41,7 @@ public final class TestJavaBindings extends TestCase { assertTrue("conn.getLibVirVersion()", conn.getLibVirVersion() > 6000); assertTrue("conn.connectionVersion()", Connect.connectionVersion(conn) > 6000); assertEquals("conn.getLibVirVersion()", 2, conn.getVersion()); + assertTrue("conn.isAlive", conn.isAlive()); assertTrue("conn.isEncrypted", conn.isEncrypted() == 0); assertTrue("conn.isSecure", conn.isSecure() == 1); } -- 1.7.9.5

This adds the setKeepAlive() method to the Connect class. Signed-off-by: Claudio Bley <cbley@av-test.de> --- src/main/java/org/libvirt/Connect.java | 33 ++++++++++++++++++++++++++++ src/main/java/org/libvirt/jna/Libvirt.java | 1 + 2 files changed, 34 insertions(+) diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index 69d59b6..eecad06 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -1443,4 +1443,37 @@ public class Connect { public boolean isAlive() throws LibvirtException { return (1 == processError(libvirt.virConnectIsAlive(VCP))); } + + /** + * Start sending keepalive messages after interval second of + * inactivity and consider the connection to be broken when no + * response is received after count keepalive messages sent in a + * row. + * <p> + * In other words, sending count + 1 keepalive message results in + * closing the connection. + * <p> + * When interval is <= 0, no keepalive messages will be sent. + * <p> + * When count is 0, the connection will be automatically closed after + * interval seconds of inactivity without sending any keepalive + * messages. + * <p> + * <em>Note</em>: client has to implement and run event loop to be + * able to use keepalive messages. Failure to do so may result in + * connections being closed unexpectedly. + * <p> + * <em>Note</em>: This API function controls only keepalive messages sent by + * the client. If the server is configured to use keepalive you still + * need to run the event loop to respond to them, even if you disable + * keepalives by this function. + * + * @param interval number of seconds of inactivity before a keepalive + * message is sent + * @param count number of messages that can be sent in a row + * @return {@code true} when successful, {@code false} otherwise. + */ + public boolean setKeepAlive(int interval, int count) throws LibvirtException { + return (0 == processError(libvirt.virConnectSetKeepAlive(VCP, interval, count))); + } } diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java index c82ad24..69ec221 100644 --- a/src/main/java/org/libvirt/jna/Libvirt.java +++ b/src/main/java/org/libvirt/jna/Libvirt.java @@ -154,6 +154,7 @@ public interface Libvirt extends Library { ConnectionPointer virConnectOpen(String name); ConnectionPointer virConnectOpenAuth(String name, virConnectAuth auth, int flags); ConnectionPointer virConnectOpenReadOnly(String name); + int virConnectSetKeepAlive(ConnectionPointer virConnectPtr, int interval, int count); /** * @deprecated as of libvirt 0.6.0, all errors reported in the -- 1.7.9.5

The old wrapping was of no use since the only thing you could register was a "generic" callback. At runtime,you would have to provide a real callback function matching the prototype of the native callback type. Trying to use a generic callback instead quickly leads to failure or JVM crashes. Thus, it's safe to remove those methods now. Signed-off-by: Claudio Bley <cbley@av-test.de> --- src/main/java/org/libvirt/Connect.java | 24 ------------------------ src/main/java/org/libvirt/jna/Libvirt.java | 22 +++++++++++++++++----- 2 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index eecad06..b26fca4 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -318,30 +318,6 @@ public class Connect { } /** - * Adds a callback to receive notifications of arbitrary domain events - * occurring on a domain. - * - * @see <a - * href="http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventRegisterAny">Libvirt - * Documentation</a> - * @param domain - * option domain to limit the events monitored - * @param eventId - * the events to monitor - * @param cb - * the callback function to use. - * @return The return value from this method is a positive integer - * identifier for the callback. - * @throws LibvirtException on failure - */ - public int domainEventRegisterAny(Domain domain, int eventId, Libvirt.VirConnectDomainEventGenericCallback cb) - throws LibvirtException { - DomainPointer ptr = domain == null ? null : domain.VDP; - int returnValue = libvirt.virConnectDomainEventRegisterAny(VCP, ptr, eventId, cb, null, null); - return processError(returnValue); - } - - /** * Registers a default event implementation based on the poll() * system call. * <p> diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java index 69ec221..29db556 100644 --- a/src/main/java/org/libvirt/jna/Libvirt.java +++ b/src/main/java/org/libvirt/jna/Libvirt.java @@ -65,6 +65,19 @@ public interface Libvirt extends Library { } /** + * Domain Event Callbacks + */ + + /** + * Common Event Callback super interface. + * + * All domain event callbacks extend this interface. + * + * @see #virConnectDomainEventRegisterAny + */ + interface VirDomainEventCallback extends Callback {} + + /** * Error callback */ interface VirErrorCallback extends Callback { @@ -93,10 +106,6 @@ public interface Libvirt extends Library { void freeCallback(Pointer opaque) ; } - interface VirConnectDomainEventGenericCallback extends Callback { - void eventCallback(ConnectionPointer virConnectPtr, DomainPointer virDomainPointer, Pointer opaque) ; - } - Libvirt INSTANCE = (Libvirt) Native.loadLibrary("virt", Libvirt.class); // Constants we need @@ -117,7 +126,10 @@ public interface Libvirt extends Library { int virConnCopyLastError(ConnectionPointer virConnectPtr, virError to); int virConnectClose(ConnectionPointer virConnectPtr); int virConnectCompareCPU(ConnectionPointer virConnectPtr, String xmlDesc, int flags); - int virConnectDomainEventRegisterAny(ConnectionPointer virConnectPtr, DomainPointer virDomainPtr, int eventID, Libvirt.VirConnectDomainEventGenericCallback cb, Pointer opaque, Libvirt.VirFreeCallback freecb); + + // Register Domain Event Callbacks + int virConnectDomainEventRegisterAny(ConnectionPointer virConnectPtr, DomainPointer virDomainPtr, int eventID, VirDomainEventCallback cb, Pointer opaque, Libvirt.VirFreeCallback freecb); + int virConnectDomainEventDeregisterAny(ConnectionPointer virConnectPtr, int callbackID) ; void virConnSetErrorFunc(ConnectionPointer virConnectPtr, Pointer userData, VirErrorCallback callback); int virConnectIsAlive(ConnectionPointer virConnectPtr); -- 1.7.9.5

Change return type to void since we throw an exception on failure, otherwise it was successful. Again, this is safe because that method could hardly be used by anyone. Signed-off-by: Claudio Bley <cbley@av-test.de> --- src/main/java/org/libvirt/Connect.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index b26fca4..1b05f6f 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -307,14 +307,11 @@ public class Connect { * href="http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventDeregisterAny">Libvirt * Documentation</a> * @param callbackID - * the callback to deregister - * @return 0 on success, -1 on failure + * the callback identifier * @throws LibvirtException */ - public int domainEventDeregisterAny(int callbackID) throws LibvirtException { - int returnValue = libvirt.virConnectDomainEventDeregisterAny(VCP, callbackID); - processError(); - return returnValue; + public void domainEventDeregister(int callbackID) throws LibvirtException { + processError(libvirt.virConnectDomainEventDeregisterAny(VCP, callbackID)); } /** -- 1.7.9.5

For convenience and the sake of type safety we don't let the user deal with Libvirt.VirDomainEventCallback interfaces directly. Instead, there will be a specific interface definition for each type of callback as we soon shall see. Signed-off-by: Claudio Bley <cbley@av-test.de> --- src/main/java/org/libvirt/Connect.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index 1b05f6f..c8ae1ec 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -350,6 +350,16 @@ public class Connect { ErrorHandler.processError(Libvirt.INSTANCE); } + int domainEventRegister(Domain domain, int eventID, Libvirt.VirDomainEventCallback cb) + throws LibvirtException + { + DomainPointer ptr = domain == null ? null : domain.VDP; + + return processError(libvirt.virConnectDomainEventRegisterAny(VCP, ptr, + eventID, cb, + null, null)); + } + /** * Finds a domain based on the hypervisor ID number. * -- 1.7.9.5

Note: these are only used internally. Signed-off-by: Claudio Bley <cbley@av-test.de> --- src/main/java/org/libvirt/Connect.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index c8ae1ec..aea5e31 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -31,6 +31,25 @@ import com.sun.jna.ptr.LongByReference; public class Connect { /** + * Event IDs. + */ + protected static final class DomainEventID { + static final int LIFECYCLE = 0; + static final int REBOOT = 1; + static final int RTC_CHANGE = 2; + static final int WATCHDOG = 3; + static final int IO_ERROR = 4; + static final int GRAPHICS = 5; + static final int IO_ERROR_REASON = 6; + static final int CONTROL_ERROR = 7; + static final int BLOCK_JOB = 8; + static final int DISK_CHANGE = 9; + static final int TRAY_CHANGE = 10; + static final int PMWAKEUP = 11; + static final int PMSUSPEND = 12; + } + + /** * Get the version of a connection. * * @see <a -- 1.7.9.5

Signed-off-by: Claudio Bley <cbley@av-test.de> --- src/main/java/org/libvirt/Connect.java | 53 ++++++++++++++++++++++++++++ src/main/java/org/libvirt/Domain.java | 16 +++++++++ src/main/java/org/libvirt/jna/Libvirt.java | 8 +++++ 3 files changed, 77 insertions(+) diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index aea5e31..b7befc4 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -49,6 +49,19 @@ public class Connect { static final int PMSUSPEND = 12; } + public static abstract class DomainEvent { + /* Event Callbacks */ + + interface IOErrorCallback { + final int eventID = DomainEventID.IO_ERROR; + + void onIOError(Connect connect, Domain domain, + String srcPath, + String devAlias, + int action); + } + } + /** * Get the version of a connection. * @@ -379,6 +392,46 @@ public class Connect { null, null)); } + int domainEventRegister(Domain domain, final DomainEvent.IOErrorCallback cb) throws LibvirtException { + if (cb == null) + throw new IllegalArgumentException("IOError callback cannot be null"); + + Libvirt.VirConnectDomainEventIOErrorCallback virCB = new Libvirt.VirConnectDomainEventIOErrorCallback() { + @Override + public void eventCallback(ConnectionPointer virConnectPtr, DomainPointer virDomainPointer, + String srcPath, + String devAlias, + int action, + com.sun.jna.Pointer opaque) { + assert(VCP.equals(virConnectPtr)); + + Domain d = new Domain(Connect.this, virDomainPointer); + cb.onIOError(Connect.this, d, + srcPath, + devAlias, + action); + } + }; + + return domainEventRegister(domain, cb.eventID, virCB); + } + + /** + * Adds a callback to receive notifications of IOError domain events + * occurring on a domain. + * + * @see <a + * href="http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventRegisterAny">Libvirt + * Documentation</a> + * @param cb + * the IOErrorCallback instance + * @return The return value from this method is a positive integer identifier for the callback. + * @throws LibvirtException on failure + */ + public int domainEventRegister(final DomainEvent.IOErrorCallback cb) throws LibvirtException { + return domainEventRegister(null, cb); + } + /** * Finds a domain based on the hypervisor ID number. * diff --git a/src/main/java/org/libvirt/Domain.java b/src/main/java/org/libvirt/Domain.java index 1c86bd4..7d31326 100644 --- a/src/main/java/org/libvirt/Domain.java +++ b/src/main/java/org/libvirt/Domain.java @@ -865,6 +865,22 @@ public class Domain { } /** + * Adds a callback to receive notifications of IOError domain events + * occurring on this domain. + * + * @see <a + * href="http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventRegisterAny">Libvirt + * Documentation</a> + * @param cb + * the IOErrorCallback instance + * @return The return value from this method is a positive integer identifier for the callback. + * @throws LibvirtException on failure + */ + public int register(final Connect.DomainEvent.IOErrorCallback cb) throws LibvirtException { + return virConnect.domainEventRegister(this, cb); + } + + /** * Revert the domain to a given snapshot. * * @see <a href= diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java index 29db556..5791ee3 100644 --- a/src/main/java/org/libvirt/jna/Libvirt.java +++ b/src/main/java/org/libvirt/jna/Libvirt.java @@ -77,6 +77,14 @@ public interface Libvirt extends Library { */ interface VirDomainEventCallback extends Callback {} + interface VirConnectDomainEventIOErrorCallback extends VirDomainEventCallback { + void eventCallback(ConnectionPointer virConnectPtr, DomainPointer virDomainPointer, + String srcPath, + String devAlias, + int action, + Pointer opaque); + } + /** * Error callback */ -- 1.7.9.5

Signed-off-by: Claudio Bley <cbley@av-test.de> --- src/main/java/org/libvirt/Connect.java | 43 ++++++++++++++++++++++++++++ src/main/java/org/libvirt/Domain.java | 18 ++++++++++++ src/main/java/org/libvirt/jna/Libvirt.java | 4 +++ 3 files changed, 65 insertions(+) diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index b7befc4..380aca2 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -60,6 +60,12 @@ public class Connect { String devAlias, int action); } + + public interface RebootCallback { + final int eventID = DomainEventID.REBOOT; + + void onReboot(Connect connect, Domain domain); + } } /** @@ -432,6 +438,43 @@ public class Connect { return domainEventRegister(null, cb); } + int domainEventRegister(Domain domain, final DomainEvent.RebootCallback cb) throws LibvirtException { + if (cb == null) + throw new IllegalArgumentException("RebootCallback cannot be null"); + + Libvirt.VirConnectDomainEventGenericCallback virCB = new Libvirt.VirConnectDomainEventGenericCallback() { + @Override + public void eventCallback(ConnectionPointer virConnectPtr, + DomainPointer virDomainPointer, + com.sun.jna.Pointer opaque) + { + assert(VCP.equals(virConnectPtr)); + Domain d = new Domain(Connect.this, virDomainPointer); + cb.onReboot(Connect.this, d); + } + }; + + return domainEventRegister(domain, cb.eventID, virCB); + } + + /** + * Adds a callback to receive notifications of Reboot domain events + * occurring on an arbitrary domain. + * + * @see <a + * href="http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventRegisterAny">Libvirt + * Documentation</a> + * @param cb + * the RebootCallback instance + * @return The return value from this method is a positive integer identifier for the callback. + * @throws LibvirtException on failure + */ + public int domainEventRegister(final DomainEvent.RebootCallback cb) + throws LibvirtException + { + return domainEventRegister(null, cb); + } + /** * Finds a domain based on the hypervisor ID number. * diff --git a/src/main/java/org/libvirt/Domain.java b/src/main/java/org/libvirt/Domain.java index 7d31326..650018f 100644 --- a/src/main/java/org/libvirt/Domain.java +++ b/src/main/java/org/libvirt/Domain.java @@ -881,6 +881,24 @@ public class Domain { } /** + * Adds a callback to receive notifications of Reboot domain events + * occurring on this domain. + * + * @see <a + * href="http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventRegisterAny">Libvirt + * Documentation</a> + * @param cb + * the RebootCallback instance + * @return The return value from this method is a positive integer identifier for the callback. + * @throws LibvirtException on failure + */ + public int domainEventRegister(final Connect.DomainEvent.RebootCallback cb) + throws LibvirtException + { + return virConnect.domainEventRegister(this, cb); + } + + /** * Revert the domain to a given snapshot. * * @see <a href= diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java index 5791ee3..566cff6 100644 --- a/src/main/java/org/libvirt/jna/Libvirt.java +++ b/src/main/java/org/libvirt/jna/Libvirt.java @@ -85,6 +85,10 @@ public interface Libvirt extends Library { Pointer opaque); } + interface VirConnectDomainEventGenericCallback extends VirDomainEventCallback { + void eventCallback(ConnectionPointer virConnectPtr, DomainPointer virDomainPointer, Pointer opaque); + } + /** * Error callback */ -- 1.7.9.5

Signed-off-by: Claudio Bley <cbley@av-test.de> --- src/main/java/org/libvirt/Connect.java | 68 ++++++++++++++++++++++++++++ src/main/java/org/libvirt/Domain.java | 17 +++++++ src/main/java/org/libvirt/jna/Libvirt.java | 7 +++ 3 files changed, 92 insertions(+) diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index 380aca2..84cb0df 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -66,6 +66,27 @@ public class Connect { void onReboot(Connect connect, Domain domain); } + + /** + * @see <a href="http://libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventCallback">virConnectDomainEventCallback</a> + */ + public interface LifecycleCallback { + public static enum Event { + DEFINED, + UNDEFINED, + STARTED, + SUSPENDED, + RESUMED, + STOPPED, + SHUTDOWN; + } + + final int eventID = DomainEventID.LIFECYCLE; + + void onLifecycleChange(Connect connect, Domain domain, + Event event, + int detail); + } } /** @@ -457,6 +478,53 @@ public class Connect { return domainEventRegister(domain, cb.eventID, virCB); } + int domainEventRegister(Domain domain, final DomainEvent.LifecycleCallback cb) throws LibvirtException { + if (cb == null) + throw new IllegalArgumentException("LifecycleCallback cannot be null"); + + final DomainEvent.LifecycleCallback.Event events[] = DomainEvent.LifecycleCallback.Event.values(); + + Libvirt.VirConnectDomainEventCallback virCB = new Libvirt.VirConnectDomainEventCallback() { + @Override + public int eventCallback(ConnectionPointer virConnectPtr, DomainPointer virDomainPointer, + int event, + int detail, + com.sun.jna.Pointer opaque) + { + assert(VCP.equals(virConnectPtr)); + + if (0 <= event && event < events.length) { + Domain d = new Domain(Connect.this, virDomainPointer); + cb.onLifecycleChange(Connect.this, d, + events[event], + detail); + } else { + // TODO: throw an exception? + } + return 0; + } + }; + + return domainEventRegister(domain, cb.eventID, virCB); + } + + /** + * Adds a callback to receive notifications of domain lifecycle events + * occurring on some domain. + * + * @see <a + * href="http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventRegisterAny">Libvirt + * Documentation</a> + * @param cb + * the LifecycleCallback instance + * @return The return value from this method is a positive integer identifier for the callback. + * @throws LibvirtException on failure + */ + public int domainEventRegister(final DomainEvent.LifecycleCallback cb) throws LibvirtException + { + return domainEventRegister(null, cb); + } + /** * Adds a callback to receive notifications of Reboot domain events * occurring on an arbitrary domain. diff --git a/src/main/java/org/libvirt/Domain.java b/src/main/java/org/libvirt/Domain.java index 650018f..e6ffaa0 100644 --- a/src/main/java/org/libvirt/Domain.java +++ b/src/main/java/org/libvirt/Domain.java @@ -899,6 +899,23 @@ public class Domain { } /** + * Adds a callback to receive notifications of domain lifecycle events + * occurring on this domain. + * + * @see <a + * href="http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventRegisterAny">Libvirt + * Documentation</a> + * @param cb + * the LifecycleCallback instance + * @return The return value from this method is a positive integer identifier for the callback. + * @throws LibvirtException on failure + */ + public int register(final Connect.DomainEvent.LifecycleCallback cb) throws LibvirtException + { + return virConnect.domainEventRegister(this, cb); + } + + /** * Revert the domain to a given snapshot. * * @see <a href= diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java index 566cff6..210a471 100644 --- a/src/main/java/org/libvirt/jna/Libvirt.java +++ b/src/main/java/org/libvirt/jna/Libvirt.java @@ -89,6 +89,13 @@ public interface Libvirt extends Library { void eventCallback(ConnectionPointer virConnectPtr, DomainPointer virDomainPointer, Pointer opaque); } + interface VirConnectDomainEventCallback extends VirDomainEventCallback { + int eventCallback(ConnectionPointer virConnectPtr, DomainPointer virDomainPointer, + int event, + int detail, + Pointer opaque); + } + /** * Error callback */ -- 1.7.9.5

Signed-off-by: Claudio Bley <cbley@av-test.de> --- src/main/java/org/libvirt/Connect.java | 41 ++++++++++++++++++++++++++++ src/main/java/org/libvirt/Domain.java | 17 ++++++++++++ src/main/java/org/libvirt/jna/Libvirt.java | 6 ++++ 3 files changed, 64 insertions(+) diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index 84cb0df..50a9524 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -87,6 +87,12 @@ public class Connect { Event event, int detail); } + + public interface PMWakeupCallback { + final int eventID = DomainEventID.PMWAKEUP; + + void onPMWakeup(Connect connect, Domain domain, int reason); + } } /** @@ -525,6 +531,41 @@ public class Connect { return domainEventRegister(null, cb); } + int domainEventRegister(Domain domain, final DomainEvent.PMWakeupCallback cb) throws LibvirtException { + if (cb == null) + throw new IllegalArgumentException("PMWakeupCallback cannot be null"); + + Libvirt.VirDomainEventCallback virCB = + new Libvirt.VirConnectDomainEventPMChangeCallback() { + @Override + public void eventCallback(ConnectionPointer virConnectPtr, DomainPointer virDomainPointer, + int reason, com.sun.jna.Pointer opaque) { + assert(VCP.equals(virConnectPtr)); + Domain d = new Domain(Connect.this, virDomainPointer); + cb.onPMWakeup(Connect.this, d, reason); + } + }; + + return domainEventRegister(domain, cb.eventID, virCB); + } + + /** + * Adds a callback to receive notifications of PMWakeup events + * occurring on some domain. + * + * @see <a + * href="http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventRegisterAny">Libvirt + * Documentation</a> + * @param cb + * the PMWakeupCallback instance + * @return The return value from this method is a positive integer identifier for the callback. + * @throws LibvirtException on failure + */ + public int domainEventRegister(final DomainEvent.PMWakeupCallback cb) throws LibvirtException + { + return domainEventRegister(null, cb); + } + /** * Adds a callback to receive notifications of Reboot domain events * occurring on an arbitrary domain. diff --git a/src/main/java/org/libvirt/Domain.java b/src/main/java/org/libvirt/Domain.java index e6ffaa0..30184ad 100644 --- a/src/main/java/org/libvirt/Domain.java +++ b/src/main/java/org/libvirt/Domain.java @@ -916,6 +916,23 @@ public class Domain { } /** + * Adds a callback to receive notifications of PMWakeup events + * occurring on some domain. + * + * @see <a + * href="http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventRegisterAny">Libvirt + * Documentation</a> + * @param cb + * the PMWakeupCallback instance + * @return The return value from this method is a positive integer identifier for the callback. + * @throws LibvirtException on failure + */ + public int register(final Connect.DomainEvent.PMWakeupCallback cb) throws LibvirtException + { + return virConnect.domainEventRegister(this, cb); + } + + /** * Revert the domain to a given snapshot. * * @see <a href= diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java index 210a471..1e35202 100644 --- a/src/main/java/org/libvirt/jna/Libvirt.java +++ b/src/main/java/org/libvirt/jna/Libvirt.java @@ -96,6 +96,12 @@ public interface Libvirt extends Library { Pointer opaque); } + // PMWakeup and PMSuspend have the same callback interface. + interface VirConnectDomainEventPMChangeCallback extends VirDomainEventCallback { + void eventCallback(ConnectionPointer virConnectPtr, DomainPointer virDomainPointer, + int reason, Pointer opaque); + } + /** * Error callback */ -- 1.7.9.5

Signed-off-by: Claudio Bley <cbley@av-test.de> --- src/main/java/org/libvirt/Connect.java | 41 ++++++++++++++++++++++++++++++++ src/main/java/org/libvirt/Domain.java | 17 +++++++++++++ 2 files changed, 58 insertions(+) diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index 50a9524..99ac207 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -93,6 +93,12 @@ public class Connect { void onPMWakeup(Connect connect, Domain domain, int reason); } + + public interface PMSuspendCallback { + final int eventID = DomainEventID.PMSUSPEND; + + void onPMSuspend(Connect connect, Domain domain, int reason); + } } /** @@ -549,6 +555,41 @@ public class Connect { return domainEventRegister(domain, cb.eventID, virCB); } + int domainEventRegister(Domain domain, final DomainEvent.PMSuspendCallback cb) throws LibvirtException { + if (cb == null) + throw new IllegalArgumentException("PMSuspendCallback cannot be null"); + + Libvirt.VirDomainEventCallback virCB = + new Libvirt.VirConnectDomainEventPMChangeCallback() { + @Override + public void eventCallback(ConnectionPointer virConnectPtr, DomainPointer virDomainPointer, + int reason, com.sun.jna.Pointer opaque) { + assert(VCP.equals(virConnectPtr)); + Domain d = new Domain(Connect.this, virDomainPointer); + cb.onPMSuspend(Connect.this, d, reason); + } + }; + + return domainEventRegister(domain, cb.eventID, virCB); + } + + /** + * Adds a callback to receive notifications of PMSuspend events + * occurring on some domain. + * + * @see <a + * href="http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventRegisterAny">Libvirt + * Documentation</a> + * @param cb + * the PMSuspendCallback instance + * @return The return value from this method is a positive integer identifier for the callback. + * @throws LibvirtException on failure + */ + public int domainEventRegister(final DomainEvent.PMSuspendCallback cb) throws LibvirtException + { + return domainEventRegister(null, cb); + } + /** * Adds a callback to receive notifications of PMWakeup events * occurring on some domain. diff --git a/src/main/java/org/libvirt/Domain.java b/src/main/java/org/libvirt/Domain.java index 30184ad..87ba31c 100644 --- a/src/main/java/org/libvirt/Domain.java +++ b/src/main/java/org/libvirt/Domain.java @@ -933,6 +933,23 @@ public class Domain { } /** + * Adds a callback to receive notifications of PMSuspend events + * occurring on this domain. + * + * @see <a + * href="http://www.libvirt.org/html/libvirt-libvirt.html#virConnectDomainEventRegisterAny">Libvirt + * Documentation</a> + * @param cb + * the PMSuspendCallback instance + * @return The return value from this method is a positive integer identifier for the callback. + * @throws LibvirtException on failure + */ + public int domainEventRegister(final Connect.DomainEvent.PMSuspendCallback cb) throws LibvirtException + { + return virConnect.domainEventRegister(this, cb); + } + + /** * Revert the domain to a given snapshot. * * @see <a href= -- 1.7.9.5

At Thu, 17 Jan 2013 16:18:58 +0100, Claudio Bley wrote:
Hi.
This patch series is for early review. Please comment.
Forgot the sample code. Here it is: ,---- | package org.libvirt.sample; | | import org.libvirt.*; | | class EventSample { | volatile static boolean keepGoing = true; | | public static void main(String[] args) throws LibvirtException { | Connect c = null; | try { | Connect.initEventLoop(); | | c = new Connect("qemu:///system"); | | c.setKeepAlive(3, 10); | | int cb1 = c.domainEventRegister(new Connect.DomainEvent.LifecycleCallback() { | @Override | public void onLifecycleChange(Connect c, | Domain d, | Connect.DomainEvent.LifecycleCallback.Event event, | int detail) | { | System.out.println("lifecycle change: " + d + " " + event + " " + detail); | } | }); | | System.out.println("Press Ctrl+D to exit.\n"); | | new Thread() { | @Override | public void run() { | try { | while (System.in.read() > 0); | } catch (java.io.IOException e) {} | keepGoing = false; | } | }.start(); | | while (keepGoing && c.isAlive()) c.processEvent(); | | c.domainEventDeregister(cb1); | } finally { | if (c != null) c.close(); | } | } | } `---- Claudio -- AV-Test GmbH, Henricistraße 20, 04155 Leipzig, Germany Phone: +49 341 265 310 19 Web:<http://www.av-test.org> Eingetragen am / Registered at: Amtsgericht Stendal (HRB 114076) Geschaeftsfuehrer (CEO): Andreas Marx, Guido Habicht, Maik Morgenstern
participants (1)
-
Claudio Bley