-
Notifications
You must be signed in to change notification settings - Fork 5
lib/vdi: Add VDI resize support and integrate into VM & linstor operations #273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
aad64b9
2ab7618
b919032
e7c3e71
5589bef
f1193d9
fdc4d32
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ | |
from lib.common import PackageManagerEnum, parse_xe_dict, safe_split, strtobool, wait_for, wait_for_not | ||
from lib.snapshot import Snapshot | ||
from lib.vif import VIF | ||
from lib.vdi import VDI | ||
|
||
class VM(BaseVM): | ||
def __init__(self, uuid, host): | ||
|
@@ -130,6 +131,9 @@ def wait_for_vm_running_and_ssh_up(self): | |
self.wait_for_os_booted() | ||
wait_for(self.is_ssh_up, "Wait for SSH up") | ||
|
||
def wait_for_vm_running(self): | ||
wait_for(self.is_running) | ||
|
||
def ssh_touch_file(self, filepath): | ||
logging.info("Create file on VM (%s)" % filepath) | ||
self.ssh(['touch', filepath]) | ||
|
@@ -361,6 +365,24 @@ def test_snapshot_on_running_vm(self): | |
finally: | ||
snapshot.destroy(verify=True) | ||
|
||
def vdi_resize(self, vdi_uuid, new_size=None): | ||
# Reference | ||
# MAX_VHD_SIZE = 2088960 * 1024 * 1024 # 2088960 MB | ||
# MIN_VHD_SIZE = 1 * 1024 * 1024 # 1MB | ||
|
||
# Following assert may be removed in future if we support online vdi resize | ||
assert not self.is_running(), f"Expected halted, got running" | ||
|
||
vdi_obj = VDI(vdi_uuid, sr=self.get_sr()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just |
||
if new_size is None: | ||
# Resize by double, ideally it should be within min and max limits reference | ||
vdi_size = int(vdi_obj.param_get("virtual-size")) | ||
new_size = str(vdi_size * 2) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be cleaner to use integers to manipulate size objects. def vdi_resize(self, vdi_uuid: str, new_size: Optional[int] = None) -> None:
... |
||
|
||
vdi_obj.resize(new_size) | ||
resized_vdi_size = vdi_obj.param_get("virtual-size") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same idea, better convert to |
||
assert int(resized_vdi_size) == int(new_size), f"Expected {new_size}, got {resized_vdi_size}" | ||
|
||
def get_messages(self, name): | ||
args = { | ||
'obj-uuid': self.uuid, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,13 +2,13 @@ | |
import pytest | ||
import time | ||
|
||
from .conftest import STORAGE_POOL_NAME, LINSTOR_PACKAGE | ||
from .conftest import LINSTOR_PACKAGE | ||
from lib.commands import SSHCommandFailed | ||
from lib.common import wait_for, vm_image | ||
from tests.storage import vdi_is_open | ||
|
||
# Requirements: | ||
# - one XCP-ng host >= 8.2 with an additional unused disk for the SR | ||
# - two or more XCP-ng hosts >= 8.2 with additional unused disk(s) for the SR | ||
# - access to XCP-ng RPM repository from the host | ||
|
||
class TestLinstorSRCreateDestroy: | ||
|
@@ -18,15 +18,15 @@ class TestLinstorSRCreateDestroy: | |
and VM import. | ||
""" | ||
|
||
def test_create_sr_without_linstor(self, host, lvm_disk): | ||
def test_create_sr_without_linstor(self, host, lvm_disks, provisioning_type, storage_pool_name): | ||
# This test must be the first in the series in this module | ||
assert not host.is_package_installed('python-linstor'), \ | ||
"linstor must not be installed on the host at the beginning of the tests" | ||
try: | ||
sr = host.sr_create('linstor', 'LINSTOR-SR-test', { | ||
'group-name': STORAGE_POOL_NAME, | ||
'group-name': storage_pool_name, | ||
'redundancy': '1', | ||
'provisioning': 'thin' | ||
'provisioning': provisioning_type | ||
}, shared=True) | ||
try: | ||
sr.destroy() | ||
|
@@ -36,13 +36,13 @@ def test_create_sr_without_linstor(self, host, lvm_disk): | |
except SSHCommandFailed as e: | ||
logging.info("SR creation failed, as expected: {}".format(e)) | ||
|
||
def test_create_and_destroy_sr(self, pool_with_linstor): | ||
def test_create_and_destroy_sr(self, pool_with_linstor, provisioning_type, storage_pool_name): | ||
# Create and destroy tested in the same test to leave the host as unchanged as possible | ||
master = pool_with_linstor.master | ||
sr = master.sr_create('linstor', 'LINSTOR-SR-test', { | ||
'group-name': STORAGE_POOL_NAME, | ||
'group-name': storage_pool_name, | ||
'redundancy': '1', | ||
'provisioning': 'thin' | ||
'provisioning': provisioning_type | ||
}, shared=True) | ||
# import a VM in order to detect vm import issues here rather than in the vm_on_linstor_sr fixture used in | ||
# the next tests, because errors in fixtures break teardown | ||
|
@@ -78,6 +78,15 @@ def test_snapshot(self, vm_on_linstor_sr): | |
finally: | ||
vm.shutdown(verify=True) | ||
|
||
@pytest.mark.small_vm | ||
@pytest.mark.big_vm | ||
def test_resize_vdi(self, vm_on_linstor_sr): | ||
vm = vm_on_linstor_sr | ||
logging.info("* VDI Resize started *") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we really want |
||
for vdi_uuid in vm.vdi_uuids(): | ||
vm.vdi_resize(vdi_uuid) | ||
logging.info("* VDI Resize completed *") | ||
|
||
# *** tests with reboots (longer tests). | ||
|
||
@pytest.mark.reboot | ||
|
@@ -147,7 +156,7 @@ def _ensure_resource_remain_diskless(host, controller_option, volume_name, diskl | |
|
||
class TestLinstorDisklessResource: | ||
@pytest.mark.small_vm | ||
def test_diskless_kept(self, host, linstor_sr, vm_on_linstor_sr): | ||
def test_diskless_kept(self, host, linstor_sr, vm_on_linstor_sr, storage_pool_name): | ||
vm = vm_on_linstor_sr | ||
vdi_uuids = vm.vdi_uuids(sr_uuid=linstor_sr.uuid) | ||
vdi_uuid = vdi_uuids[0] | ||
|
@@ -157,10 +166,12 @@ def test_diskless_kept(self, host, linstor_sr, vm_on_linstor_sr): | |
for member in host.pool.hosts: | ||
controller_option += f"{member.hostname_or_ip}," | ||
|
||
sr_group_name = "xcp-sr-" + storage_pool_name.replace("/", "_") | ||
|
||
# Get volume name from VDI uuid | ||
# "xcp/volume/{vdi_uuid}/volume-name": "{volume_name}" | ||
output = host.ssh([ | ||
"linstor-kv-tool", "--dump-volumes", "-g", "xcp-sr-linstor_group_thin_device", | ||
"linstor-kv-tool", "--dump-volumes", "-g", sr_group_name, | ||
"|", "grep", "volume-name", "|", "grep", vdi_uuid | ||
]) | ||
volume_name = output.split(': ')[1].split('"')[1] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are more states than just "running" and halted, that would probably need
assert self.is_halted()
here