Merge lp:~ltrager/maas/lp1685361_2.1 into lp:maas/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
Reviewer Review Type Date Requested Status
Lee Trager (community) Approve
Review via email: mp+323114@code.launchpad.net

Commit message

Fix 00-maas-07-block-devices to run on Trusty.

To post a comment you must log in.
Revision history for this message
Lee Trager (ltrager) wrote :
review: Approve

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):

Subscribers

People subscribed via source and target branches

to all changes: