def test_fd_sock(self): d = Dispatcher() self.disp = d # for _test_fd_sock_helper() import socket s = socket.socket() s.setblocking(0) s.bind(('', 65000)) s.listen(10) d.fd_register(s.fileno(), d.EV_FD_IN, self._test_fd_sock_helper) d.fd_modify(s.fileno(), 0) d.fd_unregister(s.fileno()) c = socket.socket() c.setblocking(0) ret = c.connect_ex(('localhost', 65000)) self.assertEqual(ret, 115, 'async connect failed') d.fd_register(s.fileno(), d.EV_FD_IN, self._test_fd_sock_helper) d.loop() self.assertEqual(self.got_fd, s.fileno()) self.assertEqual(self.got_eventmask, Dispatcher.EV_FD_IN) del d del s del c
class OpenRpdDriver(HalDriverClient): """The OpenRPD base driver """ ## __metaclass__ = AddLoggerToClass def __init__(self, drvName, drvDesc, drvVer, supportedMsgType, supportedNotificationMsgs, interestedNotification=None): """ :param drvName: The driver name, such as Generic Driver :param drvDesc: driver for full Cable Labs RPHY support :param drvVer: driver version :param supportedMsgType: will support all RPHY OpenRPD message types :param supportedNotificationMsgs: the supported notification msg types :return: OpenRPD Driver object NOTES: The 'supportedNotificationMsgs' parameter passed to HalDriverClient and then forwarded to HalManager.py, but it seems HalManager.py does NOT do anything with this parameter. Consider remove it from ClientProvision.proto? As of now, we don't need to have this parameter. It just adds confusion! """ if supportedMsgType is None: supportedMsgType = OpenRpdMsgHandler.default_supported_msg_types super(OpenRpdDriver, self).__init__(drvName, drvDesc, drvVer, supportedMsgType, supportedNotificationMsgs, interestedNotification) # update the supported messages self.HalMsgsHandler = { "HalClientRegisterRsp": self.recv_register_msg_cb, "HalClientHelloRsp": self.recvHelloRspMsgCb, "HalConfig": self.recv_cfg_msg_cb, "HalConfigRsp": self.recv_cfg_msg_rsp_cb, "HalNotification": self.recvNotificationCb, } # Handlers for different configuration messages self.hal_config_msg_handlers = { HalConfigMsg.MsgTypeRpdCapabilities: OpenRpdMsgHandler.capabilities_get, HalConfigMsg.MsgTypeDsRfPort: OpenRpdMsgHandler.config_ds_port, HalConfigMsg.MsgTypeDsScQamChannelConfig: OpenRpdMsgHandler.config_dsqam_channel, HalConfigMsg.MsgTypeDsOfdmChannelConfig: OpenRpdMsgHandler.config_dsofdm_channel, HalConfigMsg.MsgTypeDsOfdmProfile: OpenRpdMsgHandler.config_dsofdm_profile, HalConfigMsg.MsgTypeDsRfPortPerf: OpenRpdMsgHandler.req_dummy, HalConfigMsg.MsgTypeDsScQamChannelPerf: OpenRpdMsgHandler.req_dsqam_channel_status, HalConfigMsg.MsgTypeDsOfdmChannelPerf: OpenRpdMsgHandler.req_dsofdm_channel_status, HalConfigMsg.MsgTypeDsOob551IPerf: OpenRpdMsgHandler.req_oob551_mod_status, HalConfigMsg.MsgTypeDsOob552Perf: OpenRpdMsgHandler.req_oob552_mod_status, HalConfigMsg.MsgTypeNdfPerf: OpenRpdMsgHandler.req_dummy, HalConfigMsg.MsgTypeUsRfPortPerf: OpenRpdMsgHandler.req_dummy, HalConfigMsg.MsgTypeUsScQamChannelConfig: OpenRpdMsgHandler.config_usatdma_channel, HalConfigMsg.MsgTypeUsOfdmaChannelConfig: OpenRpdMsgHandler.config_usofdma_channel, HalConfigMsg.MsgTypeUsOfdmaInitialRangingIuc: OpenRpdMsgHandler.config_dummy, HalConfigMsg.MsgTypeUsOfdmaFineRangingIuc: OpenRpdMsgHandler.config_dummy, HalConfigMsg.MsgTypeUsOfdmaDataRangingIuc: OpenRpdMsgHandler.config_dummy, HalConfigMsg.MsgTypeUsOfdmaDataIuc: OpenRpdMsgHandler.config_dummy, HalConfigMsg.MsgTypeUsOfdmaSubcarrierCfgState: OpenRpdMsgHandler.req_dummy, HalConfigMsg.MsgTypeUsScQamChannelPerf: OpenRpdMsgHandler.req_dummy, HalConfigMsg.MsgTypeUsOfdmaChannelPerf: OpenRpdMsgHandler.req_dummy, HalConfigMsg.MsgTypeUsOob551IPerf: OpenRpdMsgHandler.req_oob551_demod_status, HalConfigMsg.MsgTypeUsOob552Perf: OpenRpdMsgHandler.req_oob552_demod_status, HalConfigMsg.MsgTypeNdrPerf: OpenRpdMsgHandler.req_dummy, HalConfigMsg.MsgTypeSidQos: OpenRpdMsgHandler.config_sid_qos, # L2TPv3 messages HalConfigMsg.MsgTypeL2tpv3CapabilityQuery: OpenRpdMsgHandler.capabilities_get, HalConfigMsg.MsgTypeL2tpv3SessionReqNone: OpenRpdMsgHandler.req_depi_pw, HalConfigMsg.MsgTypeL2tpv3SessionReqDsOfdm: OpenRpdMsgHandler.req_depi_pw, HalConfigMsg.MsgTypeL2tpv3SessionReqDsOfdmPlc: OpenRpdMsgHandler.req_depi_pw, HalConfigMsg.MsgTypeL2tpv3SessionReqDsScqam: OpenRpdMsgHandler.req_depi_pw, HalConfigMsg.MsgTypeL2tpv3SessionReqUsAtdma: OpenRpdMsgHandler.req_uepi_pw, HalConfigMsg.MsgTypeL2tpv3SessionReqUsOfdma: OpenRpdMsgHandler.req_uepi_pw, HalConfigMsg.MsgTypeL2tpv3SessionReqScte551Fwd: OpenRpdMsgHandler.req_dummy, HalConfigMsg.MsgTypeL2tpv3SessionReqScte551Ret: OpenRpdMsgHandler.req_dummy, HalConfigMsg.MsgTypeL2tpv3SessionReqScte552Fwd: OpenRpdMsgHandler.req_dummy, HalConfigMsg.MsgTypeL2tpv3SessionReqScte552Ret: OpenRpdMsgHandler.req_dummy, HalConfigMsg.MsgTypeL2tpv3SessionReqNdf: OpenRpdMsgHandler.req_ndf, HalConfigMsg.MsgTypeL2tpv3SessionReqNdr: OpenRpdMsgHandler.req_ndr, # Ptp # HalConfigMsg.MsgTypeRdtiConfig: config_docsis_timer HalConfigMsg.MsgTypeL2tpv3CinIfAssignment: OpenRpdMsgHandler.cin_if_assign, HalConfigMsg.MsgTypeL2tpv3LcceIdAssignment: OpenRpdMsgHandler.lcce_id_assign, # VspAvpQuery HalConfigMsg.MsgTypeVspAvpExchange: OpenRpdMsgHandler.vsp_avp_handler, # RcpVendorSpecificTlv HalConfigMsg.MsgTypeRcpVendorSpecific: OpenRpdMsgHandler.vsp_tlv_handler, } self.disconnected = True self.dispatcher = Dispatcher() # setup the logging self.logger = OpenRpdMsgHandler.get_msg_handler_logger() self.logger.info("OpenRPD Driver Initialized") self.seqNum = 0 # start modeled from HalPtpDriver.py def start(self, simulate_mode=False): """start poll the transport socket :return: """ self.logger.info("Setup the Hal Transport connection...") self.connectionSetup() self.logger.info("Connection setup done...") self.logger.info("Register the driver with the Hal manager...") self.register(self.drvID) self.logger.info("End of register...") self.dispatcher.loop() def recv_register_msg_cb(self, cfg): """the callback handler for the configuration message Modified from base class by registering the sockets with dispatcher. :param cfg: the configuration message received from the Hal :return: """ # self.logger.debug("Recv a Message from the Hal:" % str(cfg.msg)) if cfg.msg.Rsp.Status != HalCommon_pb2.SUCCESS: self.logger.error("Cannot register to Hal, reason[%s]" % cfg.msg.Rsp.ErrorDescription) return self.drvID = cfg.msg.ClientID # Setup the push and pull connection self.pullPath = cfg.msg.PathFromHalToClient self.pushPath = cfg.msg.PathFromClientToHal # get the index of the path index = self._getIndexFromPath() if index == -1: self.logger.error("Cannot get index from the path [%s]" % self.pushPath) return if self.index == -1: self.index = index self.pushSock = HalTransport( HalTransport.HalTransportClientAgentPull, HalTransport.HalClientMode, index=index, socketMode=HalTransport.HalSocketPushMode, disconnectHandlerCb=self.connectionDisconnectCb) self.pullSock = HalTransport( HalTransport.HalTransportClientAgentPush, HalTransport.HalClientMode, index=index, socketMode=HalTransport.HalSocketPullMode, disconnectHandlerCb=self.connectionDisconnectCb) # register driver's sockets with the dispatcher self.dispatcher.fd_register(self.pullSock.socket, zmq.POLLIN, self.openrpd_drv_hal_cb) self.dispatcher.fd_register(self.pushSock.monitor, zmq.POLLIN, self.openrpd_drv_hal_cb) self.dispatcher.fd_register(self.pullSock.monitor, zmq.POLLIN, self.openrpd_drv_hal_cb) # send Hello To Hal self.sayHelloToHal() if (None is not self.interestedNotification): self.sendInterestedNotifications(self.interestedNotification) self.disconnected = False return def connectionSetup(self): """Create the connection to the mgr :return: """ self.logger.info("Create the connection to the mgr....") # Create a connection to Hal driver mgr self.mgrConnection = HalTransport( HalTransport.HalTransportClientMgr, HalTransport.HalClientMode, disconnectHandlerCb=self.disconnectCb) self.mgrConnection.connects() self.HalMsgsHandler[ self.mgrConnection.socket] = self.recv_register_msg_cb # register the mgr socket with the dispatcher self.dispatcher.fd_register(self.mgrConnection.socket, zmq.POLLIN, self.openrpd_drv_hal_cb) self.dispatcher.fd_register(self.mgrConnection.monitor, zmq.POLLIN, self.openrpd_drv_hal_cb) def connection_cleanup(self): """Close the connection to the mgr :return: """ if self.disconnected: self.logger.debug("A previous event has been processed, skip it!") return if self.mgrConnection is not None: self.dispatcher.fd_unregister(self.mgrConnection.socket) self.dispatcher.fd_unregister(self.mgrConnection.monitor) self.mgrConnection.socket.disable_monitor() self.mgrConnection.monitor.close() self.mgrConnection.socket.close() if self.pullSock is not None: self.dispatcher.fd_unregister(self.pullSock.socket) self.dispatcher.fd_unregister(self.pullSock.monitor) self.pullSock.socket.disable_monitor() self.pullSock.monitor.close() self.pullSock.socket.close() if self.pushSock is not None: self.dispatcher.fd_unregister(self.pushSock.monitor) self.pushSock.socket.disable_monitor() self.pushSock.monitor.close() self.pushSock.socket.close() self.disconnected = True def disconnectCb(self, msg): """A disconnect condition has been detected, clean up the connection and then reconnect and re-register with the Hal. :param msg: :return: """ self.logger.error("Detected disconnected condition") if self.disconnected: self.logger.info("A previous event has been processed, skip it!") return self.logger.info("Detected disconnected, registering again") # clean up the push and pull socket self.dispatcher.fd_unregister(self.mgrConnection.socket) self.dispatcher.fd_unregister(self.mgrConnection.monitor) self.mgrConnection.monitor.close() self.mgrConnection.close() # re-register the message self.connectionSetup() # The zmq lower part will handle the reconnect self.register(self.drvID) self.disconnected = True def openrpd_drv_hal_cb(self, sock, mask): self.logger.debug("Driver received hal cb event") if self.pushSock is not None and sock == self.pushSock.monitor: self.pushSock.monitorHandler(recv_monitor_message(sock)) return if self.pullSock is not None and sock == self.pullSock.monitor: self.pullSock.monitorHandler(recv_monitor_message(sock)) return if sock == self.mgrConnection.monitor: self.mgrConnection.monitorHandler(recv_monitor_message(sock)) return while sock.getsockopt(zmq.EVENTS) and zmq.POLLIN: try: bin = sock.recv(flags=zmq.NOBLOCK) msg = HalMessage.DeSerialize(bin) self.logger.debug("Got a zmq msg:%s type:%s" % (msg.msg, msg.type)) if msg.type in self.HalMsgsHandler: handler = self.HalMsgsHandler[msg.type] handler(msg) except zmq.ZMQError as e: self.logger.debug( "Got an error when trying with nonblock read:" + str(e)) break except Exception as e: self.logger.error("Got an un-expected error:%s", str(e)) break def recvNotificationCb(self, ntf): """Receive a notification message from the HAL. :param ntf: :return: """ try: handler = self.hal_config_msg_handlers[ntf.msg.HalNotificationType] self.logger.info("Receive a interest notification message:" + str(ntf.msg)) if not isinstance(ntf, HalMessage): raise AttributeError("Invalid HAL message passed") ntf = handler(ntf) if None is not ntf: self.send_cfg_msg(HalConfigMsg.MsgTypeVspAvpExchange, ntf.msg.HalNotificationPayLoad) else: self.logger.info("Notification message return is None") except Exception as e: self.logger.error("Got an error:%s, the ntf msg:%s", str(e), ntf.msg) def send_cfg_msg(self, cfgMsgType, payload): msg = HalMessage("HalConfig", SrcClientID=self.drvID, CfgMsgType=cfgMsgType, SeqNum=self.seqNum, CfgMsgPayload=payload) self.logger.debug("sending config - type: %d, msg: %s" % (cfgMsgType, msg)) self.pushSock.send(msg.Serialize()) self.seqNum += 1 return def send_cfg_rsp_msg(self, cfg): """The configuration response routine :param cfg: The original configuration message :return: """ result = HalCommon_pb2.SUCCESS cfgMsg = cfg.msg l2tpcfgmsgType = (HalConfigMsg.MsgTypeL2tpv3SessionReqDsOfdm, HalConfigMsg.MsgTypeL2tpv3SessionReqDsOfdmPlc, HalConfigMsg.MsgTypeL2tpv3SessionReqDsScqam, HalConfigMsg.MsgTypeL2tpv3SessionReqUsAtdma, HalConfigMsg.MsgTypeL2tpv3SessionReqUsOfdma, HalConfigMsg.MsgTypeL2tpv3SessionReqScte551Fwd, HalConfigMsg.MsgTypeL2tpv3SessionReqScte551Ret, HalConfigMsg.MsgTypeL2tpv3SessionReqScte552Fwd, HalConfigMsg.MsgTypeL2tpv3SessionReqScte552Ret, HalConfigMsg.MsgTypeL2tpv3SessionReqNdf, HalConfigMsg.MsgTypeL2tpv3SessionReqNdr, HalConfigMsg.MsgTypeL2tpv3CinIfAssignment, HalConfigMsg.MsgTypeL2tpv3LcceIdAssignment) if cfgMsg.CfgMsgType in l2tpcfgmsgType: rsp = L2tpv3Hal_pb2.t_l2tpSessionRsp() req = L2tpv3Hal_pb2.t_l2tpSessionReq() req.ParseFromString(cfgMsg.CfgMsgPayload) # fill session_selector rsp.session_selector.local_session_id = req.session_selector.local_session_id rsp.session_selector.remote_session_id = req.session_selector.remote_session_id rsp.session_selector.local_ip = req.session_selector.local_ip rsp.session_selector.remote_ip = req.session_selector.remote_ip rsp.result = True elif (cfgMsg.CfgMsgType == HalConfigMsg.MsgTypeVspAvpExchange): rsp = L2tpv3VspAvp_pb2.t_l2tpVspAvpMsg() rsp.ParseFromString(cfgMsg.CfgMsgPayload) self.logger.debug( "vsp_avp_handler re-parse srcClientID: %s, Seq num: %d, " "op: %d, vid %d, attr %d, strVal %s" % (cfg.msg.SrcClientID, cfg.msg.SeqNum, rsp.oper, rsp.vendorId, rsp.attrType, rsp.attrValBuf)) if rsp.rspCode == L2tpv3VspAvp_pb2.t_l2tpVspAvpMsg( ).VSP_AVP_STATUS_FAILURE: # send HalConfigRsp with failure status if OpenRPD driver can't handle this. result = HalCommon_pb2.FAILED elif (cfgMsg.CfgMsgType == HalConfigMsg.MsgTypeRcpVendorSpecific): rsp = t_RcpMessage() rsp.ParseFromString(cfgMsg.CfgMsgPayload) self.logger.debug("send_cfg_rsp_msg payload: %s, result: %d" % (rsp.RpdDataMessage.RpdData, rsp.RcpDataResult)) else: rsp = t_RcpMessage() rsp.ParseFromString(cfgMsg.CfgMsgPayload) self.logger.debug("send_cfg_rsp_msg payload: %s" % rsp.RpdDataMessage.RpdData) rsp.RcpDataResult = t_RcpMessage.RCP_RESULT_OK payload = rsp.SerializeToString() self.logger.debug("cfg response srcClientID: %s, Seq num: %d" % (cfgMsg.SrcClientID, cfgMsg.SeqNum)) msg = HalMessage("HalConfigRsp", SrcClientID=cfgMsg.SrcClientID, SeqNum=cfgMsg.SeqNum, Rsp={ "Status": HalCommon_pb2.SUCCESS, "ErrorDescription": "" }, CfgMsgType=cfgMsg.CfgMsgType, CfgMsgPayload=payload) self.logger.debug("sending cfg response - type: %d, msg: %s" % (cfgMsg.CfgMsgType, msg)) self.pushSock.send(msg.Serialize()) def recv_cfg_msg_rsp_cb(self, cfg): cfgMsg = cfg.msg self.logger.debug("receive cfg response - type: %d" % (cfgMsg.CfgMsgType)) pass def recv_cfg_msg_cb(self, cfg): """Receive a configuration message from the Hal, processing it :param cfg: :return: """ try: handler = self.hal_config_msg_handlers[cfg.msg.CfgMsgType] self.logger.info("Received a cfg message type: %d", cfg.msg.CfgMsgType) if not isinstance(cfg, HalMessage): raise AttributeError("Invalid HAL message passed") cfg = handler(cfg) self.send_cfg_rsp_msg(cfg) except Exception as e: self.logger.error("Got an error:%s, the cfg msg:%s", str(e), cfg.msg) def cleanup_sockets(self): for fd in self.fd_to_socket: sock = self.fd_to_socket[fd] self.poller.unregister(sock) sock.close() self.fd_to_socket.clear()
class ProcessAgent(object): __metaclass__ = AddLoggerToClass PROCESSSTATE_ALIVE = 0 PROCESSSTATE_DEAD = -1 AGENTTYPE_INTERFACE_STATUS = provision_pb2.AGENTTYPE_INTERFACE_STATUS AGENTTYPE_8021X = provision_pb2.AGENTTYPE_8021X AGENTTYPE_DHCP = provision_pb2.AGENTTYPE_DHCP AGENTTYPE_TOD = provision_pb2.AGENTTYPE_TOD AGENTTYPE_IPSEC = provision_pb2.AGENTTYPE_IPSEC AGENTTYPE_GCP = provision_pb2.AGENTTYPE_GCP AGENTTYPE_PTP = provision_pb2.AGENTTYPE_PTP AGENTTYPE_L2TP = provision_pb2.AGENTTYPE_L2TP AgentName = { AGENTTYPE_INTERFACE_STATUS: "AGENTTYPE_INTERFACE_STATUS", AGENTTYPE_8021X: "AGENTTYPE_8021X", AGENTTYPE_DHCP: "AGENTTYPE_DHCP", AGENTTYPE_TOD: "AGENTTYPE_TOD", AGENTTYPE_IPSEC: "AGENTTYPE_IPSEC", AGENTTYPE_GCP: "AGENTTYPE_GCP", AGENTTYPE_PTP: "AGENTTYPE_PTP", AGENTTYPE_L2TP: "AGENTTYPE_L2TP", } SockPathMapping = { AGENTTYPE_INTERFACE_STATUS: { "api": "ipc:///tmp/rpd_provision_agent_interface_status_api.sock", "push": "ipc:///tmp/rpd_provision_agent_interface_status_push.sock", "pull": "ipc:///tmp/rpd_provision_agent_interface_status_pull.sock", "cli": "ipc:///tmp/zmq-interface.ipc" }, AGENTTYPE_8021X: { "api": "ipc:///tmp/rpd_provision_agent_8021x_api.sock", "push": "ipc:///tmp/rpd_provision_agent_8021x_push.sock", "pull": "ipc:///tmp/rpd_provision_agent_8021x_pull.sock", "cli": "ipc:///tmp/zmq-8021x.ipc" }, AGENTTYPE_DHCP: { "api": "ipc:///tmp/rpd_provision_agent_dhcp_api.sock", "push": "ipc:///tmp/rpd_provision_agent_dhcp_push.sock", "pull": "ipc:///tmp/rpd_provision_agent_dhcp_pull.sock", "cli": "ipc:///tmp/zmq-dhcp.ipc" }, AGENTTYPE_TOD: { "api": "ipc:///tmp/rpd_provision_agent_tod_api.sock", "push": "ipc:///tmp/rpd_provision_agent_tod_push.sock", "pull": "ipc:///tmp/rpd_provision_agent_tod_pull.sock", "cli": "ipc:///tmp/zmq-tod.ipc" }, AGENTTYPE_IPSEC: { "api": "ipc:///tmp/rpd_provision_agent_ipsec_api.sock", "push": "ipc:///tmp/rpd_provision_agent_ipsec_push.sock", "pull": "ipc:///tmp/rpd_provision_agent_ipsec_pull.sock", "cli": "ipc:///tmp/zmq-ikev2.ipc" }, AGENTTYPE_GCP: { "api": "ipc:///tmp/rpd_provision_agent_gcp_api.sock", "push": "ipc:///tmp/rpd_provision_agent_gcp_push.sock", "pull": "ipc:///tmp/rpd_provision_agent_gcp_pull.sock", "cli": "ipc:///tmp/zmq-gcp.ipc" }, AGENTTYPE_PTP: { "api": "ipc:///tmp/rpd_provision_agent_ptp_api.sock", "push": "ipc:///tmp/rpd_provision_agent_ptp_push.sock", "pull": "ipc:///tmp/rpd_provision_agent_ptp_pull.sock", "cli": "ipc:///tmp/zmq-ptp.ipc" }, AGENTTYPE_L2TP: { "api": "ipc:///tmp/rpd_provision_agent_l2tp_api.sock", "push": "ipc:///tmp/rpd_provision_agent_l2tp_push.sock", "pull": "ipc:///tmp/rpd_provision_agent_l2tp_pull.sock", "cli": "ipc:///tmp/zmq-l2tp.ipc" }, } def __init__(self, agent_type): if agent_type not in self.AgentName: self.logger.error("Cannot setup the process agent for type:%d" % agent_type) raise ProcessAgentError("Unknown Type:%d" % agent_type) if self._process_is_running(agent_type): self.logger.error( "Cannot setup the process agent for %s since a same agent has been up", agent_type) raise ProcessAgentError("Cannot setup a duplicated %s" % self.AgentName[agent_type]) event_path = self.SockPathMapping[agent_type]["pull"] api_path = self.SockPathMapping[agent_type]["api"] cli_path = self.SockPathMapping[agent_type]["cli"] # Create the pull and api sock to handle the request self.event_transport = Transport(event_path, Transport.PULLSOCK) self.api_transport = Transport(api_path, Transport.REPSOCK) self.cli_transport = Transport(cli_path, Transport.REPSOCK) # create a dispatcher self.dispatcher = Dispatcher() # register the event self.register_transport(self.event_transport, self._process_event_callback, None) self.register_transport(self.api_transport, self.api_event_callback, None) self.register_transport(self.cli_transport, self._process_cli_callback, None) # the region to hold all the process obj self.processes = {} # the region to hold all the ccap cores self.ccap_cores = {} self.mgrs = {} # agent information maintain self.name = self.AgentName[agent_type] self.id = agent_type # we will generate uuid def __str__(self): """Encoding this process agent to a string.""" return ProcessAgentEncoder().encode(self) @staticmethod def is_all_agent_started(): """Check if all agents are started.""" for agent_type in ProcessAgent.AgentName: checked = False # will retry 10 times in 1 second for i in range(10): file_name = "/tmp/ProcessAgent_" + ProcessAgent.AgentName[ agent_type] try: process_file = open(file_name, "r") # get the pid pidbuff = process_file.read() process_file.close() if pidbuff: pid = int(pidbuff) # check if the pid is alive if psutil.pid_exists(pid): checked = True break except IOError: pass time.sleep(0.1) if not checked: return checked return True @staticmethod def _process_is_running(agent_type): # Check if we have setup a agent for this type file_name = "/tmp/ProcessAgent_" + ProcessAgent.AgentName[agent_type] try: process_file = open(file_name, "r") # get the pid pid = int(process_file.read()) # check if the pid is alive if psutil.pid_exists(pid): return True else: process_file.close() except IOError: pass finally: process_file = open(file_name, "w") process_file.write(str(os.getpid())) return False def api_event_callback(self, fd, eventmask): """Call back functions, the subclass should implement this function. :param fd: passed from the register. the arg should contains the transport information. :param eventmask: passed from the dispatcher, which indicates the event type. :return: None """ # Receive the msg from the remote if eventmask == 0 or self.api_transport.sock != fd: self.logger.warn("Got a fake process event[%x], ignore it." % eventmask) return if eventmask & self.dispatcher.EV_FD_ERR: self.logger.error("Got an error event, handle the failure.") # FixMe: may need more action to handle the failure return if self.api_transport.sock.getsockopt(zmq.EVENTS) != zmq.POLLIN: self.logger.debug("Got a fake event, the receive is not ready!") return try: data = self.api_transport.sock.recv(flags=zmq.NOBLOCK) msg = process_agent_pb2.api_request() msg.ParseFromString(data) self.logger.debug("Receive an api message from the FSM:%s" % str(msg)) # check the fields, we only processing the register fields fields = msg.ListFields() for field in fields: desc, value = field if desc.name == "mgr_reg": self._handle_mgr_register(value) elif desc.name == "core_reg": self._handle_core_register(value) else: self.logger.error( "Cannot handle the request since no handler for this, msg:%s.", msg) except zmq.Again: pass except Exception as e: self.logger.error("Cannot process the event, reason:%s" % str(e)) rsp = process_agent_pb2.msg_register_rsp() rsp.id = "" rsp.agent_id = self.id rsp.status = process_agent_pb2.msg_register_rsp.FAIL rsp.reason = "Exception happens" api_rsp = process_agent_pb2.api_rsp() api_rsp.reg_rsp.CopyFrom(rsp) data = api_rsp.SerializeToString() self.send_reg_rsp(data) def _handle_core_register(self, reg): self.logger.info("%s Processing the core register request:%s" % (self.AgentName[self.id], reg)) id = reg.ccap_core_id action = reg.action mgr_id = reg.mgr_id if action == process_agent_pb2.msg_core_register.REG: # check is the client has been registered if id in self.ccap_cores: self.logger.info( "The ccap core[%s] has been registered, ignore this request." % id) rsp = process_agent_pb2.msg_register_rsp() rsp.id = id rsp.agent_id = self.id rsp.status = process_agent_pb2.msg_register_rsp.OK rsp.reason = "Core [%s] has been registered, ignore this register request." % id api_rsp = process_agent_pb2.api_rsp() api_rsp.reg_rsp.CopyFrom(rsp) self.send_reg_rsp(api_rsp) return if mgr_id not in self.mgrs: self.logger.info("Cannot find the mgr[%s], core id is [%s]" % (mgr_id, id)) rsp = process_agent_pb2.msg_register_rsp() rsp.id = id rsp.agent_id = self.id rsp.status = process_agent_pb2.msg_register_rsp.FAIL rsp.reason = "Cannot find the mgr:%s." % mgr_id api_rsp = process_agent_pb2.api_rsp() api_rsp.reg_rsp.CopyFrom(rsp) self.send_reg_rsp(api_rsp) return # Add the fsm to our internal database self.ccap_cores[id] = { "mgr": mgr_id, } # send the feed back self.logger.info("CCap core [%s] registered successfully" % id) rsp = process_agent_pb2.msg_register_rsp() rsp.id = id rsp.agent_id = self.id rsp.status = process_agent_pb2.msg_register_rsp.OK rsp.reason = "Register successfully" api_rsp = process_agent_pb2.api_rsp() api_rsp.reg_rsp.CopyFrom(rsp) self.send_reg_rsp(api_rsp) return elif action == process_agent_pb2.msg_manager_register.UNREG: # check if the requester has been registered if id not in self.ccap_cores: self.logger.error( "Cannot process unregister request since we cannot find the id[%s] in local db", id) rsp = process_agent_pb2.msg_register_rsp() rsp.id = id rsp.agent_id = self.id rsp.status = process_agent_pb2.msg_register_rsp.FAIL rsp.reason = "Cannot process the unregister request since cannot find the id[%s] in local db" % id api_rsp = process_agent_pb2.api_rsp() api_rsp.reg_rsp.CopyFrom(rsp) self.send_reg_rsp(api_rsp) return # process the requester self.ccap_cores.pop(id) # send the feed back self.logger.info("CCAP core [%s] unregistered successfully" % id) rsp = process_agent_pb2.msg_register_rsp() rsp.id = id rsp.agent_id = self.id rsp.status = process_agent_pb2.msg_register_rsp.OK rsp.reason = "Unregistered successfully" api_rsp = process_agent_pb2.api_rsp() api_rsp.reg_rsp.CopyFrom(rsp) self.send_reg_rsp(api_rsp) return else: pass def _handle_mgr_register(self, reg): self.logger.info("%s Processing the mgr register request:%s" % (self.AgentName[self.id], reg)) id = reg.id action = reg.action if action == process_agent_pb2.msg_manager_register.REG: path = module_name = parameter = None if reg.HasField("path_info"): path = reg.path_info if reg.HasField("module_name"): module_name = reg.module_name if reg.HasField("parameter"): parameter = reg.parameter # check is the client has been registered if id in self.mgrs: self.logger.info( "The mgr[%s] has been registered, ignore this request." % id) rsp = process_agent_pb2.msg_register_rsp() rsp.id = id rsp.agent_id = self.id rsp.status = process_agent_pb2.msg_register_rsp.OK rsp.reason = "Mgr has been registered, ignore this register request." api_rsp = process_agent_pb2.api_rsp() api_rsp.reg_rsp.CopyFrom(rsp) self.send_reg_rsp(api_rsp) return if path is None: self.logger.error( "Cannot process the register request since the pull sock is none." ) rsp = process_agent_pb2.msg_register_rsp() rsp.id = id rsp.agent_id = self.id rsp.status = process_agent_pb2.msg_register_rsp.FAIL rsp.reason = "Path is not included in request message" api_rsp = process_agent_pb2.api_rsp() api_rsp.reg_rsp.CopyFrom(rsp) self.send_reg_rsp(api_rsp) return # Create the pull, will not register to dispatcher, since we will # use the non-block send transport = Transport(path, Transport.PUSHSOCK, Transport.TRANSPORT_CLIENT) # Add the fsm to our internal database self.mgrs[id] = { "transport": transport, "name": module_name, "para": parameter, "path": path, } # send the feed back self.logger.info("Mgr[%s] registered successfully" % id) rsp = process_agent_pb2.msg_register_rsp() rsp.id = id rsp.agent_id = self.id rsp.status = process_agent_pb2.msg_register_rsp.OK rsp.reason = "Register successfully" api_rsp = process_agent_pb2.api_rsp() api_rsp.reg_rsp.CopyFrom(rsp) self.send_reg_rsp(api_rsp) return elif action == process_agent_pb2.msg_manager_register.UNREG: # check if the requester has been registered if id not in self.mgrs: self.logger.error( "Cannot process the mgr unregister request since cannot find the id[%s] in local db" % id) rsp = process_agent_pb2.msg_register_rsp() rsp.id = id rsp.agent_id = self.id rsp.status = process_agent_pb2.msg_register_rsp.FAIL rsp.reason = "Cannot process mgr unregister request since cannot find the id[%s] in local db" % id api_rsp = process_agent_pb2.api_rsp() api_rsp.reg_rsp.CopyFrom(rsp) self.send_reg_rsp(api_rsp) return # process the requester requester = self.mgrs[id] transport = requester["transport"] if transport and transport.sock: transport.sock.close() self.mgrs.pop(id) # send the feed back self.logger.info("Id[%s] unregistered successfully" % id) rsp = process_agent_pb2.msg_register_rsp() rsp.id = id rsp.agent_id = self.id rsp.status = process_agent_pb2.msg_register_rsp.OK rsp.reason = "Unregistered successfully" api_rsp = process_agent_pb2.api_rsp() api_rsp.reg_rsp.CopyFrom(rsp) self.send_reg_rsp(api_rsp) return else: pass def _send_event_notification(self, ccap_id, status, reason, result="DOWN"): """This is a private function, used to send the event notification. :param ccap_id: ccap core ID :param status: FAIL/OK :param reason: The fail reason :param result: The success result. :return: Node """ msg_event_notification = process_agent_pb2.msg_event_notification() msg_event_notification.core_event.id = ccap_id msg_event_notification.core_event.ccap_core_id = ccap_id msg_event_notification.core_event.status = status msg_event_notification.core_event.reason = reason msg_event_notification.core_event.event_id = self.id msg_event_notification.core_event.result = result # Get the transport if ccap_id in self.ccap_cores: ccap_core = self.ccap_cores[ccap_id] transport = self.mgrs[ccap_core["mgr"]]['transport'] transport.sock.send(msg_event_notification.SerializeToString(), flags=zmq.NOBLOCK) self.logger.debug("Process an event action for id %s, return:%s" % (ccap_id, msg_event_notification)) else: self.logger.warn( "ccap id %s is not in core db of process agent %s " % (ccap_id, self.__class__)) return def _send_ka_notification(self, mgr_id, status, reason): """This is a private function, used to send the event notification. TODO paramaters dont match :param ccap_id: ccap core ID :param status: FAIL/OK :param reason: The fail reason :param result: The success result. :return: Node """ msg_event_notification = process_agent_pb2.msg_event_notification() msg_ka_rsp = process_agent_pb2.msg_ka_rsp() msg_ka_rsp.id = mgr_id msg_ka_rsp.status = status msg_ka_rsp.reason = reason msg_ka_rsp.agent_id = self.id msg_event_notification.ka_rsp.CopyFrom(msg_ka_rsp) # Get the transport if mgr_id in self.mgrs: transport = self.mgrs[mgr_id]['transport'] transport.sock.send(msg_event_notification.SerializeToString(), flags=zmq.NOBLOCK) self.logger.debug("Process an event action for id %s, return:%s" % (mgr_id, msg_ka_rsp)) else: self.logger.warn( "mgr id %s is not in mgr db of process agent %s " % (mgr_id, self.__class__)) return def process_event_action(self, action): """The subclass should overwrite this function. :param action: :return: """ raise NotImplementedError def process_ka_action(self, action): """Process the request from the client. :param action: :return: """ mgr_id = action.id event_action = action.action if event_action == process_agent_pb2.msg_manager_ka.KA: self._send_ka_notification(mgr_id, process_agent_pb2.msg_ka_rsp.OK, reason="KA successfully") else: self._send_ka_notification( mgr_id, process_agent_pb2.msg_ka_rsp.FAIL, reason="{} not supported".format(event_action)) def _process_event_callback(self, fd, eventmask): """Callback function for API socket. :param fd: passed from the dispatcher, the fd should contains the transport information :param eventmask: passed from the dispatcher, which indicates the event type. :return: None """ # Receive the msg from the remote if eventmask == 0 or self.event_transport.sock != fd: self.logger.warn("Got a fake process event, ignore it") return if eventmask & self.dispatcher.EV_FD_ERR: self.logger.error("Got an error event.") # FixMe: may need more action return if self.event_transport.sock.getsockopt(zmq.EVENTS) != zmq.POLLIN: self.logger.debug("Got a fake event, the receive is not ready!") return try: data = self.event_transport.sock.recv(flags=zmq.NOBLOCK) msg = process_agent_pb2.msg_event_request() msg.ParseFromString(data) self.logger.debug("Receive an event message from the FSM:%s" % str(msg)) # check the fields, we only processing the register fields fields = msg.ListFields() for field in fields: desc, value = field if desc.name == "action": self.process_event_action(value) elif desc.name == "ka_msg": self.process_ka_action(value) except zmq.Again: pass except Exception as e: self.logger.error("%s:Cannot process the event, reason:%s", self.name, str(e)) def process_cli_action(self, msg): """The subclass should overwrite this function. :param msg: t_CliMessage :return: """ raise NotImplementedError def _process_cli_callback(self, fd, eventmask): """Callback function for API socket. :param fd: passed from the dispatcher, the fd should contains the transport information :param eventmask: passed from the dispatcher, which indicates the event type. :return: None """ # Receive the msg from the remote if eventmask == 0 or self.cli_transport.sock != fd: self.logger.warn("Got a fake cli message, ignore it") return # FixMe: may need more action if eventmask & self.dispatcher.EV_FD_ERR: self.logger.error("Got an error when receiving the msg.") return if self.cli_transport.sock.getsockopt(zmq.EVENTS) != zmq.POLLIN: self.logger.debug( "Got a fake cli message, the receive is not ready!") return try: data = self.cli_transport.sock.recv(flags=zmq.NOBLOCK) msg = t_CliMessage() msg.ParseFromString(data) self.logger.debug("Receive an CLI message: %s" % str(msg)) self.process_cli_action(msg) except zmq.Again as e: pass except Exception as e: self.logger.error("Cannot process the CLI message, reason:%s" % str(e)) def send_reg_rsp(self, ipc_msg): """Send register response message via api sock. :param ipc_msg: message information """ if not isinstance( ipc_msg, process_agent_pb2.api_rsp) or not ipc_msg.IsInitialized(): self.logger.error('Invalid IPC message provided.') return False try: self.api_transport.sock.send(ipc_msg.SerializeToString(), flags=zmq.NOBLOCK) except Exception: # as e: self.logger.error( "Got error when send register response message: {}".format( ipc_msg)) def send_cli_rsp(self, rsp_msg): """Send cli response message via cli sock. :param rsp_msg: message information """ try: self.cli_transport.sock.send(rsp_msg.SerializeToString(), flags=zmq.NOBLOCK) except Exception: # as e: self.logger.error( "Got error when send CLI response message: {}".format(rsp_msg)) def start(self): """The start function will make the process into a endless loop. :return: Never return """ self.dispatcher.loop() def register_poll_timer(self, timeout, callback, args=None): """Register a timer to dispatcher. :param timeout: the timeout value, the unit is second :param callback: Call back function, the format is {"function": func, "args": args} :return: """ self.logger.info("Register a timer into dispatcher, timeout:%d" % timeout) return self.dispatcher.timer_register( timeout, callback, arg=args, timer_type=DpTimerManager.TIMER_REPEATED) def unregister_poll_timer(self, timer): """Unregister a timer. :param timer: a timer returned by register_poll_timer. :return: """ self.dispatcher.timer_unregister(timer) def register_transport(self, transport, callback, arg=None): """Register transport to dispatcher, the dispatcher will call the function when some events happens, currently, we will the use the PULLIN event. :param transport: one transport class, represents a socket, with a fileno. :param callback: the callback function, which will called when we received sth. :param arg: the args we passed into callback :return: None """ if not isinstance(transport, Transport): self.logger.error( "Cannot register the transport, parameter transport type is not correct, expect: " "Transport, real:%s" % type(transport)) return False self.logger.info("Register a transport into dispatcher, path=%s" % transport.path) self.dispatcher.fd_register(transport.sock, Dispatcher.EV_FD_IN | Dispatcher.EV_FD_ERR, callback) def unregister_transport(self, transport): """Remove the transport from the dispatcher. :param transport: one transport class, represents a socket, with a fileno. :return: None """ if not isinstance(transport, Transport): self.logger.error( "Cannot unregister the transport, parameter transport type is not correct, expect: " "Transport, real:%s" % type(transport)) return False self.logger.info("UnRegister a transport into dispatcher, path=%s" % transport.path) self.dispatcher.fd_unregister(transport.fileno) def start_process(self, args): """ :param args: The args includes the command, and the it should be a tuple or a list. :return: popen process class """ try: popenObj = subprocess.Popen(args, cwd="/tmp/") return popenObj except Exception as e: self.logger.error(str(e)) return None def terminate_process(self, popenObj): """Terminate a process. :param popenObj: this is a obj returned by the start process :return: True for execute cmd successfully, false for arg error """ if not isinstance(popenObj, subprocess.Popen): self.logger.warn( "Cannot terminate a process since the arg is %s, not Popen object.", type(popenObj)) return False self.logger.info("Terminate process %d", popenObj.pid) popenObj.terminate() return True def kill_process(self, popenObj): """kill a process. :param popenObj: this is a obj returned by the start process :return: True for execute cmd successfully, false for arg error """ if not isinstance(popenObj, subprocess.Popen): self.logger.warn( "Cannot kill a process since the arg is %s, not Popen object.", type(popenObj)) return False self.logger.info("kill process %d", popenObj.pid) popenObj.kill() return True def check_process_status(self, popenObj): """Check the status of the process. :param popenObj: this is a obj returned by the start process :return: Terminated/Alive """ if not isinstance(popenObj, subprocess.Popen): self.logger.warn( "Cannot terminate a process since the arg is %s, not Popen object.", type(popenObj)) return False, -1 popenObj.poll() retcode = popenObj.returncode if retcode is None: return self.PROCESSSTATE_ALIVE return self.PROCESSSTATE_DEAD def set_logging_level(self, level): """Set module logger level for system logging. :param level: """ try: self.logger.setLevel(level) return True, 'success' except (ValueError, TypeError) as e: return False, str(e) def cleanup_db(self, ccap_core_id): """cleanup the remain requester if exist.""" raise NotImplementedError()
def test_fd_reg(self): d = Dispatcher() d.fd_register(0, Dispatcher.EV_FD_ALL, None) d.fd_modify(0, 0) d.fd_unregister(0) del d
class HalPtpDriver(HalDriverClient): """The Driver Client for Hal.""" SYNC = "ALIGNED" LOS = "LOSS OF SYNC" __metaclass__ = AddLoggerToClass def __init__(self, drvName, drvDesc, drvVer, supportedMsgType, supportedNotificationMsgs, logConfigurePath=None): """Init. :param drvName: The driver name, such as BCM3160 Driver :param drvDesc: A brief description about this driver, such as the driver main functionality description :param drvVer: Driver specific version, such as 1.0.1 :param supportedMsgType: a tuple or list for the driver supported msg types, the form will be (1, 2, 456, 10) :param supportedNotificationMsgs: the driver supported notification msg types the form will be (1, 3, 4) :return: HalDriverClient object """ super(HalPtpDriver, self).__init__(drvName, drvDesc, drvVer, supportedMsgType, supportedNotificationMsgs, logConfigurePath) # update the supported messages self.HalMsgsHandler = { "HalClientRegisterRsp": self.recvRegisterMsgCb, "HalClientHelloRsp": self.recvHelloRspMsgCb, "HalConfig": self.recvCfgMsgCb, } self.HalConfigMsgHandlers = { MsgTypePtpStatusGet: self.ptp_status_get, MsgTypeRdtiConfig: self.config_rdti, } self.ptpStatus = self.LOS self.ptpNewStatus = self.LOS self.dispatcher = Dispatcher() def start(self, simulate_mode=False): """Start polling the transport socket. :return: """ self.logger.info("Start the driver client poll...") self.connectionSetup() self.logger.info("Connection setup done...") self.logger.info("Begin register...") self.register(self.drvID) self.logger.info("End of register...") self.dispatcher.loop() def ptpdrv_hal_cb(self, sock, mask): self.logger.debug("Receive prp drv event") if self.pushSock is not None and sock == self.pushSock.monitor: self.pushSock.monitorHandler(recv_monitor_message(sock)) return if self.pullSock is not None and sock == self.pullSock.monitor: self.pullSock.monitorHandler(recv_monitor_message(sock)) return if sock == self.mgrConnection.monitor: self.mgrConnection.monitorHandler(recv_monitor_message(sock)) return while sock.getsockopt(zmq.EVENTS) and zmq.POLLIN: try: bin = sock.recv(flags=zmq.NOBLOCK) msg = HalMessage.DeSerialize(bin) self.logger.debug("Got a zmq msg:%s type:%s" % (msg.msg, msg.type)) if msg.type in self.HalMsgsHandler: handler = self.HalMsgsHandler[msg.type] handler(msg) except zmq.ZMQError as e: self.logger.debug( "Got an error when trying with nonblock read:" + str(e)) break except Exception as e: self.logger.warning("Got an un-expected error:%s", str(e)) break def register(self, DriverID): """Send a register message to Hal and get the client ID from the Hal. :return: """ if DriverID is None: registerMsg = HalMessage( "HalClientRegister", ClientName=self.drvname, ClientDescription=self.drvDesc, ClientVersion=self.drvVer, ClientSupportedMessages=self.supportedMsgType, ClientSupportedNotificationMessages=self. supportedNotificationMsgs) else: registerMsg = HalMessage( "HalClientRegister", ClientName=self.drvname, ClientDescription=self.drvDesc, ClientVersion=self.drvVer, ClientSupportedMessages=self.supportedMsgType, ClientSupportedNotificationMessages=self. supportedNotificationMsgs, ClientID=DriverID) if self.mgrConnection is None: errMsg = "Cannot send the register since the mgr connection is not setup" self.logger.error(errMsg) raise HalDriverClientError(errMsg) self.logger.debug("Send the register msg to Hal...") self.mgrConnection.send(registerMsg.Serialize()) def recvRegisterMsgCb(self, cfg): """The callback handler for the configuration message. :param cfg: the configuration message received frm the Hal :return: """ self.logger.debug("Recv a register rsp Message from the Hal: %s" % cfg.msg) if cfg.msg.Rsp.Status != HalCommon_pb2.SUCCESS: self.logger.error("Cannot register to Hal, reason[%s]", cfg.msg.Rsp.ErrorDescription) return self.drvID = cfg.msg.ClientID # Setup the push and pull connection self.pullPath = cfg.msg.PathFromHalToClient self.pushPath = cfg.msg.PathFromClientToHal # get the index of the path index = self._getIndexFromPath() if index == -1: self.logger.error("Cannot get index from the path [%s]" % self.pushPath) return if self.index == -1: self.index = index self.pushSock = HalTransport( HalTransport.HalTransportClientAgentPull, HalTransport.HalClientMode, index=index, socketMode=HalTransport.HalSocketPushMode, disconnectHandlerCb=self.connectionDisconnectCb) self.pullSock = HalTransport( HalTransport.HalTransportClientAgentPush, HalTransport.HalClientMode, index=index, socketMode=HalTransport.HalSocketPullMode, disconnectHandlerCb=self.connectionDisconnectCb) # register to the poller self.dispatcher.fd_register(self.pullSock.socket, zmq.POLLIN, self.ptpdrv_hal_cb) self.dispatcher.fd_register(self.pushSock.monitor, zmq.POLLIN, self.ptpdrv_hal_cb) self.dispatcher.fd_register(self.pullSock.monitor, zmq.POLLIN, self.ptpdrv_hal_cb) # send Hello To Hal self.sayHelloToHal() if self.interestedNotification is not None: self.sendInterestedNotifications(self.interestedNotification) self.disconnected = False return def connectionSetup(self): """Create the connection to the mgr and setup the poller. :return: """ self.logger.info("Create the connection to the mgr....") # Create a connection to Hal driver mgr # Create a connection to Hal driver mgr self.mgrConnection = HalTransport( HalTransport.HalTransportClientMgr, HalTransport.HalClientMode, disconnectHandlerCb=self.connectionDisconnectCb) self.mgrConnection.connects() self.HalMsgsHandler[self.mgrConnection.socket] = self.recvRegisterMsgCb self.HalMsgsHandler[self.mgrConnection.socket] = self.recvRegisterMsgCb # register the mgr socket self.dispatcher.fd_register(self.mgrConnection.socket, zmq.POLLIN, self.ptpdrv_hal_cb) self.dispatcher.fd_register(self.mgrConnection.monitor, zmq.POLLIN, self.ptpdrv_hal_cb) def connection_cleanup(self): """Close the connection to the mgr. :return: """ if self.disconnected: self.logger.debug("A previous event has been processed, skip it!") return if self.mgrConnection is not None: self.dispatcher.fd_unregister(self.mgrConnection.socket) self.dispatcher.fd_unregister(self.mgrConnection.monitor) self.mgrConnection.socket.disable_monitor() self.mgrConnection.monitor.close() self.mgrConnection.socket.close() if self.pullSock is not None: self.dispatcher.fd_unregister(self.pullSock.socket) self.dispatcher.fd_unregister(self.pullSock.monitor) self.pullSock.socket.disable_monitor() self.pullSock.monitor.close() self.pullSock.socket.close() if self.pushSock is not None: self.dispatcher.fd_unregister(self.pushSock.monitor) self.pushSock.socket.disable_monitor() self.pushSock.monitor.close() self.pushSock.socket.close() self.disconnected = True def connectionDisconnectCb(self, msg): """TODO: confusing comment here. Need clarification. The connection has been detected disconnected , register it again We have reconenct, we have to assure the regiter message is received by the HAL :param msg: :return: """ if self.disconnected: self.logger.info("A previous event has been processed, skip it!") return self.logger.info("Detected disconnected, register again") # clean up the push and pull socket # self.poller.unregister(self.pullSock.socket) self.dispatcher.fd_unregister(self.mgrConnection.socket) self.dispatcher.fd_unregister(self.mgrConnection.monitor) self.mgrConnection.monitor.close() self.mgrConnection.close() # re-register the message self.connectionSetup() self.register(self.drvID) # The zmq lower part will handle the reconnect self.disconnected = True def recvHelloRspMsgCb(self, hello): """Call back for Hello Message. :param hello: :return: """ self.logger.debug("Recv a hello message") def recvCfgMsgCb(self, cfg): """Receive a configuration message from the Hal, processing it. :param cfg: :return: """ try: handler = self.HalConfigMsgHandlers[cfg.msg.CfgMsgType] handler(cfg) except Exception as e: self.logger.error("Got an error:%s, the cfg msg:%s", str(e), cfg.msg) def ptp_status_get(self, cfg): cfg.msg.CfgMsgPayload = self.SYNC self.sendCfgRspMsg(cfg) def config_rdti(self, cfg): rdti_config_data = t_RcpMessage() rdti_config_data.ParseFromString(cfg.msg.CfgMsgPayload) rdti_config_data.RcpDataResult = t_RcpMessage.RCP_RESULT_OK cfg.msg.CfgMsgPayload = rdti_config_data.SerializeToString() self.logger.debug("Recv ptp configuration message, %s" % rdti_config_data) self.sendCfgRspMsg(cfg) def sendCfgRspMsg(self, cfg, rsp=None): """The configuration response routine, the driver implementor should fill sth into this function. :param cfg: The original configuration message :return: """ cfgMsg = cfg.msg rsp = {"Status": HalCommon_pb2.SUCCESS, "ErrorDescription": ""} msg = HalMessage("HalConfigRsp", SrcClientID=cfgMsg.SrcClientID, SeqNum=cfgMsg.SeqNum, Rsp=rsp, CfgMsgType=cfgMsg.CfgMsgType, CfgMsgPayload=cfgMsg.CfgMsgPayload) self.pushSock.send(msg.Serialize())