Ejemplo n.º 1
0
    def test_device_name(self):
        # check that devicetree.names property contains all device's names

        # mock lvs_info to avoid blockdev call allowing run as non-root
        with patch.object(LVsInfo, 'cache',
                          new_callable=PropertyMock) as mock_lvs_cache:
            mock_lvs_cache.return_value = {"sdmock": "dummy"}

            tree = DeviceTree()
            dev_names = ["sda", "sdb", "sdc"]

            for dev_name in dev_names:
                dev = DiskDevice(dev_name)
                tree._add_device(dev)
                self.assertTrue(dev in tree.devices)

            # frobnicate a bit with the hidden status of the devices:
            # * hide sda
            # * hide and unhide again sdb
            # * leave sdc unchanged
            tree.hide(tree.get_device_by_name("sda"))
            tree.hide(tree.get_device_by_name("sdb"))
            tree.unhide(tree.get_device_by_name("sdb", hidden=True))

            # some lvs names may be already present in the system (mocked)
            lv_info = list(lvs_info.cache.keys())

            # all devices should still be present in the tree.names
            self.assertEqual(sorted(tree.names), sorted(lv_info + dev_names))
Ejemplo n.º 2
0
    def test_run(self, *args):
        """Test multipath device populator."""
        device_get_name = args[0]
        add_slave_devices = args[1]

        devicetree = DeviceTree()
        data = {"DM_UUID": "1-2-3-4"}

        device_name = "mpathtest"
        device_get_name.return_value = device_name
        slave_1 = Mock(tags=set())
        slave_1.parents = []
        slave_2 = Mock(tags=set())
        slave_2.parents = []
        devicetree._add_device(slave_1)
        devicetree._add_device(slave_2)
        add_slave_devices.return_value = [slave_1, slave_2]

        helper = self.helper_class(devicetree, data)

        device = helper.run()
        self.assertIsInstance(device, MultipathDevice)
        self.assertTrue(device.exists)
        self.assertEqual(device.name, device_name)
        self.assertTrue(device in devicetree.devices)
Ejemplo n.º 3
0
    def test_expand_taglist(self):
        tree = DeviceTree()

        sda = DiskDevice("sda")
        sdb = DiskDevice("sdb")
        sdc = DiskDevice("sdc")
        sdd = DiskDevice("sdd")

        tree._add_device(sda)
        tree._add_device(sdb)
        tree._add_device(sdc)
        tree._add_device(sdd)

        sda.tags = {Tags.remote}
        sdb.tags = {Tags.ssd}
        sdc.tags = {Tags.local, Tags.ssd}
        sdd.tags = set()

        self.assertEqual(tree.expand_taglist(["sda", "sdb"]), {"sda", "sdb"})
        self.assertEqual(tree.expand_taglist(["@local"]), {"sdc"})
        self.assertEqual(tree.expand_taglist(["@ssd"]), {"sdb", "sdc"})
        self.assertEqual(tree.expand_taglist(["@ssd", "sdd", "@local"]),
                         {"sdb", "sdc", "sdd"})
        with self.assertRaises(ValueError):
            tree.expand_taglist(["sdd", "@invalid_tag"])
Ejemplo n.º 4
0
    def test_run(self, *args):
        """Test multipath device populator."""
        device_get_name = args[0]
        add_slave_devices = args[1]

        devicetree = DeviceTree()
        # set up some fake udev data to verify handling of specific entries
        data = Mock()
        _data = {"ID_WWN": "0x5000c50086fb75ca", "DM_UUID": "1-2-3-4"}

        def _getitem_(key, extra=None):
            return _data.get(key, extra)

        data.get = Mock(side_effect=_getitem_)
        data.__getitem__ = Mock(side_effect=_getitem_)

        device_name = "mpathtest"
        device_get_name.return_value = device_name
        slave_1 = Mock(tags=set())
        slave_1.parents = []
        slave_2 = Mock(tags=set())
        slave_2.parents = []
        devicetree._add_device(slave_1)
        devicetree._add_device(slave_2)
        add_slave_devices.return_value = [slave_1, slave_2]

        helper = self.helper_class(devicetree, data)

        device = helper.run()
        self.assertIsInstance(device, MultipathDevice)
        self.assertTrue(device.exists)
        self.assertEqual(device.name, device_name)
        self.assertEqual(device.wwn, _data["ID_WWN"])
        self.assertTrue(device in devicetree.devices)
Ejemplo n.º 5
0
    def test_run(self, *args):
        """Test partition device populator."""
        device_get_partition_disk = args[0]
        device_get_name = args[1]
        get_device_by_name = args[2]

        devicetree = DeviceTree()
        data = Mock()

        # for every case:
        #   1. device(s) in tree
        #   2. lvm filter updated
        #   3. exceptions raised

        # base case: disk is already in the tree, normal disk
        fmt = get_format("disklabel", exists=True, device="/dev/xyz")
        disk = DiskDevice("xyz", fmt=fmt, exists=True)
        devicetree._add_device(disk)

        device_name = "xyz1"
        device_get_name.return_value = device_name
        device_get_partition_disk.return_value = "xyz"
        get_device_by_name.return_value = disk
        helper = self.helper_class(devicetree, data)

        device = helper.run()
        self.assertIsInstance(device, PartitionDevice)
        self.assertTrue(device.exists)
        self.assertEqual(device.name, device_name)
        self.assertTrue(device in devicetree.devices)
Ejemplo n.º 6
0
    def test_run(self, *args):
        """Test partition device populator."""
        device_get_partition_disk = args[0]
        device_get_name = args[1]
        get_device_by_name = args[2]

        devicetree = DeviceTree()
        data = Mock()

        # for every case:
        #   1. device(s) in tree
        #   2. lvm filter updated
        #   3. exceptions raised

        # base case: disk is already in the tree, normal disk
        fmt = get_format("disklabel", exists=True, device="/dev/xyz")
        disk = DiskDevice("xyz", fmt=fmt, exists=True)
        devicetree._add_device(disk)

        device_name = "xyz1"
        device_get_name.return_value = device_name
        device_get_partition_disk.return_value = "xyz"
        get_device_by_name.return_value = disk
        helper = self.helper_class(devicetree, data)

        device = helper.run()
        self.assertIsInstance(device, PartitionDevice)
        self.assertTrue(device.exists)
        self.assertEqual(device.name, device_name)
        self.assertTrue(device in devicetree.devices)
Ejemplo n.º 7
0
    def test_run(self, *args):
        """Test multipath device populator."""
        device_get_name = args[0]
        add_slave_devices = args[1]

        devicetree = DeviceTree()
        data = {"DM_UUID": "1-2-3-4"}

        device_name = "mpathtest"
        device_get_name.return_value = device_name
        slave_1 = Mock()
        slave_1.parents = []
        slave_2 = Mock()
        slave_2.parents = []
        devicetree._add_device(slave_1)
        devicetree._add_device(slave_2)
        add_slave_devices.return_value = [slave_1, slave_2]

        helper = self.helper_class(devicetree, data)

        device = helper.run()
        self.assertIsInstance(device, MultipathDevice)
        self.assertTrue(device.exists)
        self.assertEqual(device.name, device_name)
        self.assertTrue(device in devicetree.devices)
Ejemplo n.º 8
0
    def test_hide_ignored_disks(self):
        tree = DeviceTree()

        sda = DiskDevice("sda")
        sdb = DiskDevice("sdb")
        sdc = DiskDevice("sdc")

        tree._add_device(sda)
        tree._add_device(sdb)
        tree._add_device(sdc)

        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        # test ignored_disks
        tree.ignored_disks = ["sdb"]

        # verify hide is called as expected
        with patch.object(tree, "hide") as hide:
            tree._hide_ignored_disks()
            hide.assert_called_with(sdb)

        # verify that hide works as expected
        tree._hide_ignored_disks()
        self.assertTrue(sda in tree.devices)
        self.assertFalse(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        # unhide sdb and make sure it works
        tree.unhide(sdb)
        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        # test exclusive_disks
        tree.ignored_disks = []
        tree.exclusive_disks = ["sdc"]
        with patch.object(tree, "hide") as hide:
            tree._hide_ignored_disks()
            hide.assert_any_call(sda)
            hide.assert_any_call(sdb)

        tree._hide_ignored_disks()
        self.assertFalse(sda in tree.devices)
        self.assertFalse(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        tree.unhide(sda)
        tree.unhide(sdb)
        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)
Ejemplo n.º 9
0
    def test_recursive_remove(self):
        devicetree = DeviceTree()
        devicetree._add_device(self.disk1)
        devicetree._add_device(self.partition1)
        devicetree._add_device(self.partition2)
        devicetree._add_device(self.disk2)
        devicetree._add_device(self.vg)
        devicetree._add_device(self.lv)

        self.assertIn(self.disk1, devicetree.devices)
        self.assertIn(self.partition1, devicetree.devices)
        self.assertIn(self.lv, devicetree.devices)
        self.assertEqual(devicetree.get_device_by_name(self.disk1.name), self.disk1)
        self.assertIsNotNone(devicetree.get_device_by_name(self.partition1.name))
        self.assertIsNotNone(devicetree.get_device_by_name(self.partition1.name, hidden=True))
        self.assertIsNotNone(devicetree.get_device_by_name(self.lv.name, hidden=True))
        self.assertIsNotNone(devicetree.get_device_by_path(self.lv.path, hidden=True))
        self.assertIsNotNone(devicetree.get_device_by_id(self.partition2.id, hidden=True,
                                                         incomplete=True))
        self.assertEqual(len(devicetree.get_dependent_devices(self.disk1)), 4)
        with patch('blivet.devicetree.ActionDestroyFormat.apply'):
            devicetree.recursive_remove(self.disk1)
            self.assertTrue(self.disk1 in devicetree.devices)
            self.assertFalse(self.partition1 in devicetree.devices)
            self.assertFalse(self.partition2 in devicetree.devices)
            self.assertFalse(self.vg in devicetree.devices)
            self.assertFalse(self.lv in devicetree.devices)
Ejemplo n.º 10
0
    def test_recursive_remove(self):
        devicetree = DeviceTree()
        devicetree._add_device(self.disk1)
        devicetree._add_device(self.partition1)
        devicetree._add_device(self.partition2)
        devicetree._add_device(self.disk2)
        devicetree._add_device(self.vg)
        devicetree._add_device(self.lv)

        self.assertIn(self.disk1, devicetree.devices)
        self.assertIn(self.partition1, devicetree.devices)
        self.assertIn(self.lv, devicetree.devices)
        self.assertEqual(devicetree.get_device_by_name(self.disk1.name), self.disk1)
        self.assertIsNotNone(devicetree.get_device_by_name(self.partition1.name))
        self.assertIsNotNone(devicetree.get_device_by_name(self.partition1.name, hidden=True))
        self.assertIsNotNone(devicetree.get_device_by_name(self.lv.name, hidden=True))
        self.assertIsNotNone(devicetree.get_device_by_path(self.lv.path, hidden=True))
        self.assertIsNotNone(devicetree.get_device_by_id(self.partition2.id, hidden=True,
                                                         incomplete=True))
        self.assertEqual(len(devicetree.get_dependent_devices(self.disk1)), 4)
        with patch('blivet.devicetree.ActionDestroyFormat.apply'):
            devicetree.recursive_remove(self.disk1)
            self.assertTrue(self.disk1 in devicetree.devices)
            self.assertFalse(self.partition1 in devicetree.devices)
            self.assertFalse(self.partition2 in devicetree.devices)
            self.assertFalse(self.vg in devicetree.devices)
            self.assertFalse(self.lv in devicetree.devices)
Ejemplo n.º 11
0
    def test_get_device_by_name(self):
        dt = DeviceTree()

        dev1 = StorageDevice("dev1", exists=False, parents=[])
        dev2 = StorageDevice("dev2", exists=False, parents=[dev1])
        dt._add_device(dev1)
        dt._add_device(dev2)

        self.assertIsNone(dt.get_device_by_name("dev3"))
        self.assertEqual(dt.get_device_by_name("dev2"), dev2)
        self.assertEqual(dt.get_device_by_name("dev1"), dev1)

        dev2.complete = False
        self.assertEqual(dt.get_device_by_name("dev2"), None)
        self.assertEqual(dt.get_device_by_name("dev2", incomplete=True), dev2)

        dev3 = StorageDevice("dev3", exists=True, parents=[])
        dt._add_device(dev3)
        dt.hide(dev3)
        self.assertIsNone(dt.get_device_by_name("dev3"))
        self.assertEqual(dt.get_device_by_name("dev3", hidden=True), dev3)
Ejemplo n.º 12
0
    def test_get_device_by_name(self):
        dt = DeviceTree()

        dev1 = StorageDevice("dev1", exists=False, parents=[])
        dev2 = StorageDevice("dev2", exists=False, parents=[dev1])
        dt._add_device(dev1)
        dt._add_device(dev2)

        self.assertIsNone(dt.get_device_by_name("dev3"))
        self.assertEqual(dt.get_device_by_name("dev2"), dev2)
        self.assertEqual(dt.get_device_by_name("dev1"), dev1)

        dev2.complete = False
        self.assertEqual(dt.get_device_by_name("dev2"), None)
        self.assertEqual(dt.get_device_by_name("dev2", incomplete=True), dev2)

        dev3 = StorageDevice("dev3", exists=True, parents=[])
        dt._add_device(dev3)
        dt.hide(dev3)
        self.assertIsNone(dt.get_device_by_name("dev3"))
        self.assertEqual(dt.get_device_by_name("dev3", hidden=True), dev3)
Ejemplo n.º 13
0
    def test_get_related_disks(self):
        tree = DeviceTree()

        sda = DiskDevice("sda", size=Size('300g'))
        sdb = DiskDevice("sdb", size=Size('300g'))
        sdc = DiskDevice("sdc", size=Size('300G'))

        tree._add_device(sda)
        tree._add_device(sdb)
        tree._add_device(sdc)

        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        sda.format = get_format("lvmpv", device=sda.path)
        sdb.format = get_format("lvmpv", device=sdb.path)
        vg = LVMVolumeGroupDevice("relvg", parents=[sda, sdb])
        tree._add_device(vg)

        self.assertEqual(tree.get_related_disks(sda), set([sda, sdb]))
        self.assertEqual(tree.get_related_disks(sdb), set([sda, sdb]))
        self.assertEqual(tree.get_related_disks(sdc), set())
        tree.hide(sda)
        self.assertEqual(tree.get_related_disks(sda), set([sda, sdb]))
        self.assertEqual(tree.get_related_disks(sdb), set([sda, sdb]))
        tree.hide(sdb)
        self.assertEqual(tree.get_related_disks(sda), set([sda, sdb]))
        self.assertEqual(tree.get_related_disks(sdb), set([sda, sdb]))
        tree.unhide(sda)
        self.assertEqual(tree.get_related_disks(sda), set([sda, sdb]))
        self.assertEqual(tree.get_related_disks(sdb), set([sda, sdb]))
Ejemplo n.º 14
0
    def test_add_device(self, *args):  # pylint: disable=unused-argument
        dt = DeviceTree()

        dev1 = StorageDevice("dev1", exists=False, uuid=sentinel.dev1_uuid, parents=[])

        self.assertEqual(dt.devices, list())

        # things are called, updated as expected when a device is added
        with patch("blivet.devicetree.callbacks") as callbacks:
            dt._add_device(dev1)
            self.assertTrue(callbacks.device_added.called)

        self.assertEqual(dt.devices, [dev1])
        self.assertTrue(dev1 in dt.devices)
        self.assertTrue(dev1.name in dt.names)
        self.assertTrue(dev1.add_hook.called)  # pylint: disable=no-member

        # adding an already-added device fails
        six.assertRaisesRegex(self, ValueError, "already in tree", dt._add_device, dev1)

        dev2 = StorageDevice("dev2", exists=False, parents=[])
        dev3 = StorageDevice("dev3", exists=False, parents=[dev1, dev2])

        # adding a device with one or more parents not already in the tree fails
        six.assertRaisesRegex(self, DeviceTreeError, "parent.*not in tree", dt._add_device, dev3)
        self.assertFalse(dev2 in dt.devices)
        self.assertFalse(dev2.name in dt.names)

        dt._add_device(dev2)
        self.assertTrue(dev2 in dt.devices)
        self.assertTrue(dev2.name in dt.names)

        dt._add_device(dev3)
        self.assertTrue(dev3 in dt.devices)
        self.assertTrue(dev3.name in dt.names)
Ejemplo n.º 15
0
    def test_get_related_disks(self):
        tree = DeviceTree()

        sda = DiskDevice("sda", size=Size('300g'))
        sdb = DiskDevice("sdb", size=Size('300g'))
        sdc = DiskDevice("sdc", size=Size('300G'))

        tree._add_device(sda)
        tree._add_device(sdb)
        tree._add_device(sdc)

        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        sda.format = get_format("lvmpv", device=sda.path)
        sdb.format = get_format("lvmpv", device=sdb.path)
        vg = LVMVolumeGroupDevice("relvg", parents=[sda, sdb])
        tree._add_device(vg)

        self.assertEqual(tree.get_related_disks(sda), set([sda, sdb]))
        self.assertEqual(tree.get_related_disks(sdb), set([sda, sdb]))
        self.assertEqual(tree.get_related_disks(sdc), set())
        tree.hide(sda)
        self.assertEqual(tree.get_related_disks(sda), set([sda, sdb]))
        self.assertEqual(tree.get_related_disks(sdb), set([sda, sdb]))
        tree.hide(sdb)
        self.assertEqual(tree.get_related_disks(sda), set([sda, sdb]))
        self.assertEqual(tree.get_related_disks(sdb), set([sda, sdb]))
        tree.unhide(sda)
        self.assertEqual(tree.get_related_disks(sda), set([sda, sdb]))
        self.assertEqual(tree.get_related_disks(sdb), set([sda, sdb]))
Ejemplo n.º 16
0
    def test_resolve_device(self):
        dt = DeviceTree()

        dev1_label = "dev1_label"
        dev1_uuid = "1234-56-7890"
        fmt1 = get_format("ext4", label=dev1_label, uuid=dev1_uuid)
        dev1 = StorageDevice("dev1", exists=True, fmt=fmt1, size=fmt1.min_size)
        dt._add_device(dev1)

        dev2_label = "dev2_label"
        fmt2 = get_format("swap", label=dev2_label)
        dev2 = StorageDevice("dev2", exists=True, fmt=fmt2)
        dt._add_device(dev2)

        dev3 = StorageDevice("sdp2", exists=True)
        dt._add_device(dev3)

        dt.edd_dict.update({"dev1": 0x81, "dev2": 0x82})

        self.assertEqual(dt.resolve_device(dev1.name), dev1)
        self.assertEqual(dt.resolve_device("LABEL=%s" % dev1_label), dev1)
        self.assertEqual(dt.resolve_device("UUID=%s" % dev1_label), None)
        self.assertEqual(dt.resolve_device("UUID=%s" % dev1_uuid), dev1)
        self.assertEqual(dt.resolve_device("/dev/dev1"), dev1)

        self.assertEqual(dt.resolve_device("dev2"), dev2)
        self.assertEqual(dt.resolve_device("0x82"), dev2)

        self.assertEqual(dt.resolve_device(dev3.name), dev3)
Ejemplo n.º 17
0
    def test_resolve_device(self):
        dt = DeviceTree()

        dev1_label = "dev1_label"
        dev1_uuid = "1234-56-7890"
        fmt1 = get_format("ext4", label=dev1_label, uuid=dev1_uuid)
        dev1 = StorageDevice("dev1", exists=True, fmt=fmt1)
        dt._add_device(dev1)

        dev2_label = "dev2_label"
        fmt2 = get_format("swap", label=dev2_label)
        dev2 = StorageDevice("dev2", exists=True, fmt=fmt2)
        dt._add_device(dev2)

        dev3 = StorageDevice("sdp2", exists=True)
        dt._add_device(dev3)

        dt.edd_dict.update({"dev1": 0x81,
                            "dev2": 0x82})

        self.assertEqual(dt.resolve_device(dev1.name), dev1)
        self.assertEqual(dt.resolve_device("LABEL=%s" % dev1_label), dev1)
        self.assertEqual(dt.resolve_device("UUID=%s" % dev1_label), None)
        self.assertEqual(dt.resolve_device("UUID=%s" % dev1_uuid), dev1)
        self.assertEqual(dt.resolve_device("/dev/dev1"), dev1)

        self.assertEqual(dt.resolve_device("dev2"), dev2)
        self.assertEqual(dt.resolve_device("0x82"), dev2)

        self.assertEqual(dt.resolve_device(dev3.name), dev3)
Ejemplo n.º 18
0
    def test_run(self, *args):
        """Test dm device populator."""
        device_is_dm_livecd = args[2]
        device_get_name = args[1]

        devicetree = DeviceTree()

        # The general case for dm devices is that adding the slave/parent devices
        # will result in the dm device itself being in the tree.
        device = Mock()
        devicetree.get_device_by_name.return_value = device
        data = {"DM_UUID": sentinel.dm_uuid}
        helper = self.helper_class(devicetree, data)

        self.assertEqual(helper.run(), device)
        self.assertEqual(devicetree._add_slave_devices.call_count, 1)  # pylint: disable=no-member
        self.assertEqual(devicetree.get_device_by_name.call_count, 1)  # pylint: disable=no-member
        # since we faked the lookup as if the device was already in the tree
        # the helper should not have added it, meaning it shouldn't be there
        self.assertFalse(device in devicetree.devices)

        # The other case is adding a live media image
        parent = Mock()
        parent.parents = []
        devicetree._add_slave_devices.return_value = [parent]
        devicetree._add_device(parent)
        devicetree.get_device_by_name.return_value = None
        device_name = "livedevice"
        device_get_name.return_value = device_name
        device_is_dm_livecd.return_value = True

        device = helper.run()
        self.assertIsInstance(device, DMDevice)
        self.assertTrue(device in devicetree.devices)
        self.assertEqual(device.dm_uuid, sentinel.dm_uuid)
        self.assertEqual(device.name, device_name)
        self.assertEqual(device.sysfs_path, sentinel.sysfs_path)
        self.assertEqual(list(device.parents), [parent])
Ejemplo n.º 19
0
    def test_run(self, *args):
        """Test dm device populator."""
        device_is_dm_livecd = args[2]
        device_get_name = args[1]

        devicetree = DeviceTree()

        # The general case for dm devices is that adding the slave/parent devices
        # will result in the dm device itself being in the tree.
        device = Mock()
        devicetree.get_device_by_name.return_value = device
        data = {"DM_UUID": sentinel.dm_uuid}
        helper = self.helper_class(devicetree, data)

        self.assertEqual(helper.run(), device)
        self.assertEqual(devicetree._add_slave_devices.call_count, 1)  # pylint: disable=no-member
        self.assertEqual(devicetree.get_device_by_name.call_count, 1)  # pylint: disable=no-member
        # since we faked the lookup as if the device was already in the tree
        # the helper should not have added it, meaning it shouldn't be there
        self.assertFalse(device in devicetree.devices)

        # The other case is adding a live media image
        parent = Mock()
        parent.parents = []
        devicetree._add_slave_devices.return_value = [parent]
        devicetree._add_device(parent)
        devicetree.get_device_by_name.return_value = None
        device_name = "livedevice"
        device_get_name.return_value = device_name
        device_is_dm_livecd.return_value = True

        device = helper.run()
        self.assertIsInstance(device, DMDevice)
        self.assertTrue(device in devicetree.devices)
        self.assertEqual(device.dm_uuid, sentinel.dm_uuid)
        self.assertEqual(device.name, device_name)
        self.assertEqual(device.sysfs_path, sentinel.sysfs_path)
        self.assertEqual(list(device.parents), [parent])
Ejemplo n.º 20
0
    def test_remove_device(self, *args):  # pylint: disable=unused-argument
        dt = DeviceTree()

        dev1 = StorageDevice("dev1", exists=False, parents=[])

        # removing a device not in the tree raises an exception
        six.assertRaisesRegex(self, ValueError, "not in tree",
                              dt._remove_device, dev1)

        dt._add_device(dev1)
        with patch("blivet.devicetree.callbacks") as callbacks:
            dt._remove_device(dev1)
            self.assertTrue(callbacks.device_removed.called)

        self.assertFalse(dev1 in dt.devices)
        self.assertFalse(dev1.name in dt.names)
        self.assertTrue(dev1.remove_hook.called)  # pylint: disable=no-member

        dev2 = StorageDevice("dev2", exists=False, parents=[dev1])
        dt._add_device(dev1)
        dt._add_device(dev2)
        self.assertTrue(dev2 in dt.devices)
        self.assertTrue(dev2.name in dt.names)

        # removal of a non-leaf device raises an exception
        six.assertRaisesRegex(self, ValueError, "non-leaf device",
                              dt._remove_device, dev1)
        self.assertTrue(dev1 in dt.devices)
        self.assertTrue(dev1.name in dt.names)
        self.assertTrue(dev2 in dt.devices)
        self.assertTrue(dev2.name in dt.names)

        # forcing removal of non-leaf device does not remove the children
        dt._remove_device(dev1, force=True)
        self.assertFalse(dev1 in dt.devices)
        self.assertFalse(dev1.name in dt.names)
        self.assertTrue(dev2 in dt.devices)
        self.assertTrue(dev2.name in dt.names)
Ejemplo n.º 21
0
    def test_remove_device(self, *args):  # pylint: disable=unused-argument
        dt = DeviceTree()

        dev1 = StorageDevice("dev1", exists=False, parents=[])

        # removing a device not in the tree raises an exception
        six.assertRaisesRegex(self, ValueError, "not in tree", dt._remove_device, dev1)

        dt._add_device(dev1)
        with patch("blivet.devicetree.callbacks") as callbacks:
            dt._remove_device(dev1)
            self.assertTrue(callbacks.device_removed.called)

        self.assertFalse(dev1 in dt.devices)
        self.assertFalse(dev1.name in dt.names)
        self.assertTrue(dev1.remove_hook.called)  # pylint: disable=no-member

        dev2 = StorageDevice("dev2", exists=False, parents=[dev1])
        dt._add_device(dev1)
        dt._add_device(dev2)
        self.assertTrue(dev2 in dt.devices)
        self.assertTrue(dev2.name in dt.names)

        # removal of a non-leaf device raises an exception
        six.assertRaisesRegex(self, ValueError, "non-leaf device", dt._remove_device, dev1)
        self.assertTrue(dev1 in dt.devices)
        self.assertTrue(dev1.name in dt.names)
        self.assertTrue(dev2 in dt.devices)
        self.assertTrue(dev2.name in dt.names)

        # forcing removal of non-leaf device does not remove the children
        dt._remove_device(dev1, force=True)
        self.assertFalse(dev1 in dt.devices)
        self.assertFalse(dev1.name in dt.names)
        self.assertTrue(dev2 in dt.devices)
        self.assertTrue(dev2.name in dt.names)
Ejemplo n.º 22
0
    def test_device_name(self):
        # check that devicetree.names property contains all device's names

        # mock lvs_info to avoid blockdev call allowing run as non-root
        with patch.object(LVsInfo, 'cache',
                          new_callable=PropertyMock) as mock_lvs_cache:
            mock_lvs_cache.return_value = {
                "sdmock": "dummy",
                "testvg-testlv": "dummy"
            }

            tree = DeviceTree()
            dev_names = ["sda", "sdb", "sdc"]

            for dev_name in dev_names:
                dev = DiskDevice(dev_name, size=Size("1 GiB"))
                tree._add_device(dev)
                self.assertTrue(dev in tree.devices)
                self.assertTrue(dev.name in tree.names)

            dev.format = get_format("lvmpv", device=dev.path)
            vg = LVMVolumeGroupDevice("testvg", parents=[dev])
            tree._add_device(vg)
            dev_names.append(vg.name)

            lv = LVMLogicalVolumeDevice("testlv", parents=[vg])
            tree._add_device(lv)
            dev_names.append(lv.name)

            # frobnicate a bit with the hidden status of the devices:
            # * hide sda
            # * hide and unhide again sdb
            # * leave sdc unchanged
            tree.hide(tree.get_device_by_name("sda"))
            tree.hide(tree.get_device_by_name("sdb"))
            tree.unhide(tree.get_device_by_name("sdb", hidden=True))

            # some lvs names may be already present in the system (mocked)
            lv_info = list(lvs_info.cache.keys())

            # all devices should still be present in the tree.names
            self.assertEqual(set(tree.names), set(lv_info + dev_names))

            # "remove" the LV, it should no longer be in the list
            tree.actions._actions.append(
                Mock(device=lv,
                     type=ACTION_TYPE_DESTROY,
                     obj=ACTION_OBJECT_DEVICE))
            tree._remove_device(lv)
            self.assertFalse(lv.name in tree.names)
Ejemplo n.º 23
0
    def test_add_device(self, *args):  # pylint: disable=unused-argument
        dt = DeviceTree()

        dev1 = StorageDevice("dev1",
                             exists=False,
                             uuid=sentinel.dev1_uuid,
                             parents=[])

        self.assertEqual(dt.devices, list())

        # things are called, updated as expected when a device is added
        with patch("blivet.devicetree.callbacks") as callbacks:
            dt._add_device(dev1)
            self.assertTrue(callbacks.device_added.called)

        self.assertEqual(dt.devices, [dev1])
        self.assertTrue(dev1 in dt.devices)
        self.assertTrue(dev1.name in dt.names)
        self.assertTrue(dev1.add_hook.called)  # pylint: disable=no-member

        # adding an already-added device fails
        six.assertRaisesRegex(self, DeviceTreeError,
                              "Trying to add already existing device.",
                              dt._add_device, dev1)

        # adding a device with the same UUID
        dev_clone = StorageDevice("dev_clone",
                                  exists=False,
                                  uuid=sentinel.dev1_uuid,
                                  parents=[])
        six.assertRaisesRegex(self, DuplicateUUIDError, "Duplicate UUID.*",
                              dt._add_device, dev_clone)

        dev2 = StorageDevice("dev2", exists=False, parents=[])
        dev3 = StorageDevice("dev3", exists=False, parents=[dev1, dev2])

        # adding a device with one or more parents not already in the tree fails
        six.assertRaisesRegex(self, DeviceTreeError, "parent.*not in tree",
                              dt._add_device, dev3)
        self.assertFalse(dev2 in dt.devices)
        self.assertFalse(dev2.name in dt.names)

        dt._add_device(dev2)
        self.assertTrue(dev2 in dt.devices)
        self.assertTrue(dev2.name in dt.names)

        dt._add_device(dev3)
        self.assertTrue(dev3 in dt.devices)
        self.assertTrue(dev3.name in dt.names)
Ejemplo n.º 24
0
class FSSetTestCase(unittest.TestCase):
    """Test the class that represents a set of filesystems."""

    def setUp(self):
        """Set up the test."""
        self.maxDiff = None
        self.devicetree = DeviceTree()
        self.fsset = FSSet(self.devicetree)

    def _add_device(self, device):
        """Add a device to the device tree."""
        self.devicetree._add_device(device)

    def _get_mount_points(self, devices):
        """Get mount points of the given devices."""
        return [getattr(d.format, "mountpoint", None) for d in devices]

    def _get_format_types(self, devices):
        """Get format types of the given devices."""
        return [d.format.type for d in devices]

    def test_system_filesystems(self):
        """Test the system_filesystems property."""
        devices = self.fsset.system_filesystems

        # There are some devices in the list.
        assert devices

        # The devices are always the same.
        assert devices == self.fsset.system_filesystems

    @patch("pyanaconda.modules.storage.devicetree.fsset.platform", X86())
    def test_collect_filesystems(self):
        """Test the collect_filesystems method."""
        devices = self.fsset.collect_filesystems()
        mount_points = self._get_mount_points(devices)
        format_types = self._get_format_types(devices)

        assert mount_points == [
            '/dev',
            '/dev/pts',
            '/dev/shm',
            '/proc',
            '/proc/bus/usb',
            '/run',
            '/sys',
            '/sys/fs/selinux',
            '/tmp',
        ]

        assert format_types == [
            'bind',
            'devpts',
            'tmpfs',
            'proc',
            'usbfs',
            'bind',
            'sysfs',
            'selinuxfs',
            'tmpfs',
        ]

    @patch("pyanaconda.modules.storage.devicetree.fsset.platform", EFI())
    def test_collect_filesystems_efi(self):
        """Test the collect_filesystems method with EFI."""
        devices = self.fsset.collect_filesystems()
        mount_points = self._get_mount_points(devices)
        format_types = self._get_format_types(devices)

        assert mount_points == [
            '/dev',
            '/dev/pts',
            '/dev/shm',
            '/proc',
            '/proc/bus/usb',
            '/run',
            '/sys',
            '/sys/firmware/efi/efivars',
            '/sys/fs/selinux',
            '/tmp',
        ]

        assert format_types == [
            'bind',
            'devpts',
            'tmpfs',
            'proc',
            'usbfs',
            'bind',
            'sysfs',
            'efivarfs',
            'selinuxfs',
            'tmpfs',
        ]

    @patch("pyanaconda.modules.storage.devicetree.fsset.platform", X86())
    def test_collect_filesystems_tmp(self):
        """Test the collect_filesystems method with /tmp."""
        self._add_device(StorageDevice("dev1", fmt=get_format("ext4", mountpoint="/tmp")))

        devices = self.fsset.collect_filesystems()
        mount_points = self._get_mount_points(devices)
        format_types = self._get_format_types(devices)

        assert mount_points == [
            '/dev',
            '/dev/pts',
            '/dev/shm',
            '/proc',
            '/proc/bus/usb',
            '/run',
            '/sys',
            '/sys/fs/selinux',
            '/tmp',
        ]

        assert format_types == [
            'bind',
            'devpts',
            'tmpfs',
            'proc',
            'usbfs',
            'bind',
            'sysfs',
            'selinuxfs',
            'ext4',
        ]

    @patch("pyanaconda.modules.storage.devicetree.fsset.platform", X86())
    def test_collect_filesystems_extra(self):
        """Test the collect_filesystems method with additional devices."""
        self._add_device(StorageDevice("dev1", fmt=get_format("ext4", mountpoint="/boot")))
        self._add_device(StorageDevice("dev2", fmt=get_format("ext4", mountpoint="/")))
        self._add_device(StorageDevice("dev3", fmt=get_format("ext4", mountpoint="/home")))
        self._add_device(StorageDevice("dev4", fmt=get_format("swap")))
        self._add_device(StorageDevice("dev5", fmt=get_format("swap")))

        devices = self.fsset.collect_filesystems()
        mount_points = self._get_mount_points(devices)
        format_types = self._get_format_types(devices)

        assert mount_points == [
            None,
            None,
            '/',
            '/boot',
            '/dev',
            '/dev/pts',
            '/dev/shm',
            '/home',
            '/proc',
            '/proc/bus/usb',
            '/run',
            '/sys',
            '/sys/fs/selinux',
            '/tmp',
        ]

        assert format_types == [
            'swap',
            'swap',
            'ext4',
            'ext4',
            'bind',
            'devpts',
            'tmpfs',
            'ext4',
            'proc',
            'usbfs',
            'bind',
            'sysfs',
            'selinuxfs',
            'tmpfs',
        ]
Ejemplo n.º 25
0
    def test_hide_ignored_disks(self):
        tree = DeviceTree()

        sda = DiskDevice("sda")
        sdb = DiskDevice("sdb")
        sdc = DiskDevice("sdc")

        tree._add_device(sda)
        tree._add_device(sdb)
        tree._add_device(sdc)

        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        # test ignored_disks
        tree.ignored_disks = ["sdb"]

        # verify hide is called as expected
        with patch.object(tree, "hide") as hide:
            tree._hide_ignored_disks()
            hide.assert_called_with(sdb)

        # verify that hide works as expected
        tree._hide_ignored_disks()
        self.assertTrue(sda in tree.devices)
        self.assertFalse(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        # unhide sdb and make sure it works
        tree.unhide(sdb)
        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        # test exclusive_disks
        tree.ignored_disks = []
        tree.exclusive_disks = ["sdc"]
        with patch.object(tree, "hide") as hide:
            tree._hide_ignored_disks()
            hide.assert_any_call(sda)
            hide.assert_any_call(sdb)

        tree._hide_ignored_disks()
        self.assertFalse(sda in tree.devices)
        self.assertFalse(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        tree.unhide(sda)
        tree.unhide(sdb)
        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        # now test exclusive_disks special cases for multipath
        sda.format = get_format("multipath_member", exists=True)
        sdb.format = get_format("multipath_member", exists=True)
        sdc.format = get_format("multipath_member", exists=True)
        mpatha = MultipathDevice("mpatha", parents=[sda, sdb, sdc])
        tree._add_device(mpatha)

        tree.ignored_disks = []
        tree.exclusive_disks = ["mpatha"]

        with patch.object(tree, "hide") as hide:
            tree._hide_ignored_disks()
            self.assertFalse(hide.called)

        tree._hide_ignored_disks()
        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)
        self.assertTrue(mpatha in tree.devices)

        # all members in exclusive_disks implies the mpath in exclusive_disks
        tree.exclusive_disks = ["sda", "sdb", "sdc"]
        with patch.object(tree, "hide") as hide:
            tree._hide_ignored_disks()
            self.assertFalse(hide.called)

        tree._hide_ignored_disks()
        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)
        self.assertTrue(mpatha in tree.devices)

        tree.exclusive_disks = ["sda", "sdb"]
        with patch.object(tree, "hide") as hide:
            tree._hide_ignored_disks()
            hide.assert_any_call(mpatha)
            hide.assert_any_call(sdc)

        # verify that hide works as expected
        tree._hide_ignored_disks()
        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertFalse(sdc in tree.devices)
        self.assertFalse(mpatha in tree.devices)
Ejemplo n.º 26
0
    def test_run(self, *args):
        """Test lvm format populator."""
        get_device_by_uuid = args[0]

        devicetree = DeviceTree()
        data = dict()
        device = Mock()
        device.parents = []
        device.size = Size("10g")
        devicetree._add_device(device)

        # pylint: disable=attribute-defined-outside-init
        self._pvs = blockdev.lvm.pvs
        self._vgs = blockdev.lvm.vgs
        self._lvs = blockdev.lvm.lvs
        blockdev.lvm.pvs = Mock(return_value=[])
        blockdev.lvm.vgs = Mock(return_value=[])
        blockdev.lvm.lvs = Mock(return_value=[])
        self.addCleanup(self._clean_up)

        # base case: pv format with no vg
        with patch("blivet.udev.device_get_format",
                   return_value=self.udev_type):
            helper = self.helper_class(devicetree, data, device)
            helper.run()
            self.assertEqual(
                device.format.type,
                self.blivet_type,
                msg="Wrong format type after FormatPopulator.run on %s" %
                self.udev_type)

        # pv belongs to a valid vg which is already in the tree (no lvs)
        pv_info = Mock()

        pv_info.vg_name = "testvgname"
        pv_info.vg_uuid = sentinel.vg_uuid
        pv_info.pe_start = 0
        pv_info.pv_free = 0

        device.path = sentinel.pv_path

        vg_device = Mock()
        vg_device.parents = []
        vg_device.lvs = []
        get_device_by_uuid.return_value = vg_device

        with patch("blivet.static_data.lvm_info.PVsInfo.cache",
                   new_callable=PropertyMock) as mock_pvs_cache:
            mock_pvs_cache.return_value = {sentinel.pv_path: pv_info}
            with patch("blivet.udev.device_get_format",
                       return_value=self.udev_type):
                helper = self.helper_class(devicetree, data, device)
                self.assertFalse(device in vg_device.parents)
                helper.run()
                self.assertEqual(
                    device.format.type,
                    self.blivet_type,
                    msg="Wrong format type after FormatPopulator.run on %s" %
                    self.udev_type)

                self.assertEqual(get_device_by_uuid.call_count, 3)
                get_device_by_uuid.assert_called_with(pv_info.vg_uuid,
                                                      incomplete=True)
                self.assertTrue(device in vg_device.parents)

        get_device_by_uuid.reset_mock()
        get_device_by_uuid.return_value = None

        # pv belongs to a valid vg which is not in the tree (no lvs, either)
        pv_info.vg_size = "10g"
        pv_info.vg_free = 0
        pv_info.vg_extent_size = "4m"
        pv_info.vg_extent_count = 2500
        pv_info.vg_free_count = 0
        pv_info.vg_pv_count = 1

        with patch("blivet.static_data.lvm_info.PVsInfo.cache",
                   new_callable=PropertyMock) as mock_pvs_cache:
            mock_pvs_cache.return_value = {sentinel.pv_path: pv_info}
            with patch("blivet.udev.device_get_format",
                       return_value=self.udev_type):
                helper = self.helper_class(devicetree, data, device)
                helper.run()
                self.assertEqual(
                    device.format.type,
                    self.blivet_type,
                    msg="Wrong format type after FormatPopulator.run on %s" %
                    self.udev_type)

                self.assertEqual(get_device_by_uuid.call_count, 2)
                get_device_by_uuid.assert_called_with(pv_info.vg_uuid,
                                                      incomplete=True)
                vg_device = devicetree.get_device_by_name(pv_info.vg_name)
                self.assertTrue(vg_device is not None)
                devicetree._remove_device(vg_device)

        get_device_by_uuid.reset_mock()

        # pv belongs to a valid vg not in the tree with two lvs
        lv1 = Mock()
        lv1.vg_name = pv_info.vg_name
        lv1.lv_name = "testlv1"
        lv1.uuid = sentinel.lv1_uuid
        lv1.attr = "-wi-ao----"
        lv1.size = "2g"
        lv1.segtype = "linear"
        lv1_name = "%s-%s" % (pv_info.vg_name, lv1.lv_name)

        lv2 = Mock()
        lv2.vg_name = pv_info.vg_name
        lv2.lv_name = "testlv2"
        lv2.uuid = sentinel.lv2_uuid
        lv2.attr = "-wi-ao----"
        lv2.size = "7g"
        lv2.segtype = "linear"
        lv2_name = "%s-%s" % (pv_info.vg_name, lv2.lv_name)

        lv_info = {lv1_name: lv1, lv2_name: lv2}

        device.format.container_uuid = pv_info.vg_uuid

        def gdbu(uuid, **kwargs):  # pylint: disable=unused-argument
            # This version doesn't check format UUIDs
            return next((d for d in devicetree.devices if d.uuid == uuid),
                        None)

        get_device_by_uuid.side_effect = gdbu

        with patch("blivet.static_data.lvm_info.PVsInfo.cache",
                   new_callable=PropertyMock) as mock_pvs_cache:
            mock_pvs_cache.return_value = {sentinel.pv_path: pv_info}
            with patch("blivet.static_data.lvm_info.LVsInfo.cache",
                       new_callable=PropertyMock) as mock_lvs_cache:
                mock_lvs_cache.return_value = lv_info
                with patch("blivet.udev.device_get_format",
                           return_value=self.udev_type):
                    self.assertEqual(
                        devicetree.get_device_by_name(pv_info.vg_name,
                                                      incomplete=True), None)
                    helper = self.helper_class(devicetree, data, device)
                    helper.run()
                    self.assertEqual(
                        device.format.type,
                        self.blivet_type,
                        msg="Wrong format type after FormatPopulator.run on %s"
                        % self.udev_type)

                    self.assertEqual(get_device_by_uuid.call_count, 4,
                                     get_device_by_uuid.mock_calls
                                     )  # two for vg and one for each lv
                    get_device_by_uuid.assert_has_calls([
                        call(pv_info.vg_uuid, incomplete=True),
                        call(lv1.uuid),
                        call(lv2.uuid)
                    ],
                                                        any_order=True)
                    vg_device = devicetree.get_device_by_name(pv_info.vg_name)
                    self.assertTrue(vg_device is not None)

                    lv1_device = devicetree.get_device_by_name(lv1_name)
                    self.assertEqual(lv1_device.uuid, lv1.uuid)
                    lv2_device = devicetree.get_device_by_name(lv2_name)
                    self.assertEqual(lv2_device.uuid, lv2.uuid)
Ejemplo n.º 27
0
    def test_hide_ignored_disks(self):
        tree = DeviceTree()

        sda = DiskDevice("sda")
        sdb = DiskDevice("sdb")
        sdc = DiskDevice("sdc")

        tree._add_device(sda)
        tree._add_device(sdb)
        tree._add_device(sdc)

        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        # test ignored_disks
        tree.ignored_disks = ["sdb"]

        # verify hide is called as expected
        with patch.object(tree, "hide") as hide:
            tree._hide_ignored_disks()
            hide.assert_called_with(sdb)

        # verify that hide works as expected
        tree._hide_ignored_disks()
        self.assertTrue(sda in tree.devices)
        self.assertFalse(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        # unhide sdb and make sure it works
        tree.unhide(sdb)
        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        # test exclusive_disks
        tree.ignored_disks = []
        tree.exclusive_disks = ["sdc"]
        with patch.object(tree, "hide") as hide:
            tree._hide_ignored_disks()
            hide.assert_any_call(sda)
            hide.assert_any_call(sdb)

        tree._hide_ignored_disks()
        self.assertFalse(sda in tree.devices)
        self.assertFalse(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        tree.unhide(sda)
        tree.unhide(sdb)
        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)

        # now test exclusive_disks special cases for multipath
        sda.format = get_format("multipath_member", exists=True)
        sdb.format = get_format("multipath_member", exists=True)
        sdc.format = get_format("multipath_member", exists=True)
        mpatha = MultipathDevice("mpatha", parents=[sda, sdb, sdc])
        tree._add_device(mpatha)

        tree.ignored_disks = []
        tree.exclusive_disks = ["mpatha"]

        with patch.object(tree, "hide") as hide:
            tree._hide_ignored_disks()
            self.assertFalse(hide.called)

        tree._hide_ignored_disks()
        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)
        self.assertTrue(mpatha in tree.devices)

        # all members in exclusive_disks implies the mpath in exclusive_disks
        tree.exclusive_disks = ["sda", "sdb", "sdc"]
        with patch.object(tree, "hide") as hide:
            tree._hide_ignored_disks()
            self.assertFalse(hide.called)

        tree._hide_ignored_disks()
        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertTrue(sdc in tree.devices)
        self.assertTrue(mpatha in tree.devices)

        tree.exclusive_disks = ["sda", "sdb"]
        with patch.object(tree, "hide") as hide:
            tree._hide_ignored_disks()
            hide.assert_any_call(mpatha)
            hide.assert_any_call(sdc)

        # verify that hide works as expected
        tree._hide_ignored_disks()
        self.assertTrue(sda in tree.devices)
        self.assertTrue(sdb in tree.devices)
        self.assertFalse(sdc in tree.devices)
        self.assertFalse(mpatha in tree.devices)
Ejemplo n.º 28
0
    def test_recursive_remove(self):
        dt = DeviceTree()
        dev1 = StorageDevice("dev1", exists=False, parents=[])
        dev2 = StorageDevice("dev2", exists=False, parents=[dev1])
        dt._add_device(dev1)
        dt._add_device(dev2)

        # normal
        self.assertTrue(dev1 in dt.devices)
        self.assertTrue(dev2 in dt.devices)
        self.assertEqual(dt.actions._actions, list())
        dt.recursive_remove(dev1)
        self.assertFalse(dev1 in dt.devices)
        self.assertFalse(dev2 in dt.devices)
        self.assertNotEqual(dt.actions._actions, list())

        dt.reset()
        dt._add_device(dev1)
        dt._add_device(dev2, new=False)  # restore parent/child relationships

        # remove_device clears descendants and formatting but preserves the device
        dev1.format = get_format("swap")
        self.assertEqual(dev1.format.type, "swap")
        self.assertEqual(dt.actions._actions, list())
        dt.recursive_remove(dev1, remove_device=False)
        self.assertTrue(dev1 in dt.devices)
        self.assertFalse(dev2 in dt.devices)
        self.assertEqual(dev1.format.type, None)
        self.assertNotEqual(dt.actions._actions, list())

        dt.reset()
        dt._add_device(dev1)
        dt._add_device(dev2, new=False)  # restore parent/child relationships

        # actions=False performs the removals without scheduling actions
        self.assertEqual(dt.actions._actions, list())
        dt.recursive_remove(dev1, actions=False)
        self.assertFalse(dev1 in dt.devices)
        self.assertFalse(dev2 in dt.devices)
        self.assertEqual(dt.actions._actions, list())

        dt.reset()
        dt._add_device(dev1)
        dt._add_device(dev2, new=False)  # restore parent/child relationships

        # modparent only works when actions=False is passed
        with patch.object(dt, "_remove_device") as remove_device:
            dt.recursive_remove(dev1, actions=False)
            remove_device.assert_called_with(dev1, modparent=True)

            dt.recursive_remove(dev1, actions=False, modparent=False)
            remove_device.assert_called_with(dev1, modparent=False)
Ejemplo n.º 29
0
    def test_run(self, *args):
        """Test md format populator."""
        get_device_by_uuid = args[0]
        get_devices = args[1]
        device_is_md = args[2]

        devicetree = DeviceTree()
        data = dict()
        device = Mock()
        device.name = sentinel.dev1_name
        device.parents = []
        device.size = Size("10g")
        devicetree._add_device(device)

        # pylint: disable=attribute-defined-outside-init
        self._examine = blockdev.md.examine
        blockdev.md.examine = Mock()
        self.addCleanup(self._clean_up)

        # member belongs to a valid array which is already in the tree
        md_info = Mock()
        md_info.uuid = sentinel.md_uuid
        blockdev.md.examine.return_value = md_info

        md_device = Mock()
        get_device_by_uuid.return_value = md_device

        with patch("blivet.udev.device_get_format",
                   return_value=self.udev_type):
            helper = self.helper_class(devicetree, data, device)
            helper.run()
            self.assertEqual(
                device.format.type,
                self.blivet_type,
                msg="Wrong format type after FormatPopulator.run on %s" %
                self.udev_type)

            self.assertEqual(get_device_by_uuid.call_count, 1)
            get_device_by_uuid.assert_called_with(md_info.uuid,
                                                  incomplete=True)
            md_device.parents.append.assert_called_once_with(device)  # pylint: disable=no-member

        get_device_by_uuid.reset_mock()
        get_device_by_uuid.return_value = None

        # first of two members belonging to a valid array which is not in the tree
        array_name = "mdtest"
        md_info.level = "raid1"
        md_info.num_devices = 2
        md_info.metadata = "1.2"
        md_info.device = "/dev/md/" + array_name
        blockdev.md.examine.return_value = md_info

        device_is_md.return_value = True
        md_udev = {
            "MD_LEVEL": md_info.level,
            "MD_UUID": sentinel.md_uuid,
            "MD_DEVNAME": array_name
        }
        get_devices.return_value = [md_udev]

        with patch("blivet.udev.device_get_format",
                   return_value=self.udev_type):
            helper = self.helper_class(devicetree, data, device)
            helper.run()
            self.assertEqual(
                device.format.type,
                self.blivet_type,
                msg="Wrong format type after FormatPopulator.run on %s" %
                self.udev_type)

            self.assertEqual(get_device_by_uuid.call_count, 1)
            get_device_by_uuid.assert_called_with(md_info.uuid,
                                                  incomplete=True)
            array = devicetree.get_device_by_name(array_name)
            self.assertTrue(array is None)
            array = devicetree.get_device_by_name(array_name, incomplete=True)
            self.assertTrue(array is not None)
            self.assertFalse(array.complete)
            self.assertEqual(array.name, array_name)

        get_device_by_uuid.reset_mock()
        array = devicetree.get_device_by_name(array_name, incomplete=True)
        get_device_by_uuid.return_value = array

        # second of two members belonging to a valid array
        device2 = Mock()
        device2.name = sentinel.dev2_name
        device2.parents = []
        device2.size = Size("10g")
        devicetree._add_device(device2)

        with patch("blivet.udev.device_get_format",
                   return_value=self.udev_type):
            helper = self.helper_class(devicetree, data, device2)
            helper.run()
            self.assertEqual(
                device2.format.type,
                self.blivet_type,
                msg="Wrong format type after FormatPopulator.run on %s" %
                self.udev_type)

            self.assertEqual(get_device_by_uuid.call_count,
                             1)  # one for the array
            get_device_by_uuid.assert_called_with(md_info.uuid,
                                                  incomplete=True)

            array = devicetree.get_device_by_name(array_name)
            self.assertTrue(array is not None)
            self.assertTrue(array.complete)
            self.assertEqual(array.name, array_name)
Ejemplo n.º 30
0
    def test_run(self, *args):
        """Test md format populator."""
        get_device_by_uuid = args[0]
        get_devices = args[1]
        device_is_md = args[2]

        devicetree = DeviceTree()
        data = dict()
        device = Mock()
        device.name = sentinel.dev1_name
        device.parents = []
        device.size = Size("10g")
        devicetree._add_device(device)

        # pylint: disable=attribute-defined-outside-init
        self._examine = blockdev.md.examine
        blockdev.md.examine = Mock()
        self.addCleanup(self._clean_up)

        # member belongs to a valid array which is already in the tree
        md_info = Mock()
        md_info.uuid = sentinel.md_uuid
        blockdev.md.examine.return_value = md_info

        md_device = Mock()
        get_device_by_uuid.return_value = md_device

        with patch("blivet.udev.device_get_format", return_value=self.udev_type):
            helper = self.helper_class(devicetree, data, device)
            helper.run()
            self.assertEqual(device.format.type,
                             self.blivet_type,
                             msg="Wrong format type after FormatPopulator.run on %s" % self.udev_type)

            self.assertEqual(get_device_by_uuid.call_count, 1)
            get_device_by_uuid.assert_called_with(md_info.uuid, incomplete=True)
            md_device.parents.append.assert_called_once_with(device)  # pylint: disable=no-member

        get_device_by_uuid.reset_mock()
        get_device_by_uuid.return_value = None

        # first of two members belonging to a valid array which is not in the tree
        array_name = "mdtest"
        md_info.level = "raid1"
        md_info.num_devices = 2
        md_info.metadata = "1.2"
        md_info.device = "/dev/md/" + array_name
        blockdev.md.examine.return_value = md_info

        device_is_md.return_value = True
        md_udev = {"MD_LEVEL": md_info.level, "MD_UUID": sentinel.md_uuid, "MD_DEVNAME": array_name}
        get_devices.return_value = [md_udev]

        with patch("blivet.udev.device_get_format", return_value=self.udev_type):
            helper = self.helper_class(devicetree, data, device)
            helper.run()
            self.assertEqual(device.format.type,
                             self.blivet_type,
                             msg="Wrong format type after FormatPopulator.run on %s" % self.udev_type)

            self.assertEqual(get_device_by_uuid.call_count, 1)
            get_device_by_uuid.assert_called_with(md_info.uuid, incomplete=True)
            array = devicetree.get_device_by_name(array_name)
            self.assertTrue(array is None)
            array = devicetree.get_device_by_name(array_name, incomplete=True)
            self.assertTrue(array is not None)
            self.assertFalse(array.complete)
            self.assertEqual(array.name, array_name)

        get_device_by_uuid.reset_mock()
        array = devicetree.get_device_by_name(array_name, incomplete=True)
        get_device_by_uuid.return_value = array

        # second of two members belonging to a valid array
        device2 = Mock()
        device2.name = sentinel.dev2_name
        device2.parents = []
        device2.size = Size("10g")
        devicetree._add_device(device2)

        with patch("blivet.udev.device_get_format", return_value=self.udev_type):
            helper = self.helper_class(devicetree, data, device2)
            helper.run()
            self.assertEqual(device2.format.type,
                             self.blivet_type,
                             msg="Wrong format type after FormatPopulator.run on %s" % self.udev_type)

            self.assertEqual(get_device_by_uuid.call_count, 1)  # one for the array
            get_device_by_uuid.assert_called_with(md_info.uuid, incomplete=True)

            array = devicetree.get_device_by_name(array_name)
            self.assertTrue(array is not None)
            self.assertTrue(array.complete)
            self.assertEqual(array.name, array_name)
Ejemplo n.º 31
0
    def test_run(self, *args):
        """Test lvm format populator."""
        get_device_by_uuid = args[0]

        devicetree = DeviceTree()
        data = dict()
        device = Mock()
        device.parents = []
        device.size = Size("10g")
        devicetree._add_device(device)

        # pylint: disable=attribute-defined-outside-init
        self._pvs = blockdev.lvm.pvs
        self._vgs = blockdev.lvm.vgs
        self._lvs = blockdev.lvm.lvs
        blockdev.lvm.pvs = Mock(return_value=[])
        blockdev.lvm.vgs = Mock(return_value=[])
        blockdev.lvm.lvs = Mock(return_value=[])
        self.addCleanup(self._clean_up)

        # base case: pv format with no vg
        with patch("blivet.udev.device_get_format", return_value=self.udev_type):
            helper = self.helper_class(devicetree, data, device)
            helper.run()
            self.assertEqual(device.format.type,
                             self.blivet_type,
                             msg="Wrong format type after FormatPopulator.run on %s" % self.udev_type)

        # pv belongs to a valid vg which is already in the tree (no lvs)
        pv_info = Mock()

        pv_info.vg_name = "testvgname"
        pv_info.vg_uuid = sentinel.vg_uuid
        pv_info.pe_start = 0
        pv_info.pv_free = 0

        device.path = sentinel.pv_path

        vg_device = Mock()
        vg_device.parents = []
        vg_device.lvs = []
        get_device_by_uuid.return_value = vg_device

        with patch("blivet.static_data.lvm_info.PVsInfo.cache", new_callable=PropertyMock) as mock_pvs_cache:
            mock_pvs_cache.return_value = {sentinel.pv_path: pv_info}
            with patch("blivet.udev.device_get_format", return_value=self.udev_type):
                helper = self.helper_class(devicetree, data, device)
                self.assertFalse(device in vg_device.parents)
                helper.run()
                self.assertEqual(device.format.type,
                                 self.blivet_type,
                                 msg="Wrong format type after FormatPopulator.run on %s" % self.udev_type)

                self.assertEqual(get_device_by_uuid.call_count, 3)
                get_device_by_uuid.assert_called_with(pv_info.vg_uuid, incomplete=True)
                self.assertTrue(device in vg_device.parents)

        get_device_by_uuid.reset_mock()
        get_device_by_uuid.return_value = None

        # pv belongs to a valid vg which is not in the tree (no lvs, either)
        pv_info.vg_size = "10g"
        pv_info.vg_free = 0
        pv_info.vg_extent_size = "4m"
        pv_info.vg_extent_count = 2500
        pv_info.vg_free_count = 0
        pv_info.vg_pv_count = 1

        with patch("blivet.static_data.lvm_info.PVsInfo.cache", new_callable=PropertyMock) as mock_pvs_cache:
            mock_pvs_cache.return_value = {sentinel.pv_path: pv_info}
            with patch("blivet.udev.device_get_format", return_value=self.udev_type):
                helper = self.helper_class(devicetree, data, device)
                helper.run()
                self.assertEqual(device.format.type,
                                 self.blivet_type,
                                 msg="Wrong format type after FormatPopulator.run on %s" % self.udev_type)

                self.assertEqual(get_device_by_uuid.call_count, 2)
                get_device_by_uuid.assert_called_with(pv_info.vg_uuid, incomplete=True)
                vg_device = devicetree.get_device_by_name(pv_info.vg_name)
                self.assertTrue(vg_device is not None)
                devicetree._remove_device(vg_device)

        get_device_by_uuid.reset_mock()

        # pv belongs to a valid vg not in the tree with two lvs
        lv1 = Mock()
        lv1.vg_name = pv_info.vg_name
        lv1.lv_name = "testlv1"
        lv1.uuid = sentinel.lv1_uuid
        lv1.attr = "-wi-ao----"
        lv1.size = "2g"
        lv1.segtype = "linear"
        lv1_name = "%s-%s" % (pv_info.vg_name, lv1.lv_name)

        lv2 = Mock()
        lv2.vg_name = pv_info.vg_name
        lv2.lv_name = "testlv2"
        lv2.uuid = sentinel.lv2_uuid
        lv2.attr = "-wi-ao----"
        lv2.size = "7g"
        lv2.segtype = "linear"
        lv2_name = "%s-%s" % (pv_info.vg_name, lv2.lv_name)

        lv_info = {lv1_name: lv1,
                   lv2_name: lv2}

        device.format.container_uuid = pv_info.vg_uuid

        def gdbu(uuid, **kwargs):  # pylint: disable=unused-argument
            # This version doesn't check format UUIDs
            return next((d for d in devicetree.devices if d.uuid == uuid), None)
        get_device_by_uuid.side_effect = gdbu

        with patch("blivet.static_data.lvm_info.PVsInfo.cache", new_callable=PropertyMock) as mock_pvs_cache:
            mock_pvs_cache.return_value = {sentinel.pv_path: pv_info}
            with patch("blivet.static_data.lvm_info.LVsInfo.cache", new_callable=PropertyMock) as mock_lvs_cache:
                mock_lvs_cache.return_value = lv_info
                with patch("blivet.udev.device_get_format", return_value=self.udev_type):
                    self.assertEqual(devicetree.get_device_by_name(pv_info.vg_name, incomplete=True), None)
                    helper = self.helper_class(devicetree, data, device)
                    helper.run()
                    self.assertEqual(device.format.type,
                                     self.blivet_type,
                                     msg="Wrong format type after FormatPopulator.run on %s" % self.udev_type)

                    self.assertEqual(get_device_by_uuid.call_count, 4,
                                     get_device_by_uuid.mock_calls)  # two for vg and one for each lv
                    get_device_by_uuid.assert_has_calls([call(pv_info.vg_uuid, incomplete=True),
                                                        call(lv1.uuid),
                                                        call(lv2.uuid)],
                                                        any_order=True)
                    vg_device = devicetree.get_device_by_name(pv_info.vg_name)
                    self.assertTrue(vg_device is not None)

                    lv1_device = devicetree.get_device_by_name(lv1_name)
                    self.assertEqual(lv1_device.uuid, lv1.uuid)
                    lv2_device = devicetree.get_device_by_name(lv2_name)
                    self.assertEqual(lv2_device.uuid, lv2.uuid)
Ejemplo n.º 32
0
class DeviceTreeIgnoredExclusiveMultipathTestCase(unittest.TestCase):
    def setUp(self):
        self.tree = DeviceTree()

        self.sda = DiskDevice("sda")
        self.sdb = DiskDevice("sdb")
        self.sdc = DiskDevice("sdc")

        self.tree._add_device(self.sda)
        self.tree._add_device(self.sdb)
        self.tree._add_device(self.sdc)

        self.assertTrue(self.sda in self.tree.devices)
        self.assertTrue(self.sdb in self.tree.devices)
        self.assertTrue(self.sdc in self.tree.devices)

        # now test exclusive_disks special cases for multipath
        self.sda.format = get_format("multipath_member", exists=True)
        self.sdb.format = get_format("multipath_member", exists=True)
        self.sdc.format = get_format("multipath_member", exists=True)
        self.mpatha = MultipathDevice("mpatha",
                                      parents=[self.sda, self.sdb, self.sdc])
        self.tree._add_device(self.mpatha)

    def test_exclusive_disks_multipath_1(self):
        # multipath is exclusive -> all disks should be exclusive
        self.tree.ignored_disks = []
        self.tree.exclusive_disks = ["mpatha"]

        with patch.object(self.tree, "hide") as hide:
            self.tree._hide_ignored_disks()
            self.assertFalse(hide.called)

        self.tree._hide_ignored_disks()
        self.assertTrue(self.sda in self.tree.devices)
        self.assertTrue(self.sdb in self.tree.devices)
        self.assertTrue(self.sdc in self.tree.devices)
        self.assertTrue(self.mpatha in self.tree.devices)

    def test_exclusive_disks_multipath_2(self):
        # all disks exclusive -> mpath should also be exclusive
        self.tree.exclusive_disks = ["sda", "sdb", "sdc"]
        with patch.object(self.tree, "hide") as hide:
            self.tree._hide_ignored_disks()
            self.assertFalse(hide.called)

        self.tree._hide_ignored_disks()
        self.assertTrue(self.sda in self.tree.devices)
        self.assertTrue(self.sdb in self.tree.devices)
        self.assertTrue(self.sdc in self.tree.devices)
        self.assertTrue(self.mpatha in self.tree.devices)

    def test_exclusive_disks_multipath_3(self):
        # some disks exclusive -> mpath should be hidden
        self.tree.exclusive_disks = ["sda", "sdb"]
        with patch.object(self.tree, "hide") as hide:
            self.tree._hide_ignored_disks()
            hide.assert_any_call(self.mpatha)
            hide.assert_any_call(self.sdc)

        # verify that hide works as expected
        self.tree._hide_ignored_disks()
        self.assertTrue(self.sda in self.tree.devices)
        self.assertTrue(self.sdb in self.tree.devices)
        self.assertFalse(self.sdc in self.tree.devices)
        self.assertFalse(self.mpatha in self.tree.devices)

    def test_ignored_disks_multipath_1(self):
        # mpatha ignored -> disks should be hidden
        self.tree.ignored_disks = ["mpatha"]
        self.tree.exclusive_disks = []

        with patch.object(self.tree, "hide") as hide:
            self.tree._hide_ignored_disks()
            hide.assert_any_call(self.mpatha)
            hide.assert_any_call(self.sda)
            hide.assert_any_call(self.sdb)
            hide.assert_any_call(self.sdc)

        self.tree._hide_ignored_disks()
        self.assertFalse(self.sda in self.tree.devices)
        self.assertFalse(self.sdb in self.tree.devices)
        self.assertFalse(self.sdc in self.tree.devices)
        self.assertFalse(self.mpatha in self.tree.devices)

    def test_ignored_disks_multipath_2(self):
        # all disks ignored -> mpath should be hidden
        self.tree.ignored_disks = ["sda", "sdb", "sdc"]
        self.tree.exclusive_disks = []

        with patch.object(self.tree, "hide") as hide:
            self.tree._hide_ignored_disks()
            hide.assert_any_call(self.mpatha)
            hide.assert_any_call(self.sda)
            hide.assert_any_call(self.sdb)
            hide.assert_any_call(self.sdc)

        self.tree._hide_ignored_disks()
        self.assertFalse(self.sda in self.tree.devices)
        self.assertFalse(self.sdb in self.tree.devices)
        self.assertFalse(self.sdc in self.tree.devices)
        self.assertFalse(self.mpatha in self.tree.devices)

    def test_ignored_disks_multipath_3(self):
        # some disks ignored -> error
        self.tree.ignored_disks = ["sda", "sdb"]
        self.tree.exclusive_disks = []

        with self.assertRaises(InvalidMultideviceSelection):
            self.tree._hide_ignored_disks()
Ejemplo n.º 33
0
    def test_recursive_remove(self):
        dt = DeviceTree()
        dev1 = StorageDevice("dev1", exists=False, parents=[])
        dev2 = StorageDevice("dev2", exists=False, parents=[dev1])
        dt._add_device(dev1)
        dt._add_device(dev2)

        # normal
        self.assertTrue(dev1 in dt.devices)
        self.assertTrue(dev2 in dt.devices)
        self.assertEqual(dt.actions._actions, list())
        dt.recursive_remove(dev1)
        self.assertFalse(dev1 in dt.devices)
        self.assertFalse(dev2 in dt.devices)
        self.assertNotEqual(dt.actions._actions, list())

        dt.reset()
        dt._add_device(dev1)
        dt._add_device(dev2, new=False)  # restore parent/child relationships

        # remove_device clears descendants and formatting but preserves the device
        dev1.format = get_format("swap")
        self.assertEqual(dev1.format.type, "swap")
        self.assertEqual(dt.actions._actions, list())
        dt.recursive_remove(dev1, remove_device=False)
        self.assertTrue(dev1 in dt.devices)
        self.assertFalse(dev2 in dt.devices)
        self.assertEqual(dev1.format.type, None)
        self.assertNotEqual(dt.actions._actions, list())

        dt.reset()
        dt._add_device(dev1)
        dt._add_device(dev2, new=False)  # restore parent/child relationships

        # actions=False performs the removals without scheduling actions
        self.assertEqual(dt.actions._actions, list())
        dt.recursive_remove(dev1, actions=False)
        self.assertFalse(dev1 in dt.devices)
        self.assertFalse(dev2 in dt.devices)
        self.assertEqual(dt.actions._actions, list())

        dt.reset()
        dt._add_device(dev1)
        dt._add_device(dev2, new=False)  # restore parent/child relationships

        # modparent only works when actions=False is passed
        with patch.object(dt, "_remove_device") as remove_device:
            dt.recursive_remove(dev1, actions=False)
            remove_device.assert_called_with(dev1, modparent=True)

            dt.recursive_remove(dev1, actions=False, modparent=False)
            remove_device.assert_called_with(dev1, modparent=False)