diff --git a/trove/common/cfg.py b/trove/common/cfg.py index 23e5153513..4db72b98f1 100644 --- a/trove/common/cfg.py +++ b/trove/common/cfg.py @@ -988,7 +988,8 @@ mongodb_opts = [ help='Maximum time to wait (in seconds) for a replica set ' 'initialization process to complete.'), cfg.StrOpt('root_controller', - default='trove.extensions.common.service.DefaultRootController', + default='trove.extensions.mongodb.service.' + 'MongoDBRootController', help='Root controller implementation for mongodb.'), cfg.StrOpt('guest_log_exposed_logs', default='', help='List of Guest Logs to expose for publishing.'), diff --git a/trove/extensions/common/service.py b/trove/extensions/common/service.py index 2f18ed2594..8120b48c5f 100644 --- a/trove/extensions/common/service.py +++ b/trove/extensions/common/service.py @@ -129,10 +129,20 @@ class ClusterRootController(DefaultRootController): tenant_id, cluster_id) return self.instance_root_index(req, tenant_id, single_instance_id) + def _block_cluster_instance_actions(self): + return False + + def check_cluster_instance_actions(self, instance_id): + # Check if instance is in a cluster and if actions are allowed + instance = DBInstance.find_by(id=instance_id) + if instance.cluster_id and self._block_cluster_instance_actions(): + raise exception.ClusterInstanceOperationNotSupported() + def root_create(self, req, body, tenant_id, instance_id, is_cluster): if is_cluster: return self.cluster_root_create(req, body, tenant_id, instance_id) else: + self.check_cluster_instance_actions(instance_id) return self.instance_root_create(req, body, instance_id) def instance_root_create(self, req, body, instance_id, diff --git a/trove/extensions/mongodb/__init__.py b/trove/extensions/mongodb/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/trove/extensions/mongodb/service.py b/trove/extensions/mongodb/service.py new file mode 100644 index 0000000000..8900c95366 --- /dev/null +++ b/trove/extensions/mongodb/service.py @@ -0,0 +1,47 @@ +# Copyright 2015 Tesora Inc. +# 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. + +from oslo_log import log as logging + +from trove.common import cfg +from trove.common import exception +from trove.extensions.common.service import ClusterRootController +from trove.instance.models import DBInstance + +LOG = logging.getLogger(__name__) +CONF = cfg.CONF +MANAGER = CONF.datastore_manager if CONF.datastore_manager else 'mongodb' + + +class MongoDBRootController(ClusterRootController): + + def delete(self, req, tenant_id, instance_id): + raise exception.DatastoreOperationNotSupported( + operation='disable_root', datastore=MANAGER) + + def _block_cluster_instance_actions(self): + return True + + def _find_query_router_ids(self, tenant_id, cluster_id): + args = {'tenant_id': tenant_id, 'cluster_id': cluster_id, + 'type': 'query_router'} + query_router_instances = DBInstance.find_all(**args).all() + return [db_instance.id for db_instance in query_router_instances] + + def _get_cluster_instance_id(self, tenant_id, cluster_id): + instance_ids = self._find_cluster_node_ids(tenant_id, cluster_id) + single_instance_id = self._find_query_router_ids(tenant_id, + cluster_id)[0] + return single_instance_id, instance_ids diff --git a/trove/tests/unittests/common/test_common_extensions.py b/trove/tests/unittests/common/test_common_extensions.py index 85491d0f2b..07cc0d6775 100644 --- a/trove/tests/unittests/common/test_common_extensions.py +++ b/trove/tests/unittests/common/test_common_extensions.py @@ -190,14 +190,16 @@ class TestClusterRootController(trove_testtools.TestCase): self.controller.root_create(req, body, tenant_id, uuid, is_cluster) mock_cluster_root_create.assert_called_with(req, body, tenant_id, uuid) + @patch.object(ClusterRootController, "check_cluster_instance_actions") @patch.object(ClusterRootController, "instance_root_create") - def test_root_create_instance(self, mock_instance_root_create): + def test_root_create_instance(self, mock_instance_root_create, mock_check): req = Mock() body = Mock() tenant_id = Mock() uuid = utils.generate_uuid() is_cluster = False self.controller.root_create(req, body, tenant_id, uuid, is_cluster) + mock_check.assert_called_with(uuid) mock_instance_root_create.assert_called_with(req, body, uuid) @patch.object(models.ClusterRoot, "load")