def test_get_partition_by_id_or_name_by_name_invalid_table(self): partition_table = factory.make_PartitionTable() other_table = factory.make_PartitionTable() partition = factory.make_Partition(partition_table=partition_table) self.assertRaises( Partition.DoesNotExist, Partition.objects.get_partition_by_id_or_name, partition.name, other_table, )
def test_raid_creation_with_names(self): node = factory.make_Node() device_size = 10 * 1000 ** 4 bds = [ factory.make_PhysicalBlockDevice(node=node, size=device_size) for _ in range(10) ] for bd in bds[5:]: factory.make_PartitionTable(block_device=bd) block_devices_ids = [ bd.id for bd in bds if bd.get_partitiontable() is None ] block_device_names = [ bd.name for bd in bds if bd.get_partitiontable() is None ] partitions = [ bd.get_partitiontable().add_partition() for bd in bds[5:] ] partition_ids = [ part.id for part in partitions ] partition_names = [ part.name for part in partitions ] form = CreateRaidForm(node=node, data={ 'name': 'md1', 'level': FILESYSTEM_GROUP_TYPE.RAID_6, 'block_devices': block_device_names, 'partitions': partition_names, }) self.assertTrue(form.is_valid(), form.errors) raid = form.save() self.assertEqual('md1', raid.name) self.assertEqual(8 * partitions[0].size, raid.get_size()) self.assertEqual(FILESYSTEM_GROUP_TYPE.RAID_6, raid.group_type) self.assertItemsEqual( block_devices_ids, [ fs.block_device.id for fs in raid.filesystems.exclude(block_device=None) ]) self.assertItemsEqual( partition_ids, [ fs.partition.id for fs in raid.filesystems.exclude(partition=None) ])
def test_update_updates_volume_group(self): self.become_admin() node = factory.make_Node(status=NODE_STATUS.READY) volume_group = factory.make_VolumeGroup(node=node) delete_block_device = factory.make_PhysicalBlockDevice(node=node) factory.make_Filesystem( fstype=FILESYSTEM_TYPE.LVM_PV, block_device=delete_block_device, filesystem_group=volume_group, ) delete_bd_for_partition = factory.make_PhysicalBlockDevice(node=node) delete_table = factory.make_PartitionTable( block_device=delete_bd_for_partition) delete_partition = factory.make_Partition(partition_table=delete_table) factory.make_Filesystem( fstype=FILESYSTEM_TYPE.LVM_PV, partition=delete_partition, filesystem_group=volume_group, ) new_name = factory.make_name("vg") new_uuid = "%s" % uuid.uuid4() new_block_device = factory.make_PhysicalBlockDevice(node=node) new_bd_for_partition = factory.make_PhysicalBlockDevice(node=node) new_table = factory.make_PartitionTable( block_device=new_bd_for_partition) new_partition = factory.make_Partition(partition_table=new_table) uri = get_volume_group_uri(volume_group) response = self.client.put( uri, { "name": new_name, "uuid": new_uuid, "add_block_devices": [new_block_device.id], "remove_block_devices": [delete_block_device.id], "add_partitions": [new_partition.id], "remove_partitions": [delete_partition.id], }, ) self.assertEqual(http.client.OK, response.status_code, response.content) volume_group = reload_object(volume_group) self.assertEqual(new_name, volume_group.name) self.assertEqual(new_uuid, volume_group.uuid) self.assertEqual( volume_group.id, new_block_device.get_effective_filesystem().filesystem_group.id, ) self.assertEqual( volume_group.id, new_partition.get_effective_filesystem().filesystem_group.id, ) self.assertIsNone(delete_block_device.get_effective_filesystem()) self.assertIsNone(delete_partition.get_effective_filesystem())
def test_get_free_block_devices_for_node(self): node = factory.make_Node(with_boot_disk=False) free_devices = [factory.make_BlockDevice(node=node) for _ in range(3)] # Block devices with partition tables. for _ in range(3): factory.make_PartitionTable(block_device=factory.make_BlockDevice( node=node)) # Block devices with filesystems. for _ in range(3): factory.make_Filesystem(block_device=factory.make_BlockDevice( node=node)) self.assertItemsEqual( free_devices, BlockDevice.objects.get_free_block_devices_for_node(node))
def test_udpate_partitiontable_type(self): block_device = factory.make_PhysicalBlockDevice() factory.make_PartitionTable(table_type=PARTITION_TABLE_TYPE.GPT, block_device=block_device) form = UpdatePhysicalBlockDeviceForm( instance=block_device, data={"partition_table_type": PARTITION_TABLE_TYPE.MBR}, ) self.assertTrue(form.is_valid(), form.errors) block_device = form.save() self.assertEqual( block_device.get_partitiontable().table_type, PARTITION_TABLE_TYPE.MBR, )
def test_create_raid_10(self): """Checks it's possible to create a RAID 10 using 4 raw devices, 4 partitions, one spare device and one spare partition.""" self.become_admin() node = factory.make_Node(status=NODE_STATUS.READY) # Add 10 10TB physical block devices to the node. bds = [ factory.make_PhysicalBlockDevice(node=node, size=10 * 1000**4) for i in range(10) ] for bd in bds[5:]: factory.make_PartitionTable(block_device=bd) for bd in bds[5:]: bd.get_partitiontable().add_partition(size=1000**4) large_partitions = [ bd.get_partitiontable().add_partition() for bd in bds[5:] ] uuid4 = str(uuid.uuid4()) uri = get_raid_devices_uri(node) block_devices = [ bd.id for bd in bds[1:] if bd.get_partitiontable() is None ] partitions = [lp.id for lp in large_partitions[1:]] spare_devices = [bds[0].id] spare_partitions = [large_partitions[0].id] response = self.client.post( uri, { 'name': 'md0', 'uuid': uuid4, 'level': FILESYSTEM_GROUP_TYPE.RAID_10, 'block_devices': block_devices, 'partitions': partitions, 'spare_devices': spare_devices, 'spare_partitions': spare_partitions, }) self.assertEqual(http.client.OK, response.status_code, response.content) parsed_device = json.loads( response.content.decode(settings.DEFAULT_CHARSET)) (parsed_block_devices, parsed_partitions, parsed_block_device_spares, parsed_partition_spares) = (get_devices_from_raid(parsed_device)) # Size is equivalent to 4 of the smallest device (the partitions). self.assertEqual(4 * large_partitions[0].size, parsed_device['size']) self.assertItemsEqual(block_devices, parsed_block_devices) self.assertItemsEqual(partitions, parsed_partitions) self.assertItemsEqual(spare_devices, parsed_block_device_spares) self.assertItemsEqual(spare_partitions, parsed_partition_spares)
def test_save_doesnt_overwrite_uuid(self): uuid = uuid4() table = factory.make_PartitionTable( table_type=PARTITION_TABLE_TYPE.GPT) partition = factory.make_Partition(partition_table=table, uuid=uuid) partition.save() self.assertEqual("%s" % uuid, partition.uuid)
def test_mount_sets_mount_path_on_filesystem_as_user(self): node = factory.make_Node( status=NODE_STATUS.ALLOCATED, owner=self.user) block_device = factory.make_PhysicalBlockDevice(node=node) partition_table = factory.make_PartitionTable( block_device=block_device) partition = partition_table.add_partition() filesystem = factory.make_Filesystem( partition=partition, acquired=True) uri = get_partition_uri(partition) mount_point = '/mnt' mount_options = factory.make_name("mount-options") response = self.client.post(uri, { 'op': 'mount', 'mount_point': mount_point, 'mount_options': mount_options, }) self.assertEqual( http.client.OK, response.status_code, response.content) parsed_device = json.loads( response.content.decode(settings.DEFAULT_CHARSET)) self.assertThat( parsed_device["filesystem"], ContainsDict({ "mount_point": Equals(mount_point), "mount_options": Equals(mount_options), })) self.assertThat( reload_object(filesystem), MatchesStructure( mount_point=Equals(mount_point), mount_options=Equals(mount_options), is_mounted=Is(True), ))
def test_change_storages_to_partitions_bcache(self): """Tests update bcache method by changing backing device to a partition.""" mock_create_audit_event = self.patch( bcache_module, "create_audit_event" ) self.become_admin() node = factory.make_Node(status=NODE_STATUS.READY) bcache = factory.make_FilesystemGroup( node=node, group_type=FILESYSTEM_GROUP_TYPE.BCACHE, cache_mode=CACHE_MODE_TYPE.WRITEBACK, ) uri = get_bcache_device_uri(bcache) new_backing = factory.make_PartitionTable( block_device=factory.make_PhysicalBlockDevice(node=node) ).add_partition() response = self.client.put(uri, {"backing_partition": new_backing.id}) self.assertEqual( http.client.OK, response.status_code, response.content ) parsed_device = json_load_bytes(response.content) self.assertEqual(new_backing.id, parsed_device["backing_device"]["id"]) self.assertEqual("partition", parsed_device["backing_device"]["type"]) self.assertThat( mock_create_audit_event, MockCalledOnceWith( EVENT_TYPES.NODE, ENDPOINT.API, ANY, node.system_id, "Updated bcache.", ), )
def test_bcache_with_invalid_block_device_fails(self): """Tests allowable device list validation.""" node = factory.make_Node() cache_set = factory.make_CacheSet(node=node) filesystems = [ factory.make_Filesystem( partition=factory.make_PartitionTable( block_device=factory.make_PhysicalBlockDevice( node=node)).add_partition(), fstype=FILESYSTEM_TYPE.BCACHE_BACKING, ) ] backing_device = factory.make_PhysicalBlockDevice() bcache = factory.make_FilesystemGroup( group_type=FILESYSTEM_GROUP_TYPE.BCACHE, cache_set=cache_set, filesystems=filesystems, ) form = UpdateBcacheForm(bcache=bcache, data={"backing_device": backing_device.id}) self.assertFalse(form.is_valid(), form.errors) self.assertIn("Select a valid choice.", form.errors["backing_device"][0]) self.assertIn( "is not one of the available choices.", form.errors["backing_device"][0], )
def test_bcache_creation_with_names(self): node = factory.make_Node() backing_size = 10 * 1000**4 cache_set = factory.make_CacheSet(node=node) backing_device = factory.make_PhysicalBlockDevice(node=node, size=backing_size) backing_partition_table = factory.make_PartitionTable( block_device=backing_device) backing_partition = backing_partition_table.add_partition() uuid = str(uuid4()) form = CreateBcacheForm( node=node, data={ "name": "bcache0", "uuid": uuid, "cache_set": cache_set.name, "backing_partition": backing_partition.name, "cache_mode": CACHE_MODE_TYPE.WRITEBACK, }, ) self.assertTrue(form.is_valid(), form.errors) bcache = form.save() self.assertEqual("bcache0", bcache.name) self.assertEqual(uuid, bcache.uuid) self.assertEqual(cache_set, bcache.cache_set) self.assertEqual( backing_partition.get_effective_filesystem(), bcache.filesystems.get(fstype=FILESYSTEM_TYPE.BCACHE_BACKING), ) self.assertEqual(FILESYSTEM_GROUP_TYPE.BCACHE, bcache.group_type)
def test_get_overhead_size_for_ppc64el(self): node = factory.make_Node(architecture="ppc64el/generic") block_device = factory.make_PhysicalBlockDevice(node=node) partition_table = factory.make_PartitionTable( block_device=block_device) self.assertEquals(PARTITION_TABLE_EXTRA_SPACE + PREP_PARTITION_SIZE, partition_table.get_overhead_size())
def test_choices_are_being_populated_correctly(self): node = factory.make_Node(with_boot_disk=False) # Make 10 block devices. bds = [factory.make_PhysicalBlockDevice(node=node) for _ in range(10)] # Partition the last 5 devices with a single partition. partitions = [ factory.make_PartitionTable(block_device=bd).add_partition() for bd in bds[5:] ] partition_choices = [p.id for p in partitions ] + [p.name for p in partitions] # Get the chocies of the non-partitioned devices. block_device_choices = [ bd.id for bd in bds if bd.get_partitiontable() is None ] + [bd.name for bd in bds if bd.get_partitiontable() is None] cache_set = factory.make_CacheSet(block_device=bds[1]) form = UpdateCacheSetForm(cache_set=cache_set, data={}) # Should allow all devices and partitions, including the one currently # in use on the cache set. self.assertItemsEqual( block_device_choices, [k for (k, v) in form.fields["cache_device"].choices], ) self.assertItemsEqual( partition_choices, [k for (k, v) in form.fields["cache_partition"].choices], )
def test_creates_with_partitions_by_name(self): node = make_Node_with_VMFS6_layout() block_device = factory.make_PhysicalBlockDevice( node=node, size=(MIN_BLOCK_DEVICE_SIZE * 3) + PARTITION_TABLE_EXTRA_SPACE) partition_table = factory.make_PartitionTable( block_device=block_device) partitions = [ partition_table.add_partition(size=MIN_BLOCK_DEVICE_SIZE) for _ in range(2) ] partition_names = [ partition.name for partition in partitions ] data = { 'name': factory.make_name('name'), 'partitions': partition_names, } form = CreateVMFSForm(node, data=data) self.assertTrue(form.is_valid(), form._errors) volume_group = form.save() partitions_in_vg = [ filesystem.partition for filesystem in volume_group.filesystems.all() ] self.assertItemsEqual(partitions, partitions_in_vg)
def test_validate_enough_space_will_round_down_a_block(self): partition_table = factory.make_PartitionTable() partition = partition_table.add_partition() prev_size = partition.size partition.size += partition_table.get_block_size() partition.save() self.assertEqual(prev_size, partition.size)
def test_get_partition_number_returns_starting_at_2_for_amd64_gpt(self): node = factory.make_Node( architecture="amd64/generic", bios_boot_method="pxe", with_boot_disk=False, ) block_device = factory.make_PhysicalBlockDevice( node=node, size=( (2 * (1024 ** 4)) + PARTITION_TABLE_EXTRA_SPACE + BIOS_GRUB_PARTITION_SIZE ), ) node.boot_disk = block_device node.save() partition_table = factory.make_PartitionTable( block_device=block_device, table_type=PARTITION_TABLE_TYPE.GPT ) partitions = [ partition_table.add_partition(size=MIN_BLOCK_DEVICE_SIZE) for _ in range(4) ] idx = 2 for partition in partitions: self.expectThat(idx, Equals(partition.get_partition_number())) idx += 1
def test_validate_can_save_gpt_larger_than_2TiB(self): block_device = factory.make_BlockDevice(size=3 * (1024 ** 4)) # 3TiB partition_table = factory.make_PartitionTable( block_device=block_device, table_type=PARTITION_TABLE_TYPE.GPT ) # Test is that an error is not raised. partition_table.add_partition()
def test_save_sets_table_type_to_MBR_for_arm64(self): node = factory.make_Node( architecture="arm64/generic", with_boot_disk=False ) boot_disk = factory.make_PhysicalBlockDevice(node=node) partition_table = factory.make_PartitionTable(block_device=boot_disk) self.assertEqual(PARTITION_TABLE_TYPE.GPT, partition_table.table_type)
def test_creates_with_partitions(self): node = make_Node_with_VMFS6_layout() block_device = factory.make_PhysicalBlockDevice( node=node, size=(MIN_BLOCK_DEVICE_SIZE * 3) + PARTITION_TABLE_EXTRA_SPACE) partition_table = factory.make_PartitionTable( block_device=block_device) partitions = [ partition_table.add_partition(size=MIN_BLOCK_DEVICE_SIZE) for _ in range(2) ] partition_ids = [ partition.id for partition in partitions ] data = { 'name': factory.make_name('name'), 'partitions': partition_ids, } form = CreateVMFSForm(node, data=data) self.assertTrue(form.is_valid(), form._errors) vmfs = form.save() self.assertItemsEqual( partition_ids, [fs.get_parent().id for fs in vmfs.filesystems.all()])
def test_get_block_devices_in_filesystem_group(self): node = factory.make_Node() filesystem_group = factory.make_FilesystemGroup( group_type=FILESYSTEM_GROUP_TYPE.LVM_VG ) block_devices = [ filesystem.block_device for filesystem in filesystem_group.filesystems.all() if filesystem.block_device is not None ] block_device_with_partitions = factory.make_PhysicalBlockDevice( node=node ) partition_table = factory.make_PartitionTable( block_device=block_device_with_partitions ) partition = factory.make_Partition(partition_table=partition_table) factory.make_Filesystem( fstype=FILESYSTEM_TYPE.LVM_PV, partition=partition, filesystem_group=filesystem_group, ) block_devices_in_filesystem_group = ( BlockDevice.objects.get_block_devices_in_filesystem_group( filesystem_group ) ) self.assertItemsEqual(block_devices, block_devices_in_filesystem_group) self.assertNotIn( block_device_with_partitions, block_devices_in_filesystem_group )
def test_get_overhead_size(self): node = factory.make_Node(bios_boot_method="pxe") block_device = factory.make_PhysicalBlockDevice(node=node) partition_table = factory.make_PartitionTable( block_device=block_device) self.assertEquals(PARTITION_TABLE_EXTRA_SPACE, partition_table.get_overhead_size())
def test_read_returns_partitions(self): node = factory.make_Node(with_boot_disk=False) block_size = 1024 block_device = factory.make_PhysicalBlockDevice(node=node, size=1000000 * block_size) partition_table = factory.make_PartitionTable( block_device=block_device, table_type="MBR") # Use PartitionTable methods that auto-size and position partitions partition1 = partition_table.add_partition(size=50000 * block_size) partition2 = partition_table.add_partition() uri = get_blockdevices_uri(node) response = self.client.get(uri) self.assertEqual(http.client.OK, response.status_code, response.content) parsed_devices = json_load_bytes(response.content) self.assertEqual(parsed_devices[0]["partition_table_type"], "MBR") self.assertEqual(len(parsed_devices[0]["partitions"]), 2) # We should have one device self.assertEqual(len(parsed_devices), 1) [parsed_device] = parsed_devices # Verify the two partitions created above have the expected sizes self.assertIn(partition1.size, [p["size"] for p in parsed_device["partitions"]]) self.assertIn(partition2.size, [p["size"] for p in parsed_device["partitions"]])
def test_get_size_returns_block_device_size_minus_initial_offset(self): partition_table = factory.make_PartitionTable() self.assertEqual( round_size_to_nearest_block( partition_table.block_device.size - PARTITION_TABLE_EXTRA_SPACE, PARTITION_ALIGNMENT_SIZE, False), partition_table.get_size())
def test_read_returns_filesystems_on_partitions(self): node = factory.make_Node(with_boot_disk=False) block_size = 1024 block_device = factory.make_PhysicalBlockDevice(node=node, size=1000000 * block_size) partition_table = factory.make_PartitionTable( block_device=block_device, table_type="MBR") # Use PartitionTable methods that auto-size and position partitions partition1 = partition_table.add_partition(size=50000 * block_size) partition2 = partition_table.add_partition() filesystem1 = factory.make_Filesystem(partition=partition1) filesystem2 = factory.make_Filesystem(partition=partition2) uri = get_blockdevices_uri(node) response = self.client.get(uri) self.assertEqual(http.client.OK, response.status_code, response.content) parsed_devices = json_load_bytes(response.content) # We should have one device self.assertEqual(len(parsed_devices), 1) [parsed_device] = parsed_devices # Check whether the filesystems are what we expect them to be self.assertEqual( parsed_device["partitions"][0]["filesystem"]["uuid"], filesystem1.uuid, ) self.assertEqual( parsed_device["partitions"][1]["filesystem"]["uuid"], filesystem2.uuid, )
def test_choices_are_being_populated_correctly(self): node = factory.make_Node(with_boot_disk=False) # Make 10 block devices. bds = [ factory.make_PhysicalBlockDevice(node=node, size=10 * 1000**4) for _ in range(10) ] # Make 3 cache sets. cache_sets = [factory.make_CacheSet(node=node) for _ in range(3)] cache_set_choices = [cache_set.id for cache_set in cache_sets ] + [cache_set.name for cache_set in cache_sets] # Partition the last 5 devices with a single partition. partitions = [ factory.make_PartitionTable(block_device=bd).add_partition() for bd in bds[5:] ] partition_choices = [partition.id for partition in partitions ] + [partition.name for partition in partitions] # Get the IDs of the non-partitioned devices. block_devices = [ bd.id for bd in bds if bd.get_partitiontable() is None ] + [bd.name for bd in bds if bd.get_partitiontable() is None] form = CreateBcacheForm(node=node, data={}) self.assertItemsEqual( cache_set_choices, [k for (k, v) in form.fields["cache_set"].choices], ) self.assertItemsEqual( block_devices, [k for (k, v) in form.fields["backing_device"].choices], ) self.assertItemsEqual( partition_choices, [k for (k, v) in form.fields["backing_partition"].choices], )
def test_read_returns_partitions(self): node = factory.make_Node() block_size = 1024 block_device = factory.make_PhysicalBlockDevice(node=node, size=1000000 * block_size) partition_table = factory.make_PartitionTable( block_device=block_device, table_type="MBR") # Use PartitionTable methods that auto-size and position partitions partition1 = partition_table.add_partition(size=50000 * block_size) partition2 = partition_table.add_partition() uri = get_blockdevice_uri(block_device) response = self.client.get(uri) self.assertEqual(http.client.OK, response.status_code, response.content) parsed_device = json_load_bytes(response.content) self.assertThat( parsed_device["partitions"][0], ContainsDict({ "bootable": Equals(partition1.bootable), "id": Equals(partition1.id), "size": Equals(partition1.size), "uuid": Equals(partition1.uuid), }), ) self.assertThat( parsed_device["partitions"][1], ContainsDict({ "bootable": Equals(partition2.bootable), "id": Equals(partition2.id), "size": Equals(partition2.size), "uuid": Equals(partition2.uuid), }), )
def test_bcache_update_with_boot_disk(self): node = factory.make_Node(with_boot_disk=False) boot_disk = factory.make_PhysicalBlockDevice(node=node) cache_set = factory.make_CacheSet(node=node) filesystems = [ factory.make_Filesystem( partition=factory.make_PartitionTable( block_device=factory.make_PhysicalBlockDevice( node=node)).add_partition(), fstype=FILESYSTEM_TYPE.BCACHE_BACKING, ) ] bcache = factory.make_FilesystemGroup( group_type=FILESYSTEM_GROUP_TYPE.BCACHE, cache_set=cache_set, filesystems=filesystems, ) form = UpdateBcacheForm(bcache=bcache, data={"backing_device": boot_disk.id}) self.assertTrue(form.is_valid(), form.errors) bcache = form.save() boot_partition = boot_disk.get_partitiontable().partitions.first() self.assertEqual( boot_partition.get_effective_filesystem(), bcache.filesystems.get(fstype=FILESYSTEM_TYPE.BCACHE_BACKING), )
def test_read_partition(self): device = factory.make_PhysicalBlockDevice( size=(MIN_PARTITION_SIZE * 4) + PARTITION_TABLE_EXTRA_SPACE) partition_table = factory.make_PartitionTable(block_device=device) partition = factory.make_Partition( partition_table=partition_table, size=MIN_PARTITION_SIZE, bootable=True, ) uri = get_partition_uri(partition) response = self.client.get(uri) self.assertEqual(http.client.OK, response.status_code, response.content) parsed_partition = json.loads( response.content.decode(settings.DEFAULT_CHARSET)) self.assertThat( parsed_partition, ContainsDict({ "bootable": Is(True), "id": Equals(partition.id), "size": Equals(partition.size), "system_id": Equals(device.node.system_id), "device_id": Equals(device.id), }), )
def test_can_create_filesystem_on_partition_on_boot_disk(self): node = factory.make_Node(with_boot_disk=False) boot_disk = factory.make_PhysicalBlockDevice(node=node) partition_table = factory.make_PartitionTable(block_device=boot_disk) partition = factory.make_Partition(partition_table=partition_table) # Test is that an error is not raised. factory.make_Filesystem(partition=partition)
def test_unformat_missing_partition(self): self.become_admin() node = factory.make_Node(status=NODE_STATUS.READY) device = factory.make_PhysicalBlockDevice( node=node, size=(MIN_PARTITION_SIZE * 4) + PARTITION_TABLE_EXTRA_SPACE, ) factory.make_PartitionTable(block_device=device) partition_id = random.randint(1, 1000) # Most likely a bogus one partition_id = random.randint(1, 1000) # Most likely a bogus one uri = reverse("partition_handler", args=[node.system_id, device.id, partition_id]) response = self.client.post(uri, {"op": "unformat"}) # Returns nothing and a NOT_FOUND status. self.assertEqual(http.client.NOT_FOUND, response.status_code, response.content)