class ZdSnapshotRollbackHandler(CommonBaseHandler): """rollback """ args_list = [ ArgsMap('cluster_name', required=True), ArgsMap('path', required=True), ArgsMap('snapshot_id', default=""), ArgsMap('recursive', default=""), ] @authenticated def response(self): """rollback """ if self.snapshot_id: snapshot = ZdSnapshot.one(id=self.snapshot_id) else: snapshot = SnapshotService.last_snapshot(self.cluster_name, self.path) # 检查快照是否存在 if not snapshot: return self.ajax_popup(code=300, msg="快照未找到,请手动查看一下") if self.recursive == "1": # 递归回滚快照 SnapshotService.rollback_snapshots_recursively( self.cluster_name, snapshot) else: SnapshotService.rollback_snapshot(self.cluster_name, snapshot) return self.ajax_ok(close_current=False)
class ZdZookeeperSearchHandler(CommonBaseHandler): '''search,搜索 ''' args_list = [ ArgsMap('pageSize', 'page_size', default=30), ArgsMap('pageCurrent', 'current_page', default=1), ArgsMap('orderDirection', 'order_direction', default="asc"), ArgsMap('orderField', 'order_field', default="id"), ] @authenticated def response(self): '''search ''' clauses = self.parse_query(ZdZookeeper) order = getattr(ZdZookeeper, self.order_field) records = ZdZookeeper.select().order_by( getattr(order, self.order_direction)() ).where(reduce(operator.and_, clauses)) self.render('config/zookeeper/datagrid.html', total=records.count(), current_page=self.current_page, page_size=self.page_size, records=records.paginate(self.current_page, self.page_size))
class ZdZnodeEditHandler(CommonBaseHandler): """edit, 修改 """ args_list = [ ArgsMap('cluster_name', required=True), ArgsMap('path', required=True), ] @authenticated def response(self): '''edit ''' node_type = data = download_link = "" normalized_path = normalize_path(self.path) znode = ZdZnode.one(path=normalized_path, cluster_name=self.cluster_name, deleted='0') if znode: node_type = znode.type # "0"代表普通节点, "1"代表文本节点 if node_type == "1": # 文件节点提供下载路径 download_link = "/config/znode/download?path={0}&cluster_name={1}".format( self.path, self.cluster_name) else: data = ZookeeperService.get(self.cluster_name, self.path) return self.render('config/znode/edit.html', action='/config/znode/save', cluster_name=self.cluster_name, path=normalized_path, data=data, download_link=download_link)
class ZdQconfAgentIndexHandler(CommonBaseHandler): '''index, 查看 ''' args_list = [ ArgsMap('pageSize', 'page_size', default=30), ArgsMap('pageCurrent', 'current_page', default=1), ArgsMap('orderDirection', 'order_direction', default="asc"), ArgsMap('orderField', 'order_field', default="id"), ] @authenticated def response(self): '''index ''' clauses = self.parse_query(ZdQconfAgent) order = getattr(ZdQconfAgent, self.order_field) records = ZdQconfAgent.select().order_by( getattr(order, self.order_direction)() ).where(reduce(operator.and_, clauses)) self.render('config/agent/index.html', action='/config/agent/index', total=records.count(), current_page=self.current_page, page_size=self.page_size, records=records.paginate(self.current_page, self.page_size))
class ZdZookeeperSaveHandler(CommonBaseHandler): """save """ args_list = [ ArgsMap('id', default=''), ArgsMap('cluster_name', default=''), ArgsMap('hosts', default=''), ArgsMap('business', default=''), ] @authenticated def response(self): '''add ''' if self.id: # 修改记录 tb_inst = ZdZookeeper.one(id=self.id) else: # 新增记录 zookeeper = ZdZookeeper.one(cluster_name=self.cluster_name, deleted='0') # 检验集群名称是否重复 if zookeeper: return self.ajax_popup(code=300, msg="zookeeper集群名称重复!") else: tb_inst = ZdZookeeper() if self.id: tb_inst.id = self.id if self.cluster_name: tb_inst.cluster_name = self.cluster_name if self.hosts: tb_inst.hosts = self.hosts if self.business: tb_inst.business = self.business tb_inst.save() return self.ajax_ok(forward="/config/zookeeper/index")
class ZdServiceIndexHandler(CommonBaseHandler): '''index, 查看 ''' args_list = [ ArgsMap('pageSize', 'page_size', default=30), ArgsMap('pageCurrent', 'current_page', default=1), ArgsMap('orderDirection', 'order_direction', default="asc"), ArgsMap('orderField', 'order_field', default="id"), ] @authenticated def response(self): '''index ''' # zookeeper clusters clusters = ZdZookeeper.select().where(ZdZookeeper.deleted == "0") if clusters.count() < 1: return self.ajax_popup(code=300, msg="请先到zookeeper管理菜单下设置集群信息!") clauses = self.parse_query(ZdService) order = getattr(ZdService, self.order_field) records = ZdService.select().order_by( getattr(order, self.order_direction)() ).where(reduce(operator.and_, clauses) & (ZdService.deleted == "0")) self.render('config/service/index.html', action='/config/service/index', total=records.count(), current_page=self.current_page, page_size=self.page_size, records=records.paginate(self.current_page, self.page_size))
class ZdZnodeShowHandler(CommonBaseHandler): """tree """ args_list = [ ArgsMap('cluster_name', required=True), ArgsMap('path', default="/"), ] @authenticated def response(self): """返回指定zookeeper集群的znode信息, 响应ajax请求 """ nodes = [] normalized_path = normalize_path(self.path) if USE_QCONF: ZnodeService.get_znode_tree_from_qconf(self.cluster_name, normalized_path, nodes) else: zoo_client = ZookeeperService.get_zoo_client(self.cluster_name) if not zoo_client: return self.ajax_popup(code=300, msg="连接zookeeper出错!") ZnodeService.get_znode_tree(zoo_client, normalized_path, nodes) if normalized_path != "/" and len(nodes) <= 1: return self.ajax_popup(code=300, msg="对不起,该节点路径下(%s)无数据!" % self.path) znodes_data = json.dumps(nodes) return self.render('config/znode/displaytree.html', cluster_name=self.cluster_name, znodes_data=znodes_data)
class ZdZnodeEditTreeHandler(CommonBaseHandler): """batch edit, 批量修改 """ args_list = [ #ArgsMap('path', required=True), ArgsMap('path', required=False), ArgsMap('cluster_name', required=True), ArgsMap('service_name', required=True), ] @authenticated def response(self): '''batch edit ''' #child_znodes = ZnodeService.get_child_znodes( # self.cluster_name, self.path) #return self.render('config/znode/batchedit.html', # action='/config/znode/batchsave', # cluster_name=self.cluster_name, # parent_path=self.path, # child_znodes=child_znodes) return self.render('config/znode/batchedit.html', action='/config/znode/batchsave', cluster_name=self.cluster_name, service_name=self.service_name)
class ZdZnodeSaveCopyHandler(CommonBaseHandler): """savecopy """ args_list = [ ArgsMap('cluster_name', required=True), ArgsMap('path', required=True), ArgsMap('old_path', required=True), ArgsMap('parent_path', default='/'), ] @authenticated def response(self): '''savecopy ''' # node_name中不可包含`/`特殊字符 if self.path and not ZnodeService.is_node_name_ok(self.path): return self.ajax_popup(code=300, msg="节点名不允许包含特殊字符'/'!") zk_path = "" if not self.path: # 新增节点需要进行存在检验 return self.ajax_popup(code=300, msg="节点名称不能为空!") else: zk_path = os.path.join(self.parent_path, self.path) if ZookeeperService.exists(self.cluster_name, zk_path): return self.ajax_popup(code=300, msg="节点已经存在!") normalized_path = normalize_path(self.old_path) nodes = [] if USE_QCONF: ZnodeService.get_znode_tree_from_qconf(self.cluster_name, normalized_path, nodes) else: zoo_client = ZookeeperService.get_zoo_client(self.cluster_name) if not zoo_client: return self.ajax_popup(code=300, msg="连接zookeeper出错!") ZnodeService.get_znode_tree(zoo_client, normalized_path, nodes) path = full_path(self.path,self.parent_path) #ZnodeService.save_znode_tree(self.cluster_name , normalized_path , path) index = self.old_path.rfind('/') old_node_name = self.old_path[index+1:] for node in nodes: new_path = node['path'].replace(old_node_name,self.path,1) ZnodeService.save_znode_tree(self.cluster_name , node['path'] ,new_path) #ret = ZnodeService.save_znode_tree(self.cluster_name ,self.parent_path,self.old_path,self.path) #if not ret: # return self.ajax_popup(code=300,msg='添加失败') return self.ajax_ok(close_current=True)
class ZdZnodeBatchSaveHandler(CommonBaseHandler): """save """ args_list = [ ArgsMap('cluster_name', required=True), ArgsMap('service_name', required=True), #ArgsMap('parent_path', required='/'), #ArgsMap('description', default=''), #ArgsMap('deleted', default=''), ] @authenticated def response(self): '''save ''' keys = self.get_arguments("key") values = self.get_arguments("value") descriptions = self.get_arguments("description") for key in keys: if not key.startswith("/" + self.service_name + "/"): return self.ajax_popup(code=300, msg="键值格式错误,请输入完整路径!") #batch_data = [] #for node_name, node_value in zip(keys, values): # # 过滤掉所有key为空字符串的项 # if node_name == '': # continue # # 检验node_name中是否包含`/`特殊字符 # if not ZnodeService.is_node_name_ok(node_name): # return self.ajax_popup(code=300, msg="节点名不允许包含特殊字符'/'!") # batch_data.append((node_name, node_value)) ## 更新字典,需要删除旧字典与新字典的差集项 #ZnodeService.delete_znodes_diff_with_keys( # self.cluster_name, self.parent_path, keys) ## 更新在zookeeper和mysql上存储的配置信息, 同时进行快照备份 #ZnodeService.set_batch_znodes(cluster_name=self.cluster_name, # parent_path=self.parent_path, # batch_data=batch_data, # description=self.description) for node_name, node_value, node_description in zip( keys, values, descriptions): ZnodeService.set_znode(self.cluster_name, node_name, node_value, description=node_description) return self.ajax_ok(close_current=True)
class ZdQconfAgentSaveHandler(CommonBaseHandler): """save """ args_list = [ ArgsMap('id', default=''), ArgsMap('ip', default=''), ArgsMap('hostname', default=''), ArgsMap('cluster_name', default=''), ArgsMap('notes', default=''), ArgsMap('create_user', default=''), ArgsMap('create_time', default=''), ArgsMap('update_user', default=''), ArgsMap('update_time', default=''), ArgsMap('deleted', default=''), ] @authenticated def response(self): '''add ''' if self.id: # 修改记录 tb_inst = ZdQconfAgent.one(id=self.id) else: # 新增记录 tb_inst = ZdQconfAgent() if self.id: tb_inst.id = self.id if self.ip: tb_inst.ip = self.ip if self.hostname: tb_inst.hostname = self.hostname if self.cluster_name: tb_inst.cluster_name = self.cluster_name if self.notes: tb_inst.notes = self.notes if self.create_user: tb_inst.create_user = self.create_user if self.create_time: tb_inst.create_time = self.create_time if self.update_user: tb_inst.update_user = self.update_user if self.update_time: tb_inst.update_time = self.update_time if self.deleted: tb_inst.deleted = self.deleted tb_inst.save() return self.ajax_ok(forward="/config/agent/index")
class ZdServiceSaveHandler(CommonBaseHandler): """save """ args_list = [ #add时不传入id delete时传入delete 不提供edit操作 ArgsMap('id', default=''), ArgsMap('cluster_name', default=''), ArgsMap('service_name', default=''), ] @authenticated def response(self): '''add ''' if self.id: # 修改记录 tb_inst = ZdService.one(id=self.id) else: zookeeper = ZdZookeeper.one(cluster_name=self.cluster_name, deleted='0') if zookeeper is None: return self.ajax_popup(code=300, msg="zookeeper集群不存在!") else: # 新增记录 service = ZdService.one(zookeeper=zookeeper.id, service_name=self.service_name, deleted='0') # 检验集群下是否已经有该服务 if service: return self.ajax_popup(code=300, msg="service名称重复!") else: tb_inst = ZdService() if self.id: tb_inst.id = self.id if self.service_name: tb_inst.service_name = self.service_name tb_inst.zookeeper = zookeeper tb_inst.save() # 更新在zookeeper和mysql上存储的配置信息, 同时进行快照备份 # 当一个节点的父节点存在时才会保存快照 ZnodeService.set_znode(cluster_name=self.cluster_name, path='/', data='', znode_type='0', description='') ZnodeService.set_znode(cluster_name=self.cluster_name, path='/' + self.service_name, data='', znode_type='0', description='') return self.ajax_ok(forward="/config/service/index")
class ZdZookeeperQueryServicesHandler(CommonBaseHandler): """query_services, 查询集群下该用户有权限的所有子系统 """ args_list = [ ArgsMap('cluster', default=''), ] def response(self): zookeeper = ZdZookeeper.one(cluster_name=self.cluster, deleted='0') #self.set_header('Content-Type', 'application/json; charset=UTF-8') #self.write(json.dumps({'message': 'ok'})) #self.finish() if zookeeper is not None: services = ZdService.select().where((ZdService.zookeeper == zookeeper.id) & (ZdService.deleted == '0')) if services.count() >= 1: json_data = '{"service_names":[' for service in services: json_data += '"' json_data += service.service_name json_data += '",' json_data = json_data[0:len(json_data)-1] json_data += "]}" return json_data else: json_data = '' self.finish() else: self.finish()
class ZdUserEditHandler(CommonBaseHandler): '''edit, 修改 ''' args_list = [ ArgsMap('info_ids', default=''), ] @authenticated def response(self): '''edit ''' if self.info_ids: id_li = self.info_ids.split(',') if len(id_li) != 1: return self.ajax_popup(close_current=False, code=300, msg="请选择单条记录进行修改") else: user = ZdUser.one(id=id_li[0], deleted='0') result = dict() zookeepers = ZdZookeeper.select().where(ZdZookeeper.deleted == '0') for zookeeper in zookeepers: services = ZdService.select().where((ZdService.zookeeper == zookeeper.id) & (ZdService.deleted == '0')) result[zookeeper] = services return self.render('config/user/edit.html', action='config/user/save', user=user, result=result) else: return self.ajax_popup(close_current=False, code=300, msg="请选择某条记录进行修改")
class ZdUserDeleteHandler(CommonBaseHandler): '''delete, 删除 ''' args_list = [ ArgsMap('info_ids', default=''), ] @authenticated def response(self): '''delete ''' if self.info_ids: id_li = self.info_ids.split(',') if len(id_li) != 1: return self.ajax_popup(close_current=False, code=300, msg="请选择单条记录进行修改") else: user = ZdUser.one(id=id_li[0], deleted='0') user.deleted = '1' user.save() return self.ajax_ok(forward="config/user/index") else: return self.ajax_popup(close_current=False, code=300, msg="请选择某条记录进行修改")
class ZdZookeeperExportHandler(CommonBaseHandler): """export,导出数据到excel """ args_list = [ ArgsMap('info_ids', default=''), ] def response(self): '''导出选中数据到excel中 ''' id_li = self.info_ids.split(',') sheet_text = ZdZookeeper.select().where(ZdZookeeper.id << id_li) sheet_title = [ {'name': '集群名称'}, {'name': '集群配置'}, {'name': '集群业务'}, ] bind_attr = ( 'cluster_name', 'hosts', 'business', ) ewb = ExcelWorkBook() sheet_name = ZdZookeeper._meta.db_table ewb.add_sheet(sheet_name) ewb.add_title(sheet_name, sheet_title) ewb.add_text(sheet_name, sheet_text, bind=bind_attr) filename = '{}.xls'.format(sheet_name) filename = urllib.urlencode({'filename': filename}) self.set_header('Content-Disposition', 'attachment;{}'.format(filename)) self.finish(ewb.get_stream())
class ZdQconfAgentEditHandler(CommonBaseHandler): """edit, 修改 """ args_list = [ ArgsMap('info_ids', default=''), ] def response(self): '''edit ''' if self.info_ids: id_li = self.info_ids.split(',') if len(id_li) != 1: return self.ajax_popup(close_current=False, code=300, msg="请选择单条记录进行修改") clusters = ZdZookeeper.select().where(ZdZookeeper.deleted == "0") record = ZdQconfAgent.one(id=id_li[0]) return self.render('config/agent/edit.html', action='/config/agent/save', clusters=clusters, record=record) else: return self.ajax_popup(close_current=False, code=300, msg="请选择某条记录进行修改")
class ZdSnapshotSaveHandler(CommonBaseHandler): """save """ args_list = [ ArgsMap('cluster_name', required=True), ArgsMap('path', default='') ] @authenticated def response(self): '''add ''' try: SnapshotService.make_snapshot(self.cluster_name, self.path) return self.ajax_ok(close_current=False) except MakeSnapshotError: return self.ajax_popup(code=300, msg="父节点快照尚未生成,无法创建快照!")
class WsZnodeAddSnapshotHandler(CommonBaseHandler): """批量生成快照 """ args_list = [ ArgsMap('cluster_name', required=True), ArgsMap('path', default='/'), ] @authenticated def response(self): """根据父节点路径批量生成快照 """ try: SnapshotService.make_snapshots_from_path(self.cluster_name, self.path) return self.ajax_ok(close_current=False) except MakeSnapshotError: return self.ajax_popup(code=300, msg="父节点快照尚未生成,无法创建快照!")
class ZdZnodeImportTreeHandler(CommonBaseHandler): """batch edit, 批量修改 """ args_list = [ ArgsMap('path', required=True), ArgsMap('cluster_name', required=True), ] @authenticated def response(self): '''batch edit ''' return self.render('config/znode/batchimport.html', action='/config/znode/importsave', cluster_name=self.cluster_name, parent_path=self.path, uploadfile='', child_znodes=[])
class WsSnapshotDeleteNodesHandler(CommonBaseHandler): """删除快照节点树形结构信息 """ args_list = [ ArgsMap('cluster_name', required=True), ArgsMap('node_path', required=True), ArgsMap('recursive', default='0') ] @authenticated def response(self): """删除树节点节点 """ err_msg = SnapshotService.delete_snapshot_nodes( self.cluster_name, self.node_path, self.recursive) if err_msg: return self.ajax_popup(code=300, msg=err_msg) else: return self.ajax_ok(close_current=False)
class ZdQconfFeedbackSaveHandler(ApiBaseHandler): """save """ args_list = [ ArgsMap('id', default=''), ArgsMap('hostname', default=''), ArgsMap('ip', default=''), ArgsMap('node_whole', default=''), ArgsMap('value_md5', default=''), ArgsMap('idc', default=''), ArgsMap('update_time', default=''), ArgsMap('data_type', default=''), ArgsMap('deleted', default=''), ] def response(self): '''add ''' feedback = ZdQconfFeedback.one(idc=self.idc, ip=self.ip, path=self.node_whole) if feedback is None: # create new feedback record feedback = ZdQconfFeedback() # 填充字段 if self.idc: feedback.idc = self.idc if self.ip: feedback.ip = self.ip if self.hostname: feedback.hostname = self.hostname if self.node_whole: feedback.path = self.node_whole if self.value_md5: feedback.md5_value = self.value_md5 if self.update_time: # convert unix timestamp to datetime update_time = datetime.fromtimestamp(int( self.update_time)).strftime('%Y-%m-%d %H:%M:%S') feedback.update_time = update_time if self.data_type: feedback.data_type = self.data_type # 自定义字段 if self.deleted: feedback.deleted = self.deleted feedback.save() # qconf protocol, return '0' means ok self.finish('0')
class ZdZnodeChildHandler(CommonBaseHandler): """tree """ args_list = [ ArgsMap('cluster_name', required=True), ArgsMap('path', default="/"), ArgsMap('pid', default=0), ] @authenticated def response(self): """返回指定zookeeper集群的znode信息, 响应ajax请求 """ nodes = [] normalized_path = normalize_path(self.path) if USE_QCONF: ZnodeService.get_znode_tree_from_qconf(self.cluster_name, normalized_path, nodes) else: zoo_client = ZookeeperService.get_zoo_client(self.cluster_name) if not zoo_client: return self.ajax_popup(code=300, msg="连接zookeeper出错!") ZnodeService.get_znode_tree(zoo_client, normalized_path, nodes, current_id=self.pid + 1, parent_id=self.pid) if normalized_path != "/" and len(nodes) <= 1: return self.ajax_popup(code=300, msg="对不起,该节点路径下(%s)无数据!" % self.path) for node in nodes: zk_node = ZdZnode.one(path=node["path"], cluster_name=self.cluster_name) if zk_node: node['type'] = zk_node.type node['business'] = zk_node.business node['data'] = ZookeeperService.get(self.cluster_name, node["path"]) znodes_data = json.dumps(nodes) return znodes_data
class PassPortHandler(CommonBaseHandler): '''search,搜索 ''' args_list = [ ArgsMap('token', required=True), ArgsMap('fromPath', default='/'), ] def response(self): self.set_secure_cookie('token', self.token) url = PASSPORT['publicUrl'] + 'api/findAdminByToken?token=' + quote( self.token) + '&projectKey=' + quote(PASSPORT['projectKey']) resp = json.load(urlopen(url)) self.set_secure_cookie('email', quote(resp['email'].encode('utf-8'))) self.set_secure_cookie('name', quote(resp['name'].encode('utf-8'))) # self.set_cookie('email', (resp['email']).encode('utf-8')) # self.set_cookie('name', (resp['name']).encode('utf-8')) redirecturl = self.request.protocol + '://' + self.request.host + unquote( self.fromPath) self.redirect(redirecturl.encode('utf-8'))
class ZdZnodeSyncstatusHandler(CommonBaseHandler): '''syncstatus ''' args_list = [ ArgsMap('cluster_name', required=True), ArgsMap('path', required=True) ] @authenticated def response(self): '''客户端同步状况查看 ''' # md5 value in zookeeper znode_value = ZookeeperService.get(self.cluster_name, self.path) #znode_md5_value = hashlib.md5(znode_value).hexdigest() # agent value, idc转换为zookeeper集群名称,方便统一管理 feedbacks = ZdFeedback.select().where( (ZdFeedback.cluster == self.cluster_name) & (ZdFeedback.path == self.path) & (ZdFeedback.deleted == '0')) count = feedbacks.count() equal_counts = 0 not_equal_counts = 0 # check sync_status for feedback in feedbacks: feedback.znode_value = znode_value if znode_value == feedback.value: feedback.sync_status = "相等" equal_counts = equal_counts + 1 else: feedback.sync_status = "不等" not_equal_counts = not_equal_counts + 1 return self.render('config/znode/syncstatus.html', path=self.path, count=count, equal_counts=equal_counts, not_equal_counts=not_equal_counts, cluster=self.cluster_name, feedbacks=feedbacks)