}
+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,
virDomainXMLOptionPtr xmlopt,
void *parseOpaque)
{
- int ret;
+ int ret = -1;
bool localParseOpaque = false;
struct virDomainDefPostParseDeviceIteratorData data = {
.caps = caps,
.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 &&
xmlopt->config.priv,
&data.parseOpaque);
- if (ret < 0)
- return ret;
+ if (virDomainDefPostParseCheckFailure(def, parseFlags, ret) < 0)
+ goto cleanup;
localParseOpaque = true;
}
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;
ret = xmlopt->config.assignAddressesCallback(def, caps, parseFlags,
xmlopt->config.priv,
data.parseOpaque);
- if (ret < 0)
+ if (virDomainDefPostParseCheckFailure(def, parseFlags, ret) < 0)
goto cleanup;
}
if (localParseOpaque && xmlopt->config.domainPostParseDataFree)
xmlopt->config.domainPostParseDataFree(data.parseOpaque);
+ if (ret == 1)
+ ret = -1;
+
return ret;
}
/* 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 */
};
* 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,
* 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 {
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)
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);