]> xenbits.xensource.com Git - libvirt.git/commitdiff
conf: Add infrastructure for adding configuration validation
authorPeter Krempa <pkrempa@redhat.com>
Thu, 26 May 2016 13:58:53 +0000 (15:58 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Tue, 7 Jun 2016 11:02:20 +0000 (13:02 +0200)
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.

12 files changed:
src/conf/domain_conf.c
src/conf/domain_conf.h
src/conf/snapshot_conf.c
src/conf/virdomainobjlist.c
src/libvirt_private.syms
src/libxl/libxl_domain.c
src/libxl/libxl_migration.c
src/openvz/openvz_driver.c
src/qemu/qemu_domain.c
src/qemu/qemu_driver.c
src/qemu/qemu_migration.c
src/security/virt-aa-helper.c

index 1f08b57a2590f0b91afc691d495b628471443907..7a6c021073050aa273bf6ffa8c12bf3c52dd79b3 100644 (file)
@@ -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;
index c9b398603f28f6dacf6bb3e6e3712344802a65e0..1a2621e4b2c14b875fd7497b9997399bef37171f 100644 (file)
@@ -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 {
index c7794e9b1970fd15e4c6b2c85428f6a3f5083254..c52c4810eab1bdc5d9010f03903159163ddebfc4 100644 (file)
@@ -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);
index 05c532a3ba326cc0245e46dc9d71eb3da253aac1..27590c873fa7f86eec77f6ddd5a6d53b50b41d14 100644 (file)
@@ -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);
index 33b80e859920c5fba1c96e6a8de94fa5ed97d2c5..8f664ef60ff375a0905f38b3c3c490b289506138 100644 (file)
@@ -244,6 +244,7 @@ virDomainDefSetMemoryInitial;
 virDomainDefSetMemoryTotal;
 virDomainDefSetVcpus;
 virDomainDefSetVcpusMax;
+virDomainDefValidate;
 virDomainDeleteConfig;
 virDomainDeviceAddressIsValid;
 virDomainDeviceAddressTypeToString;
index 9fe8be04ee72136efec27181ba4aec334f4f3955..4a21f68e2251d67fe290053771b4fab9f37cc91a 100644 (file)
@@ -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);
index a809aa05110c65829d3f32a9308d661e572a41ab..539ee1bb23b3b68bf71b98144989bf8c219b5b9f 100644 (file)
@@ -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) {
index 73322c3d389081cdd74d999ca1ad0d5bc5f8f409..aa482c9cd0361a0310502e1e4c3d3f3096685b73 100644 (file)
@@ -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,
index c21465d41c764885117b50e603f973d30e3167f9..fd6d6d2a06920be5994f783bf106400f2538aa9d 100644 (file)
@@ -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:
index 0fbdee6d18c7439e794e3f125d07f38d497dfe50..8463e8de39874b42b1ab9fb633d893a6fa638e5f 100644 (file)
@@ -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) {
index bed5f0b581b9b731b98923a0a52695f5d141bdd5..b9ac6fa700212557eb331bc969c2271358405590 100644 (file)
@@ -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) {
index 691bbdf63afee75018a4d6991d8dd7307318766e..6b0685c93b4e366d198b77e6ffc9b5f09ca77c45 100644 (file)
@@ -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"));