490 lines
20 KiB
Python
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()
|