]> xenbits.xensource.com Git - libvirt.git/commitdiff
conf: add infrastructure for tolerating certain post parse callback failures
authorPeter Krempa <pkrempa@redhat.com>
Tue, 15 Aug 2017 16:41:59 +0000 (18:41 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Fri, 18 Aug 2017 13:07:44 +0000 (15:07 +0200)
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
src/conf/domain_conf.h
src/conf/virdomainobjlist.c

index d13747d06bfa794eab40c531319e230164555f57..3bef5bed3b4ae1fc91f6ea887d124be597e8daaf 100644 (file)
@@ -4839,6 +4839,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,
@@ -4846,7 +4863,7 @@ virDomainDefPostParse(virDomainDefPtr def,
                       virDomainXMLOptionPtr xmlopt,
                       void *parseOpaque)
 {
-    int ret;
+    int ret = -1;
     bool localParseOpaque = false;
     struct virDomainDefPostParseDeviceIteratorData data = {
         .caps = caps,
@@ -4855,13 +4872,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 &&
@@ -4870,8 +4889,8 @@ virDomainDefPostParse(virDomainDefPtr def,
                                                       xmlopt->config.priv,
                                                       &data.parseOpaque);
 
-        if (ret < 0)
-            return ret;
+        if (virDomainDefPostParseCheckFailure(def, parseFlags, ret) < 0)
+            goto cleanup;
         localParseOpaque = true;
     }
 
@@ -4885,17 +4904,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;
@@ -4904,7 +4924,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;
     }
 
@@ -4917,6 +4937,9 @@ virDomainDefPostParse(virDomainDefPtr def,
     if (localParseOpaque && xmlopt->config.domainPostParseDataFree)
         xmlopt->config.domainPostParseDataFree(data.parseOpaque);
 
+    if (ret == 1)
+        ret = -1;
+
     return ret;
 }
 
index 956996fdd71051bf463b0f8d4588c8424ce1adb6..1f1dc1de0112fd3c4aae3bc7e0a8f6bd5bdf8e38 100644 (file)
@@ -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 {
index a8b3f41243f217fcc364ddf5f343e18e35bd175b..b9f78c572794fd02e22ec9fec3628791d21ba887 100644 (file)
@@ -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);