]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Add UNDEFINE_TPM and UNDEFINE_KEEP_TPM flags
authorStefan Berger <stefanb@linux.ibm.com>
Tue, 4 Oct 2022 13:38:13 +0000 (09:38 -0400)
committerMichal Privoznik <mprivozn@redhat.com>
Tue, 4 Oct 2022 14:34:28 +0000 (16:34 +0200)
Add UNDEFINE_TPM and UNDEFINE_KEEP_TPM flags to qemuDomainUndefineFlags()
API and --tpm and --keep-tpm to 'virsh undefine'. Pass the
virDomainUndefineFlagsValues via qemuDomainRemoveInactive()
from qemuDomainUndefineFlags() all the way down to
qemuTPMEmulatorCleanupHost() and delete TPM storage there considering that
the UNDEFINE_TPM flag has priority over the persistent_state attribute
from the domain XML. Pass 0 in all other API call sites to
qemuDomainRemoveInactive() for now.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
13 files changed:
docs/manpages/virsh.rst
include/libvirt/libvirt-domain.h
src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_driver.c
src/qemu/qemu_extdevice.c
src/qemu/qemu_extdevice.h
src/qemu/qemu_migration.c
src/qemu/qemu_process.c
src/qemu/qemu_snapshot.c
src/qemu/qemu_tpm.c
src/qemu/qemu_tpm.h
tools/virsh-domain.c

index 45469f2f35d34b77cdaf83d578d0b6e59559aa2a..5d11c488031d8347a5ace935460eab370c4b8392 100644 (file)
@@ -4486,6 +4486,7 @@ undefine
       [--checkpoints-metadata] [--nvram] [--keep-nvram]
       [ {--storage volumes | --remove-all-storage
          [--delete-storage-volume-snapshots]} --wipe-storage]
+      [--tpm] [--keep-tpm]
 
 Undefine a domain. If the domain is running, this converts it to a
 transient domain, without stopping it. If the domain is inactive,
@@ -4537,6 +4538,11 @@ failure.
 The flag *--wipe-storage* specifies that the storage volumes should be
 wiped before removal.
 
+*--tpm* and *--keep-tpm* specify accordingly to delete or keep a TPM's
+persistent state directory structure and files. If the flags are omitted
+then the persistent_state attribute in the TPM emulator definition in the
+domain XML determines whether the TPM state is kept.
+
 NOTE: For an inactive domain, the domain name or UUID must be used as the
 *domain*.
 
index 7430a08619f9ace999126145aeddbdc943687531..8357aea7970d87835e21276950c96f25531be103 100644 (file)
@@ -2267,6 +2267,10 @@ typedef enum {
     VIR_DOMAIN_UNDEFINE_CHECKPOINTS_METADATA = (1 << 4), /* If last use of domain,
                                                             then also remove any
                                                             checkpoint metadata (Since: 5.6.0) */
+    VIR_DOMAIN_UNDEFINE_TPM                = (1 << 5), /* Also remove any
+                                                          TPM state (Since: 8.9.0) */
+    VIR_DOMAIN_UNDEFINE_KEEP_TPM           = (1 << 6), /* Keep TPM state (Since: 8.9.0) */
+    /* Future undefine control flags should come here. */
 } virDomainUndefineFlagsValues;
 
 
index ee024d17cd13f5e8957fdf28b8452e5ba6eb74e0..858d14af6a0f5d7e847bc874e0c0a1314a5a38fb 100644 (file)
@@ -7168,7 +7168,8 @@ qemuDomainSnapshotDiscardAllMetadata(virQEMUDriver *driver,
 
 static void
 qemuDomainRemoveInactiveCommon(virQEMUDriver *driver,
-                               virDomainObj *vm)
+                               virDomainObj *vm,
+                               virDomainUndefineFlagsValues flags)
 {
     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
     g_autofree char *snapDir = NULL;
@@ -7194,7 +7195,7 @@ qemuDomainRemoveInactiveCommon(virQEMUDriver *driver,
         if (rmdir(chkDir) < 0 && errno != ENOENT)
             VIR_WARN("unable to remove checkpoint directory %s", chkDir);
     }
-    qemuExtDevicesCleanupHost(driver, vm->def);
+    qemuExtDevicesCleanupHost(driver, vm->def, flags);
 }
 
 
@@ -7205,14 +7206,15 @@ qemuDomainRemoveInactiveCommon(virQEMUDriver *driver,
  */
 void
 qemuDomainRemoveInactive(virQEMUDriver *driver,
-                         virDomainObj *vm)
+                         virDomainObj *vm,
+                         virDomainUndefineFlagsValues flags)
 {
     if (vm->persistent) {
         /* Short-circuit, we don't want to remove a persistent domain */
         return;
     }
 
-    qemuDomainRemoveInactiveCommon(driver, vm);
+    qemuDomainRemoveInactiveCommon(driver, vm, flags);
 
     virDomainObjListRemove(driver->domains, vm);
 }
@@ -7234,7 +7236,7 @@ qemuDomainRemoveInactiveLocked(virQEMUDriver *driver,
         return;
     }
 
-    qemuDomainRemoveInactiveCommon(driver, vm);
+    qemuDomainRemoveInactiveCommon(driver, vm, 0);
 
     virDomainObjListRemoveLocked(driver->domains, vm);
 }
index ef149b9fa96f852db4f8bc138257fa24cbbe60b1..a22deaf1135d657e39ad176a6609b4af7bb845d8 100644 (file)
@@ -681,7 +681,8 @@ int qemuDomainSnapshotDiscardAllMetadata(virQEMUDriver *driver,
                                          virDomainObj *vm);
 
 void qemuDomainRemoveInactive(virQEMUDriver *driver,
-                              virDomainObj *vm);
+                              virDomainObj *vm,
+                              virDomainUndefineFlagsValues flags);
 
 void
 qemuDomainRemoveInactiveLocked(virQEMUDriver *driver,
index 3db45929452e9d7b570a66350481db9e07e0e5cf..40d23b5723838d625c81ac0e89aed7efc110ec20 100644 (file)
@@ -1626,7 +1626,7 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn,
         goto cleanup;
 
     if (qemuProcessBeginJob(vm, VIR_DOMAIN_JOB_OPERATION_START, flags) < 0) {
-        qemuDomainRemoveInactive(driver, vm);
+        qemuDomainRemoveInactive(driver, vm, 0);
         goto cleanup;
     }
 
@@ -1635,7 +1635,7 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn,
                          VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
                          start_flags) < 0) {
         virDomainAuditStart(vm, "booted", false);
-        qemuDomainRemoveInactive(driver, vm);
+        qemuDomainRemoveInactive(driver, vm, 0);
         qemuProcessEndJob(vm);
         goto cleanup;
     }
@@ -2118,7 +2118,7 @@ qemuDomainDestroyFlags(virDomainPtr dom,
     ret = 0;
  endjob:
     if (ret == 0)
-        qemuDomainRemoveInactive(driver, vm);
+        qemuDomainRemoveInactive(driver, vm, 0);
     virDomainObjEndJob(vm);
 
  cleanup:
@@ -2738,7 +2738,7 @@ qemuDomainSaveInternal(virQEMUDriver *driver,
     }
     virDomainObjEndAsyncJob(vm);
     if (ret == 0)
-        qemuDomainRemoveInactive(driver, vm);
+        qemuDomainRemoveInactive(driver, vm, 0);
 
  cleanup:
     virQEMUSaveDataFree(data);
@@ -3278,7 +3278,7 @@ qemuDomainCoreDumpWithFormat(virDomainPtr dom,
 
     virDomainObjEndAsyncJob(vm);
     if (ret == 0 && flags & VIR_DUMP_CRASH)
-        qemuDomainRemoveInactive(driver, vm);
+        qemuDomainRemoveInactive(driver, vm, 0);
 
  cleanup:
     virDomainObjEndAPI(&vm);
@@ -3590,7 +3590,7 @@ processGuestPanicEvent(virQEMUDriver *driver,
  endjob:
     virDomainObjEndAsyncJob(vm);
     if (removeInactive)
-        qemuDomainRemoveInactive(driver, vm);
+        qemuDomainRemoveInactive(driver, vm, 0);
 }
 
 
@@ -4068,7 +4068,7 @@ processMonitorEOFEvent(virQEMUDriver *driver,
     virObjectEventStateQueue(driver->domainEventState, event);
 
  endjob:
-    qemuDomainRemoveInactive(driver, vm);
+    qemuDomainRemoveInactive(driver, vm, 0);
     virDomainObjEndJob(vm);
 }
 
@@ -6000,7 +6000,7 @@ qemuDomainRestoreInternal(virConnectPtr conn,
     virFileWrapperFdFree(wrapperFd);
     virQEMUSaveDataFree(data);
     if (vm && ret < 0)
-        qemuDomainRemoveInactive(driver, vm);
+        qemuDomainRemoveInactive(driver, vm, 0);
     virDomainObjEndAPI(&vm);
     return ret;
 }
@@ -6690,7 +6690,7 @@ qemuDomainDefineXMLFlags(virConnectPtr conn,
         } else {
             /* Brand new domain. Remove it */
             VIR_INFO("Deleting domain '%s'", vm->def->name);
-            qemuDomainRemoveInactive(driver, vm);
+            qemuDomainRemoveInactive(driver, vm, 0);
         }
     }
 
@@ -6723,7 +6723,9 @@ qemuDomainUndefineFlags(virDomainPtr dom,
                   VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA |
                   VIR_DOMAIN_UNDEFINE_CHECKPOINTS_METADATA |
                   VIR_DOMAIN_UNDEFINE_NVRAM |
-                  VIR_DOMAIN_UNDEFINE_KEEP_NVRAM, -1);
+                  VIR_DOMAIN_UNDEFINE_KEEP_NVRAM |
+                  VIR_DOMAIN_UNDEFINE_TPM |
+                  VIR_DOMAIN_UNDEFINE_KEEP_TPM, -1);
 
     if ((flags & VIR_DOMAIN_UNDEFINE_NVRAM) &&
         (flags & VIR_DOMAIN_UNDEFINE_KEEP_NVRAM)) {
@@ -6732,6 +6734,13 @@ qemuDomainUndefineFlags(virDomainPtr dom,
         return -1;
     }
 
+    if ((flags & VIR_DOMAIN_UNDEFINE_TPM) &&
+        (flags & VIR_DOMAIN_UNDEFINE_KEEP_TPM)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       "%s", _("cannot both keep and delete TPM"));
+        return -1;
+    }
+
     if (!(vm = qemuDomainObjFromDomain(dom)))
         return -1;
 
@@ -6830,7 +6839,7 @@ qemuDomainUndefineFlags(virDomainPtr dom,
      */
     vm->persistent = 0;
     if (!virDomainObjIsActive(vm))
-        qemuDomainRemoveInactive(driver, vm);
+        qemuDomainRemoveInactive(driver, vm, flags);
 
     ret = 0;
  endjob:
index b8e3c1000ab58152072c0dc367224db9e9afa43e..24a57b0f74f0c5546640aaa11c85b41bdfcfc6c7 100644 (file)
@@ -151,7 +151,8 @@ qemuExtDevicesPrepareHost(virQEMUDriver *driver,
 
 void
 qemuExtDevicesCleanupHost(virQEMUDriver *driver,
-                          virDomainDef *def)
+                          virDomainDef *def,
+                          virDomainUndefineFlagsValues flags)
 {
     size_t i;
 
@@ -159,7 +160,7 @@ qemuExtDevicesCleanupHost(virQEMUDriver *driver,
         return;
 
     for (i = 0; i < def->ntpms; i++) {
-        qemuExtTPMCleanupHost(def->tpms[i]);
+        qemuExtTPMCleanupHost(def->tpms[i], flags);
     }
 }
 
index 43d2a4dfffb80451e9a5b43bce32e7c2170b18b1..6b05b59cd67697b09f95b49fbdde4e85a47fd27b 100644 (file)
@@ -41,7 +41,8 @@ int qemuExtDevicesPrepareHost(virQEMUDriver *driver,
     G_GNUC_WARN_UNUSED_RESULT;
 
 void qemuExtDevicesCleanupHost(virQEMUDriver *driver,
-                               virDomainDef *def)
+                               virDomainDef *def,
+                               virDomainUndefineFlagsValues flags)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 
 int qemuExtDevicesStart(virQEMUDriver *driver,
index c63b00c9222d397853627fc04ee96f7d6eef3116..126a4f6d3845c7eeb83626847984f21ee380e01b 100644 (file)
@@ -3391,7 +3391,7 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver,
          * and there is no 'goto cleanup;' in the middle of those */
         VIR_FREE(priv->origname);
         virDomainObjRemoveTransientDef(vm);
-        qemuDomainRemoveInactive(driver, vm);
+        qemuDomainRemoveInactive(driver, vm, 0);
     }
     virDomainObjEndAPI(&vm);
     virErrorRestore(&origErr);
@@ -4036,7 +4036,7 @@ qemuMigrationSrcConfirm(virQEMUDriver *driver,
             virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm);
             vm->persistent = 0;
         }
-        qemuDomainRemoveInactive(driver, vm);
+        qemuDomainRemoveInactive(driver, vm, 0);
     }
 
  cleanup:
@@ -6039,7 +6039,7 @@ qemuMigrationSrcPerformJob(virQEMUDriver *driver,
             virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm);
             vm->persistent = 0;
         }
-        qemuDomainRemoveInactive(driver, vm);
+        qemuDomainRemoveInactive(driver, vm, 0);
     }
 
     virErrorRestore(&orig_err);
@@ -6166,7 +6166,7 @@ qemuMigrationSrcPerformPhase(virQEMUDriver *driver,
     }
 
     if (!virDomainObjIsActive(vm))
-        qemuDomainRemoveInactive(driver, vm);
+        qemuDomainRemoveInactive(driver, vm, 0);
 
     return ret;
 }
@@ -6702,7 +6702,7 @@ qemuMigrationDstFinishActive(virQEMUDriver *driver,
     }
 
     if (!virDomainObjIsActive(vm))
-        qemuDomainRemoveInactive(driver, vm);
+        qemuDomainRemoveInactive(driver, vm, 0);
 
     virErrorRestore(&orig_err);
     return NULL;
@@ -6839,7 +6839,7 @@ qemuMigrationProcessUnattended(virQEMUDriver *driver,
     qemuMigrationJobFinish(vm);
 
     if (!virDomainObjIsActive(vm))
-        qemuDomainRemoveInactive(driver, vm);
+        qemuDomainRemoveInactive(driver, vm, 0);
 }
 
 
index 998f4aa63c632905ebed51ae84576c77489449b6..97336e26228aa6618ddad5efe411eb99a56e8cf1 100644 (file)
@@ -8442,7 +8442,7 @@ qemuProcessAutoDestroy(virDomainObj *dom,
                                      VIR_DOMAIN_EVENT_STOPPED,
                                      VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
 
-    qemuDomainRemoveInactive(driver, dom);
+    qemuDomainRemoveInactive(driver, dom, 0);
 
     virDomainObjEndJob(dom);
 
@@ -8905,7 +8905,7 @@ qemuProcessReconnect(void *opaque)
     if (jobStarted)
         virDomainObjEndJob(obj);
     if (!virDomainObjIsActive(obj))
-        qemuDomainRemoveInactive(driver, obj);
+        qemuDomainRemoveInactive(driver, obj, 0);
     virDomainObjEndAPI(&obj);
     virIdentitySetCurrent(NULL);
     return;
index d2835ab1a857a54900278339d48d50c87ec46f5a..06b5c180ff2d22d3f7a027626dfa91296572bdd4 100644 (file)
@@ -2103,7 +2103,7 @@ qemuSnapshotRevertInactive(virDomainObj *vm,
     }
 
     if (qemuSnapshotInternalRevertInactive(driver, vm, snap) < 0) {
-        qemuDomainRemoveInactive(driver, vm);
+        qemuDomainRemoveInactive(driver, vm, 0);
         return -1;
     }
 
@@ -2125,7 +2125,7 @@ qemuSnapshotRevertInactive(virDomainObj *vm,
                               start_flags);
         virDomainAuditStart(vm, "from-snapshot", rc >= 0);
         if (rc < 0) {
-            qemuDomainRemoveInactive(driver, vm);
+            qemuDomainRemoveInactive(driver, vm, 0);
             return -1;
         }
         detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT;
index 20e38ceaa26b543e22a7e7dbef02622600322db5..dc09c94a4da74ac230fe44420cc8a8860f27a6aa 100644 (file)
@@ -693,14 +693,23 @@ qemuTPMEmulatorInitPaths(virDomainTPMDef *tpm,
 /**
  * qemuTPMEmulatorCleanupHost:
  * @tpm: TPM definition
+ * @flags: flags indicating whether to keep or remove TPM persistent state
  *
  * Clean up persistent storage for the swtpm.
  */
 static void
-qemuTPMEmulatorCleanupHost(virDomainTPMDef *tpm)
+qemuTPMEmulatorCleanupHost(virDomainTPMDef *tpm,
+                           virDomainUndefineFlagsValues flags)
 {
-    if (!tpm->data.emulator.persistent_state)
+    /*
+     * remove TPM state if:
+     * - persistent_state flag is set and the UNDEFINE_TPM flag is set
+     * - persistent_state flag is not set and the KEEP_TPM flag is not set
+     */
+    if ((tpm->data.emulator.persistent_state && (flags & VIR_DOMAIN_UNDEFINE_TPM)) ||
+        (!tpm->data.emulator.persistent_state && !(flags & VIR_DOMAIN_UNDEFINE_KEEP_TPM))) {
         qemuTPMEmulatorDeleteStorage(tpm);
+    }
 }
 
 
@@ -991,9 +1000,10 @@ qemuExtTPMPrepareHost(virQEMUDriver *driver,
 
 
 void
-qemuExtTPMCleanupHost(virDomainTPMDef *tpm)
+qemuExtTPMCleanupHost(virDomainTPMDef *tpm,
+                      virDomainUndefineFlagsValues flags)
 {
-    qemuTPMEmulatorCleanupHost(tpm);
+    qemuTPMEmulatorCleanupHost(tpm, flags);
 }
 
 
index 9951f025a67c378beee16fc72b54186c8dd213c9..f068f3ca5a326cff5c033b78f4ee8a9db0ce6946 100644 (file)
@@ -35,7 +35,8 @@ int qemuExtTPMPrepareHost(virQEMUDriver *driver,
     ATTRIBUTE_NONNULL(3)
     G_GNUC_WARN_UNUSED_RESULT;
 
-void qemuExtTPMCleanupHost(virDomainTPMDef *tpm)
+void qemuExtTPMCleanupHost(virDomainTPMDef *tpm,
+                           virDomainUndefineFlagsValues flags)
     ATTRIBUTE_NONNULL(1);
 
 int qemuExtTPMStart(virQEMUDriver *driver,
index 20aadb59f3efce90c91c8ad0947f4b0e5d95d2a0..2d22547cc61e44073e47e87c7805d0031a5e32fd 100644 (file)
@@ -3650,6 +3650,14 @@ static const vshCmdOptDef opts_undefine[] = {
      .type = VSH_OT_BOOL,
      .help = N_("keep nvram file")
     },
+    {.name = "tpm",
+     .type = VSH_OT_BOOL,
+     .help = N_("remove TPM state")
+    },
+    {.name = "keep-tpm",
+     .type = VSH_OT_BOOL,
+     .help = N_("keep TPM state")
+    },
     {.name = NULL}
 };
 
@@ -3677,6 +3685,8 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
     bool delete_snapshots = vshCommandOptBool(cmd, "delete-storage-volume-snapshots");
     bool nvram = vshCommandOptBool(cmd, "nvram");
     bool keep_nvram = vshCommandOptBool(cmd, "keep-nvram");
+    bool tpm = vshCommandOptBool(cmd, "tpm");
+    bool keep_tpm = vshCommandOptBool(cmd, "keep-tpm");
     /* Positive if these items exist.  */
     int has_managed_save = 0;
     int has_snapshots_metadata = 0;
@@ -3702,6 +3712,7 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
 
     VSH_REQUIRE_OPTION("delete-storage-volume-snapshots", "remove-all-storage");
     VSH_EXCLUSIVE_OPTIONS("nvram", "keep-nvram");
+    VSH_EXCLUSIVE_OPTIONS("tpm", "keep-tpm");
 
     ignore_value(vshCommandOptStringQuiet(ctl, cmd, "storage", &vol_string));
 
@@ -3729,6 +3740,10 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
         flags |= VIR_DOMAIN_UNDEFINE_NVRAM;
     if (keep_nvram)
         flags |= VIR_DOMAIN_UNDEFINE_KEEP_NVRAM;
+    if (tpm)
+        flags |= VIR_DOMAIN_UNDEFINE_TPM;
+    if (keep_tpm)
+        flags |= VIR_DOMAIN_UNDEFINE_KEEP_TPM;
 
     if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
         return false;