1 | The following changes since commit 2b483739791b33c46e6084b51edcf62107058ae1: | 1 | The following changes since commit 834eddf22ec762839b724538c7be1d1d3b2d9d3b: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20170904-2' into staging (2017-09-04 17:21:24 +0100) | 3 | Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging (2018-03-13 10:49:02 +0000) |
4 | 4 | ||
5 | are available in the git repository at: | 5 | are available in the git repository at: |
6 | 6 | ||
7 | git://github.com/stefanha/qemu.git tags/block-pull-request | 7 | git://github.com/codyprime/qemu-kvm-jtc.git tags/block-pull-request |
8 | 8 | ||
9 | for you to fetch changes up to b461151ff31c7925f271c297e8abed20231ac7d3: | 9 | for you to fetch changes up to 44acd46f60ce6f16d369cd443e77949deca56a2c: |
10 | 10 | ||
11 | block: document semantics of bdrv_co_preadv|pwritev (2017-09-05 11:07:02 +0100) | 11 | block: include original filename when reporting invalid URIs (2018-03-13 08:06:55 -0400) |
12 | 12 | ||
13 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
14 | 14 | Block patch | |
15 | ---------------------------------------------------------------- | 15 | ---------------------------------------------------------------- |
16 | 16 | ||
17 | Daniel P. Berrange (1): | 17 | Daniel P. Berrangé (1): |
18 | block: document semantics of bdrv_co_preadv|pwritev | 18 | block: include original filename when reporting invalid URIs |
19 | 19 | ||
20 | Stefan Hajnoczi (3): | 20 | block/gluster.c | 2 +- |
21 | qemu.py: make VM() a context manager | 21 | block/sheepdog.c | 2 +- |
22 | iotests.py: add FilePath context manager | 22 | 2 files changed, 2 insertions(+), 2 deletions(-) |
23 | qemu-iotests: use context managers for resource cleanup in 194 | ||
24 | |||
25 | include/block/block_int.h | 31 +++++++++++ | ||
26 | scripts/qemu.py | 16 +++++- | ||
27 | tests/qemu-iotests/194 | 117 +++++++++++++++++++++--------------------- | ||
28 | tests/qemu-iotests/iotests.py | 26 ++++++++++ | ||
29 | 4 files changed, 130 insertions(+), 60 deletions(-) | ||
30 | 23 | ||
31 | -- | 24 | -- |
32 | 2.13.5 | 25 | 2.13.6 |
33 | 26 | ||
34 | 27 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | There are a number of ways to ensure that the QEMU process is shut down | ||
2 | when the test ends, including atexit.register(), try: finally:, or | ||
3 | unittest.teardown() methods. All of these require extra code and the | ||
4 | programmer must remember to add vm.shutdown(). | ||
5 | 1 | ||
6 | A nice solution is context managers: | ||
7 | |||
8 | with VM(binary) as vm: | ||
9 | ... | ||
10 | # vm is guaranteed to be shut down here | ||
11 | |||
12 | Cc: Eduardo Habkost <ehabkost@redhat.com> | ||
13 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
14 | Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> | ||
15 | Message-id: 20170824072202.26818-2-stefanha@redhat.com | ||
16 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
17 | --- | ||
18 | scripts/qemu.py | 16 +++++++++++++++- | ||
19 | 1 file changed, 15 insertions(+), 1 deletion(-) | ||
20 | |||
21 | diff --git a/scripts/qemu.py b/scripts/qemu.py | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/scripts/qemu.py | ||
24 | +++ b/scripts/qemu.py | ||
25 | @@ -XXX,XX +XXX,XX @@ import qmp.qmp | ||
26 | |||
27 | |||
28 | class QEMUMachine(object): | ||
29 | - '''A QEMU VM''' | ||
30 | + '''A QEMU VM | ||
31 | + | ||
32 | + Use this object as a context manager to ensure the QEMU process terminates:: | ||
33 | + | ||
34 | + with VM(binary) as vm: | ||
35 | + ... | ||
36 | + # vm is guaranteed to be shut down here | ||
37 | + ''' | ||
38 | |||
39 | def __init__(self, binary, args=[], wrapper=[], name=None, test_dir="/var/tmp", | ||
40 | monitor_address=None, socket_scm_helper=None, debug=False): | ||
41 | @@ -XXX,XX +XXX,XX @@ class QEMUMachine(object): | ||
42 | self._socket_scm_helper = socket_scm_helper | ||
43 | self._debug = debug | ||
44 | |||
45 | + def __enter__(self): | ||
46 | + return self | ||
47 | + | ||
48 | + def __exit__(self, exc_type, exc_val, exc_tb): | ||
49 | + self.shutdown() | ||
50 | + return False | ||
51 | + | ||
52 | # This can be used to add an unused monitor instance. | ||
53 | def add_monitor_telnet(self, ip, port): | ||
54 | args = 'tcp:%s:%d,server,nowait,telnet' % (ip, port) | ||
55 | -- | ||
56 | 2.13.5 | ||
57 | |||
58 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | The scratch/ (TEST_DIR) directory is not automatically cleaned up after | ||
2 | test execution. It is the responsibility of tests to remove any files | ||
3 | they create. | ||
4 | 1 | ||
5 | A nice way of doing this is to declare files at the beginning of the | ||
6 | test and automatically remove them with a context manager: | ||
7 | |||
8 | with iotests.FilePath('test.img') as img_path: | ||
9 | qemu_img(...) | ||
10 | qemu_io(...) | ||
11 | # img_path is guaranteed to be deleted here | ||
12 | |||
13 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
14 | Message-id: 20170824072202.26818-3-stefanha@redhat.com | ||
15 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
16 | --- | ||
17 | tests/qemu-iotests/iotests.py | 26 ++++++++++++++++++++++++++ | ||
18 | 1 file changed, 26 insertions(+) | ||
19 | |||
20 | diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py | ||
21 | index XXXXXXX..XXXXXXX 100644 | ||
22 | --- a/tests/qemu-iotests/iotests.py | ||
23 | +++ b/tests/qemu-iotests/iotests.py | ||
24 | @@ -XXX,XX +XXX,XX @@ class Timeout: | ||
25 | def timeout(self, signum, frame): | ||
26 | raise Exception(self.errmsg) | ||
27 | |||
28 | + | ||
29 | +class FilePath(object): | ||
30 | + '''An auto-generated filename that cleans itself up. | ||
31 | + | ||
32 | + Use this context manager to generate filenames and ensure that the file | ||
33 | + gets deleted:: | ||
34 | + | ||
35 | + with TestFilePath('test.img') as img_path: | ||
36 | + qemu_img('create', img_path, '1G') | ||
37 | + # migration_sock_path is automatically deleted | ||
38 | + ''' | ||
39 | + def __init__(self, name): | ||
40 | + filename = '{0}-{1}'.format(os.getpid(), name) | ||
41 | + self.path = os.path.join(test_dir, filename) | ||
42 | + | ||
43 | + def __enter__(self): | ||
44 | + return self.path | ||
45 | + | ||
46 | + def __exit__(self, exc_type, exc_val, exc_tb): | ||
47 | + try: | ||
48 | + os.remove(self.path) | ||
49 | + except OSError: | ||
50 | + pass | ||
51 | + return False | ||
52 | + | ||
53 | + | ||
54 | class VM(qtest.QEMUQtestMachine): | ||
55 | '''A QEMU VM''' | ||
56 | |||
57 | -- | ||
58 | 2.13.5 | ||
59 | |||
60 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Switch from atexit.register() to a more elegant idiom of declaring | ||
2 | resources in a with statement: | ||
3 | 1 | ||
4 | with FilePath('monitor.sock') as monitor_path, | ||
5 | VM() as vm: | ||
6 | ... | ||
7 | |||
8 | The files and VMs will be automatically cleaned up whether the test | ||
9 | passes or fails. | ||
10 | |||
11 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
12 | Message-id: 20170824072202.26818-4-stefanha@redhat.com | ||
13 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
14 | --- | ||
15 | tests/qemu-iotests/194 | 117 ++++++++++++++++++++++++------------------------- | ||
16 | 1 file changed, 58 insertions(+), 59 deletions(-) | ||
17 | |||
18 | diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194 | ||
19 | index XXXXXXX..XXXXXXX 100755 | ||
20 | --- a/tests/qemu-iotests/194 | ||
21 | +++ b/tests/qemu-iotests/194 | ||
22 | @@ -XXX,XX +XXX,XX @@ | ||
23 | # | ||
24 | # Non-shared storage migration test using NBD server and drive-mirror | ||
25 | |||
26 | -import os | ||
27 | -import atexit | ||
28 | import iotests | ||
29 | |||
30 | iotests.verify_platform(['linux']) | ||
31 | |||
32 | -img_size = '1G' | ||
33 | -source_img_path = os.path.join(iotests.test_dir, 'source.img') | ||
34 | -dest_img_path = os.path.join(iotests.test_dir, 'dest.img') | ||
35 | -iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, source_img_path, img_size) | ||
36 | -iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, dest_img_path, img_size) | ||
37 | - | ||
38 | -iotests.log('Launching VMs...') | ||
39 | -migration_sock_path = os.path.join(iotests.test_dir, 'migration.sock') | ||
40 | -nbd_sock_path = os.path.join(iotests.test_dir, 'nbd.sock') | ||
41 | -source_vm = iotests.VM('source').add_drive(source_img_path) | ||
42 | -dest_vm = (iotests.VM('dest').add_drive(dest_img_path) | ||
43 | - .add_incoming('unix:{0}'.format(migration_sock_path))) | ||
44 | -source_vm.launch() | ||
45 | -atexit.register(source_vm.shutdown) | ||
46 | -dest_vm.launch() | ||
47 | -atexit.register(dest_vm.shutdown) | ||
48 | - | ||
49 | -iotests.log('Launching NBD server on destination...') | ||
50 | -iotests.log(dest_vm.qmp('nbd-server-start', addr={'type': 'unix', 'data': {'path': nbd_sock_path}})) | ||
51 | -iotests.log(dest_vm.qmp('nbd-server-add', device='drive0', writable=True)) | ||
52 | - | ||
53 | -iotests.log('Starting `drive-mirror` on source...') | ||
54 | -iotests.log(source_vm.qmp( | ||
55 | - 'drive-mirror', | ||
56 | - device='drive0', | ||
57 | - target='nbd+unix:///drive0?socket={0}'.format(nbd_sock_path), | ||
58 | - sync='full', | ||
59 | - format='raw', # always raw, the server handles the format | ||
60 | - mode='existing', | ||
61 | - job_id='mirror-job0')) | ||
62 | - | ||
63 | -iotests.log('Waiting for `drive-mirror` to complete...') | ||
64 | -iotests.log(source_vm.event_wait('BLOCK_JOB_READY'), | ||
65 | - filters=[iotests.filter_qmp_event]) | ||
66 | - | ||
67 | -iotests.log('Starting migration...') | ||
68 | -source_vm.qmp('migrate-set-capabilities', | ||
69 | - capabilities=[{'capability': 'events', 'state': True}]) | ||
70 | -dest_vm.qmp('migrate-set-capabilities', | ||
71 | - capabilities=[{'capability': 'events', 'state': True}]) | ||
72 | -iotests.log(source_vm.qmp('migrate', uri='unix:{0}'.format(migration_sock_path))) | ||
73 | - | ||
74 | -while True: | ||
75 | - event1 = source_vm.event_wait('MIGRATION') | ||
76 | - iotests.log(event1, filters=[iotests.filter_qmp_event]) | ||
77 | - if event1['data']['status'] in ('completed', 'failed'): | ||
78 | - iotests.log('Gracefully ending the `drive-mirror` job on source...') | ||
79 | - iotests.log(source_vm.qmp('block-job-cancel', device='mirror-job0')) | ||
80 | - break | ||
81 | - | ||
82 | -while True: | ||
83 | - event2 = source_vm.event_wait('BLOCK_JOB_COMPLETED') | ||
84 | - iotests.log(event2, filters=[iotests.filter_qmp_event]) | ||
85 | - if event2['event'] == 'BLOCK_JOB_COMPLETED': | ||
86 | - iotests.log('Stopping the NBD server on destination...') | ||
87 | - iotests.log(dest_vm.qmp('nbd-server-stop')) | ||
88 | - break | ||
89 | +with iotests.FilePath('source.img') as source_img_path, \ | ||
90 | + iotests.FilePath('dest.img') as dest_img_path, \ | ||
91 | + iotests.FilePath('migration.sock') as migration_sock_path, \ | ||
92 | + iotests.FilePath('nbd.sock') as nbd_sock_path, \ | ||
93 | + iotests.VM('source') as source_vm, \ | ||
94 | + iotests.VM('dest') as dest_vm: | ||
95 | + | ||
96 | + img_size = '1G' | ||
97 | + iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, source_img_path, img_size) | ||
98 | + iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, dest_img_path, img_size) | ||
99 | + | ||
100 | + iotests.log('Launching VMs...') | ||
101 | + (source_vm.add_drive(source_img_path) | ||
102 | + .launch()) | ||
103 | + (dest_vm.add_drive(dest_img_path) | ||
104 | + .add_incoming('unix:{0}'.format(migration_sock_path)) | ||
105 | + .launch()) | ||
106 | + | ||
107 | + iotests.log('Launching NBD server on destination...') | ||
108 | + iotests.log(dest_vm.qmp('nbd-server-start', addr={'type': 'unix', 'data': {'path': nbd_sock_path}})) | ||
109 | + iotests.log(dest_vm.qmp('nbd-server-add', device='drive0', writable=True)) | ||
110 | + | ||
111 | + iotests.log('Starting `drive-mirror` on source...') | ||
112 | + iotests.log(source_vm.qmp( | ||
113 | + 'drive-mirror', | ||
114 | + device='drive0', | ||
115 | + target='nbd+unix:///drive0?socket={0}'.format(nbd_sock_path), | ||
116 | + sync='full', | ||
117 | + format='raw', # always raw, the server handles the format | ||
118 | + mode='existing', | ||
119 | + job_id='mirror-job0')) | ||
120 | + | ||
121 | + iotests.log('Waiting for `drive-mirror` to complete...') | ||
122 | + iotests.log(source_vm.event_wait('BLOCK_JOB_READY'), | ||
123 | + filters=[iotests.filter_qmp_event]) | ||
124 | + | ||
125 | + iotests.log('Starting migration...') | ||
126 | + source_vm.qmp('migrate-set-capabilities', | ||
127 | + capabilities=[{'capability': 'events', 'state': True}]) | ||
128 | + dest_vm.qmp('migrate-set-capabilities', | ||
129 | + capabilities=[{'capability': 'events', 'state': True}]) | ||
130 | + iotests.log(source_vm.qmp('migrate', uri='unix:{0}'.format(migration_sock_path))) | ||
131 | + | ||
132 | + while True: | ||
133 | + event1 = source_vm.event_wait('MIGRATION') | ||
134 | + iotests.log(event1, filters=[iotests.filter_qmp_event]) | ||
135 | + if event1['data']['status'] in ('completed', 'failed'): | ||
136 | + iotests.log('Gracefully ending the `drive-mirror` job on source...') | ||
137 | + iotests.log(source_vm.qmp('block-job-cancel', device='mirror-job0')) | ||
138 | + break | ||
139 | + | ||
140 | + while True: | ||
141 | + event2 = source_vm.event_wait('BLOCK_JOB_COMPLETED') | ||
142 | + iotests.log(event2, filters=[iotests.filter_qmp_event]) | ||
143 | + if event2['event'] == 'BLOCK_JOB_COMPLETED': | ||
144 | + iotests.log('Stopping the NBD server on destination...') | ||
145 | + iotests.log(dest_vm.qmp('nbd-server-stop')) | ||
146 | + break | ||
147 | -- | ||
148 | 2.13.5 | ||
149 | |||
150 | diff view generated by jsdifflib |
1 | From: "Daniel P. Berrange" <berrange@redhat.com> | 1 | From: Daniel P. Berrangé <berrange@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | 3 | Consider passing a JSON based block driver to "qemu-img commit" |
4 | |||
5 | $ qemu-img commit 'json:{"driver":"qcow2","file":{"driver":"gluster",\ | ||
6 | "volume":"gv0","path":"sn1.qcow2", | ||
7 | "server":[{"type":\ | ||
8 | "tcp","host":"10.73.199.197","port":"24007"}]},}' | ||
9 | |||
10 | Currently it will commit the content and then report an incredibly | ||
11 | useless error message when trying to re-open the committed image: | ||
12 | |||
13 | qemu-img: invalid URI | ||
14 | Usage: file=gluster[+transport]://[host[:port]]volume/path[?socket=...][,file.debug=N][,file.logfile=/path/filename.log] | ||
15 | |||
16 | With this fix we get: | ||
17 | |||
18 | qemu-img: invalid URI json:{"server.0.host": "10.73.199.197", | ||
19 | "driver": "gluster", "path": "luks.qcow2", "server.0.type": | ||
20 | "tcp", "server.0.port": "24007", "volume": "gv0"} | ||
21 | |||
22 | Of course the root cause problem still exists, but now we know | ||
23 | what actually needs fixing. | ||
24 | |||
25 | Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> | ||
4 | Reviewed-by: Eric Blake <eblake@redhat.com> | 26 | Reviewed-by: Eric Blake <eblake@redhat.com> |
5 | Signed-off-by: Daniel P. Berrange <berrange@redhat.com> | 27 | Message-id: 20180206105204.14817-1-berrange@redhat.com |
6 | Message-id: 20170831105456.9558-1-berrange@redhat.com | 28 | Signed-off-by: Jeff Cody <jcody@redhat.com> |
7 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
8 | --- | 29 | --- |
9 | include/block/block_int.h | 31 +++++++++++++++++++++++++++++++ | 30 | block/gluster.c | 2 +- |
10 | 1 file changed, 31 insertions(+) | 31 | block/sheepdog.c | 2 +- |
32 | 2 files changed, 2 insertions(+), 2 deletions(-) | ||
11 | 33 | ||
12 | diff --git a/include/block/block_int.h b/include/block/block_int.h | 34 | diff --git a/block/gluster.c b/block/gluster.c |
13 | index XXXXXXX..XXXXXXX 100644 | 35 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/include/block/block_int.h | 36 | --- a/block/gluster.c |
15 | +++ b/include/block/block_int.h | 37 | +++ b/block/gluster.c |
16 | @@ -XXX,XX +XXX,XX @@ struct BlockDriver { | 38 | @@ -XXX,XX +XXX,XX @@ static int qemu_gluster_parse(BlockdevOptionsGluster *gconf, |
17 | 39 | if (filename) { | |
18 | int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs, | 40 | ret = qemu_gluster_parse_uri(gconf, filename); |
19 | int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); | 41 | if (ret < 0) { |
20 | + | 42 | - error_setg(errp, "invalid URI"); |
21 | + /** | 43 | + error_setg(errp, "invalid URI %s", filename); |
22 | + * @offset: position in bytes to read at | 44 | error_append_hint(errp, "Usage: file=gluster[+transport]://" |
23 | + * @bytes: number of bytes to read | 45 | "[host[:port]]volume/path[?socket=...]" |
24 | + * @qiov: the buffers to fill with read data | 46 | "[,file.debug=N]" |
25 | + * @flags: currently unused, always 0 | 47 | diff --git a/block/sheepdog.c b/block/sheepdog.c |
26 | + * | 48 | index XXXXXXX..XXXXXXX 100644 |
27 | + * @offset and @bytes will be a multiple of 'request_alignment', | 49 | --- a/block/sheepdog.c |
28 | + * but the length of individual @qiov elements does not have to | 50 | +++ b/block/sheepdog.c |
29 | + * be a multiple. | 51 | @@ -XXX,XX +XXX,XX @@ static void sd_parse_uri(SheepdogConfig *cfg, const char *filename, |
30 | + * | 52 | |
31 | + * @bytes will always equal the total size of @qiov, and will be | 53 | cfg->uri = uri = uri_parse(filename); |
32 | + * no larger than 'max_transfer'. | 54 | if (!uri) { |
33 | + * | 55 | - error_setg(&err, "invalid URI"); |
34 | + * The buffer in @qiov may point directly to guest memory. | 56 | + error_setg(&err, "invalid URI '%s'", filename); |
35 | + */ | 57 | goto out; |
36 | int coroutine_fn (*bdrv_co_preadv)(BlockDriverState *bs, | 58 | } |
37 | uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags); | ||
38 | int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs, | ||
39 | int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); | ||
40 | int coroutine_fn (*bdrv_co_writev_flags)(BlockDriverState *bs, | ||
41 | int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, int flags); | ||
42 | + /** | ||
43 | + * @offset: position in bytes to write at | ||
44 | + * @bytes: number of bytes to write | ||
45 | + * @qiov: the buffers containing data to write | ||
46 | + * @flags: zero or more bits allowed by 'supported_write_flags' | ||
47 | + * | ||
48 | + * @offset and @bytes will be a multiple of 'request_alignment', | ||
49 | + * but the length of individual @qiov elements does not have to | ||
50 | + * be a multiple. | ||
51 | + * | ||
52 | + * @bytes will always equal the total size of @qiov, and will be | ||
53 | + * no larger than 'max_transfer'. | ||
54 | + * | ||
55 | + * The buffer in @qiov may point directly to guest memory. | ||
56 | + */ | ||
57 | int coroutine_fn (*bdrv_co_pwritev)(BlockDriverState *bs, | ||
58 | uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags); | ||
59 | 59 | ||
60 | -- | 60 | -- |
61 | 2.13.5 | 61 | 2.13.6 |
62 | 62 | ||
63 | 63 | diff view generated by jsdifflib |