[libvirt] [PATCH v3 7/8] network: Create real network status files
Laine Stump
laine at laine.org
Tue Dec 11 16:38:15 UTC 2012
On 12/11/2012 11:09 AM, Michal Privoznik wrote:
> 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",
ACK.
More information about the libvir-list
mailing list