diff --git a/karbor/services/protection/protection_plugins/volume/volume_glance_plugin.py b/karbor/services/protection/protection_plugins/volume/volume_glance_plugin.py index 773a1e50..95115163 100644 --- a/karbor/services/protection/protection_plugins/volume/volume_glance_plugin.py +++ b/karbor/services/protection/protection_plugins/volume/volume_glance_plugin.py @@ -418,6 +418,36 @@ class RestoreOperation(protection_plugin.Operation): resource_type=constants.VOLUME_RESOURCE_TYPE) +class VerifyOperation(protection_plugin.Operation): + def __init__(self): + super(VerifyOperation, self).__init__() + + def on_main(self, checkpoint, resource, context, parameters, **kwargs): + original_volume_id = resource.id + bank_section = checkpoint.get_resource_bank_section( + original_volume_id) + LOG.info('Verifying the volume backup, volume id: %s', + original_volume_id) + + update_method = partial( + utils.update_resource_verify_result, + kwargs.get('verify'), resource.type, original_volume_id) + + backup_status = bank_section.get_object("status") + + if backup_status == constants.RESOURCE_STATUS_AVAILABLE: + update_method(constants.RESOURCE_STATUS_AVAILABLE) + else: + reason = ('The status of volume backup status is %s.' + % backup_status) + update_method(backup_status, reason) + raise exception.VerifyResourceFailed( + name="Volume backup", + reason=reason, + resource_id=original_volume_id, + resource_type=resource.type) + + class DeleteOperation(protection_plugin.Operation): def on_main(self, checkpoint, resource, context, parameters, **kwargs): volume_id = resource.id @@ -473,6 +503,10 @@ class VolumeGlanceProtectionPlugin(protection_plugin.ProtectionPlugin): def get_saved_info_schema(cls, resources_type): return volume_schemas.SAVED_INFO_SCHEMA + @classmethod + def get_verify_schema(cls, resource_type): + return volume_schemas.VERIFY_SCHEMA + @classmethod def get_saved_info(cls, metadata_store, resource): pass @@ -487,3 +521,6 @@ class VolumeGlanceProtectionPlugin(protection_plugin.ProtectionPlugin): def get_delete_operation(self, resource): return DeleteOperation() + + def get_verify_operation(self, resource): + return VerifyOperation() diff --git a/karbor/services/protection/protection_plugins/volume/volume_glance_plugin_schemas.py b/karbor/services/protection/protection_plugins/volume/volume_glance_plugin_schemas.py index 0f3170b5..da448f1d 100644 --- a/karbor/services/protection/protection_plugins/volume/volume_glance_plugin_schemas.py +++ b/karbor/services/protection/protection_plugins/volume/volume_glance_plugin_schemas.py @@ -43,6 +43,12 @@ RESTORE_SCHEMA = { "required": ["restore_name"] } +VERIFY_SCHEMA = { + "title": "Volume Glance Protection Verify", + "type": "object", + "properties": {} +} + SAVED_INFO_SCHEMA = { "title": "Volume Glance Protection Saved Info", "type": "object", diff --git a/karbor/tests/unit/protection/test_cinder_glance_plugin.py b/karbor/tests/unit/protection/test_cinder_glance_plugin.py index b3613b60..636ee07b 100644 --- a/karbor/tests/unit/protection/test_cinder_glance_plugin.py +++ b/karbor/tests/unit/protection/test_cinder_glance_plugin.py @@ -13,6 +13,7 @@ import collections from karbor.common import constants from karbor.context import RequestContext +from karbor import exception from karbor.resource import Resource from karbor.services.protection.bank_plugin import Bank from karbor.services.protection.bank_plugin import BankPlugin @@ -236,3 +237,36 @@ class VolumeGlanceProtectionPluginTest(base.TestCase): def test_get_supported_resources_types(self): types = self.plugin.get_supported_resources_types() self.assertEqual([constants.VOLUME_RESOURCE_TYPE], types) + + @mock.patch('karbor.services.protection.protection_plugins.utils.' + 'update_resource_verify_result') + def test_verify_backup(self, mock_update_verify): + resource = Resource(id="123", + type=constants.VOLUME_RESOURCE_TYPE, + name='fake') + + fake_bank_section.get_object = mock.MagicMock() + fake_bank_section.get_object.return_value = 'available' + + verify_operation = self.plugin.get_verify_operation(resource) + call_hooks(verify_operation, self.checkpoint, resource, self.cntxt, + {}) + mock_update_verify.assert_called_with( + None, resource.type, resource.id, 'available') + + @mock.patch('karbor.services.protection.protection_plugins.utils.' + 'update_resource_verify_result') + def test_verify_backup_with_error_status(self, mock_update_verify): + resource = Resource(id="123", + type=constants.VOLUME_RESOURCE_TYPE, + name='fake') + fake_bank_section.get_object = mock.MagicMock() + fake_bank_section.get_object.return_value = 'error' + + verify_operation = self.plugin.get_verify_operation(resource) + self.assertRaises( + exception.VerifyResourceFailed, call_hooks, verify_operation, + self.checkpoint, resource, self.cntxt, {}) + mock_update_verify.assert_called_with( + None, resource.type, resource.id, 'error', + 'The status of volume backup status is error.')