def modify_mobile_www_config(game, region, scopes, filename, option_name, option_value): conf = ConfigReader(game, region) ip = conf.get("mobile_www_ip") if conf.has_option("mobile_www_port"): """ 如果前端资源服务器限制了ssh连接端口的话,修改Fabric的连接到该host的端口 """ port = conf.getint("mobile_www_port") if port: ip = '{}:{}'.format(ip, port) root_dir = conf.get("mobile_www_root_test") @hosts(ip) def _modify_mobile_www_config(): for each_scope in scopes: with cd(root_dir): _filename = '{}/{}'.format(each_scope, filename) config_file = MConfig(_filename) config_file.modify(key=option_name, value=option_value) execute(_modify_mobile_www_config)
def mobile_static_resources(game, region, component, game_env): """ 总的调度函数,负责读取一些参数,然后传给prod或test的函数 """ conf = ConfigReader(game, region) ip = conf.get("mobile_www_ip") if conf.has_option("mobile_www_port"): """ 如果前端资源服务器限制了ssh连接端口的话,修改Fabric的连接到该host的端口 """ port = conf.getint("mobile_www_port") if port: ip = '{}:{}'.format(ip, port) if game_env == 'test': root_dir = conf.get("mobile_www_root_test") test_env_mobile_static_resources(game, region, component, root_dir, ip) elif game_env == 'prod': root_dir_prod = conf.get("mobile_www_root") root_dir_test = conf.get("mobile_www_root_test") prod_env_mobile_static_resources(game, region, component, root_dir_prod, root_dir_test, ip)
def _prod_env_mobile_static_resources(): #备份 remote_backup_dir = "/app/opbak/prod_mobile_static_resources_release/{}_{}_{}".format( game, region, TIMESTAMP) remote_mkdir(remote_backup_dir) static_resources_dir_prod = '{}/static_resources'.format(root_dir_prod) remote_mkdir(static_resources_dir_prod) static_resources_dir_test = '{}/static_resources'.format(root_dir_test) with cd(static_resources_dir_prod): if remote_dir_exists(component): run('cp -r {} {}/'.format(component, remote_backup_dir)) #同步新版本的目录到生产环境 run('rsync -aqP --delete {test_dir}/{component}/ {prod_dir}/{component}/' .format(test_dir=static_resources_dir_test, prod_dir=static_resources_dir_prod, component=component)) #等待备份服务器同步完毕, 再接着更新 conf_wait_rsync = ConfigReader(game, region) if conf_wait_rsync.has_option("mobile_www_wait_rsync"): wait_rsync = conf_wait_rsync.getboolean("mobile_www_wait_rsync") if wait_rsync: rsync_to_backup(game, region)
def sync(game, region): """ 强行使测试环境目录与正式环境同步 """ conf = ConfigReader(game, region) ip = conf.get("mobile_www_ip") if conf.has_option("mobile_www_port"): """ 如果前端资源服务器限制了ssh连接端口的话,修改Fabric的连接到该host的端口 """ port = conf.getint("mobile_www_port") if port: ip = '{}:{}'.format(ip, port) root_dir_prod = conf.get("mobile_www_root") root_dir_test = conf.get("mobile_www_root_test") exclude_files = ['proxy.lua', 'lyServers'] exclude_param = ' '.join( ['--exclude={}'.format(each) for each in exclude_files]) with settings(host_string=ip): run('''rsync -aqP --delete {exclude} {root_dir_prod}/ {root_dir_test}/''' .format(exclude=exclude_param, root_dir_prod=root_dir_prod, root_dir_test=root_dir_test))
def update_exec(game, region, version, type): if not type: print "ERROR: restartType 必须指定!" sys.exit(1) if not null(version): print "上传后端包..." local('/app/opbin/rundeck/online.backend -g {} -t {}'.format(game, version)) conf = ConfigReader(game, region) proxy_pay1 = conf.get('proxy_pay1') proxy_pay2 = conf.get('proxy_pay2') proxy_pay1_ip = conf.get('proxy_pay1_ip') proxy_pay2_ip = conf.get('proxy_pay2_ip') serverlist = {proxy_pay1:proxy_pay1_ip,proxy_pay2:proxy_pay2_ip} print serverlist #serverlist = {"twproxy_10001":"113.196.114.26"} #serverlist = {"trproxy_10001":"85.195.72.74"} if conf.has_option("gateway"): gateway = conf.get('gateway') for server,ip in serverlist.items(): if gateway == "": with settings(host_string=ip): run('export JAVA_HOME=/usr/local/jdk;export LC_ALL=\'en_US.UTF-8\';export LANG=\'en_US.UTF-8\';sh /app/{}_{}/backend/bin/startup.sh {}'.format(game,server,type)) time.sleep(3) cmd = 'ps x -o stime,cmd|grep -v grep | grep -E "java.*{}_{}/"'.format(game,server) run(cmd) else: with settings(host_string=ip,gateway = gateway): run('export JAVA_HOME=/usr/local/jdk;export LC_ALL=\'en_US.UTF-8\';export LANG=\'en_US.UTF-8\';sh /app/{}_{}/backend/bin/startup.sh {}'.format(game,server,type)) time.sleep(3) cmd = 'ps x -o stime,cmd|grep -v grep | grep -E "java.*{}_{}/"'.format(game,server) run(cmd)
def mobile_www_release(game, region, version, scopes, game_env, mode=1): """ 总的调度函数,负责读取一些参数,然后传给prod或test的函数 目前打包任何.zip文件的时候,都同时copy出一份不带zip的压缩包。目的是防止一些小的电信运营商(如长城宽带)缓存.zip文件。 """ version_regex_check(version) conf = ConfigReader(game, region) ip = conf.get("mobile_www_ip") if conf.has_option("mobile_www_port"): """ 如果前端资源服务器限制了ssh连接端口的话,修改Fabric的连接到该host的端口 """ port = conf.getint("mobile_www_port") if port: ip = '{}:{}'.format(ip, port) if conf.has_option("gateway"): """ 配置gateway """ env.gateway = conf.get("gateway") if conf.has_option("mobile_www_start_zip_version"): start_zip_version = conf.get("mobile_www_start_zip_version") else: start_zip_version = "0.0.0.0" if game_env == 'test': root_dir = conf.get("mobile_www_root_test") test_env_mobile_www_release(game, region, version, scopes, root_dir, ip, start_zip_version=start_zip_version, mode=mode) elif game_env == 'prod': root_dir_prod = conf.get("mobile_www_root") root_dir_test = conf.get("mobile_www_root_test") prod_env_mobile_www_release(game, region, version, scopes, root_dir_prod, root_dir_test, ip, start_zip_version=start_zip_version, mode=mode)
def web_www_incremental_update(game, region, version): """ 页游前端增量更新 """ check_incremental_version(version) conf = ConfigReader(game, region) if conf.has_option("gateway"): gateway = conf.get('gateway') """ gateway存在且不为空的时候 """ if gateway != "": #with settings(host_string='ast_hk'): # run('/app/opbin/rundeck/online.frontend_gchw -g {} -t {}'.format(game, version)) local('/app/opbin/rundeck/online.frontend_gchw -g {} -t {}'.format(game, version)) else: local('/app/opbin/rundeck/online.frontend -g {} -t {}'.format(game, version))
def web_www_incremental_update(game, region, version): """ 页游前端增量更新 """ check_incremental_version(version) conf = ConfigReader(game, region) if conf.has_option("gateway"): gateway = conf.get('gateway') """ gateway存在且不为空的时候 """ if gateway != "": #with settings(host_string='ast_hk'): # run('/app/opbin/rundeck/online.frontend_gchw -g {} -t {}'.format(game, version)) local('/app/opbin/rundeck/online.frontend_gchw -g {} -t {}'.format( game, version)) else: local('/app/opbin/rundeck/online.frontend -g {} -t {}'.format( game, version))
def _prod_env_mobile_static_resources(): #备份 remote_backup_dir = "/app/opbak/prod_mobile_static_resources_release/{}_{}_{}".format(game, region, TIMESTAMP) remote_mkdir(remote_backup_dir) static_resources_dir_prod = '{}/static_resources'.format(root_dir_prod) remote_mkdir(static_resources_dir_prod) static_resources_dir_test = '{}/static_resources'.format(root_dir_test) with cd(static_resources_dir_prod): if remote_dir_exists(component): run('cp -r {} {}/'.format(component, remote_backup_dir)) #同步新版本的目录到生产环境 run('rsync -aqP --delete {test_dir}/{component}/ {prod_dir}/{component}/'.format(test_dir=static_resources_dir_test, prod_dir=static_resources_dir_prod, component=component)) #等待备份服务器同步完毕, 再接着更新 conf_wait_rsync = ConfigReader(game, region) if conf_wait_rsync.has_option("mobile_www_wait_rsync"): wait_rsync = conf_wait_rsync.getboolean("mobile_www_wait_rsync") if wait_rsync: rsync_to_backup(game, region)
def sync(game, region): """ 强行使测试环境目录与正式环境同步 """ conf = ConfigReader(game, region) ip = conf.get("mobile_www_ip") if conf.has_option("mobile_www_port"): """ 如果前端资源服务器限制了ssh连接端口的话,修改Fabric的连接到该host的端口 """ port = conf.getint("mobile_www_port") if port: ip = '{}:{}'.format(ip, port) root_dir_prod = conf.get("mobile_www_root") root_dir_test = conf.get("mobile_www_root_test") exclude_files = ['proxy.lua', 'lyServers'] exclude_param = ' '.join(['--exclude={}'.format(each) for each in exclude_files]) with settings(host_string=ip): run('''rsync -aqP --delete {exclude} {root_dir_prod}/ {root_dir_test}/'''.format(exclude=exclude_param, root_dir_prod=root_dir_prod, root_dir_test=root_dir_test))
def mobile_entrance_mode(self): conf = ConfigReader(self.game, self.region) if conf.has_option('mobile_entrance_mode'): return conf.getint('mobile_entrance_mode') else: return 1
def _prod_env_mobile_www_release(): #检查测试环境中在用的版本与即将更新的版本是否一致 with cd(root_dir_test): for each_scope in scopes: _result = run('grep --color=never sys_version.game {}/version.lua'.format(each_scope)) if len(_result.splitlines()) != 1: raise Exception('[ERROR] More than one line returned when do "grep sys_version.game {}/version.lua".'.format(each_scope)) test_env_current_version = _result.split('"')[1] if test_env_current_version != version: raise Exception("测试环境中 {} 的sys_version.game为:{}, 本次即将更新的版本为:{}, 不匹配".format(each_scope, test_env_current_version, version)) #备份 remote_backup_dir = "/app/opbak/mobile_www_prod_backup/{}_{}_{}".format(game, region, TIMESTAMP) remote_mkdir(remote_backup_dir) with cd(root_dir_prod): if remote_dir_exists(version): run('mv {} {}/'.format(version, remote_backup_dir)) for each_scope in scopes: if remote_dir_exists(each_scope): run('cp -r {} {}/'.format(each_scope, remote_backup_dir)) else: print('[Warning] {root_dir}/目录下不存在{scope}, 默认这是{scope}的第一次发布。'.format(root_dir=root_dir_prod, scope=each_scope)) #拷贝新版本的目录到生产环境 with cd(root_dir_test): run('cp -r {} {}/'.format(version, root_dir_prod)) need_diff_versions = filter_need_diff_versions(root_dir_prod, start_zip_version, reverse=False) #处理完整版版本之间的差异包 print('开始将完整版的差异包从测试环境拷贝到生产环境...') for each_version in need_diff_versions: if version_tuple(each_version) >= version_tuple(version): print('跳过{}, 不需要版本差异包'.format(each_version)) else: if mode == 2: _inner_scopes = list_inner_scopes(root_dir_prod, each_version) for each_scope in _inner_scopes: diff_from_lua = '{}/{}/{}/res.lua'.format(root_dir_prod, each_version, each_scope) if remote_file_exists(diff_from_lua): dest = '{0}/{1}/{2}.lua,{0}/{1}/{2}.zip,{0}/{1}/{2}'.format(each_version, each_scope, version) print('正在拷贝 {} 完整版的差异包 ==> {} ...'.format(each_version, dest.replace(',', ', '))) sys.stdout.flush() copy_diff(root_dir_test, root_dir_prod, dest) else: diff_from_lua = '{}/{}/res.lua'.format(root_dir_prod, each_version) if remote_file_exists(diff_from_lua): dest = '{0}/{1}.lua,{0}/{1}.zip,{0}/{1}'.format(each_version, version) print('正在拷贝 {} 完整版的差异包 ==> {} ...'.format(each_version, dest.replace(',', ', '))) sys.stdout.flush() copy_diff(root_dir_test, root_dir_prod, dest) #处理预览版版本之间的差异包 print('开始将预览版的差异包从测试环境拷贝到生产环境...') for each_version in need_diff_versions: if version_tuple(each_version) >= version_tuple(version): print('跳过{}, 不需要版本差异包'.format(each_version)) else: if mode == 2: _inner_scopes = list_inner_scopes(root_dir_prod, each_version) for each_scope in _inner_scopes: diff_from_lua = '{}/{}/{}/res_preview.lua'.format(root_dir_prod, each_version, each_scope) if remote_file_exists(diff_from_lua): dest = '{0}/{1}/{2}_preview.lua,{0}/{1}/{2}_preview.zip,{0}/{1}/{2}_preview'.format(each_version, each_scope, version) print('正在拷贝 {} 预览版的差异包 ==> {} ...'.format(each_version, dest.replace(',', ', '))) sys.stdout.flush() copy_diff(root_dir_test, root_dir_prod, dest) else: diff_from_lua = '{}/{}/res_preview.lua'.format(root_dir_prod, each_version) if remote_file_exists(diff_from_lua): dest = '{0}/{1}_preview.lua,{0}/{1}_preview.zip,{0}/{1}_preview'.format(each_version, each_scope, version) print('正在拷贝 {} 预览版的差异包 ==> {} ...'.format(each_version, dest.replace(',', ', '))) sys.stdout.flush() copy_diff(root_dir_test, root_dir_prod, dest) #等待备份服务器同步完毕, 再接着更新 conf_wait_rsync = ConfigReader(game, region) if conf_wait_rsync.has_option("mobile_www_wait_rsync"): wait_rsync = conf_wait_rsync.getboolean("mobile_www_wait_rsync") if wait_rsync: rsync_to_backup(game, region) for each_scope in scopes: run('cp -rf {}/{} {}/'.format(root_dir_test, each_scope, root_dir_prod))
# 由于思科防火墙vpn协议,tcp 长连接通道会断掉,所以采用心跳包的形式 if game_server == "heartbeat": logger.info('heartbeat') continue logger.info(game_server) ssh_ip, region, port, mixed_server = get_opstree(game_server) logger.info('server staus is {}'.format(mixed_server)) if mixed_server == 0: game = game_server.split('_')[0] logger.info('game = {}, ssh_ip = {}, region = {}, port = {}'.format( game, ssh_ip, region, port)) # 读取配置 conf = ConfigReader(game, region) if conf.has_option("gateway"): """ 配置gateway """ env.gateway = conf.get("gateway") if conf.has_option("gateway_port"): gateway_port = conf.getint("gateway_port") env.gateway = '{}:{}'.format(env.gateway, gateway_port) # 连接机器处理 coredump 进程 html = coredump_task(logger, ssh_ip, game_server, port) send_email(game_server, html) # 去掉 gateway # 消费端假死问题,强制重新连接 # async_task.reconnect()
def clean_up_diff_packages(game, region): """ 清理动更差异包 """ conf = ConfigReader(game, region) ip = conf.get("mobile_www_ip") if conf.has_option("mobile_www_port"): """ 如果前端资源服务器限制了ssh连接端口的话,修改Fabric的连接到该host的端口 """ port = conf.getint("mobile_www_port") if port: ip = '{}:{}'.format(ip, port) if conf.has_option("mobile_www_start_zip_version"): start_zip_version = conf.get("mobile_www_start_zip_version") else: start_zip_version = "" if conf.has_option("clean_30lv_diff_packages"): clean_30lv_diff_packages = conf.getboolean("clean_30lv_diff_packages") else: clean_30lv_diff_packages = False root_dir_prod = conf.get("mobile_www_root") root_dir_test = conf.get("mobile_www_root_test") @hosts(ip) def _do_clean_job(root_dir): need_scan_versions = filter_need_diff_versions(root_dir, start_zip_version, reverse=False) platforms = list_platforms(root_dir) _versions_in_use = [] for each_platform in platforms: _version = platform_version(root_dir, each_platform) _versions_in_use.append(_version) versions_in_use = list(set(_versions_in_use)) min_version = sorted_versions(versions_in_use)[0] #算出目前在用的最小的version for each_version_dir in need_scan_versions: _each_version_dir = "{}/{}".format(root_dir, each_version_dir) existed_diff_packages = sorted_versions( list_existed_diff_packages(_each_version_dir)) #保留最近3个差异动更包 for each_package in existed_diff_packages[0:-3]: #if version_tuple(each_package) < version_tuple(min_version): if each_package not in versions_in_use: if clean_30lv_diff_packages: #目前只有gcmob需要清理30lv的差异包 _packages = '{0}/{1},{0}/{1}_preview,{0}/{1}_30lv'.format( _each_version_dir, each_package).split(',') else: _packages = '{0}/{1},{0}/{1}_preview'.format( _each_version_dir, each_package).split(',') for each in _packages: delete_package(each) #for each_root_dir in [root_dir_test]: for each_root_dir in [root_dir_test, root_dir_prod]: print('开始清理{}下的差异包...'.format(each_root_dir)) execute(_do_clean_job, each_root_dir)