[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