From 4e30d916a3f521a60480a21913ad8ae70bacc759 Mon Sep 17 00:00:00 2001 From: Jean-Louis Dupond Date: Mon, 12 Jun 2023 12:58:39 +0200 Subject: [PATCH] Add list_bitmaps command Signed-off-by: Jean-Louis Dupond Change-Id: Ic3e078340278739745ab27ab97d9f23b482781df --- lib/vdsm/API.py | 3 ++ lib/vdsm/api/vdsm-api.yml | 20 ++++++++++++++ lib/vdsm/host/caps.py | 1 + lib/vdsm/storage/bitmaps.py | 11 ++++++++ lib/vdsm/storage/hsm.py | 15 ++++++++++ lib/vdsm/storage/sdm/api/Makefile.am | 1 + lib/vdsm/storage/sdm/api/list_bitmaps.py | 35 ++++++++++++++++++++++++ tests/storage/bitmaps_test.py | 23 ++++++++++++++++ tests/storage/sdm_clear_bitmaps_test.py | 2 +- 9 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 lib/vdsm/storage/sdm/api/list_bitmaps.py diff --git a/lib/vdsm/API.py b/lib/vdsm/API.py index b0ce6b1d7a..39f4f1f184 100644 --- a/lib/vdsm/API.py +++ b/lib/vdsm/API.py @@ -1757,6 +1757,9 @@ def remove_bitmap(self, job_id, vol_info, bitmap): def clear_bitmaps(self, job_id, vol_info): return self._irs.sdm_clear_bitmaps(job_id, vol_info) + def list_bitmaps(self, job_id, vol_info): + return self._irs.sdm_list_bitmaps(job_id, vol_info) + class Lease(APIBase): ctorArgs = [] diff --git a/lib/vdsm/api/vdsm-api.yml b/lib/vdsm/api/vdsm-api.yml index 2382ecfb7a..bfa5839c72 100644 --- a/lib/vdsm/api/vdsm-api.yml +++ b/lib/vdsm/api/vdsm-api.yml @@ -7478,6 +7478,13 @@ types: type: boolean added: '4.5' + - defaultvalue: false + description: Indicates whether listing volume bitmaps + is implemented in VDSM + name: list_bitmaps + type: boolean + added: '4.5.5' + type: object VdsmNetworkCapabilities: &VdsmNetworkCapabilities @@ -12606,6 +12613,19 @@ SDM.clear_bitmaps: name: vol_info type: *CopyDataDIVEndpoint +SDM.list_bitmaps: + added: '4.5.5' + description: List all the bitmaps from the volume. + Allowed only for a volume with qcow2 format. + params: + - description: A UUID to be used for tracking the job progress + name: job_id + type: *UUID + + - description: The volume to list the bitmap from. + name: vol_info + type: *CopyDataDIVEndpoint + NBD.start_server: added: '4.3' description: Start serving a volume using NBD protocol. Fail if the service diff --git a/lib/vdsm/host/caps.py b/lib/vdsm/host/caps.py index c6ae827bc8..6721bf39e8 100644 --- a/lib/vdsm/host/caps.py +++ b/lib/vdsm/host/caps.py @@ -175,6 +175,7 @@ def get(): caps['measure_active'] = True caps['mailbox_events'] = config.getboolean("mailbox", "events_enable") caps['zerocopy_migrations'] = hasattr(libvirt, 'VIR_MIGRATE_ZEROCOPY') + caps['list_bitmaps'] = True return caps diff --git a/lib/vdsm/storage/bitmaps.py b/lib/vdsm/storage/bitmaps.py index 35b37a28ed..fc12c7d9e2 100644 --- a/lib/vdsm/storage/bitmaps.py +++ b/lib/vdsm/storage/bitmaps.py @@ -168,6 +168,17 @@ def clear_bitmaps(vol_path): vol_path=vol_path) +def list_bitmaps(vol_path): + """ + List bitmaps to the given volume path + + Arguments: + vol_path (str): Path to the volume + """ + bitmaps = _query_bitmaps(vol_path) + return bitmaps + + def _add_bitmap(vol_path, bitmap, granularity=None, enable=True): log.info("Add bitmap %s to %r", bitmap, vol_path) diff --git a/lib/vdsm/storage/hsm.py b/lib/vdsm/storage/hsm.py index 65474ec9c8..1561e6ea63 100644 --- a/lib/vdsm/storage/hsm.py +++ b/lib/vdsm/storage/hsm.py @@ -78,6 +78,7 @@ add_bitmap, copy_data, clear_bitmaps, + list_bitmaps, merge as api_merge, move_device, reduce_domain, @@ -3492,6 +3493,20 @@ def sdm_clear_bitmaps(self, job_id, vol_info): job = clear_bitmaps.Job(job_id, self._pool.id, vol_info) self.sdm_schedule(job) + @public + def sdm_list_bitmaps(self, job_id, vol_info): + """ + List all the bitmaps from the given volume. + + Arguments: + job_id (str): The UUID of the job. + vol_info (dict): Dictionary that contains all the needed info + on the volume. + """ + job = list_bitmaps.Job(job_id, self._pool.id, vol_info) + self.sdm_schedule(job) + return dict(uuidlist=bitmaps) + # Lease operations @public diff --git a/lib/vdsm/storage/sdm/api/Makefile.am b/lib/vdsm/storage/sdm/api/Makefile.am index ff27cae206..99eca3b95b 100644 --- a/lib/vdsm/storage/sdm/api/Makefile.am +++ b/lib/vdsm/storage/sdm/api/Makefile.am @@ -12,6 +12,7 @@ dist_vdsmsdmapi_PYTHON = \ base.py \ copy_data.py \ clear_bitmaps.py \ + list_bitmaps.py \ merge.py \ move_device.py \ reduce_domain.py \ diff --git a/lib/vdsm/storage/sdm/api/list_bitmaps.py b/lib/vdsm/storage/sdm/api/list_bitmaps.py new file mode 100644 index 0000000000..1e61697c85 --- /dev/null +++ b/lib/vdsm/storage/sdm/api/list_bitmaps.py @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: Red Hat, Inc. +# SPDX-License-Identifier: GPL-2.0-or-later + +from vdsm.storage import bitmaps +from vdsm.storage import constants as sc +from vdsm.storage import exception as se +from vdsm.storage import guarded +from vdsm.storage.sdm.volume_info import VolumeInfo + +from . import base + + +class Job(base.Job): + + def __init__(self, job_id, host_id, vol_info): + super(Job, self).__init__(job_id, 'list_bitmaps', host_id) + self._vol_info = VolumeInfo(vol_info, host_id) + self._bitmaps = None + + def _validate(self): + if self._vol_info.volume.getFormat() != sc.COW_FORMAT: + raise se.UnsupportedOperation( + "Volume is not in COW format", + vol_uuid=self._vol_info.vol_id) + + def _run(self): + with guarded.context(self._vol_info.locks): + self._validate() + with self._vol_info.prepare(): + with self._vol_info.volume_operation(): + self._bitmaps = bitmaps.list_bitmaps(self._vol_info.path) + + @property + def bitmaps(self): + return self._bitmaps diff --git a/tests/storage/bitmaps_test.py b/tests/storage/bitmaps_test.py index 02046253fe..96c3f848fd 100644 --- a/tests/storage/bitmaps_test.py +++ b/tests/storage/bitmaps_test.py @@ -333,3 +333,26 @@ def test_clear_bitmaps_failed(monkeypatch, tmp_mount, vol_chain): monkeypatch.setattr(qemuimg, "bitmap_remove", qemuimg_failure) with pytest.raises(exception.RemoveBitmapError): bitmaps.clear_bitmaps(vol_chain.top_vol) + + +def test_list_bitmaps(tmp_mount, vol_chain): + # Add new bitmaps to top volume + for bitmap in ['bitmap_1', 'bitmap_2']: + op = qemuimg.bitmap_add(vol_chain.top_vol, bitmap) + op.run() + + uuids = bitmaps.list_bitmaps(vol_chain.top_vol) + assert uuids == ['bitmap_1', 'bitmap_2'] + + +def test_list_bitmaps_empty(tmp_mount, vol_chain): + # Add new bitmaps to top volume + for bitmap in ['bitmap_1', 'bitmap_2']: + op = qemuimg.bitmap_add(vol_chain.top_vol, bitmap) + op.run() + + # Clear top volume bitmaps + bitmaps.clear_bitmaps(vol_chain.top_vol) + + uuids = bitmaps.list_bitmaps(vol_chain.top_vol) + assert uuids == [] diff --git a/tests/storage/sdm_clear_bitmaps_test.py b/tests/storage/sdm_clear_bitmaps_test.py index e8ff2ec82b..145f1f1ef4 100644 --- a/tests/storage/sdm_clear_bitmaps_test.py +++ b/tests/storage/sdm_clear_bitmaps_test.py @@ -28,7 +28,7 @@ from vdsm.storage import guarded from vdsm.storage import qemuimg from vdsm.storage.sdm import volume_info -from vdsm.storage.sdm.api import clear_bitmaps +from vdsm.storage.sdm.api import clear_bitmaps, list_bitmaps def failure(*args, **kwargs):