2021-07-12 19:26:30 +08:00

490 lines
20 KiB
Python

#!/usr/bin/python
# -*- coding:utf-8 _*-
# python wjtx.py createconfig -f game1130.xlsx
# python wjtx.py addproject -f game1130.xlsx
# python wjtx.py initdb -s 310-315
# python wjtx.py changestatus -m maintain -o remove -s 295-300
# python wjtx.py autoload
import click
import json
import redis
import xlrd
from ops.mmysql import MysqlBase
import logging
import datetime
from ops.common import run_cmd
from ops.plog import define_logger
from ops.mansible import AnsiInterface, write_host
import time
import uuid
import os
Global_redis_1009 = {"host": "10.10.6.4", "port": "6379", "db": 0}
Global_redis_1012 = {"host": "10.10.6.6", "port": "6379", "db": 0}
Ywplatform_db = {"host": '10.10.3.5', "user": "root",
"pswd": "0usmUwROtWjf", "port": 3306}
Legend_db = {"host": '10.10.6.2', "user": "wjtx",
"pswd": "mMWA4DKCfeOL", "port": 3306}
rule = {"union": 1000, "huawei": 2000, "xiaomi": 3000, "oppo": 4000}
Methods_values = {"hide": 3, "new": 1, "hot": 2, "maintain": 0}
define_logger(filename="/data/logs/wjtx_tools.log")
log = logging.getLogger(__name__)
@click.group()
def main():
pass
@main.command()
@click.option('-g', '--gameid', type=click.Choice(['1009', '1012']), default='1009', help='gameid', required=True)
@click.option('-s', '--serverid', type=int, help='serverid', required=True)
@click.option('-t', '--times', type=str, help='重置开服的时间', required=True)
def changeservertime(times, gameid, serverid):
wjtx = Wjtx_tools(gameid)
wjtx.change_server_opentime(serverid, times)
@main.command()
@click.option('-g', '--gameid', type=click.Choice(['1009', '1012']), default='1009', help='gameid')
@click.option('-s', '--serverid', type=str, help='serverid', required=True)
def initdb(gameid, serverid):
wjtx = Wjtx_tools(gameid)
wjtx.init_wjtx_mysql(serverid)
@main.command()
@click.option('-g', '--gameid', type=click.Choice(['1009', '1012']), default='1009', help='gameid', required=True)
def createhostlist(gameid):
wjtx = Wjtx_tools(gameid)
wjtx.create_alive_host()
@main.command()
@click.option('-g', '--gameid', type=click.Choice(['1009', '1012']), default='1009', help='gameid', required=True)
def autoload(gameid):
wjtx = Wjtx_tools(gameid)
wjtx.ops_autoload()
@main.command()
@click.option('-g', '--gameid', type=click.Choice(['1009', '1012']), default='1009', help='gameid', required=True)
@click.option('-f', '--filename', type=str, help='脚本路径', required=True)
def addproject(gameid, filename):
wjtx = Wjtx_tools(gameid)
wjtx.add_ops_projectmanage(filename)
@main.command()
@click.option('-g', '--gameid', type=click.Choice(['1009', '1012']), default='1009', help='gameid', required=True)
@click.option('-f', '--filename', type=str, help='脚本路径', required=True)
def createconfig(gameid, filename):
wjtx = Wjtx_tools(gameid)
wjtx.create_config(filename)
@main.command()
@click.option('-g', '--gameid', type=click.Choice(['1009', '1012']), default='1009', help='gameid', required=True)
@click.option('-s', '--serverid', type=str, help='操作的serverids', required=True)
@click.option('-m', '--method', default='maintain', required=True,
type=click.Choice(['maintain', 'hide', 'new', 'hot']), help='维护、隐藏、新服、热点')
@click.option('-o', '--operate', help='操作方法 add/remove', default='add', required=True,
type=click.Choice(['add', 'remove']))
def changestatus(gameid, method, operate, serverid):
wjtx = Wjtx_tools(gameid)
wjtx.change_server_status(serverid, method, operate)
class Wjtx_tools:
def __init__(self, gameid):
self.gameid = gameid
if self.gameid == '1009':
self.redis_conn = redis.Redis(host=Global_redis_1009['host'], port=Global_redis_1009['port'],
charset='utf8', db=Global_redis_1009.get('db') or 0, decode_responses=True)
elif self.gameid == '1012':
self.redis_conn = redis.Redis(host=Global_redis_1012['host'], port=Global_redis_1012['port'],
charset='utf8', db=Global_redis_1012.get('db') or 0, decode_responses=True)
else:
log.error(f"gameid={self.gameid} not in define!")
raise Exception(f"gameid={self.gameid} not in define!")
def create_alive_host(self):
hosts = list()
data = self.redis_conn.hgetall('game_info')
for line in data.values():
recode = json.loads(line)
if (int(recode['areaId']) % 100 + 9000) == int(recode['tcpPort']) and recode['status'] == 1:
hosts.append(recode['externalIp'])
hosts = list(set(hosts))
hosts.sort()
filename = ""
if self.gameid == "1009":
filename = "wjtx_1009.host"
elif self.gameid == "1012":
filename = "wjtx_1012.host"
if hosts:
log.info(f"write hosts with {filename}")
with open(filename, 'w') as f:
f.write('\n'.join(hosts))
else:
log.error("get host from wjtx redis failed!")
def create_config(self, filename):
n_cols = ["ptname", "serverid", "ip", "port",
"port_2", "redis_port", "servername"]
cols_str = ["serverid", "port", "port_2", "redis_port"]
cols_unicode = ["servername"]
data = self._read_excel(filename)
for i in range(0, len(data)):
if data[i][0]:
temp = {}
for j in range(0, len(n_cols)):
if n_cols[j] in cols_unicode:
temp[n_cols[j]] = json.dumps(data[i][j])[1:-1]
elif n_cols[j] in cols_str:
temp[n_cols[j]] = str(int(data[i][j]))
else:
temp[n_cols[j]] = data[i][j]
self._build_wjtx_config(temp)
def _build_wjtx_config(self, data):
for server_type in ['game', 'stage']:
if server_type == "stage":
data['port'] = str(int(data['port']) - 2000)
template_file = f"{server_type}_{self.gameid}.sample"
with open(template_file, 'r') as f:
templates = f.read()
try:
new = templates.format(**data)
except Exception:
raise Exception(f"fill {data} failed!")
# config_path=fr"D:\ops\SVN\prod\{server_type}{self.gameid}"
# filename = f"{config_path}\{server_type}server\config\conf/application-{data['serverid']}.properties"
config_paths = os.sep.join(
['', 'data', 'publish', 'prod', "game" + self.gameid, server_type + 'server', 'config', 'conf'])
full_name = config_paths + os.sep + \
f"application-{data['serverid']}.properties"
log.info(f"write config with {full_name}")
if not os.path.isdir(config_paths):
os.makedirs(config_paths)
with open(full_name, 'w') as f:
f.write(new)
def change_server_status(self, serverid, method, operate):
serverlist = list()
if len(serverid.split('-')) == 2:
begin = int(serverid.split('-')[0])
end = int(serverid.split('-')[1]) + 1
for i in range(begin, end):
serverlist.append(i)
else:
serverlist = serverid.split(",")
key = "server_state"
for serverid in serverlist:
old = self.redis_conn.hget(key, serverid)
if old == "":
raise Exception(f"get serverid failed ,{serverid},{old}")
if operate == 'remove':
new = self._unSetBitFlag(old, Methods_values.get(method))
else:
new = self._setBitFlag(old, Methods_values.get(method))
values = f"{serverid}-{new}"
log.info(
f"serverid={serverid} {old} {method} {operate} set to {values}")
self.redis_conn.hset(key, serverid, new)
self.redis_conn.publish("server_state_web_publish", values)
def ops_autoload(self):
alive_server = list()
alive_server = self._get_alive_server()
game_recode = self._get_server_info(alive_server, 'game')
project_name = f'game{self.gameid}game'
self._add_recode2mysql(project_name, game_recode)
stage_recode = self._get_server_info(alive_server, 'stage')
project_name = f'game{self.gameid}stage'
self._add_recode2mysql(project_name, stage_recode)
def add_ops_projectmanage(self, filename):
data = self._build_excel_data(self._read_excel(filename))
ip_serverid, ip_redis = self._format_servcice_info(data)
assert self._check_host(ip_serverid.keys())
assert self._check_redis(ip_redis)
self._change_ops_projectmanage(ip_serverid)
def change_server_opentime(self, serverid, times):
Legend_db['db'] = f"legend_{serverid}"
mysql_conn = MysqlBase(**Legend_db)
tablename = "server_info"
u_data = {'start_time': times}
mysql_conn.update(tablename, u_data, True)
host_info = json.loads(self.redis_conn.hget('game_info', serverid))
hostip = host_info.get('innerIp', None)
assert hostip
restart_cmd = f"su - kingsome -c 'cd /data/apps/game{self.gameid}game && sh restart.sh {serverid}'"
hostfilename = write_host(hostip)
time.sleep(10)
myansible = AnsiInterface(hostfilename)
resule = myansible.exec_command(restart_cmd)
if not (resule['failed'] or resule['unreachable']):
log.info(f"restart {serverid} success!")
else:
log.error(f"restart {serverid} failed,output was {resule}")
def init_wjtx_mysql(self, serverid):
sids = list()
if len(str(serverid).split("-")) == 2:
begin = serverid.split('-')[0]
end = int(serverid.split('-')[1]) + 1
assert begin, end
for i in range(int(begin), int(end)):
sids.append(i)
else:
sids = serverid.split(",")
for sid in sids:
mysql_conn = f"mysql -u{Legend_db['user']} -p{Legend_db['pswd']} -h{Legend_db['host']}"
create_sql = f"create database legend_{sid} default character set utf8mb4 collate utf8mb4_unicode_ci;create database logger_{sid} default character set utf8mb4 collate utf8mb4_unicode_ci;"
create_db_cmd = f"{mysql_conn} -e'{create_sql}'"
status, out = run_cmd(create_db_cmd)
if not status:
log.error(f"create db error {out}")
raise Exception(out)
else:
log.info(f"create db=legend_{sid},logger_{sid}")
create_table_sql = f"{mysql_conn} legend_{sid} -e'source sql/wjtx_game.sql'"
status, out = run_cmd(create_table_sql)
if not status:
log.error(f"init db error {out}")
raise Exception(out)
self.redis_conn.hset('game_stage', sid, sid)
log.info(f"add {sid} to redis key=game_stage!")
def _change_ops_projectmanage(self, ip_serverid):
Ywplatform_db['db'] = 'ywplatform'
ywplatform = MysqlBase(**Ywplatform_db)
condition = ""
services = list()
if self.gameid == "1009":
condition = f"env='prod' and project_name in ('game1009game','game1009stage','game1009conf')"
services = ['game1009game', 'game1009stage', 'game1009conf']
elif self.gameid == "1012":
condition = f"env='prod' and project_name in ('game1012game','game1012stage','game1012conf')"
services = ['game1012game', 'game1012stage', 'game1012conf']
remark = {"remark": 1}
ywplatform.update('deploy_projectmanage', remark, condition)
for service in services:
get_service_conf_sql = f"""SELECT project_address, config_address
FROM deploy_projectmanage
WHERE project_name = '{service}'
AND env = 'prod'
LIMIT 1;"""
service_conf = ywplatform.query(get_service_conf_sql)
if not service_conf:
log.error(
f"get service={service} from deploy_projectmanage failed!")
raise Exception(
f"get service={service} from deploy_projectmanage failed!")
project_address, config_address = service_conf[0]
for ip in ip_serverid.keys():
check_sql = f"""SELECT run_server, run_script
FROM `deploy_projectmanage`
WHERE project_name = '{service}'
AND env = 'prod'
AND run_server = '{ip}';"""
data = ywplatform.query(check_sql)
if not data:
temp = {}
temp['sid'] = uuid.uuid4().hex
temp['project_name'] = service
temp['compile_script'] = 'boundle.sh'
temp['run_script'] = f'sh restart.sh {ip_serverid[ip]}'
temp['env'] = 'prod'
temp['run_server'] = f'{ip}'
temp['remark'] = '0'
temp['update_time'] = datetime.datetime.now().strftime(
"%Y-%m-%d %H:%M:%S")
temp['create_time'] = datetime.datetime.now().strftime(
"%Y-%m-%d %H:%M:%S")
temp['user_id'] = '4'
temp['port'] = 7000
temp['reload_script'] = 'sh reload.sh'
temp['res_address'] = ''
temp['res_reload_script'] = 'sh reloadres.sh'
temp['is_monitor'] = '1'
temp['is_tmp'] = '0'
temp['region'] = ''
temp['is_scaling'] = '0'
temp['project_address'] = project_address
temp['config_address'] = config_address
log.info(f"add recode with {service} {temp['run_server']}")
ywplatform.insert('deploy_projectmanage', temp)
else:
log.error(f"{ip} {service} was in db!")
def _check_host(self, ips):
for key in ips:
cmd = f"ping {key} -c 1 -s 1 -W 1 | grep '100% packet loss'|wc -l"
status, out = run_cmd(cmd)
if status and out.decode().strip() == '0':
pass
else:
return False
print(f"check ip with {ips} success!")
return True
def _check_redis(self, ip_redis):
for key in ip_redis:
for port in ip_redis[key].split(','):
try:
_ = redis.Redis(host=key, port=port, charset='utf8')
except:
return False
print(f"check redis {ip_redis} success!")
return True
def _format_servcice_info(self, data):
ip_serverid = dict()
ip_redis = dict()
for line in data:
if ip_serverid.get(line['ip'], None):
ip_serverid[line['ip']
] = f"{ip_serverid[line['ip']]},{line['serverid']}"
else:
ip_serverid[line['ip']] = line['serverid']
if ip_redis.get(line['ip'], None):
ip_redis[line['ip']
] = f"{ip_redis[line['ip']]},{line['redis_port']}"
else:
ip_redis[line['ip']] = line['redis_port']
return ip_serverid, ip_redis
def _build_excel_data(self, data):
out_data = list()
n_cols = ["ptname", "serverid", "ip", "port",
"port_2", "redis_port", "servername"]
cols_unicode = ["servername"]
cols_str = ["serverid", "port", "port_2", "redis_port"]
for i in range(0, len(data)):
if data[i][0]:
temp = {}
for j in range(0, len(n_cols)):
if n_cols[j] in cols_unicode:
temp[n_cols[j]] = json.dumps(data[i][j])[1:-1]
elif n_cols[j] in cols_str:
temp[n_cols[j]] = str(int(data[i][j]))
else:
temp[n_cols[j]] = data[i][j]
out_data.append(temp)
return out_data
# def _hasBitFlag(self, flags, bit):
# return (flags & (1 << bit)) != 0
def _setBitFlag(self, flags, bit):
return int(flags) | (1 << int(bit))
def _unSetBitFlag(self, flags, bit):
return int(flags) & (~(1 << int(bit)))
def _read_excel(self, file):
try:
data = xlrd.open_workbook(file)
table = data.sheet_by_index(0)
nrows = table.nrows
ncols = table.ncols
all = list()
for row in range(1, nrows):
excel_list = []
for col in range(ncols):
cell_value = table.cell(row, col).value
excel_list.append(cell_value)
all.append(excel_list)
return all
except Exception:
pass
def _get_alive_server(self):
alive_server = list()
data = self.redis_conn.hgetall('game_info')
for line in data.values():
recode = json.loads(line)
if (int(recode['areaId']) % 100 + 9000) == int(recode['tcpPort']) and recode['status'] == 1:
alive_server.append(recode['areaId'])
servers = list(set(alive_server))
return servers
def _get_server_info(self, alive_server, server_type):
out_data = list()
key = f"{server_type}_info"
data = self.redis_conn.hgetall(key)
for line in data.values():
recode = json.loads(line)
if recode['areaId'] in alive_server:
# if (int(recode['areaId']) % 100 + 9000) == int(recode['tcpPort']) and recode['status'] == 1:
item = {}
item['serverid'] = recode['areaId']
item['ip'] = recode['innerIp']
item['port'] = recode['tcpPort']
out_data.append(item)
return out_data
def _add_recode2mysql(self, project, data):
mysql_conf = Ywplatform_db
mysql_conf['db'] = 'ywplatform'
mysql_conn = MysqlBase(**mysql_conf)
autoload_table = 'ops_servicemonitor'
int_list = ['port', 'check_item', 'match_values', 'in_use']
for line in data:
temp = {}
temp['project_name'] = project
temp['check_type'] = 'port'
temp['method'] = 'get'
temp['check_item'] = 1
temp['check_data'] = ""
temp['match_values'] = 1
temp['start_cmd'] = f"sh restart.sh {line['serverid']}"
temp['base_dir'] = '/data/apps'
temp['user'] = 'kingsome'
temp['in_use'] = 1
temp['up_addr'] = line['ip']
temp['port'] = line['port']
for key in list(temp.keys()):
if key in int_list:
temp[key] = str(int(temp[key]))
temp['serviceid'] = uuid.uuid4().hex
temp['remark'] = 0
temp['region'] = ""
temp['update_time'] = datetime.datetime.now().strftime(
"%Y-%m-%d %H:%M:%S")
temp['create_time'] = datetime.datetime.now().strftime(
"%Y-%m-%d %H:%M:%S")
condition = f"project_name='{temp['project_name']}' and up_addr='{temp['up_addr']}' and port='{temp['port']}'"
recode_status = f"select * from {autoload_table} where {condition}"
check_s = mysql_conn.query(recode_status)
if not check_s:
mysql_conn.insert('ops_servicemonitor', temp)
log.info(f"insert {temp}")
else:
u_data = {'in_use': temp['in_use']}
mysql_conn.update(autoload_table, u_data, condition)
log.info(f"update {u_data} where {condition}")
if __name__ == "__main__":
main()