mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 21:55:25 +00:00
domifaddr: Add virsh support
tools/virsh-domain-monitor.c * Introduce new command : domifaddr Usage: domifaddr <domain> [interface] [--full] [--source lease|agent] Example outputs: virsh # domifaddr f20 Name MAC address Protocol Address ------------------------------------------------------------------------------- lo 00:00:00:00:00:00 ipv4 127.0.0.1/8 - - ipv6 ::1/128 vnet0 52:54:00:2e:45:ce ipv4 10.1.33.188/24 - - ipv6 2001:db8:0:f101::2/64 - - ipv6 fe80::5054:ff:fe2e:45ce/64 vnet1 52:54:00:b1:70:19 ipv4 192.168.105.201/16 - - ipv4 192.168.201.195/16 - - ipv6 fe80::5054:ff:feb1:7019/64 vnet2 52:54:00:36:2a:e5 N/A N/A vnet3 52:54:00:20:70:3d ipv4 192.168.105.240/16 - - ipv6 fe80::5054:ff:fe20:703d/64 virsh # domifaddr f20 eth1 --source lease Name MAC address Protocol Address ------------------------------------------------------------------------------- vnet1 52:54:00:b1:70:19 ipv4 192.168.105.201/16 - - ipv4 192.168.201.195/16 - - ipv6 fe80::5054:ff:feb1:7019/64 virsh # domifaddr f20 eth0 --source agent --full Name MAC address Protocol Address ------------------------------------------------------------------------------- eth0 52:54:00:2e:45:ce ipv4 10.1.33.188/24 eth0 52:54:00:2e:45:ce ipv6 2001:db8:0:f101::2/64 eth0 52:54:00:2e:45:ce ipv6 fe80::5054:ff:fe2e:45ce/64 tools/virsh.pod * Document new command Signed-off-by: Nehal J Wani <nehaljw.kkd1@gmail.com>
This commit is contained in:
parent
0977b8aa07
commit
2f36e6944e
@ -2197,6 +2197,143 @@ cmdDomstats(vshControl *ctl, const vshCmd *cmd)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* "domifaddr" command
|
||||||
|
*/
|
||||||
|
static const vshCmdInfo info_domifaddr[] = {
|
||||||
|
{"help", N_("Get network interfaces' addresses for a running domain")},
|
||||||
|
{"desc", N_("Get network interfaces' addresses for a running domain")},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const vshCmdOptDef opts_domifaddr[] = {
|
||||||
|
{.name = "domain",
|
||||||
|
.type = VSH_OT_DATA,
|
||||||
|
.flags = VSH_OFLAG_REQ,
|
||||||
|
.help = N_("domain name, id or uuid")},
|
||||||
|
{.name = "interface",
|
||||||
|
.type = VSH_OT_STRING,
|
||||||
|
.flags = VSH_OFLAG_NONE,
|
||||||
|
.help = N_("network interface name")},
|
||||||
|
{.name = "full",
|
||||||
|
.type = VSH_OT_BOOL,
|
||||||
|
.flags = VSH_OFLAG_NONE,
|
||||||
|
.help = N_("display full fields")},
|
||||||
|
{.name = "source",
|
||||||
|
.type = VSH_OT_STRING,
|
||||||
|
.flags = VSH_OFLAG_NONE,
|
||||||
|
.help = N_("address source: 'lease' or 'agent'")},
|
||||||
|
{.name = NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
cmdDomIfAddr(vshControl *ctl, const vshCmd *cmd)
|
||||||
|
{
|
||||||
|
virDomainPtr dom = NULL;
|
||||||
|
const char *interface = NULL;
|
||||||
|
virDomainInterfacePtr *ifaces = NULL;
|
||||||
|
size_t i, j;
|
||||||
|
int ifaces_count = 0;
|
||||||
|
bool ret = false;
|
||||||
|
bool full = vshCommandOptBool(cmd, "full");
|
||||||
|
const char *sourcestr = NULL;
|
||||||
|
int source = VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE;
|
||||||
|
|
||||||
|
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (vshCommandOptString(cmd, "interface", &interface) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
if (vshCommandOptString(cmd, "source", &sourcestr) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (sourcestr) {
|
||||||
|
if (STREQ(sourcestr, "lease")) {
|
||||||
|
source = VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE;
|
||||||
|
} else if (STREQ(sourcestr, "agent")) {
|
||||||
|
source = VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT;
|
||||||
|
} else {
|
||||||
|
vshError(ctl, _("Unknown data source '%s'"), sourcestr);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ifaces_count = virDomainInterfaceAddresses(dom, &ifaces, source, 0)) < 0) {
|
||||||
|
vshError(ctl, _("Failed to query for interfaces addresses"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
vshPrintExtra(ctl, " %-10s %-20s %-8s %s\n%s%s\n", _("Name"),
|
||||||
|
_("MAC address"), _("Protocol"), _("Address"),
|
||||||
|
_("-------------------------------------------------"),
|
||||||
|
_("------------------------------"));
|
||||||
|
|
||||||
|
for (i = 0; i < ifaces_count; i++) {
|
||||||
|
virDomainInterfacePtr iface = ifaces[i];
|
||||||
|
const char *ip_addr_str = NULL;
|
||||||
|
const char *type = NULL;
|
||||||
|
|
||||||
|
if (interface && STRNEQ(interface, iface->name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* When the interface has no IP address */
|
||||||
|
if (!iface->naddrs) {
|
||||||
|
vshPrintExtra(ctl, " %-10s %-17s %-12s %s\n",
|
||||||
|
iface->name, iface->hwaddr, "N/A", "N/A");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < iface->naddrs; j++) {
|
||||||
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
|
||||||
|
switch (iface->addrs[j].type) {
|
||||||
|
case VIR_IP_ADDR_TYPE_IPV4:
|
||||||
|
type = "ipv4";
|
||||||
|
break;
|
||||||
|
case VIR_IP_ADDR_TYPE_IPV6:
|
||||||
|
type = "ipv6";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
virBufferAsprintf(&buf, "%-12s %s/%d",
|
||||||
|
type, iface->addrs[j].addr,
|
||||||
|
iface->addrs[j].prefix);
|
||||||
|
|
||||||
|
if (virBufferError(&buf)) {
|
||||||
|
virBufferFreeAndReset(&buf);
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ip_addr_str = virBufferContentAndReset(&buf);
|
||||||
|
|
||||||
|
if (!ip_addr_str)
|
||||||
|
ip_addr_str = "";
|
||||||
|
|
||||||
|
/* Don't repeat interface name */
|
||||||
|
if (full || !j)
|
||||||
|
vshPrintExtra(ctl, " %-10s %-17s %s\n",
|
||||||
|
iface->name, iface->hwaddr, ip_addr_str);
|
||||||
|
else
|
||||||
|
vshPrintExtra(ctl, " %-10s %-17s %s\n",
|
||||||
|
"-", "-", ip_addr_str);
|
||||||
|
|
||||||
|
virBufferFreeAndReset(&buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (ifaces && ifaces_count > 0) {
|
||||||
|
for (i = 0; i < ifaces_count; i++)
|
||||||
|
virDomainInterfaceFree(ifaces[i]);
|
||||||
|
}
|
||||||
|
VIR_FREE(ifaces);
|
||||||
|
|
||||||
|
virDomainFree(dom);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
const vshCmdDef domMonitoringCmds[] = {
|
const vshCmdDef domMonitoringCmds[] = {
|
||||||
{.name = "domblkerror",
|
{.name = "domblkerror",
|
||||||
.handler = cmdDomBlkError,
|
.handler = cmdDomBlkError,
|
||||||
@ -2234,6 +2371,12 @@ const vshCmdDef domMonitoringCmds[] = {
|
|||||||
.info = info_domif_getlink,
|
.info = info_domif_getlink,
|
||||||
.flags = 0
|
.flags = 0
|
||||||
},
|
},
|
||||||
|
{.name = "domifaddr",
|
||||||
|
.handler = cmdDomIfAddr,
|
||||||
|
.opts = opts_domifaddr,
|
||||||
|
.info = info_domifaddr,
|
||||||
|
.flags = 0
|
||||||
|
},
|
||||||
{.name = "domiflist",
|
{.name = "domiflist",
|
||||||
.handler = cmdDomiflist,
|
.handler = cmdDomiflist,
|
||||||
.opts = opts_domiflist,
|
.opts = opts_domiflist,
|
||||||
|
@ -731,6 +731,22 @@ B<Explanation of fields> (fields appear in the following order):
|
|||||||
flush_total_times - total time flush operations took (ns)
|
flush_total_times - total time flush operations took (ns)
|
||||||
<-- other fields provided by hypervisor -->
|
<-- other fields provided by hypervisor -->
|
||||||
|
|
||||||
|
|
||||||
|
=item B<domifaddr> I<domain> [I<interface>] [I<--full>]
|
||||||
|
[I<--source lease|agent>]
|
||||||
|
|
||||||
|
Get a list of interfaces of a running domain along with their IP and MAC
|
||||||
|
addresses, or limited output just for one interface if I<interface> is
|
||||||
|
specified. Note that I<interface> can be driver dependent, it can be the name
|
||||||
|
within guest OS or the name you would see in domain XML. Moreover, the whole
|
||||||
|
command may require a guest agent to be configured for the queried domain under
|
||||||
|
some drivers, notably qemu. If I<--full> is specified, the interface name is
|
||||||
|
always displayed when the interface has multiple addresses or alias, otherwise
|
||||||
|
it only displays the interface name for the first address, and "-" for the
|
||||||
|
others. The I<--source> argument specifies what data source to use for the
|
||||||
|
addresses, currently one of 'lease' to read DHCP leases, or 'agent' to query
|
||||||
|
the guest OS via an agent. If unspecified, 'lease' is the default.
|
||||||
|
|
||||||
=item B<domifstat> I<domain> I<interface-device>
|
=item B<domifstat> I<domain> I<interface-device>
|
||||||
|
|
||||||
Get network interface stats for a running domain.
|
Get network interface stats for a running domain.
|
||||||
|
Loading…
Reference in New Issue
Block a user