[libvirt] [PATCHv4 2/4] net-dhcp-leases: Implement the remote protocol

Nehal J Wani nehaljw.kkd1 at gmail.com
Thu Sep 26 08:08:54 UTC 2013


Implement RPC calls for virNetworkGetDHCPLeases, virNetworkGetDHCPLeasesForMAC

daemon/remote.c
   * Define remoteSerializeNetworkDHCPLeases,
            remoteDispatchNetworkGetDHCPLeases
   * Define remoteDispatchNetworkGetDHCPLeasesForMAC
   * Define helper function make_dhcp_lease

src/remote/remote_driver.c
   * Define remoteNetworkGetDHCPLeases
   * Define remoteNetworkGetDHCPLeasesForMAC
   * Define helper function make_dhcp_lease

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              | 157 ++++++++++++++++++++++++++++++++++++++++
 src/remote/remote_driver.c   | 169 ++++++++++++++++++++++++++++++++++++++++++-
 src/remote/remote_protocol.x |  59 ++++++++++++++-
 src/remote_protocol-structs  |  47 ++++++++++++
 src/rpc/gendispatch.pl       |   1 +
 5 files changed, 429 insertions(+), 4 deletions(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 9497cc1..770f62a 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -88,6 +88,7 @@ static void make_nonnull_node_device(remote_nonnull_node_device *dev_dst, virNod
 static void make_nonnull_secret(remote_nonnull_secret *secret_dst, virSecretPtr secret_src);
 static void make_nonnull_nwfilter(remote_nonnull_nwfilter *net_dst, virNWFilterPtr nwfilter_src);
 static void make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src);
+static void make_dhcp_lease(remote_network_dhcp_lease *lease_dst, virNetworkDHCPLeasesPtr lease_src);
 
 static virTypedParameterPtr
 remoteDeserializeTypedParameters(remote_typed_param *args_params_val,
@@ -5209,6 +5210,136 @@ cleanup:
 }
 
 
+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);
+    virNetworkDHCPLeasesPtr *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);
+        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++)
+            make_dhcp_lease(ret->leases.leases_val + i, leases[i]);
+    } 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);
+    virNetworkDHCPLeasesPtr *leases = NULL;
+    virNetworkPtr net = NULL;
+    int nleases = 0;
+    const char *mac = NULL;
+
+    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;
+
+    mac = args->mac;
+
+    if ((nleases = virNetworkGetDHCPLeasesForMAC(net, 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++)
+            make_dhcp_lease(ret->leases.leases_val + i, leases[i]);
+    } 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;
+}
+
 
 /*----- Helpers. -----*/
 
@@ -5343,6 +5474,32 @@ make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDo
     make_nonnull_domain(&snapshot_dst->dom, snapshot_src->domain);
 }
 
+
+/* Copy contents of virNetworkDHCPLeasesPtr to remote_network_dhcp_lease */
+static void
+make_dhcp_lease(remote_network_dhcp_lease *lease_dst, virNetworkDHCPLeasesPtr lease_src)
+{
+    char **hostname_tmp = NULL;
+    char **clientid_tmp = NULL;
+    ignore_value(VIR_ALLOC_QUIET(hostname_tmp));
+    ignore_value(VIR_ALLOC_QUIET(clientid_tmp));
+
+    lease_dst->expirytime = lease_src->expirytime;
+    lease_dst->type = lease_src->type;
+    lease_dst->prefix = lease_src->prefix;
+    if (lease_src->type == VIR_IP_ADDR_TYPE_IPV4)
+        ignore_value(VIR_STRDUP_QUIET(lease_dst->id.remote_interface_id_u.mac,
+                                      lease_src->id.mac));
+    else
+        lease_dst->id.remote_interface_id_u.iaid = lease_src->id.iaid;
+    ignore_value(VIR_STRDUP_QUIET(lease_dst->ipaddr,  lease_src->ipaddr));
+    ignore_value(VIR_STRDUP_QUIET(*hostname_tmp,  lease_src->hostname));
+    ignore_value(VIR_STRDUP_QUIET(*clientid_tmp,  lease_src->clientid));
+    lease_dst->hostname = *hostname_tmp ? hostname_tmp : NULL;
+    lease_dst->clientid = *clientid_tmp ? clientid_tmp : NULL;
+}
+
+
 static int
 remoteSerializeDomainDiskErrors(virDomainDiskErrorPtr errors,
                                 int nerrors,
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 96ccb99..95910b6 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -14,7 +14,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Lesser General Public
+ * You should have received a make of the GNU Lesser General Public
  * License along with this library.  If not, see
  * <http://www.gnu.org/licenses/>.
  *
@@ -150,6 +150,7 @@ static void make_nonnull_storage_vol(remote_nonnull_storage_vol *vol_dst, virSto
 static void make_nonnull_secret(remote_nonnull_secret *secret_dst, virSecretPtr secret_src);
 static void make_nonnull_nwfilter(remote_nonnull_nwfilter *nwfilter_dst, virNWFilterPtr nwfilter_src);
 static void make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src);
+static void make_dhcp_lease(virNetworkDHCPLeasesPtr lease_src, remote_network_dhcp_lease *lease_dst);
 static void remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event);
 /*----------------------------------------------------------------------*/
 
@@ -1058,7 +1059,7 @@ doRemoteClose(virConnectPtr conn, struct private_data *priv)
     virObjectUnref(priv->qemuProgram);
     priv->remoteProgram = priv->qemuProgram = priv->lxcProgram = NULL;
 
-    /* Free hostname copy */
+    /* Free hostname make */
     VIR_FREE(priv->hostname);
 
     /* See comment for remoteType. */
@@ -3756,7 +3757,7 @@ static sasl_callback_t *remoteAuthMakeCallbacks(int *credtype, int ncredtype)
  *
  * Builds up an array of libvirt credential structs, populating
  * with data from the SASL interaction struct. These two structs
- * are basically a 1-to-1 copy of each other.
+ * are basically a 1-to-1 make of each other.
  */
 static int remoteAuthMakeCredentials(sasl_interact_t *interact,
                                      virConnectCredentialPtr *cred,
@@ -6661,6 +6662,143 @@ done:
     return rv;
 }
 
+
+static int
+remoteNetworkGetDHCPLeases(virNetworkPtr net,
+                           virNetworkDHCPLeasesPtr **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;
+
+    virNetworkDHCPLeasesPtr *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;
+
+            make_dhcp_lease(leases_ret[i], &ret.leases.leases_val[i]);
+        }
+
+        *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,
+                                 virNetworkDHCPLeasesPtr **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;
+
+    virNetworkDHCPLeasesPtr *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;
+
+            make_dhcp_lease(leases_ret[i], &ret.leases.leases_val[i]);
+        }
+
+        *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;
+}
+
+
 static void
 remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event)
 {
@@ -6793,6 +6931,29 @@ make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDo
     make_nonnull_domain(&snapshot_dst->dom, snapshot_src->domain);
 }
 
+
+/* Copy contents of remote_network_dhcp_lease to virNetworkDHCPLeasesPtr */
+static void
+make_dhcp_lease(virNetworkDHCPLeasesPtr 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 (lease_src->type == VIR_IP_ADDR_TYPE_IPV4)
+        ignore_value(VIR_STRDUP_QUIET(lease_dst->id.mac,
+                                      lease_src->id.remote_interface_id_u.mac));
+    else
+        lease_dst->id.iaid = lease_src->id.remote_interface_id_u.iaid;
+    ignore_value(VIR_STRDUP_QUIET(lease_dst->ipaddr, lease_src->ipaddr));
+    if (lease_src->hostname)
+        ignore_value(VIR_STRDUP_QUIET(lease_dst->hostname, *lease_src->hostname));
+    else
+        lease_dst->hostname = NULL;
+    if (lease_src->clientid)
+        ignore_value(VIR_STRDUP_QUIET(lease_dst->clientid, *lease_src->clientid));
+    else
+        lease_dst->clientid = NULL;
+}
 /*----------------------------------------------------------------------*/
 
 unsigned long remoteVersion(void)
@@ -7021,6 +7182,8 @@ static virNetworkDriver network_driver = {
     .networkSetAutostart = remoteNetworkSetAutostart, /* 0.3.0 */
     .networkIsActive = remoteNetworkIsActive, /* 0.7.3 */
     .networkIsPersistent = remoteNetworkIsPersistent, /* 0.7.3 */
+    .networkGetDHCPLeases = remoteNetworkGetDHCPLeases, /* 1.1.3 */
+    .networkGetDHCPLeasesForMAC = remoteNetworkGetDHCPLeasesForMAC, /* 1.1.3 */
 };
 
 static virInterfaceDriver interface_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 8d17bad..c630951 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -235,6 +235,11 @@ const REMOTE_DOMAIN_JOB_STATS_MAX = 16;
 /* Upper limit on number of CPU models */
 const REMOTE_CONNECT_CPU_MODELS_MAX = 8192;
 
+/*
+ * Upper limit on the maximum number of leases in one lease file
+ */
+const REMOTE_NETWORK_DHCP_LEASES_MAX = 32768;
+
 /* UUID.  VIR_UUID_BUFLEN definition comes from libvirt.h */
 typedef opaque remote_uuid[VIR_UUID_BUFLEN];
 
@@ -2849,6 +2854,46 @@ struct remote_connect_get_cpu_model_names_ret {
     int ret;
 };
 
+union remote_interface_id switch (int type) {
+case VIR_IP_ADDR_TYPE_IPV4:
+    remote_nonnull_string mac;
+case VIR_IP_ADDR_TYPE_IPV6:
+    unsigned hyper iaid;
+};
+
+struct remote_network_dhcp_lease {
+    hyper expirytime;
+    remote_interface_id id;
+    remote_nonnull_string ipaddr;
+    remote_string hostname;
+    remote_string clientid;
+    int type;
+    unsigned int prefix;
+};
+
+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<REMOTE_NETWORK_DHCP_LEASES_MAX>;
+    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<REMOTE_NETWORK_DHCP_LEASES_MAX>;
+    unsigned int ret;
+};
+
 /*----- Protocol. -----*/
 
 /* Define the program number, protocol version and procedure numbers here. */
@@ -5018,5 +5063,17 @@ enum remote_procedure {
      * @generate: none
      * @acl: connect:read
      */
-    REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES = 312
+    REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES = 312,
+
+    /**
+     * @generate: none
+     * @acl: network:read
+     */
+    REMOTE_PROC_NETWORK_GET_DHCP_LEASES = 313,
+
+    /**
+     * @generate: none
+     * @acl: network:read
+     */
+    REMOTE_PROC_NETWORK_GET_DHCP_LEASES_FOR_MAC = 314
 };
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 98d2d5b..b6779d5 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -8,6 +8,10 @@ enum {
         VIR_TYPED_PARAM_BOOLEAN = 6,
         VIR_TYPED_PARAM_STRING = 7,
 };
+enum {
+        VIR_IP_ADDR_TYPE_IPV4 = 0,
+        VIR_IP_ADDR_TYPE_IPV6 = 1,
+};
 struct remote_nonnull_domain {
         remote_nonnull_string      name;
         remote_uuid                uuid;
@@ -2328,6 +2332,47 @@ struct remote_connect_get_cpu_model_names_ret {
         } models;
         int                        ret;
 };
+struct remote_dhcp_interface_id {
+        int                        type;
+        union {
+                remote_nonnull_string mac;
+                uint64_t           iaid;
+        } remote_interface_id_u;
+};
+struct remote_network_dhcp_lease {
+        int64_t                    expirytime;
+        remote_interface_id   id;
+        remote_nonnull_string      ipaddr;
+        remote_string              hostname;
+        remote_string              clientid;
+        int                        type;
+        u_int                      prefix;
+};
+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,
@@ -2641,4 +2686,6 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_CREATE_WITH_FILES = 310,
         REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED = 311,
         REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES = 312,
+        REMOTE_PROC_NETWORK_GET_DHCP_LEASES = 313,
+        REMOTE_PROC_NETWORK_GET_DHCP_LEASES_FOR_MAC = 314,
 };
diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
index ceb1ad8..5a503cf 100755
--- a/src/rpc/gendispatch.pl
+++ b/src/rpc/gendispatch.pl
@@ -66,6 +66,7 @@ sub fixup_name {
     $name =~ s/Fstrim$/FSTrim/;
     $name =~ s/Scsi/SCSI/;
     $name =~ s/Wwn$/WWN/;
+    $name =~ s/Dhcp$/DHCP/;
 
     return $name;
 }
-- 
1.7.11.7




More information about the libvir-list mailing list