Merge lp:~ltrager/maas/lp1685361_2.1 into lp:maas/2.1
- lp1685361_2.1
- Merge into 2.1
Proposed by
Lee Trager
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Lee Trager | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 5601 | ||||
Proposed branch: | lp:~ltrager/maas/lp1685361_2.1 | ||||
Merge into: | lp:maas/2.1 | ||||
Diff against target: |
841 lines (+232/-387) 2 files modified
src/provisioningserver/refresh/node_info_scripts.py (+8/-1) src/provisioningserver/refresh/tests/test_node_info_scripts.py (+224/-386) |
||||
To merge this branch: | bzr merge lp:~ltrager/maas/lp1685361_2.1 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Lee Trager (community) | Approve | ||
Review via email: mp+323114@code.launchpad.net |
Commit message
Fix 00-maas-
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/provisioningserver/refresh/node_info_scripts.py' |
2 | --- src/provisioningserver/refresh/node_info_scripts.py 2017-03-22 21:46:10 +0000 |
3 | +++ src/provisioningserver/refresh/node_info_scripts.py 2017-04-25 09:25:16 +0000 |
4 | @@ -294,7 +294,7 @@ |
5 | blockdevs = [] |
6 | block_list = check_output(( |
7 | "lsblk", "--exclude", "1,2,7", "-d", "-P", |
8 | - "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN", "-x", "MAJ:MIN")) |
9 | + "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN")) |
10 | block_list = block_list.decode("utf-8") |
11 | for blockdev in block_list.splitlines(): |
12 | tokens = shlex.split(blockdev) |
13 | @@ -304,6 +304,13 @@ |
14 | current_block[k] = v.strip() |
15 | blockdevs.append(current_block) |
16 | |
17 | + # Sort drives by MAJ:MIN so MAAS picks the correct boot drive. |
18 | + # lsblk -x MAJ:MIN can't be used as the -x flag only appears in |
19 | + # lsblk 2.71.1 or newer which is unavailable on Trusty. See LP:1673724 |
20 | + blockdevs = sorted( |
21 | + blockdevs, |
22 | + key=lambda blockdev: [int(i) for i in blockdev['MAJ:MIN'].split(':')]) |
23 | + |
24 | # Grab the device path, serial number, and sata connection. |
25 | UDEV_MAPPINGS = { |
26 | "DEVNAME": "PATH", |
27 | |
28 | === modified file 'src/provisioningserver/refresh/tests/test_node_info_scripts.py' |
29 | --- src/provisioningserver/refresh/tests/test_node_info_scripts.py 2017-03-22 21:46:10 +0000 |
30 | +++ src/provisioningserver/refresh/tests/test_node_info_scripts.py 2017-04-25 09:25:16 +0000 |
31 | @@ -5,7 +5,6 @@ |
32 | |
33 | __all__ = [] |
34 | |
35 | -from functools import partial |
36 | from inspect import getsource |
37 | from io import StringIO |
38 | import json |
39 | @@ -18,6 +17,7 @@ |
40 | check_output, |
41 | STDOUT, |
42 | ) |
43 | +import sys |
44 | from textwrap import dedent |
45 | import time |
46 | from unittest.mock import call |
47 | @@ -338,16 +338,19 @@ |
48 | @typed |
49 | def make_lsblk_output( |
50 | self, name=None, read_only=False, removable=False, |
51 | - model=None, rotary=True) -> bytes: |
52 | + model=None, rotary=True, maj_min=None) -> bytes: |
53 | if name is None: |
54 | name = factory.make_name('name') |
55 | if model is None: |
56 | model = factory.make_name('model') |
57 | + if maj_min is None: |
58 | + maj_min = (random.randint(0, 255), random.randint(0, 255)) |
59 | read_only = "1" if read_only else "0" |
60 | removable = "1" if removable else "0" |
61 | rotary = "1" if rotary else "0" |
62 | - output = 'NAME="%s" RO="%s" RM="%s" MODEL="%s" ROTA="%s"' % ( |
63 | - name, read_only, removable, model, rotary) |
64 | + output = ( |
65 | + 'NAME="%s" RO="%s" RM="%s" MODEL="%s" ROTA="%s" MAJ:MIN="%s"' % ( |
66 | + name, read_only, removable, model, rotary, '%s:%s' % maj_min)) |
67 | return output.encode("ascii") |
68 | |
69 | @typed |
70 | @@ -373,21 +376,54 @@ |
71 | return output.encode("ascii") |
72 | |
73 | def call_gather_physical_block_devices( |
74 | - self, dev_disk_byid='/dev/disk/by-id/'): |
75 | + self, dev_disk_byid='/dev/disk/by-id/', file_path=None): |
76 | output = StringIO() |
77 | - namespace = {"print": partial(print, file=output)} |
78 | + |
79 | + def neutered_print(*args, **kwargs): |
80 | + file = kwargs.pop('file', None) |
81 | + if file is not None and file == sys.stderr: |
82 | + return |
83 | + return print(*args, **kwargs, file=output) |
84 | + |
85 | + namespace = {"print": neutered_print} |
86 | + if file_path is not None: |
87 | + namespace['__file__'] = file_path |
88 | gather_physical_block_devices = isolate_function( |
89 | node_info_module.gather_physical_block_devices, namespace) |
90 | gather_physical_block_devices(dev_disk_byid=dev_disk_byid) |
91 | return json.loads(output.getvalue()) |
92 | |
93 | + def make_output( |
94 | + self, name, maj_min, model, serial, size, block_size, |
95 | + drive_path=None, device_id_path=None, rotary=True, |
96 | + removable=False, read_only=False, sata=True): |
97 | + if drive_path is None: |
98 | + drive_path = '/dev/%s' % name |
99 | + ret = { |
100 | + 'NAME': name, |
101 | + 'PATH': drive_path, |
102 | + 'MAJ:MIN': '%s:%s' % maj_min, |
103 | + 'RO': '1' if read_only else '0', |
104 | + 'RM': '1' if removable else '0', |
105 | + 'MODEL': model, |
106 | + 'ROTA': '1' if rotary else '0', |
107 | + 'SATA': '1' if sata else '0', |
108 | + 'SERIAL': serial, |
109 | + 'SIZE': str(size), |
110 | + 'BLOCK_SIZE': str(block_size), |
111 | + 'RPM': '5400', |
112 | + } |
113 | + if device_id_path is not None: |
114 | + ret['ID_PATH'] = device_id_path |
115 | + return ret |
116 | + |
117 | def test__calls_lsblk(self): |
118 | check_output = self.patch(subprocess, "check_output") |
119 | check_output.return_value = b"" |
120 | self.call_gather_physical_block_devices() |
121 | self.assertThat(check_output, MockCalledOnceWith(( |
122 | "lsblk", "--exclude", "1,2,7", "-d", "-P", |
123 | - "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN", "-x", "MAJ:MIN"))) |
124 | + "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN"))) |
125 | |
126 | def test__returns_empty_list_when_no_disks(self): |
127 | check_output = self.patch(subprocess, "check_output") |
128 | @@ -407,7 +443,7 @@ |
129 | self.assertThat(check_output, MockCallsMatch( |
130 | call(( |
131 | "lsblk", "--exclude", "1,2,7", "-d", "-P", |
132 | - "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN", "-x", "MAJ:MIN")), |
133 | + "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN")), |
134 | call(("udevadm", "info", "-q", "all", "-n", name)))) |
135 | |
136 | def test__returns_empty_list_when_cdrom_only(self): |
137 | @@ -439,128 +475,52 @@ |
138 | self.assertThat(check_output, MockCallsMatch( |
139 | call(( |
140 | "lsblk", "--exclude", "1,2,7", "-d", "-P", |
141 | - "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN", "-x", "MAJ:MIN")), |
142 | + "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN")), |
143 | call(("udevadm", "info", "-q", "all", "-n", name)), |
144 | call(("sudo", "blockdev", "--getsize64", "/dev/%s" % name)), |
145 | call(("sudo", "blockdev", "--getbsz", "/dev/%s" % name)))) |
146 | |
147 | - def test__returns_block_device(self): |
148 | - name = factory.make_name('name') |
149 | - model = factory.make_name('model') |
150 | - serial = factory.make_name('serial') |
151 | - size = random.randint(3000 * 1000, 1000 * 1000 * 1000) |
152 | - block_size = random.choice([512, 1024, 4096]) |
153 | - check_output = self.patch(subprocess, "check_output") |
154 | - |
155 | - # Create simulated /dev tree |
156 | - devroot = self.make_dir() |
157 | - os.mkdir(os.path.join(devroot, 'disk')) |
158 | - byidroot = os.path.join(devroot, 'disk', 'by_id') |
159 | - os.mkdir(byidroot) |
160 | - os.mknod(os.path.join(devroot, name)) |
161 | - os.symlink(os.path.join(devroot, name), |
162 | - os.path.join(byidroot, 'deviceid')) |
163 | - |
164 | - check_output.side_effect = [ |
165 | - self.make_lsblk_output(name=name, model=model), |
166 | - self.make_udevadm_output(name, serial=serial, dev=devroot), |
167 | - b'%d' % size, |
168 | - b'%d' % block_size, |
169 | - ] |
170 | - self.assertEqual([{ |
171 | - "NAME": name, |
172 | - "PATH": os.path.join(devroot, name), |
173 | - "ID_PATH": os.path.join(byidroot, 'deviceid'), |
174 | - "RO": "0", |
175 | - "RM": "0", |
176 | - "MODEL": model, |
177 | - "ROTA": "1", |
178 | - "SATA": "1", |
179 | - "SERIAL": serial, |
180 | - "SIZE": "%s" % size, |
181 | - "BLOCK_SIZE": "%s" % block_size, |
182 | - "RPM": "5400", |
183 | - }], self.call_gather_physical_block_devices(byidroot)) |
184 | - |
185 | - def test__returns_block_device_with_shortest_byidpath_long_first(self): |
186 | - name = factory.make_name('name') |
187 | - model = factory.make_name('model') |
188 | - serial = factory.make_name('serial') |
189 | - size = random.randint(3000 * 1000, 1000 * 1000 * 1000) |
190 | - block_size = random.choice([512, 1024, 4096]) |
191 | - check_output = self.patch(subprocess, "check_output") |
192 | - |
193 | - # Create simulated /dev tree |
194 | - devroot = self.make_dir() |
195 | - os.mkdir(os.path.join(devroot, 'disk')) |
196 | - byidroot = os.path.join(devroot, 'disk', 'by_id') |
197 | - os.mkdir(byidroot) |
198 | - os.mknod(os.path.join(devroot, name)) |
199 | - os.symlink(os.path.join(devroot, name), |
200 | - os.path.join(byidroot, 'deviceid-long')) |
201 | - os.symlink(os.path.join(devroot, name), |
202 | - os.path.join(byidroot, 'deviceid')) |
203 | - |
204 | - check_output.side_effect = [ |
205 | - self.make_lsblk_output(name=name, model=model), |
206 | - self.make_udevadm_output(name, serial=serial, dev=devroot), |
207 | - b'%d' % size, |
208 | - b'%d' % block_size, |
209 | - ] |
210 | - self.assertEqual([{ |
211 | - "NAME": name, |
212 | - "PATH": os.path.join(devroot, name), |
213 | - "ID_PATH": os.path.join(byidroot, 'deviceid'), |
214 | - "RO": "0", |
215 | - "RM": "0", |
216 | - "MODEL": model, |
217 | - "ROTA": "1", |
218 | - "SATA": "1", |
219 | - "SERIAL": serial, |
220 | - "SIZE": "%s" % size, |
221 | - "BLOCK_SIZE": "%s" % block_size, |
222 | - "RPM": "5400", |
223 | - }], self.call_gather_physical_block_devices(byidroot)) |
224 | - |
225 | - def test__returns_block_device_with_first_byidpath_long_second(self): |
226 | - name = factory.make_name('name') |
227 | - model = factory.make_name('model') |
228 | - serial = factory.make_name('serial') |
229 | - size = random.randint(3000 * 1000, 1000 * 1000 * 1000) |
230 | - block_size = random.choice([512, 1024, 4096]) |
231 | - check_output = self.patch(subprocess, "check_output") |
232 | - |
233 | - # Create simulated /dev tree |
234 | - devroot = self.make_dir() |
235 | - os.mkdir(os.path.join(devroot, 'disk')) |
236 | - byidroot = os.path.join(devroot, 'disk', 'by_id') |
237 | - os.mkdir(byidroot) |
238 | - os.mknod(os.path.join(devroot, name)) |
239 | - os.symlink(os.path.join(devroot, name), |
240 | - os.path.join(byidroot, 'deviceid')) |
241 | - os.symlink(os.path.join(devroot, name), |
242 | - os.path.join(byidroot, 'deviceid-longest')) |
243 | - |
244 | - check_output.side_effect = [ |
245 | - self.make_lsblk_output(name=name, model=model), |
246 | - self.make_udevadm_output(name, serial=serial, dev=devroot), |
247 | - b'%d' % size, |
248 | - b'%d' % block_size, |
249 | - ] |
250 | - self.assertEqual([{ |
251 | - "NAME": name, |
252 | - "PATH": os.path.join(devroot, name), |
253 | - "ID_PATH": os.path.join(byidroot, 'deviceid'), |
254 | - "RO": "0", |
255 | - "RM": "0", |
256 | - "MODEL": model, |
257 | - "ROTA": "1", |
258 | - "SATA": "1", |
259 | - "SERIAL": serial, |
260 | - "SIZE": "%s" % size, |
261 | - "BLOCK_SIZE": "%s" % block_size, |
262 | - "RPM": "5400", |
263 | - }], self.call_gather_physical_block_devices(byidroot)) |
264 | + def test__returns_sorted_block_devices(self): |
265 | + output = [] |
266 | + check_output_side_effects = [] |
267 | + # Create simulated /dev tree |
268 | + devroot = self.make_dir() |
269 | + os.mkdir(os.path.join(devroot, 'disk')) |
270 | + byidroot = os.path.join(devroot, 'disk', 'by_id') |
271 | + os.mkdir(byidroot) |
272 | + for _ in range(3): |
273 | + name = factory.make_name('name') |
274 | + model = factory.make_name('model') |
275 | + serial = factory.make_name('serial') |
276 | + size = random.randint(3000 * 1000, 1000 * 1000 * 1000) |
277 | + block_size = random.choice([512, 1024, 4096]) |
278 | + maj_min = (random.randint(0, 255), random.randint(0, 255)) |
279 | + |
280 | + # Create simulated /dev tree |
281 | + drive_path = os.path.join(devroot, name) |
282 | + os.mknod(drive_path) |
283 | + device_id_path = os.path.join( |
284 | + byidroot, factory.make_name('deviceid')) |
285 | + os.symlink(drive_path, device_id_path) |
286 | + |
287 | + check_output_side_effects += [ |
288 | + self.make_lsblk_output( |
289 | + name=name, model=model, maj_min=maj_min), |
290 | + self.make_udevadm_output(name, serial=serial, dev=devroot), |
291 | + b'%d' % size, |
292 | + b'%d' % block_size, |
293 | + ] |
294 | + output.append( |
295 | + self.make_output( |
296 | + name, maj_min, model, serial, size, block_size, |
297 | + drive_path, device_id_path)) |
298 | + |
299 | + check_output = self.patch(subprocess, "check_output") |
300 | + check_output.side_effect = check_output_side_effects |
301 | + |
302 | + for ref, out in zip( |
303 | + output, self.call_gather_physical_block_devices(byidroot)): |
304 | + self.assertDictEqual(ref, out) |
305 | |
306 | def test__removes_duplicate_block_device_same_serial_and_model(self): |
307 | """Multipath disks get multiple IDs, but same serial/model is same |
308 | @@ -570,107 +530,51 @@ |
309 | serial = factory.make_name('serial') |
310 | size = random.randint(3000 * 1000, 1000 * 1000 * 1000) |
311 | block_size = random.choice([512, 1024, 4096]) |
312 | - check_output = self.patch(subprocess, "check_output") |
313 | - |
314 | - name2 = factory.make_name('name') |
315 | - |
316 | - # Create simulated /dev tree. |
317 | - devroot = self.make_dir() |
318 | - os.mkdir(os.path.join(devroot, 'disk')) |
319 | - byidroot = os.path.join(devroot, 'disk', 'by_id') |
320 | - os.mkdir(byidroot) |
321 | - |
322 | - os.mknod(os.path.join(devroot, name)) |
323 | - os.symlink(os.path.join(devroot, name), |
324 | - os.path.join(byidroot, 'deviceid')) |
325 | - |
326 | - os.mknod(os.path.join(devroot, name2)) |
327 | - os.symlink(os.path.join(devroot, name2), |
328 | - os.path.join(byidroot, 'deviceid2')) |
329 | - |
330 | - check_output.side_effect = [ |
331 | - b"\n".join([ |
332 | - self.make_lsblk_output(name=name, model=model), |
333 | - self.make_lsblk_output(name=name2, model=model)]), |
334 | - self.make_udevadm_output(name, serial=serial, dev=devroot), |
335 | - self.make_udevadm_output(name2, serial=serial, dev=devroot), |
336 | - b'%d' % size, |
337 | - b'%d' % block_size, |
338 | - b'%d' % size, |
339 | - b'%d' % block_size, |
340 | - ] |
341 | - |
342 | - self.assertEqual([{ |
343 | - "NAME": name, |
344 | - "PATH": os.path.join(devroot, name), |
345 | - "ID_PATH": os.path.join(byidroot, 'deviceid'), |
346 | - "RO": "0", |
347 | - "RM": "0", |
348 | - "MODEL": model, |
349 | - "ROTA": "1", |
350 | - "SATA": "1", |
351 | - "SERIAL": serial, |
352 | - "SIZE": "%s" % size, |
353 | - "BLOCK_SIZE": "%s" % block_size, |
354 | - "RPM": "5400", |
355 | - }], self.call_gather_physical_block_devices(byidroot)) |
356 | - |
357 | - def test__removes_duplicate_block_device_same_serial_blank_model(self): |
358 | - """Multipath disks get multiple IDs, but same serial is same device.""" |
359 | - name = factory.make_name('name') |
360 | - model = "" |
361 | - serial = factory.make_name('serial') |
362 | - size = random.randint(3000 * 1000, 1000 * 1000 * 1000) |
363 | - block_size = random.choice([512, 1024, 4096]) |
364 | - check_output = self.patch(subprocess, "check_output") |
365 | - |
366 | - name2 = factory.make_name('name') |
367 | - |
368 | - # Create simulated /dev tree. |
369 | - devroot = self.make_dir() |
370 | - os.mkdir(os.path.join(devroot, 'disk')) |
371 | - byidroot = os.path.join(devroot, 'disk', 'by_id') |
372 | - os.mkdir(byidroot) |
373 | - |
374 | - os.mknod(os.path.join(devroot, name)) |
375 | - os.symlink(os.path.join(devroot, name), |
376 | - os.path.join(byidroot, 'deviceid')) |
377 | - |
378 | - os.mknod(os.path.join(devroot, name2)) |
379 | - os.symlink(os.path.join(devroot, name2), |
380 | - os.path.join(byidroot, 'deviceid2')) |
381 | - |
382 | - check_output.side_effect = [ |
383 | - b"\n".join([ |
384 | - self.make_lsblk_output(name=name, model=model), |
385 | - self.make_lsblk_output(name=name2, model=model)]), |
386 | - self.make_udevadm_output(name, serial=serial, dev=devroot), |
387 | - self.make_udevadm_output(name2, serial=serial, dev=devroot), |
388 | - b'%d' % size, |
389 | - b'%d' % block_size, |
390 | - b'%d' % size, |
391 | - b'%d' % block_size, |
392 | - ] |
393 | - |
394 | - self.assertEqual([{ |
395 | - "NAME": name, |
396 | - "PATH": os.path.join(devroot, name), |
397 | - "ID_PATH": os.path.join(byidroot, 'deviceid'), |
398 | - "RO": "0", |
399 | - "RM": "0", |
400 | - "MODEL": model, |
401 | - "ROTA": "1", |
402 | - "SATA": "1", |
403 | - "SERIAL": serial, |
404 | - "SIZE": "%s" % size, |
405 | - "BLOCK_SIZE": "%s" % block_size, |
406 | - "RPM": "5400", |
407 | - }], self.call_gather_physical_block_devices(byidroot)) |
408 | + maj_min = (random.randint(0, 255), random.randint(0, 255)) |
409 | + check_output = self.patch(subprocess, "check_output") |
410 | + |
411 | + name2 = factory.make_name('name') |
412 | + |
413 | + # Create simulated /dev tree. |
414 | + devroot = self.make_dir() |
415 | + os.mkdir(os.path.join(devroot, 'disk')) |
416 | + byidroot = os.path.join(devroot, 'disk', 'by_id') |
417 | + os.mkdir(byidroot) |
418 | + |
419 | + drive_path = os.path.join(devroot, name) |
420 | + os.mknod(drive_path) |
421 | + device_id_path = os.path.join(byidroot, 'deviceid') |
422 | + os.symlink(os.path.join(devroot, name), device_id_path) |
423 | + |
424 | + os.mknod(os.path.join(devroot, name2)) |
425 | + device_id_path2 = os.path.join(byidroot, 'deviceid2') |
426 | + os.symlink(os.path.join(devroot, name2), device_id_path2) |
427 | + |
428 | + check_output.side_effect = [ |
429 | + b"\n".join([ |
430 | + self.make_lsblk_output( |
431 | + name=name, model=model, maj_min=maj_min), |
432 | + self.make_lsblk_output( |
433 | + name=name2, model=model, maj_min=maj_min)]), |
434 | + self.make_udevadm_output(name, serial=serial, dev=devroot), |
435 | + self.make_udevadm_output(name2, serial=serial, dev=devroot), |
436 | + b'%d' % size, |
437 | + b'%d' % block_size, |
438 | + b'%d' % size, |
439 | + b'%d' % block_size, |
440 | + ] |
441 | + |
442 | + self.assertItemsEqual( |
443 | + [self.make_output( |
444 | + name, maj_min, model, serial, size, block_size, drive_path, |
445 | + device_id_path)], |
446 | + self.call_gather_physical_block_devices(byidroot)) |
447 | |
448 | def test__keeps_block_device_same_serial_different_model(self): |
449 | """Multipath disks get multiple IDs, but same serial is same device.""" |
450 | name = factory.make_name('name') |
451 | model = factory.make_name('model') |
452 | + maj_min = (0, 0) |
453 | serial = factory.make_name('serial') |
454 | size = random.randint(3000 * 1000, 1000 * 1000 * 1000) |
455 | block_size = random.choice([512, 1024, 4096]) |
456 | @@ -678,6 +582,7 @@ |
457 | |
458 | name2 = factory.make_name('name') |
459 | model2 = factory.make_name('model') |
460 | + maj_min2 = (1, 1) |
461 | |
462 | # Create simulated /dev tree. |
463 | devroot = self.make_dir() |
464 | @@ -685,18 +590,23 @@ |
465 | byidroot = os.path.join(devroot, 'disk', 'by_id') |
466 | os.mkdir(byidroot) |
467 | |
468 | - os.mknod(os.path.join(devroot, name)) |
469 | - os.symlink(os.path.join(devroot, name), |
470 | - os.path.join(byidroot, 'deviceid')) |
471 | + drive_path = os.path.join(devroot, name) |
472 | + os.mknod(drive_path) |
473 | + device_id_path = os.path.join(byidroot, 'deviceid') |
474 | + os.symlink(os.path.join(devroot, name), device_id_path) |
475 | |
476 | - os.mknod(os.path.join(devroot, name2)) |
477 | - os.symlink(os.path.join(devroot, name2), |
478 | - os.path.join(byidroot, 'deviceid2')) |
479 | + drive_path2 = os.path.join(devroot, name2) |
480 | + os.mknod(drive_path2) |
481 | + device_id_path2 = os.path.join(byidroot, 'deviceid2') |
482 | + os.symlink(os.path.join(devroot, name2), device_id_path2) |
483 | |
484 | check_output.side_effect = [ |
485 | b"\n".join([ |
486 | - self.make_lsblk_output(name=name, model=model), |
487 | - self.make_lsblk_output(name=name2, model=model2)]), |
488 | + self.make_lsblk_output( |
489 | + name=name, model=model, maj_min=maj_min), |
490 | + self.make_lsblk_output( |
491 | + name=name2, model=model2, maj_min=maj_min2) |
492 | + ]), |
493 | self.make_udevadm_output(name, serial=serial, dev=devroot), |
494 | self.make_udevadm_output(name2, serial=serial, dev=devroot), |
495 | b'%d' % size, |
496 | @@ -705,44 +615,29 @@ |
497 | b'%d' % block_size, |
498 | ] |
499 | |
500 | - self.assertEqual([{ |
501 | - "NAME": name, |
502 | - "PATH": os.path.join(devroot, name), |
503 | - "ID_PATH": os.path.join(byidroot, 'deviceid'), |
504 | - "RO": "0", |
505 | - "RM": "0", |
506 | - "MODEL": model, |
507 | - "ROTA": "1", |
508 | - "SATA": "1", |
509 | - "SERIAL": serial, |
510 | - "SIZE": "%s" % size, |
511 | - "BLOCK_SIZE": "%s" % block_size, |
512 | - "RPM": "5400", |
513 | - }, { |
514 | - "NAME": name2, |
515 | - "PATH": os.path.join(devroot, name2), |
516 | - "ID_PATH": os.path.join(byidroot, 'deviceid2'), |
517 | - "RO": "0", |
518 | - "RM": "0", |
519 | - "MODEL": model2, |
520 | - "ROTA": "1", |
521 | - "SATA": "1", |
522 | - "SERIAL": serial, |
523 | - "SIZE": "%s" % size, |
524 | - "BLOCK_SIZE": "%s" % block_size, |
525 | - "RPM": "5400", |
526 | - }], self.call_gather_physical_block_devices(byidroot)) |
527 | + for ref, out in zip( |
528 | + [ |
529 | + self.make_output( |
530 | + name, maj_min, model, serial, size, block_size, |
531 | + drive_path, device_id_path), |
532 | + self.make_output( |
533 | + name2, maj_min2, model2, serial, size, block_size, |
534 | + drive_path2, device_id_path2), |
535 | + ], self.call_gather_physical_block_devices(byidroot)): |
536 | + self.assertDictEqual(ref, out) |
537 | |
538 | def test__keeps_block_device_blank_serial_same_model(self): |
539 | """Multipath disks get multiple IDs, but same serial is same device.""" |
540 | name = factory.make_name('name') |
541 | model = factory.make_name('model') |
542 | + maj_min = (0, 0) |
543 | serial = '' |
544 | size = random.randint(3000 * 1000, 1000 * 1000 * 1000) |
545 | block_size = random.choice([512, 1024, 4096]) |
546 | check_output = self.patch(subprocess, "check_output") |
547 | |
548 | name2 = factory.make_name('name') |
549 | + maj_min2 = (1, 1) |
550 | |
551 | # Create simulated /dev tree. |
552 | devroot = self.make_dir() |
553 | @@ -750,18 +645,22 @@ |
554 | byidroot = os.path.join(devroot, 'disk', 'by_id') |
555 | os.mkdir(byidroot) |
556 | |
557 | - os.mknod(os.path.join(devroot, name)) |
558 | - os.symlink(os.path.join(devroot, name), |
559 | - os.path.join(byidroot, 'deviceid')) |
560 | + drive_path = os.path.join(devroot, name) |
561 | + os.mknod(drive_path) |
562 | + device_id_path = os.path.join(byidroot, 'deviceid') |
563 | + os.symlink(os.path.join(devroot, name), device_id_path) |
564 | |
565 | - os.mknod(os.path.join(devroot, name2)) |
566 | - os.symlink(os.path.join(devroot, name2), |
567 | - os.path.join(byidroot, 'deviceid2')) |
568 | + drive_path2 = os.path.join(devroot, name2) |
569 | + os.mknod(drive_path2) |
570 | + device_id_path2 = os.path.join(byidroot, 'deviceid2') |
571 | + os.symlink(os.path.join(devroot, name2), device_id_path2) |
572 | |
573 | check_output.side_effect = [ |
574 | b"\n".join([ |
575 | - self.make_lsblk_output(name=name, model=model), |
576 | - self.make_lsblk_output(name=name2, model=model)]), |
577 | + self.make_lsblk_output( |
578 | + name=name, model=model, maj_min=maj_min), |
579 | + self.make_lsblk_output( |
580 | + name=name2, model=model, maj_min=maj_min2)]), |
581 | self.make_udevadm_output(name, serial=serial, dev=devroot), |
582 | self.make_udevadm_output(name2, serial=serial, dev=devroot), |
583 | b'%d' % size, |
584 | @@ -770,38 +669,22 @@ |
585 | b'%d' % block_size, |
586 | ] |
587 | |
588 | - self.assertEqual([{ |
589 | - "NAME": name, |
590 | - "PATH": os.path.join(devroot, name), |
591 | - "ID_PATH": os.path.join(byidroot, 'deviceid'), |
592 | - "RO": "0", |
593 | - "RM": "0", |
594 | - "MODEL": model, |
595 | - "ROTA": "1", |
596 | - "SATA": "1", |
597 | - "SERIAL": serial, |
598 | - "SIZE": "%s" % size, |
599 | - "BLOCK_SIZE": "%s" % block_size, |
600 | - "RPM": "5400", |
601 | - }, { |
602 | - "NAME": name2, |
603 | - "PATH": os.path.join(devroot, name2), |
604 | - "ID_PATH": os.path.join(byidroot, 'deviceid2'), |
605 | - "RO": "0", |
606 | - "RM": "0", |
607 | - "MODEL": model, |
608 | - "ROTA": "1", |
609 | - "SATA": "1", |
610 | - "SERIAL": serial, |
611 | - "SIZE": "%s" % size, |
612 | - "BLOCK_SIZE": "%s" % block_size, |
613 | - "RPM": "5400", |
614 | - }], self.call_gather_physical_block_devices(byidroot)) |
615 | + for ref, out in zip( |
616 | + [ |
617 | + self.make_output( |
618 | + name, maj_min, model, serial, size, block_size, |
619 | + drive_path, device_id_path), |
620 | + self.make_output( |
621 | + name2, maj_min2, model, serial, size, block_size, |
622 | + drive_path2, device_id_path2), |
623 | + ], self.call_gather_physical_block_devices(byidroot)): |
624 | + self.assertDictEqual(ref, out) |
625 | |
626 | def test__returns_block_device_without_id_path(self): |
627 | """Block devices without by-id links should not have ID_PATH key""" |
628 | name = factory.make_name('name') |
629 | model = factory.make_name('model') |
630 | + maj_min = (random.randint(0, 255), random.randint(0, 255)) |
631 | serial = factory.make_name('serial') |
632 | size = random.randint(3000 * 1000, 1000 * 1000 * 1000) |
633 | block_size = random.choice([512, 1024, 4096]) |
634 | @@ -812,158 +695,113 @@ |
635 | os.mkdir(os.path.join(devroot, 'disk')) |
636 | byidroot = os.path.join(devroot, 'disk', 'by_id') |
637 | os.mkdir(byidroot) |
638 | - os.mknod(os.path.join(devroot, name)) |
639 | + drive_path = os.path.join(devroot, name) |
640 | + os.mknod(drive_path) |
641 | |
642 | check_output.side_effect = [ |
643 | - self.make_lsblk_output(name=name, model=model), |
644 | + self.make_lsblk_output(name=name, model=model, maj_min=maj_min), |
645 | self.make_udevadm_output(name, serial=serial, dev=devroot), |
646 | b'%d' % size, |
647 | b'%d' % block_size, |
648 | ] |
649 | - self.assertEqual([{ |
650 | - "NAME": name, |
651 | - "PATH": os.path.join(devroot, name), |
652 | - "RO": "0", |
653 | - "RM": "0", |
654 | - "MODEL": model, |
655 | - "ROTA": "1", |
656 | - "SATA": "1", |
657 | - "SERIAL": serial, |
658 | - "SIZE": "%s" % size, |
659 | - "BLOCK_SIZE": "%s" % block_size, |
660 | - "RPM": "5400", |
661 | - }], self.call_gather_physical_block_devices(byidroot)) |
662 | + for ref, out in zip( |
663 | + [ |
664 | + self.make_output( |
665 | + name, maj_min, model, serial, size, block_size, |
666 | + drive_path), |
667 | + ], self.call_gather_physical_block_devices(byidroot)): |
668 | + self.assertDictEqual(ref, out) |
669 | |
670 | def test__returns_block_device_readonly(self): |
671 | name = factory.make_name('name') |
672 | model = factory.make_name('model') |
673 | + maj_min = (random.randint(0, 255), random.randint(0, 255)) |
674 | serial = factory.make_name('serial') |
675 | size = random.randint(3000 * 1000, 1000 * 1000 * 1000) |
676 | block_size = random.choice([512, 1024, 4096]) |
677 | check_output = self.patch(subprocess, "check_output") |
678 | check_output.side_effect = [ |
679 | - self.make_lsblk_output(name=name, model=model, read_only=True), |
680 | + self.make_lsblk_output( |
681 | + name=name, model=model, read_only=True, maj_min=maj_min), |
682 | self.make_udevadm_output(name, serial=serial), |
683 | b'%d' % size, |
684 | b'%d' % block_size, |
685 | ] |
686 | - self.assertEqual([{ |
687 | - "NAME": name, |
688 | - "PATH": "/dev/%s" % name, |
689 | - "RO": "1", |
690 | - "RM": "0", |
691 | - "MODEL": model, |
692 | - "ROTA": "1", |
693 | - "SATA": "1", |
694 | - "SERIAL": serial, |
695 | - "SIZE": "%s" % size, |
696 | - "BLOCK_SIZE": "%s" % block_size, |
697 | - "RPM": "5400", |
698 | - }], self.call_gather_physical_block_devices()) |
699 | + for ref, out in zip( |
700 | + [ |
701 | + self.make_output( |
702 | + name, maj_min, model, serial, size, |
703 | + block_size, read_only=True), |
704 | + ], self.call_gather_physical_block_devices()): |
705 | + self.assertDictEqual(ref, out) |
706 | |
707 | def test__returns_block_device_ssd(self): |
708 | name = factory.make_name('name') |
709 | model = factory.make_name('model') |
710 | + maj_min = (random.randint(0, 255), random.randint(0, 255)) |
711 | serial = factory.make_name('serial') |
712 | size = random.randint(3000 * 1000, 1000 * 1000 * 1000) |
713 | block_size = random.choice([512, 1024, 4096]) |
714 | check_output = self.patch(subprocess, "check_output") |
715 | check_output.side_effect = [ |
716 | - self.make_lsblk_output(name=name, model=model, rotary=False), |
717 | + self.make_lsblk_output( |
718 | + name=name, model=model, rotary=False, maj_min=maj_min), |
719 | self.make_udevadm_output(name, serial=serial), |
720 | b'%d' % size, |
721 | b'%d' % block_size, |
722 | ] |
723 | - self.assertEqual([{ |
724 | - "NAME": name, |
725 | - "PATH": "/dev/%s" % name, |
726 | - "RO": "0", |
727 | - "RM": "0", |
728 | - "MODEL": model, |
729 | - "ROTA": "0", |
730 | - "SATA": "1", |
731 | - "SERIAL": serial, |
732 | - "SIZE": "%s" % size, |
733 | - "BLOCK_SIZE": "%s" % block_size, |
734 | - "RPM": "5400", |
735 | - }], self.call_gather_physical_block_devices()) |
736 | + for ref, out in zip( |
737 | + [ |
738 | + self.make_output( |
739 | + name, maj_min, model, serial, size, block_size, |
740 | + rotary=False), |
741 | + ], self.call_gather_physical_block_devices()): |
742 | + self.assertDictEqual(ref, out) |
743 | |
744 | def test__returns_block_device_not_sata(self): |
745 | name = factory.make_name('name') |
746 | model = factory.make_name('model') |
747 | + maj_min = (random.randint(0, 255), random.randint(0, 255)) |
748 | serial = factory.make_name('serial') |
749 | size = random.randint(3000 * 1000, 1000 * 1000 * 1000) |
750 | block_size = random.choice([512, 1024, 4096]) |
751 | check_output = self.patch(subprocess, "check_output") |
752 | check_output.side_effect = [ |
753 | - self.make_lsblk_output(name=name, model=model), |
754 | + self.make_lsblk_output(name=name, model=model, maj_min=maj_min), |
755 | self.make_udevadm_output(name, serial=serial, sata=False), |
756 | b'%d' % size, |
757 | b'%d' % block_size, |
758 | ] |
759 | - self.assertEqual([{ |
760 | - "NAME": name, |
761 | - "PATH": "/dev/%s" % name, |
762 | - "RO": "0", |
763 | - "RM": "0", |
764 | - "MODEL": model, |
765 | - "ROTA": "1", |
766 | - "SATA": "0", |
767 | - "SERIAL": serial, |
768 | - "SIZE": "%s" % size, |
769 | - "BLOCK_SIZE": "%s" % block_size, |
770 | - "RPM": "5400", |
771 | - }], self.call_gather_physical_block_devices()) |
772 | + for ref, out in zip( |
773 | + [ |
774 | + self.make_output( |
775 | + name, maj_min, model, serial, size, block_size, |
776 | + sata=False), |
777 | + ], self.call_gather_physical_block_devices()): |
778 | + self.assertDictEqual(ref, out) |
779 | |
780 | def test__returns_block_device_removable(self): |
781 | name = factory.make_name('name') |
782 | model = factory.make_name('model') |
783 | + maj_min = (random.randint(0, 255), random.randint(0, 255)) |
784 | serial = factory.make_name('serial') |
785 | size = random.randint(3000 * 1000, 1000 * 1000 * 1000) |
786 | block_size = random.choice([512, 1024, 4096]) |
787 | check_output = self.patch(subprocess, "check_output") |
788 | check_output.side_effect = [ |
789 | - self.make_lsblk_output(name=name, model=model, removable=True), |
790 | + self.make_lsblk_output( |
791 | + name=name, model=model, removable=True, maj_min=maj_min), |
792 | self.make_udevadm_output(name, serial=serial), |
793 | b'%d' % size, |
794 | b'%d' % block_size, |
795 | ] |
796 | - self.assertEqual([{ |
797 | - "NAME": name, |
798 | - "PATH": "/dev/%s" % name, |
799 | - "RO": "0", |
800 | - "RM": "1", |
801 | - "MODEL": model, |
802 | - "ROTA": "1", |
803 | - "SATA": "1", |
804 | - "SERIAL": serial, |
805 | - "SIZE": "%s" % size, |
806 | - "BLOCK_SIZE": "%s" % block_size, |
807 | - "RPM": "5400", |
808 | - }], self.call_gather_physical_block_devices()) |
809 | - |
810 | - def test__returns_multiple_block_devices_in_order(self): |
811 | - names = [factory.make_name('name') for _ in range(3)] |
812 | - lsblk = [ |
813 | - self.make_lsblk_output(name=name) |
814 | - for name in names |
815 | - ] |
816 | - call_outputs = [] |
817 | - call_outputs.append(b"\n".join(lsblk)) |
818 | - for name in names: |
819 | - call_outputs.append(self.make_udevadm_output(name)) |
820 | - for name in names: |
821 | - call_outputs.append( |
822 | - b"%d" % random.randint(1000 * 1000, 1000 * 1000 * 1000)) |
823 | - call_outputs.append( |
824 | - b"%d" % random.choice([512, 1024, 4096])) |
825 | - check_output = self.patch(subprocess, "check_output") |
826 | - check_output.side_effect = call_outputs |
827 | - device_names = [ |
828 | - block_info['NAME'] |
829 | - for block_info in self.call_gather_physical_block_devices() |
830 | - ] |
831 | - self.assertEqual(names, device_names) |
832 | + for ref, out in zip( |
833 | + [ |
834 | + self.make_output( |
835 | + name, maj_min, model, serial, size, block_size, |
836 | + removable=True), |
837 | + ], self.call_gather_physical_block_devices()): |
838 | + self.assertDictEqual(ref, out) |
839 | |
840 | |
841 | class TestVirtualityScript(MAASTestCase): |
Approved in https:/ /code.launchpad .net/~ltrager/ maas/lp1685361/ +merge/ 322993