]>
Commit | Line | Data |
---|---|---|
bacebded JS |
1 | #!/usr/bin/env python |
2 | # | |
3 | # This test covers the basic fleecing workflow, which provides a | |
4 | # point-in-time snapshot of a node that can be queried over NBD. | |
5 | # | |
6 | # Copyright (C) 2018 Red Hat, Inc. | |
7 | # John helped, too. | |
8 | # | |
9 | # This program is free software; you can redistribute it and/or modify | |
10 | # it under the terms of the GNU General Public License as published by | |
11 | # the Free Software Foundation; either version 2 of the License, or | |
12 | # (at your option) any later version. | |
13 | # | |
14 | # This program is distributed in the hope that it will be useful, | |
15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | # GNU General Public License for more details. | |
18 | # | |
19 | # You should have received a copy of the GNU General Public License | |
20 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | # | |
22 | # Creator/Owner: John Snow <jsnow@redhat.com> | |
23 | ||
24 | import iotests | |
25 | from iotests import log, qemu_img, qemu_io, qemu_io_silent | |
26 | ||
27 | iotests.verify_platform(['linux']) | |
e79c4cd1 FZ |
28 | iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk', |
29 | 'vhdx', 'raw']) | |
bacebded JS |
30 | |
31 | patterns = [("0x5d", "0", "64k"), | |
32 | ("0xd5", "1M", "64k"), | |
33 | ("0xdc", "32M", "64k"), | |
34 | ("0xcd", "0x3ff0000", "64k")] # 64M - 64K | |
35 | ||
36 | overwrite = [("0xab", "0", "64k"), # Full overwrite | |
37 | ("0xad", "0x00f8000", "64k"), # Partial-left (1M-32K) | |
38 | ("0x1d", "0x2008000", "64k"), # Partial-right (32M+32K) | |
39 | ("0xea", "0x3fe0000", "64k")] # Adjacent-left (64M - 128K) | |
40 | ||
41 | zeroes = [("0", "0x00f8000", "32k"), # Left-end of partial-left (1M-32K) | |
42 | ("0", "0x2010000", "32k"), # Right-end of partial-right (32M+64K) | |
43 | ("0", "0x3fe0000", "64k")] # overwrite[3] | |
44 | ||
45 | remainder = [("0xd5", "0x108000", "32k"), # Right-end of partial-left [1] | |
46 | ("0xdc", "32M", "32k"), # Left-end of partial-right [2] | |
47 | ("0xcd", "0x3ff0000", "64k")] # patterns[3] | |
48 | ||
49 | with iotests.FilePath('base.img') as base_img_path, \ | |
50 | iotests.FilePath('fleece.img') as fleece_img_path, \ | |
51 | iotests.FilePath('nbd.sock') as nbd_sock_path, \ | |
52 | iotests.VM() as vm: | |
53 | ||
54 | log('--- Setting up images ---') | |
55 | log('') | |
56 | ||
57 | assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0 | |
58 | assert qemu_img('create', '-f', "qcow2", fleece_img_path, '64M') == 0 | |
59 | ||
60 | for p in patterns: | |
61 | qemu_io('-f', iotests.imgfmt, | |
62 | '-c', 'write -P%s %s %s' % p, base_img_path) | |
63 | ||
64 | log('Done') | |
65 | ||
66 | log('') | |
67 | log('--- Launching VM ---') | |
68 | log('') | |
69 | ||
70 | vm.add_drive(base_img_path) | |
71 | vm.launch() | |
72 | log('Done') | |
73 | ||
74 | log('') | |
75 | log('--- Setting up Fleecing Graph ---') | |
76 | log('') | |
77 | ||
78 | src_node = "drive0" | |
79 | tgt_node = "fleeceNode" | |
80 | ||
81 | # create tgt_node backed by src_node | |
82 | log(vm.qmp("blockdev-add", **{ | |
83 | "driver": "qcow2", | |
84 | "node-name": tgt_node, | |
85 | "file": { | |
86 | "driver": "file", | |
87 | "filename": fleece_img_path, | |
88 | }, | |
89 | "backing": src_node, | |
90 | })) | |
91 | ||
92 | # Establish COW from source to fleecing node | |
93 | log(vm.qmp("blockdev-backup", | |
94 | device=src_node, | |
95 | target=tgt_node, | |
96 | sync="none")) | |
97 | ||
98 | log('') | |
99 | log('--- Setting up NBD Export ---') | |
100 | log('') | |
101 | ||
102 | nbd_uri = 'nbd+unix:///%s?socket=%s' % (tgt_node, nbd_sock_path) | |
103 | log(vm.qmp("nbd-server-start", | |
104 | **{"addr": { "type": "unix", | |
105 | "data": { "path": nbd_sock_path } } })) | |
106 | ||
107 | log(vm.qmp("nbd-server-add", device=tgt_node)) | |
108 | ||
109 | log('') | |
110 | log('--- Sanity Check ---') | |
111 | log('') | |
112 | ||
113 | for p in (patterns + zeroes): | |
114 | cmd = "read -P%s %s %s" % p | |
115 | log(cmd) | |
116 | assert qemu_io_silent('-r', '-f', 'raw', '-c', cmd, nbd_uri) == 0 | |
117 | ||
118 | log('') | |
119 | log('--- Testing COW ---') | |
120 | log('') | |
121 | ||
122 | for p in overwrite: | |
123 | cmd = "write -P%s %s %s" % p | |
124 | log(cmd) | |
125 | log(vm.hmp_qemu_io(src_node, cmd)) | |
126 | ||
127 | log('') | |
128 | log('--- Verifying Data ---') | |
129 | log('') | |
130 | ||
131 | for p in (patterns + zeroes): | |
132 | cmd = "read -P%s %s %s" % p | |
133 | log(cmd) | |
134 | assert qemu_io_silent('-r', '-f', 'raw', '-c', cmd, nbd_uri) == 0 | |
135 | ||
136 | log('') | |
137 | log('--- Cleanup ---') | |
138 | log('') | |
139 | ||
140 | log(vm.qmp('block-job-cancel', device=src_node)) | |
141 | log(vm.event_wait('BLOCK_JOB_CANCELLED'), | |
142 | filters=[iotests.filter_qmp_event]) | |
143 | log(vm.qmp('nbd-server-stop')) | |
144 | log(vm.qmp('blockdev-del', node_name=tgt_node)) | |
145 | vm.shutdown() | |
146 | ||
147 | log('') | |
148 | log('--- Confirming writes ---') | |
149 | log('') | |
150 | ||
151 | for p in (overwrite + remainder): | |
152 | cmd = "read -P%s %s %s" % p | |
153 | log(cmd) | |
154 | assert qemu_io_silent(base_img_path, '-c', cmd) == 0 | |
155 | ||
156 | log('') | |
157 | log('Done') |