Implement the qemud's network stubs, but don't actually do anything
when starting a network.
Note, an example XML file would be:
<network>
<name>TestNetwork</name>
<uuid>ac57b808-bfdd-4aa3-8da8-0bd4ac1faceb</uuid>
<ip address="10.0.0.1" netmask="255.255.255.0">
<dhcp>
<range start="10.0.0.16" end="10.0.0.32" />
<range start="10.0.0.128" end="10.0.0.254" />
</dhcp>
</ip>
</network>
Signed-off-by: Mark McLoughlin <markmc(a)redhat.com>
Index: libvirt-foo/qemud/conf.c
===================================================================
--- libvirt-foo.orig/qemud/conf.c 2007-02-14 14:57:31.000000000 +0000
+++ libvirt-foo.orig/qemud/conf.c 2007-02-14 14:57:31.000000000 +0000
@@ -1098,17 +1098,186 @@ struct qemud_vm *qemudLoadConfigXML(stru
}
+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;
}
@@ -1118,7 +1287,7 @@ static void qemudLoadConfig(struct qemud
}
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;
}
@@ -1128,10 +1297,20 @@ static void qemudLoadConfig(struct qemud
}
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:
@@ -1141,7 +1320,8 @@ static void qemudLoadConfig(struct qemud
static
int qemudScanConfigDir(struct qemud_server *server,
- const char *configDir) {
+ const char *configDir,
+ int isGuest) {
DIR *dir;
struct dirent *entry;
@@ -1159,7 +1339,7 @@ int qemudScanConfigDir(struct qemud_serv
if (qemudMakeConfigPath(configDir, entry->d_name, NULL, file, PATH_MAX) <
0)
continue;
- qemudLoadConfig(server, file);
+ qemudLoadConfig(server, file, isGuest);
}
closedir(dir);
@@ -1169,7 +1349,9 @@ int qemudScanConfigDir(struct qemud_serv
/* 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 */
@@ -1424,19 +1606,54 @@ char *qemudGenerateXML(struct qemud_serv
}
-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, "<network>\n") < 0)
+ goto no_memory;
+
+ if (qemudBufferPrintf(&buf, " <name>%s</name>\n",
network->def.name) < 0)
+ goto no_memory;
+
+ uuid = network->def.uuid;
+ if (qemudBufferPrintf(&buf, "
<uuid>%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x</uuid>\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, "</network>\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;
}
Index: libvirt-foo/qemud/conf.h
===================================================================
--- libvirt-foo.orig/qemud/conf.h 2007-02-14 15:06:41.000000000 +0000
+++ libvirt-foo.orig/qemud/conf.h 2007-02-14 15:06:41.000000000 +0000
@@ -30,18 +30,26 @@ int qemudBuildCommandLine(struct qemud_s
struct qemud_vm *vm,
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
Index: libvirt-foo/qemud/driver.c
===================================================================
--- libvirt-foo.orig/qemud/driver.c 2007-02-14 15:46:58.000000000 +0000
+++ libvirt-foo.orig/qemud/driver.c 2007-02-14 15:46:58.000000000 +0000
@@ -522,9 +522,11 @@ int qemudDomainUndefine(struct qemud_ser
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_ser
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;
}
/*
Index: libvirt-foo/qemud/internal.h
===================================================================
--- libvirt-foo.orig/qemud/internal.h 2007-02-14 15:46:58.000000000 +0000
+++ libvirt-foo.orig/qemud/internal.h 2007-02-14 15:46:58.000000000 +0000
@@ -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_serv
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
/*
Index: libvirt-foo/qemud/qemud.c
===================================================================
--- libvirt-foo.orig/qemud/qemud.c 2007-02-14 14:53:23.000000000 +0000
+++ libvirt-foo.orig/qemud/qemud.c 2007-02-14 14:53:23.000000000 +0000
@@ -251,6 +251,9 @@ static struct qemud_server *qemudInitial
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 *qemudInitial
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
}
+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;
--