Add MongoDB cluster root-enable support
Root access is needed to be able to shrink MongoDB clusters that have role-based access control enabled. Without it, shrink isn't possible. Following the approach implemented for Vertica, add an extension for MongoDB root management. Also include an optional guard against running root-enable against individual cluster instances. Change-Id: I1a3b221ecf575b0389e871fb246d5cd633abc56f Closes-bug: #1554659
This commit is contained in:
+2
-1
@@ -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.'),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user