In the case of TLS-PSK-enabled migration, Libvirt manages the lifecycle
of the pre-shared key. Add a new test scenario to the migration cookie
test suite to validate the generation of pre-shared key when the
QEMU_MIGRATION_COOKIE_TLS_PSK flag is set. In addition, the test also
checks the length and the hexadecimal encoding of the pre-shared key.
Signed-off-by: Abhisek Panda <abhisek.panda1@nutanix.com>
---
tests/qemumigrationcookiexmltest.c | 123 +++++++++++++++++++++++++++++
tests/testutilsqemu.c | 12 +++
2 files changed, 135 insertions(+)
diff --git a/tests/qemumigrationcookiexmltest.c b/tests/qemumigrationcookiexmltest.c
index adf2eb4d08..0914793974 100644
--- a/tests/qemumigrationcookiexmltest.c
+++ b/tests/qemumigrationcookiexmltest.c
@@ -16,6 +16,7 @@
#include <config.h>
+#include <stddef.h>
#include <unistd.h>
#include <sys/types.h>
@@ -92,6 +93,99 @@ testQemuMigrationCookieDataFree(struct testQemuMigrationCookieData *data)
}
+static int
+testQemuMigrationCookiePSKValidate(const char *key)
+{
+ g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(&driver);
+ size_t expected_key_len = 2 * cfg->migrateTLSPSKLength; /* The pre-shared key's length is 2 * PSK length */
+ size_t i;
+
+ if (!key) {
+ VIR_TEST_DEBUG("\nThe pre-shared key is not present in the migration cookie.");
+ return -1;
+ }
+
+ if (strlen(key) != expected_key_len) {
+ VIR_TEST_DEBUG("\nThe length of the pre-shared key is incorrect.");
+ return -1;
+ }
+
+ /* Check the characters of the key */
+ for (i = 0; i < expected_key_len; i++) {
+ if (!g_ascii_isxdigit(key[i])) {
+ VIR_TEST_DEBUG("\nThe key contains non-hex characters");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+static int
+testQemuMigrationCookiePSKAttribute(const void *opaque)
+{
+ struct testQemuMigrationCookieData *data = (struct testQemuMigrationCookieData *) opaque;
+ g_autoptr(qemuMigrationCookie) cookie = NULL;
+ qemuDomainObjPrivate *priv;
+
+ /* if the VM object parsing step failed there's nothing this test can do */
+ if (!data->vm) {
+ VIR_TEST_DEBUG("\nmissing VM object\n");
+ return -1;
+ }
+ priv = data->vm->privateData;
+
+ if (!(cookie = qemuMigrationCookieNew(data->vm->def, NULL)))
+ return -1;
+
+ g_free(cookie->localHostname);
+ cookie->localHostname = g_strdup("hostname2");
+
+ if (virUUIDParse("8b3f4dc4-6a8e-5f9b-94a5-4c35babd8d95", cookie->localHostuuid) < 0) {
+ VIR_TEST_DEBUG("\nfailed to parse fake UUID");
+ return -1;
+ }
+
+ /* Format the migration cookie at the source */
+ if (qemuMigrationCookieFormat(cookie,
+ &driver,
+ data->vm,
+ data->cookiePopulateParty,
+ &data->xmlstr,
+ &data->xmlstrlen,
+ data->cookiePopulateFlags) < 0) {
+ VIR_TEST_DEBUG("\nfailed to populate and format qemu migration cookie");
+ return -1;
+ }
+
+ /* Check for the <migration-key> element in the generated migration cookie XML */
+ if (!strstr(data->xmlstr, "<migration-key>")) {
+ VIR_TEST_DEBUG("\nthe migration cookie is missing the migration-key element:\n%s\n",
+ data->xmlstr);
+ return -1;
+ }
+
+ /* Parse the migration cookie at the destination */
+ if (!(data->cookie = qemuMigrationCookieParse(&driver,
+ data->vm,
+ data->vm->def,
+ NULL,
+ priv->qemuCaps,
+ data->xmlstr,
+ data->xmlstrlen,
+ data->cookieParseFlags))) {
+ VIR_TEST_DEBUG("\nfailed to parse qemu migration cookie:\n%s\n", data->xmlstr);
+ return -1;
+ }
+
+ if (testQemuMigrationCookiePSKValidate(data->cookie->tlsPSK) < 0)
+ return -1;
+
+ return 0;
+}
+
+
static int
testQemuMigrationCookiePopulate(const void *opaque)
{
@@ -418,6 +512,32 @@ testQemuMigrationCookieXML2XMLBitmaps(const char *name,
return ret;
}
+/* tests the generation and persistence of the pre-shared keys */
+static int
+testQemuMigrationCookiePSK(const char *domxml)
+{
+ struct testQemuMigrationCookieData *data = g_new0(struct testQemuMigrationCookieData, 1);
+ int ret = 0;
+
+ data->cookiePopulateFlags = QEMU_MIGRATION_COOKIE_TLS_PSK;
+ data->cookiePopulateParty = QEMU_MIGRATION_SOURCE;
+ data->cookieParseFlags = QEMU_MIGRATION_COOKIE_TLS_PSK;
+ data->inStatus = g_strconcat(abs_srcdir, "/", domxml, NULL);
+
+ /* load status XML as domain object */
+ if (testQemuMigrationCookieDomInit(data) < 0)
+ ret = -1;
+
+ /* test PSK generation and persistence */
+ if (virTestRun("qemumigrationcookie-psk-lifecycle",
+ testQemuMigrationCookiePSKAttribute, data) < 0)
+ ret = -1;
+
+ testQemuMigrationCookieDataFree(data);
+
+ return ret;
+}
+
static int
mymain(void)
@@ -448,6 +568,9 @@ mymain(void)
if (testQemuMigrationCookieXML2XMLBitmaps("nbd-bitmaps", "qemustatusxml2xmldata/migration-out-nbd-bitmaps-in.xml", 0) < 0)
ret = -1;
+ if (testQemuMigrationCookiePSK("qemustatusxml2xmldata/modern-in.xml") < 0)
+ ret = -1;
+
virBufferFreeAndReset(&testnamebuf);
cleanup:
diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c
index e5e3342b53..b0e0d41895 100644
--- a/tests/testutilsqemu.c
+++ b/tests/testutilsqemu.c
@@ -297,6 +297,7 @@ qemuTestCapsCacheInsert(virFileCache *cache,
#define STATEDIRTEMPLATE abs_builddir "/qemustatedir-XXXXXX"
#define CONFIGDIRTEMPLATE abs_builddir "/qemuconfigdir-XXXXXX"
+#define TLSPSKDIRTEMPLATE abs_builddir "/pskstatedir-XXXXXX"
int qemuTestDriverInit(virQEMUDriver *driver)
{
@@ -304,6 +305,7 @@ int qemuTestDriverInit(virQEMUDriver *driver)
virSecurityManager *mgr = NULL;
char statedir[] = STATEDIRTEMPLATE;
char configdir[] = CONFIGDIRTEMPLATE;
+ char tlspskdir[] = TLSPSKDIRTEMPLATE;
memset(driver, 0, sizeof(*driver));
@@ -328,6 +330,7 @@ int qemuTestDriverInit(virQEMUDriver *driver)
* dirs. */
VIR_FREE(cfg->stateDir);
VIR_FREE(cfg->configDir);
+ VIR_FREE(cfg->tlsPSKStateDir);
/* Override paths to ensure predictable output
*
@@ -367,6 +370,13 @@ int qemuTestDriverInit(virQEMUDriver *driver)
cfg->configDir = g_strdup(configdir);
+ if (!g_mkdtemp(tlspskdir)) {
+ fprintf(stderr, "Cannot create fake tlsPSKStateDir");
+ goto error;
+ }
+
+ cfg->tlsPSKStateDir = g_strdup(tlspskdir);
+
driver->caps = testQemuCapsInit();
if (!driver->caps)
goto error;
@@ -433,6 +443,8 @@ int qemuTestDriverInit(virQEMUDriver *driver)
cfg->dumpGuestCore = false;
+ cfg->migrateTLSPSKLength = 32;
+
driver->privileged = true;
return 0;
--
2.43.7
On Wed, Jul 29, 2026 at 08:58:59 +0000, Abhisek Panda wrote: > In the case of TLS-PSK-enabled migration, Libvirt manages the lifecycle > of the pre-shared key. Add a new test scenario to the migration cookie > test suite to validate the generation of pre-shared key when the > QEMU_MIGRATION_COOKIE_TLS_PSK flag is set. In addition, the test also > checks the length and the hexadecimal encoding of the pre-shared key. > > Signed-off-by: Abhisek Panda <abhisek.panda1@nutanix.com> > --- > tests/qemumigrationcookiexmltest.c | 123 +++++++++++++++++++++++++++++ > tests/testutilsqemu.c | 12 +++ > 2 files changed, 135 insertions(+) Looks reasonable; but I'll do a once-over once other things are solved
© 2016 - 2026 Red Hat, Inc.