Couchbase Root Password Can Go Out Of Sync

if a user goes to the web console of a couchbase instance and adds
another couchbase instance as a server to create a cluster, the root
password for the second server is replaced with the first server's
password (aka they're synced).

this is problematic because the ping check today relies on the
password in /etc/couchbase/secret_key, which is only set on
prepare(). this means that the status for the second server (and
the third, and etc.) flips to 'shutdown' because the state of the
database cannot be ascertained.

the solution is to retrieve the current password from config.dat if
the status check fails with the stored value in secret_key. if the
password parsed from config.dat works, update the stored value in
secret_key.

Change-Id: Ia39b9c57df88b6784d13d8f3fd86967c7cffa743
Closes-Bug: #1380984
This commit is contained in:
amcrn 2014-10-16 17:35:26 -07:00
parent 101d454b70
commit 3190c0ac5b
2 changed files with 49 additions and 10 deletions

View File

@ -229,19 +229,53 @@ class CouchbaseAppStatus(service.BaseDbStatus):
"""
def _get_actual_db_status(self):
self.ip_address = operating_system.get_ip_address()
pwd = None
try:
pwd = CouchbaseRootAccess.get_password()
out, err = utils.execute_with_timeout(
(system.cmd_couchbase_status %
{'IP': self.ip_address, 'PWD': pwd}),
shell=True)
server_stats = json.loads(out)
if not err and server_stats["clusterMembership"] == "active":
return rd_instance.ServiceStatuses.RUNNING
else:
return rd_instance.ServiceStatuses.SHUTDOWN
return self._get_status_from_couchbase(pwd)
except exception.ProcessExecutionError:
LOG.exception(_("Error getting Couchbase status."))
# log the exception, but continue with native config approach
LOG.exception(_("Error getting the Couchbase status."))
try:
out, err = utils.execute_with_timeout(
system.cmd_get_password_from_config, shell=True)
except exception.ProcessExecutionError:
LOG.exception(_("Error getting the root password from the "
"native Couchbase config file."))
return rd_instance.ServiceStatuses.SHUTDOWN
config_pwd = out.strip() if out is not None else None
if not config_pwd or config_pwd == pwd:
LOG.debug("The root password from the native Couchbase config "
"file is either empty or already matches the "
"stored value.")
return rd_instance.ServiceStatuses.SHUTDOWN
try:
status = self._get_status_from_couchbase(config_pwd)
except exception.ProcessExecutionError:
LOG.exception(_("Error getting Couchbase status using the "
"password parsed from the native Couchbase "
"config file."))
return rd_instance.ServiceStatuses.SHUTDOWN
# if the parsed root password worked, update the stored value to
# avoid having to consult/parse the couchbase config file again.
LOG.debug("Updating the stored value for the Couchbase "
"root password.")
CouchbaseRootAccess().write_password_to_file(config_pwd)
return status
def _get_status_from_couchbase(self, pwd):
out, err = utils.execute_with_timeout(
(system.cmd_couchbase_status %
{'IP': self.ip_address, 'PWD': pwd}),
shell=True)
server_stats = json.loads(out)
if not err and server_stats["clusterMembership"] == "active":
return rd_instance.ServiceStatuses.RUNNING
else:
return rd_instance.ServiceStatuses.SHUTDOWN

View File

@ -42,3 +42,8 @@ cmd_update_sysctl_conf = ('echo "vm.swappiness = 0" | sudo tee -a '
'/etc/sysctl.conf')
cmd_reset_pwd = 'sudo /opt/couchbase/bin/cbreset_password %(IP)s:8091'
pwd_file = COUCHBASE_CONF_DIR + SECRET_KEY
cmd_get_password_from_config = """sudo /opt/couchbase/bin/erl -noinput -eval \
'case file:read_file("/opt/couchbase/var/lib/couchbase/config/config.dat") \
of {ok, B} -> io:format("~p~n", [binary_to_term(B)]) end.' \
-run init stop | grep '\[{"root",\[{password,' | awk -F\\" '{print $4}'
"""