Example #1
0
    def test_availability_mdraidplugin(self):

        availability.CACHE_AVAILABILITY = False
        availability.BLOCKDEV_DM_PLUGIN._method = availability.AvailableMethod

        # if the plugin is not in, there's nothing to test
        self.assertIn(availability.BLOCKDEV_MDRAID_PLUGIN,
                      self.luks.external_dependencies)

        # dev is not among its unavailable dependencies
        availability.BLOCKDEV_MDRAID_PLUGIN._method = availability.AvailableMethod
        availability.MKFS_HFSPLUS_APP._method = availability.AvailableMethod  # macefi
        self.assertNotIn(availability.BLOCKDEV_MDRAID_PLUGIN,
                         self.luks.unavailable_dependencies)
        self.assertIsNotNone(ActionCreateDevice(self.luks))
        self.assertIsNotNone(ActionDestroyDevice(self.luks))
        self.assertIsNotNone(
            ActionCreateFormat(self.luks, fmt=get_format("macefi")))
        self.assertIsNotNone(ActionDestroyFormat(self.luks))

        # dev is among the unavailable dependencies
        availability.BLOCKDEV_MDRAID_PLUGIN._method = availability.UnavailableMethod
        self.assertIn(availability.BLOCKDEV_MDRAID_PLUGIN,
                      self.luks.unavailable_dependencies)
        with self.assertRaises(ValueError):
            ActionCreateDevice(self.luks)
        with self.assertRaises(ValueError):
            ActionDestroyDevice(self.dev)
        with self.assertRaises(ValueError):
            ActionCreateFormat(self.dev)
        with self.assertRaises(ValueError):
            ActionDestroyFormat(self.dev)
Example #2
0
    def testActionCreation(self):
        """ Verify correct operation of action class constructors. """
        # instantiation of device resize action for non-existent device should
        # fail
        # XXX resizable depends on existence, so this is covered implicitly
        sdd = self.storage.devicetree.getDeviceByName("sdd")
        p = self.newDevice(device_class=PartitionDevice, name="sdd1", size=Size("32 GiB"), parents=[sdd])
        with self.assertRaises(ValueError):
            ActionResizeDevice(p, p.size + Size("7232 MiB"))

        # instantiation of device resize action for non-resizable device
        # should fail
        vg = self.storage.devicetree.getDeviceByName("VolGroup")
        self.assertNotEqual(vg, None)
        with self.assertRaises(ValueError):
            ActionResizeDevice(vg, vg.size + Size("32 MiB"))

        # instantiation of format resize action for non-resizable format type
        # should fail
        lv_swap = self.storage.devicetree.getDeviceByName("VolGroup-lv_swap")
        self.assertNotEqual(lv_swap, None)
        with self.assertRaises(ValueError):
            ActionResizeFormat(lv_swap, lv_swap.size + Size("32 MiB"))

        # instantiation of format resize action for non-existent format
        # should fail
        lv_root = self.storage.devicetree.getDeviceByName("VolGroup-lv_root")
        self.assertNotEqual(lv_root, None)
        lv_root.format.exists = False
        with self.assertRaises(ValueError):
            ActionResizeFormat(lv_root, lv_root.size - Size("1000 MiB"))
        lv_root.format.exists = True

        # instantiation of device create action for existing device should
        # fail
        lv_swap = self.storage.devicetree.getDeviceByName("VolGroup-lv_swap")
        self.assertNotEqual(lv_swap, None)
        self.assertEqual(lv_swap.exists, True)
        with self.assertRaises(ValueError):
            ActionCreateDevice(lv_swap)

        # instantiation of format destroy action for device causes device's
        # format attribute to be a DeviceFormat instance
        lv_swap = self.storage.devicetree.getDeviceByName("VolGroup-lv_swap")
        self.assertNotEqual(lv_swap, None)
        orig_format = lv_swap.format
        self.assertEqual(lv_swap.format.type, "swap")
        destroy_swap = ActionDestroyFormat(lv_swap)
        self.assertEqual(lv_swap.format.type, "swap")
        destroy_swap.apply()
        self.assertEqual(lv_swap.format.type, None)

        # instantiation of format create action for device causes new format
        # to be accessible via device's format attribute
        new_format = getFormat("vfat", device=lv_swap.path)
        create_swap = ActionCreateFormat(lv_swap, new_format)
        self.assertEqual(lv_swap.format.type, None)
        create_swap.apply()
        self.assertEqual(lv_swap.format, new_format)
        lv_swap.format = orig_format
    def test_unsupported_disklabel(self):
        """ Test behavior of partitions on unsupported disklabels. """
        # Verify basic properties of the disk and disklabel.
        self.assertTrue(self.disk1.partitioned)
        self.assertFalse(self.disk1.format.supported)
        self.assertTrue(self.disk3.partitioned)
        self.assertTrue(self.disk3.format.supported)  # normal disklabel is supported

        # Verify some basic properties of the partitions.
        self.assertFalse(self.partition1.disk.format.supported)
        self.assertFalse(self.partition2.disk.format.supported)
        self.assertEqual(self.partition1.disk, self.disk1)
        self.assertEqual(self.partition2.disk, self.disk1)
        self.assertIsNone(self.partition1.parted_partition)
        self.assertIsNone(self.partition2.parted_partition)
        self.assertFalse(self.partition1.is_magic)
        self.assertFalse(self.partition2.is_magic)

        # Verify that probe returns without changing anything.
        partition1_type = sentinel.partition1_type
        self.partition1._part_type = partition1_type
        self.partition1.probe()
        self.assertEqual(self.partition1.part_type, partition1_type)
        self.partition1._part_type = None

        # partition1 is not resizable even though it contains a resizable filesystem
        self.assertEqual(self.partition1.resizable, False)

        # lv is resizable as usual
        with patch.object(self.lv.format, "_resizable", new=True):
            self.assertEqual(self.lv.resizable, True)

        # the lv's destroy method should call blockdev.lvm.lvremove as usual
        with patch.object(self.lv, "_pre_destroy"):
            with patch("blivet.devices.lvm.blockdev.lvm.lvremove") as lvremove:
                self.lv.destroy()
                self.assertTrue(lvremove.called)

        # the vg's destroy method should call blockdev.lvm.vgremove as usual
        with patch.object(self.vg, "_pre_destroy"):
            with patch.multiple("blivet.devices.lvm.blockdev.lvm",
                                vgreduce=DEFAULT,
                                vgdeactivate=DEFAULT,
                                vgremove=DEFAULT) as mocks:
                self.vg.destroy()
        self.assertTrue(mocks["vgreduce"].called)
        self.assertTrue(mocks["vgdeactivate"].called)
        self.assertTrue(mocks["vgremove"].called)

        # the partition's destroy method shouldn't try to call any disklabel methods
        with patch.object(self.partition2, "_pre_destroy"):
            with patch.object(self.partition2.disk, "original_format") as disklabel:
                self.partition2.destroy()
        self.assertEqual(len(disklabel.mock_calls), 0)
        self.assertTrue(self.partition2.exists)

        # Destroying the disklabel should set all partitions to non-existing.
        # XXX This part is handled by ActionList.
        actions = ActionList()
        unsupported_disklabel = self.disk1.format
        actions.add(ActionDestroyFormat(self.disk1))
        self.assertTrue(self.disk1.format.exists)
        self.assertTrue(self.partition1.exists)
        self.assertTrue(self.partition2.exists)
        with patch.object(unsupported_disklabel, "_pre_destroy"):
            with patch.object(unsupported_disklabel, "_destroy") as destroy:
                with patch.object(actions, "_pre_process"):
                    with patch.object(actions, "_post_process"):
                        actions.process(devices=[self.partition1, self.partition2, self.disk1])

        self.assertTrue(destroy.called)
        self.assertFalse(unsupported_disklabel.exists)
        self.assertFalse(self.partition1.exists)
        self.assertFalse(self.partition2.exists)
Example #4
0
    def testActionDependencies(self):
        """ Verify correct functioning of action dependencies. """
        # ActionResizeDevice
        # an action that shrinks a device should require the action that
        # shrinks the device's format
        lv_root = self.storage.devicetree.getDeviceByName("VolGroup-lv_root")
        self.assertNotEqual(lv_root, None)
        lv_root.format._minInstanceSize = Size("10 MiB")
        lv_root.format._targetSize = lv_root.format._minInstanceSize
        # lv_root.format._resizable = True
        shrink_format = ActionResizeFormat(lv_root, lv_root.size - Size("5 GiB"))
        shrink_format.apply()
        shrink_device = ActionResizeDevice(lv_root, lv_root.size - Size("5 GiB"))
        shrink_device.apply()
        self.assertEqual(shrink_device.requires(shrink_format), True)
        self.assertEqual(shrink_format.requires(shrink_device), False)
        shrink_format.cancel()
        shrink_device.cancel()

        # ActionResizeDevice
        # an action that grows a format should require the action that
        # grows the device
        orig_size = lv_root.currentSize
        grow_device = ActionResizeDevice(lv_root, orig_size + Size("100 MiB"))
        grow_device.apply()
        grow_format = ActionResizeFormat(lv_root, orig_size + Size("100 MiB"))
        grow_format.apply()
        self.assertEqual(grow_format.requires(grow_device), True)
        self.assertEqual(grow_device.requires(grow_format), False)

        # create something like uncommitted autopart
        self.destroyAllDevices()
        sda = self.storage.devicetree.getDeviceByName("sda")
        sdb = self.storage.devicetree.getDeviceByName("sdb")
        sda1 = self.newDevice(device_class=PartitionDevice, name="sda1", size=Size("500 MiB"), parents=[sda])
        sda1_format = self.newFormat("ext4", mountpoint="/boot", device=sda1.path)
        self.scheduleCreateDevice(sda1)
        self.scheduleCreateFormat(device=sda1, fmt=sda1_format)

        sda2 = self.newDevice(device_class=PartitionDevice, name="sda2", size=Size("99.5 GiB"), parents=[sda])
        sda2_format = self.newFormat("lvmpv", device=sda2.path)
        self.scheduleCreateDevice(sda2)
        self.scheduleCreateFormat(device=sda2, fmt=sda2_format)

        sdb1 = self.newDevice(device_class=PartitionDevice, name="sdb1", size=Size("100 GiB"), parents=[sdb])
        sdb1_format = self.newFormat("lvmpv", device=sdb1.path)
        self.scheduleCreateDevice(sdb1)
        self.scheduleCreateFormat(device=sdb1, fmt=sdb1_format)

        vg = self.newDevice(device_class=LVMVolumeGroupDevice, name="VolGroup", parents=[sda2, sdb1])
        self.scheduleCreateDevice(vg)

        lv_root = self.newDevice(
            device_class=LVMLogicalVolumeDevice, name="lv_root", parents=[vg], size=Size("160 GiB")
        )
        self.scheduleCreateDevice(lv_root)
        fmt = self.newFormat("ext4", device=lv_root.path, mountpoint="/")
        self.scheduleCreateFormat(device=lv_root, fmt=fmt)

        lv_swap = self.newDevice(device_class=LVMLogicalVolumeDevice, name="lv_swap", parents=[vg], size=Size("4 GiB"))
        self.scheduleCreateDevice(lv_swap)
        fmt = self.newFormat("swap", device=lv_swap.path)
        self.scheduleCreateFormat(device=lv_swap, fmt=fmt)

        # ActionCreateDevice
        # creation of an LV should require the actions that create the VG,
        # its PVs, and the devices that contain the PVs
        lv_root = self.storage.devicetree.getDeviceByName("VolGroup-lv_root")
        self.assertNotEqual(lv_root, None)
        actions = self.storage.devicetree.actions.find(action_type="create", object_type="device", device=lv_root)
        self.assertEqual(len(actions), 1, "wrong number of device create actions for lv_root: " "%d" % len(actions))
        create_lv_action = actions[0]

        vgs = [d for d in self.storage.vgs if d.name == "VolGroup"]
        self.assertNotEqual(vgs, [])
        vg = vgs[0]
        actions = self.storage.devicetree.actions.find(action_type="create", object_type="device", device=vg)
        self.assertEqual(len(actions), 1, "wrong number of device create actions for VolGroup")
        create_vg_action = actions[0]

        self.assertEqual(create_lv_action.requires(create_vg_action), True)

        create_pv_actions = []
        pvs = [d for d in self.storage.pvs if d in vg.pvs]
        self.assertNotEqual(pvs, [])
        for pv in pvs:
            # include device and format create actions for each pv
            actions = self.storage.devicetree.actions.find(action_type="create", device=pv)
            self.assertEqual(len(actions), 2, "wrong number of device create actions for " "pv %s" % pv.name)
            create_pv_actions.append(actions[0])

        for pv_action in create_pv_actions:
            self.assertEqual(create_lv_action.requires(pv_action), True)
            # also check that the vg create action requires the pv actions
            self.assertEqual(create_vg_action.requires(pv_action), True)

        # ActionCreateDevice
        # the higher numbered partition of two that are scheduled to be
        # created on a single disk should require the action that creates the
        # lower numbered of the two, eg: create sda2 before creating sda3
        sdc = self.storage.devicetree.getDeviceByName("sdc")
        self.assertNotEqual(sdc, None)

        sdc1 = self.newDevice(device_class=PartitionDevice, name="sdc1", parents=[sdc], size=Size("50 GiB"))
        create_sdc1 = self.scheduleCreateDevice(sdc1)
        self.assertEqual(isinstance(create_sdc1, ActionCreateDevice), True)

        sdc2 = self.newDevice(device_class=PartitionDevice, name="sdc2", parents=[sdc], size=Size("50 GiB"))
        create_sdc2 = self.scheduleCreateDevice(sdc2)
        self.assertEqual(isinstance(create_sdc2, ActionCreateDevice), True)

        self.assertEqual(create_sdc2.requires(create_sdc1), True)
        self.assertEqual(create_sdc1.requires(create_sdc2), False)

        # ActionCreateDevice
        # actions that create partitions on two separate disks should not
        # require each other, regardless of the partitions' numbers
        sda1 = self.storage.devicetree.getDeviceByName("sda1")
        self.assertNotEqual(sda1, None)
        actions = self.storage.devicetree.actions.find(action_type="create", object_type="device", device=sda1)
        self.assertEqual(len(actions), 1, "wrong number of create actions found for sda1")
        create_sda1 = actions[0]
        self.assertEqual(create_sdc2.requires(create_sda1), False)
        self.assertEqual(create_sda1.requires(create_sdc1), False)

        # ActionDestroyDevice
        # an action that destroys a device containing an mdmember format
        # should require the action that destroys the md array it is a
        # member of if an array is defined
        self.destroyAllDevices(disks=["sdc", "sdd"])
        sdc = self.storage.devicetree.getDeviceByName("sdc")
        self.assertNotEqual(sdc, None)
        sdd = self.storage.devicetree.getDeviceByName("sdd")
        self.assertNotEqual(sdd, None)

        sdc1 = self.newDevice(device_class=PartitionDevice, name="sdc1", parents=[sdc], size=Size("40 GiB"))
        self.scheduleCreateDevice(sdc1)
        fmt = self.newFormat("mdmember", device=sdc1.path)
        self.scheduleCreateFormat(device=sdc1, fmt=fmt)

        sdd1 = self.newDevice(device_class=PartitionDevice, name="sdd1", parents=[sdd], size=Size("40 GiB"))
        self.scheduleCreateDevice(sdd1)
        fmt = self.newFormat("mdmember", device=sdd1.path)
        self.scheduleCreateFormat(device=sdd1, fmt=fmt)

        md0 = self.newDevice(
            device_class=MDRaidArrayDevice,
            name="md0",
            level="raid0",
            minor=0,
            memberDevices=2,
            totalDevices=2,
            parents=[sdc1, sdd1],
        )
        self.scheduleCreateDevice(md0)
        fmt = self.newFormat("ext4", device=md0.path, mountpoint="/home")
        self.scheduleCreateFormat(device=md0, fmt=fmt)

        destroy_md0_format = self.scheduleDestroyFormat(md0)
        destroy_md0 = self.scheduleDestroyDevice(md0)
        destroy_members = [self.scheduleDestroyDevice(sdc1)]
        destroy_members.append(self.scheduleDestroyDevice(sdd1))

        for member in destroy_members:
            # device and format destroy actions for md members should require
            # both device and format destroy actions for the md array
            for array in [destroy_md0_format, destroy_md0]:
                self.assertEqual(member.requires(array), True)

        # ActionDestroyDevice
        # when there are two actions that will each destroy a partition on the
        # same disk, the action that will destroy the lower-numbered
        # partition should require the action that will destroy the higher-
        # numbered partition, eg: destroy sda2 before destroying sda1
        self.destroyAllDevices(disks=["sdc", "sdd"])
        sdc1 = self.newDevice(device_class=PartitionDevice, name="sdc1", parents=[sdc], size=Size("50 GiB"))
        self.scheduleCreateDevice(sdc1)

        sdc2 = self.newDevice(device_class=PartitionDevice, name="sdc2", parents=[sdc], size=Size("40 GiB"))
        self.scheduleCreateDevice(sdc2)

        destroy_sdc1 = self.scheduleDestroyDevice(sdc1)
        destroy_sdc2 = self.scheduleDestroyDevice(sdc2)
        self.assertEqual(destroy_sdc1.requires(destroy_sdc2), True)
        self.assertEqual(destroy_sdc2.requires(destroy_sdc1), False)

        self.destroyAllDevices(disks=["sdc", "sdd"])
        sdc = self.storage.devicetree.getDeviceByName("sdc")
        self.assertNotEqual(sdc, None)
        sdd = self.storage.devicetree.getDeviceByName("sdd")
        self.assertNotEqual(sdd, None)

        sdc1 = self.newDevice(device_class=PartitionDevice, name="sdc1", parents=[sdc], size=Size("50 GiB"))
        create_pv = self.scheduleCreateDevice(sdc1)
        fmt = self.newFormat("lvmpv", device=sdc1.path)
        create_pv_format = self.scheduleCreateFormat(device=sdc1, fmt=fmt)

        testvg = self.newDevice(device_class=LVMVolumeGroupDevice, name="testvg", parents=[sdc1])
        create_vg = self.scheduleCreateDevice(testvg)
        testlv = self.newDevice(
            device_class=LVMLogicalVolumeDevice, name="testlv", parents=[testvg], size=Size("30 GiB")
        )
        create_lv = self.scheduleCreateDevice(testlv)
        fmt = self.newFormat("ext4", device=testlv.path)
        create_lv_format = self.scheduleCreateFormat(device=testlv, fmt=fmt)

        # ActionCreateFormat
        # creation of a format on a non-existent device should require the
        # action that creates the device
        self.assertEqual(create_lv_format.requires(create_lv), True)

        # ActionCreateFormat
        # an action that creates a format on a device should require an action
        # that creates a device that the format's device depends on
        self.assertEqual(create_lv_format.requires(create_pv), True)
        self.assertEqual(create_lv_format.requires(create_vg), True)

        # ActionCreateFormat
        # an action that creates a format on a device should require an action
        # that creates a format on a device that the format's device depends on
        self.assertEqual(create_lv_format.requires(create_pv_format), True)

        # XXX from here on, the devices are existing but not in the tree, so
        #     we instantiate and use actions directly
        self.destroyAllDevices(disks=["sdc", "sdd"])
        sdc1 = self.newDevice(
            device_class=PartitionDevice, exists=True, name="sdc1", parents=[sdc], size=Size("50 GiB")
        )
        sdc1.format = self.newFormat("lvmpv", device=sdc1.path, exists=True, device_instance=sdc1)
        testvg = self.newDevice(
            device_class=LVMVolumeGroupDevice, exists=True, name="testvg", parents=[sdc1], size=Size("50 GiB")
        )
        testlv = self.newDevice(
            device_class=LVMLogicalVolumeDevice, exists=True, size=Size("30 GiB"), name="testlv", parents=[testvg]
        )
        testlv.format = self.newFormat("ext4", device=testlv.path, exists=True, device_instance=testlv)

        # ActionResizeDevice
        # an action that resizes a device should require an action that grows
        # a device that the first action's device depends on, eg: grow
        # device containing PV before resize of VG or LVs
        sdc1.format._resizable = True  # override lvmpv.resizable
        sdc1.exists = True
        sdc1.format.exists = True
        grow_pv = ActionResizeDevice(sdc1, sdc1.size + Size("10 GiB"))
        grow_pv.apply()
        grow_lv = ActionResizeDevice(testlv, testlv.size + Size("5 GiB"))
        grow_lv.apply()
        grow_lv_format = ActionResizeFormat(testlv, testlv.size + Size("5 GiB"))
        grow_lv_format.apply()
        sdc1.exists = False
        sdc1.format.exists = False

        self.assertEqual(grow_lv.requires(grow_pv), True)
        self.assertEqual(grow_pv.requires(grow_lv), False)

        # ActionResizeFormat
        # an action that grows a format should require the action that grows
        # the format's device
        self.assertEqual(grow_lv_format.requires(grow_lv), True)
        self.assertEqual(grow_lv.requires(grow_lv_format), False)

        # ActionResizeFormat
        # an action that resizes a device's format should depend on an action
        # that grows a device the first device depends on
        self.assertEqual(grow_lv_format.requires(grow_pv), True)
        self.assertEqual(grow_pv.requires(grow_lv_format), False)

        # ActionResizeFormat
        # an action that resizes a device's format should depend on an action
        # that grows a format on a device the first device depends on
        # XXX resize of PV format is not allowed, so there's no real-life
        #     example of this to test

        grow_lv_format.cancel()
        grow_lv.cancel()
        grow_pv.cancel()

        # ActionResizeDevice
        # an action that resizes a device should require an action that grows
        # a format on a device that the first action's device depends on, eg:
        # grow PV format before resize of VG or LVs
        # XXX resize of PV format is not allowed, so there's no real-life
        #     example of this to test

        # ActionResizeDevice
        # an action that resizes a device should require an action that
        # shrinks a device that depends on the first action's device, eg:
        # shrink LV before resizing VG or PV devices
        testlv.format._minInstanceSize = Size("10 MiB")
        testlv.format._targetSize = testlv.format._minInstanceSize
        shrink_lv = ActionResizeDevice(testlv, testlv.size - Size("10 GiB"))
        shrink_lv.apply()
        sdc1.exists = True
        sdc1.format.exists = True
        shrink_pv = ActionResizeDevice(sdc1, sdc1.size - Size("5 GiB"))
        shrink_pv.apply()
        sdc1.exists = False
        sdc1.format.exists = False

        self.assertEqual(shrink_pv.requires(shrink_lv), True)
        self.assertEqual(shrink_lv.requires(shrink_pv), False)

        # ActionResizeDevice
        # an action that resizes a device should require an action that
        # shrinks a format on a device that depends on the first action's
        # device, eg: shrink LV format before resizing VG or PV devices
        shrink_lv_format = ActionResizeFormat(testlv, testlv.size)
        shrink_lv_format.apply()
        self.assertEqual(shrink_pv.requires(shrink_lv_format), True)
        self.assertEqual(shrink_lv_format.requires(shrink_pv), False)

        # ActionResizeFormat
        # an action that resizes a device's format should depend on an action
        # that shrinks a device that depends on the first device
        # XXX can't think of a real-world example of this since PVs and MD
        #     member devices are not resizable in anaconda

        # ActionResizeFormat
        # an action that resizes a device's format should depend on an action
        # that shrinks a format on a device that depends on the first device
        # XXX can't think of a real-world example of this since PVs and MD
        #     member devices are not resizable in anaconda

        shrink_lv_format.cancel()
        shrink_lv.cancel()
        shrink_pv.cancel()

        # ActionCreateFormat
        # an action that creates a format on a device should require an action
        # that resizes a device that the format's device depends on
        # XXX Really? Is this always so?

        # ActionCreateFormat
        # an action that creates a format on a device should require an action
        # that resizes a format on a device that the format's device depends on
        # XXX Same as above.

        # ActionCreateFormat
        # an action that creates a format on a device should require an action
        # that resizes the device that will contain the format
        grow_lv = ActionResizeDevice(testlv, testlv.size + Size("1 GiB"))
        fmt = self.newFormat("disklabel", device=testlv.path)
        format_lv = ActionCreateFormat(testlv, fmt)
        self.assertEqual(format_lv.requires(grow_lv), True)
        self.assertEqual(grow_lv.requires(format_lv), False)

        # ActionDestroyFormat
        # an action that destroys a format should require an action that
        # destroys a device that depends on the format's device
        destroy_pv_format = ActionDestroyFormat(sdc1)
        destroy_lv_format = ActionDestroyFormat(testlv)
        destroy_lv = ActionDestroyDevice(testlv)
        self.assertEqual(destroy_pv_format.requires(destroy_lv), True)
        self.assertEqual(destroy_lv.requires(destroy_pv_format), False)

        # ActionDestroyFormat
        # an action that destroys a format should require an action that
        # destroys a format on a device that depends on the first format's
        # device
        self.assertEqual(destroy_pv_format.requires(destroy_lv_format), True)
        self.assertEqual(destroy_lv_format.requires(destroy_pv_format), False)

        sdc2 = self.newDevice(device_class=PartitionDevice, name="sdc2", size=Size("5 GiB"), parents=[sdc])
        create_sdc2 = self.scheduleCreateDevice(sdc2)

        # create actions should always require destroy actions -- even for
        # unrelated devices -- since, after pruning, it should always be the
        # case that destroy actions are processed before create actions (no
        # create/destroy loops are allowed)
        self.assertEqual(create_sdc2.requires(destroy_lv), True)

        # similarly, create actions should also require resize actions
        self.assertEqual(create_sdc2.requires(grow_lv), True)
Example #5
0
    def testActionObsoletes(self):
        """ Verify correct operation of DeviceAction.obsoletes. """
        self.destroyAllDevices(disks=["sdc"])
        sdc = self.storage.devicetree.getDeviceByName("sdc")
        self.assertNotEqual(sdc, None)

        sdc1 = self.newDevice(device_class=PartitionDevice, name="sdc1", parents=[sdc], size=Size("40 GiB"))

        # ActionCreateDevice
        #
        # - obsoletes other ActionCreateDevice instances w/ lower id and same
        #   device
        create_device_1 = ActionCreateDevice(sdc1)
        create_device_1.apply()
        create_device_2 = ActionCreateDevice(sdc1)
        create_device_2.apply()
        self.assertEqual(create_device_2.obsoletes(create_device_1), True)
        self.assertEqual(create_device_1.obsoletes(create_device_2), False)

        # ActionCreateFormat
        #
        # - obsoletes other ActionCreateFormat instances w/ lower id and same
        #   device
        format_1 = self.newFormat("ext3", mountpoint="/home", device=sdc1.path)
        format_2 = self.newFormat("ext3", mountpoint="/opt", device=sdc1.path)
        create_format_1 = ActionCreateFormat(sdc1, format_1)
        create_format_1.apply()
        create_format_2 = ActionCreateFormat(sdc1, format_2)
        create_format_2.apply()
        self.assertEqual(create_format_2.obsoletes(create_format_1), True)
        self.assertEqual(create_format_1.obsoletes(create_format_2), False)

        # ActionResizeFormat
        #
        # - obsoletes other ActionResizeFormat instances w/ lower id and same
        #   device
        sdc1.exists = True
        sdc1.format.exists = True
        sdc1.format._resizable = True
        resize_format_1 = ActionResizeFormat(sdc1, sdc1.size - Size("1000 MiB"))
        resize_format_1.apply()
        resize_format_2 = ActionResizeFormat(sdc1, sdc1.size - Size("5000 MiB"))
        resize_format_2.apply()
        self.assertEqual(resize_format_2.obsoletes(resize_format_1), True)
        self.assertEqual(resize_format_1.obsoletes(resize_format_2), False)
        sdc1.exists = False
        sdc1.format.exists = False

        # ActionCreateFormat
        #
        # - obsoletes resize format actions w/ lower id on same device
        new_format = self.newFormat("ext4", mountpoint="/foo", device=sdc1.path)
        create_format_3 = ActionCreateFormat(sdc1, new_format)
        create_format_3.apply()
        self.assertEqual(create_format_3.obsoletes(resize_format_1), True)
        self.assertEqual(create_format_3.obsoletes(resize_format_2), True)

        # ActionResizeDevice
        #
        # - obsoletes other ActionResizeDevice instances w/ lower id and same
        #   device
        sdc1.exists = True
        sdc1.format.exists = True
        sdc1.format._resizable = True
        resize_device_1 = ActionResizeDevice(sdc1, sdc1.size + Size("10 GiB"))
        resize_device_1.apply()
        resize_device_2 = ActionResizeDevice(sdc1, sdc1.size - Size("10 GiB"))
        resize_device_2.apply()
        self.assertEqual(resize_device_2.obsoletes(resize_device_1), True)
        self.assertEqual(resize_device_1.obsoletes(resize_device_2), False)
        sdc1.exists = False
        sdc1.format.exists = False

        # ActionDestroyFormat
        #
        # - obsoletes all format actions w/ higher id on same device (including
        #   self if format does not exist)
        destroy_format_1 = ActionDestroyFormat(sdc1)
        destroy_format_1.apply()
        destroy_format_2 = ActionDestroyFormat(sdc1)
        destroy_format_2.apply()
        self.assertEqual(destroy_format_1.obsoletes(create_format_1), True)
        self.assertEqual(destroy_format_1.obsoletes(resize_format_1), True)
        self.assertEqual(destroy_format_1.obsoletes(destroy_format_1), True)
        self.assertEqual(destroy_format_2.obsoletes(destroy_format_1), False)
        self.assertEqual(destroy_format_1.obsoletes(destroy_format_2), True)

        # ActionDestroyDevice
        #
        # - obsoletes all actions w/ lower id that act on the same non-existent
        #   device (including self)
        # sdc1 does not exist
        destroy_sdc1 = ActionDestroyDevice(sdc1)
        destroy_sdc1.apply()
        self.assertEqual(destroy_sdc1.obsoletes(create_format_2), True)
        self.assertEqual(destroy_sdc1.obsoletes(resize_format_2), True)
        self.assertEqual(destroy_sdc1.obsoletes(create_device_1), True)
        self.assertEqual(destroy_sdc1.obsoletes(resize_device_1), True)
        self.assertEqual(destroy_sdc1.obsoletes(destroy_sdc1), True)

        # ActionDestroyDevice
        #
        # - obsoletes all but ActionDestroyFormat actions w/ lower id on the
        #   same existing device
        # sda1 exists
        sda1 = self.storage.devicetree.getDeviceByName("sda1")
        self.assertNotEqual(sda1, None)
        # sda1.format._resizable = True
        resize_sda1_format = ActionResizeFormat(sda1, sda1.size - Size("50 MiB"))
        resize_sda1_format.apply()
        resize_sda1 = ActionResizeDevice(sda1, sda1.size - Size("50 MiB"))
        resize_sda1.apply()
        destroy_sda1_format = ActionDestroyFormat(sda1)
        destroy_sda1_format.apply()
        destroy_sda1 = ActionDestroyDevice(sda1)
        destroy_sda1.apply()
        self.assertEqual(destroy_sda1.obsoletes(resize_sda1_format), True)
        self.assertEqual(destroy_sda1.obsoletes(resize_sda1), True)
        self.assertEqual(destroy_sda1.obsoletes(destroy_sda1), False)
        self.assertEqual(destroy_sda1.obsoletes(destroy_sda1_format), False)