diff --git a/daemon/admin_server.c b/daemon/admin_server.c index 712a44beca106b51d0f753b443e1b5d7ee90c845..189091e75a150d83a1fde16226cc74b24ff3969c 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 a921b2b15cac099148ee1331740acfa0625dc1c9..ab9df96b351f5b775054aee82150c2cdff74c014 100644 --- a/include/libvirt/libvirt-admin.h +++ b/include/libvirt/libvirt-admin.h @@ -61,6 +61,9 @@ int virAdmGetVersion(unsigned long long *libVer); char *virAdmConnectGetURI(virAdmConnectPtr conn); +int virAdmConnectGetLibVersion(virAdmConnectPtr conn, + unsigned long long *libVer); + /** * virAdmConnectCloseFunc: * @conn: virAdmConnect connection diff --git a/po/POTFILES.in b/po/POTFILES.in index 669322858a1fd34fdc1f567470e291aff84f4228..9cc129f06f98ee6f0f974fcfbe1f29f275b3d879 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 d0ca1a375755dc4b10aaa6d89621777eedb3494a..878983d2ec74a88d2040c43ed1855aa379fdf61f 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/admin_protocol-structs b/src/admin_protocol-structs index 3ac31fa2532a399fcb55fe1e283fff86c247fc07..809379be349822cf7d9fedbf479f4922709d84b4 100644 --- a/src/admin_protocol-structs +++ b/src/admin_protocol-structs @@ -2,7 +2,11 @@ struct admin_connect_open_args { u_int flags; }; +struct admin_connect_get_lib_version_ret { + uint64_t libVer; +}; enum admin_procedure { ADMIN_PROC_CONNECT_OPEN = 1, ADMIN_PROC_CONNECT_CLOSE = 2, + ADMIN_PROC_CONNECT_GET_LIB_VERSION = 3, }; diff --git a/src/libvirt-admin.c b/src/libvirt-admin.c index 9a5ee303f98b2860f162f88439a610e895d59ee6..6e6da81b3f5d632ea1f85b71118c58b7ac71591d 100644 --- a/src/libvirt-admin.c +++ b/src/libvirt-admin.c @@ -523,3 +523,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 401cd4e7f4279115b86ccc3856337b129cb38447..85380dcb2fc53e0b52baed8891e189a0a5ad32ed 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 511f6ad27f8d31f2263ec6b68ef75473ad8a151a..33b1db45a31d20a4792e428e6d11010ee8a8ede1 100644 --- a/src/libvirt_admin_public.syms +++ b/src/libvirt_admin_public.syms @@ -18,6 +18,7 @@ LIBVIRT_ADMIN_1.3.0 { virAdmGetVersion; virAdmConnectIsAlive; virAdmConnectGetURI; + virAdmConnectGetLibVersion; virAdmConnectRegisterCloseCallback; virAdmConnectUnregisterCloseCallback; }; diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl index b6d50f393ba13bc3455266e62d940cb96cf6eb9b..5cfc5120b209227715562dcececce9397637d797 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; @@ -1401,8 +1401,13 @@ elsif ($mode eq "client") { my $ret_name = $1; if ($call->{ProcName} =~ m/Get(Lib)?Version/) { - push(@args_list, "unsigned long *$ret_name"); - push(@ret_list, "if ($ret_name) HYPER_TO_ULONG(*$ret_name, ret.$ret_name);"); + 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 9afb332a366cd9c61192c56082e8c1c6a6852c9e..137296357d250508b80e9a3ab2a60c153bcd3e5e 100644 --- a/tools/virt-admin.c +++ b/tools/virt-admin.c @@ -197,6 +197,67 @@ cmdURI(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) return true; } +/* + * "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 @@ -516,6 +577,12 @@ static const vshCmdDef vshAdmCmds[] = { .info = info_uri, .flags = 0 }, + {.name = "version", + .handler = cmdVersion, + .opts = NULL, + .info = info_version, + .flags = 0 + }, {.name = "connect", .handler = cmdConnect, .opts = opts_connect,