[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Libvir] [patch 07/12] Add dnsmasq support.



Add support for starting dnsmasq and a <dhcp> element to configure
the behaviour of the dhcp server.

Note, there's quite a bit more interesting stuff we can do with
dnsmasq to e.g. pre-define a set of mac <-> ip address mappings
but we can add that later.

Signed-off-by: Mark McLoughlin <markmc redhat com>

Index: libvirt-foo/qemud/conf.c
===================================================================
--- libvirt-foo.orig/qemud/conf.c	2007-02-14 15:59:02.000000000 +0000
+++ libvirt-foo.orig/qemud/conf.c	2007-02-14 15:59:02.000000000 +0000
@@ -1099,6 +1099,12 @@ struct qemud_vm *qemudLoadConfigXML(stru
 
 
 void qemudFreeNetwork(struct qemud_network *network) {
+    struct qemud_dhcp_range_def *range = network->def.ranges;
+    while (range) {
+        struct qemud_dhcp_range_def *next = range->next;
+        free(range);
+        range = next;
+    }
     free(network);
 }
 
@@ -1177,11 +1183,61 @@ static int qemudParseBridgeXML(struct qe
     return 1;
 }
 
+static int qemudParseDhcpRangesXML(struct qemud_server *server,
+                                   struct qemud_network *network,
+                                   xmlNodePtr node) {
+
+    xmlNodePtr cur;
+
+    cur = node->children;
+    while (cur != NULL) {
+        struct qemud_dhcp_range_def *range;
+        xmlChar *start, *end;
+
+        if (cur->type != XML_ELEMENT_NODE ||
+            !xmlStrEqual(cur->name, BAD_CAST "range")) {
+            cur = cur->next;
+            continue;
+        }
+
+        if (!(range = calloc(1, sizeof(struct qemud_dhcp_range_def)))) {
+            qemudReportError(server, VIR_ERR_NO_MEMORY, "range");
+            return 0;
+        }
+
+        start = xmlGetProp(cur, BAD_CAST "start");
+        end = xmlGetProp(cur, BAD_CAST "end");
+
+        if (start && start[0] && end && end[0]) {
+            strncpy(range->start, (const char *)start, BR_INET_ADDR_MAXLEN-1);
+            range->start[BR_INET_ADDR_MAXLEN-1] = '\0';
+
+            strncpy(range->end, (const char *)end, BR_INET_ADDR_MAXLEN-1);
+            range->end[BR_INET_ADDR_MAXLEN-1] = '\0';
+
+            range->next = network->def.ranges;
+            network->def.ranges = range;
+            network->def.nranges++;
+        } else {
+            free(range);
+        }
+
+        if (start)
+            xmlFree(start);
+        if (end)
+            xmlFree(end);
+
+        cur = cur->next;
+    }
+
+    return 1;
+}
 
 static int qemudParseInetXML(struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_network *network,
                              xmlNodePtr node) {
     xmlChar *address, *netmask;
+    xmlNodePtr cur;
 
     address = xmlGetProp(node, BAD_CAST "address");
     if (address != NULL) {
@@ -1199,6 +1255,15 @@ static int qemudParseInetXML(struct qemu
         netmask = NULL;
     }
 
+    cur = node->children;
+    while (cur != NULL) {
+        if (cur->type == XML_ELEMENT_NODE &&
+            xmlStrEqual(cur->name, BAD_CAST "dhcp") &&
+            !qemudParseDhcpRangesXML(server, network, cur))
+            return 0;
+        cur = cur->next;
+    }
+
     return 1;
 }
 
@@ -1724,7 +1789,24 @@ char *qemudGenerateNetworkXML(struct qem
             qemudBufferPrintf(&buf, " netmask='%s'", network->def.netmask) < 0)
             goto no_memory;
 
-        if (qemudBufferAdd(&buf, "/>\n") < 0)
+        if (qemudBufferAdd(&buf, ">\n") < 0)
+            goto no_memory;
+
+        if (network->def.ranges) {
+            struct qemud_dhcp_range_def *range = network->def.ranges;
+            if (qemudBufferAdd(&buf, "    <dhcp>\n") < 0)
+                goto no_memory;
+            while (range) {
+                if (qemudBufferPrintf(&buf, "      <range start='%s' end='%s' />\n",
+                                      range->start, range->end) < 0)
+                    goto no_memory;
+                range = range->next;
+            }
+            if (qemudBufferAdd(&buf, "    </dhcp>\n") < 0)
+                goto no_memory;
+        }
+
+        if (qemudBufferAdd(&buf, "  </ip>\n") < 0)
             goto no_memory;
     }
 
Index: libvirt-foo/qemud/internal.h
===================================================================
--- libvirt-foo.orig/qemud/internal.h	2007-02-14 15:59:02.000000000 +0000
+++ libvirt-foo.orig/qemud/internal.h	2007-02-14 15:59:02.000000000 +0000
@@ -200,6 +200,14 @@ struct qemud_vm {
     struct qemud_vm *next;
 };
 
+/* Store start and end addresses of a dhcp range */
+struct qemud_dhcp_range_def {
+    char start[BR_INET_ADDR_MAXLEN];
+    char end[BR_INET_ADDR_MAXLEN];
+
+    struct qemud_dhcp_range_def *next;
+};
+
 /* Virtual Network main configuration */
 struct qemud_network_def {
     unsigned char uuid[QEMUD_UUID_RAW_LEN];
@@ -211,6 +219,9 @@ struct qemud_network_def {
 
     char ipAddress[BR_INET_ADDR_MAXLEN];
     char netmask[BR_INET_ADDR_MAXLEN];
+
+    int nranges;
+    struct qemud_dhcp_range_def *ranges;
 };
 
 /* Virtual Network runtime state */
@@ -220,6 +231,7 @@ struct qemud_network {
     struct qemud_network_def def;
 
     char bridge[BR_IFNAME_MAXLEN];
+    int dnsmasqPid;
 
     unsigned int active : 1;
 
Index: libvirt-foo/qemud/qemud.c
===================================================================
--- libvirt-foo.orig/qemud/qemud.c	2007-02-14 15:59:02.000000000 +0000
+++ libvirt-foo.orig/qemud/qemud.c	2007-02-14 15:59:02.000000000 +0000
@@ -703,6 +703,105 @@ static int qemudDispatchVMFailure(struct
     return 0;
 }
 
+static int
+qemudBuildDnsmasqArgv(struct qemud_server *server,
+                      struct qemud_network *network,
+                      char ***argv) {
+    int i, len;
+    char buf[BR_INET_ADDR_MAXLEN * 2];
+    struct qemud_dhcp_range_def *range;
+
+    len =
+        1 + /* dnsmasq */
+        1 + /* --keep-in-foreground */
+        1 + /* --bind-interfaces */
+        2 + /* --pid-file "" */
+        2 + /* --conf-file "" */
+        2 + /* --except-interface lo */
+        2 + /* --listen-address 10.0.0.1 */
+        (2 * network->def.nranges) + /* --dhcp-range 10.0.0.2,10.0.0.254 */
+        1;  /* NULL */
+
+    if (!(*argv = malloc(len * sizeof(char *))))
+        goto no_memory;
+
+    memset(*argv, 0, len * sizeof(char *));
+
+#define APPEND_ARG(v, n, s) do {     \
+        if (!((v)[(n)] = strdup(s))) \
+            goto no_memory;          \
+    } while (0)
+
+    i = 0;
+
+    APPEND_ARG(*argv, i++, "dnsmasq");
+
+    APPEND_ARG(*argv, i++, "--keep-in-foreground");
+    APPEND_ARG(*argv, i++, "--bind-interfaces");
+
+    APPEND_ARG(*argv, i++, "--pid-file");
+    APPEND_ARG(*argv, i++, "");
+
+    APPEND_ARG(*argv, i++, "--conf-file");
+    APPEND_ARG(*argv, i++, "");
+
+    APPEND_ARG(*argv, i++, "--except-interface");
+    APPEND_ARG(*argv, i++, "lo");
+
+    APPEND_ARG(*argv, i++, "--listen-address");
+    APPEND_ARG(*argv, i++, network->def.ipAddress);
+
+    range = network->def.ranges;
+    while (range) {
+        snprintf(buf, sizeof(buf), "%s,%s",
+                 range->start, range->end);
+
+        APPEND_ARG(*argv, i++, "--dhcp-range");
+        APPEND_ARG(*argv, i++, buf);
+
+        range = range->next;
+    }
+
+#undef APPEND_ARG
+
+    return 0;
+
+ no_memory:
+    if (argv) {
+        for (i = 0; (*argv)[i]; i++)
+            free((*argv)[i]);
+        free(*argv);
+    }
+    qemudReportError(server, VIR_ERR_NO_MEMORY, "dnsmasq argv");
+    return -1;
+}
+
+
+static int
+dhcpStartDhcpDaemon(struct qemud_server *server,
+                    struct qemud_network *network)
+{
+    char **argv;
+    int ret, i;
+
+    if (network->def.ipAddress[0] == '\0') {
+        qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
+                         "cannot start dhcp daemon without IP address for server");
+        return -1;
+    }
+
+    argv = NULL;
+    if (qemudBuildDnsmasqArgv(server, network, &argv) < 0)
+        return -1;
+
+    ret = qemudExec(server, argv, &network->dnsmasqPid, NULL, NULL);
+
+    for (i = 0; argv[i]; i++)
+        free(argv[i]);
+    free(argv);
+
+    return ret;
+}
 
 int qemudStartNetworkDaemon(struct qemud_server *server,
                             struct qemud_network *network) {
@@ -758,10 +857,21 @@ int qemudStartNetworkDaemon(struct qemud
         goto err_delbr;
     }
 
+    if (network->def.ranges &&
+        dhcpStartDhcpDaemon(server, network) < 0)
+        goto err_delbr1;
+
     network->active = 1;
 
     return 0;
 
+ err_delbr1:
+    if (network->def.ipAddress[0] &&
+        (err = brSetInterfaceUp(server->brctl, network->bridge, 0))) {
+        printf("Damn! Failed to bring down bridge '%s' : %s\n",
+               network->bridge, strerror(err));
+    }
+
  err_delbr:
     if ((err = brDeleteBridge(server->brctl, network->bridge))) {
         printf("Damn! Couldn't delete bridge '%s' : %s\n",
@@ -780,6 +890,9 @@ int qemudShutdownNetworkDaemon(struct qe
     if (!network->active)
         return 0;
 
+    if (network->dnsmasqPid > 0)
+        kill(network->dnsmasqPid, SIGTERM);
+
     if (network->def.ipAddress[0] &&
         (err = brSetInterfaceUp(server->brctl, network->bridge, 0))) {
         printf("Damn! Failed to bring down bridge '%s' : %s\n",
@@ -812,7 +925,15 @@ int qemudShutdownNetworkDaemon(struct qe
         curr = curr->next;
     }
 
+    if (network->dnsmasqPid > 0 &&
+        waitpid(network->dnsmasqPid, NULL, WNOHANG) != network->dnsmasqPid) {
+        kill(network->dnsmasqPid, SIGKILL);
+        if (waitpid(network->dnsmasqPid, NULL, 0) != network->dnsmasqPid)
+            printf("Got unexpected pid for dnsmasq, damn\n");
+    }
+
     network->bridge[0] = '\0';
+    network->dnsmasqPid = -1;
     network->active = 0;
 
     return 0;

-- 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]