]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
peer2peer migration: allow connecting to local sockets
authorMartin Kletzander <mkletzan@redhat.com>
Mon, 24 Aug 2020 22:31:23 +0000 (00:31 +0200)
committerMartin Kletzander <mkletzan@redhat.com>
Fri, 4 Sep 2020 08:20:49 +0000 (10:20 +0200)
Local socket connections were outright disabled because there was no "server"
part in the URI.  However, given how requirements and usage scenarios are
evolving, some management apps might need the source libvirt daemon to connect
to the destination daemon over a UNIX socket for peer2peer migration.  Since we
cannot know where the socket leads (whether the same daemon or not) let's decide
that based on whether the socket path is non-standard, or rather explicitly
specified in the URI.  Checking non-standard path would require to ask the
daemon for configuration and the only misuse that it would prevent would be a
pretty weird one.  And that's not worth it.  The assumption is that whenever
someone uses explicit UNIX socket paths in the URI for migration they better
know what they are doing.

Partially resolves: https://bugzilla.redhat.com/1638889

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
docs/manpages/virsh.rst
src/libvirt-domain.c
src/remote/remote_driver.c
src/util/viruri.c
src/util/viruri.h
tests/virmigtest.c

index c64a47c5a59b6f72384eb1c097ec33d76804064b..a0d6c3fadda61a9c4d8997d652e7c05e9329d353 100644 (file)
@@ -3235,6 +3235,15 @@ has different semantics:
 
 * peer2peer migration: the *desturi* is an address of the target host as seen from the source machine.
 
+In a special circumstance where you require a complete control of the connection
+and/or libvirt does not have network access to the remote side you can use a
+UNIX transport in the URI and specify a socket path in the query, for example
+with the qemu driver you could use this:
+
+.. code-block::
+
+      qemu+unix:///system?socket=/path/to/socket
+
 When *migrateuri* is not specified, libvirt will automatically determine the
 hypervisor specific URI.  Some hypervisors, including QEMU, have an optional
 "migration_host" configuration parameter (useful when the host has multiple
index da5a21e4c4d445d186642e4b721ba06df8f20e62..cde86c77e892c5f73f1117a15eaa1aa7f5faea61 100644 (file)
@@ -3276,7 +3276,13 @@ virDomainMigrateCheckNotLocal(const char *dconnuri)
 
     if (!(tempuri = virURIParse(dconnuri)))
         return -1;
-    if (!tempuri->server || STRPREFIX(tempuri->server, "localhost")) {
+
+    /*
+     * If someone migrates explicitly to a unix socket, then they have to know
+     * what they are doing and it most probably was not a mistake.
+     */
+    if ((tempuri->server && STRPREFIX(tempuri->server, "localhost")) ||
+        (!tempuri->server && !virURICheckUnixSocket(tempuri))) {
         virReportInvalidArg(dconnuri, "%s",
                             _("Attempt to migrate guest to the same host"));
         return -1;
index a9f76ede5a91193e021bcc3974dcf89f74be421e..8c055e03478ac60d4b2e59f9bbbb746dd696e906 100644 (file)
@@ -1429,9 +1429,13 @@ remoteConnectOpen(virConnectPtr conn,
 
         /* If there's a driver registered we must defer to that.
          * If there isn't a driver, we must connect in "direct"
-         * mode - see doRemoteOpen */
+         * mode - see doRemoteOpen.
+         * One exception is if we are trying to connect to an
+         * unknown socket path as that might be proxied to remote
+         * host */
         if (!conn->uri->server &&
-            virHasDriverForURIScheme(driver)) {
+            virHasDriverForURIScheme(driver) &&
+            !virURICheckUnixSocket(conn->uri)) {
             ret = VIR_DRV_OPEN_DECLINED;
             goto cleanup;
         }
index 0112186fdbc4ab38bc9bfc623ba2f22433db7c4c..dd7559662bd2ac886486c8dea3bdc69e7c5d21a6 100644 (file)
@@ -393,3 +393,33 @@ virURIGetParam(virURIPtr uri, const char *name)
                    _("Missing URI parameter '%s'"), name);
     return NULL;
 }
+
+
+/**
+ * virURICheckUnixSocket:
+ * @uri: URI to check
+ *
+ * Check if the URI looks like it refers to a non-standard socket path.  In such
+ * scenario the socket might be proxied to a remote server even though the URI
+ * looks like it is only local.
+ *
+ * Returns: true if the URI might be proxied to a remote server
+ */
+bool
+virURICheckUnixSocket(virURIPtr uri)
+{
+    size_t i = 0;
+
+    if (!uri->scheme)
+        return false;
+
+    if (STRNEQ_NULLABLE(strchr(uri->scheme, '+'), "+unix"))
+        return false;
+
+    for (i = 0; i < uri->paramsCount; i++) {
+        if (STREQ(uri->params[i].name, "socket"))
+            return true;
+    }
+
+    return false;
+}
index e607ecc109e720e3f23d65b0ab29470064d89e22..dc4907b55059e5700ea474fa47d9ef363ca0ea7a 100644 (file)
@@ -62,4 +62,6 @@ int virURIResolveAlias(virConfPtr conf, const char *alias, char **uri);
 
 const char *virURIGetParam(virURIPtr uri, const char *name);
 
+bool virURICheckUnixSocket(virURIPtr uri);
+
 #define VIR_URI_SERVER(uri) ((uri) && (uri)->server ? (uri)->server : "localhost")
index df8d51bab94bc1c13a3db94298d0a50f5aed0de3..af6643397e903f86287a9749172ea8347c5ddf66 100644 (file)
@@ -83,7 +83,7 @@ mymain(void)
 
     TEST("scheme://some.cryptorandom.fqdn.tld");
 
-    TEST_FAIL("hehe+unix:///?socket=/path/to/some-sock");
+    TEST("hehe+unix:///?socket=/path/to/some-sock");
 
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }