network: Create real network status files

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.
This commit is contained in:
Michal Privoznik 2012-11-18 16:59:21 +01:00
parent 07d1b6b5b1
commit ae757743dc
4 changed files with 189 additions and 46 deletions

View File

@ -1825,6 +1825,79 @@ cleanup:
return def; 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 static int
virNetworkDNSDefFormat(virBufferPtr buf, virNetworkDNSDefFormat(virBufferPtr buf,
virNetworkDNSDefPtr def) virNetworkDNSDefPtr def)
@ -2003,26 +2076,28 @@ virPortGroupDefFormat(virBufferPtr buf,
return 0; 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; unsigned char *uuid;
char uuidstr[VIR_UUID_STRING_BUFLEN]; char uuidstr[VIR_UUID_STRING_BUFLEN];
int ii; int ii;
virBufferAddLit(&buf, "<network"); virBufferAddLit(buf, "<network");
if (!(flags & VIR_NETWORK_XML_INACTIVE) && (def->connections > 0)) { if (!(flags & VIR_NETWORK_XML_INACTIVE) && (def->connections > 0)) {
virBufferAsprintf(&buf, " connections='%d'", def->connections); virBufferAsprintf(buf, " connections='%d'", def->connections);
} }
if (def->ipv6nogw) if (def->ipv6nogw)
virBufferAddLit(&buf, " ipv6='yes'"); virBufferAddLit(buf, " ipv6='yes'");
virBufferAddLit(&buf, ">\n"); virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(&buf, 2); virBufferAdjustIndent(buf, 2);
virBufferEscapeString(&buf, "<name>%s</name>\n", def->name); virBufferEscapeString(buf, "<name>%s</name>\n", def->name);
uuid = def->uuid; uuid = def->uuid;
virUUIDFormat(uuid, uuidstr); virUUIDFormat(uuid, uuidstr);
virBufferAsprintf(&buf, "<uuid>%s</uuid>\n", uuidstr); virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuidstr);
if (def->forward.type != VIR_NETWORK_FORWARD_NONE) { if (def->forward.type != VIR_NETWORK_FORWARD_NONE) {
const char *dev = NULL; const char *dev = NULL;
@ -2036,40 +2111,40 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
def->forward.type, def->name); def->forward.type, def->name);
goto error; goto error;
} }
virBufferAddLit(&buf, "<forward"); virBufferAddLit(buf, "<forward");
virBufferEscapeString(&buf, " dev='%s'", dev); virBufferEscapeString(buf, " dev='%s'", dev);
virBufferAsprintf(&buf, " mode='%s'", mode); virBufferAsprintf(buf, " mode='%s'", mode);
if (def->forward.type == VIR_NETWORK_FORWARD_HOSTDEV) { if (def->forward.type == VIR_NETWORK_FORWARD_HOSTDEV) {
if (def->forward.managed) if (def->forward.managed)
virBufferAddLit(&buf, " managed='yes'"); virBufferAddLit(buf, " managed='yes'");
else else
virBufferAddLit(&buf, " managed='no'"); virBufferAddLit(buf, " managed='no'");
} }
virBufferAsprintf(&buf, "%s>\n", virBufferAsprintf(buf, "%s>\n",
(def->forward.nifs || def->forward.npfs) ? "" : "/"); (def->forward.nifs || def->forward.npfs) ? "" : "/");
virBufferAdjustIndent(&buf, 2); virBufferAdjustIndent(buf, 2);
/* For now, hard-coded to at most 1 forward.pfs */ /* For now, hard-coded to at most 1 forward.pfs */
if (def->forward.npfs) if (def->forward.npfs)
virBufferEscapeString(&buf, "<pf dev='%s'/>\n", virBufferEscapeString(buf, "<pf dev='%s'/>\n",
def->forward.pfs[0].dev); def->forward.pfs[0].dev);
if (def->forward.nifs && if (def->forward.nifs &&
(!def->forward.npfs || !(flags & VIR_NETWORK_XML_INACTIVE))) { (!def->forward.npfs || !(flags & VIR_NETWORK_XML_INACTIVE))) {
for (ii = 0; ii < def->forward.nifs; ii++) { for (ii = 0; ii < def->forward.nifs; ii++) {
if (def->forward.type != VIR_NETWORK_FORWARD_HOSTDEV) { if (def->forward.type != VIR_NETWORK_FORWARD_HOSTDEV) {
virBufferEscapeString(&buf, "<interface dev='%s'", virBufferEscapeString(buf, "<interface dev='%s'",
def->forward.ifs[ii].device.dev); def->forward.ifs[ii].device.dev);
if (!(flags & VIR_NETWORK_XML_INACTIVE) && if (!(flags & VIR_NETWORK_XML_INACTIVE) &&
(def->forward.ifs[ii].connections > 0)) { (def->forward.ifs[ii].connections > 0)) {
virBufferAsprintf(&buf, " connections='%d'", virBufferAsprintf(buf, " connections='%d'",
def->forward.ifs[ii].connections); def->forward.ifs[ii].connections);
} }
virBufferAddLit(&buf, "/>\n"); virBufferAddLit(buf, "/>\n");
} }
else { else {
if (def->forward.ifs[ii].type == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI) { if (def->forward.ifs[ii].type == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI) {
if (virDevicePCIAddressFormat(&buf, if (virDevicePCIAddressFormat(buf,
def->forward.ifs[ii].device.pci, def->forward.ifs[ii].device.pci,
true) < 0) true) < 0)
goto error; goto error;
@ -2077,67 +2152,116 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
} }
} }
} }
virBufferAdjustIndent(&buf, -2); virBufferAdjustIndent(buf, -2);
if (def->forward.npfs || def->forward.nifs) if (def->forward.npfs || def->forward.nifs)
virBufferAddLit(&buf, "</forward>\n"); virBufferAddLit(buf, "</forward>\n");
} }
if (def->forward.type == VIR_NETWORK_FORWARD_NONE || if (def->forward.type == VIR_NETWORK_FORWARD_NONE ||
def->forward.type == VIR_NETWORK_FORWARD_NAT || def->forward.type == VIR_NETWORK_FORWARD_NAT ||
def->forward.type == VIR_NETWORK_FORWARD_ROUTE) { def->forward.type == VIR_NETWORK_FORWARD_ROUTE) {
virBufferAddLit(&buf, "<bridge"); virBufferAddLit(buf, "<bridge");
if (def->bridge) if (def->bridge)
virBufferEscapeString(&buf, " name='%s'", def->bridge); virBufferEscapeString(buf, " name='%s'", def->bridge);
virBufferAsprintf(&buf, " stp='%s' delay='%ld' />\n", virBufferAsprintf(buf, " stp='%s' delay='%ld' />\n",
def->stp ? "on" : "off", def->stp ? "on" : "off",
def->delay); def->delay);
} else if (def->forward.type == VIR_NETWORK_FORWARD_BRIDGE && } else if (def->forward.type == VIR_NETWORK_FORWARD_BRIDGE &&
def->bridge) { def->bridge) {
virBufferEscapeString(&buf, "<bridge name='%s' />\n", def->bridge); virBufferEscapeString(buf, "<bridge name='%s' />\n", def->bridge);
} }
if (def->mac_specified) { if (def->mac_specified) {
char macaddr[VIR_MAC_STRING_BUFLEN]; char macaddr[VIR_MAC_STRING_BUFLEN];
virMacAddrFormat(&def->mac, macaddr); virMacAddrFormat(&def->mac, macaddr);
virBufferAsprintf(&buf, "<mac address='%s'/>\n", macaddr); virBufferAsprintf(buf, "<mac address='%s'/>\n", macaddr);
} }
if (def->domain) 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; goto error;
if (virNetDevVlanFormat(&def->vlan, &buf) < 0) if (virNetDevVlanFormat(&def->vlan, buf) < 0)
goto error; goto error;
if (virNetDevBandwidthFormat(def->bandwidth, &buf) < 0) if (virNetDevBandwidthFormat(def->bandwidth, buf) < 0)
goto error; goto error;
for (ii = 0; ii < def->nips; ii++) { for (ii = 0; ii < def->nips; ii++) {
if (virNetworkIpDefFormat(&buf, &def->ips[ii]) < 0) if (virNetworkIpDefFormat(buf, &def->ips[ii]) < 0)
goto error; goto error;
} }
if (virNetDevVPortProfileFormat(def->virtPortProfile, &buf) < 0) if (virNetDevVPortProfileFormat(def->virtPortProfile, buf) < 0)
goto error; goto error;
for (ii = 0; ii < def->nPortGroups; ii++) for (ii = 0; ii < def->nPortGroups; ii++)
if (virPortGroupDefFormat(&buf, &def->portGroups[ii]) < 0) if (virPortGroupDefFormat(buf, &def->portGroups[ii]) < 0)
goto error; goto error;
virBufferAdjustIndent(&buf, -2); virBufferAdjustIndent(buf, -2);
virBufferAddLit(&buf, "</network>\n"); 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)) if (virBufferError(&buf))
goto no_memory; goto no_memory;
return virBufferContentAndReset(&buf); return virBufferContentAndReset(&buf);
no_memory: no_memory:
virReportOOMError(); virReportOOMError();
error: 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, "</networkstatus>");
if (virBufferError(&buf))
goto no_memory;
return virBufferContentAndReset(&buf);
no_memory:
virReportOOMError();
error:
virBufferFreeAndReset(&buf); virBufferFreeAndReset(&buf);
return NULL; return NULL;
} }
@ -2209,9 +2333,10 @@ int virNetworkSaveStatus(const char *statusDir,
virNetworkObjPtr network) virNetworkObjPtr network)
{ {
int ret = -1; int ret = -1;
int flags = 0;
char *xml; char *xml;
if (!(xml = virNetworkDefFormat(network->def, 0))) if (!(xml = virNetworkObjFormat(network, flags)))
goto cleanup; goto cleanup;
if (virNetworkSaveXML(statusDir, network->def, xml)) if (virNetworkSaveXML(statusDir, network->def, xml))

View File

@ -282,6 +282,8 @@ virNetworkDefPtr virNetworkDefParseString(const char *xmlStr);
virNetworkDefPtr virNetworkDefParseFile(const char *filename); virNetworkDefPtr virNetworkDefParseFile(const char *filename);
virNetworkDefPtr virNetworkDefParseNode(xmlDocPtr xml, virNetworkDefPtr virNetworkDefParseNode(xmlDocPtr xml,
xmlNodePtr root); xmlNodePtr root);
int virNetworkObjUpdateParseFile(const char *filename,
virNetworkObjPtr net);
char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags); char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags);

View File

@ -875,6 +875,7 @@ virNetworkObjSetDefTransient;
virNetworkObjUnlock; virNetworkObjUnlock;
virNetworkObjUnsetDefTransient; virNetworkObjUnsetDefTransient;
virNetworkObjUpdate; virNetworkObjUpdate;
virNetworkObjUpdateParseFile;
virNetworkRemoveInactive; virNetworkRemoveInactive;
virNetworkSaveConfig; virNetworkSaveConfig;
virNetworkSaveStatus; virNetworkSaveStatus;

View File

@ -259,7 +259,6 @@ networkFindActiveConfigs(struct network_driver *driver) {
for (i = 0 ; i < driver->networks.count ; i++) { for (i = 0 ; i < driver->networks.count ; i++) {
virNetworkObjPtr obj = driver->networks.objs[i]; virNetworkObjPtr obj = driver->networks.objs[i];
virNetworkDefPtr tmp;
char *config; char *config;
virNetworkObjLock(obj); virNetworkObjLock(obj);
@ -277,12 +276,10 @@ networkFindActiveConfigs(struct network_driver *driver) {
} }
/* Try and load the live config */ /* 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); VIR_FREE(config);
if (tmp) {
obj->newDef = obj->def;
obj->def = tmp;
}
/* If bridge exists, then mark it active */ /* If bridge exists, then mark it active */
if (obj->def->bridge && if (obj->def->bridge &&
@ -4617,6 +4614,14 @@ networkPlugBandwidth(virNetworkObjPtr net,
iface->data.network.actual->class_id = class_id; iface->data.network.actual->class_id = class_id;
/* update sum of 'floor'-s of attached NICs */ /* update sum of 'floor'-s of attached NICs */
net->floor_sum += iface->bandwidth->in->floor; 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 */ /* update rate for non guaranteed NICs */
new_rate -= net->floor_sum; new_rate -= net->floor_sum;
if (virNetDevBandwidthUpdateRate(net->def->bridge, "1:2", if (virNetDevBandwidthUpdateRate(net->def->bridge, "1:2",
@ -4651,6 +4656,16 @@ networkUnplugBandwidth(virNetworkObjPtr net,
goto cleanup; goto cleanup;
/* update sum of 'floor'-s of attached NICs */ /* update sum of 'floor'-s of attached NICs */
net->floor_sum -= iface->bandwidth->in->floor; 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 */ /* update rate for non guaranteed NICs */
new_rate -= net->floor_sum; new_rate -= net->floor_sum;
if (virNetDevBandwidthUpdateRate(net->def->bridge, "1:2", if (virNetDevBandwidthUpdateRate(net->def->bridge, "1:2",