Skip to content

Commit bfe1af4

Browse files
CE-509 REST API implementation for cluster-init
CE-510 REST API implementation for xdcr-setup CE-511 REST API implementation for setting-cluster CE-518 index creation inside scope support CE-519 snapshot fails with backup restore failure CE-520 status check of replication fails in xdcr dsource type CE-521 cluster init fails when couchbase instance is recreated on a machine CE-523 bucket-flush command fix CE-525 server-add command fix VDB creation fix for couchbase version 7.1.3 PR URL: https://www.github.com/delphix/couchbase-plugin/pull/54
1 parent 77ab707 commit bfe1af4

File tree

8 files changed

+445
-116
lines changed

8 files changed

+445
-116
lines changed

src/controller/couchbase_lib/_bucket.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ def monitor_bucket(self, bucket_name, staging_UUID):
214214
while pending_docs != 0:
215215
logger.debug("Documents pending for replication: {}".format(pending_docs))
216216
helper_lib.sleepForSecond(30)
217-
stdout, stderr, exit_code = utilities.execute_bash(self.connection, command, **kwargs)
217+
stdout, stderr, exit_code = utilities.execute_expect(self.connection, command, **kwargs)
218218
content = json.loads(stdout)
219219
pending_docs = self._get_last_value_of_node_stats(list(content["nodeStats"].values())[0])
220220
else:

src/controller/couchbase_lib/_cb_backup.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"""This class contains methods for all cb backup manager.
77
This is child class of Resource and parent class of CouchbaseOperation
88
"""
9+
import json
910
#######################################################################################################################
1011
import logging
1112
from utils import utilities
@@ -61,14 +62,36 @@ def cb_backup_full(self, csv_bucket):
6162
# **env)
6263
# logger.debug("Backup restore: {}".format(cmd))
6364
# utilities.execute_bash(self.connection, cmd, **kwargs)
64-
65+
map_data_list = []
66+
if int(self.repository.version.split(".")[0]) == 7:
67+
for bucket_name in csv_bucket.split(","):
68+
logger.debug(f"bucket_name: {bucket_name}")
69+
stdout, _, _ = self.run_couchbase_command(
70+
couchbase_command='get_scope_list_expect',
71+
base_path=helper_lib.get_base_directory_of_given_path(
72+
self.repository.cb_shell_path),
73+
bucket_name=bucket_name
74+
)
75+
json_scope_data = json.loads(stdout)
76+
for s in json_scope_data["scopes"]:
77+
scope_name = s["name"]
78+
if scope_name == "_default":
79+
continue
80+
collection_list = s["collections"]
81+
for c in collection_list:
82+
collection_name = c["name"]
83+
if collection_name == "_default":
84+
continue
85+
map_data_list.append(f"{bucket_name}.{scope_name}.{collection_name}={bucket_name}.{scope_name}.{collection_name}")
6586

6687
stdout, stderr, exit_code = self.run_couchbase_command(couchbase_command='cb_backup_full',
6788
backup_location=self.parameters.couchbase_bak_loc,
6889
csv_bucket_list=csv_bucket,
6990
backup_repo=self.parameters.couchbase_bak_repo,
7091
skip=skip,
71-
base_path=helper_lib.get_base_directory_of_given_path(self.repository.cb_shell_path)
92+
base_path=helper_lib.get_base_directory_of_given_path(self.repository.cb_shell_path),
93+
map_data=",".join(map_data_list),
94+
repo_version = self.repository.version
7295
)
7396

7497
if exit_code != 0:

src/controller/couchbase_lib/_cluster.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,17 @@ def cluster_init(self):
6969
lambda_expr = lambda output: bool(re.search(ALREADY_CLUSTER_INIT, output))
7070
env = _ClusterMixin.generate_environment_map(self)
7171
env['additional_services'] = additional_service
72-
cmd = CommandFactory.cluster_init(cluster_name=cluster_name, **env)
73-
logger.debug("Cluster init: {}".format(cmd))
74-
stdout, stderr, exit_code = utilities.execute_bash(self.connection, command_name=cmd, callback_func=lambda_expr,
75-
**kwargs)
72+
if int(self.repository.version.split(".")[0]) == 7:
73+
env.update(kwargs[ENV_VAR_KEY])
74+
cmd, env_vars = CommandFactory.cluster_init_rest_expect(cluster_name=cluster_name, **env)
75+
kwargs[ENV_VAR_KEY].update(env_vars)
76+
stdout, stderr, exit_code = utilities.execute_expect(self.connection,
77+
cmd, **kwargs)
78+
else:
79+
cmd = CommandFactory.cluster_init(cluster_name=cluster_name, **env)
80+
logger.debug("Cluster init: {}".format(cmd))
81+
stdout, stderr, exit_code = utilities.execute_bash(self.connection, command_name=cmd, callback_func=lambda_expr,
82+
**kwargs)
7683
if re.search(r"ERROR", str(stdout)):
7784
if re.search(r"ERROR: Cluster is already initialized", stdout):
7885
logger.debug("Performing cluster setting as cluster is already initialized")

src/controller/couchbase_operation.py

Lines changed: 166 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,9 @@ def run_couchbase_command(self, couchbase_command, **kwargs):
117117
"get_indexes_name",
118118
"rename_cluster",
119119
"server_add",
120-
"rebalance"]:
120+
"rebalance",
121+
"get_scope_list_expect",
122+
"change_cluster_password"]:
121123
method_to_call = getattr(CommandFactory, couchbase_command)
122124
command = method_to_call(shell_path=self.repository.cb_shell_path,
123125
install_path=self.repository.cb_install_path,
@@ -131,7 +133,7 @@ def run_couchbase_command(self, couchbase_command, **kwargs):
131133
logger.debug("couchbase command to run: {}".format(command))
132134
stdout, stderr, exit_code = utilities.execute_bash(self.connection, command, environment_vars=env)
133135
else:
134-
couchbase_command = couchbase_command+"_expect"
136+
couchbase_command = couchbase_command+"_expect" if not couchbase_command.endswith("_expect") else couchbase_command
135137
logger.debug('new_couchbase_command: {}'.format(couchbase_command))
136138
method_to_call = getattr(CommandFactory, couchbase_command)
137139
command, env_vars = method_to_call(shell_path=self.repository.cb_shell_path,
@@ -632,17 +634,46 @@ def get_indexes_definition(self):
632634

633635
if self.parameters.d_source_type == constants.CBBKPMGR:
634636
logger.debug("Only build for backup ingestion")
635-
637+
# logger.debug(f"couchbase repository: {self.repository}")
638+
#
639+
# buckets = {}
640+
# for i in indexes_raw['indexes']:
641+
# if i['bucket'] in buckets:
642+
# buckets[i['bucket']].append(i['indexName'])
643+
# else:
644+
# buckets[i['bucket']] = [ i['indexName'] ]
645+
#
646+
# for buc, ind in buckets.items():
647+
# ind_def = 'build index on `{}` (`{}`)'.format(buc, '`,`'.join(ind))
648+
# indexes.append(ind_def)
636649
buckets = {}
637650
for i in indexes_raw['indexes']:
638-
if i['bucket'] in buckets:
639-
buckets[i['bucket']].append(i['indexName'])
640-
else:
641-
buckets[i['bucket']] = [ i['indexName'] ]
642-
643-
for buc, ind in buckets.items():
644-
ind_def = 'build index on `{}` (`{}`)'.format(buc, '`,`'.join(ind))
645-
indexes.append(ind_def)
651+
bucket_name = i['bucket']
652+
index_name = i['indexName']
653+
scope_name = i['scope'] if 'scope' in i.keys() else '_default'
654+
collection_name = i[
655+
'collection'] if 'collection' in i.keys() else '_default'
656+
657+
if bucket_name not in buckets:
658+
buckets[bucket_name] = {}
659+
if scope_name not in buckets[bucket_name].keys():
660+
buckets[bucket_name][scope_name] = {}
661+
if collection_name not in buckets[bucket_name][
662+
scope_name].keys():
663+
buckets[bucket_name][scope_name][collection_name] = []
664+
665+
buckets[bucket_name][scope_name][collection_name].append(
666+
index_name)
667+
668+
for bucket_name in buckets.keys():
669+
for scope_name in buckets[bucket_name].keys():
670+
for collection_name in buckets[bucket_name][scope_name].keys():
671+
ind = buckets[bucket_name][scope_name][collection_name]
672+
if collection_name == "_default" and scope_name == "_default":
673+
ind_def = f'build index on `{bucket_name}` (`{"`,`".join(ind)}`)'
674+
else:
675+
ind_def = f'build index on `{bucket_name}`.{scope_name}.{collection_name} (`{"`,`".join(ind)}`)'
676+
indexes.append(ind_def)
646677

647678
else:
648679
# full definition for replication
@@ -716,14 +747,23 @@ def save_config(self, what, nodeno=1):
716747
target_local_filename = os.path.join(targetdir,"local.ini_{}".format(nodeno))
717748
target_encryption_filename = os.path.join(targetdir,"encrypted_data_keys_{}".format(nodeno))
718749

719-
if nodeno == 1:
750+
if nodeno == 1 or int(self.repository.version.split(".")[0]) == 7:
720751
ip_file = "{}/../var/lib/couchbase/ip".format(helper_lib.get_base_directory_of_given_path(self.repository.cb_shell_path))
721752
target_ip_filename = os.path.join(targetdir,"ip_{}".format(nodeno))
753+
output, err, exit_code = self.run_os_command(
754+
os_command='check_file',
755+
file_path=ip_file
756+
)
757+
if exit_code != 0 and "Found" not in output:
758+
ip_file = "{}/../var/lib/couchbase/ip_start".format(
759+
helper_lib.get_base_directory_of_given_path(
760+
self.repository.cb_shell_path))
761+
target_ip_filename = os.path.join(targetdir,
762+
"ip_start_{}".format(nodeno))
722763
else:
723764
ip_file = "{}/../var/lib/couchbase/ip_start".format(helper_lib.get_base_directory_of_given_path(self.repository.cb_shell_path))
724765
target_ip_filename = os.path.join(targetdir,"ip_start_{}".format(nodeno))
725766

726-
727767
filename = "{}/../var/lib/couchbase/config/config.dat".format(helper_lib.get_base_directory_of_given_path(self.repository.cb_shell_path))
728768

729769
command_output, std_err, exit_code = self.run_os_command(
@@ -790,6 +830,22 @@ def save_config(self, what, nodeno=1):
790830
if exit_code != 0:
791831
raise UserError("Error saving configuration file: local.ini", "Check sudo or user privileges to read Couchbase local.ini file", std_err)
792832

833+
if int(self.repository.version.split(".")[0]) == 7:
834+
chronicle_target_dir = os.path.join(targetdir, f"chronicle_{nodeno}")
835+
command_output, std_err, exit_code = self.run_os_command(
836+
os_command='check_directory',
837+
dir_path=chronicle_target_dir
838+
)
839+
if exit_code == 0 and "Found" in command_output:
840+
command_output, std_err, exit_code = self.run_os_command(
841+
os_command='delete_dir',
842+
dirname=chronicle_target_dir
843+
)
844+
command_output, std_err, exit_code = self.run_os_command(
845+
os_command="os_cpr",
846+
srcname="{}/../var/lib/couchbase/config/chronicle".format(helper_lib.get_base_directory_of_given_path(self.repository.cb_shell_path)),
847+
trgname=chronicle_target_dir
848+
)
793849

794850

795851
def check_cluster_notconfigured(self):
@@ -831,7 +887,54 @@ def check_config(self):
831887
if exit_code == 0 and "Found" in command_output:
832888
return True
833889
else:
834-
return False
890+
return False
891+
892+
def delete_data_folder(self, nodeno=1):
893+
data_folder = "{}/data_{}".format(self.parameters.mount_path, nodeno)
894+
command_output, command_stderr, command_exit_code = self.run_os_command(
895+
os_command="check_directory",
896+
dir_path=data_folder
897+
)
898+
logger.debug(f"check data directory >> command_output=={command_output}"
899+
f" , command_stderr=={command_stderr} , "
900+
f"command_exit_code=={command_exit_code}")
901+
if command_output == "Found":
902+
command_output, command_stderr, command_exit_code = self.run_os_command(
903+
os_command="delete_dir",
904+
dirname=data_folder
905+
)
906+
907+
def delete_config_folder(self):
908+
if int(self.repository.version.split(".")[0]) == 7:
909+
config_directory_path = "{}/../var/lib/couchbase/config".format(
910+
helper_lib.get_base_directory_of_given_path(
911+
self.repository.cb_shell_path))
912+
command_output, command_stderr, command_exit_code = self.run_os_command(
913+
os_command="check_directory",
914+
dir_path=config_directory_path
915+
)
916+
logger.debug(f"check directory >> command_output=={command_output}"
917+
f" , command_stderr=={command_stderr} , "
918+
f"command_exit_code=={command_exit_code}")
919+
if command_output == "Found":
920+
target_folder = f"{config_directory_path}_bkp"
921+
command_output, command_stderr, command_exit_code = self.run_os_command(
922+
os_command="check_directory",
923+
dir_path=target_folder
924+
)
925+
if command_output == "Found":
926+
command_output, command_stderr, command_exit_code = self.run_os_command(
927+
os_command="delete_dir",
928+
dirname=target_folder
929+
)
930+
command_output, command_stderr, command_exit_code = self.run_os_command(
931+
os_command='os_mv',
932+
srcname=config_directory_path,
933+
trgname=target_folder
934+
)
935+
logger.debug(f"mv directory >> command_output=={command_output}"
936+
f" , command_stderr=={command_stderr} , "
937+
f"command_exit_code=={command_exit_code}")
835938

836939
def restore_config(self, what, nodeno=1):
837940

@@ -931,6 +1034,28 @@ def restore_config(self, what, nodeno=1):
9311034

9321035
logger.debug("local.ini restore - exit_code: {} stdout: {} std_err: {}".format(exit_code, command_output, std_err))
9331036

1037+
if int(self.repository.version.split(".")[0]) == 7:
1038+
source_chronicle_dirname = os.path.join(sourcedir, "chronicle_{}".format(nodeno))
1039+
target_chronicle_dirname = "{}/../var/lib/couchbase/config/chronicle".format(helper_lib.get_base_directory_of_given_path(self.repository.cb_shell_path))
1040+
command_output, std_err, exit_code = self.run_os_command(
1041+
os_command='check_directory',
1042+
dir_path=target_chronicle_dirname
1043+
)
1044+
if exit_code == 0 and "Found" in command_output:
1045+
command_output, std_err, exit_code = self.run_os_command(
1046+
os_command='delete_dir',
1047+
dirname=target_chronicle_dirname
1048+
)
1049+
command_output, std_err, exit_code = self.run_os_command(
1050+
os_command='os_cpr',
1051+
srcname=source_chronicle_dirname,
1052+
trgname=target_chronicle_dirname
1053+
)
1054+
1055+
logger.debug(
1056+
"chronicle restore - exit_code: {} stdout: {} std_err: {}".format(
1057+
exit_code, command_output, std_err))
1058+
9341059
if what == 'parent':
9351060
#local.ini needs to have a proper entry
9361061
filename = "{}/../etc/couchdb/local.ini".format(helper_lib.get_base_directory_of_given_path(self.repository.cb_shell_path))
@@ -989,6 +1114,12 @@ def delete_config(self):
9891114

9901115
logger.debug("fix local.ini permission - exit_code: {} stdout: {} std_err: {}".format(exit_code, command_output, std_err))
9911116

1117+
chronicle_dir_name = "{}/../var/lib/couchbase/config/chronicle".format(helper_lib.get_base_directory_of_given_path(self.repository.cb_shell_path))
1118+
command_output, std_err, exit_code = self.run_os_command(
1119+
os_command='delete_dir',
1120+
dirname=chronicle_dir_name
1121+
)
1122+
9921123
def ignore_err(self, input):
9931124
return True
9941125

@@ -998,14 +1129,28 @@ def rename_cluster(self):
9981129

9991130
logger.debug("start rename_cluster")
10001131

1132+
# command_output, std_err, exit_code = self.run_couchbase_command(
1133+
# couchbase_command='rename_cluster',
1134+
# username=self.snapshot.couchbase_admin,
1135+
# password=self.snapshot.couchbase_admin_password,
1136+
# newuser=self.parameters.couchbase_admin,
1137+
# newpass=self.parameters.couchbase_admin_password,
1138+
# newname=self.parameters.tgt_cluster_name
1139+
# )
10011140
command_output, std_err, exit_code = self.run_couchbase_command(
1002-
couchbase_command='rename_cluster',
1003-
username=self.snapshot.couchbase_admin,
1004-
password=self.snapshot.couchbase_admin_password,
1005-
newuser=self.parameters.couchbase_admin,
1006-
newpass=self.parameters.couchbase_admin_password,
1007-
newname=self.parameters.tgt_cluster_name
1008-
)
1141+
couchbase_command='rename_cluster',
1142+
username=self.snapshot.couchbase_admin,
1143+
password=self.snapshot.couchbase_admin_password,
1144+
newname=self.parameters.tgt_cluster_name
1145+
)
1146+
command_output, std_err, exit_code = self.run_couchbase_command(
1147+
couchbase_command='change_cluster_password',
1148+
username=self.snapshot.couchbase_admin,
1149+
password=self.snapshot.couchbase_admin_password,
1150+
newuser=self.parameters.couchbase_admin,
1151+
newpass=self.parameters.couchbase_admin_password
1152+
)
1153+
10091154

10101155
logger.debug("rename cluster - exit_code: {} stdout: {} std_err: {}".format(exit_code, command_output, std_err))
10111156

0 commit comments

Comments
 (0)