[libvirt] [PATCH 07/12] conf: add infrastructure for tolerating certain post parse callback failures

Peter Krempa pkrempa at redhat.com
Wed Aug 16 14:57:56 UTC 2017


Some failures of the post parse callback can be tolerated. This is
specifically desired when loading the configs of existing VMs. In such
case the post parse callback should not really be modifying anything
in the definition.

This patch adds a parse flag VIR_DOMAIN_DEF_PARSE_ALLOW_POST_PARSE_FAIL
which will allow the callbacks to report non-fatal failures by returning
a positive return value. In such case the field 'postParseFailed' in the
domain definition is set to true, to notify the drivers that the
callback failed and possibly needs to be re-run.
---
 src/conf/domain_conf.c      | 47 +++++++++++++++++++++++++++++++++------------
 src/conf/domain_conf.h      | 16 ++++++++++++++-
 src/conf/virdomainobjlist.c |  6 ++++--
 3 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f94317e52..fdac9a443 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4836,6 +4836,23 @@ virDomainDefPostParseInternal(virDomainDefPtr def,
 }


+static int
+virDomainDefPostParseCheckFailure(virDomainDefPtr def,
+                                  unsigned int parseFlags,
+                                  int ret)
+{
+    if (ret <= 0)
+        return ret;
+
+    if (!(parseFlags & VIR_DOMAIN_DEF_PARSE_ALLOW_POST_PARSE_FAIL))
+        return -1;
+
+    virResetLastError();
+    def->postParseFailed = true;
+    return 0;
+}
+
+
 int
 virDomainDefPostParse(virDomainDefPtr def,
                       virCapsPtr caps,
@@ -4843,7 +4860,7 @@ virDomainDefPostParse(virDomainDefPtr def,
                       virDomainXMLOptionPtr xmlopt,
                       void *parseOpaque)
 {
-    int ret;
+    int ret = -1;
     bool localParseOpaque = false;
     struct virDomainDefPostParseDeviceIteratorData data = {
         .caps = caps,
@@ -4852,13 +4869,15 @@ virDomainDefPostParse(virDomainDefPtr def,
         .parseOpaque = parseOpaque,
     };

+    def->postParseFailed = false;
+
     /* call the basic post parse callback */
     if (xmlopt->config.domainPostParseBasicCallback) {
         ret = xmlopt->config.domainPostParseBasicCallback(def, caps,
                                                           xmlopt->config.priv);

-        if (ret < 0)
-            return ret;
+        if (virDomainDefPostParseCheckFailure(def, parseFlags, ret) < 0)
+            goto cleanup;
     }

     if (!data.parseOpaque &&
@@ -4867,8 +4886,8 @@ virDomainDefPostParse(virDomainDefPtr def,
                                                       xmlopt->config.priv,
                                                       &data.parseOpaque);

-        if (ret < 0)
-            return ret;
+        if (virDomainDefPostParseCheckFailure(def, parseFlags, ret) < 0)
+            goto cleanup;
         localParseOpaque = true;
     }

@@ -4882,17 +4901,18 @@ virDomainDefPostParse(virDomainDefPtr def,
         ret = xmlopt->config.domainPostParseCallback(def, caps, parseFlags,
                                                      xmlopt->config.priv,
                                                      data.parseOpaque);
-        if (ret < 0)
+        if (virDomainDefPostParseCheckFailure(def, parseFlags, ret) < 0)
             goto cleanup;
     }

     /* iterate the devices */
-    if ((ret = virDomainDeviceInfoIterateInternal(def,
-                                                  virDomainDefPostParseDeviceIterator,
-                                                  true,
-                                                  &data)) < 0)
-        goto cleanup;
+    ret = virDomainDeviceInfoIterateInternal(def,
+                                             virDomainDefPostParseDeviceIterator,
+                                             true,
+                                             &data);

+    if (virDomainDefPostParseCheckFailure(def, parseFlags, ret) < 0)
+        goto cleanup;

     if ((ret = virDomainDefPostParseInternal(def, &data)) < 0)
         goto cleanup;
@@ -4901,7 +4921,7 @@ virDomainDefPostParse(virDomainDefPtr def,
         ret = xmlopt->config.assignAddressesCallback(def, caps, parseFlags,
                                                      xmlopt->config.priv,
                                                      data.parseOpaque);
-        if (ret < 0)
+        if (virDomainDefPostParseCheckFailure(def, parseFlags, ret) < 0)
             goto cleanup;
     }

@@ -4914,6 +4934,9 @@ virDomainDefPostParse(virDomainDefPtr def,
     if (localParseOpaque && xmlopt->config.domainPostParseDataFree)
         xmlopt->config.domainPostParseDataFree(data.parseOpaque);

+    if (ret == 1)
+        ret = -1;
+
     return ret;
 }

diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index be7298137..13bdd2bc4 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2411,6 +2411,12 @@ struct _virDomainDef {

     /* Application-specific custom metadata */
     xmlNodePtr metadata;
+
+    /* internal fields */
+    bool postParseFailed; /* set to true if one of the custom post parse
+                             callbacks failed for a non-critical reason
+                             (was not able to fill in some data) and thus
+                             should be re-run before starting */
 };


@@ -2510,7 +2516,10 @@ typedef int (*virDomainDefPostParseBasicCallback)(virDomainDefPtr def,
  * overall domain defaults.
  * @parseOpaque is opaque data passed by virDomainDefParse* caller,
  * @opaque is opaque data set by driver (usually pointer to driver
- * private data). */
+ * private data). Non-fatal failures should be reported by returning 1. In
+ * cases when that is allowed, such failure is translated to a success return
+ * value and the failure is noted in def->postParseFailed. Drivers should then
+ * re-run the post parse callback when attempting to use such definition. */
 typedef int (*virDomainDefPostParseCallback)(virDomainDefPtr def,
                                              virCapsPtr caps,
                                              unsigned int parseFlags,
@@ -2825,6 +2834,11 @@ typedef enum {
      * that would break ABI otherwise.  This should be used only if it's safe
      * to do such change. */
     VIR_DOMAIN_DEF_PARSE_ABI_UPDATE_MIGRATION = 1 << 12,
+    /* Allows to ignore certain failures in the post parse callbacks, which
+     * may happen due to missing packages and can be fixed by re-running the
+     * post parse callbacks before starting. Failure of the post parse callback
+     * is recorded as def->postParseFail */
+    VIR_DOMAIN_DEF_PARSE_ALLOW_POST_PARSE_FAIL = 1 << 13,
 } virDomainDefParseFlags;

 typedef enum {
diff --git a/src/conf/virdomainobjlist.c b/src/conf/virdomainobjlist.c
index a8b3f4124..b9f78c572 100644
--- a/src/conf/virdomainobjlist.c
+++ b/src/conf/virdomainobjlist.c
@@ -465,7 +465,8 @@ virDomainObjListLoadConfig(virDomainObjListPtr doms,
     if (!(def = virDomainDefParseFile(configFile, caps, xmlopt, NULL,
                                       VIR_DOMAIN_DEF_PARSE_INACTIVE |
                                       VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS |
-                                      VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
+                                      VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE |
+                                      VIR_DOMAIN_DEF_PARSE_ALLOW_POST_PARSE_FAIL)))
         goto error;

     if ((autostartLink = virDomainConfigFile(autostartDir, name)) == NULL)
@@ -516,7 +517,8 @@ virDomainObjListLoadStatus(virDomainObjListPtr doms,
                                       VIR_DOMAIN_DEF_PARSE_ACTUAL_NET |
                                       VIR_DOMAIN_DEF_PARSE_PCI_ORIG_STATES |
                                       VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS |
-                                      VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
+                                      VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE |
+                                      VIR_DOMAIN_DEF_PARSE_ALLOW_POST_PARSE_FAIL)))
         goto error;

     virUUIDFormat(obj->def->uuid, uuidstr);
-- 
2.14.0




More information about the libvir-list mailing list