[libvirt] [PATCH 3/7] qemu_agent: Implement 'guest-network-get-interfaces' command handling

Michal Privoznik mprivozn at redhat.com
Fri Jun 8 08:04:34 UTC 2012


This command returns an array of all guest interfaces among
with their IP and HW addresses.
---
 src/qemu/qemu_agent.c |  158 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_agent.h |    4 +
 2 files changed, 162 insertions(+), 0 deletions(-)

diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index bc4ceff..1a434c1 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -1370,3 +1370,161 @@ qemuAgentSuspend(qemuAgentPtr mon,
     virJSONValueFree(reply);
     return ret;
 }
+
+int
+qemuAgentGetInterfaces(qemuAgentPtr mon,
+                       virDomainInterfacePtr *ifaces,
+                       unsigned int *ifaces_count)
+{
+    int ret = -1;
+    int i, j, size = -1;
+    virJSONValuePtr cmd;
+    virJSONValuePtr reply = NULL;
+    virJSONValuePtr ret_array = NULL;
+
+    cmd = qemuAgentMakeCommand("guest-network-get-interfaces", NULL);
+
+    if (!cmd)
+        return -1;
+
+    if (qemuAgentCommand(mon, cmd, &reply) < 0 ||
+        qemuAgentCheckError(cmd, reply) < 0)
+        goto cleanup;
+
+    if (!(ret_array = virJSONValueObjectGet(reply, "return"))) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("qemu agent didn't provide 'return' field"));
+        goto cleanup;
+    }
+
+    if ((size = virJSONValueArraySize(ret_array)) < 0) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("qemu agent didn't return an array of interfaces"));
+        goto cleanup;
+    }
+
+    *ifaces_count = (unsigned int) size;
+
+    if (VIR_ALLOC_N(*ifaces, size) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    for (i = 0; i < size; i++) {
+        virJSONValuePtr tmp_iface = virJSONValueArrayGet(ret_array, i);
+        virJSONValuePtr ip_addr_arr = NULL;
+        const char *name, *hwaddr;
+        int ip_addr_arr_size;
+
+        /* Shouldn't happen but doesn't hurt to check neither */
+        if (!tmp_iface) {
+            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                            _("something has went really wrong"));
+            goto cleanup;
+        }
+
+        /* interface name is required to be presented */
+        name = virJSONValueObjectGetString(tmp_iface, "name");
+        if (!name) {
+            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                            _("qemu agent didn't provide 'name' field"));
+            goto cleanup;
+        }
+
+        if (!((*ifaces)[i].name = strdup(name))) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        /* hwaddr might be omitted */
+        hwaddr = virJSONValueObjectGetString(tmp_iface, "hardware-address");
+        if (hwaddr && !((*ifaces)[i].hwaddr = strdup(hwaddr))) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        /* as well as IP address which - moreover -
+         * can be presented multiple times */
+        ip_addr_arr = virJSONValueObjectGet(tmp_iface, "ip-addresses");
+        if (!ip_addr_arr)
+            continue;
+
+        if ((ip_addr_arr_size = virJSONValueArraySize(ip_addr_arr)) < 0) {
+            /* Mmm, empty 'ip-address'? */
+            continue;
+        }
+
+        (*ifaces)[i].ip_addrs_count = (unsigned int) ip_addr_arr_size;
+
+        if (VIR_ALLOC_N((*ifaces)[i].ip_addrs, ip_addr_arr_size) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        for (j = 0; j < ip_addr_arr_size; j++) {
+            virJSONValuePtr ip_addr_obj = virJSONValueArrayGet(ip_addr_arr, j);
+            virDomainIPAddressPtr ip_addr = &(*ifaces)[i].ip_addrs[j];
+            const char *type, *addr;
+
+            /* Shouldn't happen but doesn't hurt to check neither */
+            if (!ip_addr_obj) {
+                qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                _("something has went really wrong"));
+                goto cleanup;
+            }
+
+            type = virJSONValueObjectGetString(ip_addr_obj, "ip-address-type");
+            if (!type) {
+                qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                                _("qemu agent didn't provide 'ip-address-type'"
+                                  " field for interface '%s'"), name);
+                goto cleanup;
+            } else if (STREQ(type, "ipv4")) {
+                ip_addr->type = VIR_IP_ADDR_TYPE_IPV4;
+            } else if (STREQ(type, "ipv6")) {
+                ip_addr->type = VIR_IP_ADDR_TYPE_IPV6;
+            } else {
+                qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                                _("unknown ip address type '%s'"),
+                                type);
+                goto cleanup;
+            }
+
+            addr = virJSONValueObjectGetString(ip_addr_obj, "ip-address");
+            if (!addr) {
+                qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                                _("qemu agent didn't provide 'ip-address'"
+                                  " field for interface '%s'"), name);
+                goto cleanup;
+            }
+            if (!(ip_addr->addr = strdup(addr))) {
+                virReportOOMError();
+                goto cleanup;
+            }
+
+            if (virJSONValueObjectGetNumberInt(ip_addr_obj, "prefix",
+                                               &ip_addr->prefix) < 0) {
+                qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                _("malformed 'prefix' field"));
+                goto cleanup;
+            }
+        }
+    }
+
+    ret = 0;
+
+cleanup:
+    if (ret < 0 && *ifaces && size> 0) {
+        for (i = 0; i < size; i++) {
+            VIR_FREE((*ifaces)[i].name);
+            VIR_FREE((*ifaces)[i].hwaddr);
+            for (j = 0; j < (*ifaces)[i].ip_addrs_count; j++)
+                VIR_FREE((*ifaces)[i].ip_addrs[j].addr);
+            VIR_FREE((*ifaces)[i].ip_addrs);
+        }
+        VIR_FREE(*ifaces);
+    }
+    virJSONValueFree(cmd);
+    virJSONValueFree(reply);
+    return ret;
+}
diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
index 98c23b0..55d0920 100644
--- a/src/qemu/qemu_agent.h
+++ b/src/qemu/qemu_agent.h
@@ -71,4 +71,8 @@ int qemuAgentFSThaw(qemuAgentPtr mon);
 
 int qemuAgentSuspend(qemuAgentPtr mon,
                      unsigned int target);
+
+int qemuAgentGetInterfaces(qemuAgentPtr mon,
+                           virDomainInterfacePtr *ifaces,
+                           unsigned int *ifaces_count);
 #endif /* __QEMU_AGENT_H__ */
-- 
1.7.8.5




More information about the libvir-list mailing list