[libvirt] [PATCH v3 4/9] qemu: add helper function for querying OS info

Jonathon Jongsma posted 9 patches 5 years, 3 months ago
[libvirt] [PATCH v3 4/9] qemu: add helper function for querying OS info
Posted by Jonathon Jongsma 5 years, 3 months ago
This function queries the guest operating system information and adds
the returned information to an array of typed parameters with field
names intended to be returned in virDomainGetGuestInfo().

Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
---
 src/qemu/qemu_agent.c |  53 ++++++++++++++++++
 src/qemu/qemu_agent.h |   1 +
 tests/qemuagenttest.c | 122 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 176 insertions(+)

diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index 963a4b9359..0fcc3fdabd 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -2331,3 +2331,56 @@ qemuAgentGetUsers(qemuAgentPtr mon,
     virJSONValueFree(reply);
     return ret;
 }
+
+int
+qemuAgentGetOSInfo(qemuAgentPtr mon,
+                   virTypedParameterPtr *params,
+                   int *nparams,
+                   int *maxparams)
+{
+    int ret = -1;
+    virJSONValuePtr cmd;
+    virJSONValuePtr reply = NULL;
+    virJSONValuePtr data = NULL;
+    const char *result;
+
+    if (!(cmd = qemuAgentMakeCommand("guest-get-osinfo", NULL)))
+        return -1;
+
+    if (qemuAgentCommand(mon, cmd, &reply, true,
+                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
+        goto cleanup;
+
+    if (!(data = virJSONValueObjectGetObject(reply, "return"))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("guest-get-osinfo reply was missing return data"));
+        goto cleanup;
+    }
+
+#define OSINFO_ADD_PARAM(agent_string_, param_string_) \
+    do { \
+        if ((result = virJSONValueObjectGetString(data, agent_string_))) { \
+            if (virTypedParamsAddString(params, nparams, maxparams, \
+                                        param_string_, result) < 0) { \
+                goto cleanup; \
+            } \
+        } \
+    } while (0)
+    OSINFO_ADD_PARAM("id", "os.id");
+    OSINFO_ADD_PARAM("name", "os.name");
+    OSINFO_ADD_PARAM("pretty-name", "os.pretty-name");
+    OSINFO_ADD_PARAM("version", "os.version");
+    OSINFO_ADD_PARAM("version-id", "os.version-id");
+    OSINFO_ADD_PARAM("machine", "os.machine");
+    OSINFO_ADD_PARAM("variant", "os.variant");
+    OSINFO_ADD_PARAM("variant-id", "os.variant-id");
+    OSINFO_ADD_PARAM("kernel-release", "os.kernel-release");
+    OSINFO_ADD_PARAM("kernel-version", "os.kernel-version");
+
+    ret = 0;
+
+ cleanup:
+    virJSONValueFree(cmd);
+    virJSONValueFree(reply);
+    return ret;
+}
diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
index 05621b521a..ee019455e5 100644
--- a/src/qemu/qemu_agent.h
+++ b/src/qemu/qemu_agent.h
@@ -122,3 +122,4 @@ int qemuAgentSetUserPassword(qemuAgentPtr mon,
                              bool crypted);
 
 int qemuAgentGetUsers(qemuAgentPtr mon, virTypedParameterPtr *params, int *nparams, int *maxparams);
+int qemuAgentGetOSInfo(qemuAgentPtr mon, virTypedParameterPtr *params, int *nparams, int *maxparams);
diff --git a/tests/qemuagenttest.c b/tests/qemuagenttest.c
index f2936a59f0..489b77d403 100644
--- a/tests/qemuagenttest.c
+++ b/tests/qemuagenttest.c
@@ -1068,6 +1068,127 @@ testQemuAgentUsers(const void *data)
     return ret;
 }
 
+static const char testQemuAgentOSInfoResponse[] =
+    "{\"return\": "
+    "   {\"name\":\"CentOS Linux\", "
+    "   \"kernel-release\":\"3.10.0-862.14.4.el7.x86_64\", "
+    "   \"version\":\"7 (Core)\", "
+    "   \"pretty-name\":\"CentOS Linux 7 (Core)\", "
+    "   \"version-id\":\"7\", "
+    "   \"kernel-version\":\"#1 SMP Wed Sep 26 15:12:11 UTC 2018\", "
+    "   \"machine\":\"x86_64\", "
+    "   \"id\":\"centos\"} "
+    "}";
+
+static const char testQemuAgentOSInfoResponse2[] =
+    "{\"return\": "
+    "   {\"name\":\"Microsoft Windows\", "
+    "   \"kernel-release\":\"7601\", "
+    "   \"version\":\"Microsoft Windows 77\", "
+    "   \"variant\":\"client\", "
+    "   \"pretty-name\":\"Windows 7 Professional\", "
+    "   \"version-id\":\"\", "
+    "   \"variant-id\":\"client\", "
+    "   \"kernel-version\":\"6.1\", "
+    "   \"machine\":\"x86_64\", "
+    "   \"id\":\"mswindows\"} "
+    "}";
+
+static int
+testQemuAgentOSInfo(const void *data)
+{
+    virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
+    qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
+    virTypedParameterPtr params = NULL;
+    int nparams = 0;
+    int maxparams = 0;
+    int ret = -1;
+
+    if (!test)
+        return -1;
+
+    if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
+        goto cleanup;
+
+    if (qemuMonitorTestAddItem(test, "guest-get-osinfo",
+                               testQemuAgentOSInfoResponse) < 0)
+        goto cleanup;
+
+    /* get osinfo */
+    if (qemuAgentGetOSInfo(qemuMonitorTestGetAgent(test),
+                           &params, &nparams, &maxparams) < 0)
+        goto cleanup;
+
+    if (nparams != 8) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "Expected 8 params, got %d", nparams);
+        goto cleanup;
+    }
+#define VALIDATE_PARAM(param_name_, expected_) \
+    do { \
+        const char *value_ = NULL; \
+        if (virTypedParamsGetString(params, nparams, param_name_, &value_) < 0 || \
+            value_ == NULL) { \
+            virReportError(VIR_ERR_INTERNAL_ERROR, "missing param '%s'", param_name_); \
+            goto cleanup; \
+        } \
+        if (STRNEQ(value_, expected_)) { \
+            virReportError(VIR_ERR_INTERNAL_ERROR, \
+                           "Expected name '%s', got '%s'", expected_, value_); \
+            goto cleanup; \
+        } \
+    } while (0)
+
+    VALIDATE_PARAM("os.id", "centos");
+    VALIDATE_PARAM("os.name", "CentOS Linux");
+    VALIDATE_PARAM("os.version", "7 (Core)");
+    VALIDATE_PARAM("os.version-id", "7");
+    VALIDATE_PARAM("os.pretty-name", "CentOS Linux 7 (Core)");
+    VALIDATE_PARAM("os.kernel-release", "3.10.0-862.14.4.el7.x86_64");
+    VALIDATE_PARAM("os.kernel-version", "#1 SMP Wed Sep 26 15:12:11 UTC 2018");
+    VALIDATE_PARAM("os.machine", "x86_64");
+    virTypedParamsFree(params, nparams);
+    params = NULL;
+    nparams = 0;
+    maxparams = 0;
+
+    if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
+        goto cleanup;
+
+    if (qemuMonitorTestAddItem(test, "guest-get-osinfo",
+                               testQemuAgentOSInfoResponse2) < 0)
+        goto cleanup;
+
+    /* get users with domain */
+    if (qemuAgentGetOSInfo(qemuMonitorTestGetAgent(test),
+                           &params, &nparams, &maxparams) < 0)
+        goto cleanup;
+
+    if (nparams != 10) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "Expected 10 params, got %d", nparams);
+        goto cleanup;
+    }
+
+    VALIDATE_PARAM("os.id", "mswindows");
+    VALIDATE_PARAM("os.name", "Microsoft Windows");
+    VALIDATE_PARAM("os.pretty-name", "Windows 7 Professional");
+    VALIDATE_PARAM("os.version", "Microsoft Windows 77");
+    VALIDATE_PARAM("os.version-id", "");
+    VALIDATE_PARAM("os.variant", "client");
+    VALIDATE_PARAM("os.variant-id", "client");
+    VALIDATE_PARAM("os.kernel-release", "7601");
+    VALIDATE_PARAM("os.kernel-version", "6.1");
+    VALIDATE_PARAM("os.machine", "x86_64");
+    virTypedParamsFree(params, nparams);
+
+    ret = 0;
+
+ cleanup:
+    qemuMonitorTestFree(test);
+    return ret;
+}
+
 
 static int
 mymain(void)
@@ -1099,6 +1220,7 @@ mymain(void)
     DO_TEST(ArbitraryCommand);
     DO_TEST(GetInterfaces);
     DO_TEST(Users);
+    DO_TEST(OSInfo);
 
     DO_TEST(Timeout); /* Timeout should always be called last */
 
-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 4/9] qemu: add helper function for querying OS info
Posted by Michal Privoznik 5 years, 3 months ago
On 8/23/19 6:31 PM, Jonathon Jongsma wrote:
> This function queries the guest operating system information and adds
> the returned information to an array of typed parameters with field
> names intended to be returned in virDomainGetGuestInfo().
> 
> Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
> ---
>   src/qemu/qemu_agent.c |  53 ++++++++++++++++++
>   src/qemu/qemu_agent.h |   1 +
>   tests/qemuagenttest.c | 122 ++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 176 insertions(+)
> 
> diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
> index 963a4b9359..0fcc3fdabd 100644
> --- a/src/qemu/qemu_agent.c
> +++ b/src/qemu/qemu_agent.c
> @@ -2331,3 +2331,56 @@ qemuAgentGetUsers(qemuAgentPtr mon,
>       virJSONValueFree(reply);
>       return ret;
>   }
> +
> +int
> +qemuAgentGetOSInfo(qemuAgentPtr mon,
> +                   virTypedParameterPtr *params,
> +                   int *nparams,
> +                   int *maxparams)
> +{
> +    int ret = -1;
> +    virJSONValuePtr cmd;
> +    virJSONValuePtr reply = NULL;
> +    virJSONValuePtr data = NULL;

Again, VIR_AUTOPTR() is your friend ;-)

Long story short, VIR_AUTOFREE/VIR_AUTOPTR/VIR_AUTOUNREF()/... is our 
use of attribute(__cleanup__) which is a way of telling compiler to call 
a function once the associated variable goes out of scope. In general, 
the function can be anything, but we use it for automagic free/unref.
This way, we can drop explicit calls to virXXXFree() if the variable is 
marked as VIR_AUTO*** and thus save up a few lines.
Also, the code is more robust as there won't be any hidden path this 
forgets to 'goto cleanup' and thus causes a memleak.
It takes some time to get used to it and we still haven't converted our 
code fully (as you realized by now for sure).

Michal

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 4/9] qemu: add helper function for querying OS info
Posted by Daniel Henrique Barboza 5 years, 3 months ago

On 8/23/19 1:31 PM, Jonathon Jongsma wrote:
> This function queries the guest operating system information and adds
> the returned information to an array of typed parameters with field
> names intended to be returned in virDomainGetGuestInfo().
>
> Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
> ---

Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Tested-by: Daniel Henrique Barboza <danielhb413@gmail.com>

>   src/qemu/qemu_agent.c |  53 ++++++++++++++++++
>   src/qemu/qemu_agent.h |   1 +
>   tests/qemuagenttest.c | 122 ++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 176 insertions(+)
>
> diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
> index 963a4b9359..0fcc3fdabd 100644
> --- a/src/qemu/qemu_agent.c
> +++ b/src/qemu/qemu_agent.c
> @@ -2331,3 +2331,56 @@ qemuAgentGetUsers(qemuAgentPtr mon,
>       virJSONValueFree(reply);
>       return ret;
>   }
> +
> +int
> +qemuAgentGetOSInfo(qemuAgentPtr mon,
> +                   virTypedParameterPtr *params,
> +                   int *nparams,
> +                   int *maxparams)
> +{
> +    int ret = -1;
> +    virJSONValuePtr cmd;
> +    virJSONValuePtr reply = NULL;
> +    virJSONValuePtr data = NULL;
> +    const char *result;
> +
> +    if (!(cmd = qemuAgentMakeCommand("guest-get-osinfo", NULL)))
> +        return -1;
> +
> +    if (qemuAgentCommand(mon, cmd, &reply, true,
> +                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
> +        goto cleanup;
> +
> +    if (!(data = virJSONValueObjectGetObject(reply, "return"))) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                       _("guest-get-osinfo reply was missing return data"));
> +        goto cleanup;
> +    }
> +
> +#define OSINFO_ADD_PARAM(agent_string_, param_string_) \
> +    do { \
> +        if ((result = virJSONValueObjectGetString(data, agent_string_))) { \
> +            if (virTypedParamsAddString(params, nparams, maxparams, \
> +                                        param_string_, result) < 0) { \
> +                goto cleanup; \
> +            } \
> +        } \
> +    } while (0)
> +    OSINFO_ADD_PARAM("id", "os.id");
> +    OSINFO_ADD_PARAM("name", "os.name");
> +    OSINFO_ADD_PARAM("pretty-name", "os.pretty-name");
> +    OSINFO_ADD_PARAM("version", "os.version");
> +    OSINFO_ADD_PARAM("version-id", "os.version-id");
> +    OSINFO_ADD_PARAM("machine", "os.machine");
> +    OSINFO_ADD_PARAM("variant", "os.variant");
> +    OSINFO_ADD_PARAM("variant-id", "os.variant-id");
> +    OSINFO_ADD_PARAM("kernel-release", "os.kernel-release");
> +    OSINFO_ADD_PARAM("kernel-version", "os.kernel-version");
> +
> +    ret = 0;
> +
> + cleanup:
> +    virJSONValueFree(cmd);
> +    virJSONValueFree(reply);
> +    return ret;
> +}
> diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
> index 05621b521a..ee019455e5 100644
> --- a/src/qemu/qemu_agent.h
> +++ b/src/qemu/qemu_agent.h
> @@ -122,3 +122,4 @@ int qemuAgentSetUserPassword(qemuAgentPtr mon,
>                                bool crypted);
>   
>   int qemuAgentGetUsers(qemuAgentPtr mon, virTypedParameterPtr *params, int *nparams, int *maxparams);
> +int qemuAgentGetOSInfo(qemuAgentPtr mon, virTypedParameterPtr *params, int *nparams, int *maxparams);
> diff --git a/tests/qemuagenttest.c b/tests/qemuagenttest.c
> index f2936a59f0..489b77d403 100644
> --- a/tests/qemuagenttest.c
> +++ b/tests/qemuagenttest.c
> @@ -1068,6 +1068,127 @@ testQemuAgentUsers(const void *data)
>       return ret;
>   }
>   
> +static const char testQemuAgentOSInfoResponse[] =
> +    "{\"return\": "
> +    "   {\"name\":\"CentOS Linux\", "
> +    "   \"kernel-release\":\"3.10.0-862.14.4.el7.x86_64\", "
> +    "   \"version\":\"7 (Core)\", "
> +    "   \"pretty-name\":\"CentOS Linux 7 (Core)\", "
> +    "   \"version-id\":\"7\", "
> +    "   \"kernel-version\":\"#1 SMP Wed Sep 26 15:12:11 UTC 2018\", "
> +    "   \"machine\":\"x86_64\", "
> +    "   \"id\":\"centos\"} "
> +    "}";
> +
> +static const char testQemuAgentOSInfoResponse2[] =
> +    "{\"return\": "
> +    "   {\"name\":\"Microsoft Windows\", "
> +    "   \"kernel-release\":\"7601\", "
> +    "   \"version\":\"Microsoft Windows 77\", "
> +    "   \"variant\":\"client\", "
> +    "   \"pretty-name\":\"Windows 7 Professional\", "
> +    "   \"version-id\":\"\", "
> +    "   \"variant-id\":\"client\", "
> +    "   \"kernel-version\":\"6.1\", "
> +    "   \"machine\":\"x86_64\", "
> +    "   \"id\":\"mswindows\"} "
> +    "}";
> +
> +static int
> +testQemuAgentOSInfo(const void *data)
> +{
> +    virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
> +    qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
> +    virTypedParameterPtr params = NULL;
> +    int nparams = 0;
> +    int maxparams = 0;
> +    int ret = -1;
> +
> +    if (!test)
> +        return -1;
> +
> +    if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
> +        goto cleanup;
> +
> +    if (qemuMonitorTestAddItem(test, "guest-get-osinfo",
> +                               testQemuAgentOSInfoResponse) < 0)
> +        goto cleanup;
> +
> +    /* get osinfo */
> +    if (qemuAgentGetOSInfo(qemuMonitorTestGetAgent(test),
> +                           &params, &nparams, &maxparams) < 0)
> +        goto cleanup;
> +
> +    if (nparams != 8) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       "Expected 8 params, got %d", nparams);
> +        goto cleanup;
> +    }
> +#define VALIDATE_PARAM(param_name_, expected_) \
> +    do { \
> +        const char *value_ = NULL; \
> +        if (virTypedParamsGetString(params, nparams, param_name_, &value_) < 0 || \
> +            value_ == NULL) { \
> +            virReportError(VIR_ERR_INTERNAL_ERROR, "missing param '%s'", param_name_); \
> +            goto cleanup; \
> +        } \
> +        if (STRNEQ(value_, expected_)) { \
> +            virReportError(VIR_ERR_INTERNAL_ERROR, \
> +                           "Expected name '%s', got '%s'", expected_, value_); \
> +            goto cleanup; \
> +        } \
> +    } while (0)
> +
> +    VALIDATE_PARAM("os.id", "centos");
> +    VALIDATE_PARAM("os.name", "CentOS Linux");
> +    VALIDATE_PARAM("os.version", "7 (Core)");
> +    VALIDATE_PARAM("os.version-id", "7");
> +    VALIDATE_PARAM("os.pretty-name", "CentOS Linux 7 (Core)");
> +    VALIDATE_PARAM("os.kernel-release", "3.10.0-862.14.4.el7.x86_64");
> +    VALIDATE_PARAM("os.kernel-version", "#1 SMP Wed Sep 26 15:12:11 UTC 2018");
> +    VALIDATE_PARAM("os.machine", "x86_64");
> +    virTypedParamsFree(params, nparams);
> +    params = NULL;
> +    nparams = 0;
> +    maxparams = 0;
> +
> +    if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
> +        goto cleanup;
> +
> +    if (qemuMonitorTestAddItem(test, "guest-get-osinfo",
> +                               testQemuAgentOSInfoResponse2) < 0)
> +        goto cleanup;
> +
> +    /* get users with domain */
> +    if (qemuAgentGetOSInfo(qemuMonitorTestGetAgent(test),
> +                           &params, &nparams, &maxparams) < 0)
> +        goto cleanup;
> +
> +    if (nparams != 10) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       "Expected 10 params, got %d", nparams);
> +        goto cleanup;
> +    }
> +
> +    VALIDATE_PARAM("os.id", "mswindows");
> +    VALIDATE_PARAM("os.name", "Microsoft Windows");
> +    VALIDATE_PARAM("os.pretty-name", "Windows 7 Professional");
> +    VALIDATE_PARAM("os.version", "Microsoft Windows 77");
> +    VALIDATE_PARAM("os.version-id", "");
> +    VALIDATE_PARAM("os.variant", "client");
> +    VALIDATE_PARAM("os.variant-id", "client");
> +    VALIDATE_PARAM("os.kernel-release", "7601");
> +    VALIDATE_PARAM("os.kernel-version", "6.1");
> +    VALIDATE_PARAM("os.machine", "x86_64");
> +    virTypedParamsFree(params, nparams);
> +
> +    ret = 0;
> +
> + cleanup:
> +    qemuMonitorTestFree(test);
> +    return ret;
> +}
> +
>   
>   static int
>   mymain(void)
> @@ -1099,6 +1220,7 @@ mymain(void)
>       DO_TEST(ArbitraryCommand);
>       DO_TEST(GetInterfaces);
>       DO_TEST(Users);
> +    DO_TEST(OSInfo);
>   
>       DO_TEST(Timeout); /* Timeout should always be called last */
>   

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list