b38b0f
From cd8ddc9c29115f6f8428fc17fbded67f0ce99004 Mon Sep 17 00:00:00 2001
b38b0f
From: Pino Toscano <ptoscano@redhat.com>
b38b0f
Date: Mon, 8 Jul 2019 15:25:57 +0100
b38b0f
Subject: [PATCH 11/39] block/ssh: Implement .bdrv_refresh_filename()
b38b0f
MIME-Version: 1.0
b38b0f
Content-Type: text/plain; charset=UTF-8
b38b0f
Content-Transfer-Encoding: 8bit
b38b0f
b38b0f
RH-Author: Pino Toscano <ptoscano@redhat.com>
b38b0f
Message-id: <20190708152601.21123-7-ptoscano@redhat.com>
b38b0f
Patchwork-id: 89417
b38b0f
O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 06/10] block/ssh: Implement .bdrv_refresh_filename()
b38b0f
Bugzilla: 1513367
b38b0f
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
b38b0f
RH-Acked-by: Max Reitz <mreitz@redhat.com>
b38b0f
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
b38b0f
RH-Acked-by: Markus Armbruster <armbru@redhat.com>
b38b0f
b38b0f
From: Max Reitz <mreitz@redhat.com>
b38b0f
b38b0f
This requires some changes to keep iotests 104 and 207 working.
b38b0f
b38b0f
qemu-img info in 104 will now return a filename including the user name
b38b0f
and the port, which need to be filtered by adjusting REMOTE_TEST_DIR in
b38b0f
common.rc.  This additional information has to be marked optional,
b38b0f
however (which is simple as REMOTE_TEST_DIR is a regex), because
b38b0f
otherwise 197 and 215 would fail: They use it (indirectly) to filter
b38b0f
qemu-img create output which contains a backing filename they have
b38b0f
passed to it -- which probably does not contain a user name or port
b38b0f
number.
b38b0f
b38b0f
The problem in 207 is a nice one to have: qemu-img info used to return
b38b0f
json:{} filenames, but with this patch it returns nice plain ones.  We
b38b0f
now need to adjust the filtering to hide the user name (and port number
b38b0f
while we are at it).  The simplest way to do this is to include both in
b38b0f
iotests.remote_filename() so that bdrv_refresh_filename() will not
b38b0f
change it, and then iotests.img_info_log() will filter it correctly
b38b0f
automatically.
b38b0f
b38b0f
Signed-off-by: Max Reitz <mreitz@redhat.com>
b38b0f
Tested-by: Richard W.M. Jones <rjones@redhat.com>
b38b0f
Message-id: 20190225190828.17726-2-mreitz@redhat.com
b38b0f
Signed-off-by: Max Reitz <mreitz@redhat.com>
b38b0f
(cherry picked from commit b8c1f90118ee81090ff9093790f88bf335132814)
b38b0f
This patch was modified for the lack of 998b3a1e5a2dd23bf89a853e15fab,
b38b0f
by adding the 'QDict *options' parameter to ssh_refresh_filename(),
b38b0f
matching the requested prototype, and setting bs->full_open_options to
b38b0f
the specified option (following the hint of Max Reitz).
b38b0f
Signed-off-by: Pino Toscano <ptoscano@redhat.com>
b38b0f
b38b0f
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
b38b0f
---
b38b0f
 block/ssh.c                   | 55 +++++++++++++++++++++++++++++++++++++++----
b38b0f
 tests/qemu-iotests/207        | 10 ++++----
b38b0f
 tests/qemu-iotests/207.out    | 10 ++++----
b38b0f
 tests/qemu-iotests/common.rc  |  2 +-
b38b0f
 tests/qemu-iotests/iotests.py |  2 +-
b38b0f
 5 files changed, 62 insertions(+), 17 deletions(-)
b38b0f
b38b0f
diff --git a/block/ssh.c b/block/ssh.c
b38b0f
index 89abce0..f0ef874 100644
b38b0f
--- a/block/ssh.c
b38b0f
+++ b/block/ssh.c
b38b0f
@@ -75,6 +75,14 @@ typedef struct BDRVSSHState {
b38b0f
 
b38b0f
     /* Used to warn if 'flush' is not supported. */
b38b0f
     bool unsafe_flush_warning;
b38b0f
+
b38b0f
+    /*
b38b0f
+     * Store the user name for ssh_refresh_filename() because the
b38b0f
+     * default depends on the system you are on -- therefore, when we
b38b0f
+     * generate a filename, it should always contain the user name we
b38b0f
+     * are actually using.
b38b0f
+     */
b38b0f
+    char *user;
b38b0f
 } BDRVSSHState;
b38b0f
 
b38b0f
 static void ssh_state_init(BDRVSSHState *s)
b38b0f
@@ -87,6 +95,8 @@ static void ssh_state_init(BDRVSSHState *s)
b38b0f
 
b38b0f
 static void ssh_state_free(BDRVSSHState *s)
b38b0f
 {
b38b0f
+    g_free(s->user);
b38b0f
+
b38b0f
     if (s->sftp_handle) {
b38b0f
         libssh2_sftp_close(s->sftp_handle);
b38b0f
     }
b38b0f
@@ -628,14 +638,13 @@ static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts,
b38b0f
                           int ssh_flags, int creat_mode, Error **errp)
b38b0f
 {
b38b0f
     int r, ret;
b38b0f
-    const char *user;
b38b0f
     long port = 0;
b38b0f
 
b38b0f
     if (opts->has_user) {
b38b0f
-        user = opts->user;
b38b0f
+        s->user = g_strdup(opts->user);
b38b0f
     } else {
b38b0f
-        user = g_get_user_name();
b38b0f
-        if (!user) {
b38b0f
+        s->user = g_strdup(g_get_user_name());
b38b0f
+        if (!s->user) {
b38b0f
             error_setg_errno(errp, errno, "Can't get user name");
b38b0f
             ret = -errno;
b38b0f
             goto err;
b38b0f
@@ -685,7 +694,7 @@ static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts,
b38b0f
     }
b38b0f
 
b38b0f
     /* Authenticate. */
b38b0f
-    ret = authenticate(s, user, errp);
b38b0f
+    ret = authenticate(s, s->user, errp);
b38b0f
     if (ret < 0) {
b38b0f
         goto err;
b38b0f
     }
b38b0f
@@ -1240,6 +1249,41 @@ static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
b38b0f
     return ssh_grow_file(s, offset, errp);
b38b0f
 }
b38b0f
 
b38b0f
+static void ssh_refresh_filename(BlockDriverState *bs, QDict *options)
b38b0f
+{
b38b0f
+    BDRVSSHState *s = bs->opaque;
b38b0f
+    const char *path, *host_key_check;
b38b0f
+    int ret;
b38b0f
+
b38b0f
+    qdict_put_str(options, "driver", "ssh");
b38b0f
+    bs->full_open_options = qobject_ref(options);
b38b0f
+
b38b0f
+    /*
b38b0f
+     * None of these options can be represented in a plain "host:port"
b38b0f
+     * format, so if any was given, we have to abort.
b38b0f
+     */
b38b0f
+    if (s->inet->has_ipv4 || s->inet->has_ipv6 || s->inet->has_to ||
b38b0f
+        s->inet->has_numeric)
b38b0f
+    {
b38b0f
+        return;
b38b0f
+    }
b38b0f
+
b38b0f
+    path = qdict_get_try_str(bs->full_open_options, "path");
b38b0f
+    assert(path); /* mandatory option */
b38b0f
+
b38b0f
+    host_key_check = qdict_get_try_str(bs->full_open_options, "host_key_check");
b38b0f
+
b38b0f
+    ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
b38b0f
+                   "ssh://%s@%s:%s%s%s%s",
b38b0f
+                   s->user, s->inet->host, s->inet->port, path,
b38b0f
+                   host_key_check ? "?host_key_check=" : "",
b38b0f
+                   host_key_check ?: "");
b38b0f
+    if (ret >= sizeof(bs->exact_filename)) {
b38b0f
+        /* An overflow makes the filename unusable, so do not report any */
b38b0f
+        bs->exact_filename[0] = '\0';
b38b0f
+    }
b38b0f
+}
b38b0f
+
b38b0f
 static BlockDriver bdrv_ssh = {
b38b0f
     .format_name                  = "ssh",
b38b0f
     .protocol_name                = "ssh",
b38b0f
@@ -1255,6 +1299,7 @@ static BlockDriver bdrv_ssh = {
b38b0f
     .bdrv_getlength               = ssh_getlength,
b38b0f
     .bdrv_co_truncate             = ssh_co_truncate,
b38b0f
     .bdrv_co_flush_to_disk        = ssh_co_flush,
b38b0f
+    .bdrv_refresh_filename        = ssh_refresh_filename,
b38b0f
     .create_opts                  = &ssh_create_opts,
b38b0f
 };
b38b0f
 
b38b0f
diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
b38b0f
index 444ae23..8202bd1 100755
b38b0f
--- a/tests/qemu-iotests/207
b38b0f
+++ b/tests/qemu-iotests/207
b38b0f
@@ -62,7 +62,7 @@ with iotests.FilePath('t.img') as disk_path, \
b38b0f
                           'size': 4194304 })
b38b0f
     vm.shutdown()
b38b0f
 
b38b0f
-    iotests.img_info_log(remote_path, filter_path=disk_path)
b38b0f
+    iotests.img_info_log(remote_path)
b38b0f
     iotests.log("")
b38b0f
     iotests.img_info_log(disk_path)
b38b0f
 
b38b0f
@@ -87,7 +87,7 @@ with iotests.FilePath('t.img') as disk_path, \
b38b0f
                           'size': 8388608 })
b38b0f
     vm.shutdown()
b38b0f
 
b38b0f
-    iotests.img_info_log(remote_path, filter_path=disk_path)
b38b0f
+    iotests.img_info_log(remote_path)
b38b0f
 
b38b0f
     vm.launch()
b38b0f
     blockdev_create(vm, { 'driver': 'ssh',
b38b0f
@@ -104,7 +104,7 @@ with iotests.FilePath('t.img') as disk_path, \
b38b0f
                           'size': 4194304 })
b38b0f
     vm.shutdown()
b38b0f
 
b38b0f
-    iotests.img_info_log(remote_path, filter_path=disk_path)
b38b0f
+    iotests.img_info_log(remote_path)
b38b0f
 
b38b0f
     md5_key = subprocess.check_output(
b38b0f
         'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' +
b38b0f
@@ -142,7 +142,7 @@ with iotests.FilePath('t.img') as disk_path, \
b38b0f
                           'size': 8388608 })
b38b0f
     vm.shutdown()
b38b0f
 
b38b0f
-    iotests.img_info_log(remote_path, filter_path=disk_path)
b38b0f
+    iotests.img_info_log(remote_path)
b38b0f
 
b38b0f
     sha1_key = subprocess.check_output(
b38b0f
         'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' +
b38b0f
@@ -180,7 +180,7 @@ with iotests.FilePath('t.img') as disk_path, \
b38b0f
                           'size': 4194304 })
b38b0f
     vm.shutdown()
b38b0f
 
b38b0f
-    iotests.img_info_log(remote_path, filter_path=disk_path)
b38b0f
+    iotests.img_info_log(remote_path)
b38b0f
 
b38b0f
     #
b38b0f
     # Invalid path and user
b38b0f
diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out
b38b0f
index 078b7e6..fc131a6 100644
b38b0f
--- a/tests/qemu-iotests/207.out
b38b0f
+++ b/tests/qemu-iotests/207.out
b38b0f
@@ -5,7 +5,7 @@
b38b0f
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
b38b0f
 {u'return': {}}
b38b0f
 
b38b0f
-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
b38b0f
+image: TEST_IMG
b38b0f
 file format: IMGFMT
b38b0f
 virtual size: 4.0M (4194304 bytes)
b38b0f
 
b38b0f
@@ -21,7 +21,7 @@ virtual size: 4.0M (4194304 bytes)
b38b0f
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
b38b0f
 {u'return': {}}
b38b0f
 
b38b0f
-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
b38b0f
+image: TEST_IMG
b38b0f
 file format: IMGFMT
b38b0f
 virtual size: 8.0M (8388608 bytes)
b38b0f
 
b38b0f
@@ -30,7 +30,7 @@ virtual size: 8.0M (8388608 bytes)
b38b0f
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
b38b0f
 {u'return': {}}
b38b0f
 
b38b0f
-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
b38b0f
+image: TEST_IMG
b38b0f
 file format: IMGFMT
b38b0f
 virtual size: 4.0M (4194304 bytes)
b38b0f
 
b38b0f
@@ -45,7 +45,7 @@ Job failed: remote host key does not match host_key_check 'wrong'
b38b0f
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
b38b0f
 {u'return': {}}
b38b0f
 
b38b0f
-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
b38b0f
+image: TEST_IMG
b38b0f
 file format: IMGFMT
b38b0f
 virtual size: 8.0M (8388608 bytes)
b38b0f
 
b38b0f
@@ -60,7 +60,7 @@ Job failed: remote host key does not match host_key_check 'wrong'
b38b0f
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
b38b0f
 {u'return': {}}
b38b0f
 
b38b0f
-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
b38b0f
+image: TEST_IMG
b38b0f
 file format: IMGFMT
b38b0f
 virtual size: 4.0M (4194304 bytes)
b38b0f
 
b38b0f
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
b38b0f
index 6490c8d..9ff8fa1 100644
b38b0f
--- a/tests/qemu-iotests/common.rc
b38b0f
+++ b/tests/qemu-iotests/common.rc
b38b0f
@@ -145,7 +145,7 @@ else
b38b0f
         TEST_IMG="nbd:127.0.0.1:10810"
b38b0f
     elif [ "$IMGPROTO" = "ssh" ]; then
b38b0f
         TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
b38b0f
-        REMOTE_TEST_DIR="ssh://127.0.0.1$TEST_DIR"
b38b0f
+        REMOTE_TEST_DIR="ssh://\\($USER@\\)\\?127.0.0.1\\(:[0-9]\\+\\)\\?$TEST_DIR"
b38b0f
         TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE"
b38b0f
     elif [ "$IMGPROTO" = "nfs" ]; then
b38b0f
         TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
b38b0f
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
b38b0f
index 4e67fbb..0f6980a 100644
b38b0f
--- a/tests/qemu-iotests/iotests.py
b38b0f
+++ b/tests/qemu-iotests/iotests.py
b38b0f
@@ -325,7 +325,7 @@ def remote_filename(path):
b38b0f
     if imgproto == 'file':
b38b0f
         return path
b38b0f
     elif imgproto == 'ssh':
b38b0f
-        return "ssh://127.0.0.1%s" % (path)
b38b0f
+        return "ssh://%s@127.0.0.1:22%s" % (os.environ.get('USER'), path)
b38b0f
     else:
b38b0f
         raise Exception("Protocol %s not supported" % (imgproto))
b38b0f
 
b38b0f
-- 
b38b0f
1.8.3.1
b38b0f