From 990c3b6554e193db7b235d7aea4d5f97d1001b4d Mon Sep 17 00:00:00 2001 From: Nehal J Wani Date: Tue, 24 Jun 2014 02:31:50 +0530 Subject: [PATCH] net-dhcp-leases: Implement the remote protocol Implement RPC calls for virNetworkGetDHCPLeases, virNetworkGetDHCPLeasesForMAC daemon/remote.c * Define remoteSerializeNetworkDHCPLeases, remoteDispatchNetworkGetDHCPLeases * Define remoteDispatchNetworkGetDHCPLeasesForMAC * Define helper function remoteSerializeDHCPLease src/remote/remote_driver.c * Define remoteNetworkGetDHCPLeases * Define remoteNetworkGetDHCPLeasesForMAC * Define helper function remoteSerializeDHCPLease src/remote/remote_protocol.x * New RPC procedure: REMOTE_PROC_NETWORK_GET_DHCP_LEASES * Define structs remote_network_dhcp_leases, remote_network_get_dhcp_leases_args, remote_network_get_dhcp_leases_ret * New RPC procedure: REMOTE_PROC_NETWORK_GET_DHCP_LEASES_FOR_MAC * Define structs remote_network_dhcp_leases_for_mac, remote_network_get_dhcp_leases_for_mac_args, remote_network_get_dhcp_leases_for_mac_ret src/remote_protocol-structs * New structs added src/rpc/gendispatch.pl * Add exception (s/Dhcp/DHCP) for auto-generating names of the remote functions in daemon/remote_dispatch.h --- daemon/remote.c | 183 ++++++++++++++++++++++++++++++++++ src/remote/remote_driver.c | 186 +++++++++++++++++++++++++++++++++++ src/remote/remote_protocol.x | 51 +++++++++- src/remote_protocol-structs | 38 +++++++ src/rpc/gendispatch.pl | 1 + 5 files changed, 458 insertions(+), 1 deletion(-) diff --git a/daemon/remote.c b/daemon/remote.c index d09ebadc34..f4ec8eaccf 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -6202,7 +6202,190 @@ remoteDispatchNodeGetFreePages(virNetServerPtr server ATTRIBUTE_UNUSED, VIR_FREE(ret->counts.counts_val); } return rv; +} +/* Copy contents of virNetworkDHCPLeasePtr to remote_network_dhcp_lease */ +static int +remoteSerializeDHCPLease(remote_network_dhcp_lease *lease_dst, virNetworkDHCPLeasePtr lease_src) +{ + char **mac_tmp = NULL; + char **iaid_tmp = NULL; + char **hostname_tmp = NULL; + char **clientid_tmp = NULL; + + if (VIR_ALLOC(mac_tmp) < 0 || + VIR_ALLOC(iaid_tmp) < 0 || + VIR_ALLOC(hostname_tmp) < 0 || + VIR_ALLOC(clientid_tmp) < 0) + goto error; + + lease_dst->expirytime = lease_src->expirytime; + lease_dst->type = lease_src->type; + lease_dst->prefix = lease_src->prefix; + + if (VIR_STRDUP(lease_dst->interface, lease_src->interface) < 0 || + VIR_STRDUP(lease_dst->ipaddr, lease_src->ipaddr) < 0 || + VIR_STRDUP(*mac_tmp, lease_src->mac) < 0 || + VIR_STRDUP(*iaid_tmp, lease_src->iaid) < 0 || + VIR_STRDUP(*hostname_tmp, lease_src->hostname) < 0 || + VIR_STRDUP(*clientid_tmp, lease_src->clientid) < 0) + goto error; + + lease_dst->mac = *mac_tmp ? mac_tmp : NULL; + lease_dst->iaid = *iaid_tmp ? iaid_tmp : NULL; + lease_dst->hostname = *hostname_tmp ? hostname_tmp : NULL; + lease_dst->clientid = *clientid_tmp ? clientid_tmp : NULL; + + return 0; + + error: + VIR_FREE(*mac_tmp); + VIR_FREE(*iaid_tmp); + VIR_FREE(*hostname_tmp); + VIR_FREE(*clientid_tmp); + VIR_FREE(mac_tmp); + VIR_FREE(iaid_tmp); + VIR_FREE(hostname_tmp); + VIR_FREE(clientid_tmp); + VIR_FREE(lease_dst->ipaddr); + VIR_FREE(lease_dst->interface); + return -1; +} + + +static int +remoteDispatchNetworkGetDHCPLeases(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_network_get_dhcp_leases_args *args, + remote_network_get_dhcp_leases_ret *ret) +{ + int rv = -1; + size_t i; + struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client); + virNetworkDHCPLeasePtr *leases = NULL; + virNetworkPtr net = NULL; + int nleases = 0; + + if (!priv->conn) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(net = get_nonnull_network(priv->conn, args->net))) + goto cleanup; + + if ((nleases = virNetworkGetDHCPLeases(net, + args->need_results ? &leases : NULL, + args->flags)) < 0) + goto cleanup; + + if (nleases > REMOTE_NETWORK_DHCP_LEASES_MAX) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Number of leases is %d, which exceeds max limit: %d"), + nleases, REMOTE_NETWORK_DHCP_LEASES_MAX); + goto cleanup; + } + + if (leases && nleases) { + if (VIR_ALLOC_N(ret->leases.leases_val, nleases) < 0) + goto cleanup; + + ret->leases.leases_len = nleases; + + for (i = 0; i < nleases; i++) { + if (remoteSerializeDHCPLease(ret->leases.leases_val + i, leases[i]) < 0) + goto cleanup; + } + + } else { + ret->leases.leases_len = 0; + ret->leases.leases_val = NULL; + } + + ret->ret = nleases; + + rv = 0; + + cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + if (leases) { + for (i = 0; i < nleases; i++) + virNetworkDHCPLeaseFree(leases[i]); + VIR_FREE(leases); + } + virNetworkFree(net); + return rv; +} + + +static int +remoteDispatchNetworkGetDHCPLeasesForMAC(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_network_get_dhcp_leases_for_mac_args *args, + remote_network_get_dhcp_leases_for_mac_ret *ret) +{ + int rv = -1; + size_t i; + struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client); + virNetworkDHCPLeasePtr *leases = NULL; + virNetworkPtr net = NULL; + int nleases = 0; + + if (!priv->conn) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(net = get_nonnull_network(priv->conn, args->net))) + goto cleanup; + + if ((nleases = virNetworkGetDHCPLeasesForMAC(net, args->mac, + args->need_results ? &leases : NULL, + args->flags)) < 0) + goto cleanup; + + if (nleases > REMOTE_NETWORK_DHCP_LEASES_MAX) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Number of leases is %d, which exceeds max limit: %d"), + nleases, REMOTE_NETWORK_DHCP_LEASES_MAX); + return -1; + } + + if (leases && nleases) { + if (VIR_ALLOC_N(ret->leases.leases_val, nleases) < 0) + goto cleanup; + + ret->leases.leases_len = nleases; + + for (i = 0; i < nleases; i++) { + if (remoteSerializeDHCPLease(ret->leases.leases_val + i, leases[i]) < 0) + goto cleanup; + } + + } else { + ret->leases.leases_len = 0; + ret->leases.leases_val = NULL; + } + + ret->ret = nleases; + + rv = 0; + + cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + if (leases) { + for (i = 0; i < nleases; i++) + virNetworkDHCPLeaseFree(leases[i]); + VIR_FREE(leases); + } + virNetworkFree(net); + return rv; } diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index bef9fd769f..af79cb55dd 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -7549,6 +7549,190 @@ remoteNodeGetFreePages(virConnectPtr conn, } +/* Copy contents of remote_network_dhcp_lease to virNetworkDHCPLeasePtr */ +static int +remoteSerializeDHCPLease(virNetworkDHCPLeasePtr lease_dst, remote_network_dhcp_lease *lease_src) +{ + lease_dst->expirytime = lease_src->expirytime; + lease_dst->type = lease_src->type; + lease_dst->prefix = lease_src->prefix; + + if (VIR_STRDUP(lease_dst->interface, lease_src->interface) < 0) + goto error; + + if (VIR_STRDUP(lease_dst->ipaddr, lease_src->ipaddr) < 0) + goto error; + + if (lease_src->mac) { + if (VIR_STRDUP(lease_dst->mac, *lease_src->mac) < 0) + goto error; + } else { + lease_src->mac = NULL; + } + + if (lease_src->iaid) { + if (VIR_STRDUP(lease_dst->iaid, *lease_src->iaid) < 0) + goto error; + } else { + lease_src->iaid = NULL; + } + + if (lease_src->hostname) { + if (VIR_STRDUP(lease_dst->hostname, *lease_src->hostname) < 0) + goto error; + } else { + lease_src->hostname = NULL; + } + + if (lease_src->clientid) { + if (VIR_STRDUP(lease_dst->clientid, *lease_src->clientid) < 0) + goto error; + } else { + lease_src->clientid = NULL; + } + + return 0; + + error: + virNetworkDHCPLeaseFree(lease_dst); + return -1; +} + + +static int +remoteNetworkGetDHCPLeases(virNetworkPtr net, + virNetworkDHCPLeasePtr **leases, + unsigned int flags) +{ + int rv = -1; + size_t i; + struct private_data *priv = net->conn->networkPrivateData; + remote_network_get_dhcp_leases_args args; + remote_network_get_dhcp_leases_ret ret; + + virNetworkDHCPLeasePtr *leases_ret = NULL; + remoteDriverLock(priv); + + make_nonnull_network(&args.net, net); + args.flags = flags; + args.need_results = !!leases; + + memset(&ret, 0, sizeof(ret)); + + if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_GET_DHCP_LEASES, + (xdrproc_t)xdr_remote_network_get_dhcp_leases_args, (char *)&args, + (xdrproc_t)xdr_remote_network_get_dhcp_leases_ret, (char *)&ret) == -1) + goto done; + + if (ret.leases.leases_len > REMOTE_NETWORK_DHCP_LEASES_MAX) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Number of leases is %d, which exceeds max limit: %d"), + ret.leases.leases_len, REMOTE_NETWORK_DHCP_LEASES_MAX); + goto cleanup; + } + + if (leases) { + if (ret.leases.leases_len && + VIR_ALLOC_N(leases_ret, ret.leases.leases_len + 1) < 0) + goto cleanup; + + for (i = 0; i < ret.leases.leases_len; i++) { + if (VIR_ALLOC(leases_ret[i]) < 0) + goto cleanup; + + if (remoteSerializeDHCPLease(leases_ret[i], &ret.leases.leases_val[i]) < 0) + goto cleanup; + } + + *leases = leases_ret; + leases_ret = NULL; + } + + rv = ret.ret; + + cleanup: + if (leases_ret) { + for (i = 0; i < ret.leases.leases_len; i++) + virNetworkDHCPLeaseFree(leases_ret[i]); + VIR_FREE(leases_ret); + } + xdr_free((xdrproc_t)xdr_remote_network_get_dhcp_leases_ret, + (char *) &ret); + + done: + remoteDriverUnlock(priv); + return rv; +} + + +static int +remoteNetworkGetDHCPLeasesForMAC(virNetworkPtr net, + const char *mac, + virNetworkDHCPLeasePtr **leases, + unsigned int flags) +{ + int rv = -1; + size_t i; + struct private_data *priv = net->conn->networkPrivateData; + remote_network_get_dhcp_leases_for_mac_args args; + remote_network_get_dhcp_leases_for_mac_ret ret; + + virNetworkDHCPLeasePtr *leases_ret = NULL; + remoteDriverLock(priv); + + make_nonnull_network(&args.net, net); + args.mac = (char *) mac; + args.flags = flags; + args.need_results = !!leases; + + memset(&ret, 0, sizeof(ret)); + + if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_GET_DHCP_LEASES_FOR_MAC, + (xdrproc_t)xdr_remote_network_get_dhcp_leases_for_mac_args, (char *)&args, + (xdrproc_t)xdr_remote_network_get_dhcp_leases_for_mac_ret, (char *)&ret) == -1) + goto done; + + if (ret.leases.leases_len > REMOTE_NETWORK_DHCP_LEASES_MAX) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Number of leases is %d, which exceeds max limit: %d"), + ret.leases.leases_len, REMOTE_NETWORK_DHCP_LEASES_MAX); + goto cleanup; + } + + if (leases) { + if (ret.leases.leases_len && + VIR_ALLOC_N(leases_ret, ret.leases.leases_len + 1) < 0) + goto cleanup; + + for (i = 0; i < ret.leases.leases_len; i++) { + if (VIR_ALLOC(leases_ret[i]) < 0) + goto cleanup; + + if (remoteSerializeDHCPLease(leases_ret[i], &ret.leases.leases_val[i]) < 0) + goto cleanup; + } + + *leases = leases_ret; + leases_ret = NULL; + } + + rv = ret.ret; + + cleanup: + if (leases_ret) { + for (i = 0; i < ret.leases.leases_len; i++) + virNetworkDHCPLeaseFree(leases_ret[i]); + VIR_FREE(leases_ret); + } + xdr_free((xdrproc_t)xdr_remote_network_get_dhcp_leases_for_mac_ret, + (char *) &ret); + + done: + remoteDriverUnlock(priv); + return rv; +} + + /* get_nonnull_domain and get_nonnull_network turn an on-wire * (name, uuid) pair into virDomainPtr or virNetworkPtr object. * These can return NULL if underlying memory allocations fail, @@ -7913,6 +8097,8 @@ static virNetworkDriver network_driver = { .networkSetAutostart = remoteNetworkSetAutostart, /* 0.3.0 */ .networkIsActive = remoteNetworkIsActive, /* 0.7.3 */ .networkIsPersistent = remoteNetworkIsPersistent, /* 0.7.3 */ + .networkGetDHCPLeases = remoteNetworkGetDHCPLeases, /* 1.2.6 */ + .networkGetDHCPLeasesForMAC = remoteNetworkGetDHCPLeasesForMAC, /* 1.2.6 */ }; static virInterfaceDriver interface_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 50b1888386..b5f44f7503 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -238,6 +238,9 @@ const REMOTE_CONNECT_CPU_MODELS_MAX = 8192; /* Upper limit on number of mountpoints to frozen */ const REMOTE_DOMAIN_FSFREEZE_MOUNTPOINTS_MAX = 256; +/* Upper limit on the maximum number of leases in one lease file */ +const REMOTE_NETWORK_DHCP_LEASES_MAX = 65536; + /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */ typedef opaque remote_uuid[VIR_UUID_BUFLEN]; @@ -3018,6 +3021,40 @@ struct remote_node_get_free_pages_ret { unsigned hyper counts; }; +struct remote_network_dhcp_lease { + remote_nonnull_string interface; + hyper expirytime; + int type; + remote_string mac; + remote_string iaid; + remote_nonnull_string ipaddr; + unsigned int prefix; + remote_string hostname; + remote_string clientid; +}; + +struct remote_network_get_dhcp_leases_args { + remote_nonnull_network net; + int need_results; + unsigned int flags; +}; + +struct remote_network_get_dhcp_leases_ret { + remote_network_dhcp_lease leases; + unsigned int ret; +}; + +struct remote_network_get_dhcp_leases_for_mac_args { + remote_nonnull_network net; + remote_nonnull_string mac; + int need_results; + unsigned int flags; +}; + +struct remote_network_get_dhcp_leases_for_mac_ret { + remote_network_dhcp_lease leases; + unsigned int ret; +}; /*----- Protocol. -----*/ @@ -5370,5 +5407,17 @@ enum remote_procedure { * @priority: high * @acl: connect:read */ - REMOTE_PROC_NODE_GET_FREE_PAGES = 340 + REMOTE_PROC_NODE_GET_FREE_PAGES = 340, + + /** + * @generate: none + * @acl: network:read + */ + REMOTE_PROC_NETWORK_GET_DHCP_LEASES = 341, + + /** + * @generate: none + * @acl: network:read + */ + REMOTE_PROC_NETWORK_GET_DHCP_LEASES_FOR_MAC = 342 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 03268f5592..d363247925 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2485,6 +2485,42 @@ struct remote_node_get_free_pages_ret { uint64_t * counts_val; } counts; }; +struct remote_network_dhcp_lease { + remote_nonnull_string interface; + int64_t expirytime; + int type; + remote_string mac; + remote_string iaid; + remote_nonnull_string ipaddr; + u_int prefix; + remote_string hostname; + remote_string clientid; +}; +struct remote_network_get_dhcp_leases_args { + remote_nonnull_network net; + int need_results; + u_int flags; +}; +struct remote_network_get_dhcp_leases_ret { + struct { + u_int leases_len; + remote_network_dhcp_lease * leases_val; + } leases; + u_int ret; +}; +struct remote_network_get_dhcp_leases_for_mac_args { + remote_nonnull_network net; + remote_nonnull_string mac; + int need_results; + u_int flags; +}; +struct remote_network_get_dhcp_leases_for_mac_ret { + struct { + u_int leases_len; + remote_network_dhcp_lease * leases_val; + } leases; + u_int ret; +}; enum remote_procedure { REMOTE_PROC_CONNECT_OPEN = 1, REMOTE_PROC_CONNECT_CLOSE = 2, @@ -2826,4 +2862,6 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_SET_TIME = 338, REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_2 = 339, REMOTE_PROC_NODE_GET_FREE_PAGES = 340, + REMOTE_PROC_NETWORK_GET_DHCP_LEASES = 341, + REMOTE_PROC_NETWORK_GET_DHCP_LEASES_FOR_MAC = 342, }; diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl index 9cd620e0e5..d820d0ef37 100755 --- a/src/rpc/gendispatch.pl +++ b/src/rpc/gendispatch.pl @@ -68,6 +68,7 @@ sub fixup_name { $name =~ s/Fsthaw$/FSThaw/; $name =~ s/Scsi/SCSI/; $name =~ s/Wwn$/WWN/; + $name =~ s/Dhcp$/DHCP/; return $name; }