def test_delete_logical_volume_409_when_not_ready(self): self.become_admin() node = factory.make_Node(status=NODE_STATUS.ALLOCATED) volume_group = factory.make_VolumeGroup(node=node) logical_volume = factory.make_VirtualBlockDevice( filesystem_group=volume_group) uri = get_volume_group_uri(volume_group) response = self.client.post(uri, { "op": "delete_logical_volume", "id": logical_volume.id, }) self.assertEqual( http.client.CONFLICT, response.status_code, response.content)
def test_read_virtual_block_device(self): block_device = factory.make_VirtualBlockDevice() 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.assertEqual(block_device.id, parsed_device["id"]) self.assertEqual(block_device.get_name(), parsed_device["name"]) self.assertEqual("virtual", parsed_device["type"]) self.assertEqual(get_blockdevice_uri(block_device), parsed_device["resource_uri"])
def test_delete_logical_volume_403_when_not_admin(self): node = factory.make_Node(status=NODE_STATUS.READY) volume_group = factory.make_VolumeGroup(node=node) logical_volume = factory.make_VirtualBlockDevice( filesystem_group=volume_group ) uri = get_volume_group_uri(volume_group) response = self.client.post( uri, {"op": "delete_logical_volume", "id": logical_volume.id} ) self.assertEqual( http.client.FORBIDDEN, response.status_code, response.content )
def test_mount_returns_400_on_missing_mount_point(self): self.become_admin() node = factory.make_Node(status=NODE_STATUS.READY) block_device = factory.make_VirtualBlockDevice(node=node) factory.make_Filesystem(block_device=block_device) uri = get_blockdevice_uri(block_device) response = self.client.post(uri, {"op": "mount"}) self.assertEqual(http.client.BAD_REQUEST, response.status_code, response.content) parsed_error = json_load_bytes(response.content) self.assertEqual({"mount_point": ["This field is required."]}, parsed_error)
def test_format_returns_403_if_ready_and_not_admin(self): node = factory.make_Node(status=NODE_STATUS.READY) block_device = factory.make_VirtualBlockDevice(node=node) fstype = factory.pick_filesystem_type() fsuuid = "%s" % uuid.uuid4() uri = get_blockdevice_uri(block_device) response = self.client.post(uri, { "op": "format", "fstype": fstype, "uuid": fsuuid }) self.assertEqual(http.client.FORBIDDEN, response.status_code, response.content)
def test_unformat_returns_400_if_mounted(self): self.become_admin() node = factory.make_Node(status=NODE_STATUS.READY) block_device = factory.make_VirtualBlockDevice(node=node) factory.make_Filesystem(block_device=block_device, mount_point="/mnt") uri = get_blockdevice_uri(block_device) response = self.client.post(uri, {'op': 'unformat'}) self.assertEqual(http.client.BAD_REQUEST, response.status_code, response.content) self.assertEqual( b"Filesystem is mounted and cannot be unformatted. Unmount the " b"filesystem before unformatting the block device.", response.content)
def test_update_returns_409_for_non_ready_node(self): """Check update block device with a virtual one fails for a normal user.""" self.become_admin() node = factory.make_Node( status=factory.pick_enum(NODE_STATUS, but_not=[NODE_STATUS.READY])) newname = factory.make_name("lv") block_device = factory.make_VirtualBlockDevice(node=node) uri = get_blockdevice_uri(block_device) response = self.client.put(uri, { 'name': newname, }) self.assertEqual(http.client.CONFLICT, response.status_code, response.content)
def test_delete_logical_volume_deletes_logical_volume(self): self.become_admin() node = factory.make_Node(status=NODE_STATUS.READY) volume_group = factory.make_VolumeGroup(node=node) logical_volume = factory.make_VirtualBlockDevice( filesystem_group=volume_group) uri = get_volume_group_uri(volume_group) response = self.client.post(uri, { "op": "delete_logical_volume", "id": logical_volume.id }) self.assertEqual(http.client.NO_CONTENT, response.status_code, response.content) self.assertIsNone(reload_object(logical_volume))
def test_clean_no_partition_table_on_logical_volume(self): node = factory.make_Node() virtual_device = factory.make_VirtualBlockDevice(node=node) error = self.assertRaises( ValidationError, factory.make_PartitionTable, block_device=virtual_device, ) self.assertEqual( { "block_device": ["Cannot create a partition table on a logical volume."] }, error.message_dict, )
def test_format_returns_409_if_not_allocated_or_ready(self): status = factory.pick_enum( NODE_STATUS, but_not=[NODE_STATUS.READY, NODE_STATUS.ALLOCATED]) node = factory.make_Node(status=status, owner=self.user) block_device = factory.make_VirtualBlockDevice(node=node) fstype = factory.pick_filesystem_type() fsuuid = "%s" % uuid.uuid4() uri = get_blockdevice_uri(block_device) response = self.client.post(uri, { "op": "format", "fstype": fstype, "uuid": fsuuid }) self.assertEqual(http.client.CONFLICT, response.status_code, response.content)
def test_set_boot_disk_returns_400_for_virtual_device(self): self.become_admin() node = factory.make_Node(status=NODE_STATUS.READY, owner=self.user) block_device = factory.make_VirtualBlockDevice(node=node) uri = get_blockdevice_uri(block_device) response = self.client.post( uri, { "op": "set_boot_disk", }, ) self.assertEqual(http.client.BAD_REQUEST, response.status_code, response.content) self.assertEqual( b"Cannot set a virtual block device as the boot disk.", response.content, )
def test_format_formats_block_device_as_user(self): node = factory.make_Node(status=NODE_STATUS.ALLOCATED, owner=self.user) block_device = factory.make_VirtualBlockDevice(node=node) fstype = factory.pick_filesystem_type() fsuuid = "%s" % uuid.uuid4() uri = get_blockdevice_uri(block_device) response = self.client.post(uri, { "op": "format", "fstype": fstype, "uuid": fsuuid }) self.assertEqual(http.client.OK, response.status_code, response.content) parsed_device = json_load_bytes(response.content) self.assertEqual(parsed_device["filesystem"]["fstype"], fstype) self.assertEqual(parsed_device["filesystem"]["uuid"], fsuuid) self.assertIsNone(parsed_device["filesystem"]["mount_point"]) block_device = reload_object(block_device) self.assertIsNotNone(block_device.get_effective_filesystem())
def test_updates_virtual_block_device(self): block_device = factory.make_VirtualBlockDevice() name = factory.make_name("lv") vguuid = "%s" % uuid.uuid4() size = random.randint( MIN_BLOCK_DEVICE_SIZE, block_device.filesystem_group.get_size()) form = UpdateVirtualBlockDeviceForm(instance=block_device, data={ 'name': name, 'uuid': vguuid, 'size': size, }) self.assertTrue(form.is_valid(), form.errors) block_device = form.save() expected_size = round_size_to_nearest_block( size, PARTITION_ALIGNMENT_SIZE, False) self.assertThat(block_device, MatchesStructure.byEquality( name=name, uuid=vguuid, size=expected_size, ))
def test_get_physical_block_devices_multiple(self): node = factory.make_Node() block_devices = [ factory.make_PhysicalBlockDevice(node=node) for _ in range(3) ] filesystems = [ factory.make_Filesystem(fstype=FILESYSTEM_TYPE.LVM_PV, block_device=block_device) for block_device in block_devices ] fsgroup = factory.make_FilesystemGroup( node=node, filesystems=filesystems, group_type=FILESYSTEM_GROUP_TYPE.LVM_VG, ) virtual_block_device = factory.make_VirtualBlockDevice( filesystem_group=fsgroup) filesystem = factory.make_Filesystem(fstype=FILESYSTEM_TYPE.LVM_PV, block_device=virtual_block_device) self.assertEqual(filesystem.get_physical_block_devices(), block_devices)
def test_format_formats_block_device_as_user(self): node = factory.make_Node(status=NODE_STATUS.ALLOCATED, owner=self.user) block_device = factory.make_VirtualBlockDevice(node=node) fstype = factory.pick_filesystem_type() fsuuid = '%s' % uuid.uuid4() uri = get_blockdevice_uri(block_device) response = self.client.post(uri, { 'op': 'format', 'fstype': fstype, 'uuid': fsuuid }) self.assertEqual(http.client.OK, response.status_code, response.content) parsed_device = json_load_bytes(response.content) self.assertDictContainsSubset( { 'fstype': fstype, 'uuid': fsuuid, 'mount_point': None, }, parsed_device['filesystem']) block_device = reload_object(block_device) self.assertIsNotNone(block_device.get_effective_filesystem())
def test_unmount_unmounts_filesystem_as_user(self): node = factory.make_Node(status=NODE_STATUS.ALLOCATED, owner=self.user) block_device = factory.make_VirtualBlockDevice(node=node) filesystem = factory.make_Filesystem(block_device=block_device, mount_point="/mnt", acquired=True) uri = get_blockdevice_uri(block_device) response = self.client.post(uri, {'op': 'unmount'}) self.assertEqual(http.client.OK, response.status_code, response.content) self.assertThat( json_load_bytes(response.content)['filesystem'], ContainsDict({ "mount_point": Is(None), "mount_options": Is(None), })) self.assertThat( reload_object(filesystem), MatchesStructure( mount_point=Is(None), mount_options=Is(None), is_mounted=Is(False), ))
def test_actual_instance_returns_VirtualBlockDevice(self): block_device = factory.make_VirtualBlockDevice() parent_type = BlockDevice.objects.get(id=block_device.id) self.assertIsInstance(parent_type.actual_instance, VirtualBlockDevice)
def test__doesnt_delete_volume_group(self): virtual_device = factory.make_VirtualBlockDevice() volume_group = virtual_device.filesystem_group virtual_device.delete() self.assertIsNotNone(reload_object(volume_group))
def test_read(self): node = factory.make_Node(with_boot_disk=False) # Add three physical block devices physical_block_devices = [ factory.make_PhysicalBlockDevice(node=node, size=10 * 1000**3) for _ in range(3) ] # Partition and add a LVM_PV filesystem to the last two physical block # devices. Leave the first partition alone. lvm_pv_filesystems = [ factory.make_Filesystem(block_device=device, fstype=FILESYSTEM_TYPE.LVM_PV) for device in physical_block_devices[1:] ] # Make a filesystem_group (analogous to a volume group) on top of our # two lvm-pm filesystems. filesystem_group = factory.make_FilesystemGroup( group_type=FILESYSTEM_GROUP_TYPE.LVM_VG, filesystems=lvm_pv_filesystems) # Make a VirtualBlockDevice on top of the filesystem group we just # made. virtual_block_device = factory.make_VirtualBlockDevice( filesystem_group=filesystem_group, size=10 * 1000**3) # Add some iSCSI block devices. iscsi_block_devices = [ factory.make_ISCSIBlockDevice(node=node, size=10 * 1000**3) for _ in range(3) ] uri = get_blockdevices_uri(node) response = self.client.get(uri) self.assertEqual(http.client.OK, response.status_code, response.content) devices = json_load_bytes(response.content) # We should have seven devices, three physical, one virtual, and # three iscsi. self.assertEqual(len(devices), 7) self.assertEqual(len([d for d in devices if d['type'] == 'physical']), 3) self.assertEqual(len([d for d in devices if d['type'] == 'virtual']), 1) self.assertEqual(len([d for d in devices if d['type'] == 'iscsi']), 3) # The IDs we expect and the IDs we got through the API should match. expected_device_ids = [ d.id for d in (physical_block_devices + [virtual_block_device] + iscsi_block_devices) ] result_device_ids = [d["id"] for d in devices] self.assertItemsEqual(expected_device_ids, result_device_ids) # Validate that every one has a resource_uri. for d in devices: self.expectThat( d, Contains("resource_uri"), "Device(%s:%s) is missing a resource_uri." % (d['type'], d['id']))
def test_type_virtual(self): block_device = factory.make_VirtualBlockDevice() self.assertEqual("virtual", block_device.type)
def test_clears_all_objects(self): node = factory.make_Node() physical_block_devices = [ factory.make_PhysicalBlockDevice(node=node, size=10 * 1000 ** 3) for _ in range(3) ] filesystem = factory.make_Filesystem( block_device=physical_block_devices[0] ) partition_table = factory.make_PartitionTable( block_device=physical_block_devices[1] ) partition = factory.make_Partition(partition_table=partition_table) fslvm = factory.make_Filesystem( block_device=physical_block_devices[2], fstype=FILESYSTEM_TYPE.LVM_PV, ) vgroup = factory.make_FilesystemGroup( group_type=FILESYSTEM_GROUP_TYPE.LVM_VG, filesystems=[fslvm] ) vbd1 = factory.make_VirtualBlockDevice( filesystem_group=vgroup, size=2 * 1000 ** 3 ) vbd2 = factory.make_VirtualBlockDevice( filesystem_group=vgroup, size=3 * 1000 ** 3 ) filesystem_on_vbd1 = factory.make_Filesystem( block_device=vbd1, fstype=FILESYSTEM_TYPE.LVM_PV ) vgroup_on_vgroup = factory.make_FilesystemGroup( group_type=FILESYSTEM_GROUP_TYPE.LVM_VG, filesystems=[filesystem_on_vbd1], ) vbd3_on_vbd1 = factory.make_VirtualBlockDevice( filesystem_group=vgroup_on_vgroup, size=1 * 1000 ** 3 ) clear_full_storage_configuration( node, PhysicalBlockDevice=PhysicalBlockDevice, VirtualBlockDevice=VirtualBlockDevice, PartitionTable=PartitionTable, Filesystem=Filesystem, FilesystemGroup=FilesystemGroup, ) for pbd in physical_block_devices: self.expectThat( reload_object(pbd), Not(Is(None)), "Physical block device should not have been deleted.", ) self.expectThat( reload_object(filesystem), Is(None), "Filesystem should have been removed.", ) self.expectThat( reload_object(partition_table), Is(None), "PartitionTable should have been removed.", ) self.expectThat( reload_object(partition), Is(None), "Partition should have been removed.", ) self.expectThat( reload_object(fslvm), Is(None), "LVM PV Filesystem should have been removed.", ) self.expectThat( reload_object(vgroup), Is(None), "Volume group should have been removed.", ) self.expectThat( reload_object(vbd1), Is(None), "Virtual block device should have been removed.", ) self.expectThat( reload_object(vbd2), Is(None), "Virtual block device should have been removed.", ) self.expectThat( reload_object(filesystem_on_vbd1), Is(None), "Filesystem on virtual block device should have been removed.", ) self.expectThat( reload_object(vgroup_on_vgroup), Is(None), "Volume group on virtual block device should have been removed.", ) self.expectThat( reload_object(vbd3_on_vbd1), Is(None), "Virtual block device on another virtual block device should have " "been removed.", )
def test_node_is_set_to_same_node_from_filesystem_group(self): block_device = factory.make_VirtualBlockDevice() self.assertEqual(block_device.filesystem_group.get_node(), block_device.node)
def test_requires_no_fields(self): block_device = factory.make_VirtualBlockDevice() form = UpdateVirtualBlockDeviceForm(instance=block_device, data={}) self.assertTrue(form.is_valid(), form.errors) self.assertItemsEqual([], form.errors.keys())
def test_save_doesnt_overwrite_uuid(self): uuid = uuid4() block_device = factory.make_VirtualBlockDevice(uuid=uuid) self.assertEqual('%s' % uuid, block_device.uuid)
def test_read(self): node = factory.make_Node() block_devices = [ factory.make_PhysicalBlockDevice(node=node) for _ in range(3) ] block_device_ids = [bd.id for bd in block_devices] bd_filesystems = [ factory.make_Filesystem(fstype=FILESYSTEM_TYPE.LVM_PV, block_device=bd) for bd in block_devices ] partitions = [ factory.make_Partition(partition_table=factory.make_PartitionTable( block_device=factory.make_PhysicalBlockDevice(node=node))) for _ in range(3) ] partitions_ids = [partition.id for partition in partitions] partition_filesystems = [ factory.make_Filesystem(fstype=FILESYSTEM_TYPE.LVM_PV, partition=partition) for partition in partitions ] volume_group = factory.make_FilesystemGroup( group_type=FILESYSTEM_GROUP_TYPE.LVM_VG, filesystems=bd_filesystems + partition_filesystems, ) logical_volume_ids = [ factory.make_VirtualBlockDevice(filesystem_group=volume_group, size=bd.size).id for bd in block_devices ] uri = get_volume_group_uri(volume_group) response = self.client.get(uri) self.assertEqual(http.client.OK, response.status_code, response.content) parsed_volume_group = json.loads( response.content.decode(settings.DEFAULT_CHARSET)) parsed_device_ids = [ device["id"] for device in parsed_volume_group["devices"] ] parsed_logical_volume_ids = [ lv["id"] for lv in parsed_volume_group["logical_volumes"] ] self.assertThat( parsed_volume_group, ContainsDict({ "id": Equals(volume_group.id), "uuid": Equals(volume_group.uuid), "name": Equals(volume_group.name), "size": Equals(volume_group.get_size()), "human_size": Equals(human_readable_bytes(volume_group.get_size())), "available_size": Equals(volume_group.get_lvm_free_space()), "human_available_size": Equals(human_readable_bytes( volume_group.get_lvm_free_space())), "used_size": Equals(volume_group.get_lvm_allocated_size()), "human_used_size": Equals( human_readable_bytes( volume_group.get_lvm_allocated_size())), "resource_uri": Equals(get_volume_group_uri(volume_group, test_plural=False)), "system_id": Equals(node.system_id), }), ) self.assertItemsEqual(block_device_ids + partitions_ids, parsed_device_ids) self.assertItemsEqual(logical_volume_ids, parsed_logical_volume_ids)
def create_virtualblockdevice(self, params=None): if params is None: params = {} return factory.make_VirtualBlockDevice(**params)
def test_user_can_edit_VirtualBlockDevice_when_node_owner(self): backend = MAASAuthorizationBackend() user = factory.make_User() node = factory.make_Node(owner=user) device = factory.make_VirtualBlockDevice(node=node) self.assertTrue(backend.has_perm(user, NodePermission.edit, device))