diff --git a/src/controller/couchbase_lib/_bucket.py b/src/controller/couchbase_lib/_bucket.py index 91cbbf4..7bf0b0a 100644 --- a/src/controller/couchbase_lib/_bucket.py +++ b/src/controller/couchbase_lib/_bucket.py @@ -39,10 +39,14 @@ def bucket_edit(self, bucket_name, flush_value=1): logger.debug("Editing bucket: {} ".format(bucket_name)) self.__validate_bucket_name(bucket_name) env = _BucketMixin.generate_environment_map(self) - command = CommandFactory.bucket_edit(bucket_name=bucket_name, flush_value=flush_value, **env) - kwargs = {ENV_VAR_KEY: {'password': self.parameters.couchbase_admin_password}} + kwargs = {ENV_VAR_KEY: { + 'password': self.parameters.couchbase_admin_password}} + env.update(kwargs[ENV_VAR_KEY]) + # command = CommandFactory.bucket_edit(bucket_name=bucket_name, flush_value=flush_value, **env) + command, env_vars = CommandFactory.bucket_edit_expect(bucket_name=bucket_name, flush_value=flush_value, **env) + kwargs[ENV_VAR_KEY].update(env_vars) logger.debug("edit bucket {}".format(command)) - return utilities.execute_bash(self.connection, command, **kwargs) + return utilities.execute_expect(self.connection, command, **kwargs) def bucket_edit_ramquota(self, bucket_name, _ramsize): """ @@ -53,31 +57,45 @@ def bucket_edit_ramquota(self, bucket_name, _ramsize): # It requires the before bucket delete logger.debug("Editing bucket: {} ".format(bucket_name)) self.__validate_bucket_name(bucket_name) + kwargs = {ENV_VAR_KEY: { + 'password': self.parameters.couchbase_admin_password}} env = _BucketMixin.generate_environment_map(self) - command = CommandFactory.bucket_edit_ramquota(bucket_name=bucket_name, ramsize=_ramsize, **env) - kwargs = {ENV_VAR_KEY: {'password': self.parameters.couchbase_admin_password}} + env.update(kwargs[ENV_VAR_KEY]) + # command = CommandFactory.bucket_edit_ramquota(bucket_name=bucket_name, ramsize=_ramsize, **env) + command, env_vars = CommandFactory.bucket_edit_ramquota_expect(bucket_name=bucket_name, + ramsize=_ramsize, **env) + kwargs[ENV_VAR_KEY].update(env_vars) logger.debug("edit ram bucket {}".format(command)) - return utilities.execute_bash(self.connection, command, **kwargs) + return utilities.execute_expect(self.connection, command, **kwargs) def bucket_delete(self, bucket_name): # To delete the bucket logger.debug("Deleting bucket: {} ".format(bucket_name)) self.__validate_bucket_name(bucket_name) env = _BucketMixin.generate_environment_map(self) - command = CommandFactory.bucket_delete(bucket_name=bucket_name, **env) - kwargs = {ENV_VAR_KEY: {'password': self.parameters.couchbase_admin_password}} + kwargs = {ENV_VAR_KEY: { + 'password': self.parameters.couchbase_admin_password}} + env.update(kwargs[ENV_VAR_KEY]) + # command = CommandFactory.bucket_delete(bucket_name=bucket_name, **env) + command, env_vars = CommandFactory.bucket_delete_expect(bucket_name=bucket_name, **env) + kwargs[ENV_VAR_KEY].update(env_vars) logger.debug("delete bucket {}".format(command)) - return utilities.execute_bash(self.connection, command, **kwargs) + return utilities.execute_expect(self.connection, command, **kwargs) def bucket_flush(self, bucket_name): # It requires the before bucket delete logger.debug("Flushing bucket: {} ".format(bucket_name)) self.__validate_bucket_name(bucket_name) env = _BucketMixin.generate_environment_map(self) - command = CommandFactory.bucket_flush(bucket_name=bucket_name, **env) - kwargs = {ENV_VAR_KEY: {'password': self.parameters.couchbase_admin_password}} + kwargs = {ENV_VAR_KEY: { + 'password': self.parameters.couchbase_admin_password}} + env.update(kwargs[ENV_VAR_KEY]) + # command, env_vars = CommandFactory.bucket_flush(bucket_name=bucket_name, **env) + command, env_vars = CommandFactory.bucket_flush_expect( + bucket_name=bucket_name, **env) + kwargs[ENV_VAR_KEY].update(env_vars) logger.debug("flush bucket {}".format(command)) - return utilities.execute_bash(self.connection, command, **kwargs) + return utilities.execute_expect(self.connection, command, **kwargs) def bucket_remove(self, bucket_name): logger.debug("Removing bucket: {} ".format(bucket_name)) @@ -107,10 +125,14 @@ def bucket_create(self, bucket_name, ram_size, bucket_type, bucket_compression): policy = self.parameters.bucket_eviction_policy env = _BucketMixin.generate_environment_map(self) - command = CommandFactory.bucket_create(bucket_name=bucket_name, ramsize=ram_size, evictionpolicy=policy, bucket_type=bucket_type, bucket_compression=bucket_compression, **env) - kwargs = {ENV_VAR_KEY: {'password': self.parameters.couchbase_admin_password}} + kwargs = {ENV_VAR_KEY: { + 'password': self.parameters.couchbase_admin_password}} + env.update(kwargs[ENV_VAR_KEY]) + # command = CommandFactory.bucket_create(bucket_name=bucket_name, ramsize=ram_size, evictionpolicy=policy, bucket_type=bucket_type, bucket_compression=bucket_compression, **env) + command, env_vars = CommandFactory.bucket_create_expect(bucket_name=bucket_name, ramsize=ram_size, evictionpolicy=policy, bucket_type=bucket_type, bucket_compression=bucket_compression, **env) logger.debug("create bucket {}".format(command)) - output, error, exit_code = utilities.execute_bash(self.connection, command, **kwargs) + kwargs[ENV_VAR_KEY].update(env_vars) + output, error, exit_code = utilities.execute_expect(self.connection, command, **kwargs) logger.debug("create bucket output: {} {} {}".format(output, error, exit_code)) helper_lib.sleepForSecond(2) @@ -120,10 +142,17 @@ def bucket_list(self, return_type=list): # It will return also other information like ramused, ramsize etc logger.debug("Finding staged bucket list") env = _BucketMixin.generate_environment_map(self) - command = CommandFactory.bucket_list(**env) - kwargs = {ENV_VAR_KEY: {'password': self.parameters.couchbase_admin_password}} + kwargs = {ENV_VAR_KEY: { + 'password': self.parameters.couchbase_admin_password}} + env.update(kwargs[ENV_VAR_KEY]) + # command = CommandFactory.bucket_list(**env) + command, env_vars = CommandFactory.bucket_list_expect(**env) + kwargs[ENV_VAR_KEY].update(env_vars) logger.debug("list bucket {}".format(command)) - bucket_list, error, exit_code = utilities.execute_bash(self.connection, command, **kwargs) + # bucket_list, error, exit_code = utilities.execute_bash(self.connection, command, **kwargs) + bucket_list, error, exit_code = utilities.execute_expect(self.connection, + command, + **kwargs) logger.debug("list bucket output{}".format(bucket_list)) if return_type == list: #bucket_list = bucket_list.split("\n") @@ -143,7 +172,6 @@ def bucket_list(self, return_type=list): logger.debug("Bucket details in staged environment: {}".format(bucket_list)) return bucket_list_dict - def move_bucket(self, bucket_name, direction): logger.debug("Rename folder") @@ -172,11 +200,14 @@ def monitor_bucket(self, bucket_name, staging_UUID): # To monitor the replication logger.debug("Monitoring the replication for bucket {} ".format(bucket_name)) kwargs = {ENV_VAR_KEY: {'password': self.staged_source.parameters.xdcr_admin_password}} - command = CommandFactory.monitor_replication(source_username=self.staged_source.parameters.xdcr_admin, + env = kwargs[ENV_VAR_KEY] + command, env_vars = CommandFactory.monitor_replication_expect(source_username=self.staged_source.parameters.xdcr_admin, source_hostname=self.source_config.couchbase_src_host, source_port=self.source_config.couchbase_src_port, - bucket_name=bucket_name, uuid=staging_UUID) - stdout, stderr, exit_code = utilities.execute_bash(self.connection, command, **kwargs) + bucket_name=bucket_name, uuid=staging_UUID, + **env) + kwargs[ENV_VAR_KEY].update(env_vars) + stdout, stderr, exit_code = utilities.execute_expect(self.connection, command, **kwargs) logger.debug("stdout: {}".format(stdout)) content = json.loads(stdout) pending_docs = self._get_last_value_of_node_stats(list(content["nodeStats"].values())[0]) diff --git a/src/controller/couchbase_lib/_cluster.py b/src/controller/couchbase_lib/_cluster.py index d105d89..adb8803 100644 --- a/src/controller/couchbase_lib/_cluster.py +++ b/src/controller/couchbase_lib/_cluster.py @@ -92,8 +92,13 @@ def cluster_setting(self): kwargs = {ENV_VAR_KEY: {'password': self.parameters.couchbase_admin_password}} cluster_name = self._get_cluster_name() env = _ClusterMixin.generate_environment_map(self) - cmd = CommandFactory.cluster_setting(cluster_name=cluster_name, **env) - stdout, stderr, exit_code = utilities.execute_bash(self.connection, cmd, **kwargs) + env.update(kwargs[ENV_VAR_KEY]) + # cmd = CommandFactory.cluster_setting(cluster_name=cluster_name, **env) + cmd, env_vars = CommandFactory.cluster_setting_expect(cluster_name=cluster_name, **env) + # stdout, stderr, exit_code = utilities.execute_bash(self.connection, cmd, **kwargs) + kwargs[ENV_VAR_KEY].update(env_vars) + stdout, stderr, exit_code = utilities.execute_expect(self.connection, + cmd, **kwargs) if re.search(r"ERROR", str(stdout)): logger.error("Cluster modification failed, killing the execution") raise Exception(stdout) diff --git a/src/controller/couchbase_lib/_xdcr.py b/src/controller/couchbase_lib/_xdcr.py index e007951..fd78c75 100644 --- a/src/controller/couchbase_lib/_xdcr.py +++ b/src/controller/couchbase_lib/_xdcr.py @@ -40,12 +40,20 @@ def generate_environment_map(self): return env def xdcr_delete(self, cluster_name): - logger.debug("XDCR deletion for cluster_name {} has started ".format(cluster_name)) - kwargs = {ENV_VAR_KEY: {'source_password': self.parameters.xdcr_admin_password, - 'password': self.parameters.couchbase_admin_password}} + logger.debug("XDCR deletion for cluster_name {} has started ".format( + cluster_name)) + kwargs = {ENV_VAR_KEY: { + 'source_password': self.parameters.xdcr_admin_password, + 'password': self.parameters.couchbase_admin_password}} env = _XDCrMixin.generate_environment_map(self) - cmd = CommandFactory.xdcr_delete(cluster_name=cluster_name, **env) - stdout, stderr, exit_code = utilities.execute_bash(self.connection, cmd, **kwargs) + env.update(kwargs[ENV_VAR_KEY]) + # cmd = CommandFactory.xdcr_delete(cluster_name=cluster_name, **env) + cmd, env_vars = CommandFactory.xdcr_delete_expect( + cluster_name=cluster_name, **env) + kwargs[ENV_VAR_KEY].update(env_vars) + # stdout, stderr, exit_code = utilities.execute_bash(self.connection, cmd, **kwargs) + stdout, stderr, exit_code = utilities.execute_expect(self.connection, + cmd, **kwargs) if exit_code != 0: logger.error("XDCR Setup deletion failed") if stdout: @@ -61,8 +69,11 @@ def xdcr_setup(self): kwargs = {ENV_VAR_KEY: {'source_password': self.parameters.xdcr_admin_password, 'password': self.parameters.couchbase_admin_password}} env = _XDCrMixin.generate_environment_map(self) - cmd = CommandFactory.xdcr_setup(cluster_name=self.parameters.stg_cluster_name, **env) - stdout, stderr, exit_code = utilities.execute_bash(self.connection, cmd, **kwargs) + env.update(kwargs[ENV_VAR_KEY]) + # cmd = CommandFactory.xdcr_setup(cluster_name=self.parameters.stg_cluster_name, **env) + cmd, env_vars = CommandFactory.xdcr_setup_expect(cluster_name=self.parameters.stg_cluster_name, **env) + kwargs[ENV_VAR_KEY].update(env_vars) + stdout, stderr, exit_code = utilities.execute_expect(self.connection, cmd, **kwargs) helper_lib.sleepForSecond(3) def xdcr_replicate(self, src, tgt): @@ -70,9 +81,17 @@ def xdcr_replicate(self, src, tgt): logger.debug("Started XDCR replication for bucket {}".format(src)) kwargs = {ENV_VAR_KEY: {'source_password': self.parameters.xdcr_admin_password}} env = _XDCrMixin.generate_environment_map(self) - cmd = CommandFactory.xdcr_replicate(source_bucket_name=src, target_bucket_name=tgt, - cluster_name=self.parameters.stg_cluster_name, **env) - stdout, stderr, exit_code = utilities.execute_bash(self.connection, cmd, **kwargs) + env.update(kwargs[ENV_VAR_KEY]) + # cmd = CommandFactory.xdcr_replicate(source_bucket_name=src, target_bucket_name=tgt, + # cluster_name=self.parameters.stg_cluster_name, **env) + cmd, env_vars = CommandFactory.xdcr_replicate_expect( + source_bucket_name=src, + target_bucket_name=tgt, + cluster_name=self.parameters.stg_cluster_name, + **env + ) + kwargs[ENV_VAR_KEY].update(env_vars) + stdout, stderr, exit_code = utilities.execute_expect(self.connection, cmd, **kwargs) if exit_code != 0: logger.debug("XDCR replication create failed") raise Exception(stdout) diff --git a/src/controller/couchbase_operation.py b/src/controller/couchbase_operation.py index ed16299..0d10b4a 100644 --- a/src/controller/couchbase_operation.py +++ b/src/controller/couchbase_operation.py @@ -73,14 +73,14 @@ def uid(self): def gid(self): return self.__gid - def run_couchbase_command(self, couchbase_command, **kwargs): logger.debug('run_couchbase_command') logger.debug('couchbase_command: {}'.format(couchbase_command)) if "password" in kwargs: - password = kwargs.pop('password') + password = kwargs.get('password') else: password = self.parameters.couchbase_admin_password + kwargs["password"] = password if "username" in kwargs: username = kwargs.pop('username') @@ -99,14 +99,27 @@ def run_couchbase_command(self, couchbase_command, **kwargs): env["newpass"] = kwargs.pop('newpass') if "source_password" in kwargs: - env["source_password"] = kwargs.pop('source_password') + env["source_password"] = kwargs.get('source_password') autoparams = [ "shell_path", "install_path", "username", "port", "sudo", "uid", "hostname"] new_kwargs = {k: v for k, v in kwargs.items() if k not in autoparams} - - method_to_call = getattr(CommandFactory, couchbase_command) - command = method_to_call(shell_path=self.repository.cb_shell_path, + if couchbase_command not in ["get_server_list", + "couchbase_server_info", + "cb_backup_full", + "build_index", + "check_index_build", + "get_source_bucket_list", + "get_replication_uuid", + "get_stream_id", + "delete_replication", + "node_init", + "get_indexes_name", + "rename_cluster", + "server_add", + "rebalance"]: + method_to_call = getattr(CommandFactory, couchbase_command) + command = method_to_call(shell_path=self.repository.cb_shell_path, install_path=self.repository.cb_install_path, username=username, port=self.parameters.couchbase_port, @@ -115,8 +128,26 @@ def run_couchbase_command(self, couchbase_command, **kwargs): hostname=hostname, **new_kwargs) - logger.debug("couchbase command to run: {}".format(command)) - stdout, stderr, exit_code = utilities.execute_bash(self.connection, command, environment_vars=env) + logger.debug("couchbase command to run: {}".format(command)) + stdout, stderr, exit_code = utilities.execute_bash(self.connection, command, environment_vars=env) + else: + couchbase_command = couchbase_command+"_expect" + logger.debug('new_couchbase_command: {}'.format(couchbase_command)) + method_to_call = getattr(CommandFactory, couchbase_command) + command, env_vars = method_to_call(shell_path=self.repository.cb_shell_path, + install_path=self.repository.cb_install_path, + username=username, + port=self.parameters.couchbase_port, + sudo=self.need_sudo, + uid=self.uid, + hostname=hostname, + **new_kwargs + ) + env.update(env_vars) + logger.debug("couchbase command to run: {}".format(command)) + stdout, stderr, exit_code = utilities.execute_expect(self.connection, + command, + environment_vars=env) return [stdout, stderr, exit_code] @@ -337,7 +368,7 @@ def status(self, provision=False): except Exception as error: # TODO - # rewrite it + # rewrite it logger.debug("Exception: {}".format(str(error))) if re.search("Unable to connect to host at", str(error)): logger.debug("Couchbase service is not running") diff --git a/src/db_commands/commands.py b/src/db_commands/commands.py index bd7a298..cf4a742 100644 --- a/src/db_commands/commands.py +++ b/src/db_commands/commands.py @@ -163,6 +163,25 @@ class DatabaseCommand(object): def __init__(self): pass + @staticmethod + def get_parent_expect_block(): + exp_block = """ + set timeout 10 + match_max -d 50000 + log_user 0 + {command_specific_operations} + lassign [wait] pid spawnid os_error_flag value + + if {{$os_error_flag == 0}} {{ + puts "DLPX_EXPECT_EXIT_CODE: $value" + }} else {{ + puts "errno: $value" + }} + set output $expect_out(buffer) + puts $output + """ + return exp_block + @staticmethod def start_couchbase(install_path, sudo=False, uid=None, **kwargs): if sudo: @@ -246,6 +265,41 @@ def cluster_setting(shell_path, hostname, port, username, cluster_ramsize, clust # ) + @staticmethod + def cluster_setting_expect(shell_path, hostname, port, username, cluster_ramsize, + cluster_name, cluster_index_ramsize, + cluster_fts_ramsize, cluster_eventing_ramsize, + cluster_analytics_ramsize, **kwargs): + command = f"{shell_path} setting-cluster -c {hostname}:{port} -u {username} --password --cluster-ramsize {cluster_ramsize} --cluster-name {cluster_name} --cluster-index-ramsize {cluster_index_ramsize} --cluster-fts-ramsize {cluster_fts_ramsize} --cluster-eventing-ramsize {cluster_eventing_ramsize} --cluster-analytics-ramsize {cluster_analytics_ramsize}" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + + # @staticmethod + # def cluster_check(shell_path, hostname, port, username, **kwargs): + # return "{shell_path} server-list --cluster {hostname}:{port} --username {username} --password $password".format( + # shell_path=shell_path, + # hostname=hostname, + # port=port, + # username=username + # ) + + @staticmethod def xdcr_setup(shell_path, source_hostname, source_port, source_username, hostname, port, username, cluster_name, **kwargs): return "{shell_path} xdcr-setup --cluster {source_hostname}:{source_port} --username {source_username} --password $source_password --create --xdcr-hostname {hostname}:{port} --xdcr-username {username} --xdcr-password $password --xdcr-cluster-name {cluster_name}".format( @@ -259,6 +313,31 @@ def xdcr_setup(shell_path, source_hostname, source_port, source_username, hostna cluster_name=cluster_name ) + @staticmethod + def xdcr_setup_expect(shell_path, source_hostname, source_port, source_username, + hostname, port, username, cluster_name, **kwargs): + command = f"{shell_path} xdcr-setup --cluster {source_hostname}:{source_port} --username {source_username} --password --create --xdcr-hostname {hostname}:{port} --xdcr-username {username} --xdcr-cluster-name {cluster_name} --xdcr-password" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""set env(CMD) "${env(CB_CMD)} ${env(XDCR_PWD)}" + eval spawn ${env(CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "XDCR_PWD": kwargs.get("password"), + "CB_PWD": kwargs.get("source_password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def xdcr_replicate(shell_path, source_hostname, source_port, source_username, source_bucket_name, target_bucket_name, cluster_name, hostname, port, username, **kwargs): return "{shell_path} xdcr-replicate --cluster {source_hostname}:{source_port} --username {source_username} --password $source_password --create --xdcr-from-bucket {source_bucket_name} --xdcr-to-bucket {target_bucket_name} --xdcr-cluster-name {cluster_name}".format( @@ -271,6 +350,31 @@ def xdcr_replicate(shell_path, source_hostname, source_port, source_username, so cluster_name=cluster_name ) + @staticmethod + def xdcr_replicate_expect(shell_path, source_hostname, source_port, + source_username, source_bucket_name, + target_bucket_name, cluster_name, hostname, port, + username, **kwargs): + command = f"{shell_path} xdcr-replicate --cluster {source_hostname}:{source_port} --username {source_username} --password --create --xdcr-from-bucket {source_bucket_name} --xdcr-to-bucket {target_bucket_name} --xdcr-cluster-name {cluster_name}" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("source_password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def get_replication_uuid(shell_path, source_hostname, source_port, source_username, **kwargs): return "{shell_path} xdcr-setup --cluster {source_hostname}:{source_port} --username {source_username} --password $source_password --list".format( @@ -284,6 +388,29 @@ def get_replication_uuid(shell_path, source_hostname, source_port, source_userna + @staticmethod + def get_replication_uuid_expect(shell_path, source_hostname, source_port, + source_username, **kwargs): + command = f"{shell_path} xdcr-setup --cluster {source_hostname}:{source_port} --username {source_username} --password --list" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("source_password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def get_stream_id(shell_path, source_hostname, source_port, source_username, cluster_name, **kwargs): return "{shell_path} xdcr-replicate --cluster {source_hostname}:{source_port} --username {source_username} --password $source_password --xdcr-cluster-name {cluster_name} --list".format( @@ -294,6 +421,29 @@ def get_stream_id(shell_path, source_hostname, source_port, source_username, clu cluster_name=cluster_name ) + @staticmethod + def get_stream_id_expect(shell_path, source_hostname, source_port, + source_username, cluster_name, **kwargs): + command = f"{shell_path} xdcr-replicate --cluster {source_hostname}:{source_port} --username {source_username} --password --xdcr-cluster-name {cluster_name} --list" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("source_password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def pause_replication(shell_path, source_hostname, source_port, source_username, cluster_name, id, **kwargs): return "{shell_path} xdcr-replicate --cluster {source_hostname}:{source_port} --username {source_username} --password $source_password --xdcr-cluster-name {cluster_name} --pause --xdcr-replicator={id}".format( @@ -305,6 +455,29 @@ def pause_replication(shell_path, source_hostname, source_port, source_username, id=id ) + @staticmethod + def pause_replication_expect(shell_path, source_hostname, source_port, + source_username, cluster_name, id, **kwargs): + command = f"{shell_path} xdcr-replicate --cluster {source_hostname}:{source_port} --username {source_username} --password --xdcr-cluster-name {cluster_name} --pause --xdcr-replicator={id}" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("source_password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def resume_replication(shell_path, source_hostname, source_port, source_username, cluster_name, id, **kwargs): return "{shell_path} xdcr-replicate --cluster {source_hostname}:{source_port} --username {source_username} --password $source_password --xdcr-cluster-name {cluster_name} --resume --xdcr-replicator={id}".format( @@ -316,6 +489,29 @@ def resume_replication(shell_path, source_hostname, source_port, source_username id=id ) + @staticmethod + def resume_replication_expect(shell_path, source_hostname, source_port, + source_username, cluster_name, id, **kwargs): + command = f"{shell_path} xdcr-replicate --cluster {source_hostname}:{source_port} --username {source_username} --password --xdcr-cluster-name {cluster_name} --resume --xdcr-replicator={id}" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("source_password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def delete_replication(shell_path, source_hostname, source_port, source_username, id, cluster_name, **kwargs): return "{shell_path} xdcr-replicate --cluster {source_hostname}:{source_port} --username {source_username} --password $source_password --delete --xdcr-replicator {id} --xdcr-cluster-name {cluster_name}".format( @@ -327,6 +523,29 @@ def delete_replication(shell_path, source_hostname, source_port, source_username cluster_name=cluster_name ) + @staticmethod + def delete_replication_expect(shell_path, source_hostname, source_port, + source_username, id, cluster_name, **kwargs): + command = f"{shell_path} xdcr-replicate --cluster {source_hostname}:{source_port} --username {source_username} --password --delete --xdcr-replicator {id} --xdcr-cluster-name {cluster_name}" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("source_password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def xdcr_delete(shell_path, source_hostname, source_port, source_username, hostname, port, username, cluster_name, **kwargs): return "{shell_path} xdcr-setup --cluster {source_hostname}:{source_port} --username {source_username} --password $source_password --delete --xdcr-hostname {hostname}:{port} --xdcr-username {username} --xdcr-password $password --xdcr-cluster-name {cluster_name}".format( @@ -340,6 +559,31 @@ def xdcr_delete(shell_path, source_hostname, source_port, source_username, hostn cluster_name=cluster_name ) + @staticmethod + def xdcr_delete_expect(shell_path, source_hostname, source_port, source_username, + hostname, port, username, cluster_name, **kwargs): + command = f"{shell_path} xdcr-setup --cluster {source_hostname}:{source_port} --username {source_username} --password --delete --xdcr-hostname {hostname}:{port} --xdcr-username {username} --xdcr-cluster-name {cluster_name} --xdcr-password" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""set env(CMD) "${env(CB_CMD)} ${env(XDCR_PWD)}" + eval spawn ${env(CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "XDCR_PWD": kwargs.get("password"), + "CB_PWD": kwargs.get("source_password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def get_source_bucket_list(shell_path, source_hostname, source_port, source_username, **kwargs): return "{shell_path} bucket-list --cluster {source_hostname}:{source_port} --username {source_username} --password $password -o json".format( @@ -349,18 +593,84 @@ def get_source_bucket_list(shell_path, source_hostname, source_port, source_user source_username=source_username, ) + @staticmethod + def get_source_bucket_list_expect(shell_path, source_hostname, source_port, source_username, **kwargs): + command = f"{shell_path} bucket-list --cluster {source_hostname}:{source_port} --username {source_username} --password -o json" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def get_server_list(shell_path, hostname, port, username, **kwargs): return "{shell_path} server-list --cluster {hostname}:{port} --username {username} --password $password".format( shell_path=shell_path, hostname=hostname, port=port, username=username ) + @staticmethod + def get_server_list_expect(shell_path, hostname, port, username, **kwargs): + command = f"{shell_path} server-list --cluster {hostname}:{port} --username {username} --password" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def node_init(shell_path, port, username, data_path, **kwargs): return "{shell_path} node-init --cluster 127.0.0.1:{port} --username {username} --password $password --node-init-data-path {data_path} --node-init-index-path {data_path} --node-init-analytics-path {data_path} --node-init-hostname 127.0.0.1".format( shell_path=shell_path, port=port, username=username, data_path=data_path ) + @staticmethod + def node_init_expect(shell_path, port, username, data_path, **kwargs): + command = f"{shell_path} node-init --cluster 127.0.0.1:{port} --username {username} --password --node-init-data-path {data_path} --node-init-index-path {data_path} --node-init-analytics-path {data_path} --node-init-hostname 127.0.0.1" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def bucket_edit(shell_path, hostname, port, username, bucket_name, flush_value, **kwargs): return "{shell_path} bucket-edit --cluster {hostname}:{port} --username {username} --password $password --bucket={bucket_name} --enable-flush {flush_value}".format( @@ -368,6 +678,29 @@ def bucket_edit(shell_path, hostname, port, username, bucket_name, flush_value, flush_value=flush_value ) + @staticmethod + def bucket_edit_expect(shell_path, hostname, port, username, bucket_name, + flush_value, **kwargs): + command = f"{shell_path} bucket-edit --cluster {hostname}:{port} --username {username} --password --bucket={bucket_name} --enable-flush {flush_value}" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def bucket_edit_ramquota(shell_path, hostname, port, username, bucket_name, ramsize, **kwargs): return "{shell_path} bucket-edit --cluster {hostname}:{port} --username {username} --password $password --bucket={bucket_name} --bucket-ramsize {ramsize}".format( @@ -375,18 +708,87 @@ def bucket_edit_ramquota(shell_path, hostname, port, username, bucket_name, rams ramsize=ramsize ) + @staticmethod + def bucket_edit_ramquota_expect(shell_path, hostname, port, username, bucket_name, + ramsize, **kwargs): + command = f"{shell_path} bucket-edit --cluster {hostname}:{port} --username {username} --password --bucket={bucket_name} --bucket-ramsize {ramsize}" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def bucket_delete(shell_path, hostname, port, username, bucket_name, **kwargs): return "{shell_path} bucket-delete --cluster {hostname}:{port} --username {username} --password $password --bucket={bucket_name}".format( shell_path=shell_path, hostname=hostname, port=port, username=username, bucket_name=bucket_name ) + @staticmethod + def bucket_delete_expect(shell_path, hostname, port, username, bucket_name, + **kwargs): + command = f"{shell_path} bucket-delete --cluster {hostname}:{port} --username {username} --password --bucket={bucket_name}" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def bucket_flush(shell_path, hostname, port, username, bucket_name, **kwargs): return "echo 'Yes' | {shell_path} bucket-flush --cluster {hostname}:{port} --username {username} --password $password --bucket={bucket_name}".format( shell_path=shell_path, hostname=hostname, port=port, username=username, bucket_name=bucket_name ) + @staticmethod + def bucket_flush_expect(shell_path, hostname, port, username, bucket_name, + **kwargs): + command = f"echo 'Yes' | {shell_path} bucket-flush --cluster {hostname}:{port} --username {username} --password $password --bucket={bucket_name}" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def bucket_create(shell_path, hostname, port, username, bucket_name, ramsize, evictionpolicy, bucket_type, bucket_compression, **kwargs): return "{shell_path} bucket-create --cluster 127.0.0.1:{port} --username {username} --password $password --bucket {bucket_name} --bucket-type {bucket_type} --bucket-ramsize {ramsize} --bucket-replica 0 --bucket-eviction-policy {evictionpolicy} {bucket_compression} --conflict-resolution sequence --wait".format( @@ -395,18 +797,87 @@ def bucket_create(shell_path, hostname, port, username, bucket_name, ramsize, ev bucket_type=bucket_type, bucket_compression=bucket_compression ) + @staticmethod + def bucket_create_expect(shell_path, hostname, port, username, bucket_name, + ramsize, evictionpolicy, bucket_type, bucket_compression, + **kwargs): + command = f"{shell_path} bucket-create --cluster 127.0.0.1:{port} --username {username} --password --bucket {bucket_name} --bucket-type {bucket_type} --bucket-ramsize {ramsize} --bucket-replica 0 --bucket-eviction-policy {evictionpolicy} {bucket_compression} --conflict-resolution sequence --wait" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def bucket_list(shell_path, hostname, port, username, **kwargs): return "{shell_path} bucket-list --cluster {hostname}:{port} --username {username} --password $password -o json".format( shell_path=shell_path, hostname=hostname, port=port, username=username, ) + @staticmethod + def bucket_list_expect(shell_path, hostname, port, username, **kwargs): + command = f"{shell_path} bucket-list --cluster {hostname}:{port} --username {username} --password -o json" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def get_indexes_name(hostname, port, username, **kwargs): return "curl {username}:$password@{hostname}:{port}/indexStatus".format( hostname=hostname, port=port, username=username ) + @staticmethod + def get_indexes_name_expect(hostname, port, username, **kwargs): + command = f"curl -u {username} {hostname}:{port}/indexStatus" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter host password for user.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + + @staticmethod def get_backup_bucket_list(path, sudo=False, uid=None, **kwargs): if sudo: @@ -418,22 +889,84 @@ def get_backup_bucket_list(path, sudo=False, uid=None, **kwargs): path=path ) - - - - @staticmethod def build_index(base_path, hostname, port, username, index_def, **kwargs): return "{base_path}/cbq -e {hostname}:{port} -u {username} -p $password -q=true -s='{index_def}'".format( base_path=base_path, hostname=hostname, port=port, username=username, index_def=index_def ) + @staticmethod + def build_index_expect(base_path, hostname, port, username, index_def, **kwargs): + command = f"{base_path}/cbq -e {hostname}:{port} -u {username} -q=true" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter Password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + -re ".*ERROR 100 :.*" { + puts "Error occured" + send "\x04" + } + -re "(.|\n)*cbq>(.|\n)*" { + send "${env(CB_QUERY)};\n" + expect -re "\n(.|\n)*" + send "\x04" + expect eof + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command, + "CB_QUERY": index_def + } + return expect_block, env_vars + @staticmethod def check_index_build(base_path, hostname, port, username, **kwargs): return "{base_path}/cbq -e {hostname}:{port} -u {username} -p $password -q=true -s=\"SELECT COUNT(*) as unbuilt FROM system:indexes WHERE state <> 'online'\"".format( base_path=base_path, hostname=hostname, port=port, username=username ) + @staticmethod + def check_index_build_expect(base_path, hostname, port, username, **kwargs): + command = f"{base_path}/cbq -e {hostname}:{port} -u {username} -q=true" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter Password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + -re ".*ERROR 100 :.*" { + puts "Error occured" + send "\x04" + } + -re "(.|\n)*cbq>(.|\n)*" { + send "${env(CB_QUERY)};\n" + expect -re "\n(.|\n)*" + send "\x04" + expect eof + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command, + "CB_QUERY": "SELECT COUNT(*) as unbuilt FROM system:indexes WHERE state <> 'online'" + } + return expect_block, env_vars + @staticmethod def cb_backup_full(base_path, backup_location, backup_repo, hostname, port, username, csv_bucket_list, sudo, uid, skip, **kwargs): if sudo: @@ -462,6 +995,35 @@ def cb_backup_full(base_path, backup_location, backup_repo, hostname, port, user skip=skip ) + @staticmethod + def cb_backup_full_expect(base_path, backup_location, backup_repo, hostname, port, + username, csv_bucket_list, sudo, uid, skip, **kwargs): + if sudo: + command = f"sudo -u \#{uid} {base_path}/cbbackupmgr restore --archive {backup_location} --repo {backup_repo} --cluster couchbase://{hostname}:{port} --username {username} --password \ + --force-updates {skip} --no-progress-bar --include-buckets {csv_bucket_list}" + else: + command = f"{base_path}/cbbackupmgr restore --archive {backup_location} --repo {backup_repo} --cluster couchbase://{hostname}:{port} --username {username} --password \ + --force-updates {skip} --no-progress-bar --include-buckets {csv_bucket_list}" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Password:.*" { + send "${env(CB_PWD)}\n" + set timeout -1 + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + @staticmethod def monitor_replication(source_username, source_hostname, source_port, bucket_name, uuid, **kwargs): return "curl --silent -u {source_username}:$password http://{source_hostname}:{source_port}/pools/default/buckets/{bucket_name}/stats/replications%2F{uuid}%2F{bucket_name}%2F{bucket_name}%2Fchanges_left".format( @@ -478,6 +1040,35 @@ def monitor_replication(source_username, source_hostname, source_port, bucket_na # shell_path=shell_path, hostname=hostname, port=port, username=username # ) + @staticmethod + def monitor_replication_expect(source_username, source_hostname, source_port, + bucket_name, uuid, **kwargs): + command = f"curl --silent -u {source_username} http://{source_hostname}:{source_port}/pools/default/buckets/{bucket_name}/stats/replications%2F{uuid}%2F{bucket_name}%2F{bucket_name}%2Fchanges_left" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter host password for user.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + + # @staticmethod + # def couchbase_server_info(shell_path, hostname, port, username, **kwargs): + # return "{shell_path} server-info --cluster {hostname}:{port} --username {username} --password $password ".format( + # shell_path=shell_path, hostname=hostname, port=port, username=username + # ) + @staticmethod def couchbase_server_info(shell_path, hostname, username, port, **kwargs): return "{shell_path} server-info --cluster {hostname}:{port} --username {username} --password $password".format( @@ -485,6 +1076,124 @@ def couchbase_server_info(shell_path, hostname, username, port, **kwargs): ) #return("{shell_path}".format(shell_path=shell_path)) + @staticmethod + def couchbase_server_info_expect(shell_path, hostname, username, port, **kwargs): + command = f"{shell_path} server-info --cluster {hostname}:{port} --username {username} --password" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + + @staticmethod + def rename_cluster(shell_path, hostname, port, username, newuser, newname, **kwargs): + return "{shell_path} setting-cluster --cluster {hostname}:{port} --username {username} --password $password --cluster-username {newuser} --cluster-password $newpass --cluster-name {newname}".format( + shell_path=shell_path, hostname=hostname, port=port, username=username, + newuser=newuser, newname=newname + ) + + @staticmethod + def rename_cluster_expect(shell_path, hostname, port, username, newuser, newname, **kwargs): + command = f"{shell_path} setting-cluster --cluster {hostname}:{port} --username {username} --password --cluster-username {newuser} --cluster-name {newname} --cluster-password" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""set env(CMD) "${env(CB_CMD)} ${env(NEW_CB_PWD)}" + eval spawn ${env(CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "NEW_CB_PWD": kwargs.get("newpass"), + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + + @staticmethod + def server_add(shell_path, hostname, port, username, newhost, services, **kwargs): + return "{shell_path} server-add --cluster {hostname}:{port} --username {username} --password $password \ + --server-add http://{newhost}:{port} --server-add-username {username} --server-add-password $password \ + --services {services}".format( + shell_path=shell_path, hostname=hostname, port=port, username=username, services=services, newhost=newhost + ) + + @staticmethod + def server_add_expect(shell_path, hostname, port, username, newhost, services, + **kwargs): + command = f"{shell_path} server-add --cluster {hostname}:{port} --username {username} --password \ + --server-add http://{newhost}:{port} --server-add-username {username} --server-add-password $password \ + --services {services}" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + + + @staticmethod + def rebalance(shell_path, hostname, port, username, **kwargs): + return "{shell_path} rebalance --cluster {hostname}:{port} --username {username} --password $password \ + --no-progress-bar".format( + shell_path=shell_path, hostname=hostname, port=port, username=username + ) + + @staticmethod + def rebalance_expect(shell_path, hostname, port, username, **kwargs): + command = f"{shell_path} rebalance --cluster {hostname}:{port} --username {username} --password \ + --no-progress-bar" + expect_block = DatabaseCommand.get_parent_expect_block().format( + command_specific_operations="""eval spawn ${env(CB_CMD)} + expect { + -re "Enter password:.*" { + send "${env(CB_PWD)}\n" + exp_continue + } + timeout { + puts "EXPECT SCRIPT TIMEOUT" + exit 2 + } + }""" + ) + env_vars = { + "CB_PWD": kwargs.get("password"), + "CB_CMD": command + } + return expect_block, env_vars + + @staticmethod def rename_cluster(shell_path, hostname, port, username, newuser, newname, **kwargs): return "{shell_path} setting-cluster --cluster {hostname}:{port} --username {username} --password $password --cluster-username {newuser} --cluster-password $newpass --cluster-name {newname}".format( diff --git a/src/utils/utilities.py b/src/utils/utilities.py index 497ab91..a43b234 100644 --- a/src/utils/utilities.py +++ b/src/utils/utilities.py @@ -38,6 +38,68 @@ def execute_bash(source_connection, command_name, callback_func=None, environmen return [output, error, exit_code] +def execute_expect(source_connection, command_name, callback_func=None, environment_vars=None): + """ + :param callback_func: + :param source_connection: Connection object for the source environment + :param command_name: Command to be search from dictionary of bash command + :param environment_vars: Expecting environment variables which are required to execute the command + :return: list of output of command, error string, exit code + """ + + if source_connection is None: + raise exceptions.PluginScriptError("Connection object cannot be empty") + + # environment_vars["CB_PWD"] = environment_vars["password"] + result = libs.run_bash( + source_connection, + command=f"echo -e '{command_name}' > /tmp/expect_script.exp", + use_login_shell=True + ) + output = result.stdout.strip() + error = result.stderr.strip() + exit_code = result.exit_code + + logger.debug(f"script_dump_output==={output}") + logger.debug(f"script_dump_error==={error}") + logger.debug(f"script_dump_exit_code==={exit_code}") + + result = libs.run_bash( + source_connection, + command=f"/usr/bin/expect -f /tmp/expect_script.exp", + variables=environment_vars, + use_login_shell=True + ) + + # strip the each part of result to remove spaces from beginning and last of output + output = result.stdout.strip() + error = result.stderr.strip() + exit_code = result.exit_code + + logger.debug(f"expect_output==={output}") + logger.debug(f"expect_error==={error}") + logger.debug(f"expect_exit_code==={exit_code}") + + if "DLPX_EXPECT_EXIT_CODE" in output: + exit_code = int(output.split("DLPX_EXPECT_EXIT_CODE:")[1].split("\n")[0]) + msg = output.split("DLPX_EXPECT_EXIT_CODE:")[1].split("\n", 1)[1].strip() + if exit_code != 0: + error = msg + else: + output = msg + + if "cbq>" in output and output.rsplit("\n", 1)[1].strip() == "cbq>": + output = output.rsplit("\n", 1)[0] + + logger.debug(f"final_output==={output}") + logger.debug(f"final_error==={error}") + logger.debug(f"final_exit_code==={exit_code}") + # Verify the exit code of each executed command. 0 means command ran successfully and for other code it is failed. + # For failed cases we need to find the scenario in which programs will die and otherwise execution will continue. + #_handle_exit_code(exit_code, error, output, callback_func) + return [output, error, exit_code] + + def _handle_exit_code(exit_code, std_err=None, std_output=None, callback_func=None): if exit_code == 0: return