}
-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);
-}
-
-
static int qemudSaveNetworkConfig(struct qemud_server *server,
struct qemud_network *network) {
char *xml;
int fd, ret = -1;
int towrite;
- if (!(xml = qemudGenerateNetworkXML(server, network))) {
+ if (!(xml = qemudGenerateNetworkXML(server, network, 0))) {
return -1;
}
return ret;
}
+void qemudFreeNetworkDef(struct qemud_network_def *def) {
+ struct qemud_dhcp_range_def *range = def->ranges;
+ while (range) {
+ struct qemud_dhcp_range_def *next = range->next;
+ free(range);
+ range = next;
+ }
+ free(def);
+}
+
+void qemudFreeNetwork(struct qemud_network *network) {
+ qemudFreeNetworkDef(network->def);
+ if (network->newDef)
+ qemudFreeNetworkDef(network->newDef);
+ free(network);
+}
static int qemudParseBridgeXML(struct qemud_server *server ATTRIBUTE_UNUSED,
- struct qemud_network *network,
+ struct qemud_network_def *def,
xmlNodePtr node) {
xmlChar *name, *stp, *delay;
name = xmlGetProp(node, BAD_CAST "name");
if (name != NULL) {
- strncpy(network->def.bridge, (const char *)name, IF_NAMESIZE-1);
- network->def.bridge[IF_NAMESIZE-1] = '\0';
+ strncpy(def->bridge, (const char *)name, IF_NAMESIZE-1);
+ def->bridge[IF_NAMESIZE-1] = '\0';
xmlFree(name);
name = NULL;
}
stp = xmlGetProp(node, BAD_CAST "stp");
if (stp != NULL) {
if (xmlStrEqual(stp, BAD_CAST "off")) {
- network->def.disableSTP = 1;
+ def->disableSTP = 1;
}
xmlFree(stp);
stp = NULL;
delay = xmlGetProp(node, BAD_CAST "delay");
if (delay != NULL) {
- network->def.forwardDelay = strtol((const char *)delay, NULL, 10);
+ def->forwardDelay = strtol((const char *)delay, NULL, 10);
xmlFree(delay);
delay = NULL;
}
}
static int qemudParseDhcpRangesXML(struct qemud_server *server,
- struct qemud_network *network,
+ struct qemud_network_def *def,
xmlNodePtr node) {
xmlNodePtr cur;
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++;
+ range->next = def->ranges;
+ def->ranges = range;
+ def->nranges++;
} else {
free(range);
}
}
static int qemudParseInetXML(struct qemud_server *server ATTRIBUTE_UNUSED,
- struct qemud_network *network,
+ struct qemud_network_def *def,
xmlNodePtr node) {
xmlChar *address, *netmask;
xmlNodePtr cur;
address = xmlGetProp(node, BAD_CAST "address");
if (address != NULL) {
- strncpy(network->def.ipAddress, (const char *)address, BR_INET_ADDR_MAXLEN-1);
- network->def.ipAddress[BR_INET_ADDR_MAXLEN-1] = '\0';
+ strncpy(def->ipAddress, (const char *)address, BR_INET_ADDR_MAXLEN-1);
+ def->ipAddress[BR_INET_ADDR_MAXLEN-1] = '\0';
xmlFree(address);
address = NULL;
}
netmask = xmlGetProp(node, BAD_CAST "netmask");
if (netmask != NULL) {
- strncpy(network->def.netmask, (const char *)netmask, BR_INET_ADDR_MAXLEN-1);
- network->def.netmask[BR_INET_ADDR_MAXLEN-1] = '\0';
+ strncpy(def->netmask, (const char *)netmask, BR_INET_ADDR_MAXLEN-1);
+ def->netmask[BR_INET_ADDR_MAXLEN-1] = '\0';
xmlFree(netmask);
netmask = NULL;
}
while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE &&
xmlStrEqual(cur->name, BAD_CAST "dhcp") &&
- !qemudParseDhcpRangesXML(server, network, cur))
+ !qemudParseDhcpRangesXML(server, def, cur))
return 0;
cur = cur->next;
}
}
-static int qemudParseNetworkXML(struct qemud_server *server,
- xmlDocPtr xml,
- struct qemud_network *network) {
+static struct qemud_network_def *qemudParseNetworkXML(struct qemud_server *server,
+ xmlDocPtr xml) {
xmlNodePtr root = NULL;
xmlXPathContextPtr ctxt = NULL;
xmlXPathObjectPtr obj = NULL;
+ struct qemud_network_def *def;
+
+ if (!(def = calloc(1, sizeof(struct qemud_network_def)))) {
+ qemudReportError(server, VIR_ERR_NO_MEMORY, "network_def");
+ return NULL;
+ }
/* Prepare parser / xpath context */
root = xmlDocGetRootElement(xml);
qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "%s", "network name length too long");
goto error;
}
- strcpy(network->def.name, (const char *)obj->stringval);
+ strcpy(def->name, (const char *)obj->stringval);
xmlXPathFreeObject(obj);
qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "%s", "missing uuid element");
goto error;
}
- if (qemudParseUUID((const char *)obj->stringval, network->def.uuid) < 0) {
+ if (qemudParseUUID((const char *)obj->stringval, def->uuid) < 0) {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "%s", "malformed uuid element");
goto error;
}
obj = xmlXPathEval(BAD_CAST "/network/bridge[1]", ctxt);
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
- if (!qemudParseBridgeXML(server, network, obj->nodesetval->nodeTab[0])) {
+ if (!qemudParseBridgeXML(server, def, obj->nodesetval->nodeTab[0])) {
goto error;
}
}
obj = xmlXPathEval(BAD_CAST "/network/ip[1]", ctxt);
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
- if (!qemudParseInetXML(server, network, obj->nodesetval->nodeTab[0])) {
+ if (!qemudParseInetXML(server, def, obj->nodesetval->nodeTab[0])) {
goto error;
}
}
xmlXPathFreeContext(ctxt);
- return 0;
+ return def;
error:
/* XXX free all the stuff in the qemud_network struct, or leave it upto
xmlXPathFreeObject(obj);
if (ctxt)
xmlXPathFreeContext(ctxt);
- return -1;
+ qemudFreeNetworkDef(def);
+ return NULL;
}
struct qemud_network *qemudLoadNetworkConfigXML(struct qemud_server *server,
const char *file,
const char *doc,
int save) {
+ struct qemud_network_def *def = NULL;
struct qemud_network *network = NULL;
xmlDocPtr xml;
+ int newNetwork = 0;
if (!(xml = xmlReadDoc(BAD_CAST doc, file ? file : "network.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
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) {
+ if (!(def = qemudParseNetworkXML(server, xml))) {
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 ((network = qemudFindNetworkByName(server, def->name))) {
+ if (!network->active) {
+ qemudFreeNetworkDef(network->def);
+ network->def = def;
+ } else {
+ if (network->newDef)
+ qemudFreeNetworkDef(network->newDef);
+ network->newDef = def;
+ }
+ } else {
+ if (!(network = calloc(1, sizeof(struct qemud_network)))) {
+ qemudReportError(server, VIR_ERR_NO_MEMORY, "network");
+ return NULL;
+ }
+
+ newNetwork = 1;
}
if (file) {
network->configFile[PATH_MAX-1] = '\0';
} else {
if (save) {
- if (qemudMakeConfigPath(server->networkConfigDir, network->def.name, ".xml", network->configFile, PATH_MAX) < 0) {
+ 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 (newNetwork) {
+ network->next = server->inactivenetworks;
+ server->inactivenetworks = network;
+ server->ninactivenetworks++;
+ }
+
return network;
}
if (isGuest) {
qemudLoadConfigXML(server, file, xml, 1);
} else {
- struct qemud_network *network;
- if ((network = qemudLoadNetworkConfigXML(server, file, xml, 1))) {
- network->next = server->inactivenetworks;
- server->inactivenetworks = network;
- server->ninactivenetworks++;
- }
+ qemudLoadNetworkConfigXML(server, file, xml, 1);
}
cleanup:
fclose(fh);
char *qemudGenerateNetworkXML(struct qemud_server *server,
- struct qemud_network *network) {
+ struct qemud_network *network,
+ int live) {
+ struct qemud_network_def *def = live ? network->def : (network->newDef ? network->newDef : network->def);
struct qemudBuffer buf;
unsigned char *uuid;
if (qemudBufferPrintf(&buf, "<network>\n") < 0)
goto no_memory;
- if (qemudBufferPrintf(&buf, " <name>%s</name>\n", network->def.name) < 0)
+ if (qemudBufferPrintf(&buf, " <name>%s</name>\n", def->name) < 0)
goto no_memory;
- uuid = network->def.uuid;
+ uuid = 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],
goto no_memory;
if (qemudBufferPrintf(&buf, " <bridge name='%s' stp='%s' delay='%d' />\n",
- network->def.bridge,
- network->def.disableSTP ? "off" : "on",
- network->def.forwardDelay) < 0)
+ def->bridge,
+ def->disableSTP ? "off" : "on",
+ def->forwardDelay) < 0)
goto no_memory;
- if (network->def.ipAddress[0] || network->def.netmask[0]) {
+ if (def->ipAddress[0] || def->netmask[0]) {
if (qemudBufferAdd(&buf, " <ip") < 0)
goto no_memory;
- if (network->def.ipAddress[0] &&
- qemudBufferPrintf(&buf, " address='%s'", network->def.ipAddress) < 0)
+ if (def->ipAddress[0] &&
+ qemudBufferPrintf(&buf, " address='%s'", def->ipAddress) < 0)
goto no_memory;
- if (network->def.netmask[0] &&
- qemudBufferPrintf(&buf, " netmask='%s'", network->def.netmask) < 0)
+ if (def->netmask[0] &&
+ qemudBufferPrintf(&buf, " netmask='%s'", def->netmask) < 0)
goto no_memory;
if (qemudBufferAdd(&buf, ">\n") < 0)
goto no_memory;
- if (network->def.ranges) {
- struct qemud_dhcp_range_def *range = network->def.ranges;
+ if (def->ranges) {
+ struct qemud_dhcp_range_def *range = def->ranges;
if (qemudBufferAdd(&buf, " <dhcp>\n") < 0)
goto no_memory;
while (range) {
struct qemud_network *network = server->activenetworks;
while (network) {
- if (!memcmp(network->def.uuid, uuid, QEMUD_UUID_RAW_LEN))
+ 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))
+ if (!memcmp(network->def->uuid, uuid, QEMUD_UUID_RAW_LEN))
return network;
network = network->next;
}
struct qemud_network *network = server->activenetworks;
while (network) {
- if (!strcmp(network->def.name, name))
+ if (!strcmp(network->def->name, name))
return network;
network = network->next;
}
network = server->inactivenetworks;
while (network) {
- if (!strcmp(network->def.name, name))
+ if (!strcmp(network->def->name, name))
return network;
network = network->next;
}
struct qemud_network *network = server->activenetworks;
int got = 0;
while (network && got < nnames) {
- strncpy(names[got], network->def.name, QEMUD_MAX_NAME_LEN-1);
+ strncpy(names[got], network->def->name, QEMUD_MAX_NAME_LEN-1);
names[got][QEMUD_MAX_NAME_LEN-1] = '\0';
network = network->next;
got++;
struct qemud_network *network = server->inactivenetworks;
int got = 0;
while (network && got < nnames) {
- strncpy(names[got], network->def.name, QEMUD_MAX_NAME_LEN-1);
+ strncpy(names[got], network->def->name, QEMUD_MAX_NAME_LEN-1);
names[got][QEMUD_MAX_NAME_LEN-1] = '\0';
network = network->next;
got++;
return NULL;
}
- if (qemudStartNetworkDaemon(server, network) < 0) {
+ if (qemudNetworkStart(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) {
- struct qemud_network *network;
-
- if (!(network = qemudLoadNetworkConfigXML(server, NULL, xml, 1))) {
- return NULL;
- }
-
- network->next = server->inactivenetworks;
- server->inactivenetworks = network;
- server->ninactivenetworks++;
-
- return network;
+ return qemudLoadNetworkConfigXML(server, NULL, xml, 1);
}
int qemudNetworkUndefine(struct qemud_server *server, const unsigned char *uuid) {
return -1;
}
- if (qemudDeleteConfig(server, network->configFile, network->def.name) < 0)
+ if (qemudDeleteConfig(server, network->configFile, network->def->name) < 0)
return -1;
network->configFile[0] = '\0';
return -1;
}
- networkxml = qemudGenerateNetworkXML(server, network);
+ networkxml = qemudGenerateNetworkXML(server, network, 1);
if (!networkxml)
return -1;
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 */
+ (2 * network->def->nranges) + /* --dhcp-range 10.0.0.2,10.0.0.254 */
1; /* NULL */
if (!(*argv = malloc(len * sizeof(char *))))
APPEND_ARG(*argv, i++, "lo");
APPEND_ARG(*argv, i++, "--listen-address");
- APPEND_ARG(*argv, i++, network->def.ipAddress);
+ APPEND_ARG(*argv, i++, network->def->ipAddress);
- range = network->def.ranges;
+ range = network->def->ranges;
while (range) {
snprintf(buf, sizeof(buf), "%s,%s",
range->start, range->end);
char **argv;
int ret, i;
- if (network->def.ipAddress[0] == '\0') {
+ if (network->def->ipAddress[0] == '\0') {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
"cannot start dhcp daemon without IP address for server");
return -1;
return -1;
}
- if (network->def.bridge[0] == '\0' ||
- strchr(network->def.bridge, '%')) {
+ if (network->def->bridge[0] == '\0' ||
+ strchr(network->def->bridge, '%')) {
name = "vnet%d";
} else {
- name = network->def.bridge;
+ name = network->def->bridge;
}
if ((err = brAddBridge(server->brctl, name, network->bridge, sizeof(network->bridge)))) {
return -1;
}
- if (network->def.ipAddress[0] &&
- (err = brSetInetAddress(server->brctl, network->bridge, network->def.ipAddress))) {
+ if (network->def->ipAddress[0] &&
+ (err = brSetInetAddress(server->brctl, network->bridge, network->def->ipAddress))) {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
"cannot set IP address on bridge '%s' to '%s' : %s\n",
- network->bridge, network->def.ipAddress, strerror(err));
+ network->bridge, network->def->ipAddress, strerror(err));
goto err_delbr;
}
- if (network->def.netmask[0] &&
- (err = brSetInetNetmask(server->brctl, network->bridge, network->def.netmask))) {
+ if (network->def->netmask[0] &&
+ (err = brSetInetNetmask(server->brctl, network->bridge, network->def->netmask))) {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
"cannot set netmask on bridge '%s' to '%s' : %s\n",
- network->bridge, network->def.netmask, strerror(err));
+ network->bridge, network->def->netmask, strerror(err));
goto err_delbr;
}
- if (network->def.ipAddress[0] &&
+ if (network->def->ipAddress[0] &&
(err = brSetInterfaceUp(server->brctl, network->bridge, 1))) {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
"failed to bring the bridge '%s' up : %s\n",
goto err_delbr2;
}
- if (network->def.ranges &&
+ if (network->def->ranges &&
dhcpStartDhcpDaemon(server, network) < 0)
goto err_delbr2;
qemudRemoveIptablesRules(server, network);
err_delbr1:
- if (network->def.ipAddress[0] &&
+ 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));
qemudRemoveIptablesRules(server, network);
- if (network->def.ipAddress[0] &&
+ 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));
network->dnsmasqPid = -1;
network->active = 0;
+ if (network->newDef) {
+ qemudFreeNetworkDef(network->def);
+ network->def = network->newDef;
+ network->newDef = NULL;
+ }
+
return 0;
}