Switch QEMU driver over to generic network APIs

This commit is contained in:
Daniel P. Berrange 2008-07-11 17:33:45 +00:00
parent d78c0a6800
commit 381fa1fc46
6 changed files with 236 additions and 936 deletions

View File

@ -1,3 +1,8 @@
Fri Jul 11 18:32:59 BST 2008 Daniel P. Berrange <berrange@redhat.com>
* src/bridge.c, src/bridge.h, src/qemu_conf.c, src/qemu_conf.h,
src/qemu_driver.c: Switch over to generic network APIs
Fri Jul 11 17:39:59 BST 2008 Daniel P. Berrange <berrange@redhat.com>
* src/test.c, src/test.h: Convert to the new domain XML apis

View File

@ -116,60 +116,41 @@ brShutdown(brControl *ctl)
/**
* brAddBridge:
* @ctl: bridge control pointer
* @nameOrFmt: the bridge name (or name template)
* @name: pointer to @maxlen bytes to store the bridge name
* @maxlen: size of @name array
* @name: the bridge name
*
* This function register a new bridge, @nameOrFmt can be either
* a fixed name or a name template with '%d' for dynamic name allocation.
* in either case the final name for the bridge will be stored in @name.
* This function register a new bridge
*
* Returns 0 in case of success or an errno code in case of failure.
*/
#ifdef SIOCBRADDBR
int
brAddBridge(brControl *ctl,
const char *nameOrFmt,
char *name,
int maxlen)
char **name)
{
int id, subst;
if (!ctl || !ctl->fd || !nameOrFmt || !name)
if (!ctl || !ctl->fd || !name)
return EINVAL;
if (maxlen >= BR_IFNAME_MAXLEN)
maxlen = BR_IFNAME_MAXLEN;
subst = id = 0;
if (strstr(nameOrFmt, "%d"))
subst = 1;
do {
char try[BR_IFNAME_MAXLEN];
int len;
if (subst) {
len = snprintf(try, maxlen, nameOrFmt, id);
if (len >= maxlen)
return EADDRINUSE;
} else {
len = strlen(nameOrFmt);
if (len >= maxlen - 1)
return EINVAL;
strncpy(try, nameOrFmt, len);
try[len] = '\0';
}
if (ioctl(ctl->fd, SIOCBRADDBR, try) == 0) {
strncpy(name, try, maxlen);
if (*name) {
if (ioctl(ctl->fd, SIOCBRADDBR, *name) == 0)
return 0;
}
} else {
int id = 0;
do {
char try[50];
id++;
} while (subst && id <= MAX_BRIDGE_ID);
snprintf(try, sizeof(try), "virbr%d", id);
if (ioctl(ctl->fd, SIOCBRADDBR, try) == 0) {
if (!(*name = strdup(try))) {
ioctl(ctl->fd, SIOCBRDELBR, name);
return ENOMEM;
}
return 0;
}
id++;
} while (id < MAX_BRIDGE_ID);
}
return errno;
}

View File

@ -47,9 +47,7 @@ int brInit (brControl **ctl);
void brShutdown (brControl *ctl);
int brAddBridge (brControl *ctl,
const char *nameOrFmt,
char *name,
int maxlen);
char **name);
int brDeleteBridge (brControl *ctl,
const char *name);

View File

@ -180,32 +180,6 @@ struct qemud_vm *qemudFindVMByName(const struct qemud_driver *driver,
return NULL;
}
struct qemud_network *qemudFindNetworkByUUID(const struct qemud_driver *driver,
const unsigned char *uuid) {
struct qemud_network *network = driver->networks;
while (network) {
if (!memcmp(network->def->uuid, uuid, VIR_UUID_BUFLEN))
return network;
network = network->next;
}
return NULL;
}
struct qemud_network *qemudFindNetworkByName(const struct qemud_driver *driver,
const char *name) {
struct qemud_network *network = driver->networks;
while (network) {
if (STREQ(network->def->name, name))
return network;
network = network->next;
}
return NULL;
}
/* Free all memory associated with a struct qemud_vm object */
void qemudFreeVMDef(struct qemud_vm_def *def) {
@ -2254,7 +2228,7 @@ qemudNetworkIfaceConnect(virConnectPtr conn,
struct qemud_vm_net_def *net,
int vlan)
{
struct qemud_network *network = NULL;
virNetworkObjPtr network = NULL;
char *brname;
char *ifname;
char tapfdstr[4+3+32+7];
@ -2263,18 +2237,18 @@ qemudNetworkIfaceConnect(virConnectPtr conn,
int tapfd = -1;
if (net->type == QEMUD_NET_NETWORK) {
if (!(network = qemudFindNetworkByName(driver, net->dst.network.name))) {
if (!(network = virNetworkFindByName(driver->networks, net->dst.network.name))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("Network '%s' not found"),
net->dst.network.name);
goto error;
} else if (network->bridge[0] == '\0') {
} else if (network->def->bridge == NULL) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("Network '%s' not active"),
net->dst.network.name);
goto error;
}
brname = network->bridge;
brname = network->def->bridge;
if (net->dst.network.ifname[0] == '\0' ||
STRPREFIX(net->dst.network.ifname, "vnet") ||
strchr(net->dst.network.ifname, '%')) {
@ -3122,465 +3096,6 @@ qemudSaveVMDef(virConnectPtr conn,
return qemudSaveConfig(conn, driver, vm, def);
}
static int qemudSaveNetworkConfig(virConnectPtr conn,
struct qemud_driver *driver,
struct qemud_network *network,
struct qemud_network_def *def) {
char *xml;
int fd, ret = -1;
int towrite;
int err;
if (!(xml = qemudGenerateNetworkXML(conn, driver, network, def))) {
return -1;
}
if ((err = virFileMakePath(driver->networkConfigDir))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("cannot create config directory %s: %s"),
driver->networkConfigDir, strerror(err));
goto cleanup;
}
if ((fd = open(network->configFile,
O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR )) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("cannot create config file %s: %s"),
network->configFile, strerror(errno));
goto cleanup;
}
towrite = strlen(xml);
if (safewrite(fd, xml, towrite) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("cannot write config file %s: %s"),
network->configFile, strerror(errno));
goto cleanup;
}
if (close(fd) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("cannot save config file %s: %s"),
network->configFile, strerror(errno));
goto cleanup;
}
ret = 0;
cleanup:
VIR_FREE(xml);
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;
VIR_FREE(range);
range = next;
}
VIR_FREE(def);
}
void qemudFreeNetwork(struct qemud_network *network) {
qemudFreeNetworkDef(network->def);
if (network->newDef)
qemudFreeNetworkDef(network->newDef);
VIR_FREE(network);
}
static int qemudParseBridgeXML(struct qemud_driver *driver ATTRIBUTE_UNUSED,
struct qemud_network_def *def,
xmlNodePtr node) {
xmlChar *name, *stp, *delay;
name = xmlGetProp(node, BAD_CAST "name");
if (name != NULL) {
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")) {
def->disableSTP = 1;
}
xmlFree(stp);
stp = NULL;
}
delay = xmlGetProp(node, BAD_CAST "delay");
if (delay != NULL) {
def->forwardDelay = strtol((const char *)delay, NULL, 10);
xmlFree(delay);
delay = NULL;
}
return 1;
}
static int qemudParseDhcpRangesXML(virConnectPtr conn,
struct qemud_driver *driver ATTRIBUTE_UNUSED,
struct qemud_network_def *def,
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 (VIR_ALLOC(range) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for range string"));
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 = def->ranges;
def->ranges = range;
def->nranges++;
} else {
VIR_FREE(range);
}
xmlFree(start);
xmlFree(end);
cur = cur->next;
}
return 1;
}
static int qemudParseInetXML(virConnectPtr conn,
struct qemud_driver *driver ATTRIBUTE_UNUSED,
struct qemud_network_def *def,
xmlNodePtr node) {
xmlChar *address, *netmask;
xmlNodePtr cur;
address = xmlGetProp(node, BAD_CAST "address");
if (address != NULL) {
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(def->netmask, (const char *)netmask, BR_INET_ADDR_MAXLEN-1);
def->netmask[BR_INET_ADDR_MAXLEN-1] = '\0';
xmlFree(netmask);
netmask = NULL;
}
if (def->ipAddress[0] && def->netmask[0]) {
struct in_addr inaddress, innetmask;
char *netaddr;
inet_aton((const char*)def->ipAddress, &inaddress);
inet_aton((const char*)def->netmask, &innetmask);
inaddress.s_addr &= innetmask.s_addr;
netaddr = inet_ntoa(inaddress);
snprintf(def->network,sizeof(def->network)-1,
"%s/%s", netaddr, (const char *)def->netmask);
}
cur = node->children;
while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE &&
xmlStrEqual(cur->name, BAD_CAST "dhcp") &&
!qemudParseDhcpRangesXML(conn, driver, def, cur))
return 0;
cur = cur->next;
}
return 1;
}
static struct qemud_network_def *qemudParseNetworkXML(virConnectPtr conn,
struct qemud_driver *driver,
xmlDocPtr xml) {
xmlNodePtr root = NULL;
xmlXPathContextPtr ctxt = NULL;
xmlXPathObjectPtr obj = NULL, tmp = NULL;
struct qemud_network_def *def;
if (VIR_ALLOC(def) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for network_def string"));
return NULL;
}
/* Prepare parser / xpath context */
root = xmlDocGetRootElement(xml);
if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "network"))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("incorrect root element"));
goto error;
}
ctxt = xmlXPathNewContext(xml);
if (ctxt == NULL) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for xmlXPathContext string"));
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(conn, NULL, NULL, VIR_ERR_NO_NAME, NULL);
goto error;
}
if (strlen((const char *)obj->stringval) >= (QEMUD_MAX_NAME_LEN-1)) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("network name length too long"));
goto error;
}
strcpy(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)) {
int err;
if ((err = virUUIDGenerate(def->uuid))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("Failed to generate UUID: %s"), strerror(err));
goto error;
}
} else if (virUUIDParse((const char *)obj->stringval, def->uuid) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("malformed uuid element"));
goto error;
}
xmlXPathFreeObject(obj);
/* Parse bridge information */
obj = xmlXPathEval(BAD_CAST "/network/bridge[1]", ctxt);
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
if (!qemudParseBridgeXML(driver, def, obj->nodesetval->nodeTab[0])) {
goto error;
}
}
xmlXPathFreeObject(obj);
/* Parse IP information */
obj = xmlXPathEval(BAD_CAST "/network/ip[1]", ctxt);
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
if (!qemudParseInetXML(conn, driver, def, obj->nodesetval->nodeTab[0])) {
goto error;
}
}
xmlXPathFreeObject(obj);
/* IPv4 forwarding setup */
obj = xmlXPathEval(BAD_CAST "count(/network/forward) > 0", ctxt);
if ((obj != NULL) && (obj->type == XPATH_BOOLEAN) &&
obj->boolval) {
if (!def->ipAddress[0] ||
!def->netmask[0]) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("Forwarding requested, but no IPv4 address/netmask provided"));
goto error;
}
def->forward = 1;
tmp = xmlXPathEval(BAD_CAST "string(/network/forward[1]/@mode)", ctxt);
if ((tmp != NULL) && (tmp->type == XPATH_STRING) &&
(tmp->stringval != NULL) && (xmlStrEqual(tmp->stringval, BAD_CAST "route"))) {
def->forwardMode = QEMUD_NET_FORWARD_ROUTE;
} else {
def->forwardMode = QEMUD_NET_FORWARD_NAT;
}
xmlXPathFreeObject(tmp);
tmp = NULL;
tmp = xmlXPathEval(BAD_CAST "string(/network/forward[1]/@dev)", ctxt);
if ((tmp != NULL) && (tmp->type == XPATH_STRING) &&
(tmp->stringval != NULL) && (tmp->stringval[0] != 0)) {
int len;
if ((len = xmlStrlen(tmp->stringval)) >= (BR_IFNAME_MAXLEN-1)) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("forward device name '%s' is too long"),
(char*)tmp->stringval);
goto error;
}
strcpy(def->forwardDev, (char*)tmp->stringval);
} else {
def->forwardDev[0] = '\0';
}
xmlXPathFreeObject(tmp);
tmp = NULL;
} else {
def->forward = 0;
}
xmlXPathFreeObject(obj);
xmlXPathFreeContext(ctxt);
return def;
error:
/* XXX free all the stuff in the qemud_network struct, or leave it upto
the caller ? */
xmlXPathFreeObject(obj);
xmlXPathFreeObject(tmp);
xmlXPathFreeContext(ctxt);
qemudFreeNetworkDef(def);
return NULL;
}
struct qemud_network_def *
qemudParseNetworkDef(virConnectPtr conn,
struct qemud_driver *driver,
const char *xmlStr,
const char *displayName) {
xmlDocPtr xml;
struct qemud_network_def *def;
if (!(xml = xmlReadDoc(BAD_CAST xmlStr, displayName ? displayName : "network.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR, NULL);
return NULL;
}
def = qemudParseNetworkXML(conn, driver, xml);
xmlFreeDoc(xml);
return def;
}
struct qemud_network *
qemudAssignNetworkDef(virConnectPtr conn,
struct qemud_driver *driver,
struct qemud_network_def *def) {
struct qemud_network *network;
if ((network = qemudFindNetworkByName(driver, def->name))) {
if (!qemudIsActiveNetwork(network)) {
qemudFreeNetworkDef(network->def);
network->def = def;
} else {
if (network->newDef)
qemudFreeNetworkDef(network->newDef);
network->newDef = def;
}
return network;
}
if (VIR_ALLOC(network) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for network string"));
return NULL;
}
network->def = def;
network->next = driver->networks;
driver->networks = network;
driver->ninactivenetworks++;
return network;
}
void
qemudRemoveInactiveNetwork(struct qemud_driver *driver,
struct qemud_network *network)
{
struct qemud_network *prev = NULL, *curr;
curr = driver->networks;
while (curr != network) {
prev = curr;
curr = curr->next;
}
if (curr) {
if (prev)
prev->next = curr->next;
else
driver->networks = curr->next;
driver->ninactivenetworks--;
}
qemudFreeNetwork(network);
}
int
qemudSaveNetworkDef(virConnectPtr conn,
struct qemud_driver *driver,
struct qemud_network *network,
struct qemud_network_def *def) {
if (network->configFile[0] == '\0') {
int err;
if ((err = virFileMakePath(driver->networkConfigDir))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("cannot create config directory %s: %s"),
driver->networkConfigDir, strerror(err));
return -1;
}
if (virFileBuildPath(driver->networkConfigDir, def->name, ".xml",
network->configFile, PATH_MAX) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot construct config file path"));
return -1;
}
if (virFileBuildPath(driver->networkAutostartDir, def->name, ".xml",
network->autostartLink, PATH_MAX) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot construct autostart link path"));
network->configFile[0] = '\0';
return -1;
}
}
return qemudSaveNetworkConfig(conn, driver, network, def);
}
static struct qemud_vm *
qemudLoadConfig(struct qemud_driver *driver,
@ -3627,54 +3142,10 @@ qemudLoadConfig(struct qemud_driver *driver,
return vm;
}
static struct qemud_network *
qemudLoadNetworkConfig(struct qemud_driver *driver,
const char *file,
const char *path,
const char *xml,
const char *autostartLink) {
struct qemud_network_def *def;
struct qemud_network *network;
if (!(def = qemudParseNetworkDef(NULL, driver, xml, file))) {
virErrorPtr err = virGetLastError();
qemudLog(QEMUD_WARN, _("Error parsing network config '%s' : %s"),
path, err->message);
return NULL;
}
if (!virFileMatchesNameSuffix(file, def->name, ".xml")) {
qemudLog(QEMUD_WARN,
_("Network config filename '%s'"
" does not match network name '%s'"),
path, def->name);
qemudFreeNetworkDef(def);
return NULL;
}
if (!(network = qemudAssignNetworkDef(NULL, driver, def))) {
qemudLog(QEMUD_WARN,
_("Failed to load network config '%s': out of memory"), path);
qemudFreeNetworkDef(def);
return NULL;
}
strncpy(network->configFile, path, PATH_MAX);
network->configFile[PATH_MAX-1] = '\0';
strncpy(network->autostartLink, autostartLink, PATH_MAX);
network->autostartLink[PATH_MAX-1] = '\0';
network->autostart = virFileLinkPointsTo(network->autostartLink, network->configFile);
return network;
}
static
int qemudScanConfigDir(struct qemud_driver *driver,
const char *configDir,
const char *autostartDir,
int isGuest) {
const char *autostartDir) {
DIR *dir;
struct dirent *entry;
@ -3713,10 +3184,7 @@ int qemudScanConfigDir(struct qemud_driver *driver,
if (virFileReadAll(path, QEMUD_MAX_XML_LEN, &xml) < 0)
continue;
if (isGuest)
qemudLoadConfig(driver, entry->d_name, path, xml, autostartLink);
else
qemudLoadNetworkConfig(driver, entry->d_name, path, xml, autostartLink);
qemudLoadConfig(driver, entry->d_name, path, xml, autostartLink);
VIR_FREE(xml);
}
@ -3728,10 +3196,7 @@ int qemudScanConfigDir(struct qemud_driver *driver,
/* Scan for all guest and network config files */
int qemudScanConfigs(struct qemud_driver *driver) {
if (qemudScanConfigDir(driver, driver->configDir, driver->autostartDir, 1) < 0)
return -1;
if (qemudScanConfigDir(driver, driver->networkConfigDir, driver->networkAutostartDir, 0) < 0)
if (qemudScanConfigDir(driver, driver->configDir, driver->autostartDir) < 0)
return -1;
return 0;
@ -4137,83 +3602,6 @@ char *qemudGenerateXML(virConnectPtr conn,
}
char *qemudGenerateNetworkXML(virConnectPtr conn,
struct qemud_driver *driver ATTRIBUTE_UNUSED,
struct qemud_network *network,
struct qemud_network_def *def) {
virBuffer buf = VIR_BUFFER_INITIALIZER;
unsigned char *uuid;
char *tmp;
char uuidstr[VIR_UUID_STRING_BUFLEN];
virBufferAddLit(&buf, "<network>\n");
virBufferVSprintf(&buf, " <name>%s</name>\n", def->name);
uuid = def->uuid;
virUUIDFormat(uuid, uuidstr);
virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr);
if (def->forward) {
if (def->forwardDev[0]) {
virBufferVSprintf(&buf, " <forward dev='%s' mode='%s'/>\n",
def->forwardDev, (def->forwardMode == QEMUD_NET_FORWARD_ROUTE ? "route" : "nat"));
} else {
virBufferVSprintf(&buf, " <forward mode='%s'/>\n", (def->forwardMode == QEMUD_NET_FORWARD_ROUTE ? "route" : "nat"));
}
}
virBufferAddLit(&buf, " <bridge");
if (qemudIsActiveNetwork(network)) {
virBufferVSprintf(&buf, " name='%s'", network->bridge);
} else if (def->bridge[0]) {
virBufferVSprintf(&buf, " name='%s'", def->bridge);
}
virBufferVSprintf(&buf, " stp='%s' forwardDelay='%d' />\n",
def->disableSTP ? "off" : "on",
def->forwardDelay);
if (def->ipAddress[0] || def->netmask[0]) {
virBufferAddLit(&buf, " <ip");
if (def->ipAddress[0])
virBufferVSprintf(&buf, " address='%s'", def->ipAddress);
if (def->netmask[0])
virBufferVSprintf(&buf, " netmask='%s'", def->netmask);
virBufferAddLit(&buf, ">\n");
if (def->ranges) {
struct qemud_dhcp_range_def *range = def->ranges;
virBufferAddLit(&buf, " <dhcp>\n");
while (range) {
virBufferVSprintf(&buf, " <range start='%s' end='%s' />\n",
range->start, range->end);
range = range->next;
}
virBufferAddLit(&buf, " </dhcp>\n");
}
virBufferAddLit(&buf, " </ip>\n");
}
virBufferAddLit(&buf, "</network>\n");
if (virBufferError(&buf))
goto no_memory;
return virBufferContentAndReset(&buf);
no_memory:
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to generate XML: out of memory"));
tmp = virBufferContentAndReset(&buf);
VIR_FREE(tmp);
return NULL;
}
int qemudDeleteConfig(virConnectPtr conn,
struct qemud_driver *driver ATTRIBUTE_UNUSED,
const char *configFile,

View File

@ -32,6 +32,7 @@
#include "bridge.h"
#include "iptables.h"
#include "capabilities.h"
#include "network_conf.h"
#include <netinet/in.h>
#include <sched.h>
@ -96,12 +97,6 @@ enum qemud_vm_net_type {
QEMUD_NET_BRIDGE,
};
/* 2 possible types of forwarding */
enum qemud_vm_net_forward_type {
QEMUD_NET_FORWARD_NAT,
QEMUD_NET_FORWARD_ROUTE,
};
#define QEMUD_MAX_NAME_LEN 50
#define QEMUD_MAX_XML_LEN 4096
#define QEMUD_MAX_ERROR_LEN 1024
@ -349,53 +344,6 @@ 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[VIR_UUID_BUFLEN];
char name[QEMUD_MAX_NAME_LEN];
char bridge[BR_IFNAME_MAXLEN];
int disableSTP;
int forwardDelay;
int forward;
int forwardMode; /* From qemud_vm_net_forward_type */
char forwardDev[BR_IFNAME_MAXLEN];
char ipAddress[BR_INET_ADDR_MAXLEN];
char netmask[BR_INET_ADDR_MAXLEN];
char network[BR_INET_ADDR_MAXLEN+BR_INET_ADDR_MAXLEN+1];
int nranges;
struct qemud_dhcp_range_def *ranges;
};
/* Virtual Network runtime state */
struct qemud_network {
char configFile[PATH_MAX];
char autostartLink[PATH_MAX];
struct qemud_network_def *def; /* The current definition */
struct qemud_network_def *newDef; /* New definition to activate at shutdown */
char bridge[BR_IFNAME_MAXLEN];
int dnsmasqPid;
unsigned int active : 1;
unsigned int autostart : 1;
struct qemud_network *next;
};
/* Main driver state */
struct qemud_driver {
int qemuVersion;
@ -403,9 +351,9 @@ struct qemud_driver {
int ninactivevms;
struct qemud_vm *vms;
int nextvmid;
int nactivenetworks;
int ninactivenetworks;
struct qemud_network *networks;
virNetworkObjPtr networks;
brControl *brctl;
iptablesContext *iptables;
char *configDir;
@ -428,12 +376,6 @@ qemudIsActiveVM(const struct qemud_vm *vm)
return vm->id != -1;
}
static inline int
qemudIsActiveNetwork(const struct qemud_network *network)
{
return network->active;
}
void qemudReportError(virConnectPtr conn,
virDomainPtr dom,
virNetworkPtr net,
@ -451,11 +393,6 @@ struct qemud_vm *qemudFindVMByUUID(const struct qemud_driver *driver,
struct qemud_vm *qemudFindVMByName(const struct qemud_driver *driver,
const char *name);
struct qemud_network *qemudFindNetworkByUUID(const struct qemud_driver *driver,
const unsigned char *uuid);
struct qemud_network *qemudFindNetworkByName(const struct qemud_driver *driver,
const char *name);
virCapsPtr qemudCapsInit (void);
int qemudExtractVersion (virConnectPtr conn,
@ -501,30 +438,6 @@ char * qemudGenerateXML (virConnectPtr conn,
struct qemud_vm_def *def,
int live);
void qemudFreeNetworkDef (struct qemud_network_def *def);
void qemudFreeNetwork (struct qemud_network *network);
struct qemud_network *
qemudAssignNetworkDef (virConnectPtr conn,
struct qemud_driver *driver,
struct qemud_network_def *def);
void qemudRemoveInactiveNetwork (struct qemud_driver *driver,
struct qemud_network *network);
struct qemud_network_def *
qemudParseNetworkDef (virConnectPtr conn,
struct qemud_driver *driver,
const char *xmlStr,
const char *displayName);
int qemudSaveNetworkDef (virConnectPtr conn,
struct qemud_driver *driver,
struct qemud_network *network,
struct qemud_network_def *def);
char * qemudGenerateNetworkXML (virConnectPtr conn,
struct qemud_driver *driver,
struct qemud_network *network,
struct qemud_network_def *def);
const char *qemudVirtTypeToString (int type);
#endif /* WITH_QEMU */

View File

@ -120,11 +120,11 @@ static void qemudShutdownVMDaemon(virConnectPtr conn,
static int qemudStartNetworkDaemon(virConnectPtr conn,
struct qemud_driver *driver,
struct qemud_network *network);
virNetworkObjPtr network);
static int qemudShutdownNetworkDaemon(virConnectPtr conn,
struct qemud_driver *driver,
struct qemud_network *network);
virNetworkObjPtr network);
static int qemudDomainGetMaxVcpus(virDomainPtr dom);
static int qemudMonitorCommand (const struct qemud_driver *driver,
@ -137,15 +137,15 @@ static struct qemud_driver *qemu_driver = NULL;
static
void qemudAutostartConfigs(struct qemud_driver *driver) {
struct qemud_network *network;
virNetworkObjPtr network;
struct qemud_vm *vm;
network = driver->networks;
while (network != NULL) {
struct qemud_network *next = network->next;
virNetworkObjPtr next = network->next;
if (network->autostart &&
!qemudIsActiveNetwork(network) &&
!virNetworkIsActive(network) &&
qemudStartNetworkDaemon(NULL, driver, network) < 0) {
virErrorPtr err = virGetLastError();
qemudLog(QEMUD_ERR, _("Failed to autostart network '%s': %s"),
@ -247,6 +247,13 @@ qemudStartup(void) {
qemudShutdown();
return -1;
}
if (virNetworkLoadAllConfigs(NULL,
&qemu_driver->networks,
qemu_driver->networkConfigDir,
qemu_driver->networkAutostartDir) < 0) {
qemudShutdown();
return -1;
}
qemudAutostartConfigs(qemu_driver);
return 0;
@ -273,6 +280,10 @@ qemudStartup(void) {
static int
qemudReload(void) {
qemudScanConfigs(qemu_driver);
virNetworkLoadAllConfigs(NULL,
&qemu_driver->networks,
qemu_driver->networkConfigDir,
qemu_driver->networkAutostartDir);
if (qemu_driver->iptables) {
qemudLog(QEMUD_INFO,
@ -295,11 +306,14 @@ qemudReload(void) {
*/
static int
qemudActive(void) {
/* If we've any active networks or guests, then we
* mark this driver as active
*/
if (qemu_driver->nactivenetworks &&
qemu_driver->nactivevms)
virNetworkObjPtr net = qemu_driver->networks;
while (net) {
if (net->active)
return 1;
net = net->next;
}
if (qemu_driver->nactivevms)
return 1;
/* Otherwise we're happy to deal with a shutdown */
@ -314,7 +328,7 @@ qemudActive(void) {
static int
qemudShutdown(void) {
struct qemud_vm *vm;
struct qemud_network *network;
virNetworkObjPtr network;
if (!qemu_driver)
return -1;
@ -346,8 +360,8 @@ qemudShutdown(void) {
/* shutdown active networks */
network = qemu_driver->networks;
while (network) {
struct qemud_network *next = network->next;
if (qemudIsActiveNetwork(network))
virNetworkObjPtr next = network->next;
if (virNetworkIsActive(network))
qemudShutdownNetworkDaemon(NULL, qemu_driver, network);
network = next;
}
@ -355,13 +369,11 @@ qemudShutdown(void) {
/* free inactive networks */
network = qemu_driver->networks;
while (network) {
struct qemud_network *next = network->next;
qemudFreeNetwork(network);
virNetworkObjPtr next = network->next;
virNetworkObjFree(network);
network = next;
}
qemu_driver->networks = NULL;
qemu_driver->nactivenetworks = 0;
qemu_driver->ninactivenetworks = 0;
VIR_FREE(qemu_driver->configDir);
VIR_FREE(qemu_driver->autostartDir);
@ -1043,11 +1055,10 @@ static int qemudDispatchVMFailure(struct qemud_driver *driver, struct qemud_vm *
static int
qemudBuildDnsmasqArgv(virConnectPtr conn,
struct qemud_network *network,
virNetworkObjPtr network,
char ***argv) {
int i, len;
int i, len, r;
char buf[PATH_MAX];
struct qemud_dhcp_range_def *range;
len =
1 + /* dnsmasq */
@ -1113,15 +1124,13 @@ qemudBuildDnsmasqArgv(virConnectPtr conn,
LOCAL_STATE_DIR, network->def->name);
APPEND_ARG(*argv, i++, buf);
range = network->def->ranges;
while (range) {
for (r = 0 ; r < network->def->nranges ; r++) {
snprintf(buf, sizeof(buf), "%s,%s",
range->start, range->end);
network->def->ranges[r].start,
network->def->ranges[r].end);
APPEND_ARG(*argv, i++, "--dhcp-range");
APPEND_ARG(*argv, i++, buf);
range = range->next;
}
#undef APPEND_ARG
@ -1142,12 +1151,12 @@ qemudBuildDnsmasqArgv(virConnectPtr conn,
static int
dhcpStartDhcpDaemon(virConnectPtr conn,
struct qemud_network *network)
virNetworkObjPtr network)
{
char **argv;
int ret, i;
if (network->def->ipAddress[0] == '\0') {
if (network->def->ipAddress == NULL) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot start dhcp daemon without IP address for server"));
return -1;
@ -1169,27 +1178,27 @@ dhcpStartDhcpDaemon(virConnectPtr conn,
static int
qemudAddMasqueradingIptablesRules(virConnectPtr conn,
struct qemud_driver *driver,
struct qemud_network *network) {
virNetworkObjPtr network) {
int err;
/* allow forwarding packets from the bridge interface */
if ((err = iptablesAddForwardAllowOut(driver->iptables,
network->def->network,
network->bridge,
network->def->bridge,
network->def->forwardDev))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to add iptables rule to allow forwarding from '%s' : %s\n"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
goto masqerr1;
}
/* allow forwarding packets to the bridge interface if they are part of an existing connection */
if ((err = iptablesAddForwardAllowRelatedIn(driver->iptables,
network->def->network,
network->bridge,
network->def->bridge,
network->def->forwardDev))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to add iptables rule to allow forwarding to '%s' : %s\n"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
goto masqerr2;
}
@ -1208,12 +1217,12 @@ qemudAddMasqueradingIptablesRules(virConnectPtr conn,
masqerr3:
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
network->def->network,
network->bridge,
network->def->bridge,
network->def->forwardDev);
masqerr2:
iptablesRemoveForwardAllowOut(driver->iptables,
network->def->network,
network->bridge,
network->def->bridge,
network->def->forwardDev);
masqerr1:
return 0;
@ -1222,27 +1231,27 @@ qemudAddMasqueradingIptablesRules(virConnectPtr conn,
static int
qemudAddRoutingIptablesRules(virConnectPtr conn,
struct qemud_driver *driver,
struct qemud_network *network) {
virNetworkObjPtr network) {
int err;
/* allow routing packets from the bridge interface */
if ((err = iptablesAddForwardAllowOut(driver->iptables,
network->def->network,
network->bridge,
network->def->bridge,
network->def->forwardDev))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to add iptables rule to allow routing from '%s' : %s\n"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
goto routeerr1;
}
/* allow routing packets to the bridge interface */
if ((err = iptablesAddForwardAllowIn(driver->iptables,
network->def->network,
network->bridge,
network->def->bridge,
network->def->forwardDev))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to add iptables rule to allow routing to '%s' : %s\n"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
goto routeerr2;
}
@ -1252,7 +1261,7 @@ qemudAddRoutingIptablesRules(virConnectPtr conn,
routeerr2:
iptablesRemoveForwardAllowOut(driver->iptables,
network->def->network,
network->bridge,
network->def->bridge,
network->def->forwardDev);
routeerr1:
return 0;
@ -1261,7 +1270,7 @@ qemudAddRoutingIptablesRules(virConnectPtr conn,
static int
qemudAddIptablesRules(virConnectPtr conn,
struct qemud_driver *driver,
struct qemud_network *network) {
virNetworkObjPtr network) {
int err;
if (!driver->iptables && !(driver->iptables = iptablesContextNew())) {
@ -1272,71 +1281,69 @@ qemudAddIptablesRules(virConnectPtr conn,
/* allow DHCP requests through to dnsmasq */
if ((err = iptablesAddTcpInput(driver->iptables, network->bridge, 67))) {
if ((err = iptablesAddTcpInput(driver->iptables, network->def->bridge, 67))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to add iptables rule to allow DHCP requests from '%s' : %s"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
goto err1;
}
if ((err = iptablesAddUdpInput(driver->iptables, network->bridge, 67))) {
if ((err = iptablesAddUdpInput(driver->iptables, network->def->bridge, 67))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to add iptables rule to allow DHCP requests from '%s' : %s"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
goto err2;
}
/* allow DNS requests through to dnsmasq */
if ((err = iptablesAddTcpInput(driver->iptables, network->bridge, 53))) {
if ((err = iptablesAddTcpInput(driver->iptables, network->def->bridge, 53))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to add iptables rule to allow DNS requests from '%s' : %s"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
goto err3;
}
if ((err = iptablesAddUdpInput(driver->iptables, network->bridge, 53))) {
if ((err = iptablesAddUdpInput(driver->iptables, network->def->bridge, 53))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to add iptables rule to allow DNS requests from '%s' : %s"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
goto err4;
}
/* Catch all rules to block forwarding to/from bridges */
if ((err = iptablesAddForwardRejectOut(driver->iptables, network->bridge))) {
if ((err = iptablesAddForwardRejectOut(driver->iptables, network->def->bridge))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to add iptables rule to block outbound traffic from '%s' : %s"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
goto err5;
}
if ((err = iptablesAddForwardRejectIn(driver->iptables, network->bridge))) {
if ((err = iptablesAddForwardRejectIn(driver->iptables, network->def->bridge))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to add iptables rule to block inbound traffic to '%s' : %s"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
goto err6;
}
/* Allow traffic between guests on the same bridge */
if ((err = iptablesAddForwardAllowCross(driver->iptables, network->bridge))) {
if ((err = iptablesAddForwardAllowCross(driver->iptables, network->def->bridge))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to add iptables rule to allow cross bridge traffic on '%s' : %s"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
goto err7;
}
if (network->def->forward) {
/* If masquerading is enabled, set up the rules*/
if (network->def->forwardMode == QEMUD_NET_FORWARD_NAT &&
!qemudAddMasqueradingIptablesRules(conn, driver, network))
goto err8;
/* else if routing is enabled, set up the rules*/
else if (network->def->forwardMode == QEMUD_NET_FORWARD_ROUTE &&
!qemudAddRoutingIptablesRules(conn, driver, network))
goto err8;
}
/* If masquerading is enabled, set up the rules*/
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT &&
!qemudAddMasqueradingIptablesRules(conn, driver, network))
goto err8;
/* else if routing is enabled, set up the rules*/
else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE &&
!qemudAddRoutingIptablesRules(conn, driver, network))
goto err8;
iptablesSaveRules(driver->iptables);
@ -1344,56 +1351,56 @@ qemudAddIptablesRules(virConnectPtr conn,
err8:
iptablesRemoveForwardAllowCross(driver->iptables,
network->bridge);
network->def->bridge);
err7:
iptablesRemoveForwardRejectIn(driver->iptables,
network->bridge);
network->def->bridge);
err6:
iptablesRemoveForwardRejectOut(driver->iptables,
network->bridge);
network->def->bridge);
err5:
iptablesRemoveUdpInput(driver->iptables, network->bridge, 53);
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 53);
err4:
iptablesRemoveTcpInput(driver->iptables, network->bridge, 53);
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 53);
err3:
iptablesRemoveUdpInput(driver->iptables, network->bridge, 67);
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 67);
err2:
iptablesRemoveTcpInput(driver->iptables, network->bridge, 67);
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 67);
err1:
return 0;
}
static void
qemudRemoveIptablesRules(struct qemud_driver *driver,
struct qemud_network *network) {
if (network->def->forward) {
virNetworkObjPtr network) {
if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE) {
iptablesRemoveForwardMasquerade(driver->iptables,
network->def->network,
network->def->forwardDev);
if (network->def->forwardMode == QEMUD_NET_FORWARD_NAT)
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT)
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
network->def->network,
network->bridge,
network->def->bridge,
network->def->forwardDev);
else if (network->def->forwardMode == QEMUD_NET_FORWARD_ROUTE)
else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE)
iptablesRemoveForwardAllowIn(driver->iptables,
network->def->network,
network->bridge,
network->def->bridge,
network->def->forwardDev);
iptablesRemoveForwardAllowOut(driver->iptables,
network->def->network,
network->bridge,
network->def->bridge,
network->def->forwardDev);
}
iptablesRemoveForwardAllowCross(driver->iptables, network->bridge);
iptablesRemoveForwardRejectIn(driver->iptables, network->bridge);
iptablesRemoveForwardRejectOut(driver->iptables, network->bridge);
iptablesRemoveUdpInput(driver->iptables, network->bridge, 53);
iptablesRemoveTcpInput(driver->iptables, network->bridge, 53);
iptablesRemoveUdpInput(driver->iptables, network->bridge, 67);
iptablesRemoveTcpInput(driver->iptables, network->bridge, 67);
iptablesRemoveForwardAllowCross(driver->iptables, network->def->bridge);
iptablesRemoveForwardRejectIn(driver->iptables, network->def->bridge);
iptablesRemoveForwardRejectOut(driver->iptables, network->def->bridge);
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 53);
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 53);
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 67);
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 67);
iptablesSaveRules(driver->iptables);
}
@ -1419,11 +1426,10 @@ qemudEnableIpForwarding(void)
static int qemudStartNetworkDaemon(virConnectPtr conn,
struct qemud_driver *driver,
struct qemud_network *network) {
const char *name;
virNetworkObjPtr network) {
int err;
if (qemudIsActiveNetwork(network)) {
if (virNetworkIsActive(network)) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("network is already active"));
return -1;
@ -1435,94 +1441,85 @@ static int qemudStartNetworkDaemon(virConnectPtr conn,
return -1;
}
if (network->def->bridge[0] == '\0' ||
strchr(network->def->bridge, '%')) {
name = "vnet%d";
} else {
name = network->def->bridge;
}
if ((err = brAddBridge(driver->brctl, name, network->bridge, sizeof(network->bridge)))) {
if ((err = brAddBridge(driver->brctl, &network->def->bridge))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("cannot create bridge '%s' : %s"), name, strerror(err));
_("cannot create bridge '%s' : %s"),
network->def->bridge, strerror(err));
return -1;
}
if (network->def->forwardDelay &&
(err = brSetForwardDelay(driver->brctl, network->bridge, network->def->forwardDelay))) {
if (network->def->delay &&
(err = brSetForwardDelay(driver->brctl, network->def->bridge, network->def->delay))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to set bridge forward delay to %d"),
network->def->forwardDelay);
_("failed to set bridge forward delay to %ld"),
network->def->delay);
goto err_delbr;
}
if ((err = brSetEnableSTP(driver->brctl, network->bridge, network->def->disableSTP ? 0 : 1))) {
if ((err = brSetEnableSTP(driver->brctl, network->def->bridge, network->def->stp ? 1 : 0))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to set bridge STP to %s"),
network->def->disableSTP ? "off" : "on");
network->def->stp ? "on" : "off");
goto err_delbr;
}
if (network->def->ipAddress[0] &&
(err = brSetInetAddress(driver->brctl, network->bridge, network->def->ipAddress))) {
if (network->def->ipAddress &&
(err = brSetInetAddress(driver->brctl, network->def->bridge, network->def->ipAddress))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("cannot set IP address on bridge '%s' to '%s' : %s"),
network->bridge, network->def->ipAddress, strerror(err));
network->def->bridge, network->def->ipAddress, strerror(err));
goto err_delbr;
}
if (network->def->netmask[0] &&
(err = brSetInetNetmask(driver->brctl, network->bridge, network->def->netmask))) {
if (network->def->netmask &&
(err = brSetInetNetmask(driver->brctl, network->def->bridge, network->def->netmask))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("cannot set netmask on bridge '%s' to '%s' : %s"),
network->bridge, network->def->netmask, strerror(err));
network->def->bridge, network->def->netmask, strerror(err));
goto err_delbr;
}
if (network->def->ipAddress[0] &&
(err = brSetInterfaceUp(driver->brctl, network->bridge, 1))) {
if (network->def->ipAddress &&
(err = brSetInterfaceUp(driver->brctl, network->def->bridge, 1))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to bring the bridge '%s' up : %s"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
goto err_delbr;
}
if (!qemudAddIptablesRules(conn, driver, network))
goto err_delbr1;
if (network->def->forward &&
if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE &&
!qemudEnableIpForwarding()) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to enable IP forwarding : %s"), strerror(err));
goto err_delbr2;
}
if (network->def->ranges &&
if (network->def->nranges &&
dhcpStartDhcpDaemon(conn, network) < 0)
goto err_delbr2;
network->active = 1;
driver->ninactivenetworks--;
driver->nactivenetworks++;
return 0;
err_delbr2:
qemudRemoveIptablesRules(driver, network);
err_delbr1:
if (network->def->ipAddress[0] &&
(err = brSetInterfaceUp(driver->brctl, network->bridge, 0))) {
if (network->def->ipAddress &&
(err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
qemudLog(QEMUD_WARN, _("Failed to bring down bridge '%s' : %s"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
}
err_delbr:
if ((err = brDeleteBridge(driver->brctl, network->bridge))) {
if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) {
qemudLog(QEMUD_WARN, _("Failed to delete bridge '%s' : %s"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
}
return -1;
@ -1531,12 +1528,12 @@ static int qemudStartNetworkDaemon(virConnectPtr conn,
static int qemudShutdownNetworkDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
struct qemud_driver *driver,
struct qemud_network *network) {
virNetworkObjPtr network) {
int err;
qemudLog(QEMUD_INFO, _("Shutting down network '%s'"), network->def->name);
if (!qemudIsActiveNetwork(network))
if (!virNetworkIsActive(network))
return 0;
if (network->dnsmasqPid > 0)
@ -1544,15 +1541,15 @@ static int qemudShutdownNetworkDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
qemudRemoveIptablesRules(driver, network);
if (network->def->ipAddress[0] &&
(err = brSetInterfaceUp(driver->brctl, network->bridge, 0))) {
if (network->def->ipAddress &&
(err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
qemudLog(QEMUD_WARN, _("Failed to bring down bridge '%s' : %s"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
}
if ((err = brDeleteBridge(driver->brctl, network->bridge))) {
if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) {
qemudLog(QEMUD_WARN, _("Failed to delete bridge '%s' : %s"),
network->bridge, strerror(err));
network->def->bridge, strerror(err));
}
if (network->dnsmasqPid > 0 &&
@ -1563,21 +1560,18 @@ static int qemudShutdownNetworkDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
"%s", _("Got unexpected pid for dnsmasq"));
}
network->bridge[0] = '\0';
network->dnsmasqPid = -1;
network->active = 0;
if (network->newDef) {
qemudFreeNetworkDef(network->def);
virNetworkDefFree(network->def);
network->def = network->newDef;
network->newDef = NULL;
}
driver->nactivenetworks--;
driver->ninactivenetworks++;
if (!network->configFile[0])
qemudRemoveInactiveNetwork(driver, network);
if (!network->configFile)
virNetworkRemoveInactive(&driver->networks,
network);
return 0;
}
@ -3294,9 +3288,9 @@ done:
}
static virNetworkPtr qemudNetworkLookupByUUID(virConnectPtr conn ATTRIBUTE_UNUSED,
const unsigned char *uuid) {
const unsigned char *uuid) {
struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
struct qemud_network *network = qemudFindNetworkByUUID(driver, uuid);
virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, uuid);
virNetworkPtr net;
if (!network) {
@ -3309,9 +3303,9 @@ static virNetworkPtr qemudNetworkLookupByUUID(virConnectPtr conn ATTRIBUTE_UNUSE
return net;
}
static virNetworkPtr qemudNetworkLookupByName(virConnectPtr conn ATTRIBUTE_UNUSED,
const char *name) {
const char *name) {
struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
struct qemud_network *network = qemudFindNetworkByName(driver, name);
virNetworkObjPtr network = virNetworkFindByName(driver->networks, name);
virNetworkPtr net;
if (!network) {
@ -3341,16 +3335,23 @@ static int qemudCloseNetwork(virConnectPtr conn) {
}
static int qemudNumNetworks(virConnectPtr conn) {
int nactive = 0;
struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
return driver->nactivenetworks;
virNetworkObjPtr net = driver->networks;
while (net) {
if (virNetworkIsActive(net))
nactive++;
net = net->next;
}
return nactive;
}
static int qemudListNetworks(virConnectPtr conn, char **const names, int nnames) {
struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
struct qemud_network *network = driver->networks;
virNetworkObjPtr network = driver->networks;
int got = 0, i;
while (network && got < nnames) {
if (qemudIsActiveNetwork(network)) {
if (virNetworkIsActive(network)) {
if (!(names[got] = strdup(network->def->name))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for VM name string"));
@ -3369,16 +3370,23 @@ static int qemudListNetworks(virConnectPtr conn, char **const names, int nnames)
}
static int qemudNumDefinedNetworks(virConnectPtr conn) {
int ninactive = 0;
struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
return driver->ninactivenetworks;
virNetworkObjPtr net = driver->networks;
while (net) {
if (!virNetworkIsActive(net))
ninactive++;
net = net->next;
}
return ninactive;
}
static int qemudListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
struct qemud_network *network = driver->networks;
virNetworkObjPtr network = driver->networks;
int got = 0, i;
while (network && got < nnames) {
if (!qemudIsActiveNetwork(network)) {
if (!virNetworkIsActive(network)) {
if (!(names[got] = strdup(network->def->name))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for VM name string"));
@ -3398,20 +3406,23 @@ static int qemudListDefinedNetworks(virConnectPtr conn, char **const names, int
static virNetworkPtr qemudNetworkCreate(virConnectPtr conn, const char *xml) {
struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
struct qemud_network_def *def;
struct qemud_network *network;
virNetworkDefPtr def;
virNetworkObjPtr network;
virNetworkPtr net;
if (!(def = qemudParseNetworkDef(conn, driver, xml, NULL)))
if (!(def = virNetworkDefParseString(conn, xml)))
return NULL;
if (!(network = qemudAssignNetworkDef(conn, driver, def))) {
qemudFreeNetworkDef(def);
if (!(network = virNetworkAssignDef(conn,
&driver->networks,
def))) {
virNetworkDefFree(def);
return NULL;
}
if (qemudStartNetworkDaemon(conn, driver, network) < 0) {
qemudRemoveInactiveNetwork(driver, network);
virNetworkRemoveInactive(&driver->networks,
network);
return NULL;
}
@ -3421,30 +3432,34 @@ static virNetworkPtr qemudNetworkCreate(virConnectPtr conn, const char *xml) {
static virNetworkPtr qemudNetworkDefine(virConnectPtr conn, const char *xml) {
struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
struct qemud_network_def *def;
struct qemud_network *network;
virNetworkPtr net;
virNetworkDefPtr def;
virNetworkObjPtr network;
if (!(def = qemudParseNetworkDef(conn, driver, xml, NULL)))
if (!(def = virNetworkDefParseString(conn, xml)))
return NULL;
if (!(network = qemudAssignNetworkDef(conn, driver, def))) {
qemudFreeNetworkDef(def);
if (!(network = virNetworkAssignDef(conn,
&driver->networks,
def))) {
virNetworkDefFree(def);
return NULL;
}
if (qemudSaveNetworkDef(conn, driver, network, def) < 0) {
qemudRemoveInactiveNetwork(driver, network);
if (virNetworkSaveConfig(conn,
driver->networkConfigDir,
driver->networkAutostartDir,
network) < 0) {
virNetworkRemoveInactive(&driver->networks,
network);
return NULL;
}
net = virGetNetwork(conn, network->def->name, network->def->uuid);
return net;
return virGetNetwork(conn, network->def->name, network->def->uuid);
}
static int qemudNetworkUndefine(virNetworkPtr net) {
struct qemud_driver *driver = (struct qemud_driver *)net->conn->networkPrivateData;
struct qemud_network *network = qemudFindNetworkByUUID(driver, net->uuid);
virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid);
if (!network) {
qemudReportError(net->conn, NULL, net, VIR_ERR_INVALID_DOMAIN,
@ -3452,24 +3467,24 @@ static int qemudNetworkUndefine(virNetworkPtr net) {
return -1;
}
if (qemudDeleteConfig(net->conn, driver, network->configFile, network->def->name) < 0)
if (virNetworkIsActive(network)) {
qemudReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR,
"%s", _("network is still active"));
return -1;
}
if (virNetworkDeleteConfig(net->conn, network) < 0)
return -1;
if (unlink(network->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR)
qemudLog(QEMUD_WARN, _("Failed to delete autostart link '%s': %s"),
network->autostartLink, strerror(errno));
network->configFile[0] = '\0';
network->autostartLink[0] = '\0';
qemudRemoveInactiveNetwork(driver, network);
virNetworkRemoveInactive(&driver->networks,
network);
return 0;
}
static int qemudNetworkStart(virNetworkPtr net) {
struct qemud_driver *driver = (struct qemud_driver *)net->conn->networkPrivateData;
struct qemud_network *network = qemudFindNetworkByUUID(driver, net->uuid);
virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid);
if (!network) {
qemudReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
@ -3482,7 +3497,7 @@ static int qemudNetworkStart(virNetworkPtr net) {
static int qemudNetworkDestroy(virNetworkPtr net) {
struct qemud_driver *driver = (struct qemud_driver *)net->conn->networkPrivateData;
struct qemud_network *network = qemudFindNetworkByUUID(driver, net->uuid);
virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid);
int ret;
if (!network) {
@ -3498,7 +3513,7 @@ static int qemudNetworkDestroy(virNetworkPtr net) {
static char *qemudNetworkDumpXML(virNetworkPtr net, int flags ATTRIBUTE_UNUSED) {
struct qemud_driver *driver = (struct qemud_driver *)net->conn->networkPrivateData;
struct qemud_network *network = qemudFindNetworkByUUID(driver, net->uuid);
virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid);
if (!network) {
qemudReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
@ -3506,12 +3521,12 @@ static char *qemudNetworkDumpXML(virNetworkPtr net, int flags ATTRIBUTE_UNUSED)
return NULL;
}
return qemudGenerateNetworkXML(net->conn, driver, network, network->def);
return virNetworkDefFormat(net->conn, network->def);
}
static char *qemudNetworkGetBridgeName(virNetworkPtr net) {
struct qemud_driver *driver = (struct qemud_driver *)net->conn->networkPrivateData;
struct qemud_network *network = qemudFindNetworkByUUID(driver, net->uuid);
virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid);
char *bridge;
if (!network) {
qemudReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
@ -3519,7 +3534,7 @@ static char *qemudNetworkGetBridgeName(virNetworkPtr net) {
return NULL;
}
bridge = strdup(network->bridge);
bridge = strdup(network->def->bridge);
if (!bridge) {
qemudReportError(net->conn, NULL, net, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for network bridge string"));
@ -3531,7 +3546,7 @@ static char *qemudNetworkGetBridgeName(virNetworkPtr net) {
static int qemudNetworkGetAutostart(virNetworkPtr net,
int *autostart) {
struct qemud_driver *driver = (struct qemud_driver *)net->conn->networkPrivateData;
struct qemud_network *network = qemudFindNetworkByUUID(driver, net->uuid);
virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid);
if (!network) {
qemudReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
@ -3547,7 +3562,7 @@ static int qemudNetworkGetAutostart(virNetworkPtr net,
static int qemudNetworkSetAutostart(virNetworkPtr net,
int autostart) {
struct qemud_driver *driver = (struct qemud_driver *)net->conn->networkPrivateData;
struct qemud_network *network = qemudFindNetworkByUUID(driver, net->uuid);
virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid);
if (!network) {
qemudReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,