-Tue Feb 14 15:03:22 EST 2007 Mark McLoughlin <markmc@redhat.com>
+Tue Feb 14 16:04:48 IST 2007 Mark McLoughlin <markmc@redhat.com>
+
+ * 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 <markmc@redhat.com>
+
+ * 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 <markmc@redhat.com>
+
+ * 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 <markmc@redhat.com>
+
+ * 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 <markmc@redhat.com>
+
+ * src/virsh.c: add the net-* commands.
+
+Tue Feb 14 15:37:17 IST 2007 Mark McLoughlin <markmc@redhat.com>
+
+ 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 <markmc@redhat.com>
+
+ * 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 <markmc@redhat.com>
+
+ * src/conf.h: fix merge error - remove the argc argument
+ from qemudBuildCommandLine()
+
+Tue Feb 14 15:03:22 IST 2007 Mark McLoughlin <markmc@redhat.com>
* 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 <markmc@redhat.com>
+Tue Feb 14 14:58:35 IST 2007 Mark McLoughlin <markmc@redhat.com>
* 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 <markmc@redhat.com>
+Tue Feb 14 14:57:52 IST 2007 Mark McLoughlin <markmc@redhat.com>
* 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 <markmc@redhat.com>
+Tue Feb 14 14:54:25 IST 2007 Mark McLoughlin <markmc@redhat.com>
* qemud/qemud.c: Re-factor out qemudExec() so that it can
be used to launch dnsmasq.
* 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 <markmc@redhat.com>
+Tue Feb 14 14:52:12 IST 2007 Mark McLoughlin <markmc@redhat.com>
* qemud/conf.c: Re-factor bits of conf.c so that:
- split qemudScanConfigDir() out so that qemudScanConfigs()
can scan multiple configDirs
-Tue Feb 14 14:50:22 EST 2007 Mark McLoughlin <markmc@redhat.com>
+Tue Feb 14 14:50:22 IST 2007 Mark McLoughlin <markmc@redhat.com>
* 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 <markmc@redhat.com>
+Tue Feb 14 14:42:38 IST 2007 Mark McLoughlin <markmc@redhat.com>
* 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 <markmc@redhat.com>
+Tue Feb 14 14:40:52 IST 2007 Mark McLoughlin <markmc@redhat.com>
* 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 <markmc@redhat.com>
+Tue Feb 14 14:39:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
* conf.[ch]: rename from config.[ch] so we can use
autoconf's config.h
* driver.c, qemud.c: upd.
-Tue Feb 14 14:33:22 EST 2007 Mark McLoughlin <markmc@redhat.com>
+Tue Feb 14 14:33:22 IST 2007 Mark McLoughlin <markmc@redhat.com>
* autogen.sh: run autoheader
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);
}
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) {
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;
}
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;
}
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];
char ipAddress[BR_INET_ADDR_MAXLEN];
char netmask[BR_INET_ADDR_MAXLEN];
+
+ int nranges;
+ struct qemud_dhcp_range_def *ranges;
};
/* Virtual Network runtime state */
struct qemud_network_def def;
char bridge[BR_IFNAME_MAXLEN];
+ int dnsmasqPid;
unsigned int active : 1;
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) {
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",
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",
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;