diff --git a/src/rockstor/storageadmin/fixtures/test_config_backup.json b/src/rockstor/storageadmin/fixtures/test_config_backup.json index 81536632c..46c79e8c9 100644 --- a/src/rockstor/storageadmin/fixtures/test_config_backup.json +++ b/src/rockstor/storageadmin/fixtures/test_config_backup.json @@ -13,6 +13,20 @@ "role": null } }, +{ + "model": "storageadmin.pool", + "pk": 4, + "fields": { + "name": "rock-pool2", + "uuid": "3176aa98-a939-4f7b-aa6c-70c18570fc8e", + "size": 5242880, + "raid": "single", + "toc": "2023-03-03T21:21:14.952Z", + "compression": "no", + "mnt_options": "", + "role": null + } +}, { "model": "storageadmin.share", "pk": 3, diff --git a/src/rockstor/storageadmin/tests/test_config_backup.py b/src/rockstor/storageadmin/tests/test_config_backup.py index 8ac91eb7f..e2346c530 100644 --- a/src/rockstor/storageadmin/tests/test_config_backup.py +++ b/src/rockstor/storageadmin/tests/test_config_backup.py @@ -30,11 +30,14 @@ """ Fixture creation instructions: -System needs 1 non system pool 'rock-pool', at any raid level. +System needs 2 non system pools: +- 'rock-pool', at any raid level. +- 'rock-pool2', at any raid level. - Create 1 share named 'test_share01' - Create 1 share named 'test_share02' +export DJANGO_SETTINGS_MODULE="settings" poetry run django-admin dumpdata storageadmin.pool storageadmin.share \ --natural-foreign --indent 4 > \ src/rockstor/storageadmin/fixtures/test_config_backup.json @@ -1192,6 +1195,42 @@ class ConfigBackupTests(APITestMixin): "model": "smart_manager.taskdefinition", "pk": 3, }, + { + "model": "smart_manager.taskdefinition", + "pk": 4, + "fields": { + "name": "rockpool_scrub", + "task_type": "scrub", + "json_meta": '{"pool_name": "rock-pool", "pool": "2"}', + "enabled": False, + "crontab": "42 3 * * 5", + "crontabwindow": "*-*-*-*-*-*", + }, + }, + { + "model": "smart_manager.taskdefinition", + "pk": 5, + "fields": { + "name": "boguspool_scrub", + "task_type": "scrub", + "json_meta": '{"pool_name": "bogus-pool", "pool": "99"}', + "enabled": False, + "crontab": "42 3 * * 5", + "crontabwindow": "*-*-*-*-*-*", + }, + }, + { + "model": "smart_manager.taskdefinition", + "pk": 6, + "fields": { + "name": "rockpool2_scrub", + "task_type": "scrub", + "json_meta": '{"pool_name": "rock-pool2", "pool": "3"}', + "enabled": False, + "crontab": "42 3 * * 5", + "crontabwindow": "*-*-*-*-*-*", + }, + }, ] @classmethod @@ -1865,7 +1904,6 @@ def test_validate_taskdef_meta(self): "max_count": "4", } ] - out = [ { "writable": True, @@ -1876,6 +1914,14 @@ def test_validate_taskdef_meta(self): } ] + task_type.append("scrub") + taskdef_meta.append({"pool_name": "rock-pool", "pool": "2"}) + out.append({"pool_name": "rock-pool", "pool": "2"}) + + task_type.append("scrub") + taskdef_meta.append({"pool_name": "rock-pool2", "pool": "3"}) + out.append({"pool_name": "rock-pool2", "pool": "4"}) + for t, m, o in zip(task_type, taskdef_meta, out): ret = validate_taskdef_meta(self.sa_ml, m, t) self.assertEqual( @@ -1888,25 +1934,49 @@ def test_validate_taskdef_meta(self): def test_validate_task_definitions(self): """ - Test: + Test the correct parsing + Snapshot: - valid metadata (snap_daily_ts01 in sm_ml) - invalid metadata: wrong share ID in backup file (snap_daily_ts02 in sm_ml) - invalid metadata: share does not exist on target system (snap_daily_ts04 in sm_ml) + + Scrub: + - valid metadata: no pool ID change (rockpool_scrub in sm_ml) + - valid metadata: with pool ID change (rockpool2_scrub in sm_ml) + - invalid metadata: pool does not exist on target system (boguspool_scrub in sm_ml) """ - out = [{ - "task_type": "snapshot", - "name": "snap_daily_ts01", - "crontabwindow": "*-*-*-*-*-*", - "enabled": False, - "crontab": "42 3 * * *", - "meta": { - "writable": True, - "visible": True, - "prefix": "snap_daily_ts01", - "share": "3", - "max_count": "4", + out = [ + { + "task_type": "snapshot", + "name": "snap_daily_ts01", + "crontabwindow": "*-*-*-*-*-*", + "enabled": False, + "crontab": "42 3 * * *", + "meta": { + "writable": True, + "visible": True, + "prefix": "snap_daily_ts01", + "share": "3", + "max_count": "4", + }, + }, + { + "task_type": "scrub", + "name": "rockpool_scrub", + "crontabwindow": "*-*-*-*-*-*", + "enabled": False, + "crontab": "42 3 * * 5", + "meta": {"pool_name": "rock-pool", "pool": "2"}, + }, + { + "task_type": "scrub", + "name": "rockpool2_scrub", + "crontabwindow": "*-*-*-*-*-*", + "enabled": False, + "crontab": "42 3 * * 5", + "meta": {"pool_name": "rock-pool2", "pool": "4"}, }, - }] + ] ret = validate_task_definitions(self.sm_ml, self.sa_ml) self.assertEqual( ret, diff --git a/src/rockstor/storageadmin/views/config_backup.py b/src/rockstor/storageadmin/views/config_backup.py index 3e61f8bee..1a06b9630 100644 --- a/src/rockstor/storageadmin/views/config_backup.py +++ b/src/rockstor/storageadmin/views/config_backup.py @@ -33,7 +33,7 @@ import rest_framework_custom as rfc from cli.rest_util import api_call from smart_manager.models.service import Service, ServiceStatus -from storageadmin.models import ConfigBackup, RockOn, Share +from storageadmin.models import ConfigBackup, RockOn, Pool, Share from storageadmin.serializers import ConfigBackupSerializer from storageadmin.util import handle_exception from storageadmin.views.rockon_helpers import rockon_tasks_pending @@ -214,6 +214,12 @@ def validate_taskdef_meta(sa_ml, taskdef_meta, task_type): target_share_id = get_target_share_id(source_name) # Update taskdef_meta (needs to be a unicode object) taskdef_meta["share"] = unicode(target_share_id) + if task_type == "scrub": + # get ID of pool name in the target system + target_pool_id = get_target_pool_id(taskdef_meta["pool_name"]) + # Update taskdef_meta (needs to be a unicode object) + taskdef_meta["pool"] = unicode(target_pool_id) + return taskdef_meta @@ -558,6 +564,14 @@ def get_target_share_id(source_name): return so.id +def get_target_pool_id(source_name): + """ + Takes a pool name and returns its ID from the database. + """ + po = Pool.objects.get(name=source_name) + return po.id + + @db_task() @lock_task("restore_config_lock") def restore_config(cbid):