[libvirt] [PATCHv3 19/27] conf: Add separate defaults addition and validation for XML parsing

Peter Krempa pkrempa at redhat.com
Mon Mar 11 15:06:30 UTC 2013


This patch adds instrumentation that will ultimately allow to split out
filling of defaults and input validation from the XML parser to separate
functions.

With this patch, after the XML is parsed, a callback to the driver is
issued requesing to fill and validate driver specific details of the
configuration. This allows to use sensible defaults and checks on a per
driver basis at the time the XML is parsed.

Three callback pointers are exposed in the new virDomainXMLConf object:
* virDomainDeviceDefAdjustCallback - called for a single device parsed
                                     and for every single device in a
                                     domain config. A
                                     virDomainDeviceDefPtr is passed
                                     along with the domain definition
                                     and virCaps.
* virDomainDefAdjustCallback - called if a domain definition is parsed
                               device specific callbacks were called.
                               A virDomainDefPtr is passed along with
                               virCaps. There are two callbacks of this
                               kind, one called before the devices are
                               parsed and one after.

Errors may be reported in those callbacks resulting in a XML parsing
failure.

Additionally internal filler and checker functions are added that are
meant to be used forseparating the validation and defaults assignment
code from the parser function.
---

Notes:
    Version 3:
    - added support for opaque data for the callback

 src/conf/domain_conf.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++--
 src/conf/domain_conf.h |  19 ++++++++
 2 files changed, 136 insertions(+), 3 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 127629f..6766775 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -747,18 +747,26 @@ struct _virDomainXMLConf {

     /* XML namespace callbacks */
     virDomainXMLNamespace ns;
- };
-

+    /* Parser data adjust callbacks */
+    virDomainDefAdjustCallbacks adjust;
+ };

 static virClassPtr virDomainXMLConfClass;
+static void virDoaminXMLConfClassDispose(void *obj)
+{
+    virDomainXMLConfPtr xmlconf = obj;
+
+    if (xmlconf->adjust.privFree)
+        (xmlconf->adjust.privFree)(xmlconf->adjust.priv);
+}

 static int virDomainXMLConfOnceInit(void)
 {
     if (!(virDomainXMLConfClass = virClassNew(virClassForObject(),
                                               "virDomainXMLConf",
                                               sizeof(virDomainXMLConf),
-                                              NULL)))
+                                              virDoaminXMLConfClassDispose)))
         return -1;

     return 0;
@@ -2450,6 +2458,104 @@ int virDomainDeviceInfoIterate(virDomainDefPtr def,
 }


+static int
+virDomainDeviceDefAdjustInternal(virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED,
+                                 virDomainDefPtr def ATTRIBUTE_UNUSED,
+                                 virCapsPtr caps ATTRIBUTE_UNUSED)
+{
+    /* not in use yet */
+    return 0;
+}
+
+
+static int
+virDomainDefAdjustInternal(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                           virCapsPtr caps ATTRIBUTE_UNUSED)
+{
+    /* not in use yet */
+    return 0;
+}
+
+
+static int
+virDomainDeviceDefAdjust(virDomainXMLConfPtr xmlconf,
+                         virDomainDeviceDefPtr dev,
+                         virDomainDefPtr def,
+                         virCapsPtr caps)
+{
+    int ret;
+
+    if ((ret = virDomainDeviceDefAdjustInternal(dev, def, caps)) < 0)
+        return ret;
+
+    if (xmlconf && xmlconf->adjust.devices) {
+        if ((ret = xmlconf->adjust.devices(dev, def, caps,
+                                           xmlconf->adjust.priv)) < 0)
+            return ret;
+    }
+
+    return 0;
+}
+
+
+struct virDomainDefAdjustDeviceIteratorData {
+    virCapsPtr caps;
+    virDomainDefPtr def;
+    virDomainXMLConfPtr xmlconf;
+};
+
+
+static int
+virDomainDefAdjustDeviceIterator(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                                 virDomainDeviceDefPtr dev,
+                                 virDomainDeviceInfoPtr info ATTRIBUTE_UNUSED,
+                                 void *opaque)
+{
+    struct virDomainDefAdjustDeviceIteratorData *data = opaque;
+    return virDomainDeviceDefAdjust(data->xmlconf, dev, data->def, data->caps);
+}
+
+
+static int
+virDomainDefAdjust(virDomainXMLConfPtr xmlconf,
+                   virDomainDefPtr def,
+                   virCapsPtr caps)
+{
+    int ret;
+    struct virDomainDefAdjustDeviceIteratorData data = {
+        .caps = caps,
+        .def = def,
+        .xmlconf = xmlconf,
+    };
+
+    /* first the global changes */
+    if ((ret = virDomainDefAdjustInternal(def, caps)) < 0)
+        return ret;
+
+    /* then call the before-devices callback */
+    if (xmlconf && xmlconf->adjust.domainBeforeDevices) {
+        if ((ret = xmlconf->adjust.domainBeforeDevices(def, caps,
+                                                       xmlconf->adjust.priv)) < 0)
+            return ret;
+    }
+
+    /* iterate the devices */
+    if ((ret = virDomainDeviceInfoIterate(def,
+                                          virDomainDefAdjustDeviceIterator,
+                                          &data)) < 0)
+        return ret;
+
+    /* call the after-device callback */
+    if (xmlconf && xmlconf->adjust.domainAfterDevices) {
+        if ((ret = xmlconf->adjust.domainAfterDevices(def, caps,
+                                                      xmlconf->adjust.priv)) < 0)
+            return ret;
+    }
+
+    return 0;
+}
+
+
 void virDomainDefClearPCIAddresses(virDomainDefPtr def)
 {
     virDomainDeviceInfoIterate(def, virDomainDeviceInfoClearPCIAddress, NULL);
@@ -8361,6 +8467,10 @@ virDomainDeviceDefParse(virCapsPtr caps,
         goto error;
     }

+    /* callback to fill driver specific device aspects */
+    if (virDomainDeviceDefAdjust(xmlconf, dev, def,  caps) < 0)
+        goto error;
+
 cleanup:
     xmlFreeDoc(xml);
     xmlXPathFreeContext(ctxt);
@@ -10882,6 +10992,10 @@ virDomainDefParseXML(virCapsPtr caps,
     if (virDomainDefAddImplicitControllers(def) < 0)
         goto error;

+    /* callback to fill driver specific domain aspects */
+    if (virDomainDefAdjust(xmlconf, def, caps) < 0)
+        goto error;
+
     virBitmapFree(bootMap);

     return def;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 8b17f1e..98a5c37 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1937,6 +1937,25 @@ typedef void (*virDomainXMLPrivateDataFreeFunc)(void *);
 typedef int (*virDomainXMLPrivateDataFormatFunc)(virBufferPtr, void *);
 typedef int (*virDomainXMLPrivateDataParseFunc)(xmlXPathContextPtr, void *);

+typedef int (*virDomainDefAdjustCallback)(virDomainDefPtr def,
+                                          virCapsPtr caps,
+                                          void *opaque);
+typedef int (*virDomainDeviceDefAdjustCallback)(virDomainDeviceDefPtr dev,
+                                               virDomainDefPtr def,
+                                               virCapsPtr caps,
+                                               void *opaque);
+
+typedef struct _virDomainDefAdjustCallbacks virDomainDefAdjustCallbacks;
+typedef virDomainDefAdjustCallbacks *virDomainDefAdjustCallbacksPtr;
+struct _virDomainDefAdjustCallbacks {
+    virDomainDefAdjustCallback domainBeforeDevices;
+    virDomainDeviceDefAdjustCallback devices;
+    virDomainDefAdjustCallback domainAfterDevices;
+
+    void *priv;
+    virFreeCallback privFree;
+};
+
 typedef struct _virDomainXMLPrivateDataCallbacks virDomainXMLPrivateDataCallbacks;
 typedef virDomainXMLPrivateDataCallbacks *virDomainXMLPrivateDataCallbacksPtr;
 struct _virDomainXMLPrivateDataCallbacks {
-- 
1.8.1.5




More information about the libvir-list mailing list