def __send_request_to_ne(self): """ Method: __send_request_to_ne Description: 发送导出命令给网元 Parameter: 无 Return: Others: """ ne_pid = NEInfoMgr.get_ne_pid_by_id(self.ne_id) if ne_pid is None: tracelog.error("get_ne_pid_by_id(%d) failed." % self.ne_id) return req = db_sync_base.SyncFullRequest() req.ne_id = self.ne_id req.ftp_ip = self.get_worker().get_app().get_device_cfg_info().get_device_external_ip() req.ftp_port = db_sync_update_const.FTP_SERVER_PORT req.file_path = db_sync_update_const.NE_DB_DUMP_COMPRESSED_PATH % self.ne_id # 位于data/ftp目录中 req.ftp_user = "******" # TODO req.ftp_pwd = "ftp_user" # TODO frame = bf.AppFrame() frame.set_cmd_code(cmd_code_def.CMD_SYNC_NE_EXP_FULL) frame.add_data(req.serialize()) frame.set_receiver_pid(ne_pid) frame.set_next_pid(self.get_worker().get_pid("EAUGate")) mocs = self.get_worker().get_app().get_synchronized_mocs() timeout = len(mocs)*400 + 400 self.wait_for_ack(frame, timeout) # 超时时间,单位秒
def __handle_full_sync_ntf(self, frame, ne_id, sync_object, event): """ Method: __handle_full_sync_ntf Description: 处理全同步事件通知 Parameter: frame: 数据帧 ne_id: 网元的ID sync_object: 同步传输对象 event: 事件通知 Return: Others: """ tracelog.info('receive full sync notification from NE(%d)' % ne_id) error_code = NEInfoMgr.set_ne_need_sync_full(ne_id , self.get_worker().get_app().get_mit_manager() , True) if error_code != 0: tracelog.error("set_ne_need_sync_full() failed: %d" % error_code) # 不给EAU回应答;EAU收到收不到应答后,下次重试 return result = DBSyncResult() result.id = sync_object.id result.return_code = error_code result.error_message = '' result.event_ids = [] self.__send_ack(frame, result.serialize())
def handle_cmd(self, frame): """ Method: handle_cmd Description: 处理消息 Parameter: frame: AppFrame Return: Others: """ ne_id = int(frame.get_data()) self.ne_id = ne_id # 获取内存中的状态 # 如果已经在同步了,那么就不用理会本次请求 ret = NEInfoMgr.change_ne_state_to_exp(ne_id, self.get_worker().get_mit()) if ret != 0: tracelog.error("can not start sync full task. ne_id: %d" % ne_id) return tracelog.info("start sync full, ne_id:%d" % ne_id) # 如果不存在需要同步的MOC,那么就直接退出 mocs = self.get_worker().get_app().get_synchronized_mocs() if len(mocs) == 0: tracelog.info("NE has no MOC to sync, ne_id:%d" % ne_id) NEInfoMgr.change_ne_state_to_normal(self.ne_id , self.get_worker().get_mit() , False) return if self.__prepare_file_dir() != 0: tracelog.error("can not start sync full task. ne_id: %d" % ne_id) self.__change_ne_state_when_exp_failed(True) return # 获取NE的pid,向其发起同步 self.__send_request_to_ne()
def _on_round_over(self, round_id, r): """ Method: _on_round_over Description: 响应round结束的事件 Parameter: round_id: round的id r: round对象 Return: Others: """ try: frame = r.get_response_frame() rep = db_sync_base.SyncFullResponse.deserialize(frame.get_data()) except: tracelog.exception("_on_round_over error, NE id:%d" % self.ne_id) self.__change_ne_state_when_exp_failed(True) return if rep.return_code == err_code_mgr.ER_SYNC_NO_TABLE_NEED_SYNC: tracelog.info("the NE has no table to sync.") # 这种情况下,直接认为同步结束,并且不用再重试 self.__change_ne_state_when_exp_failed(False) return if rep.return_code != 0: tracelog.error("NE export data failed. ne id:%d, error:%d,%s" % ( self.ne_id , rep.return_code , rep.description)) self.__change_ne_state_when_exp_failed(True) return tracelog.info("NE export data ok. ne id:%d" % (self.ne_id)) # 将NE的状态修改为导入中 ret = NEInfoMgr.change_ne_state_to_imp(self.ne_id , self.get_worker().get_mit()) if ret != 0: tracelog.error("change_ne_state_to_imp failed. ne_id:%d" % self.ne_id) # 开始执行导入 frame = bf.AppFrame() frame.set_cmd_code(cmd_code_def.CMD_START_IMP_FULL) frame.add_data(str(self.ne_id)) self.get_worker().dispatch_frame_to_worker("SyncFullImpWorker", frame)
def __change_ne_state_when_exp_failed(self, need_retry): """ Method: __change_ne_state_when_exp_failed Description: 当网元导出失败时,修改网元状态 Parameter: need_retry: 是否需要下次全同步 Return: Others: """ ret = NEInfoMgr.change_ne_state_to_normal(self.ne_id , self.get_worker().get_mit() , need_retry) if ret != 0: tracelog.error("__change_ne_state_when_exp_failed failed." "ne_id:%d" % self.ne_id)
def __change_ne_state_when_imp_ok(self): """ Method: __change_ne_state_when_imp_ok Description: 当导入网元的数据成功时修改网元的状态 Parameter: 无 Return: Others: """ ret = NEInfoMgr.change_ne_state_to_normal(self.ne_id , self.get_worker().get_mit() , False) if ret != 0: tracelog.error("__change_ne_state_when_imp_failed failed." "ne_id:%d" % self.ne_id)
def handle_cmd(self, frame): """ Method: handle_cmd Description: 同步消息处理函数 Parameter: frame: 请求消息 Return: 无 Others: """ buf = frame.get_data() tracelog.info('received data from client at %s' % datetime.datetime.now().isoformat()) ne_id = NEInfoMgr.get_ne_id_by_pid(frame.get_sender_pid()) if ne_id is None: tracelog.error("received unknow data sync notification from NE, " "pid:%d" % frame.get_sender_pid()) return debug.info('ne id: %d' % (ne_id)) # 如果网元正处于全同步中,那么直接忽视本次事件通知 if not NEInfoMgr.is_ne_state_normal(ne_id): tracelog.info('database is full-synchonizing') return sync_object = DBSyncObject.deserialize(buf) result = DBSyncResult() result.id = sync_object.id debug.info('sync object id: %d' % sync_object.id) for event in sync_object.sync_events: if event.type == DBSyncType.FULL: self.__handle_full_sync_ntf(frame, ne_id, sync_object, event) self.get_worker().get_app().set_sync_sn(ne_id, event.priority, event.id) return events = [] for event in sync_object.sync_events: sync_sn = self.get_worker().get_app().get_sync_sn(ne_id, event.priority) debug.info('ne_id: %d, priority: %d, event_id: %d sync_sn: %d' % (ne_id, event.priority, event.id, sync_sn)) if event.id <= sync_sn: #该Event已经同步成功,重复提交将被忽略 tracelog.info('event#%d was already synchonized.current sn: %d' % (event.id, sync_sn)) result.event_ids.append(event.id) else: events.append(event) manager = self.get_worker().get_app().get_data_manager() debug.info('incremental sync starts') ret_code = manager.sync_data(events, ne_id) if ret_code != DBSyncStatus.ERROR_SUCCESS: tracelog.info('sync data failed. exit code: %d' % ret_code) if ret_code == DBSyncStatus.ERROR_CONFLICT: # 将EAU的状态设置为需要全同步 NEInfoMgr.set_ne_need_sync_full(ne_id , self.get_worker().get_app().get_mit_manager() , True) # 不给EAU回应答;EAU收到收不到应答超时后,下次重试 return for event in events: self.get_worker().get_app().set_sync_sn(ne_id, event.priority, event.id) debug.info(' event#%04d: return %d' % (event.id, ret_code)) result.event_ids.append(event.id) self.__send_ack(frame, result.serialize()) tracelog.info(result.event_ids) tracelog.info('sync processing completed.')