diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index d13747d06b..3bef5bed3b 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -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; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 956996fdd7..1f1dc1de01 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 a8b3f41243..b9f78c5727 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);