mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 03:12:22 +00:00
conf: Add infrastructure for adding configuration validation
Until now we weren't able to add checks that would reject configuration once accepted by the parser. This patch adds a new callback and infrastructure to add such checks. In this patch all the places where rejecting a now-invalid configuration wouldn't be a good idea are marked with a new parser flag.
This commit is contained in:
parent
998c9e34e6
commit
b394af162a
@ -4533,6 +4533,50 @@ virDomainDefPostParse(virDomainDefPtr def,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
virDomainDefValidateInternal(const virDomainDef *def ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virDomainDefValidate:
|
||||
* @def: domain definition
|
||||
* @caps: driver capabilities object
|
||||
* @parseFlags: virDomainDefParseFlags
|
||||
* @xmlopt: XML parser option object
|
||||
*
|
||||
* This validation function is designed to take checks of globally invalid
|
||||
* configurations that the parser needs to accept so that VMs don't vanish upon
|
||||
* daemon restart. Such definition can be rejected upon startup or define, where
|
||||
* this function shall be called.
|
||||
*
|
||||
* Returns 0 if domain definition is valid, -1 on error and reports an
|
||||
* appropriate message.
|
||||
*/
|
||||
int
|
||||
virDomainDefValidate(const virDomainDef *def,
|
||||
virCapsPtr caps,
|
||||
unsigned int parseFlags,
|
||||
virDomainXMLOptionPtr xmlopt)
|
||||
{
|
||||
/* validate configuration only in certain places */
|
||||
if (parseFlags & VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)
|
||||
return 0;
|
||||
|
||||
/* call the domain config callback */
|
||||
if (xmlopt->config.domainValidateCallback &&
|
||||
xmlopt->config.domainValidateCallback(def, caps, xmlopt->config.priv) < 0)
|
||||
return -1;
|
||||
|
||||
if (virDomainDefValidateInternal(def) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void virDomainDefClearPCIAddresses(virDomainDefPtr def)
|
||||
{
|
||||
virDomainDeviceInfoIterate(def, virDomainDeviceInfoClearPCIAddress, NULL);
|
||||
@ -16951,6 +16995,10 @@ virDomainDefParseXML(xmlDocPtr xml,
|
||||
if (virDomainDefPostParse(def, caps, flags, xmlopt) < 0)
|
||||
goto error;
|
||||
|
||||
/* valdiate configuration */
|
||||
if (virDomainDefValidate(def, caps, flags, xmlopt) < 0)
|
||||
goto error;
|
||||
|
||||
virHashFree(bootHash);
|
||||
|
||||
return def;
|
||||
@ -23729,7 +23777,8 @@ virDomainDefCopy(virDomainDefPtr src,
|
||||
char *xml;
|
||||
virDomainDefPtr ret;
|
||||
unsigned int format_flags = VIR_DOMAIN_DEF_FORMAT_SECURE;
|
||||
unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
|
||||
unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
|
||||
|
||||
if (migratable)
|
||||
format_flags |= VIR_DOMAIN_DEF_FORMAT_INACTIVE | VIR_DOMAIN_DEF_FORMAT_MIGRATABLE;
|
||||
|
@ -2361,6 +2361,12 @@ typedef int (*virDomainDefAssignAddressesCallback)(virDomainDef *def,
|
||||
unsigned int parseFlags,
|
||||
void *opaque);
|
||||
|
||||
/* Called in appropriate places where the domain conf parser can return failure
|
||||
* for configurations that were previously accepted. This shall not modify the
|
||||
* config. */
|
||||
typedef int (*virDomainDefValidateCallback)(const virDomainDef *def,
|
||||
virCapsPtr caps,
|
||||
void *opaque);
|
||||
|
||||
typedef struct _virDomainDefParserConfig virDomainDefParserConfig;
|
||||
typedef virDomainDefParserConfig *virDomainDefParserConfigPtr;
|
||||
@ -2370,6 +2376,9 @@ struct _virDomainDefParserConfig {
|
||||
virDomainDeviceDefPostParseCallback devicesPostParseCallback;
|
||||
virDomainDefAssignAddressesCallback assignAddressesCallback;
|
||||
|
||||
/* validation callbacks */
|
||||
virDomainDefValidateCallback domainValidateCallback;
|
||||
|
||||
/* private data for the callbacks */
|
||||
void *priv;
|
||||
virFreeCallback privFree;
|
||||
@ -2415,6 +2424,11 @@ virDomainDefPostParse(virDomainDefPtr def,
|
||||
unsigned int parseFlags,
|
||||
virDomainXMLOptionPtr xmlopt);
|
||||
|
||||
int virDomainDefValidate(const virDomainDef *def,
|
||||
virCapsPtr caps,
|
||||
unsigned int parseFlags,
|
||||
virDomainXMLOptionPtr xmlopt);
|
||||
|
||||
static inline bool
|
||||
virDomainObjIsActive(virDomainObjPtr dom)
|
||||
{
|
||||
@ -2580,6 +2594,8 @@ typedef enum {
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS = 1 << 8,
|
||||
/* allow updates in post parse callback that would break ABI otherwise */
|
||||
VIR_DOMAIN_DEF_PARSE_ABI_UPDATE = 1 << 9,
|
||||
/* skip definition validation checks meant to be executed on define time only */
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE = 1 << 10,
|
||||
} virDomainDefParseFlags;
|
||||
|
||||
typedef enum {
|
||||
|
@ -269,7 +269,8 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt,
|
||||
* clients will have to decide between best effort
|
||||
* initialization or outright failure. */
|
||||
if ((tmp = virXPathString("string(./domain/@type)", ctxt))) {
|
||||
int domainflags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
|
||||
int domainflags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
|
||||
if (flags & VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL)
|
||||
domainflags |= VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS;
|
||||
xmlNodePtr domainNode = virXPathNode("./domain", ctxt);
|
||||
|
@ -443,7 +443,8 @@ virDomainObjListLoadConfig(virDomainObjListPtr doms,
|
||||
goto error;
|
||||
if (!(def = virDomainDefParseFile(configFile, caps, xmlopt,
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS)))
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
|
||||
goto error;
|
||||
|
||||
if ((autostartLink = virDomainConfigFile(autostartDir, name)) == NULL)
|
||||
@ -493,7 +494,8 @@ virDomainObjListLoadStatus(virDomainObjListPtr doms,
|
||||
VIR_DOMAIN_DEF_PARSE_STATUS |
|
||||
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_OSTYPE_CHECKS |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
|
||||
goto error;
|
||||
|
||||
virUUIDFormat(obj->def->uuid, uuidstr);
|
||||
|
@ -244,6 +244,7 @@ virDomainDefSetMemoryInitial;
|
||||
virDomainDefSetMemoryTotal;
|
||||
virDomainDefSetVcpus;
|
||||
virDomainDefSetVcpusMax;
|
||||
virDomainDefValidate;
|
||||
virDomainDeleteConfig;
|
||||
virDomainDeviceAddressIsValid;
|
||||
virDomainDeviceAddressTypeToString;
|
||||
|
@ -683,7 +683,8 @@ libxlDomainSaveImageOpen(libxlDriverPrivatePtr driver,
|
||||
}
|
||||
|
||||
if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
|
||||
goto error;
|
||||
|
||||
VIR_FREE(xml);
|
||||
|
@ -419,7 +419,8 @@ libxlDomainMigrationBegin(virConnectPtr conn,
|
||||
if (xmlin) {
|
||||
if (!(tmpdef = virDomainDefParseString(xmlin, cfg->caps,
|
||||
driver->xmlopt,
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
|
||||
goto endjob;
|
||||
|
||||
if (!libxlDomainDefCheckABIStability(driver, vm->def, tmpdef))
|
||||
@ -465,7 +466,8 @@ libxlDomainMigrationPrepareDef(libxlDriverPrivatePtr driver,
|
||||
}
|
||||
|
||||
if (!(def = virDomainDefParseString(dom_xml, cfg->caps, driver->xmlopt,
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
|
||||
goto cleanup;
|
||||
|
||||
if (dname) {
|
||||
|
@ -2315,7 +2315,8 @@ openvzDomainMigratePrepare3Params(virConnectPtr dconn,
|
||||
}
|
||||
|
||||
if (!(def = virDomainDefParseString(dom_xml, driver->caps, driver->xmlopt,
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
|
||||
goto error;
|
||||
|
||||
if (!(vm = virDomainObjListAdd(driver->domains, def,
|
||||
|
@ -2990,7 +2990,8 @@ qemuDomainDefCopy(virQEMUDriverPtr driver,
|
||||
goto cleanup;
|
||||
|
||||
if (!(ret = virDomainDefParseString(xml, caps, driver->xmlopt,
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
|
||||
goto cleanup;
|
||||
|
||||
cleanup:
|
||||
|
@ -3227,7 +3227,8 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom,
|
||||
virDomainDefPtr def = NULL;
|
||||
|
||||
if (!(def = virDomainDefParseString(xmlin, caps, driver->xmlopt,
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE))) {
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) {
|
||||
goto endjob;
|
||||
}
|
||||
if (!qemuDomainDefCheckABIStability(driver, vm->def, def)) {
|
||||
@ -6414,7 +6415,8 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver,
|
||||
|
||||
/* Create a domain from this XML */
|
||||
if (!(def = virDomainDefParseString(xml, caps, driver->xmlopt,
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
|
||||
goto error;
|
||||
|
||||
if (xmlout)
|
||||
@ -14481,7 +14483,8 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
|
||||
* conversion in and back out of xml. */
|
||||
if (!(xml = qemuDomainDefFormatLive(driver, vm->def, true, true)) ||
|
||||
!(def->dom = virDomainDefParseString(xml, caps, driver->xmlopt,
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
|
||||
goto endjob;
|
||||
|
||||
if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
|
||||
|
@ -1279,7 +1279,8 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
|
||||
mig->persistent = virDomainDefParseNode(doc, nodes[0],
|
||||
caps, driver->xmlopt,
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||
VIR_DOMAIN_DEF_PARSE_ABI_UPDATE);
|
||||
VIR_DOMAIN_DEF_PARSE_ABI_UPDATE |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE);
|
||||
if (!mig->persistent) {
|
||||
/* virDomainDefParseNode already reported
|
||||
* an error for us */
|
||||
@ -3207,7 +3208,8 @@ qemuMigrationBeginPhase(virQEMUDriverPtr driver,
|
||||
|
||||
if (xmlin) {
|
||||
if (!(def = virDomainDefParseString(xmlin, caps, driver->xmlopt,
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
|
||||
goto cleanup;
|
||||
|
||||
if (!qemuDomainDefCheckABIStability(driver, vm->def, def))
|
||||
@ -3550,7 +3552,8 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
|
||||
|
||||
VIR_DEBUG("Using hook-filtered domain XML: %s", xmlout);
|
||||
newdef = virDomainDefParseString(xmlout, caps, driver->xmlopt,
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE);
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE);
|
||||
if (!newdef)
|
||||
goto cleanup;
|
||||
|
||||
@ -4023,7 +4026,8 @@ qemuMigrationPrepareDef(virQEMUDriverPtr driver,
|
||||
return NULL;
|
||||
|
||||
if (!(def = virDomainDefParseString(dom_xml, caps, driver->xmlopt,
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
|
||||
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
|
||||
goto cleanup;
|
||||
|
||||
if (dname) {
|
||||
|
@ -704,7 +704,8 @@ get_definition(vahControl * ctl, const char *xmlStr)
|
||||
}
|
||||
|
||||
ctl->def = virDomainDefParseString(xmlStr,
|
||||
ctl->caps, ctl->xmlopt, 0);
|
||||
ctl->caps, ctl->xmlopt,
|
||||
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE);
|
||||
|
||||
if (ctl->def == NULL) {
|
||||
vah_error(ctl, 0, _("could not parse XML"));
|
||||
|
Loading…
x
Reference in New Issue
Block a user