Use virNetworkGetDHCPLeases and virNetworkGetDHCPLeasesForMAC in virsh. The new feature supports the follwing methods: 1. Retrieve leases info for a given virtual network 2. Retrieve leases info for given network interface tools/virsh-domain-monitor.c * Introduce new command : net-dhcp-leases Example Usage: net-dhcp-leases <network> [mac] virsh # net-dhcp-leases --network default6 Expiry Time MAC address Protocol IP address Hostname Client ID or DUID ------------------------------------------------------------------------------------------------------------------- 2014-06-16 03:40:14 52:54:00:85:90:e2 ipv4 192.168.150.231/24 fedora20-test 01:52:54:00:85:90:e2 2014-06-16 03:40:17 52:54:00:85:90:e2 ipv6 2001:db8:ca2:2:1::c0/64 fedora20-test 00:04:b1:d8:86:42:e1:6a:aa:cf:d5:86:94:23:6f:94:04:cd 2014-06-16 03:34:42 52:54:00:e8:73:eb ipv4 192.168.150.181/24 ubuntu14-vm - 2014-06-16 03:34:46 52:54:00:e8:73:eb ipv6 2001:db8:ca2:2:1::5b/64 - 00:01:00:01:1b:30:c6:aa:52:54:00:e8:73:eb tools/virsh.pod * Document new command src/internal.h * Introduce new macro: EMPTYSTR --- src/internal.h | 5 +++ tools/virsh-network.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 6 +++ 3 files changed, 130 insertions(+) diff --git a/src/internal.h b/src/internal.h index 0b36de9..ece5379 100644 --- a/src/internal.h +++ b/src/internal.h @@ -246,6 +246,11 @@ */ # define NULLSTR(s) ((s) ? (s) : "<null>") +/* + * Similar to NULLSTR, but print '-' to make it more user friendly. + */ +# define EMPTYSTR(s) ((s) ? (s) : "-") + /** * TODO: * diff --git a/tools/virsh-network.c b/tools/virsh-network.c index 4b0df62..2d5b9be 100644 --- a/tools/virsh-network.c +++ b/tools/virsh-network.c @@ -1285,6 +1285,119 @@ cmdNetworkEvent(vshControl *ctl, const vshCmd *cmd) } +/* + * "net-dhcp-leases" command + */ +static const vshCmdInfo info_network_dhcp_leases[] = { + {.name = "help", + .data = N_("print lease info for a given network") + }, + {.name = "desc", + .data = N_("Print lease info for a given network") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_network_dhcp_leases[] = { + {.name = "network", + .type = VSH_OT_DATA, + .flags = VSH_OFLAG_REQ, + .help = N_("network name or uuid") + }, + {.name = "mac", + .type = VSH_OT_DATA, + .flags = VSH_OFLAG_NONE, + .help = N_("MAC address") + }, + {.name = NULL} +}; + +static int +vshNetworkDHCPLeaseSorter(const void *a, const void *b) +{ + int rv = -1; + + virNetworkDHCPLeasePtr *lease1 = (virNetworkDHCPLeasePtr *) a; + virNetworkDHCPLeasePtr *lease2 = (virNetworkDHCPLeasePtr *) b; + + if (*lease1 && !*lease2) + return -1; + + if (!*lease1) + return *lease2 != NULL; + + rv = vshStrcasecmp((*lease1)->mac, (*lease2)->mac); + return rv; +} + +static bool +cmdNetworkDHCPLeases(vshControl *ctl, const vshCmd *cmd) +{ + const char *name = NULL; + const char *mac = NULL; + virNetworkDHCPLeasePtr *leases = NULL; + int nleases = 0; + bool ret = false; + size_t i; + unsigned int flags = 0; + virNetworkPtr network = NULL; + + if (vshCommandOptString(cmd, "mac", &mac) < 0) + return false; + + if (!(network = vshCommandOptNetwork(ctl, cmd, &name))) + return false; + + nleases = mac ? virNetworkGetDHCPLeasesForMAC(network, mac, &leases, flags) + : virNetworkGetDHCPLeases(network, &leases, flags); + + if (nleases < 0) { + vshError(ctl, _("Failed to get leases info for %s"), name); + goto cleanup; + } + + /* Sort the list according to MAC Address/IAID */ + qsort(leases, nleases, sizeof(*leases), vshNetworkDHCPLeaseSorter); + + vshPrintExtra(ctl, " %-20s %-18s %-9s %-25s %-15s %s\n%s%s\n", + _("Expiry Time"), _("MAC address"), _("Protocol"), + _("IP address"), _("Hostname"), _("Client ID or DUID"), + "----------------------------------------------------------", + "---------------------------------------------------------"); + + for (i = 0; i < nleases; i++) { + const char *type = NULL; + char *cidr_format = NULL; + virNetworkDHCPLeasePtr lease = leases[i]; + time_t expirytime_tmp = lease->expirytime; + struct tm ts; + char expirytime[32]; + ts = *localtime_r(&expirytime_tmp, &ts); + strftime(expirytime, sizeof(expirytime), "%Y-%m-%d %H:%M:%S", &ts); + + type = (lease->type == VIR_IP_ADDR_TYPE_IPV4) ? "ipv4" : + (lease->type == VIR_IP_ADDR_TYPE_IPV6) ? "ipv6" : ""; + + ignore_value(virAsprintf(&cidr_format, "%s/%d", + lease->ipaddr, lease->prefix)); + + vshPrintExtra(ctl, " %-20s %-18s %-9s %-25s %-15s %s\n", + expirytime, EMPTYSTR(lease->mac), EMPTYSTR(type), cidr_format, + EMPTYSTR(lease->hostname), EMPTYSTR(lease->clientid)); + } + + ret = true; + + cleanup: + if (leases) { + for (i = 0; i < nleases; i++) + virNetworkDHCPLeaseFree(leases[i]); + VIR_FREE(leases); + } + virNetworkFree(network); + return ret; +} + const vshCmdDef networkCmds[] = { {.name = "net-autostart", .handler = cmdNetworkAutostart, @@ -1310,6 +1423,12 @@ const vshCmdDef networkCmds[] = { .info = info_network_destroy, .flags = 0 }, + {.name = "net-dhcp-leases", + .handler = cmdNetworkDHCPLeases, + .opts = opts_network_dhcp_leases, + .info = info_network_dhcp_leases, + .flags = 0, + }, {.name = "net-dumpxml", .handler = cmdNetworkDumpXML, .opts = opts_network_dumpxml, diff --git a/tools/virsh.pod b/tools/virsh.pod index 35cf878..87b77c7 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -2498,6 +2498,12 @@ If I<--current> is specified, affect the current network state. Both I<--live> and I<--config> flags may be given, but I<--current> is exclusive. Not specifying any flag is the same as specifying I<--current>. +=item B<net-dhcp-leases> I<network> [I<mac>] + +Get a list of dhcp leases for all network interfaces connected to the given +virtual I<network> or limited output just for one interface if I<mac> is +specified. + =back =head1 INTERFACE COMMANDS -- 1.9.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list