From ce4c0bf5a21e57d93415e89f4fb2b32353e161ed Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Thu, 12 Nov 2009 10:53:26 -0500 Subject: [PATCH] Add virConnectGetLibvirtVersion API There is currently no way to determine the libvirt version of a remote libvirtd we are connected to. This is a useful piece of data to enable feature detection. --- daemon/remote.c | 20 +++++++++++++ daemon/remote_dispatch_prototypes.h | 8 ++++++ daemon/remote_dispatch_ret.h | 1 + daemon/remote_dispatch_table.h | 5 ++++ include/libvirt/libvirt.h.in | 2 ++ python/generator.py | 1 + python/libvirt-override-api.xml | 5 ++++ python/libvirt-override.c | 26 +++++++++++++++++ src/driver.h | 4 +++ src/esx/esx_driver.c | 1 + src/libvirt.c | 44 +++++++++++++++++++++++++++++ src/libvirt_public.syms | 1 + src/lxc/lxc_driver.c | 1 + src/opennebula/one_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 25 ++++++++++++++++ src/remote/remote_protocol.c | 9 ++++++ src/remote/remote_protocol.h | 8 ++++++ src/remote/remote_protocol.x | 8 ++++-- src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/xen/xen_driver.c | 1 + 25 files changed, 175 insertions(+), 2 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 8dccb57641..31176153ee 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -258,6 +258,26 @@ remoteDispatchGetVersion (struct qemud_server *server ATTRIBUTE_UNUSED, return 0; } +static int +remoteDispatchGetLibVersion (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_get_lib_version_ret *ret) +{ + unsigned long libVer; + + if (virConnectGetLibVersion (conn, &libVer) == -1) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + ret->lib_ver = libVer; + return 0; +} + static int remoteDispatchGetHostname (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 7c2da07a9f..b05a9a48e5 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -466,6 +466,14 @@ static int remoteDispatchGetHostname( remote_error *err, void *args, remote_get_hostname_ret *ret); +static int remoteDispatchGetLibVersion( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + void *args, + remote_get_lib_version_ret *ret); static int remoteDispatchGetMaxVcpus( struct qemud_server *server, struct qemud_client *client, diff --git a/daemon/remote_dispatch_ret.h b/daemon/remote_dispatch_ret.h index c37744a39e..4543dc5e2f 100644 --- a/daemon/remote_dispatch_ret.h +++ b/daemon/remote_dispatch_ret.h @@ -114,3 +114,4 @@ remote_storage_pool_is_active_ret val_remote_storage_pool_is_active_ret; remote_storage_pool_is_persistent_ret val_remote_storage_pool_is_persistent_ret; remote_interface_is_active_ret val_remote_interface_is_active_ret; + remote_get_lib_version_ret val_remote_get_lib_version_ret; diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index cb640b67ca..f7c8a13ea1 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -787,3 +787,8 @@ .args_filter = (xdrproc_t) xdr_remote_interface_is_active_args, .ret_filter = (xdrproc_t) xdr_remote_interface_is_active_ret, }, +{ /* GetLibVersion => 157 */ + .fn = (dispatch_fn) remoteDispatchGetLibVersion, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_get_lib_version_ret, +}, diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 311ee838ec..5bc76947c9 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -489,6 +489,8 @@ int virConnectClose (virConnectPtr conn); const char * virConnectGetType (virConnectPtr conn); int virConnectGetVersion (virConnectPtr conn, unsigned long *hvVer); +int virConnectGetLibVersion (virConnectPtr conn, + unsigned long *libVer); char * virConnectGetHostname (virConnectPtr conn); char * virConnectGetURI (virConnectPtr conn); diff --git a/python/generator.py b/python/generator.py index 21b413772b..0b321169a0 100755 --- a/python/generator.py +++ b/python/generator.py @@ -255,6 +255,7 @@ foreign_encoding_args = ( # Class methods which are written by hand in libvir.c but the Python-level # code is still automatically generated (so they are not in skip_function()). skip_impl = ( + 'virConnectGetLibVersion', 'virConnectListDomainsID', 'virConnectListDefinedDomains', 'virConnectListNetworks', diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml index 148b89be11..4e551825c6 100644 --- a/python/libvirt-override-api.xml +++ b/python/libvirt-override-api.xml @@ -1,6 +1,11 @@ + + Returns the libvirt version of the connection host + + + Returns the list of the ID of the domains on the hypervisor diff --git a/python/libvirt-override.c b/python/libvirt-override.c index 6c6155b9f2..20037efc5c 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -728,6 +728,31 @@ libvirt_virGetVersion (PyObject *self ATTRIBUTE_UNUSED, PyObject *args) return Py_BuildValue ((char *) "kk", libVer, typeVer); } +static PyObject * +libvirt_virConnectGetLibVersion (PyObject *self ATTRIBUTE_UNUSED, + PyObject *args) +{ + unsigned long libVer; + int c_retval; + virConnectPtr conn; + PyObject *pyobj_conn; + + if (!PyArg_ParseTuple(args, (char *)"O:virConnectGetLibVersion", + &pyobj_conn)) + return(NULL); + conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); + + LIBVIRT_BEGIN_ALLOW_THREADS; + + c_retval = virConnectGetLibVersion(conn, &libVer); + + LIBVIRT_END_ALLOW_THREADS; + + if (c_retval == -1) + return VIR_PY_INT_FAIL; + + return PyInt_FromLong (libVer); +} static PyObject * libvirt_virConnectListDomainsID(PyObject *self ATTRIBUTE_UNUSED, @@ -2398,6 +2423,7 @@ libvirt_virEventInvokeTimeoutCallback(PyObject *self ATTRIBUTE_UNUSED, static PyMethodDef libvirtMethods[] = { #include "libvirt-export.c" {(char *) "virGetVersion", libvirt_virGetVersion, METH_VARARGS, NULL}, + {(char *) "virConnectGetLibVersion", libvirt_virConnectGetLibVersion, METH_VARARGS, NULL}, {(char *) "virConnectOpenAuth", libvirt_virConnectOpenAuth, METH_VARARGS, NULL}, {(char *) "virConnectListDomainsID", libvirt_virConnectListDomainsID, METH_VARARGS, NULL}, {(char *) "virConnectListDefinedDomains", libvirt_virConnectListDefinedDomains, METH_VARARGS, NULL}, diff --git a/src/driver.h b/src/driver.h index a9fedc2d31..09ce8e2387 100644 --- a/src/driver.h +++ b/src/driver.h @@ -71,6 +71,9 @@ typedef const char * typedef int (*virDrvGetVersion) (virConnectPtr conn, unsigned long *hvVer); +typedef int + (*virDrvGetLibVersion) (virConnectPtr conn, + unsigned long *libVer); typedef char * (*virDrvGetHostname) (virConnectPtr conn); typedef char * @@ -366,6 +369,7 @@ struct _virDriver { virDrvDrvSupportsFeature supports_feature; virDrvGetType type; virDrvGetVersion version; + virDrvGetLibVersion libvirtVersion; virDrvGetHostname getHostname; virDrvGetMaxVcpus getMaxVcpus; virDrvNodeGetInfo nodeGetInfo; diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 43776c04a3..fe75aa352c 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -3359,6 +3359,7 @@ static virDriver esxDriver = { esxSupportsFeature, /* supports_feature */ esxGetType, /* type */ esxGetVersion, /* version */ + NULL, /* libvirtVersion (impl. in libvirt.c) */ esxGetHostname, /* hostname */ NULL, /* getMaxVcpus */ esxNodeGetInfo, /* nodeGetInfo */ diff --git a/src/libvirt.c b/src/libvirt.c index 4598f26ce0..05e45f35f0 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -1439,6 +1439,50 @@ error: return -1; } +/** + * virConnectGetLibVersion: + * @conn: pointer to the hypervisor connection + * @libVer: returns the libvirt library version used on the connection (OUT) + * + * Provides @libVer, which is the version of libvirt used by the + * daemon running on the @conn host + * + * Returns -1 in case of failure, 0 otherwise, and values for @libVer have + * the format major * 1,000,000 + minor * 1,000 + release. + */ +int +virConnectGetLibVersion(virConnectPtr conn, unsigned long *libVer) +{ + int ret = -1; + DEBUG("conn=%p, libVir=%p", conn, libVer); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return -1; + } + + if (libVer == NULL) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (conn->driver->libvirtVersion) { + ret = conn->driver->libvirtVersion(conn, libVer); + if (ret < 0) + goto error; + return ret; + } + + *libVer = LIBVIR_VERSION_NUMBER; + ret = 0; +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return ret; +} + /** * virConnectGetHostname: * @conn: pointer to a hypervisor connection diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 739f8b0ab7..b4f57e77b1 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -331,6 +331,7 @@ LIBVIRT_0.7.2 { LIBVIRT_0.7.3 { global: + virConnectGetLibVersion; virConnectIsEncrypted; virConnectIsSecure; virDomainIsActive; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 7af4161fb8..d0fc01a316 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2337,6 +2337,7 @@ static virDriver lxcDriver = { NULL, /* supports_feature */ NULL, /* type */ lxcVersion, /* version */ + NULL, /* libvirtVersion (impl. in libvirt.c) */ virGetHostname, /* getHostname */ NULL, /* getMaxVcpus */ nodeGetInfo, /* nodeGetInfo */ diff --git a/src/opennebula/one_driver.c b/src/opennebula/one_driver.c index 4ecb81ef30..4857f54048 100644 --- a/src/opennebula/one_driver.c +++ b/src/opennebula/one_driver.c @@ -715,6 +715,7 @@ static virDriver oneDriver = { NULL, /* supports_feature */ NULL, /* type */ oneVersion, /* version */ + NULL, /* libvirtVersion (impl. in libvirt.c) */ NULL, /* getHostname */ NULL, /* getMaxVcpus */ NULL, /* nodeGetInfo */ diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 75b807aa50..aac2eb8056 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1468,6 +1468,7 @@ static virDriver openvzDriver = { NULL, /* supports_feature */ openvzGetType, /* type */ openvzGetVersion, /* version */ + NULL, /* libvirtVersion (impl. in libvirt.c) */ NULL, /* getHostname */ openvzGetMaxVCPUs, /* getMaxVcpus */ nodeGetInfo, /* nodeGetInfo */ diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index c73834cc99..ea9555aa0f 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -1584,6 +1584,7 @@ virDriver phypDriver = { NULL, /* supports_feature */ NULL, /* type */ NULL, /* version */ + NULL, /* libvirtVersion (impl. in libvirt.c) */ NULL, /* getHostname */ NULL, /* getMaxVcpus */ NULL, /* nodeGetInfo */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b023902202..968118ecaa 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7485,6 +7485,7 @@ static virDriver qemuDriver = { qemudSupportsFeature, /* supports_feature */ qemudGetType, /* type */ qemudGetVersion, /* version */ + NULL, /* libvirtVersion (impl. in libvirt.c) */ virGetHostname, /* getHostname */ qemudGetMaxVCPUs, /* getMaxVcpus */ nodeGetInfo, /* nodeGetInfo */ diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 71678942de..ecc0c17fc0 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1550,6 +1550,30 @@ done: return rv; } +static int +remoteGetLibVersion (virConnectPtr conn, unsigned long *libVer) +{ + int rv = -1; + remote_get_lib_version_ret ret; + struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); + + memset (&ret, 0, sizeof ret); + if (call (conn, priv, 0, REMOTE_PROC_GET_LIB_VERSION, + (xdrproc_t) xdr_void, (char *) NULL, + (xdrproc_t) xdr_remote_get_lib_version_ret, + (char *) &ret) == -1) + goto done; + + if (libVer) *libVer = ret.lib_ver; + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + static char * remoteGetHostname (virConnectPtr conn) { @@ -8740,6 +8764,7 @@ static virDriver remote_driver = { remoteSupportsFeature, /* supports_feature */ remoteType, /* type */ remoteGetVersion, /* version */ + remoteGetLibVersion, /* libvirtVersion */ remoteGetHostname, /* getHostname */ remoteGetMaxVcpus, /* getMaxVcpus */ remoteNodeGetInfo, /* nodeGetInfo */ diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 939bb4e2c1..a10558a1ba 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -308,6 +308,15 @@ xdr_remote_get_version_ret (XDR *xdrs, remote_get_version_ret *objp) return TRUE; } +bool_t +xdr_remote_get_lib_version_ret (XDR *xdrs, remote_get_lib_version_ret *objp) +{ + + if (!xdr_int64_t (xdrs, &objp->lib_ver)) + return FALSE; + return TRUE; +} + bool_t xdr_remote_get_hostname_ret (XDR *xdrs, remote_get_hostname_ret *objp) { diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index 885695c39e..2ba9be42c2 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -179,6 +179,11 @@ struct remote_get_version_ret { }; typedef struct remote_get_version_ret remote_get_version_ret; +struct remote_get_lib_version_ret { + int64_t lib_ver; +}; +typedef struct remote_get_lib_version_ret remote_get_lib_version_ret; + struct remote_get_hostname_ret { remote_nonnull_string hostname; }; @@ -1771,6 +1776,7 @@ enum remote_procedure { REMOTE_PROC_STORAGE_POOL_IS_ACTIVE = 154, REMOTE_PROC_STORAGE_POOL_IS_PERSISTENT = 155, REMOTE_PROC_INTERFACE_IS_ACTIVE = 156, + REMOTE_PROC_GET_LIB_VERSION = 157, }; typedef enum remote_procedure remote_procedure; @@ -1828,6 +1834,7 @@ extern bool_t xdr_remote_supports_feature_args (XDR *, remote_supports_feature_ extern bool_t xdr_remote_supports_feature_ret (XDR *, remote_supports_feature_ret*); extern bool_t xdr_remote_get_type_ret (XDR *, remote_get_type_ret*); extern bool_t xdr_remote_get_version_ret (XDR *, remote_get_version_ret*); +extern bool_t xdr_remote_get_lib_version_ret (XDR *, remote_get_lib_version_ret*); extern bool_t xdr_remote_get_hostname_ret (XDR *, remote_get_hostname_ret*); extern bool_t xdr_remote_get_uri_ret (XDR *, remote_get_uri_ret*); extern bool_t xdr_remote_get_max_vcpus_args (XDR *, remote_get_max_vcpus_args*); @@ -2098,6 +2105,7 @@ extern bool_t xdr_remote_supports_feature_args (); extern bool_t xdr_remote_supports_feature_ret (); extern bool_t xdr_remote_get_type_ret (); extern bool_t xdr_remote_get_version_ret (); +extern bool_t xdr_remote_get_lib_version_ret (); extern bool_t xdr_remote_get_hostname_ret (); extern bool_t xdr_remote_get_uri_ret (); extern bool_t xdr_remote_get_max_vcpus_args (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 1886282a0d..92f7010f79 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -302,6 +302,10 @@ struct remote_get_version_ret { hyper hv_ver; }; +struct remote_get_lib_version_ret { + hyper lib_ver; +}; + struct remote_get_hostname_ret { remote_nonnull_string hostname; }; @@ -1606,8 +1610,8 @@ enum remote_procedure { REMOTE_PROC_NETWORK_IS_PERSISTENT = 153, REMOTE_PROC_STORAGE_POOL_IS_ACTIVE = 154, REMOTE_PROC_STORAGE_POOL_IS_PERSISTENT = 155, - REMOTE_PROC_INTERFACE_IS_ACTIVE = 156 - + REMOTE_PROC_INTERFACE_IS_ACTIVE = 156, + REMOTE_PROC_GET_LIB_VERSION = 157 /* * Notice how the entries are grouped in sets of 10 ? diff --git a/src/test/test_driver.c b/src/test/test_driver.c index e882f0ca96..d03d55d560 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5167,6 +5167,7 @@ static virDriver testDriver = { NULL, /* supports_feature */ NULL, /* type */ testGetVersion, /* version */ + NULL, /* libvirtVersion (impl. in libvirt.c) */ virGetHostname, /* getHostname */ testGetMaxVCPUs, /* getMaxVcpus */ testNodeGetInfo, /* nodeGetInfo */ diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 5e8aa58921..7ef5a0b47a 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -1822,6 +1822,7 @@ static virDriver umlDriver = { NULL, /* supports_feature */ umlGetType, /* type */ umlGetVersion, /* version */ + NULL, /* libvirtVersion (impl. in libvirt.c) */ virGetHostname, /* getHostname */ NULL, /* getMaxVcpus */ nodeGetInfo, /* nodeGetInfo */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 8154f71302..cd60b729ce 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -6500,6 +6500,7 @@ virDriver NAME(Driver) = { NULL, /* supports_feature */ NULL, /* type */ vboxGetVersion, /* version */ + NULL, /* libvirtVersion (impl. in libvirt.c) */ virGetHostname, /* getHostname */ vboxGetMaxVcpus, /* getMaxVcpus */ nodeGetInfo, /* nodeGetInfo */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 80e81326ff..4bfcce4eee 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -1794,6 +1794,7 @@ static virDriver xenUnifiedDriver = { xenUnifiedSupportsFeature, /* supports_feature */ xenUnifiedType, /* type */ xenUnifiedGetVersion, /* version */ + NULL, /* libvirtVersion (impl. in libvirt.c) */ virGetHostname, /* getHostname */ xenUnifiedGetMaxVcpus, /* getMaxVcpus */ xenUnifiedNodeGetInfo, /* nodeGetInfo */