From 28edb063ec5cb5fdaadde296a37c81f829861f3e Mon Sep 17 00:00:00 2001 From: wangliuan Date: Mon, 11 Jan 2016 17:05:03 +0800 Subject: [PATCH] Implement the basic protection service framework Basically, this service will execute a protection operation and persist results with transactions in bank It will also collect operation execution result and update operation status As a basic framework,we just implement the interface and a simple protection example in this patch Change-Id: I1f3970e699b6f2ce2e6a9f2fa13f71789e7c288a Closes-Bug: #1524691 --- smaug/protection/bank_plugin.py | 70 +++++++++++++++++++ smaug/protection/checkpoint.py | 62 +++++++++++++++++ smaug/protection/manager.py | 76 ++++++++++++++++++++- smaug/protection/protection_plugin.py | 69 +++++++++++++++++++ smaug/protection/provider.py | 59 ++++++++++++++++ smaug/tests/unit/protection/__init__.py | 0 smaug/tests/unit/protection/fakes.py | 63 +++++++++++++++++ smaug/tests/unit/protection/test_manager.py | 23 +++++++ 8 files changed, 420 insertions(+), 2 deletions(-) create mode 100644 smaug/protection/bank_plugin.py create mode 100644 smaug/protection/checkpoint.py create mode 100644 smaug/protection/protection_plugin.py create mode 100644 smaug/protection/provider.py create mode 100644 smaug/tests/unit/protection/__init__.py create mode 100644 smaug/tests/unit/protection/fakes.py create mode 100644 smaug/tests/unit/protection/test_manager.py diff --git a/smaug/protection/bank_plugin.py b/smaug/protection/bank_plugin.py new file mode 100644 index 00000000..097e8261 --- /dev/null +++ b/smaug/protection/bank_plugin.py @@ -0,0 +1,70 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +from oslo_config import cfg +from oslo_log import log as logging + +import abc +import six + +CONF = cfg.CONF + +LOG = logging.getLogger(__name__) + + +@six.add_metaclass(abc.ABCMeta) +class BankPlugin(object): + @abc.abstractmethod + def create_object(self, key, value): + return + + @abc.abstractmethod + def update_object(self, key, options, value): + return + + @abc.abstractmethod + def get_object(self, key): + return + + @abc.abstractmethod + def list_objects(self, options): + return + + @abc.abstractmethod + def delete_object(self, key): + return + + @abc.abstractmethod + def chroot(self, context): + # TODO(wangliuan) + pass + + @abc.abstractmethod + def show_object(self, key): + # TODO(wangliuan) + pass + + @abc.abstractmethod + def acquire_lease(self, owner_id): + # TODO(wangliuan) + pass + + @abc.abstractmethod + def renew_lease(self, owner_id): + # TODO(wangliuan) + pass + + @abc.abstractmethod + def check_lease_validity(self): + # TODO(wangliuan) + pass diff --git a/smaug/protection/checkpoint.py b/smaug/protection/checkpoint.py new file mode 100644 index 00000000..361f931a --- /dev/null +++ b/smaug/protection/checkpoint.py @@ -0,0 +1,62 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +from oslo_config import cfg +from oslo_log import log as logging + + +CONF = cfg.CONF + +LOG = logging.getLogger(__name__) + + +class CheckpointSerializer(object): + def __init__(self): + super(CheckpointSerializer, self).__init__() + # TODO(wangliuan) + + def serialize(self, checkpoint, encoding_format): + # TODO(wangliuan) + pass + + def deserialize(self, data, encoding_format): + # TODO(wangliuan) + pass + + +class CheckpointCollection(object): + def __init__(self): + super(CheckpointCollection, self).__init__() + self.checkpoint_serializer = None + self.bank_plugin = None + # TODO(wangliuan) + + def list(self, list_options): + # TODO(wangliuan) + pass + + def show(self, checkpoint_id): + # TODO(wangliuan) + pass + + def delete(self, checkpoint_id): + # TODO(wangliuan) + pass + + def create(self, plan): + # TODO(wangliuan) + pass + + def update(self, checkpoint, **kwargs): + # TODO(wangliuan) + pass diff --git a/smaug/protection/manager.py b/smaug/protection/manager.py index 36a71a5f..8945f8ee 100644 --- a/smaug/protection/manager.py +++ b/smaug/protection/manager.py @@ -17,13 +17,21 @@ Protection Service from oslo_config import cfg from oslo_log import log as logging import oslo_messaging as messaging +from oslo_utils import importutils +from smaug.i18n import _LI from smaug import manager +LOG = logging.getLogger(__name__) + +protection_manager_opts = [ + cfg.IntOpt('update_protection_stats_interval', + default=3600, + help='update protection status interval') +] CONF = cfg.CONF - -LOG = logging.getLogger(__name__) +CONF.register_opts(protection_manager_opts) class ProtectionManager(manager.Manager): @@ -36,3 +44,67 @@ class ProtectionManager(manager.Manager): def __init__(self, service_name=None, *args, **kwargs): super(ProtectionManager, self).__init__(*args, **kwargs) + # TODO(wangliuan) more params and use profiler.trace_cls + self.provider_registry = importutils.import_object( + 'smaug.protection.provider.ProviderRegistry') + self.flow_engine = None + # TODO(wangliuan) + + def init_host(self): + """Handle initialization if this is a standalone service""" + # TODO(wangliuan) + LOG.info(_LI("Starting protection service")) + + # TODO(wangliuan) use flow_engine to implement protect function + def protect(self, plan): + """create protection for the given plan + + :param plan: Define that protection plan should be done + """ + # TODO(wangliuan) + pass + + def restore(self, checkpoint, **kwargs): + # TODO(wangliuan) + pass + + def delete(self, plan): + # TODO(wangliuan) + pass + + def start(self, plan): + # TODO(wangliuan) + pass + + def suspend(self, plan): + # TODO(wangliuan) + pass + + def _update_protection_stats(self, plan): + """Update protection stats + + use the loopingcall to update protection status( + interval=CONF.update_protection_stats_interval) + """ + # TODO(wangliuan) + pass + + def list_checkpoints(self, list_options): + # TODO(wangliuan) + pass + + def show_checkpoint(self, checkpoint_id): + # TODO(wangliuan) + pass + + def delete_checkpoint(self, checkpoint_id): + # TODO(wangliuan) + pass + + def list_providers(self, list_option): + # TODO(wangliuan) + pass + + def show_provider(self, provider_id): + # TODO(wangliuan) + pass diff --git a/smaug/protection/protection_plugin.py b/smaug/protection/protection_plugin.py new file mode 100644 index 00000000..4ddeab7c --- /dev/null +++ b/smaug/protection/protection_plugin.py @@ -0,0 +1,69 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +from oslo_config import cfg +from oslo_log import log as logging + + +CONF = cfg.CONF + +LOG = logging.getLogger(__name__) + + +class ProtectionData(object): + def __init__(self): + super(ProtectionData, self).__init__() + self.protection_id = None + self.protection_target = None + self.status = None + # TODO(wangliuan) + + +class ProtectionPlugin(object): + def __init__(self): + super(ProtectionPlugin, self).__init__() + self.protectable_type = None + self.schema = None + # TODO(wangliuan) + + def get_supported_resources_types(self): + # TODO(wangliuan) + pass + + def get_options_schema(self, resource_type): + # TODO(wangliuan) + pass + + def get_saved_info_schema(self, resource_type): + # TODO(wangliuan) + pass + + def get_restore_schema(self, resource_type): + # TODO(wangliuan) + pass + + def get_saved_info(self, metadata_store, resource): + # TODO(wangliuan) + pass + + def get_protection_stats(self, protection_id): + # TODO(wangliuan) + pass + + def on_resource_start(self, context): + # TODO(wangliuan) + pass + + def on_resource_end(self, context): + # TODO(wangliuan) + pass diff --git a/smaug/protection/provider.py b/smaug/protection/provider.py new file mode 100644 index 00000000..545b02e7 --- /dev/null +++ b/smaug/protection/provider.py @@ -0,0 +1,59 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +from oslo_config import cfg +from oslo_log import log as logging + + +CONF = cfg.CONF + +LOG = logging.getLogger(__name__) + + +class PluggableProtectionProvider(object): + def __init__(self): + super(PluggableProtectionProvider, self).__init__() + self._bank_plugin = None + self._plugin_map = {} + self.checkpoint_collection = None + # TODO(wangliuan) + + def _load_plugins(self, cfg_file): + # TODO(wangliuan) + pass + + def get_checkpoint_collection(self): + # TODO(wangliuan) + pass + + def build_task_flow(self, plan): + # TODO(wangliuan) + pass + + +class ProviderRegistry(object): + def __init__(self): + super(ProviderRegistry, self).__init__() + # TODO(wangliuan) + + def load_providers(self, cfg_file): + # TODO(wangliuan) + pass + + def list_providers(self, list_option): + # TODO(wangliuan) + pass + + def show_provider(self, provider_id): + # TODO(wangliuan) + pass diff --git a/smaug/tests/unit/protection/__init__.py b/smaug/tests/unit/protection/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/smaug/tests/unit/protection/fakes.py b/smaug/tests/unit/protection/fakes.py new file mode 100644 index 00000000..47a5795b --- /dev/null +++ b/smaug/tests/unit/protection/fakes.py @@ -0,0 +1,63 @@ +# Copyright 2010 OpenStack Foundation +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +def fake_protection_plan(): + protection_plan = {'id': 'fake_id', + 'is_enabled': True, + 'name': 'fake_protection_plan', + 'comments': '', + 'revision': 0, + 'resources': [], + 'protection_provider': None, + 'parameters': {}, + 'provider_id': 'fake_id' + } + return protection_plan + + +def fake_protection_definitions(): + protection_definitions = [{'plugin_id': 'fake_plugin_id'}] + return protection_definitions + + +class FakeCheckpointManager(object): + def __init__(self): + super(FakeCheckpointManager, self).__init__() + self.fake_checkpoint = None + self.fake_checkpoint_status = None + self.fake_protection_definition = None + + def list_checkpoints(self, list_options): + # TODO(wangliuan) + pass + + def show_checkpoint(self, checkpoint_id): + return 'fake_checkpoint' + + def delete_checkpoint(self, checkpoint_id): + # TODO(wangliuan) + pass + + def create_checkpoint(self, plan): + self.fake_checkpoint = 'fake_checkpoint' + return 'fake_checkpoint' + + def update_checkpoint(self, checkpoint, **kwargs): + status = kwargs.get('status', 'error') + self.fake_checkpoint_status = status + + def update_protection_definition(self, checkpoint, **kwargs): + self.fake_protection_definition = 'fake_definition' diff --git a/smaug/tests/unit/protection/test_manager.py b/smaug/tests/unit/protection/test_manager.py new file mode 100644 index 00000000..8db3f851 --- /dev/null +++ b/smaug/tests/unit/protection/test_manager.py @@ -0,0 +1,23 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +from smaug.protection import manager +from smaug.tests import base +from smaug.tests.unit.protection import fakes + + +class ProtectionServiceTest(base.TestCase): + def setUp(self): + super(ProtectionServiceTest, self).setUp() + self.pro_manager = manager.ProtectionManager() + self.protection_plan = fakes.fake_protection_plan()