[libvirt] [PATCH 10/16] conf: Add separate defaults addition and validation for XML parsing

Peter Krempa pkrempa at redhat.com
Wed Feb 20 17:06:44 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.

Two callback pointers are exposed in the virCaps object:
* virDriverDeviceDefCallback - called for a single device parsed and for
                               every single device in a domain config.
                               A virDomainDeviceDefPtr is passed.
* virDriverDomainDefCallback - called if a domain definition is parsed
                               device specific callbacks were called.
                               A virDomainDefPtr is passed.

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

Additionally two internal filler functions are added:
virDomainDeviceDefUpdateDefaultsInternal and
virDomainDefUpdateDefaultsInternal that are meant to be used for
separating the validation and defaults assignment code from the parser
function.
---
 src/conf/capabilities.h |  6 +++++
 src/conf/domain_conf.c  | 72 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+)

diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
index cc01765..56cd09f 100644
--- a/src/conf/capabilities.h
+++ b/src/conf/capabilities.h
@@ -171,6 +171,12 @@ struct _virCaps {
     bool hasWideScsiBus;
     const char *defaultInitPath;

+
+    /* these callbacks are called after a XML definition of a device or domain
+     * is parsed. They are meant to validate and fill driver-specific values. */
+    int (*virDriverDeviceDefCallback)(void *); /* virDomainDeviceDefPtr is passed */
+    int (*virDriverDomainDefCallback)(void *); /* virDomainDefPtr is passed */
+
     virDomainXMLNamespace ns;
 };

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 421492f..d881983 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2353,6 +2353,70 @@ int virDomainDeviceInfoIterate(virDomainDefPtr def,
 }


+static int
+virDomainDeviceDefUpdateDefaultsInternal(virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED)
+{
+    /* not in use yet */
+    return 0;
+}
+
+
+static int
+virDomainDefUpdateDefaultsInternal(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                                   virCapsPtr caps ATTRIBUTE_UNUSED)
+{
+    /* not in use yet */
+    return 0;
+}
+
+
+static int
+virDomainDeviceDefUpdateDefaults(virDomainDeviceDefPtr dev,
+                                 virCapsPtr caps)
+{
+    int ret;
+    /* at first call the driver callback to update the device */
+    if (caps->virDriverDeviceDefCallback &&
+        (ret = (caps->virDriverDeviceDefCallback)(dev)) < 0)
+        return ret;
+
+    /* then fill the parse defaults and do the checks */
+    return virDomainDeviceDefUpdateDefaultsInternal(dev);
+}
+
+
+static int
+virDomainDefUpdateDefaultsDeviceIterator(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                                         virDomainDeviceDefPtr dev,
+                                         virDomainDeviceInfoPtr info ATTRIBUTE_UNUSED,
+                                         void *opaque)
+{
+    virCapsPtr caps = opaque;
+    return virDomainDeviceDefUpdateDefaults(dev, caps);
+}
+
+
+static int
+virDomainDefUpdateDefaults(virDomainDefPtr def,
+                           virCapsPtr caps)
+{
+    int ret;
+
+    /* at first update all the devices , unfortunately they are separate */
+    if ((ret = virDomainDeviceInfoIterate(def,
+                                          virDomainDefUpdateDefaultsDeviceIterator,
+                                          caps)) < 0)
+        return ret;
+
+    /* call the driver callback to update the rest of the definition */
+    if (caps->virDriverDomainDefCallback &&
+        (ret = (caps->virDriverDomainDefCallback)(def)) < 0)
+        return ret;
+
+    return virDomainDefUpdateDefaultsInternal(def, caps);
+}
+
+
 void virDomainDefClearPCIAddresses(virDomainDefPtr def)
 {
     virDomainDeviceInfoIterate(def, virDomainDeviceInfoClearPCIAddress, NULL);
@@ -8224,6 +8288,10 @@ virDomainDeviceDefParse(virCapsPtr caps,
         goto error;
     }

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

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

     return def;
-- 
1.8.1.1




More information about the libvir-list mailing list