diff --git a/ChangeLog b/ChangeLog index 21207d84c3..7373e45b78 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,21 +1,115 @@ -Tue Feb 14 15:03:22 EST 2007 Mark McLoughlin +Tue Feb 14 16:04:48 IST 2007 Mark McLoughlin + + * qemud/conf.c, qemud/internal.h: add dhcp config + + * qemud/qemud.c: start dnsmasq to provide dns/dhcp + for virtual networks. + +Tue Feb 14 16:02:23 IST 2007 Mark McLoughlin + + * configure.in: add --disable-bridge-params, check + for libsysfs and various kernel headers + + * bridge.[ch]: add code for managing bridges + + * qemud/Makefile.am: add bridge.[ch] and link against + libsysfs if enabled. + + * qemud/conf.c: add support for bridge config. + + * qemud/internal.h: add various bridging bits + + * qemud/qemud.c: implement qemudStartNetworkDaemon() + and qemudShutdownNetworkDaemon(). + +Tue Feb 14 15:55:02 IST 2007 Mark McLoughlin + + * qemud/conf.[ch]: implement parsing and saving network + configs. + + * qemud/driver.c: flesh out the stubs + + * qemud/internal.h: add networks list etc. to + struct qemud_server + + * qemud/qemud.c: add qemudStartNetworkDaemon() and + qemudShutdownNetworkDaemon() stubs. + +Tue Feb 14 15:52:34 EST 2007 Mark McLoughlin + + * qemud/protocol.h: add the protocol for virtual networks + + * qemud/dispatch.c: implement the protocol + + * qemud/driver.[ch]: add stubs for the driver + + * qemud/internal.h: add struct qemud_network + + * src/qemu_internal.c: add a virtual networks driver + +Tue Feb 14 15:43:28 IST 2007 Mark McLoughlin + + * src/virsh.c: add the net-* commands. + +Tue Feb 14 15:37:17 IST 2007 Mark McLoughlin + + Note: potential ABI break here, but people should + only really be using virError structs returned from + libvirt itself. + + * include/libvirt/virterror.h: add virNetwork + to virError + + * src/internal.h, src/virterror.c: add network param + to __virRaiseError() + + * src/conf.c, src/hash.c, src/libvirt.c, src/proxy_internal.c, + src/qemu_internal.c, src/sexpr.c, src/test.c, src/xen_internal.c, + src/xend_internal.c, src/xm_internal.c, src/xml.c, src/xmlrpc.c, + src/xs_internal.c: update. + +Tue Feb 14 15:33:05 IST 2007 Mark McLoughlin + + * include/libvirt/libvirt.h.in: add the networks APIs + + * include/libvirt/virterror.h: add some error codes + + * src/driver.h: add network driver vtable + + * src/hash.c: add networks hash + + * src/internal.h: add virNetwork + + * src/libvirt.c: hook up the APIs to the network + driver + + * src/libvirt_sym.version: add the new APIs + + * src/virterror.c: handle the new error codes + +Tue Feb 14 15:07:26 IST 2007 Mark McLoughlin + + * src/conf.h: fix merge error - remove the argc argument + from qemudBuildCommandLine() + +Tue Feb 14 15:03:22 IST 2007 Mark McLoughlin * src/virsh.c: Re-name some of the VSH_DOMBYFOO stuff to VSH_BYFOO in order to re-use it for the network stuff. -Tue Feb 14 14:58:35 EST 2007 Mark McLoughlin +Tue Feb 14 14:58:35 IST 2007 Mark McLoughlin * src/hash.c, src/internal.h: Re-name virConnect->domains_mux to virConnect->hashes_mux since it will also be used to protect the networks hash. -Tue Feb 14 14:57:52 EST 2007 Mark McLoughlin +Tue Feb 14 14:57:52 IST 2007 Mark McLoughlin * qemud/conf.c: qemudSaveConfig() will always report a more specific error, so we should avoid overwriting this error. -Tue Feb 14 14:54:25 EST 2007 Mark McLoughlin +Tue Feb 14 14:54:25 IST 2007 Mark McLoughlin * qemud/qemud.c: Re-factor out qemudExec() so that it can be used to launch dnsmasq. @@ -23,7 +117,7 @@ Tue Feb 14 14:54:25 EST 2007 Mark McLoughlin * qemud/conf.c: don't return argc from qemudBuildCommandLine() as exec() doesn't need it. -Tue Feb 14 14:52:12 EST 2007 Mark McLoughlin +Tue Feb 14 14:52:12 IST 2007 Mark McLoughlin * qemud/conf.c: Re-factor bits of conf.c so that: @@ -33,25 +127,25 @@ Tue Feb 14 14:52:12 EST 2007 Mark McLoughlin - split qemudScanConfigDir() out so that qemudScanConfigs() can scan multiple configDirs -Tue Feb 14 14:50:22 EST 2007 Mark McLoughlin +Tue Feb 14 14:50:22 IST 2007 Mark McLoughlin * qemud/conf.c: handle an unspecified MAC address, fix the argv freeing code in qemudBuildCommandLine() and fix copy and paste error in qemudGenerateXML() -Tue Feb 14 14:42:38 EST 2007 Mark McLoughlin +Tue Feb 14 14:42:38 IST 2007 Mark McLoughlin * src/internal.h: add virConnect->qemud_fd so that xen and qemu don't share the handle member. * src/hash.c, src/qemu_internal.c: update -Tue Feb 14 14:40:52 EST 2007 Mark McLoughlin +Tue Feb 14 14:40:52 IST 2007 Mark McLoughlin * qemud/conf.c, qemud/dispatch.c, qemud/driver.c, qemud/qemud.c: include autoconf's config.h -Tue Feb 14 14:39:18 EST 2007 Mark McLoughlin +Tue Feb 14 14:39:18 IST 2007 Mark McLoughlin * conf.[ch]: rename from config.[ch] so we can use autoconf's config.h @@ -60,7 +154,7 @@ Tue Feb 14 14:39:18 EST 2007 Mark McLoughlin * driver.c, qemud.c: upd. -Tue Feb 14 14:33:22 EST 2007 Mark McLoughlin +Tue Feb 14 14:33:22 IST 2007 Mark McLoughlin * autogen.sh: run autoheader diff --git a/qemud/conf.c b/qemud/conf.c index da80dfc048..cbca964d4c 100644 --- a/qemud/conf.c +++ b/qemud/conf.c @@ -1099,6 +1099,12 @@ struct qemud_vm *qemudLoadConfigXML(struct qemud_server *server, 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 qemud_server *server ATTRIBUTE_UNUSED, 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 qemud_server *server ATTRIBUTE_UNUSED, 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 qemud_server *server, 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, " \n") < 0) + goto no_memory; + while (range) { + if (qemudBufferPrintf(&buf, " \n", + range->start, range->end) < 0) + goto no_memory; + range = range->next; + } + if (qemudBufferAdd(&buf, " \n") < 0) + goto no_memory; + } + + if (qemudBufferAdd(&buf, " \n") < 0) goto no_memory; } diff --git a/qemud/internal.h b/qemud/internal.h index 9552829123..6f249f603e 100644 --- a/qemud/internal.h +++ b/qemud/internal.h @@ -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; diff --git a/qemud/qemud.c b/qemud/qemud.c index 061eaecd91..32310966cb 100644 --- a/qemud/qemud.c +++ b/qemud/qemud.c @@ -703,6 +703,105 @@ static int qemudDispatchVMFailure(struct qemud_server *server, struct qemud_vm * 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_server *server, 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 qemud_server *server, 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 qemud_server *server, 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;