def rsync_fb_conf(): logger.info('Sync conf...') cluster_id = config.get_cur_cluster_id() if not validate_id(cluster_id): logger.warn('Invalid cluster id: {}'.format(cluster_id)) return cluster_list = get_cluster_list() if cluster_id not in cluster_list: logger.warn('Cluster not exist: {}'.format(cluster_id)) return my_address = config.get_local_ip_list() path_of_fb = config.get_path_of_fb(cluster_id) props_path = path_of_fb['redis_properties'] key = 'sr2_redis_master_hosts' nodes = config.get_props(props_path, key, []) meta = [['HOST', 'RESULT']] path_of_fb = config.get_path_of_fb(cluster_id) conf_path = path_of_fb['conf_path'] cluster_path = path_of_fb['cluster_path'] for node in nodes: if net.get_ip(node) in my_address: meta.append([node, color.green('OK')]) continue client = net.get_ssh(node) if not client: meta.append([node, color.red('SSH ERROR')]) continue if not net.is_dir(client, cluster_path): meta.append([node, color.red('NO CLUSTER')]) continue net.copy_dir_to_remote(client, conf_path, conf_path) meta.append([node, color.green('OK')]) utils.print_table(meta)
def _import_from_fb_to_cli_conf(rp_exists): for cluster_id in rp_exists: path_of_fb = config.get_path_of_fb(cluster_id) rp = path_of_fb['redis_properties'] d = config.get_props_as_dict(rp) nodes = d['sr2_redis_master_hosts'] master_start_port = 0 master_end_port = 0 slave_start_port = 0 slave_end_port = 0 master_enabled = 'sr2_redis_master_ports' in d slave_enabled = 'sr2_redis_slave_ports' in d if master_enabled: master_start_port = min(d['sr2_redis_master_ports']) master_end_port = max(d['sr2_redis_master_ports']) if slave_enabled: slave_start_port = min(d['sr2_redis_slave_ports']) slave_end_port = max(d['sr2_redis_slave_ports']) ssd_count = d['ssd_count'] _to_config_yaml(cluster_id=cluster_id, release='', nodes=nodes, master_start_port=master_start_port, master_end_port=master_end_port, master_enabled=master_enabled, slave_start_port=slave_start_port, slave_end_port=slave_end_port, slave_enabled=slave_enabled, ssd_count=ssd_count) logger.info('Save config.yaml from redis.properties')
def run_delete(cluster_id=None): if not cluster_id: cluster_id = config.get_cur_cluster_id() valid = cluster_util.validate_id(cluster_id) if not valid: logger.error('Invalid cluster id: {}'.format(cluster_id)) return if cluster_id not in cluster_util.get_cluster_list(): logger.error('Cluster not exist: {}'.format(cluster_id)) return cluster = Cluster() cluster.stop(force=True, reset=True) # delete cluster folder cli_cluster_path = config.get_path_of_cli(cluster_id)["cluster_path"] path_of_fb = config.get_path_of_fb(cluster_id) fb_cluster_path = path_of_fb["cluster_path"] props_path = path_of_fb['redis_properties'] key = 'sr2_redis_master_hosts' nodes = config.get_props(props_path, key, []) for node in nodes: client = get_ssh(node) cmd = [ 'rm -rf {};'.format(fb_cluster_path), 'rm -rf {}'.format(cli_cluster_path), ] ssh_execute(client=client, command=' '.join(cmd)) client.close() if config.get_cur_cluster_id() == cluster_id: cluster.use(-1)
def get_state(self, cluster_id, host='127.0.0.1'): path_of_fb = config.get_path_of_fb(cluster_id) cluster_path = path_of_fb['cluster_path'] state_file = path_join(cluster_path, '.deploy.state') client = get_ssh(host) if net.is_exist(client, state_file): return PENDING if net.is_dir(client, cluster_path): return DEPLOYED return CLEAN
def _get_cluster_ids_from_fb(): cluster_id = config.get_cur_cluster_id() path_of_fb = config.get_path_of_fb(cluster_id) base_directory = path_of_fb['base_directory'] dirs = [ f for f in os.listdir(base_directory) if not os.path.isfile(os.path.join(base_directory, f)) ] cluster_ids = [d.split('_')[1] for d in dirs if 'cluster_' in d] return cluster_ids
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'] slave_template = path_of_fb['slave_template'] RedisCliUtil._save_config(master_template, key, value) RedisCliUtil._save_config(slave_template, key, value)
def is_pending(self, cluster_id, nodes=['127.0.0.1']): if type(nodes) is type(str()): nodes = [nodes] for node in nodes: path_of_fb = config.get_path_of_fb(cluster_id) cluster_path = path_of_fb['cluster_path'] deploy_state = path_join(cluster_path, '.deploy.state') client = get_ssh(node) if net.is_exist(client, deploy_state): client.close() return True client.close() return False
def conf_restore(self, host, cluster_id, tag): logger.debug('Restore conf to cluster {}...'.format(cluster_id)) # prepare path_of_fb = config.get_path_of_fb(cluster_id) path_of_cli = config.get_path_of_cli(cluster_id) conf_path = path_of_fb['conf_path'] conf_backup_path = path_of_cli['conf_backup_path'] conf_backup_tag_path = path_join(conf_backup_path, tag) # restore conf client = get_ssh(host) net.copy_dir_to_remote(client, conf_backup_tag_path, conf_path) client.close() logger.debug('OK')
def get_cluster_list(): path_of_fb = config.get_path_of_fb(None) base_dir = path_of_fb['base_directory'] buf = os.listdir(base_dir) buf = filter(lambda x: x.startswith('cluster_'), buf) buf = map(lambda x: int(x[8:]), buf) cluster_list = [] for cluster_id in buf: cluster_id = int(cluster_id) cluster_dir = 'cluster_{}'.format(cluster_id) cluster_path = os.path.join(base_dir, cluster_dir) if not os.path.isfile(os.path.join(cluster_path, '.deploy.state')): cluster_list.append(cluster_id) cluster_list.sort() return list(cluster_list)
def install(self, host, cluster_id, name): logger.debug('Deploy cluster {} at {}...'.format(cluster_id, host)) path_of_fb = config.get_path_of_fb(cluster_id) release_path = path_of_fb['release_path'] cluster_path = path_of_fb['cluster_path'] if '/' in name: name = os.path.basename(name) installer_path = path_join(release_path, name) command = '''chmod 755 {0}; \ PATH=${{PATH}}:/usr/sbin; \ {0} --full {1}'''.format(installer_path, cluster_path) client = get_ssh(host) ssh_execute(client=client, command=command) client.close() logger.debug('OK')
def cluster_backup(self, host, cluster_id, tag): logger.info('Backup cluster {} at {}...'.format(cluster_id, host)) # prepare path_of_fb = config.get_path_of_fb(cluster_id) cluster_path = path_of_fb['cluster_path'] cluster_backup_path = path_of_fb['cluster_backup_path'] cluster_backup_tag_path = path_join(cluster_backup_path, tag) # back up cluster client = get_ssh(host) if not net.is_dir(client, cluster_backup_path): sftp = get_sftp(client) sftp.mkdir(cluster_backup_path) sftp.close() command = 'mv {} {}'.format(cluster_path, cluster_backup_tag_path) ssh_execute(client=client, command=command) client.close() logger.info('OK, {}'.format(tag))
def conf_backup(self, host, cluster_id, tag): logger.info('Backup conf of cluster {}...'.format(cluster_id)) # prepare path_of_fb = config.get_path_of_fb(cluster_id) conf_path = path_of_fb['conf_path'] path_of_cli = config.get_path_of_cli(cluster_id) conf_backup_path = path_of_cli['conf_backup_path'] conf_backup_tag_path = path_join(conf_backup_path, tag) if not os.path.isdir(conf_backup_path): os.mkdir(conf_backup_path) # back up conf os.mkdir(conf_backup_tag_path) client = get_ssh(host) net.copy_dir_from_remote(client, conf_path, conf_backup_tag_path) client.close() logger.info('OK, {}'.format(tag))
def update_redis_conf(self): """Update redis config """ logger.debug('update_redis_conf') self._update_ip_port() cluster_id = config.get_cur_cluster_id() path_of_fb = config.get_path_of_fb(cluster_id) master_template_path = path_of_fb['master_template'] slave_template_path = path_of_fb['slave_template'] for ip in self.ip_list: client = get_ssh(ip) redis_conf_dir = path_join(path_of_fb['conf_path'], 'redis') ssh_execute(client=client, command='mkdir -p %s' % redis_conf_dir) self._update_redis_conf(client, master_template_path, redis_conf_dir, ip, self.master_port_list) self._update_redis_conf(client, slave_template_path, redis_conf_dir, ip, self.slave_port_list) client.close() logger.info('update_redis_conf complete')
def edit(self): """Open vim to edit config file""" cluster_id = config.get_cur_cluster_id() path_of_fb = config.get_path_of_fb(cluster_id) # path_of_cli = config.get_path_of_cli(cluster_id) # if not os.path.exists(path_of_cli['cluster_path']): # logger.debug( # "FileNotExisted: '{}'".format( # path_of_cli['cluster_path'])) # os.system('mkdir -p {}'.format(path_of_cli['cluster_path'])) # logger.debug("CreateDir: '{}'".format(path_of_cli['cluster_path'])) # if not os.path.exists(path_of_cli['conf_path']): # logger.debug( # "FileNotExisted: '{}'".format( # path_of_cli['conf_path'])) # shutil.copytree(path_of_fb['conf_path'], path_of_cli['conf_path']) # logger.debug("CopyTree: '{}'".format(path_of_cli['cluster_path'])) editor.edit(path_of_fb['redis_properties'], syntax='sh') cluster_util.rsync_fb_conf()
def transfer_installer(self, host, cluster_id, installer_path): installer_path = os.path.expanduser(installer_path) path_of_fb = config.get_path_of_fb(cluster_id) name = os.path.basename(installer_path) dst = path_join(path_of_fb['release_path'], name) client = get_ssh(host) sftp = get_sftp(client) if not net.is_dir(client, path_of_fb['release_path']): logger.debug("Not exist releases directory at '{}'".format(host)) sftp.mkdir(path_of_fb['release_path']) logger.debug("Create releases directory at '{}'".format(host)) logger.debug('Check {}...'.format(name)) if not net.is_exist(client, dst): logger.debug('FAIL') logger.debug("Transfer '{}' to '{}'...".format(name, host)) sftp.put(installer_path, '{}.download'.format(dst)) command = 'mv {0}.download {0}'.format(dst) ssh_execute(client=client, command=command) sftp.close() client.close() logger.debug('OK')
def run_import_conf(): def _to_config_yaml(cluster_id, release, nodes, master_start_port, master_end_port, master_enabled, slave_start_port, slave_end_port, slave_enabled, ssd_count): conf = {} conf['release'] = release conf['nodes'] = nodes conf['ssd'] = {} conf['master_ports'] = {} conf['slave_ports'] = {} conf['master_ports']['from'] = int(master_start_port) conf['master_ports']['to'] = int(master_end_port) conf['master_ports']['enabled'] = bool(master_enabled) conf['slave_ports']['from'] = int(slave_start_port) conf['slave_ports']['to'] = int(slave_end_port) conf['slave_ports']['enabled'] = bool(slave_enabled) conf['ssd']['count'] = int(ssd_count) root_of_cli_config = get_root_of_cli_config() cluster_base_path = path_join(root_of_cli_config, 'clusters') if not os.path.isdir(cluster_base_path): os.mkdir(cluster_base_path) cluster_path = path_join(root_of_cli_config, 'clusters', cluster_id) if not os.path.isdir(cluster_path): os.mkdir(cluster_path) yaml_path = path_join(cluster_path, 'config.yaml') with open(yaml_path, 'w') as fd: yaml.dump(conf, fd, default_flow_style=False) def _import_from_fb_to_cli_conf(rp_exists): for cluster_id in rp_exists: path_of_fb = config.get_path_of_fb(cluster_id) rp = path_of_fb['redis_properties'] d = config.get_props_as_dict(rp) nodes = d['sr2_redis_master_hosts'] master_start_port = 0 master_end_port = 0 slave_start_port = 0 slave_end_port = 0 master_enabled = 'sr2_redis_master_ports' in d slave_enabled = 'sr2_redis_slave_ports' in d if master_enabled: master_start_port = min(d['sr2_redis_master_ports']) master_end_port = max(d['sr2_redis_master_ports']) if slave_enabled: slave_start_port = min(d['sr2_redis_slave_ports']) slave_end_port = max(d['sr2_redis_slave_ports']) ssd_count = d['ssd_count'] _to_config_yaml(cluster_id=cluster_id, release='', nodes=nodes, master_start_port=master_start_port, master_end_port=master_end_port, master_enabled=master_enabled, slave_start_port=slave_start_port, slave_end_port=slave_end_port, slave_enabled=slave_enabled, ssd_count=ssd_count) logger.info('Save config.yaml from redis.properties') def _get_cluster_ids_from_fb(): cluster_id = config.get_cur_cluster_id() path_of_fb = config.get_path_of_fb(cluster_id) base_directory = path_of_fb['base_directory'] dirs = [ f for f in os.listdir(base_directory) if not os.path.isfile(os.path.join(base_directory, f)) ] cluster_ids = [d.split('_')[1] for d in dirs if 'cluster_' in d] return cluster_ids cluster_ids = _get_cluster_ids_from_fb() root_of_cli_config = get_root_of_cli_config() rp_exists = [] rp_not_exists = [] dest_folder_exists = [] meta = [['cluster_id', 'state']] for cluster_id in cluster_ids: path_of_fb = config.get_path_of_fb(cluster_id) rp = path_of_fb['redis_properties'] dest_path = path_join(root_of_cli_config, 'clusters', cluster_id) dest_path = path_join(dest_path, 'config.yaml') cluster_path = path_of_fb['cluster_path'] deploy_state = path_join(cluster_path, '.deploy.state') pending = DeployUtil().is_pending(cluster_id) if os.path.exists(dest_path): dest_folder_exists.append(cluster_id) meta.append([cluster_id, 'SKIP(dest_exist)']) elif os.path.isfile(rp) and not os.path.isfile(deploy_state): rp_exists.append(cluster_id) meta.append([cluster_id, 'IMPORT']) else: rp_not_exists.append(cluster_id) meta.append([cluster_id, 'SKIP(broken)']) logger.info('Diff fb and cli conf folders.') utils.print_table(meta) if len(rp_exists) == 0: return import_yes = askBool('Do you want to import conf?', ['y', 'n']) if not import_yes: return _import_from_fb_to_cli_conf(rp_exists)
def _deploy(cluster_id, history_save): deploy_state = DeployUtil().get_state(cluster_id) if deploy_state == DEPLOYED: q = [ color.YELLOW, '(Watch out) ', 'Cluster {} is already deployed. '.format(cluster_id), 'Do you want to deploy again?', color.ENDC, ] yes = askBool(''.join(q), default='n') if not yes: logger.info('Cancel deploy.') return restore_yes = None current_time = strftime("%Y%m%d%H%M%s", 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 = 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('Do you want to 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 os.path.exists(tmp_backup_path): q = 'There is a history of modification. Do you want to load?' yes = ask_util.askBool(q) if not yes: shutil.rmtree(tmp_backup_path) if not os.path.exists(tmp_backup_path): shutil.copytree(conf_path, tmp_backup_path) tmp_props_path = 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: 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 = [ 'Do you want to proceed with the deploy ', 'accroding to the above information?', ] yes = askBool(''.join(msg)) if not yes: logger.info("Cancel deploy.") return # check node status logger.info('Check status of hosts...') success = Center().check_hosts_connection(hosts, True) if not success: logger.error('There are unavailable host') return logger.debug('Connection of all hosts ok') success = Center().check_include_localhost(hosts) if not success: logger.error('Must include localhost') return # if pending, delete legacy on each hosts for host in hosts: if DeployUtil().get_state(cluster_id, host) == PENDING: client = get_ssh(host) command = 'rm -rf {}'.format(cluster_path) ssh_execute(client=client, command=command) client.close() # added_hosts = post_hosts - pre_hosts logger.info('Checking for cluster exist...') meta = [['HOST', 'STATUS']] added_hosts = set(hosts) if deploy_state == DEPLOYED: pre_hosts = config.get_props(props_path, 'sr2_redis_master_hosts') added_hosts -= set(pre_hosts) can_deploy = True for host in added_hosts: client = get_ssh(host) if net.is_exist(client, cluster_path): meta.append([host, color.red('CLUSTER EXIST')]) can_deploy = False continue meta.append([host, color.green('CLEAN')]) utils.print_table(meta) if not can_deploy: logger.error('Cluster information exist on some hosts.') return # if not force: # logger.error("If you trying to force, use option '--force'") # return # 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 = get_ssh(host) Center().cluster_backup(host, cluster_id, cluster_backup_dir) client.close() # transfer & install logger.info('Transfer installer and execute...') for host in hosts: logger.info(host) client = get_ssh(host) cmd = 'mkdir -p {0} && touch {0}/.deploy.state'.format(cluster_path) ssh_execute(client=client, command=cmd) client.close() DeployUtil().transfer_installer(host, cluster_id, installer_path) DeployUtil().install(host, cluster_id, installer_name) # 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_rdp']) 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_rdbp']) 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_fdbp']) # synk props logger.info('Sync conf...') for node in hosts: if socket.gethostbyname(node) in config.get_local_ip_list(): continue client = get_ssh(node) if not client: logger.error("ssh connection fail: '{}'".format(node)) 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 hosts: home_path = net.get_home_path(node) if not home_path: return path_of_fb = config.get_path_of_fb(cluster_id) cluster_path = path_of_fb['cluster_path'] client = get_ssh(node) command = 'rm -rf {}'.format(path_join(cluster_path, '.deploy.state')) ssh_execute(client=client, command=command) client.close() logger.info('Complete to deploy cluster {}'.format(cluster_id)) Cluster().use(cluster_id)