On 01/25/2015 01:38 PM, Nehal J Wani wrote: > tools/virsh-domain-monitor.c > * Introduce new command : domifaddr > Usage: domifaddr <domain> [interface] [--full] [--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 > eth0 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 > eth1 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 > eth2 52:54:00:36:2a:e5 N/A N/A > eth3 52:54:00:20:70:3d ipv4 192.168.105.240/16 > - - ipv6 fe80::5054:ff:fe20:703d/64 > > virsh # domifaddr f20 eth1 --agent > Name MAC address Protocol Address > ------------------------------------------------------------------------------- > eth1 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 --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 > I for one like the format of the output and appreciate seeing it in the commit message! > Signed-off-by: Nehal J Wani <nehaljw.kkd1@xxxxxxxxx> > --- > tools/virsh-domain-monitor.c | 141 +++++++++++++++++++++++++++++++++++++++++++ > tools/virsh.pod | 16 +++++ > 2 files changed, 157 insertions(+) > > diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c > index 925eb1b..960b831 100644 > --- a/tools/virsh-domain-monitor.c > +++ b/tools/virsh-domain-monitor.c > @@ -2177,6 +2177,141 @@ cmdDomstats(vshControl *ctl, const vshCmd *cmd) > 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 = "lease", > + .type = VSH_OT_BOOL, > + .flags = VSH_OFLAG_NONE, > + .help = N_("parse dhcp lease file")}, > + {.name = "agent", > + .type = VSH_OT_BOOL, > + .flags = VSH_OFLAG_NONE, > + .help = N_("query qemu guest 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; > + unsigned int flags = 0; > + bool ret = false; > + bool full = vshCommandOptBool(cmd, "full"); > + > + if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) > + return false; > + > + if (vshCommandOptString(cmd, "interface", &interface) < 0) > + goto cleanup; > + > + if (vshCommandOptBool(cmd, "lease")) > + flags |= VIR_DOMAIN_INTERFACE_ADDRESSES_LEASE; > + > + if (vshCommandOptBool(cmd, "agent")) > + flags |= VIR_DOMAIN_INTERFACE_ADDRESSES_AGENT; > + Since only one style would be displayed (lease in preference over agent) - providing both flags could be an error... Unless of course you change 3/4 to allow tryAgent after tryLease returns. > + if ((ifaces_count = virDomainInterfaceAddresses(dom, &ifaces, flags)) < 0) { [1] Same Coverity issue as 2/4 > + 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 *hwaddr = ""; > + const char *ip_addr_str = NULL; > + const char *type = NULL; > + > + if (interface && STRNEQ(interface, iface->name)) > + continue; > + > + hwaddr = iface->hwaddr; > + > + /* When the interface has no IP address */ > + if (!iface->naddrs) { > + vshPrintExtra(ctl, " %-10s %-17s %-12s %s\n", > + iface->name, 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", Should this be " %-12s..." instead of "%-12s" (since everything else adds that extra space). > + 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, hwaddr, ip_addr_str); > + else > + vshPrintExtra(ctl, " %-10s %-17s %s\n", > + "-", "-", ip_addr_str); > + > + virBufferFreeAndReset(&buf); > + } > + } > + > + ret = true; > + > + cleanup: > + if (ifaces) again here Coverity complains because it doesn't understand the relationship between ifaces_count and ifaces, so going with : if (ifaces_count > 0) { for (i = 0; i < ifaces_count; i++) virDomainInterfaceFree(ifaces[i]); } pacifies Coverity. > + for (i = 0; i < ifaces_count; i++) > + virDomainInterfaceFree(ifaces[i]); > + VIR_FREE(ifaces); > + > + virDomainFree(dom); > + return ret; > +} > + > const vshCmdDef domMonitoringCmds[] = { > {.name = "domblkerror", > .handler = cmdDomBlkError, > @@ -2214,6 +2349,12 @@ const vshCmdDef domMonitoringCmds[] = { > .info = info_domif_getlink, > .flags = 0 > }, > + {.name = "domifaddr", > + .handler = cmdDomIfAddr, > + .opts = opts_domifaddr, > + .info = info_domifaddr, > + .flags = 0 > + }, > {.name = "domiflist", > .handler = cmdDomiflist, > .opts = opts_domiflist, > diff --git a/tools/virsh.pod b/tools/virsh.pod > index abe80c2..f5457bb 100644 > --- a/tools/virsh.pod > +++ b/tools/virsh.pod > @@ -729,6 +729,22 @@ B<Explanation of fields> (fields appear in the following order): > flush_total_times - total time flush operations took (ns) > <-- other fields provided by hypervisor --> > > + > +=item B<domifaddr> I<domain> [I<interface>] [I<--full>] > + [I<--snoop>]] [I<--lease>] [I<--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 interfac has multiple addresses or alias, otherwise s/interfac/interface > +it only displays the interface name for the first address, and "-" for the > +others. If I<--lease> is specified, dhcp file is parsed and if I<--agent> is > +specified, qemu guest agent is queried. It is not recommended to mix I<--agent> > +with I<--lease> as it may return ambiguous results. > + Well technically as the code is written - if --lease and --agent are provided, only --lease is returned John > =item B<domifstat> I<domain> I<interface-device> > > Get network interface stats for a running domain. > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list