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