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: