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
=== modified file 'src/provisioningserver/refresh/node_info_scripts.py'
--- src/provisioningserver/refresh/node_info_scripts.py 2017-03-22 21:46:10 +0000
+++ src/provisioningserver/refresh/node_info_scripts.py 2017-04-25 09:25:16 +0000
@@ -294,7 +294,7 @@
294 blockdevs = []294 blockdevs = []
295 block_list = check_output((295 block_list = check_output((
296 "lsblk", "--exclude", "1,2,7", "-d", "-P",296 "lsblk", "--exclude", "1,2,7", "-d", "-P",
297 "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN", "-x", "MAJ:MIN"))297 "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN"))
298 block_list = block_list.decode("utf-8")298 block_list = block_list.decode("utf-8")
299 for blockdev in block_list.splitlines():299 for blockdev in block_list.splitlines():
300 tokens = shlex.split(blockdev)300 tokens = shlex.split(blockdev)
@@ -304,6 +304,13 @@
304 current_block[k] = v.strip()304 current_block[k] = v.strip()
305 blockdevs.append(current_block)305 blockdevs.append(current_block)
306306
307 # Sort drives by MAJ:MIN so MAAS picks the correct boot drive.
308 # lsblk -x MAJ:MIN can't be used as the -x flag only appears in
309 # lsblk 2.71.1 or newer which is unavailable on Trusty. See LP:1673724
310 blockdevs = sorted(
311 blockdevs,
312 key=lambda blockdev: [int(i) for i in blockdev['MAJ:MIN'].split(':')])
313
307 # Grab the device path, serial number, and sata connection.314 # Grab the device path, serial number, and sata connection.
308 UDEV_MAPPINGS = {315 UDEV_MAPPINGS = {
309 "DEVNAME": "PATH",316 "DEVNAME": "PATH",
310317
=== modified file 'src/provisioningserver/refresh/tests/test_node_info_scripts.py'
--- src/provisioningserver/refresh/tests/test_node_info_scripts.py 2017-03-22 21:46:10 +0000
+++ src/provisioningserver/refresh/tests/test_node_info_scripts.py 2017-04-25 09:25:16 +0000
@@ -5,7 +5,6 @@
55
6__all__ = []6__all__ = []
77
8from functools import partial
9from inspect import getsource8from inspect import getsource
10from io import StringIO9from io import StringIO
11import json10import json
@@ -18,6 +17,7 @@
18 check_output,17 check_output,
19 STDOUT,18 STDOUT,
20)19)
20import sys
21from textwrap import dedent21from textwrap import dedent
22import time22import time
23from unittest.mock import call23from unittest.mock import call
@@ -338,16 +338,19 @@
338 @typed338 @typed
339 def make_lsblk_output(339 def make_lsblk_output(
340 self, name=None, read_only=False, removable=False,340 self, name=None, read_only=False, removable=False,
341 model=None, rotary=True) -> bytes:341 model=None, rotary=True, maj_min=None) -> bytes:
342 if name is None:342 if name is None:
343 name = factory.make_name('name')343 name = factory.make_name('name')
344 if model is None:344 if model is None:
345 model = factory.make_name('model')345 model = factory.make_name('model')
346 if maj_min is None:
347 maj_min = (random.randint(0, 255), random.randint(0, 255))
346 read_only = "1" if read_only else "0"348 read_only = "1" if read_only else "0"
347 removable = "1" if removable else "0"349 removable = "1" if removable else "0"
348 rotary = "1" if rotary else "0"350 rotary = "1" if rotary else "0"
349 output = 'NAME="%s" RO="%s" RM="%s" MODEL="%s" ROTA="%s"' % (351 output = (
350 name, read_only, removable, model, rotary)352 'NAME="%s" RO="%s" RM="%s" MODEL="%s" ROTA="%s" MAJ:MIN="%s"' % (
353 name, read_only, removable, model, rotary, '%s:%s' % maj_min))
351 return output.encode("ascii")354 return output.encode("ascii")
352355
353 @typed356 @typed
@@ -373,21 +376,54 @@
373 return output.encode("ascii")376 return output.encode("ascii")
374377
375 def call_gather_physical_block_devices(378 def call_gather_physical_block_devices(
376 self, dev_disk_byid='/dev/disk/by-id/'):379 self, dev_disk_byid='/dev/disk/by-id/', file_path=None):
377 output = StringIO()380 output = StringIO()
378 namespace = {"print": partial(print, file=output)}381
382 def neutered_print(*args, **kwargs):
383 file = kwargs.pop('file', None)
384 if file is not None and file == sys.stderr:
385 return
386 return print(*args, **kwargs, file=output)
387
388 namespace = {"print": neutered_print}
389 if file_path is not None:
390 namespace['__file__'] = file_path
379 gather_physical_block_devices = isolate_function(391 gather_physical_block_devices = isolate_function(
380 node_info_module.gather_physical_block_devices, namespace)392 node_info_module.gather_physical_block_devices, namespace)
381 gather_physical_block_devices(dev_disk_byid=dev_disk_byid)393 gather_physical_block_devices(dev_disk_byid=dev_disk_byid)
382 return json.loads(output.getvalue())394 return json.loads(output.getvalue())
383395
396 def make_output(
397 self, name, maj_min, model, serial, size, block_size,
398 drive_path=None, device_id_path=None, rotary=True,
399 removable=False, read_only=False, sata=True):
400 if drive_path is None:
401 drive_path = '/dev/%s' % name
402 ret = {
403 'NAME': name,
404 'PATH': drive_path,
405 'MAJ:MIN': '%s:%s' % maj_min,
406 'RO': '1' if read_only else '0',
407 'RM': '1' if removable else '0',
408 'MODEL': model,
409 'ROTA': '1' if rotary else '0',
410 'SATA': '1' if sata else '0',
411 'SERIAL': serial,
412 'SIZE': str(size),
413 'BLOCK_SIZE': str(block_size),
414 'RPM': '5400',
415 }
416 if device_id_path is not None:
417 ret['ID_PATH'] = device_id_path
418 return ret
419
384 def test__calls_lsblk(self):420 def test__calls_lsblk(self):
385 check_output = self.patch(subprocess, "check_output")421 check_output = self.patch(subprocess, "check_output")
386 check_output.return_value = b""422 check_output.return_value = b""
387 self.call_gather_physical_block_devices()423 self.call_gather_physical_block_devices()
388 self.assertThat(check_output, MockCalledOnceWith((424 self.assertThat(check_output, MockCalledOnceWith((
389 "lsblk", "--exclude", "1,2,7", "-d", "-P",425 "lsblk", "--exclude", "1,2,7", "-d", "-P",
390 "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN", "-x", "MAJ:MIN")))426 "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN")))
391427
392 def test__returns_empty_list_when_no_disks(self):428 def test__returns_empty_list_when_no_disks(self):
393 check_output = self.patch(subprocess, "check_output")429 check_output = self.patch(subprocess, "check_output")
@@ -407,7 +443,7 @@
407 self.assertThat(check_output, MockCallsMatch(443 self.assertThat(check_output, MockCallsMatch(
408 call((444 call((
409 "lsblk", "--exclude", "1,2,7", "-d", "-P",445 "lsblk", "--exclude", "1,2,7", "-d", "-P",
410 "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN", "-x", "MAJ:MIN")),446 "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN")),
411 call(("udevadm", "info", "-q", "all", "-n", name))))447 call(("udevadm", "info", "-q", "all", "-n", name))))
412448
413 def test__returns_empty_list_when_cdrom_only(self):449 def test__returns_empty_list_when_cdrom_only(self):
@@ -439,128 +475,52 @@
439 self.assertThat(check_output, MockCallsMatch(475 self.assertThat(check_output, MockCallsMatch(
440 call((476 call((
441 "lsblk", "--exclude", "1,2,7", "-d", "-P",477 "lsblk", "--exclude", "1,2,7", "-d", "-P",
442 "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN", "-x", "MAJ:MIN")),478 "-o", "NAME,RO,RM,MODEL,ROTA,MAJ:MIN")),
443 call(("udevadm", "info", "-q", "all", "-n", name)),479 call(("udevadm", "info", "-q", "all", "-n", name)),
444 call(("sudo", "blockdev", "--getsize64", "/dev/%s" % name)),480 call(("sudo", "blockdev", "--getsize64", "/dev/%s" % name)),
445 call(("sudo", "blockdev", "--getbsz", "/dev/%s" % name))))481 call(("sudo", "blockdev", "--getbsz", "/dev/%s" % name))))
446482
447 def test__returns_block_device(self):483 def test__returns_sorted_block_devices(self):
448 name = factory.make_name('name')484 output = []
449 model = factory.make_name('model')485 check_output_side_effects = []
450 serial = factory.make_name('serial')486 # Create simulated /dev tree
451 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)487 devroot = self.make_dir()
452 block_size = random.choice([512, 1024, 4096])488 os.mkdir(os.path.join(devroot, 'disk'))
453 check_output = self.patch(subprocess, "check_output")489 byidroot = os.path.join(devroot, 'disk', 'by_id')
454490 os.mkdir(byidroot)
455 # Create simulated /dev tree491 for _ in range(3):
456 devroot = self.make_dir()492 name = factory.make_name('name')
457 os.mkdir(os.path.join(devroot, 'disk'))493 model = factory.make_name('model')
458 byidroot = os.path.join(devroot, 'disk', 'by_id')494 serial = factory.make_name('serial')
459 os.mkdir(byidroot)495 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)
460 os.mknod(os.path.join(devroot, name))496 block_size = random.choice([512, 1024, 4096])
461 os.symlink(os.path.join(devroot, name),497 maj_min = (random.randint(0, 255), random.randint(0, 255))
462 os.path.join(byidroot, 'deviceid'))498
463499 # Create simulated /dev tree
464 check_output.side_effect = [500 drive_path = os.path.join(devroot, name)
465 self.make_lsblk_output(name=name, model=model),501 os.mknod(drive_path)
466 self.make_udevadm_output(name, serial=serial, dev=devroot),502 device_id_path = os.path.join(
467 b'%d' % size,503 byidroot, factory.make_name('deviceid'))
468 b'%d' % block_size,504 os.symlink(drive_path, device_id_path)
469 ]505
470 self.assertEqual([{506 check_output_side_effects += [
471 "NAME": name,507 self.make_lsblk_output(
472 "PATH": os.path.join(devroot, name),508 name=name, model=model, maj_min=maj_min),
473 "ID_PATH": os.path.join(byidroot, 'deviceid'),509 self.make_udevadm_output(name, serial=serial, dev=devroot),
474 "RO": "0",510 b'%d' % size,
475 "RM": "0",511 b'%d' % block_size,
476 "MODEL": model,512 ]
477 "ROTA": "1",513 output.append(
478 "SATA": "1",514 self.make_output(
479 "SERIAL": serial,515 name, maj_min, model, serial, size, block_size,
480 "SIZE": "%s" % size,516 drive_path, device_id_path))
481 "BLOCK_SIZE": "%s" % block_size,517
482 "RPM": "5400",518 check_output = self.patch(subprocess, "check_output")
483 }], self.call_gather_physical_block_devices(byidroot))519 check_output.side_effect = check_output_side_effects
484520
485 def test__returns_block_device_with_shortest_byidpath_long_first(self):521 for ref, out in zip(
486 name = factory.make_name('name')522 output, self.call_gather_physical_block_devices(byidroot)):
487 model = factory.make_name('model')523 self.assertDictEqual(ref, out)
488 serial = factory.make_name('serial')
489 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)
490 block_size = random.choice([512, 1024, 4096])
491 check_output = self.patch(subprocess, "check_output")
492
493 # Create simulated /dev tree
494 devroot = self.make_dir()
495 os.mkdir(os.path.join(devroot, 'disk'))
496 byidroot = os.path.join(devroot, 'disk', 'by_id')
497 os.mkdir(byidroot)
498 os.mknod(os.path.join(devroot, name))
499 os.symlink(os.path.join(devroot, name),
500 os.path.join(byidroot, 'deviceid-long'))
501 os.symlink(os.path.join(devroot, name),
502 os.path.join(byidroot, 'deviceid'))
503
504 check_output.side_effect = [
505 self.make_lsblk_output(name=name, model=model),
506 self.make_udevadm_output(name, serial=serial, dev=devroot),
507 b'%d' % size,
508 b'%d' % block_size,
509 ]
510 self.assertEqual([{
511 "NAME": name,
512 "PATH": os.path.join(devroot, name),
513 "ID_PATH": os.path.join(byidroot, 'deviceid'),
514 "RO": "0",
515 "RM": "0",
516 "MODEL": model,
517 "ROTA": "1",
518 "SATA": "1",
519 "SERIAL": serial,
520 "SIZE": "%s" % size,
521 "BLOCK_SIZE": "%s" % block_size,
522 "RPM": "5400",
523 }], self.call_gather_physical_block_devices(byidroot))
524
525 def test__returns_block_device_with_first_byidpath_long_second(self):
526 name = factory.make_name('name')
527 model = factory.make_name('model')
528 serial = factory.make_name('serial')
529 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)
530 block_size = random.choice([512, 1024, 4096])
531 check_output = self.patch(subprocess, "check_output")
532
533 # Create simulated /dev tree
534 devroot = self.make_dir()
535 os.mkdir(os.path.join(devroot, 'disk'))
536 byidroot = os.path.join(devroot, 'disk', 'by_id')
537 os.mkdir(byidroot)
538 os.mknod(os.path.join(devroot, name))
539 os.symlink(os.path.join(devroot, name),
540 os.path.join(byidroot, 'deviceid'))
541 os.symlink(os.path.join(devroot, name),
542 os.path.join(byidroot, 'deviceid-longest'))
543
544 check_output.side_effect = [
545 self.make_lsblk_output(name=name, model=model),
546 self.make_udevadm_output(name, serial=serial, dev=devroot),
547 b'%d' % size,
548 b'%d' % block_size,
549 ]
550 self.assertEqual([{
551 "NAME": name,
552 "PATH": os.path.join(devroot, name),
553 "ID_PATH": os.path.join(byidroot, 'deviceid'),
554 "RO": "0",
555 "RM": "0",
556 "MODEL": model,
557 "ROTA": "1",
558 "SATA": "1",
559 "SERIAL": serial,
560 "SIZE": "%s" % size,
561 "BLOCK_SIZE": "%s" % block_size,
562 "RPM": "5400",
563 }], self.call_gather_physical_block_devices(byidroot))
564524
565 def test__removes_duplicate_block_device_same_serial_and_model(self):525 def test__removes_duplicate_block_device_same_serial_and_model(self):
566 """Multipath disks get multiple IDs, but same serial/model is same526 """Multipath disks get multiple IDs, but same serial/model is same
@@ -570,107 +530,51 @@
570 serial = factory.make_name('serial')530 serial = factory.make_name('serial')
571 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)531 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)
572 block_size = random.choice([512, 1024, 4096])532 block_size = random.choice([512, 1024, 4096])
573 check_output = self.patch(subprocess, "check_output")533 maj_min = (random.randint(0, 255), random.randint(0, 255))
574534 check_output = self.patch(subprocess, "check_output")
575 name2 = factory.make_name('name')535
576536 name2 = factory.make_name('name')
577 # Create simulated /dev tree.537
578 devroot = self.make_dir()538 # Create simulated /dev tree.
579 os.mkdir(os.path.join(devroot, 'disk'))539 devroot = self.make_dir()
580 byidroot = os.path.join(devroot, 'disk', 'by_id')540 os.mkdir(os.path.join(devroot, 'disk'))
581 os.mkdir(byidroot)541 byidroot = os.path.join(devroot, 'disk', 'by_id')
582542 os.mkdir(byidroot)
583 os.mknod(os.path.join(devroot, name))543
584 os.symlink(os.path.join(devroot, name),544 drive_path = os.path.join(devroot, name)
585 os.path.join(byidroot, 'deviceid'))545 os.mknod(drive_path)
586546 device_id_path = os.path.join(byidroot, 'deviceid')
587 os.mknod(os.path.join(devroot, name2))547 os.symlink(os.path.join(devroot, name), device_id_path)
588 os.symlink(os.path.join(devroot, name2),548
589 os.path.join(byidroot, 'deviceid2'))549 os.mknod(os.path.join(devroot, name2))
590550 device_id_path2 = os.path.join(byidroot, 'deviceid2')
591 check_output.side_effect = [551 os.symlink(os.path.join(devroot, name2), device_id_path2)
592 b"\n".join([552
593 self.make_lsblk_output(name=name, model=model),553 check_output.side_effect = [
594 self.make_lsblk_output(name=name2, model=model)]),554 b"\n".join([
595 self.make_udevadm_output(name, serial=serial, dev=devroot),555 self.make_lsblk_output(
596 self.make_udevadm_output(name2, serial=serial, dev=devroot),556 name=name, model=model, maj_min=maj_min),
597 b'%d' % size,557 self.make_lsblk_output(
598 b'%d' % block_size,558 name=name2, model=model, maj_min=maj_min)]),
599 b'%d' % size,559 self.make_udevadm_output(name, serial=serial, dev=devroot),
600 b'%d' % block_size,560 self.make_udevadm_output(name2, serial=serial, dev=devroot),
601 ]561 b'%d' % size,
602562 b'%d' % block_size,
603 self.assertEqual([{563 b'%d' % size,
604 "NAME": name,564 b'%d' % block_size,
605 "PATH": os.path.join(devroot, name),565 ]
606 "ID_PATH": os.path.join(byidroot, 'deviceid'),566
607 "RO": "0",567 self.assertItemsEqual(
608 "RM": "0",568 [self.make_output(
609 "MODEL": model,569 name, maj_min, model, serial, size, block_size, drive_path,
610 "ROTA": "1",570 device_id_path)],
611 "SATA": "1",571 self.call_gather_physical_block_devices(byidroot))
612 "SERIAL": serial,
613 "SIZE": "%s" % size,
614 "BLOCK_SIZE": "%s" % block_size,
615 "RPM": "5400",
616 }], self.call_gather_physical_block_devices(byidroot))
617
618 def test__removes_duplicate_block_device_same_serial_blank_model(self):
619 """Multipath disks get multiple IDs, but same serial is same device."""
620 name = factory.make_name('name')
621 model = ""
622 serial = factory.make_name('serial')
623 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)
624 block_size = random.choice([512, 1024, 4096])
625 check_output = self.patch(subprocess, "check_output")
626
627 name2 = factory.make_name('name')
628
629 # Create simulated /dev tree.
630 devroot = self.make_dir()
631 os.mkdir(os.path.join(devroot, 'disk'))
632 byidroot = os.path.join(devroot, 'disk', 'by_id')
633 os.mkdir(byidroot)
634
635 os.mknod(os.path.join(devroot, name))
636 os.symlink(os.path.join(devroot, name),
637 os.path.join(byidroot, 'deviceid'))
638
639 os.mknod(os.path.join(devroot, name2))
640 os.symlink(os.path.join(devroot, name2),
641 os.path.join(byidroot, 'deviceid2'))
642
643 check_output.side_effect = [
644 b"\n".join([
645 self.make_lsblk_output(name=name, model=model),
646 self.make_lsblk_output(name=name2, model=model)]),
647 self.make_udevadm_output(name, serial=serial, dev=devroot),
648 self.make_udevadm_output(name2, serial=serial, dev=devroot),
649 b'%d' % size,
650 b'%d' % block_size,
651 b'%d' % size,
652 b'%d' % block_size,
653 ]
654
655 self.assertEqual([{
656 "NAME": name,
657 "PATH": os.path.join(devroot, name),
658 "ID_PATH": os.path.join(byidroot, 'deviceid'),
659 "RO": "0",
660 "RM": "0",
661 "MODEL": model,
662 "ROTA": "1",
663 "SATA": "1",
664 "SERIAL": serial,
665 "SIZE": "%s" % size,
666 "BLOCK_SIZE": "%s" % block_size,
667 "RPM": "5400",
668 }], self.call_gather_physical_block_devices(byidroot))
669572
670 def test__keeps_block_device_same_serial_different_model(self):573 def test__keeps_block_device_same_serial_different_model(self):
671 """Multipath disks get multiple IDs, but same serial is same device."""574 """Multipath disks get multiple IDs, but same serial is same device."""
672 name = factory.make_name('name')575 name = factory.make_name('name')
673 model = factory.make_name('model')576 model = factory.make_name('model')
577 maj_min = (0, 0)
674 serial = factory.make_name('serial')578 serial = factory.make_name('serial')
675 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)579 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)
676 block_size = random.choice([512, 1024, 4096])580 block_size = random.choice([512, 1024, 4096])
@@ -678,6 +582,7 @@
678582
679 name2 = factory.make_name('name')583 name2 = factory.make_name('name')
680 model2 = factory.make_name('model')584 model2 = factory.make_name('model')
585 maj_min2 = (1, 1)
681586
682 # Create simulated /dev tree.587 # Create simulated /dev tree.
683 devroot = self.make_dir()588 devroot = self.make_dir()
@@ -685,18 +590,23 @@
685 byidroot = os.path.join(devroot, 'disk', 'by_id')590 byidroot = os.path.join(devroot, 'disk', 'by_id')
686 os.mkdir(byidroot)591 os.mkdir(byidroot)
687592
688 os.mknod(os.path.join(devroot, name))593 drive_path = os.path.join(devroot, name)
689 os.symlink(os.path.join(devroot, name),594 os.mknod(drive_path)
690 os.path.join(byidroot, 'deviceid'))595 device_id_path = os.path.join(byidroot, 'deviceid')
596 os.symlink(os.path.join(devroot, name), device_id_path)
691597
692 os.mknod(os.path.join(devroot, name2))598 drive_path2 = os.path.join(devroot, name2)
693 os.symlink(os.path.join(devroot, name2),599 os.mknod(drive_path2)
694 os.path.join(byidroot, 'deviceid2'))600 device_id_path2 = os.path.join(byidroot, 'deviceid2')
601 os.symlink(os.path.join(devroot, name2), device_id_path2)
695602
696 check_output.side_effect = [603 check_output.side_effect = [
697 b"\n".join([604 b"\n".join([
698 self.make_lsblk_output(name=name, model=model),605 self.make_lsblk_output(
699 self.make_lsblk_output(name=name2, model=model2)]),606 name=name, model=model, maj_min=maj_min),
607 self.make_lsblk_output(
608 name=name2, model=model2, maj_min=maj_min2)
609 ]),
700 self.make_udevadm_output(name, serial=serial, dev=devroot),610 self.make_udevadm_output(name, serial=serial, dev=devroot),
701 self.make_udevadm_output(name2, serial=serial, dev=devroot),611 self.make_udevadm_output(name2, serial=serial, dev=devroot),
702 b'%d' % size,612 b'%d' % size,
@@ -705,44 +615,29 @@
705 b'%d' % block_size,615 b'%d' % block_size,
706 ]616 ]
707617
708 self.assertEqual([{618 for ref, out in zip(
709 "NAME": name,619 [
710 "PATH": os.path.join(devroot, name),620 self.make_output(
711 "ID_PATH": os.path.join(byidroot, 'deviceid'),621 name, maj_min, model, serial, size, block_size,
712 "RO": "0",622 drive_path, device_id_path),
713 "RM": "0",623 self.make_output(
714 "MODEL": model,624 name2, maj_min2, model2, serial, size, block_size,
715 "ROTA": "1",625 drive_path2, device_id_path2),
716 "SATA": "1",626 ], self.call_gather_physical_block_devices(byidroot)):
717 "SERIAL": serial,627 self.assertDictEqual(ref, out)
718 "SIZE": "%s" % size,
719 "BLOCK_SIZE": "%s" % block_size,
720 "RPM": "5400",
721 }, {
722 "NAME": name2,
723 "PATH": os.path.join(devroot, name2),
724 "ID_PATH": os.path.join(byidroot, 'deviceid2'),
725 "RO": "0",
726 "RM": "0",
727 "MODEL": model2,
728 "ROTA": "1",
729 "SATA": "1",
730 "SERIAL": serial,
731 "SIZE": "%s" % size,
732 "BLOCK_SIZE": "%s" % block_size,
733 "RPM": "5400",
734 }], self.call_gather_physical_block_devices(byidroot))
735628
736 def test__keeps_block_device_blank_serial_same_model(self):629 def test__keeps_block_device_blank_serial_same_model(self):
737 """Multipath disks get multiple IDs, but same serial is same device."""630 """Multipath disks get multiple IDs, but same serial is same device."""
738 name = factory.make_name('name')631 name = factory.make_name('name')
739 model = factory.make_name('model')632 model = factory.make_name('model')
633 maj_min = (0, 0)
740 serial = ''634 serial = ''
741 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)635 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)
742 block_size = random.choice([512, 1024, 4096])636 block_size = random.choice([512, 1024, 4096])
743 check_output = self.patch(subprocess, "check_output")637 check_output = self.patch(subprocess, "check_output")
744638
745 name2 = factory.make_name('name')639 name2 = factory.make_name('name')
640 maj_min2 = (1, 1)
746641
747 # Create simulated /dev tree.642 # Create simulated /dev tree.
748 devroot = self.make_dir()643 devroot = self.make_dir()
@@ -750,18 +645,22 @@
750 byidroot = os.path.join(devroot, 'disk', 'by_id')645 byidroot = os.path.join(devroot, 'disk', 'by_id')
751 os.mkdir(byidroot)646 os.mkdir(byidroot)
752647
753 os.mknod(os.path.join(devroot, name))648 drive_path = os.path.join(devroot, name)
754 os.symlink(os.path.join(devroot, name),649 os.mknod(drive_path)
755 os.path.join(byidroot, 'deviceid'))650 device_id_path = os.path.join(byidroot, 'deviceid')
651 os.symlink(os.path.join(devroot, name), device_id_path)
756652
757 os.mknod(os.path.join(devroot, name2))653 drive_path2 = os.path.join(devroot, name2)
758 os.symlink(os.path.join(devroot, name2),654 os.mknod(drive_path2)
759 os.path.join(byidroot, 'deviceid2'))655 device_id_path2 = os.path.join(byidroot, 'deviceid2')
656 os.symlink(os.path.join(devroot, name2), device_id_path2)
760657
761 check_output.side_effect = [658 check_output.side_effect = [
762 b"\n".join([659 b"\n".join([
763 self.make_lsblk_output(name=name, model=model),660 self.make_lsblk_output(
764 self.make_lsblk_output(name=name2, model=model)]),661 name=name, model=model, maj_min=maj_min),
662 self.make_lsblk_output(
663 name=name2, model=model, maj_min=maj_min2)]),
765 self.make_udevadm_output(name, serial=serial, dev=devroot),664 self.make_udevadm_output(name, serial=serial, dev=devroot),
766 self.make_udevadm_output(name2, serial=serial, dev=devroot),665 self.make_udevadm_output(name2, serial=serial, dev=devroot),
767 b'%d' % size,666 b'%d' % size,
@@ -770,38 +669,22 @@
770 b'%d' % block_size,669 b'%d' % block_size,
771 ]670 ]
772671
773 self.assertEqual([{672 for ref, out in zip(
774 "NAME": name,673 [
775 "PATH": os.path.join(devroot, name),674 self.make_output(
776 "ID_PATH": os.path.join(byidroot, 'deviceid'),675 name, maj_min, model, serial, size, block_size,
777 "RO": "0",676 drive_path, device_id_path),
778 "RM": "0",677 self.make_output(
779 "MODEL": model,678 name2, maj_min2, model, serial, size, block_size,
780 "ROTA": "1",679 drive_path2, device_id_path2),
781 "SATA": "1",680 ], self.call_gather_physical_block_devices(byidroot)):
782 "SERIAL": serial,681 self.assertDictEqual(ref, out)
783 "SIZE": "%s" % size,
784 "BLOCK_SIZE": "%s" % block_size,
785 "RPM": "5400",
786 }, {
787 "NAME": name2,
788 "PATH": os.path.join(devroot, name2),
789 "ID_PATH": os.path.join(byidroot, 'deviceid2'),
790 "RO": "0",
791 "RM": "0",
792 "MODEL": model,
793 "ROTA": "1",
794 "SATA": "1",
795 "SERIAL": serial,
796 "SIZE": "%s" % size,
797 "BLOCK_SIZE": "%s" % block_size,
798 "RPM": "5400",
799 }], self.call_gather_physical_block_devices(byidroot))
800682
801 def test__returns_block_device_without_id_path(self):683 def test__returns_block_device_without_id_path(self):
802 """Block devices without by-id links should not have ID_PATH key"""684 """Block devices without by-id links should not have ID_PATH key"""
803 name = factory.make_name('name')685 name = factory.make_name('name')
804 model = factory.make_name('model')686 model = factory.make_name('model')
687 maj_min = (random.randint(0, 255), random.randint(0, 255))
805 serial = factory.make_name('serial')688 serial = factory.make_name('serial')
806 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)689 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)
807 block_size = random.choice([512, 1024, 4096])690 block_size = random.choice([512, 1024, 4096])
@@ -812,158 +695,113 @@
812 os.mkdir(os.path.join(devroot, 'disk'))695 os.mkdir(os.path.join(devroot, 'disk'))
813 byidroot = os.path.join(devroot, 'disk', 'by_id')696 byidroot = os.path.join(devroot, 'disk', 'by_id')
814 os.mkdir(byidroot)697 os.mkdir(byidroot)
815 os.mknod(os.path.join(devroot, name))698 drive_path = os.path.join(devroot, name)
699 os.mknod(drive_path)
816700
817 check_output.side_effect = [701 check_output.side_effect = [
818 self.make_lsblk_output(name=name, model=model),702 self.make_lsblk_output(name=name, model=model, maj_min=maj_min),
819 self.make_udevadm_output(name, serial=serial, dev=devroot),703 self.make_udevadm_output(name, serial=serial, dev=devroot),
820 b'%d' % size,704 b'%d' % size,
821 b'%d' % block_size,705 b'%d' % block_size,
822 ]706 ]
823 self.assertEqual([{707 for ref, out in zip(
824 "NAME": name,708 [
825 "PATH": os.path.join(devroot, name),709 self.make_output(
826 "RO": "0",710 name, maj_min, model, serial, size, block_size,
827 "RM": "0",711 drive_path),
828 "MODEL": model,712 ], self.call_gather_physical_block_devices(byidroot)):
829 "ROTA": "1",713 self.assertDictEqual(ref, out)
830 "SATA": "1",
831 "SERIAL": serial,
832 "SIZE": "%s" % size,
833 "BLOCK_SIZE": "%s" % block_size,
834 "RPM": "5400",
835 }], self.call_gather_physical_block_devices(byidroot))
836714
837 def test__returns_block_device_readonly(self):715 def test__returns_block_device_readonly(self):
838 name = factory.make_name('name')716 name = factory.make_name('name')
839 model = factory.make_name('model')717 model = factory.make_name('model')
718 maj_min = (random.randint(0, 255), random.randint(0, 255))
840 serial = factory.make_name('serial')719 serial = factory.make_name('serial')
841 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)720 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)
842 block_size = random.choice([512, 1024, 4096])721 block_size = random.choice([512, 1024, 4096])
843 check_output = self.patch(subprocess, "check_output")722 check_output = self.patch(subprocess, "check_output")
844 check_output.side_effect = [723 check_output.side_effect = [
845 self.make_lsblk_output(name=name, model=model, read_only=True),724 self.make_lsblk_output(
725 name=name, model=model, read_only=True, maj_min=maj_min),
846 self.make_udevadm_output(name, serial=serial),726 self.make_udevadm_output(name, serial=serial),
847 b'%d' % size,727 b'%d' % size,
848 b'%d' % block_size,728 b'%d' % block_size,
849 ]729 ]
850 self.assertEqual([{730 for ref, out in zip(
851 "NAME": name,731 [
852 "PATH": "/dev/%s" % name,732 self.make_output(
853 "RO": "1",733 name, maj_min, model, serial, size,
854 "RM": "0",734 block_size, read_only=True),
855 "MODEL": model,735 ], self.call_gather_physical_block_devices()):
856 "ROTA": "1",736 self.assertDictEqual(ref, out)
857 "SATA": "1",
858 "SERIAL": serial,
859 "SIZE": "%s" % size,
860 "BLOCK_SIZE": "%s" % block_size,
861 "RPM": "5400",
862 }], self.call_gather_physical_block_devices())
863737
864 def test__returns_block_device_ssd(self):738 def test__returns_block_device_ssd(self):
865 name = factory.make_name('name')739 name = factory.make_name('name')
866 model = factory.make_name('model')740 model = factory.make_name('model')
741 maj_min = (random.randint(0, 255), random.randint(0, 255))
867 serial = factory.make_name('serial')742 serial = factory.make_name('serial')
868 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)743 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)
869 block_size = random.choice([512, 1024, 4096])744 block_size = random.choice([512, 1024, 4096])
870 check_output = self.patch(subprocess, "check_output")745 check_output = self.patch(subprocess, "check_output")
871 check_output.side_effect = [746 check_output.side_effect = [
872 self.make_lsblk_output(name=name, model=model, rotary=False),747 self.make_lsblk_output(
748 name=name, model=model, rotary=False, maj_min=maj_min),
873 self.make_udevadm_output(name, serial=serial),749 self.make_udevadm_output(name, serial=serial),
874 b'%d' % size,750 b'%d' % size,
875 b'%d' % block_size,751 b'%d' % block_size,
876 ]752 ]
877 self.assertEqual([{753 for ref, out in zip(
878 "NAME": name,754 [
879 "PATH": "/dev/%s" % name,755 self.make_output(
880 "RO": "0",756 name, maj_min, model, serial, size, block_size,
881 "RM": "0",757 rotary=False),
882 "MODEL": model,758 ], self.call_gather_physical_block_devices()):
883 "ROTA": "0",759 self.assertDictEqual(ref, out)
884 "SATA": "1",
885 "SERIAL": serial,
886 "SIZE": "%s" % size,
887 "BLOCK_SIZE": "%s" % block_size,
888 "RPM": "5400",
889 }], self.call_gather_physical_block_devices())
890760
891 def test__returns_block_device_not_sata(self):761 def test__returns_block_device_not_sata(self):
892 name = factory.make_name('name')762 name = factory.make_name('name')
893 model = factory.make_name('model')763 model = factory.make_name('model')
764 maj_min = (random.randint(0, 255), random.randint(0, 255))
894 serial = factory.make_name('serial')765 serial = factory.make_name('serial')
895 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)766 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)
896 block_size = random.choice([512, 1024, 4096])767 block_size = random.choice([512, 1024, 4096])
897 check_output = self.patch(subprocess, "check_output")768 check_output = self.patch(subprocess, "check_output")
898 check_output.side_effect = [769 check_output.side_effect = [
899 self.make_lsblk_output(name=name, model=model),770 self.make_lsblk_output(name=name, model=model, maj_min=maj_min),
900 self.make_udevadm_output(name, serial=serial, sata=False),771 self.make_udevadm_output(name, serial=serial, sata=False),
901 b'%d' % size,772 b'%d' % size,
902 b'%d' % block_size,773 b'%d' % block_size,
903 ]774 ]
904 self.assertEqual([{775 for ref, out in zip(
905 "NAME": name,776 [
906 "PATH": "/dev/%s" % name,777 self.make_output(
907 "RO": "0",778 name, maj_min, model, serial, size, block_size,
908 "RM": "0",779 sata=False),
909 "MODEL": model,780 ], self.call_gather_physical_block_devices()):
910 "ROTA": "1",781 self.assertDictEqual(ref, out)
911 "SATA": "0",
912 "SERIAL": serial,
913 "SIZE": "%s" % size,
914 "BLOCK_SIZE": "%s" % block_size,
915 "RPM": "5400",
916 }], self.call_gather_physical_block_devices())
917782
918 def test__returns_block_device_removable(self):783 def test__returns_block_device_removable(self):
919 name = factory.make_name('name')784 name = factory.make_name('name')
920 model = factory.make_name('model')785 model = factory.make_name('model')
786 maj_min = (random.randint(0, 255), random.randint(0, 255))
921 serial = factory.make_name('serial')787 serial = factory.make_name('serial')
922 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)788 size = random.randint(3000 * 1000, 1000 * 1000 * 1000)
923 block_size = random.choice([512, 1024, 4096])789 block_size = random.choice([512, 1024, 4096])
924 check_output = self.patch(subprocess, "check_output")790 check_output = self.patch(subprocess, "check_output")
925 check_output.side_effect = [791 check_output.side_effect = [
926 self.make_lsblk_output(name=name, model=model, removable=True),792 self.make_lsblk_output(
793 name=name, model=model, removable=True, maj_min=maj_min),
927 self.make_udevadm_output(name, serial=serial),794 self.make_udevadm_output(name, serial=serial),
928 b'%d' % size,795 b'%d' % size,
929 b'%d' % block_size,796 b'%d' % block_size,
930 ]797 ]
931 self.assertEqual([{798 for ref, out in zip(
932 "NAME": name,799 [
933 "PATH": "/dev/%s" % name,800 self.make_output(
934 "RO": "0",801 name, maj_min, model, serial, size, block_size,
935 "RM": "1",802 removable=True),
936 "MODEL": model,803 ], self.call_gather_physical_block_devices()):
937 "ROTA": "1",804 self.assertDictEqual(ref, out)
938 "SATA": "1",
939 "SERIAL": serial,
940 "SIZE": "%s" % size,
941 "BLOCK_SIZE": "%s" % block_size,
942 "RPM": "5400",
943 }], self.call_gather_physical_block_devices())
944
945 def test__returns_multiple_block_devices_in_order(self):
946 names = [factory.make_name('name') for _ in range(3)]
947 lsblk = [
948 self.make_lsblk_output(name=name)
949 for name in names
950 ]
951 call_outputs = []
952 call_outputs.append(b"\n".join(lsblk))
953 for name in names:
954 call_outputs.append(self.make_udevadm_output(name))
955 for name in names:
956 call_outputs.append(
957 b"%d" % random.randint(1000 * 1000, 1000 * 1000 * 1000))
958 call_outputs.append(
959 b"%d" % random.choice([512, 1024, 4096]))
960 check_output = self.patch(subprocess, "check_output")
961 check_output.side_effect = call_outputs
962 device_names = [
963 block_info['NAME']
964 for block_info in self.call_gather_physical_block_devices()
965 ]
966 self.assertEqual(names, device_names)
967805
968806
969class TestVirtualityScript(MAASTestCase):807class TestVirtualityScript(MAASTestCase):

Subscribers

People subscribed via source and target branches

to all changes: