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