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