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