diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 66c2a0fa22..89c42d5ad8 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -3387,6 +3387,10 @@ typedef struct _virTypedParameter virMemoryParameter; */ typedef virMemoryParameter *virMemoryParameterPtr; +int virConnectSetKeepAlive(virConnectPtr conn, + int interval, + unsigned int count); + #ifdef __cplusplus } #endif diff --git a/src/driver.h b/src/driver.h index 4c14aaa8e9..4797960939 100644 --- a/src/driver.h +++ b/src/driver.h @@ -740,6 +740,10 @@ typedef int (*virDrvDomainBlockPull)(virDomainPtr dom, const char *path, unsigned long bandwidth, unsigned int flags); +typedef int + (*virDrvSetKeepAlive)(virConnectPtr conn, + int interval, + unsigned int count); /** * _virDriver: @@ -899,6 +903,7 @@ struct _virDriver { virDrvDomainGetBlockJobInfo domainGetBlockJobInfo; virDrvDomainBlockJobSetSpeed domainBlockJobSetSpeed; virDrvDomainBlockPull domainBlockPull; + virDrvSetKeepAlive setKeepAlive; }; typedef int diff --git a/src/libvirt.c b/src/libvirt.c index 87107e5645..ff14f235cf 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -17188,3 +17188,61 @@ error: virDispatchError(dom->conn); return -1; } + + +/** + * virConnectSetKeepAlive: + * @conn: pointer to a hypervisor connection + * @interval: number of seconds of inactivity before a keepalive message is sent + * @count: number of messages that can be sent in a row + * + * 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. In other words, sending count + 1 + * keepalive message results in closing the connection. When interval is <= 0, + * no keepalive messages will be sent. When count is 0, the connection will be + * automatically closed after interval seconds of inactivity without sending + * any keepalive messages. + * + * Note: 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. + * + * Returns -1 on error, 0 on success, 1 when remote party doesn't support + * keepalive messages. + */ +int virConnectSetKeepAlive(virConnectPtr conn, + int interval, + unsigned int count) +{ + int ret = -1; + + VIR_DEBUG("conn=%p, interval=%d, count=%u", conn, interval, count); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (interval <= 0) { + virLibConnError(VIR_ERR_INVALID_ARG, + _("negative or zero interval make no sense")); + goto error; + } + + if (conn->driver->setKeepAlive) { + ret = conn->driver->setKeepAlive(conn, interval, count); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return -1; +} diff --git a/src/libvirt_internal.h b/src/libvirt_internal.h index 2550d767c8..01ba6892ee 100644 --- a/src/libvirt_internal.h +++ b/src/libvirt_internal.h @@ -39,8 +39,8 @@ int virStateActive(void); * * The remote driver passes features through to the real driver at the * remote end unmodified, except if you query a VIR_DRV_FEATURE_REMOTE* - * feature. - * + * feature. Queries for VIR_DRV_FEATURE_PROGRAM* features are answered + * directly by the RPC layer and not by the real driver. */ enum { /* Driver supports V1-style virDomainMigrate, ie. domainMigratePrepare/ @@ -89,6 +89,12 @@ enum { * Support for VIR_TYPED_PARAM_STRING */ VIR_DRV_FEATURE_TYPED_PARAM_STRING = 9, + + /* + * Remote party supports keepalive program (i.e., sending keepalive + * messages). + */ + VIR_DRV_FEATURE_PROGRAM_KEEPALIVE = 10, }; diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index bcefb100f6..2331f76219 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -498,4 +498,9 @@ LIBVIRT_0.9.7 { virDomainSnapshotNumChildren; } LIBVIRT_0.9.5; +LIBVIRT_0.9.8 { + global: + virConnectSetKeepAlive; +} LIBVIRT_0.9.7; + # .... define new API here using predicted next version number .... diff --git a/src/util/event.c b/src/util/event.c index bd781eca33..495a1f3f88 100644 --- a/src/util/event.c +++ b/src/util/event.c @@ -193,9 +193,9 @@ void virEventRegisterImpl(virEventAddHandleFunc addHandle, * not have a need to integrate with an external event * loop impl. * - * Once registered, the application can invoke - * virEventRunDefaultImpl in a loop to process - * events + * Once registered, the application has to invoke virEventRunDefaultImpl in + * a loop to process events. Failure to do so may result in connections being + * closed unexpectedly as a result of keepalive timeout. * * Returns 0 on success, -1 on failure. */