From cefeef4c7e41bdcc3140cb4ea555187f59e00f7c Mon Sep 17 00:00:00 2001 From: Gorka Eguileor Date: Thu, 19 Mar 2020 14:54:55 +0100 Subject: [PATCH] DBMS: Fix volume deletion with MySQL When using the DBMS plugin with MySQL with default configuration (hard DB row deletes) the deletion of a volume fails if the volume has metadata or admin metadata. The reason are the foreign key constraints from those 2 tables, because we are not deleting their rows before deleting the volume row. This doesn't fail with SQLite, but we leave rows behind. With this patch we will delete all metadata and admin_metadata belonging to the volume before we delete the volume row itself. Closes-Bug: #1868148 Change-Id: I8712045752a7a150a3633451246ed992dee35972 --- cinderlib/persistence/dbms.py | 4 ++++ cinderlib/tests/unit/persistence/test_dbms.py | 15 +++++++++++++++ .../fix-mysql-vol-delete-f675778ea150cb9a.yaml | 5 +++++ 3 files changed, 24 insertions(+) create mode 100644 releasenotes/notes/fix-mysql-vol-delete-f675778ea150cb9a.yaml diff --git a/cinderlib/persistence/dbms.py b/cinderlib/persistence/dbms.py index cc6a9b5..3f443f4 100644 --- a/cinderlib/persistence/dbms.py +++ b/cinderlib/persistence/dbms.py @@ -315,6 +315,10 @@ class DBPersistence(persistence_base.PersistenceDriverBase): volume.volume_type.qos_specs_id) else: LOG.debug('hard deleting volume %s', volume.id) + for model in (models.VolumeMetadata, models.VolumeAdminMetadata): + query = sqla_api.model_query(objects.CONTEXT, model) + query.filter_by(volume_id=volume.id).delete() + query = sqla_api.model_query(objects.CONTEXT, models.Volume) query.filter_by(id=volume.id).delete() if delete_type: diff --git a/cinderlib/tests/unit/persistence/test_dbms.py b/cinderlib/tests/unit/persistence/test_dbms.py index 1ddfb47..a42314c 100644 --- a/cinderlib/tests/unit/persistence/test_dbms.py +++ b/cinderlib/tests/unit/persistence/test_dbms.py @@ -120,6 +120,21 @@ class TestDBPersistence(base.BasePersistenceTest): cinder_ovos.VolumeType) self.assertEqual('__DEFAULT__', self.persistence.DEFAULT_TYPE.name) + def test_delete_volume_with_metadata(self): + vols = self.create_volumes([{'size': i, 'name': 'disk%s' % i, + 'metadata': {'k': 'v', 'k2': 'v2'}, + 'admin_metadata': {'k': '1'}} + for i in range(1, 3)]) + self.persistence.delete_volume(vols[0]) + res = self.persistence.get_volumes() + self.assertListEqualObj([vols[1]], res) + + for model in (dbms.models.VolumeMetadata, + dbms.models.VolumeAdminMetadata): + query = dbms.sqla_api.model_query(self.context, model) + res = query.filter_by(volume_id=vols[0].id).all() + self.assertEqual([], res) + class TestMemoryDBPersistence(TestDBPersistence): PERSISTENCE_CFG = {'storage': 'memory_db'} diff --git a/releasenotes/notes/fix-mysql-vol-delete-f675778ea150cb9a.yaml b/releasenotes/notes/fix-mysql-vol-delete-f675778ea150cb9a.yaml new file mode 100644 index 0000000..e0760b6 --- /dev/null +++ b/releasenotes/notes/fix-mysql-vol-delete-f675778ea150cb9a.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Bug #1868148: Volume deletion no longer fails due to DB constraints when + using the DBMS metadata persistence plugin with a MySQL backend.