-
Notifications
You must be signed in to change notification settings - Fork 169
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Cover blockresize in various scenarios Signed-off-by: Chunfu Wen <chwen@redhat.com>
- Loading branch information
Showing
2 changed files
with
285 additions
and
0 deletions.
There are no files selected for viewing
53 changes: 53 additions & 0 deletions
53
libvirt/tests/cfg/virtual_disks/virtual_disks_blockresize.cfg
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
- virtual_disks.blockresize: | ||
type = virtual_disks_blockresize | ||
take_regular_screendumps = "no" | ||
start_vm = "no" | ||
target_format = "raw" | ||
type_name = "block" | ||
driver_type = 'raw' | ||
device_type = "disk" | ||
target_dev = "sdb" | ||
status_error = "no" | ||
define_error = "no" | ||
func_supported_since_libvirt_ver = (10, 0, 0) | ||
offset = "512" | ||
size_in_mb = "100" | ||
block_size_in_bytes = "104857600" | ||
disk_slice_attrs = "{'slice_type': 'storage', 'slice_offset': '0', 'slice_size': '512'}" | ||
variants test_scenario: | ||
- capacity: | ||
resize_value = "--capacity" | ||
- specific: | ||
resize_value = "104857600B" | ||
- save_restore: | ||
only coldplug..virtio | ||
resize_value = "--capacity" | ||
vm_save = "/var/lib/libvirt/images/%s.save" | ||
- not_equal_actual_size: | ||
only coldplug..virtio | ||
resize_value = "1024B" | ||
status_error = "yes" | ||
status_error_msg = "Operation not supported: block device backed disk must be resized to its actual size" | ||
- not_zero_offset: | ||
only coldplug..virtio | ||
disk_slice_attrs = "{'slice_type': 'storage', 'slice_offset': '512', 'slice_size': '1024'}" | ||
status_error = "yes" | ||
resize_value = "--capacity" | ||
status_error_msg = "Operation not supported: resize of a disk with storage slice with non-zero .*offset.*" | ||
- non_raw_block_device: | ||
only coldplug..virtio | ||
overlay_source_file_path = "/var/lib/libvirt/images/qcow2" | ||
driver_type = 'qcow2' | ||
target_format = "qcow2" | ||
status_error = "yes" | ||
resize_value = "--capacity" | ||
status_error_msg = "Operation not supported: block resize to full capacity supported only with.*raw.*local block-based disks" | ||
variants target_bus: | ||
- virtio: | ||
- sata: | ||
- scsi: | ||
variants: | ||
- coldplug: | ||
virt_device_hotplug = "no" | ||
- hotplug: | ||
virt_device_hotplug = "yes" |
232 changes: 232 additions & 0 deletions
232
libvirt/tests/src/virtual_disks/virtual_disks_blockresize.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,232 @@ | ||
# | ||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
# | ||
# Copyright Red Hat | ||
# | ||
# SPDX-License-Identifier: GPL-2.0 | ||
|
||
# Author: Chunfu Wen <chwen@redhat.com> | ||
# | ||
|
||
import logging | ||
import os | ||
import time | ||
|
||
from virttest import libvirt_version | ||
from virttest import virsh | ||
from virttest import virt_vm | ||
from virttest import utils_misc | ||
|
||
from virttest.libvirt_xml import vm_xml, xcepts | ||
from virttest.utils_libvirt import libvirt_disk | ||
from virttest.utils_test import libvirt | ||
|
||
|
||
LOG = logging.getLogger('avocado.' + __name__) | ||
cleanup_files = [] | ||
|
||
|
||
def setup_scsi_debug_block_device(): | ||
""" | ||
Setup one scsi_debug block device | ||
:return: device name | ||
""" | ||
source_disk = libvirt.create_scsi_disk(scsi_option="", | ||
scsi_size="100") | ||
return source_disk | ||
|
||
|
||
def check_image_virtual_size(image_file, matched_size, test): | ||
""" | ||
Check whether image virtual size queried by qemu-img is matched | ||
:param image_file: image file path | ||
:param matched_size: anticipated size | ||
:param test: test case itself | ||
""" | ||
disk_info_dict = utils_misc.get_image_info(image_file) | ||
actual_size_in_bytes = str(disk_info_dict.get("vsize")) | ||
if actual_size_in_bytes != matched_size: | ||
test.fail(f"actual size of block disk is {actual_size_in_bytes}, but expected is : {matched_size}") | ||
|
||
|
||
def create_customized_disk(params, test): | ||
""" | ||
Create one customized disk with related attributes | ||
:param params: dict wrapped with params | ||
:param test: test case itself | ||
""" | ||
type_name = params.get("type_name") | ||
disk_device = params.get("device_type") | ||
device_target = params.get("target_dev") | ||
device_bus = params.get("target_bus") | ||
device_format = params.get("target_format") | ||
source_file_path = setup_scsi_debug_block_device() | ||
overlay_source_file_path = params.get("overlay_source_file_path") | ||
matched_size = params.get("block_size_in_bytes") | ||
source_dict = {} | ||
|
||
# check block size | ||
check_image_virtual_size(source_file_path, matched_size, test) | ||
|
||
if source_file_path: | ||
source_dict.update({"dev": source_file_path}) | ||
|
||
if overlay_source_file_path: | ||
libvirt.create_local_disk("file", overlay_source_file_path, "100M", device_format) | ||
cleanup_files.append(overlay_source_file_path) | ||
convert_cmd = "qemu-img convert -f qcow2 -O qcow2 %s %s" % (overlay_source_file_path, source_file_path) | ||
|
||
disk_src_dict = {"attrs": source_dict} | ||
|
||
customized_disk = libvirt_disk.create_primitive_disk_xml( | ||
type_name, disk_device, | ||
device_target, device_bus, | ||
device_format, disk_src_dict, None) | ||
|
||
# Sometimes, slice size can be gotten by command (du -b source_file_path), but here not necessary | ||
disk_slice_attrs = params.get('disk_slice_attrs') | ||
if disk_slice_attrs: | ||
disk_source = customized_disk.source | ||
disk_source.slices = customized_disk.new_slices(**eval(disk_slice_attrs)) | ||
customized_disk.source = disk_source | ||
|
||
LOG.debug("create customized xml: %s", customized_disk) | ||
return customized_disk | ||
|
||
|
||
def check_slice_within_vm(vm, new_disk, slice_value): | ||
""" | ||
Check disk slices attributes in guest internal | ||
:param vm: vm object | ||
:param new_disk: newly vm disk | ||
:param slice_value: slice value | ||
""" | ||
session = None | ||
try: | ||
session = vm.wait_for_login() | ||
cmd = ("lsblk |grep {0}" | ||
.format(new_disk)) | ||
status, output = session.cmd_status_output(cmd) | ||
LOG.debug("Disk operation in VM:\nexit code:\n%s\noutput:\n%s", | ||
status, output) | ||
return slice_value in output | ||
except Exception as err: | ||
LOG.debug("Error happens when check slices in vm: %s", str(err)) | ||
return False | ||
finally: | ||
if session: | ||
session.close() | ||
|
||
|
||
def check_vm_dumpxml(params, test, expected_attribute=True): | ||
""" | ||
Common method to check source in cdrom device | ||
:param params: one collective object representing wrapped parameters | ||
:param test: test object | ||
:param expected_attribute: bool indicating whether expected attribute exists or not | ||
""" | ||
vm_name = params.get("main_vm") | ||
disk_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) | ||
target_dev = params.get('target_dev') | ||
disk = disk_vmxml.get_disk_all()[target_dev] | ||
slices = disk.find('source').find('slices') | ||
if not expected_attribute: | ||
if slices is not None: | ||
test.fail("unexpected slices appear in vm disk xml") | ||
else: | ||
if slices is None: | ||
test.fail("slices can not be found in vm disk xml") | ||
|
||
|
||
def run(test, params, env): | ||
""" | ||
Test resize disk with slices. | ||
1.Prepare a vm with block disk | ||
2.Attach block disk with slice attribute to the vm | ||
3.Start vm | ||
4.Resize the block disk | ||
5.Check resize operations | ||
6.Check status in VM internal | ||
7.Detach device | ||
""" | ||
vm_name = params.get("main_vm") | ||
vm = env.get_vm(vm_name) | ||
virsh_dargs = {'debug': True} | ||
|
||
hotplug = "yes" == params.get("virt_device_hotplug") | ||
part_path = "/dev/%s" | ||
|
||
# Skip test if version not match expected one | ||
libvirt_version.is_libvirt_feature_supported(params) | ||
|
||
# Get disk partitions info before hot/cold plug virtual disk | ||
if vm.is_alive(): | ||
vm.destroy(gracefully=False) | ||
|
||
# Backup vm xml | ||
vmxml_backup = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) | ||
vmxml = vmxml_backup.copy() | ||
|
||
test_scenario = params.get("test_scenario") | ||
target_bus = params.get("target_bus") | ||
target_dev = params.get('target_dev') | ||
status_error = "yes" == params.get("status_error") | ||
try: | ||
device_obj = create_customized_disk(params, test) | ||
if not hotplug: | ||
vmxml.add_device(device_obj) | ||
vmxml.sync() | ||
vm.start() | ||
vm.wait_for_login() | ||
if hotplug: | ||
virsh.attach_device(vm_name, device_obj.xml, | ||
ignore_status=False, debug=True) | ||
except xcepts.LibvirtXMLError as xml_error: | ||
test.fail("Failed to define VM:\n%s" % str(xml_error)) | ||
except virt_vm.VMStartError as details: | ||
test.fail("VM failed to start." | ||
"Error: %s" % str(details)) | ||
else: | ||
session = vm.wait_for_login() | ||
time.sleep(20) | ||
new_disk, _ = libvirt_disk.get_non_root_disk_name(session) | ||
session.close() | ||
check_vm_dumpxml(params, test, True) | ||
|
||
slice_value = params.get("offset") | ||
check_slice_within_vm(vm, new_disk, slice_value) | ||
|
||
if test_scenario in ["blockresize_save_restore"]: | ||
vm_save = params.get("vm_save") | ||
cleanup_files.append(vm_save) | ||
virsh.save(vm_name, vm_save) | ||
virsh.restore(vm_save) | ||
vm.wait_for_login().close() | ||
|
||
resize_value = params.get("resize_value") | ||
result = virsh.blockresize(vm_name, target_dev, | ||
resize_value, **virsh_dargs) | ||
libvirt.check_exit_status(result, status_error) | ||
|
||
check_vm_dumpxml(params, test, False) | ||
slice_value = params.get("size_in_mb") | ||
check_slice_within_vm(vm, new_disk, slice_value) | ||
if hotplug: | ||
virsh.detach_device(vm_name, device_obj.xml, flagstr="--live", | ||
debug=True, ignore_status=False) | ||
finally: | ||
if vm.is_alive(): | ||
vm.destroy(gracefully=False) | ||
# Restoring vm | ||
vmxml_backup.sync() | ||
libvirt.delete_scsi_disk() | ||
# Clean up files | ||
for file_path in cleanup_files: | ||
if os.path.exists(file_path): | ||
os.remove(file_path) |