def kill_task(assign_data): """ :param assign_data: 测试任务下发数据 :return: 无返回 """ # 获取已下发测试任务的所有有效的worker信息 good_workers = [] # 轮询assign_data中的worker,判断是否可用 for ad in assign_data: # 根据ad的workerId查询workerInfo try: worker_info = model_mysql_workerinfo.query.filter( model_mysql_workerinfo.workerId == ad.workerId).first() except Exception as e: db_logger.error("worker:" + str(ad.workerId) + " 信息查询失败,失败原因:" + repr(e)) else: db_logger.debug("worker:" + str(ad.workerId) + " 信息查询成功") # 判断数据是否存在 if worker_info is None: # 如果worker的条目没有了,则将对应下发记录的finishTime直接赋上 update_finishtime(ad.assignId) else: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(2) r = s.connect_ex((worker_info.ip, worker_info.port)) if r != 0: # 将worker的状态置为异常 worker_info.status = 0 # 如果worker的状态为异常,则将对应下发记录的finishTime直接赋上 update_finishtime(ad.assignId) else: # 将worker的状态置为正常 worker_info.status = 1 good_workers.append(ad) try: mysqlpool.session.commit() except Exception as e: sys_logger.error("worker:" + str(ad.workerId) + " 信息更新失败,失败原因:" + repr(e)) else: sys_logger.debug("worker:" + str(ad.workerId) + " 信息更新成功") s.close() # 如果缺少可用worker if len(good_workers) < 1: pass else: # 开启线程池 pool = ThreadPool(len(good_workers)) pool.map(kill, good_workers) pool.close() pool.join()
def __send(self, to, msg): error_flag = True # -1 接收邮件地址或校验码填写非法 # 0 公共邮件发送成功 # 1 SMTP服务器连接失败 # 2 公共邮箱登陆失败 # 3 公共邮件发送失败 error_type = 0 logmsg = "准备发送邮件" sys_logger.info(logmsg) # 尝试连接服务器 try: # 根据SMTP服务器SSL状态连接 if self.smtp_ssl is True: smtp_server = smtplib.SMTP_SSL(self.smtp_host, self.smtp_port) else: smtp_server = smtplib.SMTP(self.smtp_host, self.smtp_port) # 打印日志 logmsg = "SMTP服务器连接成功" sys_logger.debug(logmsg) except Exception as A: logmsg = "SMTP服务器连接失败,失败信息:" + repr(A) error_flag = False error_type = 1 sys_logger.error(logmsg) else: try: smtp_server.login(self.send_address, self.send_password) logmsg = "公共邮件箱登陆成功" sys_logger.debug(logmsg) except Exception as B: logmsg = "公共邮件箱登陆失败,失败信息:" + repr(B) error_flag = False error_type = 2 sys_logger.error(logmsg) else: try: smtp_server.sendmail(self.send_address, to, msg.as_string()) smtp_server.quit() logmsg = "公共邮件发送成功" sys_logger.debug(logmsg) except Exception as C: logmsg = "公共邮件发送失败,失败信息:" + repr(C) error_flag = False error_type = 3 sys_logger.warn(logmsg) logmsg = "邮件发送结束" sys_logger.info(logmsg) return error_flag, error_type
def kill(assign_data): assign_id, task_id, worker_id, worker_ip, worker_port = assign_data # 打包action struct_action_data = struct.pack(dataFormat['action'], 'stopTestTask'.encode()) # 初始化并发送第一个请求 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sys_logger.debug(str(worker_id) + '|prepare to send action...') try: s.connect((worker_ip, worker_port)) s.send(struct_action_data) except Exception as e: sys_logger.error(str(worker_id) + '|send action failed:' + repr(e)) else: sys_logger.debug(str(worker_id) + '|send action succeeded') sys_logger.debug( str(worker_id) + '|listen action response from worker...') worker_response = s.recv(1024) sys_logger.debug(str(worker_id) + '|get action response from worker') worker_response = worker_response.decode() if worker_response == 'Success': # 打包base_data struct_base_data = struct.pack(dataFormat['stopTestTask'], task_id) sys_logger.debug(str(worker_id) + '|prepare to send base data...') try: s.send(struct_base_data) except Exception as e: sys_logger.error( str(worker_id) + '|send base data failed:' + repr(e)) else: sys_logger.debug(str(worker_id) + '|send base data succeeded') sys_logger.debug( str(worker_id) + '|listen base response from worker...') worker_response = s.recv(1024) sys_logger.debug( str(worker_id) + '|get base response from worker') if worker_response.decode() == 'Success': pass
# -*- coding: utf-8 -*- from automation import automation from handler.log import sys_logger from handler.config import appconfig from gevent import pywsgi from geventwebsocket.handler import WebSocketHandler if __name__ == '__main__': logmsg = "系统初始化|准备启动测试环境" sys_logger.info(logmsg) try: # 不能在生产环境中执行本文件 # automation.run(debug=False, host=appconfig.get("api", "host"), port=int(appconfig.get("api", "port"))) server = pywsgi.WSGIServer( (appconfig.get("api", "host"), int(appconfig.get("api", "port"))), automation, handler_class=WebSocketHandler ) print('服务已启动') server.serve_forever() except Exception as e: logmsg = "系统初始化|测试环境启动失败,失败原因:" + repr(e) sys_logger.error(logmsg) logmsg = "系统初始化|测试环境启动结束" sys_logger.info(logmsg)
# -*- coding: utf-8 -*- from redis import Redis, ConnectionPool from handler.config import database_config from handler.log import sys_logger msg = "准备初始化worker存储(redis)连接池" sys_logger.info(msg) try: pool = ConnectionPool( host=database_config.get("redis", "host"), port=int(database_config.get("redis", "port")), password=database_config.get("redis", "password") if database_config.get("redis", "password") else None, max_connections=int(database_config.get("redis", "max_connections")) ) redis_pool = Redis(connection_pool=pool) msg = "worker存储(redis)连接池初始化成功" sys_logger.info(msg) except Exception as e: msg = "worker存储(redis)连接池初始化失败,失败原因:" + repr(e) sys_logger.error(msg) raise RuntimeError(msg)
# -*- coding: utf-8 -*- import configparser from handler.log import sys_logger app_config = configparser.ConfigParser() msg = "准备读取环境配置文件生成配置对象" sys_logger.info(msg) try: app_config.read(filenames="config/app.ini", encoding="utf-8") msg = "环境配置文件读取成功,成功生成配置对象" sys_logger.debug(msg) except Exception as e: msg = "环境配置文件读取失败,失败原因:" + repr(e) sys_logger.error(msg) raise e else: """ 检查app.ini内各项内容是否符合填写要求 log: interval/every """ try: app_config.getint('log', 'interval') app_config.getint('log', 'every') except Exception as e: sys_logger.error(repr(e)) raise e
def multi_deploy(base, file): """ :param base: 接收测试任务基础信息 :param file: 接收测试任务文件 :return: True/False """ # 获取当前所有有效的worker信息 try: all_workers = model_mysql_workerinfo.query.filter( model_mysql_workerinfo.status == 1).all() except Exception as e: sys_logger.debug("获取执行应用列表失败,失败原因:" + repr(e)) return False # 检查worker good_workers = [] if not all_workers: sys_logger.debug("当前系统无可用worker") return False else: # 轮询可用worker,判断是否确实可用 for aw in all_workers: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(2) r = s.connect_ex((aw.ip, aw.port)) if r != 0: # 将worker的状态置为异常 aw.status = 0 try: mysqlpool.session.commit() except Exception as e: sys_logger.error("worker:" + str(aw.workerId) + " 信息更新失败,失败原因:" + repr(e)) else: sys_logger.debug("worker:" + str(aw.workerId) + " 信息更新成功") else: good_workers.append(aw) s.send(struct.pack(dataFormat['action'], 'test'.encode())) s.close() # 如果缺少可用worker,则报错 if len(good_workers) < 1: sys_logger.error("当前系统无可用worker") return False # 根据worker数量拆分base中的vUser if len(good_workers) >= base.vUser: sys_logger.debug("虚拟用户数量较少,仅选择单机运行") # 如果vUser数量小于等于worker数量,则随机取一个worker the_worker = random.sample(good_workers, 1)[0] # 调用deploy deploy_result = deploy([the_worker, base, file]) return deploy_result # 如果vUser数量大于worker数量,则均分 else: sys_logger.debug("虚拟用户数量较多,选择多机运行") u1 = base.vUser // len(good_workers) # 判断能否整除 if base.vUser % len(good_workers) == 0: users = [u1] * len(good_workers) else: users = [u1] * (len(good_workers) - 1) users.append(base.vUser - u1 * (len(good_workers) - 1)) # 开启线程池 pool = ThreadPool(len(good_workers)) worker_base_list = [] i = 0 for gw in good_workers: base.vUser = users[i] worker_base_list.append([gw, base, file]) i += 1 pool.map(deploy, worker_base_list) pool.close() pool.join() return True
def single_deploy(base, file): """ :param base: 接收测试任务基础信息 :param file: 接收测试任务文件 :return: True/False """ # 获取当前所有有效的worker信息 try: all_workers = model_mysql_workerinfo.query.filter( model_mysql_workerinfo.status == 1).all() except Exception as e: msg = "获取执行应用列表失败,失败原因:" + repr(e) sys_logger.debug(msg) return False, msg # 检查worker good_workers = [] if not all_workers: msg = "当前系统无可用worker" sys_logger.warn(msg) return False, msg else: # 轮询可用worker,判断是否确实可用 for aw in all_workers: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(2) r = s.connect_ex((aw.ip, aw.port)) if r != 0: # 将worker的状态置为异常 aw.status = 0 try: mysqlpool.session.commit() except Exception as e: sys_logger.error("worker:" + str(aw.workerId) + " 信息更新失败,失败原因:" + repr(e)) else: sys_logger.debug("worker:" + str(aw.workerId) + " 信息更新成功") else: good_workers.append(aw) s.close() # 如果缺少可用worker,则报错 if len(good_workers) < 1: msg = "当前系统无可用worker" sys_logger.error(msg) return False, msg else: # 从可用worker列表中任取一个进行下发操作 # 如果失败,则把错误返回累计起来以便写warn日志,并继续尝试,直到下发成功 deploy_msg = '' deploy_result = False while len(good_workers) > 0 and not deploy_result: i = random.randint(0, len(good_workers) - 1) # 调用deploy deploy_result, msg = deploy([good_workers[i], base, file]) deploy_msg += msg + ';' good_workers.pop(i) if deploy_result: sys_logger.debug(deploy_msg) else: sys_logger.warn(deploy_msg) return deploy_result, deploy_msg
def deploy(worker_base_file): the_worker, base, file = worker_base_file the_worker_id = the_worker.workerId msg = '' the_date = str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) # 新增下发测试任务记录 new_task_assign = model_mysql_taskassign(taskId=base.taskId, workerId=the_worker_id, vuser=base.vUser, status=0, createTime=the_date, updateTime=the_date) try: # 下发记录入库 mysqlpool.session.add(new_task_assign) mysqlpool.session.commit() except Exception as e: msg = "测试任务下发记录新增失败,失败原因:" + repr(e) sys_logger.debug(msg) return False, msg else: sys_logger.debug("测试任务下发记录新增成功") # 打包action # 初始化并发送第一个请求 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sys_logger.debug('workerId:%d,准备发送action...' % the_worker_id) try: s.connect((the_worker.ip, the_worker.port)) s.send(struct.pack(dataFormat['action'], 'newTestTask'.encode())) except Exception as e: msg = 'workerId:%d,发送action失败:%s' % (the_worker_id, repr(e)) sys_logger.error(msg) return False, msg else: msg = 'workerId:%d,发送action成功' % the_worker_id sys_logger.debug(msg) msg = 'workerId:%d,准备接收action返回...' % the_worker_id sys_logger.debug(msg) worker_response = s.recv(1024) msg = 'workerId:%d,接收到action返回' % the_worker_id sys_logger.debug(msg) worker_response = worker_response.decode() if worker_response == 'Success': msg = 'workerId:%d,准备发送basedata...' % the_worker_id sys_logger.debug(msg) try: # 打包并发送base_data s.send( struct.pack( dataFormat['newTestTask'], base.taskId, base.vUser, base.rampUpPeriod, base.startType, base.endType, base.errorType, base.excuteTimes if base.excuteTimes else 0, os.stat(file).st_size, str(base.startTime).encode() if base.startTime else ''.encode(), str(base.endTime).encode() if base.endTime else ''.encode())) except Exception as e: msg = 'workerId:%d,发送basedata失败:%s' % (the_worker_id, repr(e)) sys_logger.error(msg) return False, msg else: msg = 'workerId:%d,发送basedata成功' % the_worker_id sys_logger.debug(msg) msg = 'workerId:%d,准备接收basedata返回...' % the_worker_id sys_logger.debug(msg) worker_response = s.recv(1024) msg = 'workerId:%d,接收到basedata返回' % the_worker_id sys_logger.debug(msg) worker_response = worker_response.decode() if worker_response == 'Success': task_file = open(file, 'rb') msg = 'workerId:%d,准备发送测试任务数据及文件的压缩包...' % the_worker_id sys_logger.debug(msg) try: while True: file_data = task_file.read(1024) if not file_data: break s.send(file_data) except Exception as e: msg = 'workerId:%d,发送压缩包失败:%s' % (the_worker_id, repr(e)) sys_logger.error(msg) return False, msg else: task_file.close() msg = 'workerId:%d,发送压缩包成功' % the_worker_id sys_logger.debug(msg) msg = 'workerId:%d,准备接收压缩包返回...' % the_worker_id sys_logger.debug(msg) worker_response = s.recv(1024) msg = 'workerId:%d,接收到压缩包返回' % the_worker_id sys_logger.debug(msg) worker_response = worker_response.decode() if worker_response == 'Success': # 下发结果入库 new_task_assign.status = 1 new_task_assign.updateTime = str( datetime.datetime.now().strftime( "%Y-%m-%d %H:%M:%S")) msg = 'workerId:%d,压缩包处理成功' % the_worker_id sys_logger.debug(msg) try: mysqlpool.session.commit() except Exception as e: msg = '测试任务下发记录更新失败,失败原因:%s' % repr(e) sys_logger.debug(msg) return False, msg else: msg = '测试任务下发记录更新成功' sys_logger.debug(msg) return True, '测试任务下发成功' else: # 下发结果入库 new_task_assign.status = -1 new_task_assign.updateTime = str( datetime.datetime.now().strftime( "%Y-%m-%d %H:%M:%S")) msg = 'workerId:%d,压缩包处理失败:%s' % ( the_worker_id, worker_response.split('.') [1] if len(worker_response.split('.')) > 1 else '原因未知') sys_logger.error(msg) try: mysqlpool.session.commit() except Exception as e: msg = '测试任务下发记录更新失败,失败原因:%s' % repr(e) sys_logger.debug(msg) return False, msg else: msg = '测试任务下发记录更新成功' sys_logger.debug(msg) return False, 'workerId:%d,压缩包处理失败:%s' % ( the_worker_id, worker_response.split('.')[1] if len(worker_response.split('.')) > 1 else '原因未知') else: # 下发结果入库 new_task_assign.status = -1 new_task_assign.updateTime = str( datetime.datetime.now().strftime( "%Y-%m-%d %H:%M:%S")) msg = 'workerId:%d,basedata处理失败:%s' % ( the_worker_id, worker_response.split('.')[1] if len(worker_response.split('.')) > 1 else '原因未知') sys_logger.error(msg) try: mysqlpool.session.commit() except Exception as e: msg = '测试任务下发记录更新失败,失败原因:%s' % repr(e) sys_logger.debug(msg) return False, msg else: msg = '测试任务下发记录更新成功' sys_logger.debug(msg) return False, 'workerId:%d,basedata处理失败:%s' % ( the_worker_id, worker_response.split('.')[1] if len(worker_response.split('.')) > 1 else '原因未知') else: # 下发结果入库 new_task_assign.status = -1 new_task_assign.updateTime = str( datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) msg = 'workerId:%d,action处理失败:%s' % ( the_worker_id, worker_response.split('.')[1] if len(worker_response.split('.')) > 1 else '原因未知') sys_logger.error(msg) try: mysqlpool.session.commit() except Exception as e: msg = '测试任务下发记录更新失败,失败原因:%s' % repr(e) sys_logger.debug(msg) return False, msg else: msg = '测试任务下发记录更新成功' sys_logger.debug(msg) return False, 'workerId:%d,action处理失败:%s' % ( the_worker_id, worker_response.split('.')[1] if len(worker_response.split('.')) > 1 else '原因未知')
def sendmail_changemail_success(self, to): # 检查传参合法性 # to if type(to) is str: logmsg = "准备给" + to + "发送账户绑定邮箱修改成功邮件" sys_logger.info(logmsg) # 编辑邮件具体内容 mail_msg = """ <html> <head> <style type="text/css"> #platform_logo { height: 18px; } #platform_logo_left{ transition: all 0.5s; fill: #4DB6FF; } #platform_logo_center{ transition: all 0.5s; fill: #539D2C; } #platform_logo_right{ transition: all 0.5s; fill: #EDA833; } #platform_logo > path:hover{ transition: all 0.5s; fill: lightgrey; } </style> </head> <body style="margin:0;"> <div style="background-color: #f5f5f5;"> <div style="margin-left: 20px;padding-top: 10px; padding-bottom: 10px;font-size: 18px;font-weight: 600;"> Dear %s, </div> <div style="position: relative;margin-left: 20px;margin-right: 20px; font-size: 15px;background-color: white;border: 1px solid darkgrey;border-radius: 4px;"> <div style="margin-top: 15px;margin-left: 15px;padding-bottom: 10px;"> 您正在尝试修改绑定邮箱: <a href="%s">绑定邮箱修改成功</a> <div style="margin-left: 10px;padding-bottom: 10px;font-size: 16px;"></div> </div> </div> <div style="margin-top: 10px;padding-bottom: 10px; color: darkgrey;text-align: right;"> <div style="margin-right: 20px;font-size: 12px;"> 本条消息发送自%s测试平台 </div> </div> </div> </body> </html> """ % ( to.split("@")[0], appconfig.get("web", "http") + "://" + appconfig.get("web", "host") + ":" + appconfig.get("web", "port") + appconfig.get("web_url", "login"), appconfig.get('org', 'abbreviation'), ) # 装载消息 # 添加根MIME msg = MIMEText(mail_msg, 'html', 'utf-8') # 初始化邮件发送人 msg['From'] = Header(self.send_address, 'utf-8') # 初始化邮件接收人 msg['To'] = Header(to, 'utf-8') # 初始化邮件主题 msg['Subject'] = Header( '%s测试平台-账号注册' % appconfig.get('org', 'abbreviation'), 'utf-8' ) # 发送 result_flag, result_type = self.__send(to, msg) logmsg = "给" + to + "发送绑定邮箱修改成功邮件结束" sys_logger.info(logmsg) return result_flag, result_type else: logmsg = "接收邮件地址或校验码填写非法" sys_logger.error(logmsg) return False, -1
def sendmail_reset_password(self, user_id, to, code, operationid): # 检查传参合法性 # to if type(to) is str and type(code) is str: logmsg = "准备给" + to + "发送重置密码邮件" sys_logger.info(logmsg) # 编辑邮件具体内容 mail_msg = """ <html> <head> <style type="text/css"> #platform_logo { height: 18px; } #platform_logo_left{ transition: all 0.5s; fill: #4DB6FF; } #platform_logo_center{ transition: all 0.5s; fill: #539D2C; } #platform_logo_right{ transition: all 0.5s; fill: #EDA833; } #platform_logo > path:hover{ transition: all 0.5s; fill: lightgrey; } </style> </head> <body style="margin:0;"> <div style="background-color: #f5f5f5;"> <div style="margin-left: 20px;padding-top: 10px; padding-bottom: 10px;font-size: 18px;font-weight: 600;"> Dear %s, </div> <div style="position: relative;margin-left: 20px;margin-right: 20px; font-size: 15px;background-color: white;border: 1px solid darkgrey;border-radius: 4px;"> <div style="margin-top: 15px;margin-left: 15px;padding-bottom: 10px;"> 您正在尝试重置密码: <a href="%s?userId=%s&mail=%s&code=%s&operate=%s">点我打开重置密码页</a> <div style="margin-left: 10px;padding-bottom: 10px;font-size: 16px;"></div> </div> </div> <div style="margin-top: 10px;padding-bottom: 10px; color: darkgrey;text-align: right;"> <div style="margin-right: 20px;font-size: 12px;"> 本条消息发送自%s测试平台 </div> </div> </div> </body> </html> """ % ( to.split("@")[0], appconfig.get("web", "http") + "://" + appconfig.get("web", "host") + ":" + appconfig.get("web", "port") + appconfig.get("web_url", "resetPassword"), str(user_id), parse.quote(to), parse.quote(code), str(operationid), appconfig.get('org', 'abbreviation'), ) # 装载消息 # 添加根MIME msg = MIMEText(mail_msg, 'html', 'utf-8') # 初始化邮件发送人 msg['From'] = Header(self.send_address, 'utf-8') # 初始化邮件接收人 msg['To'] = Header(to, 'utf-8') # 初始化邮件主题 msg['Subject'] = Header( '%s测试平台-账号注册' % appconfig.get('org', 'abbreviation'), 'utf-8' ) # 发送 self.__send(to, msg) logmsg = "给" + to + "发送重置密码邮件结束" sys_logger.info(logmsg) return True else: logmsg = "接收邮件地址或校验码填写非法" sys_logger.error(logmsg) return False