From 4e8e5d27148cde9228032a1c1ba5ef4806ba3138 Mon Sep 17 00:00:00 2001 From: Morgan Jones Date: Fri, 2 May 2014 08:40:45 -0700 Subject: [PATCH] Add guestagent API calls for replication Adds API methods for the V1 implementation of replication. Partially implements: blueprint replication-v1 Change-Id: I1814ce0b928e2b7a46c2f45aa4483aa04892bf13 --- trove/guestagent/api.py | 19 +++++++++ .../guestagent/datastore/cassandra/manager.py | 16 ++++++++ .../guestagent/datastore/couchbase/manager.py | 16 ++++++++ trove/guestagent/datastore/mongodb/manager.py | 16 ++++++++ trove/guestagent/datastore/mysql/manager.py | 17 ++++++++ trove/guestagent/datastore/redis/manager.py | 16 ++++++++ trove/tests/unittests/guestagent/test_api.py | 39 +++++++++++++++++++ 7 files changed, 139 insertions(+) diff --git a/trove/guestagent/api.py b/trove/guestagent/api.py index 8b82079444..9dcd80f672 100644 --- a/trove/guestagent/api.py +++ b/trove/guestagent/api.py @@ -318,3 +318,22 @@ class API(proxy.RpcProxy): LOG.debug("Applying overrides on Instance %s", self.id) LOG.debug("Applying overrides values %s" % overrides) self._cast("apply_overrides", overrides=overrides) + + def get_replication_snapshot(self, master_config=None): + LOG.debug("Retrieving replication snapshot from instance %s", self.id) + self._call("get_replication_snapshot", AGENT_HIGH_TIMEOUT, + master_config=master_config) + + def attach_replication_slave(self, snapshot, slave_config=None): + LOG.debug("Configuring instance %s to replicate from %s", + self.id, snapshot.get('master').get('id')) + self._cast("attach_replication_slave", snapshot=snapshot, + slave_config=slave_config) + + def detach_replication_slave(self): + LOG.debug("Detaching slave %s from its master", self.id) + self._call("detach_replication_slave", AGENT_LOW_TIMEOUT) + + def demote_replication_master(self): + LOG.debug("Demoting instance %s to non-master", self.id) + self._call("demote_replication_master", AGENT_LOW_TIMEOUT) diff --git a/trove/guestagent/datastore/cassandra/manager.py b/trove/guestagent/datastore/cassandra/manager.py index a96c1da83a..c135d2a4f4 100644 --- a/trove/guestagent/datastore/cassandra/manager.py +++ b/trove/guestagent/datastore/cassandra/manager.py @@ -174,3 +174,19 @@ class Manager(periodic_task.PeriodicTasks): def apply_overrides(self, context, overrides): raise exception.DatastoreOperationNotSupported( operation='apply_overrides', datastore=MANAGER) + + def get_replication_snapshot(self, master_config): + raise exception.DatastoreOperationNotSupported( + operation='get_replication_snapshot', datastore=MANAGER) + + def attach_replication_slave(self, snapshot, slave_config): + raise exception.DatastoreOperationNotSupported( + operation='attach_replication_slave', datastore=MANAGER) + + def detach_replication_slave(self): + raise exception.DatastoreOperationNotSupported( + operation='detach_replication_slave', datastore=MANAGER) + + def demote_replication_master(self): + raise exception.DatastoreOperationNotSupported( + operation='demote_replication_master', datastore=MANAGER) diff --git a/trove/guestagent/datastore/couchbase/manager.py b/trove/guestagent/datastore/couchbase/manager.py index 51b9cff1dd..dada0886ff 100644 --- a/trove/guestagent/datastore/couchbase/manager.py +++ b/trove/guestagent/datastore/couchbase/manager.py @@ -187,3 +187,19 @@ class Manager(periodic_task.PeriodicTasks): def apply_overrides(self, context, overrides): raise exception.DatastoreOperationNotSupported( operation='apply_overrides', datastore=MANAGER) + + def get_replication_snapshot(self, master_config): + raise exception.DatastoreOperationNotSupported( + operation='get_replication_snapshot', datastore=MANAGER) + + def attach_replication_slave(self, snapshot, slave_config): + raise exception.DatastoreOperationNotSupported( + operation='attach_replication_slave', datastore=MANAGER) + + def detach_replication_slave(self): + raise exception.DatastoreOperationNotSupported( + operation='detach_replication_slave', datastore=MANAGER) + + def demote_replication_master(self): + raise exception.DatastoreOperationNotSupported( + operation='demote_replication_master', datastore=MANAGER) diff --git a/trove/guestagent/datastore/mongodb/manager.py b/trove/guestagent/datastore/mongodb/manager.py index b4b0efd679..4dac81d310 100644 --- a/trove/guestagent/datastore/mongodb/manager.py +++ b/trove/guestagent/datastore/mongodb/manager.py @@ -180,3 +180,19 @@ class Manager(periodic_task.PeriodicTasks): def apply_overrides(self, context, overrides): raise exception.DatastoreOperationNotSupported( operation='apply_overrides', datastore=MANAGER) + + def get_replication_snapshot(self, master_config): + raise exception.DatastoreOperationNotSupported( + operation='get_replication_snapshot', datastore=MANAGER) + + def attach_replication_slave(self, snapshot, slave_config): + raise exception.DatastoreOperationNotSupported( + operation='attach_replication_slave', datastore=MANAGER) + + def detach_replication_slave(self): + raise exception.DatastoreOperationNotSupported( + operation='detach_replication_slave', datastore=MANAGER) + + def demote_replication_master(self): + raise exception.DatastoreOperationNotSupported( + operation='demote_replication_master', datastore=MANAGER) diff --git a/trove/guestagent/datastore/mysql/manager.py b/trove/guestagent/datastore/mysql/manager.py index 762090474a..1b05d82585 100644 --- a/trove/guestagent/datastore/mysql/manager.py +++ b/trove/guestagent/datastore/mysql/manager.py @@ -18,6 +18,7 @@ import os from trove.common import cfg +from trove.common import exception from trove.common import instance as rd_instance from trove.guestagent import dbaas from trove.guestagent import backup @@ -203,3 +204,19 @@ class Manager(periodic_task.PeriodicTasks): def apply_overrides(self, context, overrides): app = MySqlApp(MySqlAppStatus.get()) app.apply_overrides(overrides) + + def get_replication_snapshot(self, master_config): + raise exception.DatastoreOperationNotSupported( + operation='get_replication_snapshot', datastore=MANAGER) + + def attach_replication_slave(self, snapshot, slave_config): + raise exception.DatastoreOperationNotSupported( + operation='attach_replication_slave', datastore=MANAGER) + + def detach_replication_slave(self): + raise exception.DatastoreOperationNotSupported( + operation='detach_replication_slave', datastore=MANAGER) + + def demote_replication_master(self): + raise exception.DatastoreOperationNotSupported( + operation='demote_replication_master', datastore=MANAGER) diff --git a/trove/guestagent/datastore/redis/manager.py b/trove/guestagent/datastore/redis/manager.py index 167381c20f..78892f4dc8 100644 --- a/trove/guestagent/datastore/redis/manager.py +++ b/trove/guestagent/datastore/redis/manager.py @@ -213,3 +213,19 @@ class Manager(periodic_task.PeriodicTasks): def is_root_enabled(self, context): raise exception.DatastoreOperationNotSupported( operation='is_root_enabled', datastore=MANAGER) + + def get_replication_snapshot(self, master_config): + raise exception.DatastoreOperationNotSupported( + operation='get_replication_snapshot', datastore=MANAGER) + + def attach_replication_slave(self, snapshot, slave_config): + raise exception.DatastoreOperationNotSupported( + operation='attach_replication_slave', datastore=MANAGER) + + def detach_replication_slave(self): + raise exception.DatastoreOperationNotSupported( + operation='detach_replication_slave', datastore=MANAGER) + + def demote_replication_master(self): + raise exception.DatastoreOperationNotSupported( + operation='demote_replication_master', datastore=MANAGER) diff --git a/trove/tests/unittests/guestagent/test_api.py b/trove/tests/unittests/guestagent/test_api.py index dce0b89f2b..45553cbad5 100644 --- a/trove/tests/unittests/guestagent/test_api.py +++ b/trove/tests/unittests/guestagent/test_api.py @@ -21,6 +21,11 @@ from trove.guestagent import api import trove.openstack.common.rpc as rpc import trove.common.rpc as trove_rpc +REPLICATION_SNAPSHOT = {'master': {'id': '123', 'host': '192.168.0.1', + 'port': 3306}, + 'dataset': {}, + 'binlog_position': 'binpos'} + def _mock_call_pwd_change(cmd, users=None): if users == 'dummy': @@ -275,6 +280,40 @@ class ApiTest(testtools.TestCase): # verify self._verify_rpc_cast(exp_msg, rpc.cast) + def test_get_replication_snapshot(self): + exp_resp = REPLICATION_SNAPSHOT + rpc.call = mock.Mock(return_value=exp_resp) + exp_msg = RpcMsgMatcher('get_replication_snapshot', 'master_config') + # execute + self.api.get_replication_snapshot() + # verify + self._verify_rpc_call(exp_msg, rpc.call) + + def test_attach_replication_slave(self): + rpc.cast = mock.Mock() + exp_msg = RpcMsgMatcher('attach_replication_slave', + 'snapshot', 'slave_config') + # execute + self.api.attach_replication_slave(REPLICATION_SNAPSHOT) + # verify + self._verify_rpc_cast(exp_msg, rpc.cast) + + def test_detach_replication_slave(self): + rpc.call = mock.Mock() + exp_msg = RpcMsgMatcher('detach_replication_slave') + # execute + self.api.detach_replication_slave() + # verify + self._verify_rpc_call(exp_msg, rpc.call) + + def test_demote_replication_master(self): + rpc.call = mock.Mock() + exp_msg = RpcMsgMatcher('demote_replication_master') + # execute + self.api.demote_replication_master() + # verify + self._verify_rpc_call(exp_msg, rpc.call) + def _verify_rpc_connection_and_cast(self, rpc, mock_conn, exp_msg): rpc.create_connection.assert_called_with(new=True) mock_conn.create_consumer.assert_called_with(