Currently, we are only keeping a inactive XML configuration
in status dir. This is no longer enough as we need to keep
this class_id attribute so we don't overwrite old entries
when the daemon restarts. However, since there has already
been release which has just <network/> as root element,
and we want to keep things compatible, detect that loaded
status file is older one, and don't scream about it.
---
src/conf/network_conf.c | 207 ++++++++++++++++++++++++++++++++++---------
src/conf/network_conf.h | 2 +
src/libvirt_private.syms | 1 +
src/network/bridge_driver.c | 27 +++++--
4 files changed, 190 insertions(+), 47 deletions(-)
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index ac326e1..29e3127 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -1695,6 +1695,79 @@ cleanup:
return def;
}
+int
+virNetworkObjUpdateParseFile(const char *filename,
+ virNetworkObjPtr net)
+{
+ int ret = -1;
+ xmlDocPtr xml = NULL;
+ xmlNodePtr node = NULL;
+ virNetworkDefPtr tmp = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+
+ xml = virXMLParse(filename, NULL, _("(network status)"));
+ if (!xml)
+ return -1;
+
+ ctxt = xmlXPathNewContext(xml);
+ if (ctxt == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ node = xmlDocGetRootElement(xml);
+ if (xmlStrEqual(node->name, BAD_CAST "networkstatus")) {
+ /* Newer network status file. Contains useful
+ * info which are not to be found in bare config XML */
+ char *class_id = NULL;
+ char *floor_sum = NULL;
+
+ ctxt->node = node;
+ class_id = virXPathString("string(./class_id[1]/@bitmap)", ctxt);
+ if (class_id &&
+ virBitmapParse(class_id, ',',
+ &net->class_id, CLASS_ID_BITMAP_SIZE) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Malformed 'class_id' attribute: %s"),
+ class_id);
+ VIR_FREE(class_id);
+ goto cleanup;
+ }
+ VIR_FREE(class_id);
+
+ floor_sum = virXPathString("string(./floor[1]/@sum)", ctxt);
+ if (floor_sum &&
+ virStrToLong_ull(floor_sum, NULL, 10, &net->floor_sum) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Malformed 'floor_sum' attribute: %s"),
+ floor_sum);
+ VIR_FREE(floor_sum);
+ }
+ VIR_FREE(floor_sum);
+ }
+
+ node = virXPathNode("//network", ctxt);
+ if (!node) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not find any 'network' element"));
+ goto cleanup;
+ }
+
+ ctxt->node = node;
+ tmp = virNetworkDefParseXML(ctxt);
+
+ if (tmp) {
+ net->newDef = net->def;
+ net->def = tmp;
+ }
+
+ ret = 0;
+
+cleanup:
+ xmlXPathFreeContext(ctxt);
+ return ret;
+}
+
static int
virNetworkDNSDefFormat(virBufferPtr buf,
virNetworkDNSDefPtr def)
@@ -1873,26 +1946,28 @@ virPortGroupDefFormat(virBufferPtr buf,
return 0;
}
-char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
+static int
+virNetworkDefFormatInternal(virBufferPtr buf,
+ const virNetworkDefPtr def,
+ unsigned int flags)
{
- virBuffer buf = VIR_BUFFER_INITIALIZER;
unsigned char *uuid;
char uuidstr[VIR_UUID_STRING_BUFLEN];
int ii;
- virBufferAddLit(&buf, "<network");
+ virBufferAddLit(buf, "<network");
if (!(flags & VIR_NETWORK_XML_INACTIVE) && (def->connections > 0))
{
- virBufferAsprintf(&buf, " connections='%d'",
def->connections);
+ virBufferAsprintf(buf, " connections='%d'",
def->connections);
}
if (def->ipv6nogw)
- virBufferAddLit(&buf, " ipv6='yes'");
- virBufferAddLit(&buf, ">\n");
- virBufferAdjustIndent(&buf, 2);
- virBufferEscapeString(&buf, "<name>%s</name>\n",
def->name);
+ virBufferAddLit(buf, " ipv6='yes'");
+ virBufferAddLit(buf, ">\n");
+ virBufferAdjustIndent(buf, 2);
+ virBufferEscapeString(buf, "<name>%s</name>\n", def->name);
uuid = def->uuid;
virUUIDFormat(uuid, uuidstr);
- virBufferAsprintf(&buf, "<uuid>%s</uuid>\n", uuidstr);
+ virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuidstr);
if (def->forwardType != VIR_NETWORK_FORWARD_NONE) {
const char *dev = NULL;
@@ -1906,40 +1981,40 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int
flags)
def->forwardType, def->name);
goto error;
}
- virBufferAddLit(&buf, "<forward");
- virBufferEscapeString(&buf, " dev='%s'", dev);
- virBufferAsprintf(&buf, " mode='%s'", mode);
+ virBufferAddLit(buf, "<forward");
+ virBufferEscapeString(buf, " dev='%s'", dev);
+ virBufferAsprintf(buf, " mode='%s'", mode);
if (def->forwardType == VIR_NETWORK_FORWARD_HOSTDEV) {
if (def->managed == 1)
- virBufferAddLit(&buf, " managed='yes'");
+ virBufferAddLit(buf, " managed='yes'");
else
- virBufferAddLit(&buf, " managed='no'");
+ virBufferAddLit(buf, " managed='no'");
}
- virBufferAsprintf(&buf, "%s>\n",
+ virBufferAsprintf(buf, "%s>\n",
(def->nForwardIfs || def->nForwardPfs) ? "" :
"/");
- virBufferAdjustIndent(&buf, 2);
+ virBufferAdjustIndent(buf, 2);
/* For now, hard-coded to at most 1 forwardPfs */
if (def->nForwardPfs)
- virBufferEscapeString(&buf, "<pf dev='%s'/>\n",
+ virBufferEscapeString(buf, "<pf dev='%s'/>\n",
def->forwardPfs[0].dev);
if (def->nForwardIfs &&
(!def->nForwardPfs || !(flags & VIR_NETWORK_XML_INACTIVE))) {
for (ii = 0; ii < def->nForwardIfs; ii++) {
if (def->forwardType != VIR_NETWORK_FORWARD_HOSTDEV) {
- virBufferEscapeString(&buf, "<interface
dev='%s'",
+ virBufferEscapeString(buf, "<interface
dev='%s'",
def->forwardIfs[ii].device.dev);
if (!(flags & VIR_NETWORK_XML_INACTIVE) &&
(def->forwardIfs[ii].connections > 0)) {
- virBufferAsprintf(&buf, "
connections='%d'",
+ virBufferAsprintf(buf, " connections='%d'",
def->forwardIfs[ii].connections);
}
- virBufferAddLit(&buf, "/>\n");
+ virBufferAddLit(buf, "/>\n");
}
else {
if (def->forwardIfs[ii].type ==
VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI) {
- if (virDevicePCIAddressFormat(&buf,
+ if (virDevicePCIAddressFormat(buf,
def->forwardIfs[ii].device.pci,
true) < 0)
goto error;
@@ -1947,67 +2022,116 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned
int flags)
}
}
}
- virBufferAdjustIndent(&buf, -2);
+ virBufferAdjustIndent(buf, -2);
if (def->nForwardPfs || def->nForwardIfs)
- virBufferAddLit(&buf, "</forward>\n");
+ virBufferAddLit(buf, "</forward>\n");
}
if (def->forwardType == VIR_NETWORK_FORWARD_NONE ||
- def->forwardType == VIR_NETWORK_FORWARD_NAT ||
- def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
+ def->forwardType == VIR_NETWORK_FORWARD_NAT ||
+ def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
- virBufferAddLit(&buf, "<bridge");
+ virBufferAddLit(buf, "<bridge");
if (def->bridge)
- virBufferEscapeString(&buf, " name='%s'",
def->bridge);
- virBufferAsprintf(&buf, " stp='%s' delay='%ld'
/>\n",
+ virBufferEscapeString(buf, " name='%s'", def->bridge);
+ virBufferAsprintf(buf, " stp='%s' delay='%ld'
/>\n",
def->stp ? "on" : "off",
def->delay);
} else if (def->forwardType == VIR_NETWORK_FORWARD_BRIDGE &&
def->bridge) {
- virBufferEscapeString(&buf, "<bridge name='%s' />\n",
def->bridge);
+ virBufferEscapeString(buf, "<bridge name='%s' />\n",
def->bridge);
}
if (def->mac_specified) {
char macaddr[VIR_MAC_STRING_BUFLEN];
virMacAddrFormat(&def->mac, macaddr);
- virBufferAsprintf(&buf, "<mac address='%s'/>\n",
macaddr);
+ virBufferAsprintf(buf, "<mac address='%s'/>\n",
macaddr);
}
if (def->domain)
- virBufferAsprintf(&buf, "<domain name='%s'/>\n",
def->domain);
+ virBufferAsprintf(buf, "<domain name='%s'/>\n",
def->domain);
- if (virNetworkDNSDefFormat(&buf, def->dns) < 0)
+ if (virNetworkDNSDefFormat(buf, def->dns) < 0)
goto error;
- if (virNetDevVlanFormat(&def->vlan, &buf) < 0)
+ if (virNetDevVlanFormat(&def->vlan, buf) < 0)
goto error;
- if (virNetDevBandwidthFormat(def->bandwidth, &buf) < 0)
+ if (virNetDevBandwidthFormat(def->bandwidth, buf) < 0)
goto error;
for (ii = 0; ii < def->nips; ii++) {
- if (virNetworkIpDefFormat(&buf, &def->ips[ii]) < 0)
+ if (virNetworkIpDefFormat(buf, &def->ips[ii]) < 0)
goto error;
}
- if (virNetDevVPortProfileFormat(def->virtPortProfile, &buf) < 0)
+ if (virNetDevVPortProfileFormat(def->virtPortProfile, buf) < 0)
goto error;
for (ii = 0; ii < def->nPortGroups; ii++)
- if (virPortGroupDefFormat(&buf, &def->portGroups[ii]) < 0)
+ if (virPortGroupDefFormat(buf, &def->portGroups[ii]) < 0)
goto error;
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</network>\n");
+
+ return 0;
+
+error:
+ return -1;
+}
+
+char *
+virNetworkDefFormat(virNetworkDefPtr def,
+ unsigned int flags)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+ if (virNetworkDefFormatInternal(&buf, def, flags) < 0)
+ goto error;
+
+ if (virBufferError(&buf))
+ goto no_memory;
+
+ return virBufferContentAndReset(&buf);
+
+no_memory:
+ virReportOOMError();
+error:
+ virBufferFreeAndReset(&buf);
+ return NULL;
+}
+
+static char *
+virNetworkObjFormat(virNetworkObjPtr net,
+ unsigned int flags)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ char *class_id = virBitmapFormat(net->class_id);
+
+ if (!class_id)
+ goto no_memory;
+
+ virBufferAddLit(&buf, "<networkstatus>\n");
+ virBufferAsprintf(&buf, " <class_id bitmap='%s'/>\n",
class_id);
+ virBufferAsprintf(&buf, " <floor sum='%llu'/>\n",
net->floor_sum);
+ VIR_FREE(class_id);
+
+ virBufferAdjustIndent(&buf, 2);
+ if (virNetworkDefFormatInternal(&buf, net->def, flags) < 0)
+ goto error;
+
virBufferAdjustIndent(&buf, -2);
- virBufferAddLit(&buf, "</network>\n");
+ virBufferAddLit(&buf, "</networkstatus>");
if (virBufferError(&buf))
goto no_memory;
return virBufferContentAndReset(&buf);
- no_memory:
+no_memory:
virReportOOMError();
- error:
+error:
virBufferFreeAndReset(&buf);
return NULL;
}
@@ -2079,9 +2203,10 @@ int virNetworkSaveStatus(const char *statusDir,
virNetworkObjPtr network)
{
int ret = -1;
+ int flags = 0;
char *xml;
- if (!(xml = virNetworkDefFormat(network->def, 0)))
+ if (!(xml = virNetworkObjFormat(network, flags)))
goto cleanup;
if (virNetworkSaveXML(statusDir, network->def, xml))
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 364372d..519f73d 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -276,6 +276,8 @@ virNetworkDefPtr virNetworkDefParseString(const char *xmlStr);
virNetworkDefPtr virNetworkDefParseFile(const char *filename);
virNetworkDefPtr virNetworkDefParseNode(xmlDocPtr xml,
xmlNodePtr root);
+int virNetworkObjUpdateParseFile(const char *filename,
+ virNetworkObjPtr net);
char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6564676..ab44642 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -873,6 +873,7 @@ virNetworkObjSetDefTransient;
virNetworkObjUnlock;
virNetworkObjUnsetDefTransient;
virNetworkObjUpdate;
+virNetworkObjUpdateParseFile;
virNetworkRemoveInactive;
virNetworkSaveConfig;
virNetworkSaveStatus;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 0bee453..cad2192 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -242,7 +242,6 @@ networkFindActiveConfigs(struct network_driver *driver) {
for (i = 0 ; i < driver->networks.count ; i++) {
virNetworkObjPtr obj = driver->networks.objs[i];
- virNetworkDefPtr tmp;
char *config;
virNetworkObjLock(obj);
@@ -260,12 +259,10 @@ networkFindActiveConfigs(struct network_driver *driver) {
}
/* Try and load the live config */
- tmp = virNetworkDefParseFile(config);
+ if (virNetworkObjUpdateParseFile(config, obj) < 0)
+ VIR_WARN("Unable to update config of '%s' network",
+ obj->def->name);
VIR_FREE(config);
- if (tmp) {
- obj->newDef = obj->def;
- obj->def = tmp;
- }
/* If bridge exists, then mark it active */
if (obj->def->bridge &&
@@ -4425,6 +4422,14 @@ networkPlugBandwidth(virNetworkObjPtr net,
iface->data.network.actual->class_id = class_id;
/* update sum of 'floor'-s of attached NICs */
net->floor_sum += iface->bandwidth->in->floor;
+ /* update status file */
+ if (virNetworkSaveStatus(NETWORK_STATE_DIR, net) < 0) {
+ ignore_value(virBitmapClearBit(net->class_id, class_id));
+ net->floor_sum -= iface->bandwidth->in->floor;
+ iface->data.network.actual->class_id = 0;
+ ignore_value(virNetDevBandwidthUnplug(net->def->bridge, class_id));
+ goto cleanup;
+ }
/* update rate for non guaranteed NICs */
new_rate -= net->floor_sum;
if (virNetDevBandwidthUpdateRate(net->def->bridge, "1:2",
@@ -4459,6 +4464,16 @@ networkUnplugBandwidth(virNetworkObjPtr net,
goto cleanup;
/* update sum of 'floor'-s of attached NICs */
net->floor_sum -= iface->bandwidth->in->floor;
+ /* return class ID */
+ ignore_value(virBitmapClearBit(net->class_id,
+ iface->data.network.actual->class_id));
+ /* update status file */
+ if (virNetworkSaveStatus(NETWORK_STATE_DIR, net) < 0) {
+ net->floor_sum += iface->bandwidth->in->floor;
+ ignore_value(virBitmapSetBit(net->class_id,
+ iface->data.network.actual->class_id));
+ goto cleanup;
+ }
/* update rate for non guaranteed NICs */
new_rate -= net->floor_sum;
if (virNetDevBandwidthUpdateRate(net->def->bridge, "1:2",
--
1.7.8.6