Example #1
0
    def test_dependencies_handling(self):
        device = StorageDevice("testdev1")
        self.assertTrue(device.controllable)
        self.assertIsNotNone(ActionCreateDevice(device))
        device.exists = True
        self.assertIsNotNone(ActionDestroyDevice(device))
        with patch.object(StorageDevice, "resizable", new_callable=PropertyMock(return_value=True)):
            self.assertIsNotNone(ActionResizeDevice(device, Size("1 GiB")))

        # if any external dependency is missing, it should be impossible to create, destroy, setup,
        # teardown, or resize the device (controllable encompasses setup & teardown)
        with patch.object(StorageDevice, "_external_dependencies",
                          new_callable=PropertyMock(return_value=[availability.unavailable_resource("testing")])):
            device = StorageDevice("testdev1")
            self.assertFalse(device.controllable)
            self.assertRaises(DependencyError, ActionCreateDevice, device)
            device.exists = True
            self.assertRaises(DependencyError, ActionDestroyDevice, device)
            self.assertRaises(ValueError, ActionResizeDevice, device, Size("1 GiB"))

        # same goes for formats, except that the properties they affect vary by format class
        fmt = get_format("lvmpv")
        fmt._plugin = availability.available_resource("lvm-testing")
        self.assertTrue(fmt.supported)
        self.assertTrue(fmt.formattable)
        self.assertTrue(fmt.destroyable)

        fmt._plugin = availability.unavailable_resource("lvm-testing")
        self.assertFalse(fmt.supported)
        self.assertFalse(fmt.formattable)
        self.assertFalse(fmt.destroyable)
Example #2
0
    def test_match(self):
        """Test boot format populator helper match method"""
        if self.helper_class is None:
            return

        partition = PartitionDevice("testpartitiondev")
        storagedev = StorageDevice("teststoragedev")
        storagedev.bootable = True
        data = dict()

        fmt_class = get_device_format_class(self.helper_class._type_specifier)
        if fmt_class is None:
            self.skipTest("failed to look up format class for %s" % self.helper_class._type_specifier)

        data["ID_FS_TYPE"] = self.helper_class._base_type_specifier
        partition._bootable = self.helper_class._bootable
        min_size = fmt_class._min_size
        max_size = fmt_class._max_size
        partition._size = min_size
        storagedev._size = min_size

        if fmt_class._name:
            partition._parted_partition = FakePartedPart(partition, fmt_class._name)

        self.assertTrue(self.helper_class.match(data, partition))

        # These are only valid for partitions.
        self.assertFalse(self.helper_class.match(data, storagedev))

        data["ID_FS_TYPE"] += "x"
        self.assertFalse(self.helper_class.match(data, partition))
        data["ID_FS_TYPE"] = self.helper_class._base_type_specifier

        if self.helper_class._bootable:
            partition._bootable = False
            self.assertFalse(self.helper_class.match(data, partition))
            partition._bootable = True

        if max_size:
            partition._size = max_size + 1
        elif min_size:
            partition._size = min_size - 1

        self.assertFalse(self.helper_class.match(data, partition))
        partition._size = min_size

        # we don't always match on the parted partition name, so allow
        # subclasses to decide
        if not self.name_mismatch_ok:
            orig = partition._parted_partition
            partition._parted_partition = FakePartedPart(partition, 'dontmatchanything')
            self.assertFalse(self.helper_class.match(data, partition))

            # shouldn't crash
            partition._parted_partition = None
            self.assertFalse(self.helper_class.match(data, partition))
            partition._parted_partition = orig
Example #3
0
    def test_net_dev_setting(self):
        """ Verify netdev mount option setting after format assignment. """
        netdev = FakeNetDev("net1")
        dev = StorageDevice("dev1", fmt=get_format("ext4"))
        self.assertFalse("_netdev" in dev.format.options.split(","))

        dev.parents.append(netdev)
        dev.format = get_format("ext4")
        self.assertTrue("_netdev" in dev.format.options.split(","))
Example #4
0
    def testStorageDevice(self):
        # Check that / and NUL are rejected along with . and ..
        good_names = ['sda1', '1sda', 'good-name', 'cciss/c0d0']
        bad_names = ['sda/1', 'sda\x00', '.', '..', 'cciss/..']

        for name in good_names:
            self.assertTrue(StorageDevice.isNameValid(name))

        for name in bad_names:
            self.assertFalse(StorageDevice.isNameValid(name))
    def test_resizable(self):
        """ Test resizable property of unformatted devices. """
        # Devices with no (or unrecognized) formatting should not be resizable.
        device = StorageDevice("testdev1", exists=True, size=Size("100 G"), fmt=get_format("ext4", exists=True))
        device._resizable = True
        with patch.object(device, "_format", exists=True, resizable=True):
            self.assertTrue(device.resizable)

        device = StorageDevice("testdev1", exists=True, size=Size("100 G"))
        device._resizable = True
        self.assertFalse(device.resizable)
Example #6
0
    def test_storage_device(self):
        # Check that / and NUL are rejected along with . and ..
        good_names = ['sda1', '1sda', 'good-name', 'cciss/c0d0']
        bad_names = ['sda/1', 'sda\x00', '.', '..', 'cciss/..']

        sd = StorageDevice("tester")

        for name in good_names:
            self.assertTrue(sd.is_name_valid(name))

        for name in bad_names:
            self.assertFalse(sd.is_name_valid(name))
Example #7
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)
Example #8
0
    def test_net_dev_update(self):
        """ Verify netdev mount option setting after device creation. """
        netdev = FakeNetDev("net1")
        dev = StorageDevice("dev1", fmt=get_format("ext4"))
        self.assertFalse("_netdev" in dev.format.options.split(","))

        dev.parents.append(netdev)

        # these create methods shouldn't write anything to disk
        netdev.create()
        dev.create()

        self.assertTrue("_netdev" in dev.format.options.split(","))
Example #9
0
    def test_ctor_parted_partition_error_handling(self):
        disk = StorageDevice("testdisk", exists=True)
        disk._partitionable = True
        with patch.object(disk, "_format") as fmt:
            fmt.type = "disklabel"
            self.assertTrue(disk.partitioned)

            fmt.supported = True

            # Normal case, no exn.
            device = PartitionDevice("testpart1", exists=True, parents=[disk])
            self.assertIn(device, disk.children)
            device.parents.remove(disk)
            self.assertEqual(len(disk.children), 0, msg="disk has children when it should not")

            # Parted doesn't find a partition, exn is raised.
            fmt.parted_disk.getPartitionByPath.return_value = None
            self.assertRaises(DeviceError, PartitionDevice, "testpart1", exists=True, parents=[disk])
            self.assertEqual(len(disk.children), 0, msg="device is still attached to disk in spite of ctor error")
Example #10
0
    def test_match(self):
        """Test boot format populator helper match method"""
        if self.helper_class is None:
            return

        partition = PartitionDevice("testpartitiondev")
        storagedev = StorageDevice("teststoragedev")
        storagedev.bootable = True
        data = dict()

        fmt_class = get_device_format_class(self.helper_class._type_specifier)
        if fmt_class is None:
            self.skipTest("failed to look up format class for %s" % self.helper_class._type_specifier)

        data["ID_FS_TYPE"] = self.helper_class._base_type_specifier
        partition._bootable = self.helper_class._bootable
        min_size = fmt_class._min_size
        max_size = fmt_class._max_size
        partition._size = min_size
        storagedev._size = min_size

        self.assertTrue(self.helper_class.match(data, partition))

        # These are only valid for partitions.
        self.assertFalse(self.helper_class.match(data, storagedev))

        data["ID_FS_TYPE"] += "x"
        self.assertFalse(self.helper_class.match(data, partition))
        data["ID_FS_TYPE"] = self.helper_class._base_type_specifier

        if self.helper_class._bootable:
            partition._bootable = False
            self.assertFalse(self.helper_class.match(data, partition))
            partition._bootable = True

        if max_size:
            partition._size = max_size + 1
        elif min_size:
            partition._size = min_size - 1

        self.assertFalse(self.helper_class.match(data, partition))
        partition._size = min_size
Example #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)
Example #12
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
        self.assertRaisesRegex(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
        self.assertRaisesRegex(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)
    def generate_device_factory_request_btrfs_test(self, blockdev):
        dev1 = StorageDevice("dev1",
                             fmt=get_format("btrfs"),
                             size=Size("10 GiB"))

        dev2 = BTRFSVolumeDevice("dev2", data_level="single", parents=[dev1])

        dev3 = BTRFSSubVolumeDevice(
            parents=[dev2],
            fmt=get_format("btrfs", mountpoint="/boot"),
        )

        request = utils.generate_device_factory_request(self.storage, dev3)
        self.assertEqual(
            DeviceFactoryRequest.to_structure(request), {
                "device-spec":
                get_variant(Str, dev3.name),
                "disks":
                get_variant(List[Str], []),
                "mount-point":
                get_variant(Str, "/boot"),
                "reformat":
                get_variant(Bool, True),
                "format-type":
                get_variant(Str, "btrfs"),
                "label":
                get_variant(Str, ""),
                "luks-version":
                get_variant(Str, ""),
                "device-type":
                get_variant(Int, devicefactory.DEVICE_TYPE_BTRFS),
                "device-name":
                get_variant(Str, dev3.name),
                "device-size":
                get_variant(UInt64,
                            Size("10 GiB").get_bytes()),
                "device-encrypted":
                get_variant(Bool, False),
                "device-raid-level":
                get_variant(Str, ""),
                "container-spec":
                get_variant(Str, dev2.name),
                "container-name":
                get_variant(Str, dev2.name),
                "container-size-policy":
                get_variant(Int64,
                            Size("10 GiB").get_bytes()),
                "container-encrypted":
                get_variant(Bool, False),
                "container-raid-level":
                get_variant(Str, "single"),
            })
Example #14
0
    def test_volume_group(self):
        good_names = ['vg00', 'group-name', 'groupname-']
        bad_names = ['-leading-hyphen', 'Ășnicode', 'sp aces']

        pv = StorageDevice("pv1", fmt=blivet.formats.get_format("lvmpv"),
                           size=Size("1 GiB"))
        vg = LVMVolumeGroupDevice("testvg", parents=[pv])

        for name in good_names:
            self.assertTrue(vg.is_name_valid(name))

        for name in bad_names:
            self.assertFalse(vg.is_name_valid(name))
Example #15
0
    def test_mount_existing_system(self, mount):
        storage = create_storage()
        device = StorageDevice("dev1", fmt=get_format("ext4"))
        storage.devicetree._add_device(device)

        task = MountExistingSystemTask(storage, device, True)
        task.run()

        mount.assert_called_once_with(
            storage=storage,
            root_device=device,
            read_only=True
        )
    def test_mount_device_with_options(self, mount):
        """Test MountDevice with options specified."""
        self._add_device(StorageDevice("dev1", fmt=get_format("ext4")))

        with tempfile.TemporaryDirectory() as d:
            self.interface.MountDevice("dev1", d, "ro,auto")
            mount.assert_called_once_with(mountpoint=d, options="ro,auto")

        mount.side_effect = FSError("Fake error.")
        with pytest.raises(MountFilesystemError) as cm:
            self.interface.MountDevice("dev1", "/path", "ro,auto")

        assert str(cm.value) == "Failed to mount dev1 at /path: Fake error."
Example #17
0
    def setUp(self):
        pv = StorageDevice("pv1",
                           fmt=blivet.formats.get_format("lvmpv"),
                           size=Size("1 GiB"))
        vg = LVMVolumeGroupDevice("testvg", parents=[pv])
        self.fmt = blivet.formats.get_format("xfs")
        self.lv = LVMLogicalVolumeDevice("testlv", parents=[vg], fmt=self.fmt)

        pv2 = StorageDevice("pv2",
                            fmt=blivet.formats.get_format("lvmpv"),
                            size=Size("1 GiB"))
        pv3 = StorageDevice("pv3",
                            fmt=blivet.formats.get_format("lvmpv"),
                            size=Size("1 GiB"))
        vg2 = LVMVolumeGroupDevice("testvg2", parents=[pv2, pv3])
        cache_req = LVMCacheRequest(Size("512 MiB"), [pv3], "writethrough")
        self.cached_lv = LVMLogicalVolumeDevice(
            "testcachedlv",
            parents=[vg2],
            fmt=blivet.formats.get_format("xfs"),
            exists=False,
            cache_request=cache_req)
Example #18
0
    def test_lvmcached_logical_volume_init(self):
        pv = StorageDevice("pv1",
                           fmt=blivet.formats.get_format("lvmpv"),
                           size=Size("1 GiB"))
        pv2 = StorageDevice("pv2",
                            fmt=blivet.formats.get_format("lvmpv"),
                            size=Size("512 MiB"))
        vg = LVMVolumeGroupDevice("testvg", parents=[pv, pv2])

        cache_req = LVMCacheRequest(Size("512 MiB"), [pv2], "writethrough")
        lv = LVMLogicalVolumeDevice("testlv",
                                    parents=[vg],
                                    fmt=blivet.formats.get_format("xfs"),
                                    exists=False,
                                    cache_request=cache_req)

        # the cache reserves space for its metadata from the requested size, but
        # it may require (and does in this case) a pmspare LV to be allocated
        self.assertEqual(lv.vg_space_used, Size("504 MiB"))

        # check that the LV behaves like a cached LV
        self.assertTrue(lv.cached)
        cache = lv.cache
        self.assertIsNotNone(cache)

        # check parameters reported by the (non-existing) cache
        # 512 MiB - 8 MiB (metadata) - 8 MiB (pmspare)
        self.assertEqual(cache.size, Size("496 MiB"))
        self.assertEqual(cache.md_size, Size("8 MiB"))
        self.assertEqual(cache.vg_space_used, Size("504 MiB"))
        self.assertIsInstance(cache.size, Size)
        self.assertIsInstance(cache.md_size, Size)
        self.assertIsInstance(cache.vg_space_used, Size)
        self.assertFalse(cache.exists)
        self.assertIsNone(cache.stats)
        self.assertEqual(cache.mode, "writethrough")
        self.assertIsNone(cache.backing_device_name)
        self.assertIsNone(cache.cache_device_name)
        self.assertEqual(set(cache.fast_pvs), set([pv2]))
    def mount_existing_system_test(self, mount):
        storage = create_storage()
        device = StorageDevice("dev1", fmt=get_format("ext4"))
        storage.devicetree._add_device(device)

        with tempfile.TemporaryDirectory() as sysroot:
            task = MountExistingSystemTask(storage, sysroot, device, True)
            task.run()

        mount.assert_called_once_with(storage=storage,
                                      sysroot=sysroot,
                                      root_device=device,
                                      read_only=True)
Example #20
0
 def test_lvm_logical_volume_pv_free_cached(self):
     pv = StorageDevice("pv1",
                        fmt=blivet.formats.get_format("lvmpv"),
                        size=Size("1025 MiB"))
     pv2 = StorageDevice("pv2",
                         fmt=blivet.formats.get_format("lvmpv"),
                         size=Size("513 MiB"))
     vg = LVMVolumeGroupDevice("testvg", parents=[pv, pv2])
     pv_spec = LVPVSpec(pv, Size("256 MiB"))
     pv_spec2 = LVPVSpec(pv2, Size("256 MiB"))
     cache_req = LVMCacheRequest(Size("512 MiB"), [pv], "writethrough")
     lv = LVMLogicalVolumeDevice("testlv",
                                 parents=[vg],
                                 size=Size("512 MiB"),
                                 fmt=blivet.formats.get_format("xfs"),
                                 exists=False,
                                 cache_request=cache_req,
                                 pvs=[pv_spec, pv_spec2])
     self.assertEqual(lv.seg_type, "linear")
     # 1024 MiB (free) - 256 MiB (LV part) - 504 MiB (cache shrank for pmspare space)
     self.assertEqual(pv.format.free, Size("264 MiB"))
     self.assertEqual(pv2.format.free, Size("256 MiB"))
Example #21
0
    def collect_containers_test(self):
        """Test CollectContainers."""
        dev1 = StorageDevice("dev1",
                             fmt=get_format("btrfs"),
                             size=Size("10 GiB"))
        dev2 = BTRFSVolumeDevice("dev2", parents=[dev1])

        self._add_device(dev1)
        self._add_device(dev2)

        self.assertEqual(self.interface.CollectContainers(DEVICE_TYPE_BTRFS),
                         [dev2.name])
        self.assertEqual(self.interface.CollectContainers(DEVICE_TYPE_LVM), [])
Example #22
0
    def test_vg_is_empty(self):
        pv = StorageDevice("pv1",
                           fmt=blivet.formats.get_format("lvmpv"),
                           size=Size("1024 MiB"))
        vg = LVMVolumeGroupDevice("testvg", parents=[pv])
        self.assertTrue(vg.is_empty)

        LVMLogicalVolumeDevice("testlv",
                               parents=[vg],
                               size=Size("512 MiB"),
                               fmt=blivet.formats.get_format("xfs"),
                               exists=False)
        self.assertFalse(vg.is_empty)
Example #23
0
    def test_find_unconfigured_luks(self):
        """Test FindUnconfiguredLUKS."""
        self.assertEqual(self.interface.FindUnconfiguredLUKS(), [])

        dev1 = StorageDevice("dev1", fmt=get_format("ext4"), size=Size("10 GiB"))
        self._add_device(dev1)

        self.assertEqual(self.interface.FindUnconfiguredLUKS(), [])

        dev2 = LUKSDevice("dev2", parents=[dev1], fmt=get_format("luks"), size=Size("10 GiB"))
        self._add_device(dev2)

        self.assertEqual(self.interface.FindUnconfiguredLUKS(), ["dev2"])
Example #24
0
    def test_get_ancestors(self):
        """Test GetAncestors."""
        dev1 = StorageDevice("dev1")
        self._add_device(dev1)

        dev2 = StorageDevice("dev2", parents=[dev1])
        self._add_device(dev2)

        dev3 = StorageDevice("dev3", parents=[dev2])
        self._add_device(dev3)

        dev4 = StorageDevice("dev4")
        self._add_device(dev4)

        dev5 = StorageDevice("dev5", parents=[dev4])
        self._add_device(dev5)

        self.assertEqual(self.interface.GetAncestors(["dev1"]), [])
        self.assertEqual(self.interface.GetAncestors(["dev2"]), ["dev1"])
        self.assertEqual(self.interface.GetAncestors(["dev3"]), ["dev1", "dev2"])
        self.assertEqual(self.interface.GetAncestors(["dev2", "dev3"]), ["dev1", "dev2"])
        self.assertEqual(self.interface.GetAncestors(["dev2", "dev5"]), ["dev1", "dev4"])
    def generate_device_factory_request_lvm_test(self, blockdev):
        pv1 = StorageDevice("pv1",
                            size=Size("1025 MiB"),
                            fmt=get_format("lvmpv"))
        pv2 = StorageDevice("pv2",
                            size=Size("513 MiB"),
                            fmt=get_format("lvmpv"))
        vg = LVMVolumeGroupDevice("testvg", parents=[pv1, pv2])
        lv = LVMLogicalVolumeDevice("testlv",
                                    size=Size("512 MiB"),
                                    parents=[vg],
                                    fmt=get_format("xfs"),
                                    exists=False,
                                    seg_type="raid1",
                                    pvs=[pv1, pv2])

        request = utils.generate_device_factory_request(self.storage, lv)
        self.assertEqual(
            DeviceFactoryRequest.to_structure(request), {
                "device-spec": get_variant(Str, "testvg-testlv"),
                "disks": get_variant(List[Str], []),
                "mount-point": get_variant(Str, ""),
                "reformat": get_variant(Bool, True),
                "format-type": get_variant(Str, "xfs"),
                "label": get_variant(Str, ""),
                "luks-version": get_variant(Str, ""),
                "device-type": get_variant(Int, devicefactory.DEVICE_TYPE_LVM),
                "device-name": get_variant(Str, "testlv"),
                "device-size": get_variant(UInt64,
                                           Size("508 MiB").get_bytes()),
                "device-encrypted": get_variant(Bool, False),
                "device-raid-level": get_variant(Str, ""),
                "container-spec": get_variant(Str, "testvg"),
                "container-name": get_variant(Str, "testvg"),
                "container-size-policy": get_variant(Int64, Size("1.5 GiB")),
                "container-encrypted": get_variant(Bool, False),
                "container-raid-level": get_variant(Str, ""),
            })
Example #26
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)
Example #27
0
    def mount_device_test(self, mount):
        """Test MountDevice."""
        self._add_device(StorageDevice("dev1", fmt=get_format("ext4")))

        with tempfile.TemporaryDirectory() as d:
            self.interface.MountDevice("dev1", d)
            mount.assert_called_once_with(mountpoint=d)

        mount.side_effect = FSError("Fake error.")
        with self.assertRaises(MountFilesystemError) as cm:
            self.interface.MountDevice("dev1", "/path")

        self.assertEqual(str(cm.exception),
                         "Failed to mount dev1 at /path: Fake error.")
Example #28
0
    def is_device_editable_test(self):
        """Test IsDeviceEditable."""
        dev1 = StorageDevice("dev1",
                             fmt=get_format("ext4"),
                             size=Size("10 GiB"))
        dev2 = DiskDevice("dev2",
                          fmt=get_format("disklabel"),
                          size=Size("10 GiB"))

        self._add_device(dev1)
        self._add_device(dev2)

        self.assertEqual(self.interface.IsDeviceEditable("dev1"), False)
        self.assertEqual(self.interface.IsDeviceEditable("dev2"), True)
Example #29
0
    def test_lvm_logical_volume_mirror(self):
        pv = StorageDevice("pv1",
                           fmt=blivet.formats.get_format("lvmpv"),
                           size=Size("1025 MiB"))
        pv2 = StorageDevice("pv2",
                            fmt=blivet.formats.get_format("lvmpv"),
                            size=Size("513 MiB"))
        vg = LVMVolumeGroupDevice("testvg", parents=[pv, pv2])

        lv = LVMLogicalVolumeDevice("testlv",
                                    parents=[vg],
                                    size=Size("512 MiB"),
                                    fmt=blivet.formats.get_format("xfs"),
                                    exists=False,
                                    seg_type="mirror",
                                    pvs=[pv, pv2])

        self.assertEqual(lv.seg_type, "mirror")
        # 512 MiB - 4 MiB (metadata)
        self.assertEqual(lv.size, Size("508 MiB"))
        self.assertEqual(lv._raid_level, raid.RAID1)
        self.assertTrue(lv.is_raid_lv)
        self.assertEqual(lv._num_raid_pvs, 2)
    def test_unmount_device(self, unmount):
        """Test UnmountDevice."""
        self._add_device(StorageDevice("dev1", fmt=get_format("ext4")))

        with tempfile.TemporaryDirectory() as d:
            self.interface.UnmountDevice("dev1", d)
            unmount.assert_called_once_with(mountpoint=d)

        unmount.side_effect = FSError("Fake error.")
        with pytest.raises(MountFilesystemError) as cm:
            self.interface.UnmountDevice("dev1", "/path")

        assert str(
            cm.value) == "Failed to unmount dev1 from /path: Fake error."
    def test_is_device_editable(self):
        """Test IsDeviceEditable."""
        dev1 = StorageDevice("dev1",
                             fmt=get_format("ext4"),
                             size=Size("10 GiB"))
        dev2 = DiskDevice("dev2",
                          fmt=get_format("disklabel"),
                          size=Size("10 GiB"))

        self._add_device(dev1)
        self._add_device(dev2)

        assert self.interface.IsDeviceEditable("dev1") is False
        assert self.interface.IsDeviceEditable("dev2") is True
Example #32
0
    def test_opal_verification_old_firmware(self, mocked_arch, version_getter, xfs_mountable):
        """Check verify_opal_compatibility with an older firmware."""
        storage = create_storage()

        mocked_arch.get_arch.return_value = "ppc64le"
        mocked_arch.is_powernv.return_value = True
        version_getter.return_value = "5.9.50-openpower1-p59fd803"
        xfs_mountable.return_value = True

        # No devices.
        self._verify_opal_compatibility(storage, message=None)

        # No mount points.
        dev1 = StorageDevice("dev1", size=Size("10 GiB"))
        storage.devicetree._add_device(dev1)

        self._verify_opal_compatibility(storage, message=None)

        # Different filesystem.
        dev1.format = get_format("ext2", mountpoint="/boot")
        self._verify_opal_compatibility(storage, message=None)

        # XFS on /
        dev1.format = get_format("xfs", mountpoint="/")
        self._verify_opal_compatibility(storage, message=(
            "Your firmware doesn't support XFS file system features "
            "on the /boot file system. The system will not be bootable. "
            "Please, upgrade the firmware or change the file system type."
        ))

        # XFS on /boot
        dev1.format = get_format("xfs", mountpoint="/boot")
        self._verify_opal_compatibility(storage, message=(
            "Your firmware doesn't support XFS file system features "
            "on the /boot file system. The system will not be bootable. "
            "Please, upgrade the firmware or change the file system type."
        ))
    def get_raw_device_test(self):
        """Test GetRawDevice."""
        dev1 = StorageDevice("dev1",
                             fmt=get_format("ext4"),
                             size=Size("10 GiB"))
        dev2 = LUKSDevice("dev2",
                          parents=[dev1],
                          fmt=get_format("luks"),
                          size=Size("10 GiB"))

        self._add_device(dev1)
        self._add_device(dev2)

        self.assertEqual(self.interface.GetRawDevice("dev1"), "dev1")
        self.assertEqual(self.interface.GetRawDevice("dev2"), "dev1")
Example #34
0
    def test_storage_device(self, *patches):  # pylint: disable=unused-argument
        # Check that / and NUL are rejected along with . and ..
        good_names = ['sda1', '1sda', 'good-name', 'cciss/c0d0']
        bad_names = ['sda/1', 'sda\x00', '.', '..', 'cciss/..']

        sd = StorageDevice("tester")

        for name in good_names:
            self.assertTrue(sd.is_name_valid(name))

        for name in bad_names:
            self.assertFalse(sd.is_name_valid(name))

        # Check that name validity check is omitted (only) when
        # device already exists
        # This test was added to prevent regression (see #1379145)
        for name in good_names:
            try:
                StorageDevice(name, exists=True)
            except ValueError:
                self.fail("Name check should not be performed nor failing")

            try:
                StorageDevice(name, exists=False)
            except ValueError:
                self.fail("Device name check failed when it shouldn't")

        for name in bad_names:
            try:
                StorageDevice(name, exists=True)
            except ValueError as e:
                if ' is not a valid name for this device' in str(e):
                    self.fail("Device name checked on already existing device")

            with six.assertRaisesRegex(self, ValueError, ' is not a valid name for this device'):
                StorageDevice(name, exists=False)
Example #35
0
    def test_target_size(self):
        pv = StorageDevice("pv1",
                           fmt=blivet.formats.get_format("lvmpv"),
                           size=Size("1 GiB"))
        vg = LVMVolumeGroupDevice("testvg", parents=[pv])
        orig_size = Size("800 MiB")
        lv = LVMLogicalVolumeDevice("testlv",
                                    parents=[vg],
                                    size=orig_size,
                                    fmt=blivet.formats.get_format("ext4"),
                                    exists=True)

        min_size = Size("200 MiB")
        lv.format.exists = True
        lv.format._min_instance_size = min_size
        lv.format._resizable = True

        # Make sure things are as expected to begin with.
        self.assertEqual(lv.min_size, min_size)
        self.assertEqual(lv.max_size, Size("1020 MiB"))
        self.assertEqual(lv.size, orig_size)

        # ValueError if size smaller than min_size
        with self.assertRaisesRegex(ValueError,
                                    "size.*smaller than the minimum"):
            lv.target_size = Size("1 MiB")

        # target size should be unchanged
        self.assertEqual(lv.target_size, orig_size)

        # ValueError if size larger than max_size
        with self.assertRaisesRegex(ValueError,
                                    "size.*larger than the maximum"):
            lv.target_size = Size("1 GiB")

        # target size should be unchanged
        self.assertEqual(lv.target_size, orig_size)

        # successful set of target size should also be reflected in size attr
        new_target = Size("900 MiB")
        lv.target_size = new_target
        self.assertEqual(lv.target_size, new_target)
        self.assertEqual(lv.size, new_target)

        # reset target size to original size
        lv.target_size = orig_size
        self.assertEqual(lv.target_size, orig_size)
        self.assertEqual(lv.size, orig_size)
Example #36
0
    def test_logical_volume(self):
        good_names = ['lv00', 'volume-name', 'volumename-']
        bad_names = ['-leading-hyphen', 'Ășnicode', 'sp aces',
                     'snapshot47', 'pvmove0', 'sub_tmetastring']

        pv = StorageDevice("pv1", fmt=blivet.formats.get_format("lvmpv"),
                           size=Size("1 GiB"))
        vg = LVMVolumeGroupDevice("testvg", parents=[pv])
        lv = LVMLogicalVolumeDevice("testlv", parents=[vg],
                                    fmt=blivet.formats.get_format("xfs"))

        for name in good_names:
            self.assertTrue(lv.is_name_valid(name))

        for name in bad_names:
            self.assertFalse(lv.is_name_valid(name))
Example #37
0
    def get_container_free_space_test(self):
        """Test GetContainerFreeSpace."""
        dev1 = StorageDevice("dev1",
                             fmt=get_format("lvmpv"),
                             size=Size("10 GiB"))
        dev2 = LVMVolumeGroupDevice("dev2", parents=[dev1])

        self._add_device(dev1)
        self._add_device(dev2)

        free_space = self.interface.GetContainerFreeSpace("dev1")
        self.assertEqual(free_space, 0)

        free_space = self.interface.GetContainerFreeSpace("dev2")
        self.assertGreater(free_space, Size("9 GiB").get_bytes())
        self.assertLess(free_space, Size("10 GiB").get_bytes())
Example #38
0
    def set_device_passphrase_test(self):
        """Test SetDevicePassphrase."""
        dev1 = StorageDevice("dev1",
                             fmt=get_format("ext4"),
                             size=Size("10 GiB"))
        self._add_device(dev1)

        dev2 = LUKSDevice("dev2",
                          parents=[dev1],
                          fmt=get_format("luks"),
                          size=Size("10 GiB"))
        self._add_device(dev2)

        self.assertEqual(self.interface.FindUnconfiguredLUKS(), ["dev2"])
        self.interface.SetDevicePassphrase("dev2", "123456")
        self.assertEqual(self.interface.FindUnconfiguredLUKS(), [])
    def test_get_container_free_space(self):
        """Test GetContainerFreeSpace."""
        dev1 = StorageDevice("dev1",
                             fmt=get_format("lvmpv"),
                             size=Size("10 GiB"))
        dev2 = LVMVolumeGroupDevice("dev2", parents=[dev1])

        self._add_device(dev1)
        self._add_device(dev2)

        free_space = self.interface.GetContainerFreeSpace("dev1")
        assert free_space == 0

        free_space = self.interface.GetContainerFreeSpace("dev2")
        assert free_space > Size("9 GiB").get_bytes()
        assert free_space < Size("10 GiB").get_bytes()
    def test_resizable(self):
        """ Test resizable property of unformatted devices. """
        # Devices with no (or unrecognized) formatting should not be resizable.
        device = StorageDevice("testdev1", exists=True, size=Size("100 G"), fmt=get_format("ext4", exists=True))
        device._resizable = True
        with patch.object(device, "_format", exists=True, resizable=True):
            self.assertTrue(device.resizable)

        device = StorageDevice("testdev1", exists=True, size=Size("100 G"))
        device._resizable = True
        self.assertFalse(device.resizable)
Example #41
0
    def test_get_devices(self):
        """Test GetDevices."""
        self.assertEqual(self.interface.GetDevices(), [])

        self._add_device(DiskDevice(
            "dev1",
            fmt=get_format("ext4"),
            size=Size("10 GiB")
        ))

        self._add_device(StorageDevice(
            "dev2",
            fmt=get_format("ext4"),
            size=Size("10 GiB")
        ))

        self.assertEqual(self.interface.GetDevices(), ["dev1", "dev2"])
Example #42
0
    def test_lvmthin_snap_shot_device_init(self):
        pv = StorageDevice("pv1",
                           fmt=blivet.formats.get_format("lvmpv"),
                           size=Size("1 GiB"))
        vg = LVMVolumeGroupDevice("testvg", parents=[pv])
        pool = LVMLogicalVolumeDevice("pool1",
                                      parents=[vg],
                                      size=Size("500 MiB"),
                                      seg_type="thin-pool")
        thinlv = LVMLogicalVolumeDevice("thinlv",
                                        parents=[pool],
                                        size=Size("200 MiB"),
                                        seg_type="thin")

        with self.assertRaisesRegex(
                ValueError, "lvm snapshot origin volume must already exist"):
            LVMLogicalVolumeDevice("snap1",
                                   parents=[pool],
                                   origin=thinlv,
                                   seg_type="thin")

        with self.assertRaisesRegex(
                ValueError, "lvm snapshot origin must be a logical volume"):
            LVMLogicalVolumeDevice("snap1",
                                   parents=[pool],
                                   origin=pv,
                                   seg_type="thin")

        # now make the constructor succeed so we can test some properties
        thinlv.exists = True
        snap1 = LVMLogicalVolumeDevice("snap1",
                                       parents=[pool],
                                       origin=thinlv,
                                       seg_type="thin")
        self.assertEqual(snap1.isleaf, True)
        self.assertEqual(snap1.direct, True)
        self.assertEqual(thinlv.isleaf, True)
        self.assertEqual(thinlv.direct, True)

        self.assertEqual(snap1.depends_on(thinlv), True)
        self.assertEqual(thinlv.depends_on(snap1), False)

        # existing thin snapshots do not depend on their origin
        snap1.exists = True
        self.assertEqual(snap1.depends_on(thinlv), False)