Always pass the --migration option to swtpm, if swptm supports it (staring
with v0.8). Always apply the 'release-lock-outgoing' parameter with this
option and apply the 'incoming' parameter for incoming migration so that
swtpm releases the file lock on the source side when the state is migrated
and locks the file on the destination side when the state is received.
If a started swtpm instance is capable of migrating with share storage
then remember this with a flag in the virDomainTPMDef. This flag allows
for modifications of the installed swtpm, such as installing a version
that does not support migration with shared storage.
Report an error if swtpm does not support the --migration option and an
incoming migration across shared storage is requested.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
src/conf/domain_conf.h | 1 +
src/qemu/qemu_migration.c | 8 ++++++++
src/qemu/qemu_tpm.c | 40 +++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_tpm.h | 3 +++
4 files changed, 52 insertions(+)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 352b88eae5..4f9b5c6686 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1461,6 +1461,7 @@ struct _virDomainTPMDef {
bool hassecretuuid;
bool persistent_state;
virBitmap *activePcrBanks;
+ bool canMigrateWithSharedStorage;
} emulator;
} data;
};
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index efb27a24aa..431b1b0bcb 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -38,6 +38,7 @@
#include "qemu_security.h"
#include "qemu_slirp.h"
#include "qemu_block.h"
+#include "qemu_tpm.h"
#include "domain_audit.h"
#include "virlog.h"
@@ -2789,6 +2790,13 @@ qemuMigrationSrcBegin(virConnectPtr conn,
goto cleanup;
}
+ if ((flags & VIR_MIGRATE_TPM_SHARED_STORAGE) &&
+ !qemuTPMCanMigrateSharedStorage(vm->def)) {
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("the running swtpm does not support migration with shared storage"));
+ goto cleanup;
+ }
+
if (flags & VIR_MIGRATE_POSTCOPY_RESUME) {
ret = qemuMigrationSrcBeginResumePhase(conn, driver, vm, xmlin,
cookieout, cookieoutlen, flags);
diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
index 07def3c840..fde15b7587 100644
--- a/src/qemu/qemu_tpm.c
+++ b/src/qemu/qemu_tpm.c
@@ -644,6 +644,32 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
virCommandAddArgFormat(cmd, "pwdfd=%d,mode=aes-256-cbc", migpwdfile_fd);
}
+ /* If swtpm supports it, start it with --migration release-lock-outgoing
+ * so it can migrate across shared storage if needed.
+ */
+ tpm->data.emulator.canMigrateWithSharedStorage = false;
+ if (virTPMSwtpmCapsGet(VIR_TPM_SWTPM_FEATURE_CMDARG_MIGRATION)) {
+ bool incoming = false;
+
+ if (incomingMigration && (flags & VIR_MIGRATE_TPM_SHARED_STORAGE))
+ incoming = true;
+ virCommandAddArg(cmd, "--migration");
+ virCommandAddArgFormat(cmd, "release-lock-outgoing%s",
+ incoming ? ",incoming": "");
+ tpm->data.emulator.canMigrateWithSharedStorage = true;
+ } else {
+ /* Report an error if there's an incoming migration across shared
+ * storage and swtpm does not support the --migration option.
+ */
+ if (incomingMigration && (flags & VIR_MIGRATE_TPM_SHARED_STORAGE)) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
+ _("%s (on destination side) does not support the --migration option "
+ "needed for migration with shared storage"),
+ swtpm);
+ goto error;
+ }
+ }
+
return g_steal_pointer(&cmd);
error:
@@ -967,6 +993,20 @@ qemuTPMEmulatorStart(virQEMUDriver *driver,
}
+bool
+qemuTPMCanMigrateSharedStorage(virDomainDef *def)
+{
+ size_t i;
+
+ for (i = 0; i < def->ntpms; i++) {
+ if (def->tpms[i]->type == VIR_DOMAIN_TPM_TYPE_EMULATOR &&
+ !def->tpms[i]->data.emulator.canMigrateWithSharedStorage) {
+ return false;
+ }
+ }
+ return true;
+}
+
/* ---------------------
* Module entry points
* ---------------------
diff --git a/src/qemu/qemu_tpm.h b/src/qemu/qemu_tpm.h
index 410c9ec1c6..630fa7074f 100644
--- a/src/qemu/qemu_tpm.h
+++ b/src/qemu/qemu_tpm.h
@@ -57,3 +57,6 @@ int qemuExtTPMSetupCgroup(virQEMUDriver *driver,
virCgroup *cgroup)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
G_GNUC_WARN_UNUSED_RESULT;
+
+bool qemuTPMCanMigrateSharedStorage(virDomainDef *def)
+ ATTRIBUTE_NONNULL(1);
--
2.37.3
On 10/5/22 16:02, Stefan Berger wrote:
> Always pass the --migration option to swtpm, if swptm supports it (staring
> with v0.8). Always apply the 'release-lock-outgoing' parameter with this
> option and apply the 'incoming' parameter for incoming migration so that
> swtpm releases the file lock on the source side when the state is migrated
> and locks the file on the destination side when the state is received.
>
> If a started swtpm instance is capable of migrating with share storage
> then remember this with a flag in the virDomainTPMDef. This flag allows
> for modifications of the installed swtpm, such as installing a version
> that does not support migration with shared storage.
>
> Report an error if swtpm does not support the --migration option and an
> incoming migration across shared storage is requested.
>
> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
> ---
> src/conf/domain_conf.h | 1 +
> src/qemu/qemu_migration.c | 8 ++++++++
> src/qemu/qemu_tpm.c | 40 +++++++++++++++++++++++++++++++++++++++
> src/qemu/qemu_tpm.h | 3 +++
> 4 files changed, 52 insertions(+)
>
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index 352b88eae5..4f9b5c6686 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -1461,6 +1461,7 @@ struct _virDomainTPMDef {
> bool hassecretuuid;
> bool persistent_state;
> virBitmap *activePcrBanks;
> + bool canMigrateWithSharedStorage;
I wonder whether this is something that should be stored in privateData.
I mean, gradually we are introducing 'void *privateData' not only to
virDomainObj but also to devices (lastly in
ea3c3f88462153139b36282a22d727e920735f8b). We could then store other
information there too, e.g. whether given TPM is migrating or not and
use that information when removing an inactive domain.
> } emulator;
> } data;
> };
> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
> index efb27a24aa..431b1b0bcb 100644
> --- a/src/qemu/qemu_migration.c
> +++ b/src/qemu/qemu_migration.c
> @@ -38,6 +38,7 @@
> #include "qemu_security.h"
> #include "qemu_slirp.h"
> #include "qemu_block.h"
> +#include "qemu_tpm.h"
>
> #include "domain_audit.h"
> #include "virlog.h"
> @@ -2789,6 +2790,13 @@ qemuMigrationSrcBegin(virConnectPtr conn,
> goto cleanup;
> }
>
> + if ((flags & VIR_MIGRATE_TPM_SHARED_STORAGE) &&
> + !qemuTPMCanMigrateSharedStorage(vm->def)) {
> + virReportError(VIR_ERR_NO_SUPPORT, "%s",
> + _("the running swtpm does not support migration with shared storage"));
> + goto cleanup;
> + }
> +
This works, but I think qemuMigrationSrcIsAllowed() is better place for
this check.
> if (flags & VIR_MIGRATE_POSTCOPY_RESUME) {
> ret = qemuMigrationSrcBeginResumePhase(conn, driver, vm, xmlin,
> cookieout, cookieoutlen, flags);
> diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
> index 07def3c840..fde15b7587 100644
> --- a/src/qemu/qemu_tpm.c
> +++ b/src/qemu/qemu_tpm.c
> @@ -644,6 +644,32 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
> virCommandAddArgFormat(cmd, "pwdfd=%d,mode=aes-256-cbc", migpwdfile_fd);
> }
>
> + /* If swtpm supports it, start it with --migration release-lock-outgoing
> + * so it can migrate across shared storage if needed.
> + */
> + tpm->data.emulator.canMigrateWithSharedStorage = false;
> + if (virTPMSwtpmCapsGet(VIR_TPM_SWTPM_FEATURE_CMDARG_MIGRATION)) {
> + bool incoming = false;
> +
> + if (incomingMigration && (flags & VIR_MIGRATE_TPM_SHARED_STORAGE))
> + incoming = true;
> + virCommandAddArg(cmd, "--migration");
> + virCommandAddArgFormat(cmd, "release-lock-outgoing%s",
> + incoming ? ",incoming": "");
> + tpm->data.emulator.canMigrateWithSharedStorage = true;
> + } else {
> + /* Report an error if there's an incoming migration across shared
> + * storage and swtpm does not support the --migration option.
> + */
> + if (incomingMigration && (flags & VIR_MIGRATE_TPM_SHARED_STORAGE)) {
> + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
> + _("%s (on destination side) does not support the --migration option "
> + "needed for migration with shared storage"),
Error messages are exempt from long line rule.
> + swtpm);
> + goto error;
> + }
> + }
> +
> return g_steal_pointer(&cmd);
>
> error:
Michal
On 10/5/22 10:02, Stefan Berger wrote:
> Always pass the --migration option to swtpm, if swptm supports it (staring
> with v0.8). Always apply the 'release-lock-outgoing' parameter with this
> option and apply the 'incoming' parameter for incoming migration so that
> swtpm releases the file lock on the source side when the state is migrated
> and locks the file on the destination side when the state is received.
>
> If a started swtpm instance is capable of migrating with share storage
> then remember this with a flag in the virDomainTPMDef. This flag allows
> for modifications of the installed swtpm, such as installing a version
> that does not support migration with shared storage.
>
> Report an error if swtpm does not support the --migration option and an
> incoming migration across shared storage is requested.
>
> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
> ---
> src/conf/domain_conf.h | 1 +
> src/qemu/qemu_migration.c | 8 ++++++++
> src/qemu/qemu_tpm.c | 40 +++++++++++++++++++++++++++++++++++++++
> src/qemu/qemu_tpm.h | 3 +++
> 4 files changed, 52 insertions(+)
>
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index 352b88eae5..4f9b5c6686 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -1461,6 +1461,7 @@ struct _virDomainTPMDef {
> bool hassecretuuid;
> bool persistent_state;
> virBitmap *activePcrBanks;
> + bool canMigrateWithSharedStorage;
> } emulator;
> } data;
> };
> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
> index efb27a24aa..431b1b0bcb 100644
> --- a/src/qemu/qemu_migration.c
> +++ b/src/qemu/qemu_migration.c
> @@ -38,6 +38,7 @@
> #include "qemu_security.h"
> #include "qemu_slirp.h"
> #include "qemu_block.h"
> +#include "qemu_tpm.h"
>
> #include "domain_audit.h"
> #include "virlog.h"
> @@ -2789,6 +2790,13 @@ qemuMigrationSrcBegin(virConnectPtr conn,
> goto cleanup;
> }
>
> + if ((flags & VIR_MIGRATE_TPM_SHARED_STORAGE) &&
> + !qemuTPMCanMigrateSharedStorage(vm->def)) {
> + virReportError(VIR_ERR_NO_SUPPORT, "%s",
> + _("the running swtpm does not support migration with shared storage"));
> + goto cleanup;
> + }
> +
> if (flags & VIR_MIGRATE_POSTCOPY_RESUME) {
> ret = qemuMigrationSrcBeginResumePhase(conn, driver, vm, xmlin,
> cookieout, cookieoutlen, flags);
> diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
> index 07def3c840..fde15b7587 100644
> --- a/src/qemu/qemu_tpm.c
> +++ b/src/qemu/qemu_tpm.c
> @@ -644,6 +644,32 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
> virCommandAddArgFormat(cmd, "pwdfd=%d,mode=aes-256-cbc", migpwdfile_fd);
> }
>
> + /* If swtpm supports it, start it with --migration release-lock-outgoing
> + * so it can migrate across shared storage if needed.
> + */
> + tpm->data.emulator.canMigrateWithSharedStorage = false;
> + if (virTPMSwtpmCapsGet(VIR_TPM_SWTPM_FEATURE_CMDARG_MIGRATION)) {
> + bool incoming = false;
> +
> + if (incomingMigration && (flags & VIR_MIGRATE_TPM_SHARED_STORAGE))
> + incoming = true;
> + virCommandAddArg(cmd, "--migration");
> + virCommandAddArgFormat(cmd, "release-lock-outgoing%s",
> + incoming ? ",incoming": "");
> + tpm->data.emulator.canMigrateWithSharedStorage = true;
This flag remembers the capability of swtpm that was started and allows to downgrade swtpm while the VM is running for example (which doesn't influence the running swtpm). When libvirt is restarted is unfortunately refuses to migrate the VM when --tpm-shared-storage is set up because this flag was forgotten. How would I persist this flag?
6/9 has wrong title... I will fix.
Stefan
© 2016 - 2026 Red Hat, Inc.