}
+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);
if (virDomainDefPostParse(def, caps, flags, xmlopt) < 0)
goto error;
+ /* valdiate configuration */
+ if (virDomainDefValidate(def, caps, flags, xmlopt) < 0)
+ goto error;
+
virHashFree(bootHash);
return def;
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;
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;
virDomainDeviceDefPostParseCallback devicesPostParseCallback;
virDomainDefAssignAddressesCallback assignAddressesCallback;
+ /* validation callbacks */
+ virDomainDefValidateCallback domainValidateCallback;
+
/* private data for the callbacks */
void *priv;
virFreeCallback privFree;
unsigned int parseFlags,
virDomainXMLOptionPtr xmlopt);
+int virDomainDefValidate(const virDomainDef *def,
+ virCapsPtr caps,
+ unsigned int parseFlags,
+ virDomainXMLOptionPtr xmlopt);
+
static inline bool
virDomainObjIsActive(virDomainObjPtr dom)
{
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 {
* 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);
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)
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);
virDomainDefSetMemoryTotal;
virDomainDefSetVcpus;
virDomainDefSetVcpusMax;
+virDomainDefValidate;
virDomainDeleteConfig;
virDomainDeviceAddressIsValid;
virDomainDeviceAddressTypeToString;
}
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);
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))
}
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) {
}
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,
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:
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)) {
/* 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)
* 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) {
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 */
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))
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;
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) {
}
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"));