Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save nehaljwani/6061745 to your computer and use it in GitHub Desktop.
Save nehaljwani/6061745 to your computer and use it in GitHub Desktop.
daemon/remote.c | 73 +++++++++++++++++
include/libvirt/libvirt.h.in | 23 ++++++
python/generator.py | 1 +
python/libvirt-override-api.xml | 6 ++
src/driver.h | 6 ++
src/libvirt.c | 52 ++++++++++++
src/libvirt_public.syms | 1 +
src/qemu/qemu_agent.c | 175 ++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_agent.h | 3 +
src/qemu/qemu_driver.c | 64 +++++++++++++++
src/remote/remote_driver.c | 62 +++++++++++++-
src/remote/remote_protocol.x | 33 +++++++-
tools/virsh-domain-monitor.c | 107 ++++++++++++++++++++++++
13 files changed, 604 insertions(+), 2 deletions(-)
diff --git a/daemon/remote.c b/daemon/remote.c
index cb362da..ab14ef4 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -5005,6 +5005,79 @@ cleanup:
return rv;
}
+ static int
+remoteDispatchDomainInterfacesAddresses(
+ virNetServerPtr server ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client,
+ virNetMessagePtr msg ATTRIBUTE_UNUSED,
+ virNetMessageErrorPtr rerr,
+ remote_domain_interfaces_addresses_args *args,
+ remote_domain_interfaces_addresses_ret *ret)
+{
+ virTypedParameterPtr *params = NULL;
+ virDomainPtr dom = NULL;
+ int nparams;
+ unsigned int flags = 0;
+ int rv = -1, i;
+ struct daemonClientPrivate *priv =
+ virNetServerClientGetPrivateData(client);
+
+ if (!priv->conn) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+ goto cleanup;
+ }
+
+ if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+ goto cleanup;
+ flags = args->flags;
+
+ if (args->nparams > REMOTE_DOMAIN_INTERFACES_MAX) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large"));
+ goto cleanup;
+ }
+ if (args->nparams && VIR_ALLOC_N(params, args->nparams) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ nparams = args->nparams;
+
+ if (nparams && VIR_ALLOC_N(params, nparams) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (virDomainInterfacesAddresses(dom, params, &nparams, flags) < 0)
+ goto cleanup;
+
+ ret->ifaces.ifaces_len = nparams;
+ if (VIR_ALLOC_N(ret->ifaces.ifaces_val, nparams) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (args->nparams == 0)
+ goto success;
+
+ for (i = 0; i < nparams; i++) {
+ int temp_nparams = (&params[i][0])->value.i;
+ if (remoteSerializeTypedParameters(params[i], temp_nparams,
+ &ret->ifaces.ifaces_val[i].params.params_val,
+ &ret->ifaces.ifaces_val[i].params.params_len,
+ args->flags) < 0)
+ goto cleanup;
+ }
+
+success:
+ rv = 0;
+
+cleanup:
+ if (rv < 0)
+ virNetMessageSaveError(rerr);
+ /* I am unable to use virTypedParamsFree to free params*/
+ if (dom)
+ virDomainFree(dom);
+ return rv;
+}
/*----- Helpers. -----*/
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index b791125..a624431 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2033,6 +2033,29 @@ int virDomainGetInterfaceParameters (virDomainPtr dom,
virTypedParameterPtr params,
int *nparams, unsigned int flags);
+# define VIR_DOMAIN_INTERFACE_NAME "iface-name"
+# define VIR_DOMAIN_INTERFACE_HWADDR "iface-hwaddr"
+# define VIR_DOMAIN_INTERFACES_PARAMS_COUNT "iface-count"
+# define VIR_DOMAIN_IPADDR_TYPE "ipaddr-type"
+# define VIR_DOMAIN_IPADDR_ADDR "ipaddr-addr"
+# define VIR_DOMAIN_IPADDR_PREFIX "ipaddr-prefix"
+# define VIR_DOMAIN_PARAMS_PER_IPADDR 3
+# define VIR_DOMAIN_NECESSARY_PARAMS_COUNT 3
+
+typedef enum {
+ VIR_IP_ADDR_TYPE_IPV4,
+ VIR_IP_ADDR_TYPE_IPV6,
+
+#ifdef VIR_ENUM_SENTINELS
+ VIR_IP_ADDR_TYPE_LAST
+#endif
+} virIPAddrType;
+
+int virDomainInterfacesAddresses (virDomainPtr dom,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags);
+
/* Management of domain block devices */
int virDomainBlockPeek (virDomainPtr dom,
diff --git a/python/generator.py b/python/generator.py
index da642eb..3f7bbae 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -460,6 +460,7 @@ skip_impl = (
'virNodeGetCPUMap',
'virDomainMigrate3',
'virDomainMigrateToURI3',
+ 'virDomainInterfacesAddresses',
)
lxc_skip_impl = (
diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml
index 9a88215..9b310d8 100644
--- a/python/libvirt-override-api.xml
+++ b/python/libvirt-override-api.xml
@@ -602,5 +602,11 @@
<arg name='conn' type='virConnectPtr' info='pointer to the hypervisor connection'/>
<arg name='flags' type='int' info='unused, pass 0'/>
</function>
+ <function name='virDomainInterfacesAddresses' file='python'>
+ <info>returns array of IP addresses for all domain interfaces</info>
+ <arg name='dom' type='virDomainPtr' info='pointer to the domain'/>
+ <arg name='flags' type='unsigned int' info='extra flags; not used yet, so callers should always pass 0'/>
+ <return type='virDomainInterfacePtr' info="dictionary of domain interfaces among with their HW and IP addresses"/>
+ </function>
</symbols>
</api>
diff --git a/src/driver.h b/src/driver.h
index 31851cb..5d7d242 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -500,6 +500,11 @@ typedef int
virTypedParameterPtr params,
int *nparams,
unsigned int flags);
+typedef int
+(*virDrvDomainInterfacesAddresses) (virDomainPtr dom,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags);
typedef int
(*virDrvDomainMemoryStats)(virDomainPtr domain,
@@ -1219,6 +1224,7 @@ struct _virDriver {
virDrvDomainInterfaceStats domainInterfaceStats;
virDrvDomainSetInterfaceParameters domainSetInterfaceParameters;
virDrvDomainGetInterfaceParameters domainGetInterfaceParameters;
+ virDrvDomainInterfacesAddresses domainInterfacesAddresses;
virDrvDomainMemoryStats domainMemoryStats;
virDrvDomainBlockPeek domainBlockPeek;
virDrvDomainMemoryPeek domainMemoryPeek;
diff --git a/src/libvirt.c b/src/libvirt.c
index bc1694a..1919573 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -7511,6 +7511,58 @@ error:
}
/**
+* virDomainInterfacesAddresses:
+* @dom: domain object
+* @flags: extra flags; not used yet, so callers should always pass 0
+* @params: pointer to interface parameter objects
+* @nparams: number of interface parameter (this value can be the same or
+*
+* ToDO
+*
+* Returns -1 in case of error, 0 in case of success.
+**/
+
+int
+virDomainInterfacesAddresses(virDomainPtr dom,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DOMAIN_DEBUG(dom, "params=%p, nparams=%d, flags=%x",
+ params, *nparams, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(dom)) {
+ virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ goto error;
+ }
+
+ conn = dom->conn;
+
+ if (VIR_DRV_SUPPORTS_FEATURE(dom->conn->driver, dom->conn,
+ VIR_DRV_FEATURE_TYPED_PARAM_STRING))
+ flags |= VIR_TYPED_PARAM_STRING_OKAY;
+
+ if (conn->driver->domainInterfacesAddresses) {
+ int ret;
+ ret = conn->driver->domainInterfacesAddresses(dom, params,
+ nparams, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(dom ? dom->conn : NULL);
+ return -1;
+}
+
+/**
* virNodeGetMemoryStats:
* @conn: pointer to the hypervisor connection.
* @cellNum: number of node cell. (VIR_NODE_MEMORY_STATS_ALL_CELLS means total
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 7c6edf6..ddbbb79 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -542,6 +542,7 @@ LIBVIRT_0.9.13 {
virDomainSnapshotIsCurrent;
virDomainSnapshotListAllChildren;
virDomainSnapshotRef;
+ virDomainInterfacesAddresses;
} LIBVIRT_0.9.11;
LIBVIRT_0.10.0 {
diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index 9914521..d2a0d28 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -42,6 +42,7 @@
#include "virtime.h"
#include "virobject.h"
#include "virstring.h"
+#include "virtypedparam.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -1330,6 +1331,180 @@ cleanup:
return ret;
}
+int
+qemuAgentGetInterfaces(qemuAgentPtr mon,
+ virTypedParameterPtr *params,
+ int *nparams)
+{
+ int ret = -1;
+ int size = -1;
+ int i, j;
+ 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, 1) < 0 ||
+ qemuAgentCheckError(cmd, reply) < 0)
+ goto cleanup;
+
+ /*Count number of interfaces*/
+ if (!(ret_array = virJSONValueObjectGet(reply, "return"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("qemu agent didn't provide 'return' field"));
+ goto cleanup;
+ }
+
+ if ((size = virJSONValueArraySize(ret_array)) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("qemu agent didn't return an array of interfaces"));
+ goto cleanup;
+ }
+ if (*nparams == 0){
+ *nparams = (int) size;
+ ret = 0;
+ goto cleanup;
+ }
+
+ for (i = 0; i < size; i++) {
+
+ virJSONValuePtr tmp_iface = virJSONValueArrayGet(ret_array, i);
+ virJSONValuePtr ip_addr_arr = NULL;
+ char *name, *hwaddr;
+ int ip_addr_arr_size, params_count;
+
+ /* Shouldn't happen but doesn't hurt to check neither */
+ if (!tmp_iface) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("something has went really wrong"));
+ goto cleanup;
+ }
+
+ /* interface name is required to be presented */
+ if (VIR_STRDUP(name, virJSONValueObjectGetString(tmp_iface, "name")) < 0)
+ goto cleanup;
+
+ if (!name) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("qemu agent didn't provide 'name' field"));
+ goto cleanup;
+ }
+
+ 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;
+ }
+
+ params_count = VIR_DOMAIN_PARAMS_PER_IPADDR * ip_addr_arr_size
+ + VIR_DOMAIN_NECESSARY_PARAMS_COUNT;
+ /*Allocate memory to params*/
+ if (VIR_ALLOC_N(params[i], params_count) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /*Store total number of parameters per interface */
+ if (virTypedParameterAssign(&params[i][0], VIR_DOMAIN_INTERFACES_PARAMS_COUNT,
+ VIR_TYPED_PARAM_INT, params_count) < 0)
+ goto cleanup;
+
+ /*Store interface name*/
+ if (virTypedParameterAssign(&params[i][1], VIR_DOMAIN_INTERFACE_NAME,
+ VIR_TYPED_PARAM_STRING, name) < 0)
+ goto cleanup;
+
+ /* hwaddr might be omitted */
+ if (VIR_STRDUP(hwaddr, virJSONValueObjectGetString(tmp_iface, "hardware-address")) < 0)
+ goto cleanup;
+
+ if (hwaddr && virTypedParameterAssign(&params[i][2], VIR_DOMAIN_INTERFACE_HWADDR,
+ VIR_TYPED_PARAM_STRING, hwaddr) < 0)
+ goto cleanup;
+
+ /*Enumerate though each ip */
+ for (j = 0; j < ip_addr_arr_size; j++) {
+ virJSONValuePtr ip_addr_obj = virJSONValueArrayGet(ip_addr_arr, j);
+ virTypedParameterPtr ip_type = &params[i][VIR_DOMAIN_PARAMS_PER_IPADDR * j + 3];
+ virTypedParameterPtr ip_addr = &params[i][VIR_DOMAIN_PARAMS_PER_IPADDR * j + 4];
+ virTypedParameterPtr ip_prefix = &params[i][VIR_DOMAIN_PARAMS_PER_IPADDR * j + 5];
+ char *type, *addr;
+ int addrType, prefix;
+
+ /* Shouldn't happen but doesn't hurt to check neither */
+ if (!ip_addr_obj) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("something has went really wrong"));
+ goto cleanup;
+ }
+
+ /* Getting the ip address type */
+ if (VIR_STRDUP(type, virJSONValueObjectGetString(ip_addr_obj, "ip-address-type")) < 0)
+ goto cleanup;
+ if (!type) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("qemu agent didn't provide 'ip-address-type'"
+ " field for interface '%s'"), name);
+ goto cleanup;
+ } else if (STREQ(type, "ipv4")) {
+ addrType = VIR_IP_ADDR_TYPE_IPV4;
+ } else if (STREQ(type, "ipv6")) {
+ addrType = VIR_IP_ADDR_TYPE_IPV6;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unknown ip address type '%s'"),
+ type);
+ goto cleanup;
+ }
+ if (virTypedParameterAssign(ip_type, VIR_DOMAIN_IPADDR_TYPE,
+ VIR_TYPED_PARAM_INT, addrType) < 0)
+ goto cleanup;
+
+ /* Getting the ip address value */
+ if (VIR_STRDUP(addr, virJSONValueObjectGetString(ip_addr_obj, "ip-address")) < 0)
+ goto cleanup;
+ if (!addr) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("qemu agent didn't provide 'ip-address'"
+ " field for interface '%s'"), name);
+ goto cleanup;
+ }
+ if (virTypedParameterAssign(ip_addr, VIR_DOMAIN_IPADDR_ADDR,
+ VIR_TYPED_PARAM_STRING, addr) < 0)
+ goto cleanup;
+
+ /* Getting the ip address prefix */
+ if (virJSONValueObjectGetNumberInt(ip_addr_obj, "prefix",
+ &prefix) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed 'prefix' field"));
+ goto cleanup;
+ }
+
+ if (virTypedParameterAssign(ip_prefix, VIR_DOMAIN_IPADDR_PREFIX,
+ VIR_TYPED_PARAM_INT, prefix) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed 'prefix' field"));
+ goto cleanup;
+ }
+ }
+ }
+
+ ret = 0;
+
+cleanup:
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ return ret;
+}
+
/*
* qemuAgentFSThaw:
* @mon: Agent
diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
index cf70653..fabdda3 100644
--- a/src/qemu/qemu_agent.h
+++ b/src/qemu/qemu_agent.h
@@ -83,6 +83,9 @@ int qemuAgentArbitraryCommand(qemuAgentPtr mon,
int qemuAgentFSTrim(qemuAgentPtr mon,
unsigned long long minimum);
+int qemuAgentGetInterfaces(qemuAgentPtr mon,
+ virTypedParameterPtr *params,
+ int *nparams);
typedef struct _qemuAgentCPUInfo qemuAgentCPUInfo;
typedef qemuAgentCPUInfo *qemuAgentCPUInfoPtr;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 4856f37..91b49f2 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -15869,6 +15869,69 @@ qemuNodeSuspendForDuration(virConnectPtr conn,
return nodeSuspendForDuration(target, duration, flags);
}
+static int
+qemuDomainInterfacesAddresses(virDomainPtr dom,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags)
+{
+ virQEMUDriverPtr driver = dom->conn->privateData;
+ qemuDomainObjPrivatePtr priv = NULL;
+ virDomainObjPtr vm = NULL;
+ unsigned long long ret = -1;
+
+ virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+ if (!(vm = qemuDomObjFromDomain(dom)))
+ goto cleanup;
+
+ priv = vm->privateData;
+
+ if (virDomainInterfacesAddressesEnsureACL(dom->conn, vm->def) < 0)
+ goto cleanup;
+
+ if (!virDomainObjIsActive(vm)) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain is not running"));
+ goto cleanup;
+ }
+
+
+ if (priv->agentError) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("QEMU guest agent is not "
+ "available due to an error"));
+ goto cleanup;
+ }
+
+ if (!priv->agent) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("QEMU guest agent is not configured"));
+ goto cleanup;
+ }
+
+ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+ goto cleanup;
+
+ if (!virDomainObjIsActive(vm)) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain is not running"));
+ goto endjob;
+ }
+
+ qemuDomainObjEnterAgent(vm);
+ ret = qemuAgentGetInterfaces(priv->agent, params, nparams);
+ qemuDomainObjExitAgent(vm);
+
+endjob:
+ if (qemuDomainObjEndJob(driver, vm) == 0)
+ vm = NULL;
+
+cleanup:
+ if (vm)
+ virObjectUnlock(vm);
+ return ret;
+}
static virDriver qemuDriver = {
.no = VIR_DRV_QEMU,
@@ -15907,6 +15970,7 @@ static virDriver qemuDriver = {
.domainGetMemoryParameters = qemuDomainGetMemoryParameters, /* 0.8.5 */
.domainSetBlkioParameters = qemuDomainSetBlkioParameters, /* 0.9.0 */
.domainGetBlkioParameters = qemuDomainGetBlkioParameters, /* 0.9.0 */
+ .domainInterfacesAddresses = qemuDomainInterfacesAddresses, /* 0.9.13 */
.domainGetInfo = qemuDomainGetInfo, /* 0.2.0 */
.domainGetState = qemuDomainGetState, /* 0.9.2 */
.domainGetControlInfo = qemuDomainGetControlInfo, /* 0.9.3 */
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 7f3e833..74fd13e 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -2729,6 +2729,66 @@ done:
return rv;
}
+static int
+remoteDomainInterfacesAddresses(virDomainPtr dom,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags)
+{
+ int rv = -1, i;
+ remote_domain_interfaces_addresses_args args;
+ remote_domain_interfaces_addresses_ret ret;
+ struct private_data *priv = dom->conn->privateData;
+
+ memset(&ret, 0, sizeof(ret));
+ args.flags = flags;
+ args.nparams = *nparams;
+ make_nonnull_domain(&args.dom, dom);
+
+ remoteDriverLock(priv);
+
+ if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_INTERFACES_ADDRESSES,
+ (xdrproc_t)xdr_remote_domain_interfaces_addresses_args,
+ (char *)&args,
+ (xdrproc_t)xdr_remote_domain_interfaces_addresses_ret,
+ (char *)&ret) == -1) {
+ goto done;
+ }
+
+ /* Handle the case when the caller does not know the number of stats
+ * and is asking for the number of stats supported
+ */
+ if (*nparams == 0) {
+ rv = ret.ifaces.ifaces_len;
+ goto cleanup;
+ }
+
+ /*Deserialize the ret structure and fill params*/
+ for (i = 0; i < ret.ifaces.ifaces_len; i++) {
+ int size = ret.ifaces.ifaces_val[i].params.params_val
+ ->value.remote_typed_param_value_u.i;
+ if (VIR_ALLOC_N(params[i], size) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ if (remoteDeserializeTypedParameters(ret.ifaces.ifaces_val[i].params.params_val,
+ ret.ifaces.ifaces_val[i].params.params_len,
+ REMOTE_DOMAIN_INTERFACE_ADDRESSES_MAX,
+ &params[i],
+ &size) < 0)
+ goto cleanup;
+ }
+ rv = 0;
+
+cleanup:
+ xdr_free((xdrproc_t)xdr_remote_domain_interfaces_addresses_ret,
+ (char *) &ret);
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
+
static int remoteDomainGetCPUStats(virDomainPtr domain,
virTypedParameterPtr params,
unsigned int nparams,
@@ -6434,7 +6494,6 @@ cleanup:
return rv;
}
-
static void
remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event)
{
@@ -6674,6 +6733,7 @@ static virDriver remote_driver = {
.domainMemoryPeek = remoteDomainMemoryPeek, /* 0.4.2 */
.domainGetBlockInfo = remoteDomainGetBlockInfo, /* 0.8.1 */
.nodeGetCPUStats = remoteNodeGetCPUStats, /* 0.9.3 */
+ .domainInterfacesAddresses = remoteDomainInterfacesAddresses, /* 0.9.13 */
.nodeGetMemoryStats = remoteNodeGetMemoryStats, /* 0.9.3 */
.nodeGetCellsFreeMemory = remoteNodeGetCellsFreeMemory, /* 0.3.3 */
.nodeGetFreeMemory = remoteNodeGetFreeMemory, /* 0.3.3 */
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 2e9dc1d..1d91b0e 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -236,6 +236,15 @@ const REMOTE_NODE_MEMORY_PARAMETERS_MAX = 64;
/* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */
typedef opaque remote_uuid[VIR_UUID_BUFLEN];
+/*
+ + * Upper limit on number of interfaces per domain
+ + */
+const REMOTE_DOMAIN_INTERFACES_MAX = 64;
+
+/*
+ + * Upper limit on number of ip addresses per interface
+ + */
+const REMOTE_DOMAIN_INTERFACE_ADDRESSES_MAX = 64;
/* A domain which may not be NULL. */
struct remote_nonnull_domain {
@@ -1272,6 +1281,23 @@ struct remote_domain_get_cpu_stats_ret {
int nparams;
};
+struct remote_domain_interfaces_addresses_args {
+ remote_nonnull_domain dom;
+ int nparams;
+ unsigned int flags;
+};
+
+struct remote_domain_interfaces_addresses_ret_ {
+ remote_typed_param params<REMOTE_DOMAIN_INTERFACE_ADDRESSES_MAX>;
+};
+
+struct remote_domain_interfaces_addresses_ret {
+ remote_domain_interfaces_addresses_ret_ ifaces<REMOTE_DOMAIN_INTERFACES_MAX>;
+ int ifaces_len;
+};
+
+
+
struct remote_domain_get_hostname_args {
remote_nonnull_domain dom;
unsigned int flags;
@@ -4944,6 +4970,11 @@ enum remote_procedure {
* @generate: none
* @acl: domain:migrate
*/
- REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3_PARAMS = 307
+ REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3_PARAMS = 307,
+ /**
+ * @generate: none
+ * @acl: domain:read
+ */
+ REMOTE_PROC_DOMAIN_INTERFACES_ADDRESSES = 308
};
diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index 3ba829c..0c5591e 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -1317,6 +1317,107 @@ cleanup:
return ret;
}
+/* "domifaddr" command
+ */
+static const vshCmdInfo info_domifaddr[] = {
+ {"help", N_("get network interfaces addresses for a domain")},
+ {"desc", N_("Get network interfaces addresses for a running domain")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_domifaddr[] = {
+ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+ {"interface", VSH_OT_DATA, VSH_OFLAG_NONE, N_("network interface name")},
+ {NULL, 0, 0, NULL}
+};
+static bool
+cmdDomIfAddr(vshControl *ctl, const vshCmd *cmd)
+{
+ virDomainPtr dom = NULL;
+ const char *device = NULL;
+
+ virTypedParameterPtr *params = NULL;
+ int nparams = 0;
+ unsigned int flags = 0;
+ int i, j;
+
+ bool ret = false;
+
+ if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ return false;
+
+ if (vshCommandOptString(cmd, "interface", &device) < 0) {
+ goto cleanup;
+ }
+
+ /*Find how many interfaces exist*/
+ if ((nparams = virDomainInterfacesAddresses(dom, params, &nparams, flags)) < 0) {
+ vshError(ctl, _("Failed to query for interfaces addresses"));
+ goto cleanup;
+ }
+
+ /*Allocate Memory Accordingly*/
+ if (VIR_ALLOC_N(params, nparams) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /*Send request for all interfaces*/
+ if (virDomainInterfacesAddresses(dom, params, &nparams, flags) < 0) {
+ vshError(ctl, _("Failed to query for interfaces addresses"));
+ goto cleanup;
+ }
+
+ /*Lets print to stdout*/
+ vshPrintExtra(ctl, " %-10s %-17s %s\n%s\n",
+ _("Name"), _("HW address"), _("IP address"),
+ "---------------------------------------------------");
+ ret = true;
+ for (i = 0; i < nparams; i++) {
+ virTypedParameterPtr iface = params[i];
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ const char *hwaddr = "";
+ const char *ip_addr_str = NULL;
+ virTypedParameterPtr iface_count = &iface[0];
+ virTypedParameterPtr iface_name = &iface[1];
+ virTypedParameterPtr iface_hwaddr = &iface[2];
+
+ if (device && STRNEQ(device, iface_name->value.s))
+ continue;
+
+ if (iface_hwaddr)
+ hwaddr = iface_hwaddr->value.s;
+
+ int ip_addr_count = (iface_count->value.i -
+ VIR_DOMAIN_NECESSARY_PARAMS_COUNT) / VIR_DOMAIN_PARAMS_PER_IPADDR;
+ for (j = 0; j < ip_addr_count; j++) {
+ virTypedParameterPtr ip_addr = &iface[3*j+4];
+ virTypedParameterPtr ip_prefix = &iface[3*j+5];
+ if (j)
+ virBufferAddChar(&buf, ' ');
+ virBufferAsprintf(&buf, "%s/%d",
+ ip_addr->value.s,
+ ip_prefix->value.i);
+ }
+
+ ip_addr_str = virBufferContentAndReset(&buf);
+
+ if (!ip_addr_str)
+ ip_addr_str = "";
+
+ vshPrintExtra(ctl, " %-10s %-17s %s\n",
+ iface_name->value.s, hwaddr, ip_addr_str);
+
+ virBufferFreeAndReset(&buf);
+ }
+
+cleanup:
+
+ if (dom)
+ virDomainFree(dom);
+ return ret;
+}
+
/*
* "list" command
*/
@@ -1855,6 +1956,12 @@ const vshCmdDef domMonitoringCmds[] = {
.info = info_domifstat,
.flags = 0
},
+ {.name = "domifaddr",
+ .handler = cmdDomIfAddr,
+ .opts = opts_domifaddr,
+ .info = info_domifaddr,
+ .flags = 0
+ },
{.name = "dominfo",
.handler = cmdDominfo,
.opts = opts_dominfo,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment