diff --git a/ChangeLog b/ChangeLog index 0ec717813f..905e9bed1d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,91 @@ -Tue Feb 14 14:54:25 EST 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 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 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 IST 2007 Mark McLoughlin * qemud/qemud.c: Re-factor out qemudExec() so that it can be used to launch dnsmasq. @@ -6,7 +93,7 @@ Tue Feb 14 14:54:25 EST 2007 Mark McLoughlin * qemud/conf.c: Re-factor bits of conf.c so that: @@ -16,25 +103,25 @@ Tue Feb 14 14:52:12 EST 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 * 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 * 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 * conf.[ch]: rename from config.[ch] so we can use autoconf's config.h @@ -43,7 +130,7 @@ Tue Feb 14 14:39:18 EST 2007 Mark McLoughlin * autogen.sh: run autoheader diff --git a/qemud/conf.c b/qemud/conf.c index 372370d99d..da333f2e96 100644 --- a/qemud/conf.c +++ b/qemud/conf.c @@ -1086,8 +1086,6 @@ struct qemud_vm *qemudLoadConfigXML(struct qemud_server *server, } if (qemudSaveConfig(server, vm) < 0) { - qemudReportError(server, VIR_ERR_INTERNAL_ERROR, - "cannot save config file for guest"); qemudFreeVM(vm); return NULL; } @@ -1100,17 +1098,186 @@ struct qemud_vm *qemudLoadConfigXML(struct qemud_server *server, } +void qemudFreeNetwork(struct qemud_network *network) { + free(network); +} + + +static int qemudSaveNetworkConfig(struct qemud_server *server, + struct qemud_network *network) { + char *xml; + int fd, ret = -1; + int towrite; + + if (!(xml = qemudGenerateNetworkXML(server, network))) { + return -1; + } + + if (qemudEnsureConfigDir(server, server->networkConfigDir) < 0) { + goto cleanup; + } + + if ((fd = open(network->configFile, + O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR )) < 0) { + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot create config file %s", network->configFile); + goto cleanup; + } + + towrite = strlen(xml); + if (write(fd, xml, towrite) != towrite) { + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot write config file %s", network->configFile); + goto cleanup; + } + + if (close(fd) < 0) { + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot save config file %s", network->configFile); + goto cleanup; + } + + ret = 0; + + cleanup: + + free(xml); + + return ret; +} + + +static int qemudParseNetworkXML(struct qemud_server *server, + xmlDocPtr xml, + struct qemud_network *network) { + xmlNodePtr root = NULL; + xmlXPathContextPtr ctxt = NULL; + xmlXPathObjectPtr obj = NULL; + + /* Prepare parser / xpath context */ + root = xmlDocGetRootElement(xml); + if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "network"))) { + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "%s", "incorrect root element"); + goto error; + } + + ctxt = xmlXPathNewContext(xml); + if (ctxt == NULL) { + qemudReportError(server, VIR_ERR_NO_MEMORY, "xmlXPathContext"); + goto error; + } + + + /* Extract network name */ + obj = xmlXPathEval(BAD_CAST "string(/network/name[1])", ctxt); + if ((obj == NULL) || (obj->type != XPATH_STRING) || + (obj->stringval == NULL) || (obj->stringval[0] == 0)) { + qemudReportError(server, VIR_ERR_NO_NAME, NULL); + goto error; + } + if (strlen((const char *)obj->stringval) >= (QEMUD_MAX_NAME_LEN-1)) { + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "%s", "network name length too long"); + goto error; + } + strcpy(network->def.name, (const char *)obj->stringval); + xmlXPathFreeObject(obj); + + + /* Extract network uuid */ + obj = xmlXPathEval(BAD_CAST "string(/network/uuid[1])", ctxt); + if ((obj == NULL) || (obj->type != XPATH_STRING) || + (obj->stringval == NULL) || (obj->stringval[0] == 0)) { + /* XXX auto-generate a UUID */ + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "%s", "missing uuid element"); + goto error; + } + if (qemudParseUUID((const char *)obj->stringval, network->def.uuid) < 0) { + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "%s", "malformed uuid element"); + goto error; + } + xmlXPathFreeObject(obj); + + xmlXPathFreeContext(ctxt); + + return 0; + + error: + /* XXX free all the stuff in the qemud_network struct, or leave it upto + the caller ? */ + if (obj) + xmlXPathFreeObject(obj); + if (ctxt) + xmlXPathFreeContext(ctxt); + return -1; +} + + +struct qemud_network *qemudLoadNetworkConfigXML(struct qemud_server *server, + const char *file, + const char *doc, + int save) { + struct qemud_network *network = NULL; + xmlDocPtr xml; + + if (!(xml = xmlReadDoc(BAD_CAST doc, file ? file : "network.xml", NULL, + XML_PARSE_NOENT | XML_PARSE_NONET | + XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { + qemudReportError(server, VIR_ERR_XML_ERROR, NULL); + return NULL; + } + + if (!(network = calloc(1, sizeof(struct qemud_network)))) { + qemudReportError(server, VIR_ERR_NO_MEMORY, "network"); + return NULL; + } + + if (qemudParseNetworkXML(server, xml, network) < 0) { + xmlFreeDoc(xml); + qemudFreeNetwork(network); + return NULL; + } + xmlFreeDoc(xml); + + if (qemudFindNetworkByUUID(server, network->def.uuid) || + qemudFindNetworkByName(server, network->def.name)) { + qemudReportError(server, VIR_ERR_NETWORK_EXIST, network->def.name); + qemudFreeNetwork(network); + return NULL; + } + + if (file) { + strncpy(network->configFile, file, PATH_MAX); + network->configFile[PATH_MAX-1] = '\0'; + } else { + if (save) { + if (qemudMakeConfigPath(server->networkConfigDir, network->def.name, ".xml", network->configFile, PATH_MAX) < 0) { + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot construct config file path"); + qemudFreeNetwork(network); + return NULL; + } + + if (qemudSaveNetworkConfig(server, network) < 0) { + qemudFreeNetwork(network); + return NULL; + } + } else { + network->configFile[0] = '\0'; + } + } + + return network; +} + + /* Load a guest from its persistent config file */ static void qemudLoadConfig(struct qemud_server *server, - const char *file) { + const char *file, + int isGuest) { FILE *fh; struct stat st; - struct qemud_vm *vm; char xml[QEMUD_MAX_XML_LEN]; int ret; if (!(fh = fopen(file, "r"))) { - qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot open guest config file %s", file); + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot open config file %s", file); return; } @@ -1120,7 +1287,7 @@ static void qemudLoadConfig(struct qemud_server *server, } if (st.st_size >= QEMUD_MAX_XML_LEN) { - qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "guest config too large in file %s", file); + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "config too large in file %s", file); goto cleanup; } @@ -1130,10 +1297,20 @@ static void qemudLoadConfig(struct qemud_server *server, } xml[st.st_size] = '\0'; - if ((vm = qemudLoadConfigXML(server, file, xml, 1))) { - vm->next = server->inactivevms; - server->inactivevms = vm; - server->ninactivevms++; + if (isGuest) { + struct qemud_vm *vm; + if ((vm = qemudLoadConfigXML(server, file, xml, 1))) { + vm->next = server->inactivevms; + server->inactivevms = vm; + server->ninactivevms++; + } + } else { + struct qemud_network *network; + if ((network = qemudLoadNetworkConfigXML(server, file, xml, 1))) { + network->next = server->inactivenetworks; + server->inactivenetworks = network; + server->ninactivenetworks++; + } } cleanup: @@ -1143,7 +1320,8 @@ static void qemudLoadConfig(struct qemud_server *server, static int qemudScanConfigDir(struct qemud_server *server, - const char *configDir) { + const char *configDir, + int isGuest) { DIR *dir; struct dirent *entry; @@ -1161,7 +1339,7 @@ int qemudScanConfigDir(struct qemud_server *server, if (qemudMakeConfigPath(configDir, entry->d_name, NULL, file, PATH_MAX) < 0) continue; - qemudLoadConfig(server, file); + qemudLoadConfig(server, file, isGuest); } closedir(dir); @@ -1171,7 +1349,9 @@ int qemudScanConfigDir(struct qemud_server *server, /* Scan for all guest and network config files */ int qemudScanConfigs(struct qemud_server *server) { - return qemudScanConfigDir(server, server->configDir); + if (qemudScanConfigDir(server, server->configDir, 0) < 0) + return -1; + return qemudScanConfigDir(server, server->networkConfigDir, 1); } /* Simple grow-on-demand string buffer */ @@ -1426,19 +1606,54 @@ char *qemudGenerateXML(struct qemud_server *server, struct qemud_vm *vm) { } -int qemudDeleteConfigXML(struct qemud_server *server, struct qemud_vm *vm) { - if (!vm->configFile[0]) { - qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "no config file for guest %s", vm->def.name); +char *qemudGenerateNetworkXML(struct qemud_server *server, + struct qemud_network *network) { + struct qemudBuffer buf; + unsigned char *uuid; + + buf.len = QEMUD_MAX_XML_LEN; + buf.used = 0; + buf.data = malloc(buf.len); + + if (qemudBufferPrintf(&buf, "\n") < 0) + goto no_memory; + + if (qemudBufferPrintf(&buf, " %s\n", network->def.name) < 0) + goto no_memory; + + uuid = network->def.uuid; + if (qemudBufferPrintf(&buf, " %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", + uuid[0], uuid[1], uuid[2], uuid[3], + uuid[4], uuid[5], uuid[6], uuid[7], + uuid[8], uuid[9], uuid[10], uuid[11], + uuid[12], uuid[13], uuid[14], uuid[15]) < 0) + goto no_memory; + + if (qemudBufferAdd(&buf, "\n") < 0) + goto no_memory; + + return buf.data; + + no_memory: + qemudReportError(server, VIR_ERR_NO_MEMORY, "xml"); + free(buf.data); + return NULL; +} + + +int qemudDeleteConfig(struct qemud_server *server, + const char *configFile, + const char *name) { + if (!configFile[0]) { + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "no config file for %s", name); return -1; } - if (unlink(vm->configFile) < 0) { - qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot remove config for guest %s", vm->def.name); + if (unlink(configFile) < 0) { + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "cannot remove config for %s", name); return -1; } - vm->configFile[0] = '\0'; - return 0; } diff --git a/qemud/conf.h b/qemud/conf.h index 3a5549d7f0..a363552d29 100644 --- a/qemud/conf.h +++ b/qemud/conf.h @@ -28,21 +28,28 @@ int qemudBuildCommandLine(struct qemud_server *server, struct qemud_vm *vm, - char ***argv, - int *argc); + char ***argv); + +int qemudScanConfigs(struct qemud_server *server); +int qemudDeleteConfig(struct qemud_server *server, + const char *configFile, + const char *name); void qemudFreeVM(struct qemud_vm *vm); struct qemud_vm *qemudLoadConfigXML(struct qemud_server *server, const char *file, const char *doc, int persist); -int qemudScanConfigs(struct qemud_server *server); char *qemudGenerateXML(struct qemud_server *server, struct qemud_vm *vm); -int qemudDeleteConfigXML(struct qemud_server *server, - struct qemud_vm *vm); - +void qemudFreeNetwork(struct qemud_network *network); +struct qemud_network *qemudLoadNetworkConfigXML(struct qemud_server *server, + const char *file, + const char *doc, + int persist); +char *qemudGenerateNetworkXML(struct qemud_server *server, + struct qemud_network *network); #endif diff --git a/qemud/driver.c b/qemud/driver.c index 9b16f3247d..8e246e0d60 100644 --- a/qemud/driver.c +++ b/qemud/driver.c @@ -522,9 +522,11 @@ int qemudDomainUndefine(struct qemud_server *server, const unsigned char *uuid) return -1; } - if (qemudDeleteConfigXML(server, vm) < 0) + if (qemudDeleteConfig(server, vm->configFile, vm->def.name) < 0) return -1; + vm->configFile[0] = '\0'; + while (curr) { if (curr == vm) { if (prev) { @@ -547,67 +549,198 @@ int qemudDomainUndefine(struct qemud_server *server, const unsigned char *uuid) struct qemud_network *qemudFindNetworkByUUID(const struct qemud_server *server, const unsigned char *uuid) { - server = NULL; uuid = NULL; + struct qemud_network *network = server->activenetworks; + + while (network) { + if (!memcmp(network->def.uuid, uuid, QEMUD_UUID_RAW_LEN)) + return network; + network = network->next; + } + + network = server->inactivenetworks; + while (network) { + if (!memcmp(network->def.uuid, uuid, QEMUD_UUID_RAW_LEN)) + return network; + network = network->next; + } + return NULL; } struct qemud_network *qemudFindNetworkByName(const struct qemud_server *server, const char *name) { - server = NULL; name = NULL; + struct qemud_network *network = server->activenetworks; + + while (network) { + if (!strcmp(network->def.name, name)) + return network; + network = network->next; + } + + network = server->inactivenetworks; + while (network) { + if (!strcmp(network->def.name, name)) + return network; + network = network->next; + } + return NULL; } int qemudNumNetworks(struct qemud_server *server) { - server = NULL; - return 0; + return server->nactivenetworks; } int qemudListNetworks(struct qemud_server *server, char *const*names, int nnames) { - server = NULL; names = NULL; nnames = 0; - return 0; + struct qemud_network *network = server->activenetworks; + int got = 0; + while (network && got < nnames) { + strncpy(names[got], network->def.name, QEMUD_MAX_NAME_LEN-1); + names[got][QEMUD_MAX_NAME_LEN-1] = '\0'; + network = network->next; + got++; + } + return got; } int qemudNumDefinedNetworks(struct qemud_server *server) { - server = NULL; - return 0; + return server->ninactivenetworks; } int qemudListDefinedNetworks(struct qemud_server *server, char *const*names, int nnames) { - server = NULL; names = NULL; nnames = 0; - return 0; + struct qemud_network *network = server->inactivenetworks; + int got = 0; + while (network && got < nnames) { + strncpy(names[got], network->def.name, QEMUD_MAX_NAME_LEN-1); + names[got][QEMUD_MAX_NAME_LEN-1] = '\0'; + network = network->next; + got++; + } + return got; } struct qemud_network *qemudNetworkCreate(struct qemud_server *server, const char *xml) { - server = NULL; xml = NULL; - return NULL; + struct qemud_network *network; + + if (!(network = qemudLoadNetworkConfigXML(server, NULL, xml, 0))) { + return NULL; + } + + if (qemudStartNetworkDaemon(server, network) < 0) { + qemudFreeNetwork(network); + return NULL; + } + + network->next = server->activenetworks; + server->activenetworks = network; + server->nactivenetworks++; + + return network; } struct qemud_network *qemudNetworkDefine(struct qemud_server *server, const char *xml) { - server = NULL; xml = NULL; - return NULL; + struct qemud_network *network; + + if (!(network = qemudLoadNetworkConfigXML(server, NULL, xml, 1))) { + return NULL; + } + + network->next = server->inactivenetworks; + server->inactivenetworks = network; + server->ninactivenetworks++; + + return network; } int qemudNetworkUndefine(struct qemud_server *server, const unsigned char *uuid) { - qemudReportError(server, VIR_ERR_INVALID_NETWORK, "no network with matching uuid"); - uuid = NULL; - return -1; + struct qemud_network *network = qemudFindNetworkByUUID(server, uuid); + struct qemud_network *prev = NULL, *curr = server->inactivenetworks; + + if (!network) { + qemudReportError(server, VIR_ERR_INVALID_DOMAIN, "no network with matching uuid"); + return -1; + } + + if (qemudDeleteConfig(server, network->configFile, network->def.name) < 0) + return -1; + + network->configFile[0] = '\0'; + + while (curr) { + if (curr == network) { + if (prev) { + prev->next = curr->next; + } else { + server->inactivenetworks = curr->next; + } + server->ninactivenetworks--; + break; + } + + prev = curr; + curr = curr->next; + } + + qemudFreeNetwork(network); + + return 0; } int qemudNetworkStart(struct qemud_server *server, struct qemud_network *network) { - server = NULL; network = NULL; - return 1; + struct qemud_network *prev = NULL, *curr = server->inactivenetworks; + if (qemudStartNetworkDaemon(server, network) < 0) { + return 1; + } + + while (curr) { + if (curr == network) { + if (prev) + prev->next = curr->next; + else + server->inactivenetworks = curr->next; + server->ninactivenetworks--; + break; + } + prev = curr; + curr = curr->next; + } + + network->next = server->activenetworks; + server->activenetworks = network; + server->nactivenetworks++; + + return 0; } int qemudNetworkDestroy(struct qemud_server *server, const unsigned char *uuid) { - uuid = NULL; - qemudReportError(server, VIR_ERR_INVALID_NETWORK, "no network with matching uuid"); - return -1; + struct qemud_network *network = qemudFindNetworkByUUID(server, uuid); + if (!network) { + qemudReportError(server, VIR_ERR_INVALID_NETWORK, "no network with matching uuid"); + return -1; + } + + if (qemudShutdownNetworkDaemon(server, network) < 0) + return -1; + + return 0; } int qemudNetworkDumpXML(struct qemud_server *server, const unsigned char *uuid, char *xml, int xmllen) { - qemudReportError(server, VIR_ERR_INVALID_NETWORK, "no network with matching uuid"); - uuid = NULL; xml = NULL; xmllen = 0; - return -1; + struct qemud_network *network = qemudFindNetworkByUUID(server, uuid); + char *networkxml; + if (!network) { + qemudReportError(server, VIR_ERR_INVALID_NETWORK, "no network with matching uuid"); + return -1; + } + + networkxml = qemudGenerateNetworkXML(server, network); + if (!networkxml) + return -1; + + strncpy(xml, networkxml, xmllen); + xml[xmllen-1] = '\0'; + + return 0; } /* diff --git a/qemud/internal.h b/qemud/internal.h index a52d3895b3..7a6d86b52a 100644 --- a/qemud/internal.h +++ b/qemud/internal.h @@ -207,6 +207,8 @@ struct qemud_network_def { /* Virtual Network runtime state */ struct qemud_network { + char configFile[PATH_MAX]; + struct qemud_network_def def; struct qemud_network *next; }; @@ -243,7 +245,12 @@ struct qemud_server { int ninactivevms; struct qemud_vm *inactivevms; int nextvmid; + int nactivenetworks; + struct qemud_network *activenetworks; + int ninactivenetworks; + struct qemud_network *inactivenetworks; char configDir[PATH_MAX]; + char networkConfigDir[PATH_MAX]; char errorMessage[QEMUD_MAX_ERROR_LEN]; int errorCode; }; @@ -254,6 +261,13 @@ int qemudStartVMDaemon(struct qemud_server *server, int qemudShutdownVMDaemon(struct qemud_server *server, struct qemud_vm *vm); +int qemudStartNetworkDaemon(struct qemud_server *server, + struct qemud_network *network); + +int qemudShutdownNetworkDaemon(struct qemud_server *server, + struct qemud_network *network); + + #endif /* diff --git a/qemud/qemud.c b/qemud/qemud.c index 964a2b135a..a6c99a041a 100644 --- a/qemud/qemud.c +++ b/qemud/qemud.c @@ -251,6 +251,9 @@ static struct qemud_server *qemudInitialize(int sys) { if (snprintf(server->configDir, sizeof(server->configDir), "%s/qemud", SYSCONF_DIR) >= (int)sizeof(server->configDir)) { goto cleanup; } + if (snprintf(server->networkConfigDir, sizeof(server->networkConfigDir), "%s/qemud/networks", SYSCONF_DIR) >= (int)sizeof(server->networkConfigDir)) { + goto cleanup; + } } else { struct passwd *pw; int uid; @@ -264,8 +267,13 @@ static struct qemud_server *qemudInitialize(int sys) { if (snprintf(server->configDir, sizeof(server->configDir), "%s/.qemud", pw->pw_dir) >= (int)sizeof(server->configDir)) { goto cleanup; } + + if (snprintf(server->networkConfigDir, sizeof(server->networkConfigDir), "%s/.qemud.d/networks", pw->pw_dir) >= (int)sizeof(server->networkConfigDir)) { + goto cleanup; + } } + if (qemudListen(server, sys) < 0) { goto cleanup; } @@ -696,6 +704,20 @@ static int qemudDispatchVMFailure(struct qemud_server *server, struct qemud_vm * } +int qemudStartNetworkDaemon(struct qemud_server *server, + struct qemud_network *network) { + server = NULL; network = NULL; + return 0; +} + + +int qemudShutdownNetworkDaemon(struct qemud_server *server, + struct qemud_network *network) { + server = NULL; network = NULL; + return 0; +} + + static int qemudDispatchPoll(struct qemud_server *server, struct pollfd *fds) { struct qemud_socket *sock = server->sockets; struct qemud_client *client = server->clients;