Introduce a new API to get libvirt version. It is worth noting, that
libvirt-admin and libvirt share the same version number. Unfortunately,
our existing API isn't generic enough to be used with virAdmConnectPtr
as well. Also this patch wires up this API to the virt-admin client
as a generic cmdVersion command.
---
daemon/admin_server.c | 9 ++++++
include/libvirt/libvirt-admin.h | 3 ++
po/POTFILES.in | 1 +
src/admin/admin_protocol.x | 11 ++++++-
src/libvirt-admin.c | 31 +++++++++++++++++++
src/libvirt_admin_private.syms | 1 +
src/libvirt_admin_public.syms | 1 +
src/rpc/gendispatch.pl | 11 +++++--
tools/virt-admin.c | 67 +++++++++++++++++++++++++++++++++++++++++
9 files changed, 132 insertions(+), 3 deletions(-)
diff --git a/daemon/admin_server.c b/daemon/admin_server.c
index 712a44b..189091e 100644
--- a/daemon/admin_server.c
+++ b/daemon/admin_server.c
@@ -114,4 +114,13 @@ adminDispatchConnectClose(virNetServerPtr server ATTRIBUTE_UNUSED,
return 0;
}
+static int
+adminConnectGetLibVersion(virNetDaemonPtr dmn ATTRIBUTE_UNUSED,
+ unsigned long long *libVer)
+{
+ if (libVer)
+ *libVer = LIBVIR_VERSION_NUMBER;
+ return 0;
+}
+
#include "admin_dispatch.h"
diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h
index 4539ac6..2358173 100644
--- a/include/libvirt/libvirt-admin.h
+++ b/include/libvirt/libvirt-admin.h
@@ -73,6 +73,9 @@ int virAdmConnectRegisterCloseCallback(virAdmConnectPtr conn,
int virAdmConnectUnregisterCloseCallback(virAdmConnectPtr conn,
virAdmConnectCloseFunc cb);
+int virAdmConnectGetLibVersion(virAdmConnectPtr conn,
+ unsigned long long *libVer);
+
# ifdef __cplusplus
}
# endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index d0840f4..e165a08 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,3 +1,4 @@
+daemon/admin_dispatch.h
daemon/admin_server.c
daemon/libvirtd-config.c
daemon/libvirtd.c
diff --git a/src/admin/admin_protocol.x b/src/admin/admin_protocol.x
index d0ca1a3..878983d 100644
--- a/src/admin/admin_protocol.x
+++ b/src/admin/admin_protocol.x
@@ -41,6 +41,10 @@ struct admin_connect_open_args {
unsigned int flags;
};
+struct admin_connect_get_lib_version_ret {
+ unsigned hyper libVer;
+};
+
/* Define the program number, protocol version and procedure numbers here. */
const ADMIN_PROGRAM = 0x06900690;
const ADMIN_PROTOCOL_VERSION = 1;
@@ -71,5 +75,10 @@ enum admin_procedure {
/**
* @generate: none
*/
- ADMIN_PROC_CONNECT_CLOSE = 2
+ ADMIN_PROC_CONNECT_CLOSE = 2,
+
+ /**
+ * @generate: both
+ */
+ ADMIN_PROC_CONNECT_GET_LIB_VERSION = 3
};
diff --git a/src/libvirt-admin.c b/src/libvirt-admin.c
index 9ad124e..2da3d43 100644
--- a/src/libvirt-admin.c
+++ b/src/libvirt-admin.c
@@ -604,3 +604,34 @@ int virAdmConnectUnregisterCloseCallback(virAdmConnectPtr conn,
virDispatchError(NULL);
return -1;
}
+
+/**
+ * virAdmConnectGetLibVersion:
+ * @conn: pointer to an active admin connection
+ * @libVer: stores the current remote libvirt version number
+ *
+ * Retrieves the remote side libvirt version used by the daemon. Format
+ * returned in @libVer is of a following pattern:
+ * major * 1,000,000 + minor * 1,000 + release.
+ *
+ * Returns 0 on success, -1 on failure and @libVer follows this format:
+ */
+int virAdmConnectGetLibVersion(virAdmConnectPtr conn,
+ unsigned long long *libVer)
+{
+ VIR_DEBUG("conn=%p, libVir=%p", conn, libVer);
+
+ virResetLastError();
+
+ virCheckAdmConnectReturn(conn, -1);
+ virCheckNonNullArgReturn(libVer, -1);
+
+ if (remoteAdminConnectGetLibVersion(conn, libVer) < 0)
+ goto error;
+
+ return 0;
+
+ error:
+ virDispatchError(NULL);
+ return -1;
+}
diff --git a/src/libvirt_admin_private.syms b/src/libvirt_admin_private.syms
index 401cd4e..85380dc 100644
--- a/src/libvirt_admin_private.syms
+++ b/src/libvirt_admin_private.syms
@@ -6,6 +6,7 @@
#
# admin/admin_protocol.x
+xdr_admin_connect_get_lib_version_ret;
xdr_admin_connect_open_args;
# Let emacs know we want case-insensitive sorting
diff --git a/src/libvirt_admin_public.syms b/src/libvirt_admin_public.syms
index 5b9ba51..273af4d 100644
--- a/src/libvirt_admin_public.syms
+++ b/src/libvirt_admin_public.syms
@@ -18,4 +18,5 @@ LIBVIRT_ADMIN_1.3.0 {
virAdmConnectIsAlive;
virAdmConnectRegisterCloseCallback;
virAdmConnectUnregisterCloseCallback;
+ virAdmConnectGetLibVersion;
};
diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
index b6d50f3..d5be6e8 100755
--- a/src/rpc/gendispatch.pl
+++ b/src/rpc/gendispatch.pl
@@ -50,7 +50,7 @@ my $protocol = shift or die "missing protocol argument";
my @autogen;
my $connect_ptr = $structprefix eq "admin" ? "virAdmConnectPtr" :
"virConnectPtr";
-my $prefix = ($structprefix eq "admin") ? "adm" : "vir";
+my $prefix = ($structprefix eq "admin") ? "admin" : "vir";
sub fixup_name {
my $name = shift;
@@ -125,7 +125,9 @@ sub push_privconn {
# Read the input file (usually remote_protocol.x) and form an
# opinion about the name, args and return type of each RPC.
my ($name, $ProcName, $id, $flags, %calls, @calls, %opts);
-
+#print "procprefix $procprefix\n";
+#print "structprefix $structprefix\n";
+#print "protocol $protocol\n";
my $collect_args_members = 0;
my $collect_ret_members = 0;
my $collect_opts = 0;
@@ -1401,8 +1403,13 @@ elsif ($mode eq "client") {
my $ret_name = $1;
if ($call->{ProcName} =~ m/Get(Lib)?Version/) {
+ if ($structprefix eq "admin") {
+ push(@args_list, "unsigned long long *$ret_name");
+ push(@ret_list, "*$ret_name = ret.$ret_name;");
+ } else {
push(@args_list, "unsigned long *$ret_name");
push(@ret_list, "if ($ret_name) HYPER_TO_ULONG(*$ret_name,
ret.$ret_name);");
+ }
push(@ret_list, "rv = 0;");
$single_ret_var = "int rv = -1";
$single_ret_type = "int";
diff --git a/tools/virt-admin.c b/tools/virt-admin.c
index 679ae99..0c807f2 100644
--- a/tools/virt-admin.c
+++ b/tools/virt-admin.c
@@ -143,6 +143,67 @@ vshAdmReconnect(vshControl *ctl)
disconnected = 0;
}
+/*
+ * "version" command
+ */
+static const vshCmdInfo info_version[] = {
+ {.name = "help",
+ .data = N_("show version")
+ },
+ {.name = "desc",
+ .data = N_("Display the system and also the daemon version information.")
+ },
+ {.name = NULL}
+};
+
+static bool
+cmdVersion(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+ unsigned long libVersion;
+ unsigned long long includeVersion;
+ unsigned long long daemonVersion;
+ int ret;
+ unsigned int major;
+ unsigned int minor;
+ unsigned int rel;
+ vshAdmControlPtr priv = ctl->privData;
+
+ includeVersion = LIBVIR_VERSION_NUMBER;
+ major = includeVersion / 1000000;
+ includeVersion %= 1000000;
+ minor = includeVersion / 1000;
+ rel = includeVersion % 1000;
+ vshPrint(ctl, _("Compiled against library: libvirt %d.%d.%d\n"),
+ major, minor, rel);
+
+ ret = virGetVersion(&libVersion, NULL, NULL);
+ if (ret < 0) {
+ vshError(ctl, "%s", _("failed to get the library version"));
+ return false;
+ }
+ major = libVersion / 1000000;
+ libVersion %= 1000000;
+ minor = libVersion / 1000;
+ rel = libVersion % 1000;
+ vshPrint(ctl, _("Using library: libvirt %d.%d.%d\n"),
+ major, minor, rel);
+
+ ret = virAdmConnectGetLibVersion(priv->conn, &daemonVersion);
+ if (ret < 0) {
+ vshError(ctl, "%s", _("failed to get the daemon version"));
+ } else {
+ major = daemonVersion / 1000000;
+ daemonVersion %= 1000000;
+ minor = daemonVersion / 1000;
+ rel = daemonVersion % 1000;
+ vshPrint(ctl, _("Running against daemon: %d.%d.%d\n"),
+ major, minor, rel);
+ }
+
+ return true;
+}
+
+
/* ---------------
* Command Connect
* ---------------
@@ -480,6 +541,12 @@ static const vshCmdDef vshAdmCmds[] = {
VSH_CMD_HELP,
VSH_CMD_PWD,
VSH_CMD_QUIT,
+ {.name = "version",
+ .handler = cmdVersion,
+ .opts = NULL,
+ .info = info_version,
+ .flags = 0
+ },
{.name = "connect",
.handler = cmdConnect,
.opts = opts_connect,
--
2.4.3