コード例 #1
0
ファイル: rediscli_util.py プロジェクト: mnms/LTCLI
    def command_all_async(sub_cmd, slave=True):
        def _async_target_func(m_s, pre_cmd, host, port, sub_cmd, ret):
            try:
                command = '{} -h {} -p {} {}'.format(pre_cmd, host, port,
                                                     sub_cmd)
                logger.debug(command)
                stdout = subprocess.check_output(command, shell=True)
                stdout = stdout.decode('utf-8').strip()
                ret.append((m_s, host, port, 'OK', stdout))
            except Exception as ex:
                stderr = str(ex)
                logger.debug(stderr)
                ret.append((m_s, host, port, 'FAIL', stderr))

        cluster_id = config.get_cur_cluster_id()
        master_host_list = config.get_master_host_list(cluster_id)
        master_port_list = config.get_master_port_list(cluster_id)
        if slave:
            slave_host_list = config.get_slave_host_list(cluster_id)
            slave_port_list = config.get_slave_port_list(cluster_id)
        path_of_fb = config.get_path_of_fb(cluster_id)
        sr2_redis_bin = path_of_fb['sr2_redis_bin']

        logger.debug('command_all_async')
        cluster_id = config.get_cur_cluster_id()
        lib_path = config.get_ld_library_path(cluster_id)
        env_cmd = [
            'export LD_LIBRARY_PATH={};'.format(lib_path['ld_library_path']),
            'export DYLD_LIBRARY_PATH={};'.format(
                lib_path['dyld_library_path']),
        ]
        env = ' '.join(env_cmd)
        threads = []
        ret = []  # (m/s, host, port, result, message)
        pre_cmd = '{} {}/redis-cli -c'.format(env, sr2_redis_bin)
        for host in master_host_list:
            for port in master_port_list:
                t = Thread(
                    target=_async_target_func,
                    args=('Master', pre_cmd, host, port, sub_cmd, ret),
                )
                threads.append(t)
        if slave:
            for host in slave_host_list:
                for port in slave_port_list:
                    t = Thread(
                        target=_async_target_func,
                        args=('Slave', pre_cmd, host, port, sub_cmd, ret),
                    )
                    threads.append(t)
        for th in threads:
            th.start()
            time.sleep(0.02)
        for th in threads:
            th.join()
        logger.debug(ret)
        return ret
コード例 #2
0
 def beeline(self, **kargs):
     """Connect to thriftserver command line
     """
     logger.debug('thriftserver_command_beeline')
     _check_spark()
     cluster_id = config.get_cur_cluster_id()
     path_of_fb = config.get_path_of_fb(cluster_id)
     ths_props_path = path_of_fb['thrift_properties']
     cmd = 'source {}; echo ${}'.format(ths_props_path, 'HIVE_HOST')
     host = sp.check_output(cmd, shell=True).decode('utf-8').strip()
     cmd = 'source {}; echo ${}'.format(ths_props_path, 'HIVE_PORT')
     port = sp.check_output(cmd, shell=True).decode('utf-8').strip()
     spark_env = _get_env()
     base_cmd = '{}/beeline'.format(spark_env['spark_bin'])
     options = {
         'u': 'jdbc:hive2://{}:{}'.format(host, port),
         'n': os.environ['USER']
     }
     for key, value in kargs.items():
         options[key] = value
     for key, value in options.items():
         base_cmd += ' -{} {}'.format(key, value)
     logger.debug(base_cmd)
     msg = message.get('try_connection')
     logger.info(msg)
     os.system(base_cmd)
コード例 #3
0
def open_vim_editor(target='config'):
    """Open vim editor
    :param target: config | master | slave | thriftserver
    """
    cluster_id = config.get_cur_cluster_id()
    full_path = get_full_path_of_props(cluster_id, target)
    editor.edit(full_path)
コード例 #4
0
ファイル: rediscli_util.py プロジェクト: mnms/LTCLI
    def command_all(sub_cmd, cluster_id=-1, formatter=None):
        """Send redis-cli command to all

        :param sub_cmd: sub command
        :param cluster_id: target cluster #
        :param formatter: if set, call formatter with output string
        """
        if cluster_id < 0:
            cluster_id = config.get_cur_cluster_id()
        master_host_list = config.get_master_host_list(cluster_id)
        master_port_list = config.get_master_port_list(cluster_id)
        slave_host_list = config.get_slave_host_list(cluster_id)
        slave_port_list = config.get_slave_port_list()
        outs, meta = RedisCliUtil.command_raw_all(sub_cmd, master_host_list,
                                                  master_port_list)
        logger.debug(outs)
        buf = meta[:]
        outs, meta = RedisCliUtil.command_raw_all(sub_cmd, slave_host_list,
                                                  slave_port_list)
        logger.debug(outs)
        buf += meta[1:]
        if formatter:
            formatter(buf)
        else:
            logger.debug(outs)
コード例 #5
0
    def failover_with_dir(self, server, dir):
        """Find masters that use the specified directory path and do failover with its slave

        :param server: IP or hostname
        :param dir: directory path
        """
        center = Center()
        center.update_ip_port()
        logger.debug('failover_with_dir')
        master_nodes = center.get_master_obj_list()
        cluster_id = config.get_cur_cluster_id()
        lib_path = config.get_ld_library_path(cluster_id)
        path_of_fb = config.get_path_of_fb(cluster_id)
        sr2_redis_bin = path_of_fb['sr2_redis_bin']
        env_cmd = [
            'GLOBIGNORE=*;',
            'export LD_LIBRARY_PATH={};'.format(lib_path['ld_library_path']),
            'export DYLD_LIBRARY_PATH={};'.format(
                lib_path['dyld_library_path']),
        ]
        redis_cli_cmd = os.path.join(sr2_redis_bin, 'redis-cli')

        # Find masters with dir
        ret = RedisCliUtil.command_all_async('config get dir', slave=True)
        outs = ''
        meta = []
        m_endpoint = []
        for node in master_nodes:
            m_endpoint.append(node['addr'])
        for _, host, port, res, stdout in ret:
            if res == 'OK':
                flat_stdout = '\n'.join([outs, stdout])
                line = flat_stdout.splitlines()
                if self.compare_ip(host, server) and dir in line[2]:
                    endpoint = '{}:{}'.format(socket.gethostbyname(host), port)
                    if endpoint in m_endpoint:
                        meta.append(endpoint)
            else:
                logger.warning("FAIL {}:{} {}".format(host, port, stdout))

        for endpoint in meta:
            for master_node in master_nodes:
                if endpoint == master_node['addr']:
                    for slave_node in master_node['slaves']:
                        addr = slave_node['addr']
                        (s_host, s_port) = addr.split(':')
                        sub_cmd = 'cluster failover takeover'
                        command = '{} {} -h {} -p {} {}'.format(
                            ' '.join(env_cmd),
                            redis_cli_cmd,
                            s_host,
                            s_port,
                            sub_cmd,
                        )
                        self._print(
                            message.get('try_failover_takeover').format(
                                slave=addr))
                        stdout = subprocess.check_output(command, shell=True)
                        self._print(stdout)
コード例 #6
0
 def version(self):
     """Get version of lightningDB
     """
     cluster_id = config.get_cur_cluster_id()
     tsr2_home = config.get_tsr2_home(cluster_id)
     with open(os.path.join(tsr2_home, "VERSION"), "r") as version_file:
         lines = version_file.readlines()
         logger.info("".join(lines).strip())
コード例 #7
0
def get_cli_prompt():
    """Return cli prompt

    :param user: user name
    :return: prompt string
    """
    cluster_id = config.get_cur_cluster_id(allow_empty_id=True)
    if cluster_id < 0:
        cluster_id = '-'
    user = environ['USER']
    prompt_classname = u'class:ansiwhite'
    prompt_message = u'{}@lightningdb:{}> '.format(user, cluster_id)
    return [(prompt_classname, prompt_message)]
コード例 #8
0
 def stop(self):
     """Stop thriftserver
     """
     logger.debug('thriftserver_command_stop')
     _check_spark()
     cluster_id = config.get_cur_cluster_id()
     path_of_fb = config.get_path_of_fb(cluster_id)
     ths_props_path = path_of_fb['thrift_properties']
     source_cmd = 'source {}'.format(ths_props_path)
     base_cmd = '$SPARK_SBIN/stop-thriftserver.sh'
     cmd = '{}; {}'.format(source_cmd, base_cmd)
     logger.debug(cmd)
     os.system(cmd)
コード例 #9
0
ファイル: rediscli_util.py プロジェクト: mnms/LTCLI
    def save_redis_template_config(key, value):
        """Save redis template config to file

        :param key: key
        :param value: value
        """
        key = key.strip()
        cluster_id = config.get_cur_cluster_id()
        path_of_fb = config.get_path_of_fb(cluster_id)
        master_template = path_of_fb['master_template']
        msg = message.get('save_config_to_template')
        logger.info(msg)
        RedisCliUtil._save_config(master_template, key, value)
コード例 #10
0
def get_sql_prompt():
    """Return sql prompt

    :param user: user name
    :return: prompt string
    """
    cluster_id = config.get_cur_cluster_id(allow_empty_id=True)
    if cluster_id < 0:
        cluster_id = '-'
    user = environ['USER']
    prompt_classname = u'class:ansigreen'
    prompt_message = u'({}){}@lightningdb:sql> '.format(cluster_id, user)
    return [(prompt_classname, prompt_message)]
コード例 #11
0
def _validate_cluster_id(cluster_id):
    try:
        if cluster_id is None:
            cluster_id = config.get_cur_cluster_id(allow_empty_id=True)
        elif not utils.is_number(cluster_id):
            raise ClusterIdError(cluster_id)
        cluster_id = int(cluster_id)
        run_cluster_use(cluster_id)
        return cluster_id
    except (ClusterIdError, ClusterNotExistError) as ex:
        logger.warning(ex)
        cluster_id = -1
        run_cluster_use(cluster_id)
        return cluster_id
コード例 #12
0
def _get_env():
    if 'SPARK_HOME' not in os.environ:
        raise EnvError('you should set env SPARK_HOME')
    ret = {
        'spark_home': os.environ['SPARK_HOME'],
    }
    env_list = ['SPARK_BIN', 'SPARK_SBIN', 'SPARK_LOG', 'SPARK_CONF']
    cluster_id = config.get_cur_cluster_id()
    path_of_fb = config.get_path_of_fb(cluster_id)
    ths_props_path = path_of_fb['thrift_properties']
    for env in env_list:
        cmd = 'source {}; echo ${}'.format(ths_props_path, env.upper())
        stdout = sp.check_output(cmd, shell=True).decode('utf-8').strip()
        ret[env.lower()] = stdout
    return ret
コード例 #13
0
 def thriftserver(self):
     """Edit 'thriftserver.properties'
     """
     cluster_id = config.get_cur_cluster_id()
     path_of_fb = config.get_path_of_fb(cluster_id)
     target_path = path_of_fb['thrift_properties']
     self._edit_conf(target_path, syntax='sh')
     center = Center()
     center.update_ip_port()
     success = center.check_hosts_connection()
     if not success:
         return
     success = center.sync_file(target_path)
     if success:
         msg = message.get('complete_conf_edit')
         logger.info(msg)
コード例 #14
0
 def slave(self):
     """Edit 'redis-slave.conf.template'
     """
     cluster_id = config.get_cur_cluster_id()
     path_of_fb = config.get_path_of_fb(cluster_id)
     target_path = path_of_fb['slave_template']
     self._edit_conf(target_path, syntax='sh')
     center = Center()
     center.update_ip_port()
     success = center.check_hosts_connection()
     if not success:
         return
     success = center.sync_file(target_path)
     if success:
         msg = message.get('complete_conf_edit')
         logger.info(msg)
コード例 #15
0
def run_deploy(cluster_id=None,
               history_save=True,
               clean=False,
               strategy="none"):
    """Install LightningDB package.

    :param cluster_id: cluster id
    :param history_save: save input history and use as default
    :param clean: delete redis log, node configuration
    :param strategy:
        none(default): normal deploy,
        zero-downtime: re-deploy without stop
    """
    # validate cluster id
    if cluster_id is None:
        cluster_id = config.get_cur_cluster_id(allow_empty_id=True)
        if cluster_id < 0:
            msg = message.get('error_invalid_cluster_on_deploy')
            logger.error(msg)
            return
    if not cluster_util.validate_id(cluster_id):
        raise ClusterIdError(cluster_id)

    # validate option
    if not isinstance(history_save, bool):
        msg = message.get('error_option_type_not_boolean')
        msg = msg.format(option='history-save')
        logger.error(msg)
        return
    logger.debug("option '--history-save': {}".format(history_save))
    if not isinstance(clean, bool):
        msg = message.get('error_option_type_not_boolean')
        msg = msg.format(option='clean')
        logger.error(msg)
        return
    logger.debug("option '--clean': {}".format(clean))
    strategy_list = ["none", "zero-downtime"]
    if strategy not in strategy_list:
        msg = message.get('error_deploy_strategy').format(value=strategy,
                                                          list=strategy_list)
        logger.error(msg)
        return
    if strategy == "zero-downtime":
        run_cluster_use(cluster_id)
        _deploy_zero_downtime(cluster_id)
        return
    _deploy(cluster_id, history_save, clean)
コード例 #16
0
    def force_failover(self, server):
        """ Find all masters on the server and convert them to slaves. Finally, in the server, only slaves will be remained.

        :param server: IP or hostname
        """

        logger.debug('force_failover')
        center = Center()
        center.update_ip_port()
        master_nodes = center.get_master_obj_list()
        cluster_id = config.get_cur_cluster_id()
        lib_path = config.get_ld_library_path(cluster_id)
        path_of_fb = config.get_path_of_fb(cluster_id)
        sr2_redis_bin = path_of_fb['sr2_redis_bin']
        env_cmd = [
            'GLOBIGNORE=*;',
            'export LD_LIBRARY_PATH={};'.format(lib_path['ld_library_path']),
            'export DYLD_LIBRARY_PATH={};'.format(
                lib_path['dyld_library_path']),
        ]
        redis_cli_cmd = os.path.join(sr2_redis_bin, 'redis-cli')

        outs = ''
        meta = []
        m_endpoint = []
        for node in master_nodes:
            addr = node['addr']
            (host, port) = addr.split(':')
            # if host == server:
            if self.compare_ip(host, server):
                for slave_node in node['slaves']:
                    addr = slave_node['addr']
                    (s_host, s_port) = addr.split(':')
                    sub_cmd = 'cluster failover takeover'
                    command = '{} {} -h {} -p {} {}'.format(
                        ' '.join(env_cmd),
                        redis_cli_cmd,
                        s_host,
                        s_port,
                        sub_cmd,
                    )
                    self._print(
                        message.get('try_failover_takeover').format(
                            slave=addr))
                    stdout = subprocess.check_output(command, shell=True)
                    self._print(stdout)
コード例 #17
0
 def start(self):
     """Start thriftserver
     """
     logger.debug('thriftserver_command_start')
     _check_spark()
     cluster_id = config.get_cur_cluster_id()
     path_of_fb = config.get_path_of_fb(cluster_id)
     ths_props_path = path_of_fb['thrift_properties']
     source_cmd = 'source {}'.format(ths_props_path)
     hive_opts = _get_hive_opts_str()
     base_cmd = '$SPARK_SBIN/start-thriftserver.sh {}'.format(hive_opts)
     cmd = '{}; {}'.format(source_cmd, base_cmd)
     logger.debug(cmd)
     os.system(cmd)
     spark_log = os.path.join(os.environ['SPARK_HOME'], 'logs')
     if _find_files_with_regex(spark_log, ROLLING_LOGFILE_REGEX):
         for file in _find_files_with_regex(spark_log, NOHUP_LOGFILE_REGEX):
             os.remove(os.path.join(spark_log, file))
コード例 #18
0
    def reset_distribution(self):
        """ Reset the distribution of masters and slaves with original setting
        """
        center = Center()
        center.update_ip_port()
        logger.debug('reset_distribution')
        cluster_id = config.get_cur_cluster_id()
        lib_path = config.get_ld_library_path(cluster_id)
        path_of_fb = config.get_path_of_fb(cluster_id)
        sr2_redis_bin = path_of_fb['sr2_redis_bin']
        env_cmd = [
            'GLOBIGNORE=*;',
            'export LD_LIBRARY_PATH={};'.format(lib_path['ld_library_path']),
            'export DYLD_LIBRARY_PATH={};'.format(
                lib_path['dyld_library_path']),
        ]
        redis_cli_cmd = os.path.join(sr2_redis_bin, 'redis-cli')
        slave_nodes = center.get_slave_nodes()
        master_ports = center.master_port_list

        for slave_node in slave_nodes:
            (host, port) = slave_node.split(':')
            try:
                value = int(port)
                if value in master_ports:
                    # failover takeover
                    msg = message.get('try_failover_takeover').format(
                        slave=slave_node)
                    self._print(msg)
                    sub_cmd = 'cluster failover takeover'
                    command = '{} {} -h {} -p {} {}'.format(
                        ' '.join(env_cmd),
                        redis_cli_cmd,
                        host,
                        port,
                        sub_cmd,
                    )
                    stdout = subprocess.check_output(command, shell=True)
                    outs = ''
                    outs = '\n'.join([outs, stdout])
                    self._print(outs)
            except ValueError:
                pass
コード例 #19
0
def run_monitor(n=10, t=2):
    """Monitoring logs of redis.

    :param n: number of lines to print log
    :param t: renewal cycle(sec)
    """
    if not isinstance(n, int):
        msg = message.get('error_option_type_not_number').format(option='n')
        logger.error(msg)
        return
    if not isinstance(t, int) and not isinstance(t, float):
        msg = message.get('error_option_type_not_float').format(option='t')
        logger.error(msg)
        return
    try:
        sp.check_output('which tail', shell=True)
    except Exception:
        msg = message.get('error_not_found_command_tail')
        logger.error(msg)
        return
    cluster_id = config.get_cur_cluster_id()
    path_of_fb = config.get_path_of_fb(cluster_id)
    sr2_redis_log = path_of_fb['sr2_redis_log']
    log_files = '{}/servers*'.format(sr2_redis_log)
    host_list = config.get_master_host_list()
    target_host = ask_util.host_for_monitor(host_list)
    try:
        sp.check_output('which watch', shell=True)
        command = "ssh -t {} watch -n {} 'tail -n {} {}'".format(
            target_host, t, n, log_files)
        sp.call(command, shell=True)
    except Exception:
        msg = message.get('error_not_found_command_watch')
        logger.warning(msg)
        logger.info(message.get('message_for_exit'))
        command = "tail -F -s {} {}".format(t, log_files)
        client = net.get_ssh(target_host)
        net.ssh_execute_async(client, command)
コード例 #20
0
 def monitor(self):
     """Monitoring log of thriftserver"
     """
     logger.debug('thriftserver_command_monitor')
     _check_spark()
     cluster_id = config.get_cur_cluster_id()
     path_of_fb = config.get_path_of_fb(cluster_id)
     ths_props_path = path_of_fb['thrift_properties']
     source_cmd = 'source {}'.format(ths_props_path)
     spark_log = _get_env()['spark_log']
     # log_file_path = ''.join([
     #     spark_log,
     #     '/spark-{}-org.apache'.format(os.environ['USER']),
     #     '.spark.sql.hive.thriftserver.HiveThriftServer2-1-*.out',
     # ])
     log_file_path = os.path.join(spark_log, NOHUP_LOGFILE)
     if _find_files_with_regex(spark_log, ROLLING_LOGFILE_REGEX):
         log_file_path = os.path.join(spark_log, ROLLING_LOGFILE)
     base_cmd = 'tail -F {}'.format(log_file_path)
     cmd = '{}; {}'.format(source_cmd, base_cmd)
     logger.debug(cmd)
     msg = message.get('message_for_exit')
     logger.info(msg)
     os.system(cmd)
コード例 #21
0
def _deploy(cluster_id, history_save, clean):
    deploy_state = DeployUtil().get_state(cluster_id)
    if deploy_state == DEPLOYED:
        msg = message.get('ask_deploy_again')
        msg = msg.format(cluster_id=cluster_id)
        msg = color.yellow(msg)
        yes = ask_util.askBool(msg, default='n')
        if not yes:
            logger.info(message.get('cancel'))
            return

    restore_yes = None
    no_localhost = False
    current_time = time.strftime("%Y%m%d%H%M%S", time.gmtime())
    cluster_backup_dir = 'cluster_{}_bak_{}'.format(cluster_id, current_time)
    conf_backup_dir = 'cluster_{}_conf_bak_{}'.format(cluster_id, current_time)
    tmp_backup_dir = 'cluster_{}_conf_bak_{}'.format(cluster_id, 'tmp')
    meta = [['NAME', 'VALUE']]
    path_of_fb = config.get_path_of_fb(cluster_id)
    conf_path = path_of_fb['conf_path']
    props_path = path_of_fb['redis_properties']
    cluster_path = path_of_fb['cluster_path']
    path_of_cli = config.get_path_of_cli(cluster_id)
    conf_backup_path = path_of_cli['conf_backup_path']
    tmp_backup_path = os.path.join(conf_backup_path, tmp_backup_dir)
    local_ip = config.get_local_ip()

    # ask installer
    installer_path = ask_util.installer()
    installer_name = os.path.basename(installer_path)
    meta.append(['installer', installer_name])

    # ask restore conf
    if deploy_state == DEPLOYED:
        restore_yes = ask_util.askBool(message.get('ask_restore_conf'))
        meta.append(['restore', restore_yes])

    # input props
    hosts = []
    if deploy_state == DEPLOYED:
        if restore_yes:
            meta += DeployUtil().get_meta_from_props(props_path)
            hosts = config.get_props(props_path, 'sr2_redis_master_hosts')
        else:
            if not os.path.isdir(conf_backup_path):
                os.mkdir(conf_backup_path)
            if os.path.exists(tmp_backup_path):
                msg = message.get('ask_load_history_of_previous_modification')
                yes = ask_util.askBool(msg)
                if not yes:
                    shutil.rmtree(tmp_backup_path)
            if not os.path.exists(tmp_backup_path):
                os.mkdir(tmp_backup_path)
                shutil.copy(os.path.join(conf_path, 'redis.properties'),
                            os.path.join(tmp_backup_path, 'redis.properties'))
            tmp_props_path = os.path.join(tmp_backup_path, 'redis.properties')
            editor.edit(tmp_props_path, syntax='sh')
            meta += DeployUtil().get_meta_from_props(tmp_props_path)
            hosts = config.get_props(tmp_props_path, 'sr2_redis_master_hosts')
    else:
        # new deploy
        props_dict = ask_util.props(cluster_id, save=history_save)
        hosts = props_dict['hosts']
        meta += DeployUtil().get_meta_from_dict(props_dict)
    utils.print_table(meta)

    msg = message.get('confirm_deploy_information')
    yes = ask_util.askBool(msg)
    if not yes:
        logger.info(message.get('cancel'))
        return

    # check node status
    success = Center().check_hosts_connection(hosts, True)
    if not success:
        msg = message.get('error_exist_unavailable_host')
        logger.error(msg)
        return
    logger.debug('Connection of all hosts ok.')
    success = Center().check_include_localhost(hosts)
    if not success:
        no_localhost = True

    # get port info
    if deploy_state == DEPLOYED:
        if restore_yes:
            key = 'sr2_redis_master_ports'
            m_ports = config.get_props(props_path, key, [])
            key = 'sr2_redis_slave_ports'
            s_ports = config.get_props(props_path, key, [])
            replicas = len(s_ports) // len(m_ports)
        else:
            key = 'sr2_redis_master_ports'
            m_ports = config.get_props(tmp_props_path, key, [])
            key = 'sr2_redis_slave_ports'
            s_ports = config.get_props(tmp_props_path, key, [])
            replicas = len(s_ports) // len(m_ports)
    else:
        m_ports = props_dict['master_ports']
        s_ports = props_dict['slave_ports']
        replicas = props_dict['replicas']

    while True:
        msg = message.get('check_port')
        logger.info(msg)
        host_ports_list = []
        for host in hosts:
            host_ports_list.append((host, m_ports + s_ports))
        conflict = Center().check_port_is_enable(host_ports_list)
        if not conflict:
            logger.info("OK")
            break
        utils.print_table([["HOST", "PORT"]] + conflict)
        msg = message.get('ask_port_collision')
        msg = color.yellow(msg)
        yes = ask_util.askBool(msg)
        if yes:
            logger.info("OK")
            break
        m_ports = ask_util.master_ports(False, cluster_id)
        replicas = ask_util.replicas(False)
        s_ports = ask_util.slave_ports(cluster_id, len(m_ports), replicas)
        if deploy_state == DEPLOYED:
            if restore_yes:
                key = 'sr2_redis_master_ports'
                value = cluster_util.convert_list_2_seq(m_ports)
                config.set_props(props_path, key, value)
                key = 'sr2_redis_slave_ports'
                value = cluster_util.convert_list_2_seq(s_ports)
                config.set_props(props_path, key, value)
            else:
                key = 'sr2_redis_master_ports'
                value = cluster_util.convert_list_2_seq(m_ports)
                config.set_props(tmp_props_path, key, value)
                key = 'sr2_redis_slave_ports'
                value = cluster_util.convert_list_2_seq(s_ports)
                config.set_props(tmp_props_path, key, value)
        else:
            props_dict['master_ports'] = m_ports
            props_dict['slave_ports'] = s_ports
            props_dict['replicas'] = replicas

    # if pending, delete legacy on each hosts
    if no_localhost:
        if DeployUtil().get_state(cluster_id, local_ip) == PENDING:
            client = net.get_ssh(local_ip)
            command = 'rm -rf {}'.format(cluster_path)
            net.ssh_execute(client=client, command=command)
            client.close()
    for host in hosts:
        if DeployUtil().get_state(cluster_id, host) == PENDING:
            client = net.get_ssh(host)
            command = 'rm -rf {}'.format(cluster_path)
            net.ssh_execute(client=client, command=command)
            client.close()

    # added_hosts = post_hosts - pre_hosts
    msg = message.get('check_cluster_exist')
    logger.info(msg)
    added_hosts = set(hosts)
    meta = []
    if deploy_state == DEPLOYED:
        pre_hosts = config.get_props(props_path, 'sr2_redis_master_hosts')
        added_hosts -= set(pre_hosts)
    can_deploy = True
    if no_localhost:
        added_hosts |= set([local_ip])
    for host in added_hosts:
        client = net.get_ssh(host)
        is_localhost = Center().is_localhost(host)
        if is_localhost:
            if no_localhost:
                continue
            if os.path.exists(cluster_path + '/remote'):
                meta.append([host, color.green('CLEAN')])
                continue
        if net.is_exist(client, cluster_path):
            meta.append([host, color.red('CLUSTER EXIST')])
            can_deploy = False
            continue
        meta.append([host, color.green('CLEAN')])
    if meta:
        utils.print_table([['HOST', 'STATUS']] + meta)
    if not can_deploy:
        msg = message.get('error_cluster_collision')
        logger.error(msg)
        return
        # if not force:
        #     logger.error("If you trying to force, use option '--force'")
        #     return
    logger.info('OK')

    # cluster stop and clean
    if deploy_state == DEPLOYED and clean:
        center = Center()
        cur_cluster_id = config.get_cur_cluster_id(allow_empty_id=True)
        run_cluster_use(cluster_id)
        center.update_ip_port()
        center.stop_redis()
        center.remove_all_of_redis_log_force()
        center.cluster_clean()
        run_cluster_use(cur_cluster_id)

    # backup conf
    if deploy_state == DEPLOYED:
        Center().conf_backup(local_ip, cluster_id, conf_backup_dir)

    # backup cluster
    backup_hosts = []
    if deploy_state == DEPLOYED:
        backup_hosts += set(pre_hosts)
    # if force:
    #     backup_hosts += added_hosts
    for host in backup_hosts:
        cluster_path = path_of_fb['cluster_path']
        client = net.get_ssh(host)
        Center().cluster_backup(host, cluster_id, cluster_backup_dir)
        client.close()

    # transfer & install
    msg = message.get('transfer_and_execute_installer')
    logger.info(msg)
    target_hosts = hosts + [local_ip] if no_localhost else hosts
    for host in target_hosts:
        if not (no_localhost and Center().is_localhost(host)):
            logger.info(' - {}'.format(host))
        client = net.get_ssh(host)
        cmd = 'mkdir -p {0} && touch {0}/.deploy.state'.format(cluster_path)
        net.ssh_execute(client=client, command=cmd)
        client.close()
        DeployUtil().transfer_installer(host, cluster_id, installer_path)
        try:
            DeployUtil().install(host, cluster_id, installer_name)
        except SSHCommandError as ex:
            msg = message.get('error_execute_installer')
            msg = msg.format(installer=installer_path)
            logger.error(msg)
            logger.exception(ex)
            return

    # setup props
    if deploy_state == DEPLOYED:
        if restore_yes:
            tag = conf_backup_dir
        else:
            tag = tmp_backup_dir
        Center().conf_restore(local_ip, cluster_id, tag)
    else:
        key = 'sr2_redis_master_hosts'
        config.make_key_enable(props_path, key)
        config.set_props(props_path, key, props_dict['hosts'])

        key = 'sr2_redis_master_ports'
        config.make_key_enable(props_path, key)
        value = cluster_util.convert_list_2_seq(props_dict['master_ports'])
        config.set_props(props_path, key, value)

        key = 'sr2_redis_slave_hosts'
        config.make_key_enable(props_path, key)
        config.set_props(props_path, key, props_dict['hosts'])
        config.make_key_disable(props_path, key)

        if props_dict['replicas'] > 0:
            key = 'sr2_redis_slave_hosts'
            config.make_key_enable(props_path, key)

            key = 'sr2_redis_slave_ports'
            config.make_key_enable(props_path, key)
            value = cluster_util.convert_list_2_seq(props_dict['slave_ports'])
            config.set_props(props_path, key, value)

        key = 'ssd_count'
        config.make_key_enable(props_path, key)
        config.set_props(props_path, key, props_dict['ssd_count'])

        key = 'sr2_redis_data'
        config.make_key_enable(props_path, key, v1_flg=True)
        config.make_key_enable(props_path, key, v1_flg=True)
        config.make_key_disable(props_path, key)
        config.set_props(props_path, key, props_dict['prefix_of_db_path'])

        key = 'sr2_redis_db_path'
        config.make_key_enable(props_path, key, v1_flg=True)
        config.make_key_enable(props_path, key, v1_flg=True)
        config.make_key_disable(props_path, key)
        config.set_props(props_path, key, props_dict['prefix_of_db_path'])

        key = 'sr2_flash_db_path'
        config.make_key_enable(props_path, key, v1_flg=True)
        config.make_key_enable(props_path, key, v1_flg=True)
        config.make_key_disable(props_path, key)
        config.set_props(props_path, key, props_dict['prefix_of_db_path'])

    # synk props
    msg = message.get('sync_conf')
    logger.info(msg)
    for node in hosts:
        if socket.gethostbyname(node) in config.get_local_ip_list():
            continue
        client = net.get_ssh(node)
        if not client:
            msg = message.get('error_ssh_connection').format(host=node)
            logger.error(msg)
            return
        net.copy_dir_to_remote(client, conf_path, conf_path)
        client.close()

    # set deploy state complete
    if os.path.exists(tmp_backup_path):
        shutil.rmtree(tmp_backup_path)
    for node in target_hosts:
        path_of_fb = config.get_path_of_fb(cluster_id)
        cluster_path = path_of_fb['cluster_path']
        client = net.get_ssh(node)
        cmd = 'rm -rf {}'.format(os.path.join(cluster_path, '.deploy.state'))
        net.ssh_execute(client=client, command=cmd)
        client.close()
    if no_localhost:
        os.system('touch {}/remote'.format(cluster_path))

    msg = message.get('complete_deploy').format(cluster_id=cluster_id)
    logger.info(msg)
    Cluster().use(cluster_id)
    msg = message.get('suggest_after_deploy')
    logger.info(msg)
コード例 #22
0
    def do_replicate(self, slave, master):
        """ Replicate a slave node to a master node.
            Use like 'cluster replicate {slave's ip}:{slave's port} {master's ip}:{master's port}

        :param slave: {slave's ip or hostname}:{slave's port}
        :param master: {master's ip or hostname}:{master's port}
        """
        logger.debug('do_replicate')
        # Get master's uuid
        s_hostname, s_port = slave.split(':')
        m_hostname, m_port = master.split(':')
        s_host = socket.gethostbyname(s_hostname)
        m_host = socket.gethostbyname(m_hostname)
        cluster_id = config.get_cur_cluster_id()
        lib_path = config.get_ld_library_path(cluster_id)
        path_of_fb = config.get_path_of_fb(cluster_id)
        sr2_redis_bin = path_of_fb['sr2_redis_bin']
        env_cmd = [
            'GLOBIGNORE=*;',
            'export LD_LIBRARY_PATH={};'.format(lib_path['ld_library_path']),
            'export DYLD_LIBRARY_PATH={};'.format(
                lib_path['dyld_library_path']),
        ]
        redis_cli_cmd = os.path.join(sr2_redis_bin, 'redis-cli')
        sub_cmd = 'cluster nodes'
        command = '{} {} -h {} -p {} {}'.format(
            ' '.join(env_cmd),
            redis_cli_cmd,
            s_host,
            s_port,
            sub_cmd,
        )
        stdout = subprocess.check_output(command, shell=True)
        outs = ''
        outs = '\n'.join([outs, stdout])
        lines = outs.splitlines()
        m_ip_port = m_host + str(':') + m_port
        filtered_lines = (filter(lambda x: m_ip_port in x, lines))
        if len(filtered_lines) == 0:
            msg = message.get('error_need_cluster_meet')
            self._print(msg)
            msg = message.get('cluster_meet')
            self._print(msg)
            # Cluster meet
            sub_cmd = 'cluster meet {ip} {port}'.format(ip=m_host, port=m_port)
            command = '{} {} -h {} -p {} {}'.format(
                ' '.join(env_cmd),
                redis_cli_cmd,
                s_host,
                s_port,
                sub_cmd,
            )
            stdout = subprocess.check_output(command, shell=True)
            self._print(stdout)
            # Get master's uuid
            sub_cmd = 'cluster nodes'
            command = '{} {} -h {} -p {} {}'.format(
                ' '.join(env_cmd),
                redis_cli_cmd,
                s_host,
                s_port,
                sub_cmd,
            )
            stdout = subprocess.check_output(command, shell=True)
            outs = ''
            outs = '\n'.join([outs, stdout])
            lines = outs.splitlines()
            filtered_lines = (filter(lambda x: m_ip_port in x, lines))
            m_uuid = filtered_lines[0].split()[0]
        else:
            m_uuid = filtered_lines[0].split()[0]

        if len(m_uuid) == 0:
            msg = message.get('error_no_uuid')
            raise ClusterRedisError(msg)

        # Replicate
        msg = message.get('start_replicate')
        self._print(msg)
        sub_cmd = 'cluster replicate {uuid}'.format(uuid=m_uuid)
        command = '{} {} -h {} -p {} {}'.format(
            ' '.join(env_cmd),
            redis_cli_cmd,
            s_host,
            s_port,
            sub_cmd,
        )
        stdout = subprocess.check_output(command, shell=True)
        outs = ''
        outs = '\n'.join([outs, stdout])
        self._print(outs)