diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 1e8cffeb500e1950ae85fdfcbc0437793555009e..efb85febccbfa51a546af8cdd2130265e0ded625 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4531,6 +4531,47 @@ virDomainDefPostParse(virDomainDefPtr def, } +static int +virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev ATTRIBUTE_UNUSED, + const virDomainDef *def ATTRIBUTE_UNUSED) +{ + return 0; +} + + +static int +virDomainDeviceDefValidate(const virDomainDeviceDef *dev, + const virDomainDef *def, + unsigned int parseFlags, + virDomainXMLOptionPtr xmlopt) +{ + /* validate configuration only in certain places */ + if (parseFlags & VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE) + return 0; + + if (xmlopt->config.deviceValidateCallback && + xmlopt->config.deviceValidateCallback(dev, def, xmlopt->config.priv)) + return -1; + + if (virDomainDeviceDefValidateInternal(dev, def) < 0) + return -1; + + return 0; +} + + +static int +virDomainDefValidateDeviceIterator(virDomainDefPtr def, + virDomainDeviceDefPtr dev, + virDomainDeviceInfoPtr info ATTRIBUTE_UNUSED, + void *opaque) +{ + struct virDomainDefPostParseDeviceIteratorData *data = opaque; + return virDomainDeviceDefValidate(dev, def, + data->parseFlags, data->xmlopt); +} + + static int virDomainDefValidateInternal(const virDomainDef *def ATTRIBUTE_UNUSED) { @@ -4554,11 +4595,17 @@ virDomainDefValidateInternal(const virDomainDef *def ATTRIBUTE_UNUSED) * appropriate message. */ int -virDomainDefValidate(const virDomainDef *def, +virDomainDefValidate(virDomainDefPtr def, virCapsPtr caps, unsigned int parseFlags, virDomainXMLOptionPtr xmlopt) { + struct virDomainDefPostParseDeviceIteratorData data = { + .caps = caps, + .xmlopt = xmlopt, + .parseFlags = parseFlags, + }; + /* validate configuration only in certain places */ if (parseFlags & VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE) return 0; @@ -4568,6 +4615,12 @@ virDomainDefValidate(const virDomainDef *def, xmlopt->config.domainValidateCallback(def, caps, xmlopt->config.priv) < 0) return -1; + /* iterate the devices */ + if (virDomainDeviceInfoIterateInternal(def, + virDomainDefValidateDeviceIterator, + true, &data) < 0) + return -1; + if (virDomainDefValidateInternal(def) < 0) return -1; @@ -13179,6 +13232,10 @@ virDomainDeviceDefParse(const char *xmlStr, if (virDomainDeviceDefPostParse(dev, def, caps, flags, xmlopt) < 0) goto error; + /* validate the configuration */ + if (virDomainDeviceDefValidate(dev, def, flags, xmlopt) < 0) + goto error; + cleanup: xmlFreeDoc(xml); xmlXPathFreeContext(ctxt); @@ -24234,7 +24291,8 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src, xmlStr = virBufferContentAndReset(&buf); ret = virDomainDeviceDefParse(xmlStr, def, caps, xmlopt, - VIR_DOMAIN_DEF_PARSE_INACTIVE); + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE); cleanup: VIR_FREE(xmlStr); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 1a2621e4b2c14b875fd7497b9997399bef37171f..d62d99bf2f329d53fe3364315c2b89062d6ef03f 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2368,6 +2368,12 @@ typedef int (*virDomainDefValidateCallback)(const virDomainDef *def, virCapsPtr caps, void *opaque); +/* Called once per device, for adjusting per-device settings while + * leaving the overall domain otherwise unchanged. */ +typedef int (*virDomainDeviceDefValidateCallback)(const virDomainDeviceDef *dev, + const virDomainDef *def, + void *opaque); + typedef struct _virDomainDefParserConfig virDomainDefParserConfig; typedef virDomainDefParserConfig *virDomainDefParserConfigPtr; struct _virDomainDefParserConfig { @@ -2378,6 +2384,7 @@ struct _virDomainDefParserConfig { /* validation callbacks */ virDomainDefValidateCallback domainValidateCallback; + virDomainDeviceDefValidateCallback deviceValidateCallback; /* private data for the callbacks */ void *priv; @@ -2424,7 +2431,7 @@ virDomainDefPostParse(virDomainDefPtr def, unsigned int parseFlags, virDomainXMLOptionPtr xmlopt); -int virDomainDefValidate(const virDomainDef *def, +int virDomainDefValidate(virDomainDefPtr def, virCapsPtr caps, unsigned int parseFlags, virDomainXMLOptionPtr xmlopt); diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 60867178a3578834a3db1b075a4c57bfd25c324c..bbcf8b9fce0f36dd9cec03f9ce244ad797c72881 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -3742,7 +3742,8 @@ libxlDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { if (!(dev = virDomainDeviceDefParse(xml, vm->def, cfg->caps, driver->xmlopt, - VIR_DOMAIN_DEF_PARSE_INACTIVE))) + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) goto endjob; /* Make a copy for updated domain. */ @@ -3759,7 +3760,8 @@ libxlDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, virDomainDeviceDefFree(dev); if (!(dev = virDomainDeviceDefParse(xml, vm->def, cfg->caps, driver->xmlopt, - VIR_DOMAIN_DEF_PARSE_INACTIVE))) + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) goto endjob; if (libxlDomainDetachDeviceLive(driver, vm, dev) < 0) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 927e20c7d1f866a5c98f50d549e347ecc96d3dbd..9266349a71fa4fc313e2e8e4145c9469b5989af7 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -5317,7 +5317,8 @@ static int lxcDomainDetachDeviceFlags(virDomainPtr dom, dev = dev_copy = virDomainDeviceDefParse(xml, vm->def, caps, driver->xmlopt, - VIR_DOMAIN_DEF_PARSE_INACTIVE); + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE); if (dev == NULL) goto endjob; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 8463e8de39874b42b1ab9fb633d893a6fa638e5f..a7202ed3e3a14581648dc8ec3a3757549e601db0 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -8422,7 +8422,7 @@ qemuDomainDetachDeviceFlags(virDomainPtr dom, virDomainDefPtr vmdef = NULL; virDomainDeviceDefPtr dev = NULL, dev_copy = NULL; int ret = -1; - unsigned int parse_flags = 0; + unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE; virQEMUCapsPtr qemuCaps = NULL; qemuDomainObjPrivatePtr priv; virQEMUDriverConfigPtr cfg = NULL; diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 0b0965eab8425ead7d1d914147142231c6a26705..f8b30568ef72d39bb83690e51f0e869542031c21 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2365,7 +2365,8 @@ static int umlDomainDetachDevice(virDomainPtr dom, const char *xml) } dev = virDomainDeviceDefParse(xml, vm->def, driver->caps, driver->xmlopt, - VIR_DOMAIN_DEF_PARSE_INACTIVE); + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE); if (dev == NULL) goto cleanup; diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index b62e654c9c72ff80fb676a0435a0d99ecf9fb2fe..ad5cbe9460f306b2398e127b41a8819ce9a6b6e3 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -4242,7 +4242,8 @@ static int vboxDomainDetachDevice(virDomainPtr dom, const char *xml) def->os.type = VIR_DOMAIN_OSTYPE_HVM; dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, - VIR_DOMAIN_DEF_PARSE_INACTIVE); + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE); if (dev == NULL) goto cleanup; diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c index a092689bfc653266198b51e48c8d24968ead5510..e59cf30c2628f05cad62de73c0a30d6603dfc5e4 100644 --- a/src/vz/vz_driver.c +++ b/src/vz/vz_driver.c @@ -1211,7 +1211,9 @@ static int vzDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, goto cleanup; dev = virDomainDeviceDefParse(xml, privdom->def, privconn->driver->caps, - privconn->driver->xmlopt, VIR_DOMAIN_XML_INACTIVE); + privconn->driver->xmlopt, + VIR_DOMAIN_XML_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE); if (dev == NULL) goto cleanup; diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index 4dd6b417f7677fd6c84aeb9c5de7b66298d69db8..3e3be58a560ace6394ec2bbaa6a45df953a1095a 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -2355,7 +2355,8 @@ xenDaemonDetachDeviceFlags(virConnectPtr conn, goto cleanup; if (!(dev = virDomainDeviceDefParse(xml, def, priv->caps, priv->xmlopt, - VIR_DOMAIN_DEF_PARSE_INACTIVE))) + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) goto cleanup; if (virDomainXMLDevID(conn, minidef, dev, class, ref, sizeof(ref))) diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index ef1a460a2bf4e5bb1633f4bb8fc0ba3dd77b6d03..4c9dcdfec19b429ba1fe38cc5499835c12efb0f8 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -1343,7 +1343,8 @@ xenXMDomainDetachDeviceFlags(virConnectPtr conn, if (!(dev = virDomainDeviceDefParse(xml, entry->def, priv->caps, priv->xmlopt, - VIR_DOMAIN_DEF_PARSE_INACTIVE))) + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) goto cleanup; switch (dev->type) {