
On 11/19/2012 11:51 AM, Michal Privoznik wrote:
Interfaces keeps a class_id, which is an ID from which bridge part of QoS settings is derived. We need to store class_id in domain status file, so we can later pass it to virNetDevBandwidthUnplug.
Interesting use of alias to find the original interface matching the class_id. But we already have a "status-only" subelement in every type='network' interface, so it will be much simpler to just store it there (conveniently in the bandwidth object, as I suggested in an earlier patch). (if <actual> wasn't already saved within <interface>, I might have considered doing it this way, but that ship has already sailed.)
--- src/conf/domain_conf.c | 4 +- src/qemu/qemu_domain.c | 66 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 7 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index bf23b77..37a8875 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -10242,7 +10242,7 @@ static virDomainObjPtr virDomainObjParseXML(virCapsPtr caps, VIR_FREE(nodes);
if (caps->privateDataXMLParse && - ((caps->privateDataXMLParse)(ctxt, obj->privateData)) < 0) + ((caps->privateDataXMLParse)(ctxt, obj)) < 0) goto error;
return obj; @@ -14212,7 +14212,7 @@ static char *virDomainObjFormat(virCapsPtr caps, }
if (caps->privateDataXMLFormat && - ((caps->privateDataXMLFormat)(&buf, obj->privateData)) < 0) + ((caps->privateDataXMLFormat)(&buf, obj)) < 0) goto error;
virBufferAdjustIndent(&buf, 2); diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index e0d6951..5312946 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -258,9 +258,12 @@ static void qemuDomainObjPrivateFree(void *data)
static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data) { - qemuDomainObjPrivatePtr priv = data; + virDomainObjPtr vm = data; + qemuDomainObjPrivatePtr priv = vm->privateData; const char *monitorpath; enum qemuDomainJob job; + bool do_class_id = false; + int i;
/* priv->monitor_chr is set only for qemu */ if (priv->monConfig) { @@ -283,7 +286,6 @@ static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
if (priv->nvcpupids) { - int i; virBufferAddLit(buf, " <vcpus>\n"); for (i = 0 ; i < priv->nvcpupids ; i++) { virBufferAsprintf(buf, " <vcpu pid='%d'/>\n", priv->vcpupids[i]); @@ -292,7 +294,6 @@ static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data) }
if (priv->caps) { - int i; virBufferAddLit(buf, " <qemuCaps>\n"); for (i = 0 ; i < QEMU_CAPS_LAST ; i++) { if (qemuCapsGet(priv->caps, i)) { @@ -326,15 +327,36 @@ static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data) if (priv->fakeReboot) virBufferAsprintf(buf, " <fakereboot/>\n");
+ for (i = 0; i < vm->def->nnets; i++) { + if (vm->def->nets[i]->class_id) { + do_class_id = true; + break; + } + } + + if (do_class_id) { + virBufferAddLit(buf, " <class_id>\n"); + for (; i < vm->def->nnets; i++) { + virDomainNetDefPtr iface = vm->def->nets[i]; + if (iface->class_id) { + virBufferAsprintf(buf, " <interface alias='%s' " + "class_id='%u'/>\n", + iface->info.alias, iface->class_id); + } + } + virBufferAddLit(buf, " </class_id>\n"); + } + return 0; }
static int qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data) { - qemuDomainObjPrivatePtr priv = data; + virDomainObjPtr vm = data; + qemuDomainObjPrivatePtr priv = vm->privateData; char *monitorpath; char *tmp; - int n, i; + int n, i, ii; xmlNodePtr *nodes = NULL; qemuCapsPtr caps = NULL;
@@ -471,6 +493,40 @@ static int qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data)
priv->fakeReboot = virXPathBoolean("boolean(./fakereboot)", ctxt) == 1;
+ if ((n = virXPathNodeSet("./class_id/interface", ctxt, &nodes)) < 0) + goto error; + + for (i = 0; i < n; i++) { + char *alias = virXMLPropString(nodes[i], "alias"); + char *class_id = virXMLPropString(nodes[i], "class_id"); + virDomainNetDefPtr iface = NULL; + if (alias && class_id) { + for (ii = 0; ii < vm->def->nnets; ii++) { + if (STREQ(vm->def->nets[ii]->info.alias, alias)) { + iface = vm->def->nets[ii]; + break; + } + } + + if (!iface) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("No such interface '%s'"), + alias); + VIR_FREE(alias); + VIR_FREE(class_id); + goto error; + } + + if (virStrToLong_ui(class_id, NULL, 10, &iface->class_id) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Malformed class_id attribute: %s"), + class_id); + } + } + VIR_FREE(alias); + VIR_FREE(class_id); + } + return 0;
error: