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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list