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 ProvMgrHalDriver(HalDriverClient): __metaclass__ = AddLoggerToClass ntfmsg_list = [ MsgTypeRpdCapabilities, ] cfgmsg_list = [ MsgTypeCcapCoreIdentification, MsgTypeRedundantCoreIpAddress, MsgTypeRpdCtrl, ] def __init__(self, drvName, drvDesc, drvVer, supportedMsgType, supportedNotificationMsgs, interestedNotification, dispatcher, logConfigurePath=None, mgr=None): """ :param drvName: :param drvDesc: :param drvVer: :param supportedMsgType: :param supportedNotificationMsgs: :param dispatcher: :param logConfigurePath: :param mgr: """ super(ProvMgrHalDriver, self).__init__(drvName, drvDesc, drvVer, supportedMsgType, supportedNotificationMsgs, interestedNotification) self.mgr = mgr self.rpd_cap = None self.dispatcher = dispatcher self.HalConfigMsgHandlers = { MsgTypeCcapCoreIdentification: self.recvCcapCoreIdentification, MsgTypeRedundantCoreIpAddress: self.recvRedundantCoreIpAddress, MsgTypeRpdCtrl: self.recvRpdResetCtrl, } self.HalNtfHandlers = { MsgTypeRpdCapabilities: self.recvRpdCapabilities, } self.HalConfigMsgRspHandlers = { MsgTypeRpdCapabilities: self.recMsgTypeRpdCapabilitiesRspCb, } RESET_CTRL_FILENAME = '/rpd/config/reset_ctrl' def recvRegisterMsgCb(self, cfg): # 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 to the poller self.dispatcher.fd_register(self.pullSock.socket, zmq.POLLIN, self.provmgr_cb) self.dispatcher.fd_register(self.pushSock.monitor, zmq.POLLIN, self.provmgr_cb) self.dispatcher.fd_register(self.pullSock.monitor, zmq.POLLIN, self.provmgr_cb) # send Hello To Hal self.sayHelloToHal() if self.interestedNotification is not None: self.sendInterestedNotifications(self.interestedNotification) self.disconnected = False return 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 :param rsp: respond :return: """ cfgMsg = cfg.msg msg = HalMessage("HalConfigRsp", SrcClientID=cfgMsg.SrcClientID, SeqNum=cfgMsg.SeqNum, Rsp=rsp, CfgMsgType=cfgMsg.CfgMsgType, CfgMsgPayload=cfgMsg.CfgMsgPayload) self.send(msg.Serialize()) def recvCfgMsgCb(self, cfgMsg): """Receive a configuration message from the Hal, processing it. :param cfgMsg: :return: """ try: msgType = cfgMsg.msg.CfgMsgType if msgType not in self.HalConfigMsgHandlers \ or self.HalConfigMsgHandlers[msgType] is None: rsp = { "Status": HalCommon_pb2.NOTSUPPORTED, "ErrorDescription": "msgType %d is not supported" % msgType } else: rsp = self.HalConfigMsgHandlers[msgType](cfgMsg.msg) except Exception as e: # pragma: no cover self.logger.error("Got an error:%s, the cfg msg:%s", str(e), cfgMsg.msg) rsp = { "Status": HalCommon_pb2.FAILED, "ErrorDescription": "Process configuration failed, reason:%s" % str(e) } self.sendCfgRspMsg(cfgMsg, rsp) def recvCfgMsgRspCb(self, cfg): """Receive a configuration response message from the Hal, processing it. :param cfg: :return: """ self.logger.debug("Recv a configuration response message:" + str(cfg.msg.CfgMsgType)) if cfg.msg.CfgMsgType in self.HalConfigMsgRspHandlers: cb = self.HalConfigMsgRspHandlers[cfg.msg.CfgMsgType] cb(cfg) def sendNotificationMsg(self, notificationType, notificationPayload): """Send a notification to Hal. :param notificationType: The notification type, the client must declare the notification type to Hal first :param notificationPayload: the string payload, Hal will not touch this part :return: """ self.logger.debug("send a a notification message to Hal") if self.disconnected: self.logger.warning( "The client is on disconnected state," " skip to send the message, notification type:%s", notificationType) return if notificationType is None or not isinstance(notificationPayload, str): self.logger.warning("Cannot send a None or incorrect type to HAL, " "str is required for msg.") return notification = HalMessage("HalNotification", ClientID=self.drvID, HalNotificationType=notificationType, HalNotificationPayLoad=notificationPayload) self.send(notification.Serialize()) def recvNotificationCb(self, ntf): """Receive a notification message from the HAL. :param ntf: :return: """ self.logger.info("Receive a interest notification message:" + str(ntf.msg)) self.recvNtf += 1 try: msgType = ntf.msg.HalNotificationType if msgType in self.HalNtfHandlers: self.HalNtfHandlers[msgType](ntf.msg.HalNotificationPayLoad) else: self.logger.debug( "Receive a interest notification message: no handler for %s", str(msgType)) except Exception as e: self.logger.error("Got an error:%s, the ntf msg:%s", str(e), str(msgType)) def recvHelloRspMsgCb(self, hello): """Call back for Hello Message. :param hello: :return: """ self.logger.debug("Recv a hello message") self.sendRpdCapReq() def connectionSetup(self, dispatcher): """Create the connection to the mgr and setup the poller. :return: """ self.logger.debug("Create the connection to the mgr....") # Create a connection to Hal driver mgr self.mgrConnection = HalTransport( HalTransport.HalTransportClientMgr, HalTransport.HalClientMode, disconnectHandlerCb=self.connectionDisconnectCb) # create the poller if self.poller is None: self.poller = dispatcher.get_poll() # register the mgr socket dispatcher.fd_register(self.mgrConnection.socket, zmq.POLLIN, self.provmgr_cb) dispatcher.fd_register(self.mgrConnection.monitor, zmq.POLLIN, self.provmgr_cb) def connectionDisconnectCb(self, msg): """The connection has been detected disconnected , register it again. :param msg: :return: """ if self.disconnected: self.logger.debug("A previous event has been processed, skip it!") return self.logger.debug("Detected disconnected, register again") self.poller.unregister(self.mgrConnection.socket) self.poller.unregister(self.mgrConnection.monitor) self.mgrConnection.socket.disable_monitor() self.mgrConnection.monitor.close() self.mgrConnection.close() # re-register the message self.connectionSetup(self.dispatcher) self.register(self.drvID) # The zmq lower part will handle the reconnect self.disconnected = True def start(self): """start poll the transport socket. :return: """ self.logger.debug("Start the driver poll...") try: self.connectionSetup(self.dispatcher) self.register(self.drvID) except Exception as e: self.logger.warn("ProvMgr hal client start fail exception %s", str(e)) def provmgr_cb(self, sock, mask): 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 self.mgrConnection is not None and 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) 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 non-block read:" + str(e)) break except Exception as e: self.logger.warn( "Exception happens when provmgr hal recv socket, reason:%s" % str(e)) break def DeSerializeConfigMsgPayload(self, cfgMsg): if cfgMsg.CfgMsgPayload is None: return None cfgMsgPayload = t_RcpMessage() cfgMsgPayload.ParseFromString(cfgMsg.CfgMsgPayload) return cfgMsgPayload def recvCcapCoreIdentification(self, cfgMsg): rcp_msg = self.DeSerializeConfigMsgPayload(cfgMsg) if rcp_msg is None: return { "Status": HalCommon_pb2.FAILED, "ErrorDescription": "DeSerialize ConfigMsgPayload fail" } self.logger.debug( "ProvMgr driver receive Config CcapCoreIdentification %s" % str(rcp_msg)) if rcp_msg.RpdDataMessage.RpdDataOperation == t_RpdDataMessage.RPD_CFG_READ: rcp_msg.RcpDataResult = t_RcpMessage.RCP_RESULT_OK del rcp_msg.RpdDataMessage.RpdData.CcapCoreIdentification[0] for key in CcapCoreIdentification.get_keys(): ccapCoreIdent = rcp_msg.RpdDataMessage.RpdData.CcapCoreIdentification.add( ) ccapCore = CcapCoreIdentification(key) ccapCore.read() ccapCoreIdent.Index = key ccapCoreIdent.CoreId = ccapCore.core_id ccapCoreIdent.CoreIpAddress = ccapCore.core_ip_addr ccapCoreIdent.IsPrincipal = ccapCore.is_principal ccapCoreIdent.CoreName = ccapCore.core_name ccapCoreIdent.VendorId = ccapCore.vendor_id ccapCoreIdent.InitialConfigurationComplete = ccapCore.initial_configuration_complete ccapCoreIdent.MoveToOperational = ccapCore.move_to_operational ccapCoreIdent.CoreFunction = ccapCore.core_function ccapCoreIdent.ResourceSetIndex = ccapCore.resource_set_index ccapCoreIdent.CoreMode = ccapCore.core_mode self.logger.debug("ProvMgr driver rsp ccapCoreIdent tlv %s" % ccapCoreIdent) cfgMsg.CfgMsgPayload = rcp_msg.SerializeToString() rsp = { "Status": HalCommon_pb2.SUCCESS, "ErrorDescription": "Serialize ConfigMsgPayload success" } return rsp if rcp_msg.RpdDataMessage.RpdDataOperation == t_RpdDataMessage.RPD_CFG_WRITE or \ rcp_msg.RpdDataMessage.RpdDataOperation == t_RpdDataMessage.RPD_CFG_ALLOCATE_WRITE: rsp = { "Status": HalCommon_pb2.SUCCESS_IGNORE_RESULT, "ErrorDescription": "manager hal ignore write and allocate write for ccapCoreIdentification" } return rsp def recvRedundantCoreIpAddress(self, cfgMsg): rcp_msg = self.DeSerializeConfigMsgPayload(cfgMsg) self.logger.info("ProvMgr driver receive RedundantCoreIpAddress %s" % str(rcp_msg)) rsp = {"Status": HalCommon_pb2.SUCCESS, "ErrorDescription": "success"} return rsp def recvRpdResetCtrl(self, cfgMsg): rcp_msg = self.DeSerializeConfigMsgPayload(cfgMsg) if rcp_msg is None: return { "Status": HalCommon_pb2.FAILED, "ErrorDescription": "DeSerialize ConfigMsgPayload fail" } self.logger.debug("\nProvMgr receive RpdResetCtrl:" + str(rcp_msg)) operation = rcp_msg.RpdDataMessage.RpdDataOperation recv_rcp_msg = rcp_msg.RpdDataMessage.RpdData if recv_rcp_msg.HasField("RpdCtrl") and recv_rcp_msg.RpdCtrl.HasField( "ResetCtrl"): if operation not in [ t_RpdDataMessage.RPD_CFG_WRITE, t_RpdDataMessage.RPD_CFG_READ ]: return { "Status": HalCommon_pb2.FAILED, "ErrorDescription": "Operation %d for RpdResetCtrl is not supported" % operation } rcp_rpd_resetctrl = recv_rcp_msg.RpdCtrl.ResetCtrl if operation == t_RpdDataMessage.RPD_CFG_WRITE: reset = rcp_rpd_resetctrl.Reset reset_type = rcp_tlv_def.RESET_TYPE[reset] with open(self.RESET_CTRL_FILENAME, 'w') as f: f.write(str(reset) + ":" + str(reset_type) + "\n") for ccap_core in CCAPCore.ccap_core_db.values(): ccap_core.del_ccap_core() SysTools.reboot(reset_type) if operation == t_RpdDataMessage.RPD_CFG_READ: try: with open(self.RESET_CTRL_FILENAME, 'r') as fr: reset_rd = fr.read() rcp_rpd_resetctrl.Reset = int(reset_rd.strip(":")[0]) except IOError: # file don't exist,skip check pass cfgMsg.CfgMsgPayload = rcp_msg.SerializeToString() return { "Status": HalCommon_pb2.SUCCESS, "ErrorDescription": "ProMgr handle RpdResetCtrl success for %d" % operation } else: return { "Status": HalCommon_pb2.SUCCESS_IGNORE_RESULT, "ErrorDescription": "ProvMgr Do not Have RpdCtrl Filed." } def valid_rpd_cap(self, rcp_rpd_cap): # check the instance if not isinstance(rcp_rpd_cap, t_RpdCapabilities): return False # check it is not the default value default_cap = t_RpdCapabilities() GCPObject.default_gpb(default_cap) if rcp_rpd_cap == default_cap: return False return True def recMsgTypeRpdCapabilitiesRspCb(self, halrspmsg): try: # Check the status if halrspmsg.msg.Rsp.Status != HalCommon_pb2.SUCCESS: # yes, we recv a error message from HAL self.logger.warning("Receive a hal fail message:%s" % halrspmsg.msg) return False cfg_rsp = t_RcpMessage() cfg_rsp.ParseFromString(halrspmsg.msg.CfgMsgPayload) if cfg_rsp.RcpDataResult != t_RcpMessage.RCP_RESULT_OK: # yes we recv a error msg from driver self.logger.warning("Recv a driver fail message:%s" % str(cfg_rsp)) return False rcp_rpd_cap = cfg_rsp.RpdDataMessage.RpdData.RpdCapabilities if not self.valid_rpd_cap(rcp_rpd_cap): self.logger.debug( "Receive invalid RpdCapabilities rsp from driver") return False if not self.rpd_cap: self.rpd_cap = t_RpdCapabilities() self.rpd_cap.CopyFrom(rcp_rpd_cap) self.logger.debug("Receive RpdCapabilities rsp from driver") return True except Exception as e: self.logger.warning("cap fail %s", str(e)) return False def recvRpdCapabilities(self, ntfMsg): rpd_cap = t_RpdCapabilities() rpd_cap.ParseFromString(ntfMsg) if not self.valid_rpd_cap(rpd_cap): self.logger.warning( "ProvMgr receive invalid rpdCapabilities notification from driver" ) return self.rpd_cap = rpd_cap self.logger.debug("Receive rpdCapabilities notification: %s", str(self.rpd_cap)) return def sendRpdCapReq(self): try: if self.rpd_cap: self.logger.debug( "Already has Rpd cap in store, no need to send req") return True rcp_msg = t_RcpMessage() rcp_msg.RcpDataResult = t_RcpMessage.RCP_RESULT_OK rcp_msg.RcpMessageType = t_RcpMessage.RPD_CONFIGURATION rpd_data_msg = t_RpdDataMessage() rpd_data_msg.RpdDataOperation = t_RpdDataMessage.RPD_CFG_READ rcp_cfg = config() sub_tlv = rcp_cfg.RpdCapabilities GCPObject.default_gpb(gpb=sub_tlv) rpd_data_msg.RpdData.CopyFrom(rcp_cfg) rcp_msg.RpdDataMessage.CopyFrom(rpd_data_msg) cfgMsgContent = rcp_msg.SerializeToString() msg = HalMessage("HalConfig", SrcClientID=self.drvID, SeqNum=self.seqNum, CfgMsgType=MsgTypeRpdCapabilities, CfgMsgPayload=cfgMsgContent) self.send(msg.Serialize()) self.seqNum += 1 self.logger.debug("send RPD capabilities req to hal driver") return True except Exception as e: self.logger.warning("send RPD cap req failed :%s", str(e)) return False def sendOperationalStatusNtf(self, operational): """ :param operational: True or False to represent the current operational status :return: """ led_msg = t_LED() led_msg.setLed.ledType = led_msg.LED_TYPE_STATUS led_msg.setLed.color = led_msg.LED_COLOR_GREEN if operational: led_msg.setLed.action = led_msg.LED_ACTION_LIT else: led_msg.setLed.action = led_msg.LED_ACTION_DARK self.logger.debug("Set led notification message: %s", led_msg) self.sendNotificationMsg(MsgTypeSetLed, led_msg.SerializeToString())
def test_eventHandlerMonitor(self): """test HalTransport#monitorHandler, check whether the EVENT_DISCONNECTED can be handle, if status is false case fail check whether the EVENT_CONNECT_RETRIED can be handle, if status before the timeout/after timeout was wrong, case fail check whether the EVENT_CLOSED can be handle, if status before the timeout/after timeout was wrong, case fail check whether the unnormal event can be handle, if status was wrong case fail. :keyword:HalTransport#monitorHandler :exception:assertFalse(transport.monitorHandler(msg)), assertFalse(transport.monitorHandler(msg)), assertFalse(transport.monitorHandler(msg)), assertFalse(transport.monitorHandler(msg)) :parameter: :return: """ transport = HalTransport( HalTransport.HalTransportClientMgr, HalTransport.HalServerMode, disconnectHandlerCb=None) msg = { "event": zmq.EVENT_DISCONNECTED, } self.assertFalse(transport.monitorHandler(msg)) transport.socket.disable_monitor() transport.monitor.close() transport.close() transport = HalTransport( HalTransport.HalTransportClientMgr, HalTransport.HalServerMode, disconnectHandlerCb=self._disconnectCb) self.assertTrue(transport.monitorHandler(msg)) msg = { "event": zmq.EVENT_CONNECT_RETRIED, } self.assertFalse(transport.monitorHandler(msg)) time.sleep(transport.socketLogTimeout) self.assertTrue(transport.monitorHandler(msg)) transport.socket.disable_monitor() transport.monitor.close() transport.close() transport = HalTransport( HalTransport.HalTransportClientMgr, HalTransport.HalServerMode, disconnectHandlerCb=self._disconnectCb) msg = { "event": zmq.EVENT_CLOSED, } self.assertFalse(transport.monitorHandler(msg)) time.sleep(transport.socketLogTimeout) self.assertTrue(transport.monitorHandler(msg)) msg = { "event": 10001, } self.assertFalse(transport.monitorHandler(msg)) transport.socket.disable_monitor() transport.monitor.close() transport.close()
class FaultManagementClient(HalDriverClient): """ refactor the class for fault management """ __metaclass__ = AddLoggerToClass RESET_LOG = { "PENDING": 1, "LOCAL": 2, } EVENT_VER = '0.0.1' event_buffered_local_file = "/tmp/fault_local_%s.json" % EVENT_VER event_buffered_pending_file = "/tmp/fault_pending_%s.json" % EVENT_VER def __init__(self, appName, appDesc, appVer, disp, supportedMsgType, supportedNotificationMsgs, interestedNotification=None, send_cb=None): super(FaultManagementClient, self).__init__(appName, appDesc, appVer, supportedMsgType, supportedNotificationMsgs, interestedNotification) self.operational = False self.dispatcher = disp self.send_ntf = send_cb self.poll_local_flag = False self.poll_pending_flag = False self.config_refreshed = False self.HalConfigMsgHandlers = { MsgTypeRpdGlobal: self.set_global_conf, MsgTypetEventNotification: self.read_notification_handler, MsgTypeRpdCtrl: self.reset_rpd_log, } self.HalNotificationMsgHandler = { MsgTypeSetLed: self.set_operational_mode, } rpd_event_def.RpdEventConfig.init_config() def set_global_conf(self, cfg): """set event global configuration default value.""" config_data = t_RcpMessage() config_data.ParseFromString(cfg.msg.CfgMsgPayload) config = config_data.RpdDataMessage.RpdData self.logger.debug("Recv global event configuration message, %s" % config) rpd_event_def.RpdEventConfig.set_config(config) config_data.RcpDataResult = t_RcpMessage.RCP_RESULT_OK cfg.msg.CfgMsgPayload = config_data.SerializeToString() self.config_refreshed = True def read_notification_handler(self, cfg): """CCAP core pull operation.""" config_data = t_RcpMessage() config_data.ParseFromString(cfg.msg.CfgMsgPayload) config = config_data.RpdDataMessage.RpdData self.logger.debug("Recv read request message, %s" % config_data) # prepare the response rsp_data = t_RcpMessage() rsp_data.RcpMessageType = config_data.RcpMessageType rsp_data.RpdDataMessage.RpdDataOperation = config_data.RpdDataMessage.RpdDataOperation read_count = None if config.HasField("ReadCount"): read_count = config.ReadCount # go through all requests and create the appropriate response for notify_req in config.EventNotification: # according to the spec the PendingOrLocalLog TLV must be set if notify_req.HasField("PendingOrLocalLog"): if notify_req.PendingOrLocalLog: buffered = rpd_event_def.EventCommonOperation.BUFFERED_LOCAL else: buffered = rpd_event_def.EventCommonOperation.BUFFERED_PENDING idx = None if notify_req.HasField("RpdEvLogIndex"): idx = notify_req.RpdEvLogIndex if read_count is None: read_count = 1 else: idx = 0 evtNtfs = self.read_events(buffered, idx, read_count) if evtNtfs: for evt in evtNtfs: newEvt = rsp_data.RpdDataMessage.RpdData.EventNotification.add( ) newEvt.CopyFrom(evt) else: # no events found return an empty event notification with the # required fields set newEvt = rsp_data.RpdDataMessage.RpdData.EventNotification.add( ) newEvt.PendingOrLocalLog = notify_req.PendingOrLocalLog newEvt.RpdEvLogIndex = idx else: # return the request content # Note: The default value for EvFirstTime and EvLastTime # is automatically set to R_Dummy, which is wrong for that data # type - so set 1970-1-1T00:00:00.0+0:00 as value newEvt = rsp_data.RpdDataMessage.RpdData.EventNotification.add( ) newEvt.CopyFrom(notify_req) if newEvt.HasField( "EvFirstTime") and newEvt.EvFirstTime == 'R_Dummy': newEvt.EvFirstTime = utils.Convert.pack_timestamp_to_string( 0) if newEvt.HasField( "EvLastTime") and newEvt.EvLastTime == 'R_Dummy': newEvt.EvFirstTime = utils.Convert.pack_timestamp_to_string( 0) rsp_data.RcpDataResult = t_RcpMessage.RCP_RESULT_OK cfg.msg.CfgMsgPayload = rsp_data.SerializeToString() def read_events(self, buffered, idx, rdCnt): """ Read events from the pending queue or local log """ evtNtfList = [] evts = rpd_event_def.EventCommonOperation.read_log(buffered) # calculate the number of elements to read; # if the index is not set, then treat it as 0 numElements = len(evts) if rdCnt is None: rdCnt = numElements elif rdCnt > (numElements - idx): rdCnt = numElements - idx keys = evts.keys()[idx:(idx + rdCnt)] for entry in keys: event, msg = evts[entry] text = msg['text'] evtNtfEntry = t_EventNotification() evtNtfEntry.RpdEvLogIndex = idx idx += 1 evtNtfEntry.PendingOrLocalLog = msg['PENDING_LOCAL'] evtNtfEntry.EvFirstTime = utils.Convert.pack_timestamp_to_string( int(msg['FirstTime'])) evtNtfEntry.EvLastTime = utils.Convert.pack_timestamp_to_string( int(msg['LastTime'])) evtNtfEntry.EvCounts = msg['Counts'] evtNtfEntry.EvLevel = msg['Level'] evtNtfEntry.EvId = int(event) evtNtfEntry.EvString = text.strip() evtNtfList.append(evtNtfEntry) evts.pop(entry) if len(evts): rpd_event_def.EventCommonOperation.write_log(evts, buffered) return evtNtfList def clear_rpd_log(self, reset_log): if reset_log & self.RESET_LOG["PENDING"]: if os.path.exists(self.event_buffered_pending_file): os.remove(self.event_buffered_pending_file) if reset_log & self.RESET_LOG["LOCAL"]: if os.path.exists(self.event_buffered_local_file): os.remove(self.event_buffered_local_file) def reset_rpd_log(self, cfg): """reset rpd pending and local log.""" rcp_msg = t_RcpMessage() rcp_msg.ParseFromString(cfg.msg.CfgMsgPayload) if rcp_msg is None: return { "Status": HalCommon_pb2.FAILED, "ErrorDescription": "DeSerialize ConfigMsgPayload fail" } recv_rcp_msg = rcp_msg.RpdDataMessage.RpdData if recv_rcp_msg.HasField("RpdCtrl") and recv_rcp_msg.RpdCtrl.HasField( "LogCtrl"): if rcp_msg.RpdDataMessage.RpdDataOperation == t_RpdDataMessage.RPD_CFG_WRITE: ctrl_log = recv_rcp_msg.RpdCtrl.LogCtrl reset_log = ctrl_log.ResetLog self.clear_rpd_log(reset_log) rcp_msg.RcpDataResult = t_RcpMessage.RCP_RESULT_OK cfg.msg.CfgMsgPayload = rcp_msg.SerializeToString() return { "Status": HalCommon_pb2.SUCCESS, "ErrorDescription": "Get Rpd Control success" } elif rcp_msg.RpdDataMessage.RpdDataOperation == t_RpdDataMessage.RPD_CFG_READ: return { "Status": HalCommon_pb2.SUCCESS_IGNORE_RESULT, "ErrorDescription": "Operation %d for Rpd Log Control Can Be Ignored" % rcp_msg.RpdDataMessage.RpdDataOperation } else: return { "Status": HalCommon_pb2.FAILED, "ErrorDescription": "Operation %d for LogCtrl is not supported" % rcp_msg.RpdDataMessage.RpdDataOperation } else: return { "Status": HalCommon_pb2.SUCCESS_IGNORE_RESULT, "ErrorDescription": "Rcp Msg Do Not Have RpdCtrl Field" } def set_operational_mode(self, cfg): """use set led msg to figure system operational status.""" led_msg = t_LED() led_msg.ParseFromString(cfg) self.logger.debug("Set operational msg %s" % str(led_msg)) action = led_msg.setLed.action if action == led_msg.LED_ACTION_LIT and led_msg.setLed.ledType == led_msg.LED_TYPE_STATUS \ and not self.operational: self.operational = True elif action == led_msg.LED_ACTION_DARK and led_msg.setLed.ledType == led_msg.LED_TYPE_STATUS \ and self.operational: self.operational = False def process_notification_msg(self, cfg): """process notification msg.""" ntf_msg = cfg.msg msg_type = ntf_msg.HalNotificationType if msg_type not in self.HalNotificationMsgHandler or self.HalNotificationMsgHandler[ msg_type] is None: self.logger.error("msgType %d is not supported" % msg_type) return self.HalNotificationMsgHandler[msg_type]( ntf_msg.HalNotificationPayLoad) def start(self): """Connection setup. :return: """ self.logger.debug("Start the client setup...") self.connection_setup() self.register(self.drvID) def connection_setup(self): """Create the connection to the mgr and setup the poller. :return: """ self.logger.debug("Create the connection to the mgr....") # Create a connection to Hal driver mgr self.mgrConnection = HalTransport( HalTransport.HalTransportClientMgr, HalTransport.HalClientMode, disconnectHandlerCb=self.connectionDisconnectCb) # create the poller if self.poller is None: self.poller = self.dispatcher.get_poll() # register the mgr socket self.dispatcher.fd_register(self.mgrConnection.socket, self.dispatcher.EV_FD_IN, self.fault_management_cb) self.dispatcher.fd_register(self.mgrConnection.monitor, self.dispatcher.EV_FD_IN, self.fault_management_cb) def recvRegisterMsgCb(self, cfg): # pragma: no cover """The callback handler for the configuration message. :param cfg: the configuration message received frm 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 to the poller self.dispatcher.fd_register(self.pullSock.socket, zmq.POLLIN, self.fault_management_cb) self.dispatcher.fd_register(self.pushSock.monitor, zmq.POLLIN, self.fault_management_cb) self.dispatcher.fd_register(self.pullSock.monitor, zmq.POLLIN, self.fault_management_cb) # send Hello To Hal self.sayHelloToHal() if self.interestedNotification is not None: self.sendInterestedNotifications(self.interestedNotification) self.disconnected = False return def fault_management_cb(self, sock, mask): # pragma: no cover """Fault management callback. :param sock: zmq socket :param mask: event mask :return: """ 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 self.mgrConnection is not None and 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" % msg.msg) if msg.type in self.HalMsgsHandler: handler = self.HalMsgsHandler[msg.type] handler(msg) except zmq.ZMQError as e: self.logger.debug( "Getting an error when trying with nonblock read:" + str(e)) break except Exception as e: self.logger.error("Error happens, reason:%s" % str(e)) break 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) self.logger.debug( "Recv a configuration message, send the rsp to it") self.sendCfgRspMsg(cfg) except Exception as e: self.logger.error("Got an error:%s, the cfg msg:%s", str(e), cfg.msg) def recvNotificationCb(self, msg): """ Receive a configuration message from the Hal, processing it :param msg: :return: """ self.logger.debug("Recv a notification message\n%s", str(msg.msg)) self.process_notification_msg(msg)
class HalPtpClient(HalClient): """The PTP Client for Hal.""" SYNC = "ALIGNED" LOS = "LOSS OF SYNC" __metaclass__ = AddLoggerToClass def __init__(self, appName, appDesc, appVer, supportedNotification, supportedMsgsTypes, dispatcher, notifyCb, logConfigurePath=None): # sanity check the input args super(HalPtpClient, self).__init__(appName, appDesc, appVer, supportedNotification, logConfigurePath, supportedMsgsTypes) if not isinstance(supportedNotification, tuple) and not isinstance( supportedNotification, list): raise HalClientError( "supportedMsgsTypes should be a tuple or list") self.HalMsgsHandler = { "HalClientRegisterRsp": self.recvRegisterMsgCb, "HalSetLoggingLevelRsp": self.recvHalSetLoggingLevelRspCb, "HalClientHelloRsp": self.recvHelloRspMsgCb, "HalConfigRsp": self.recvCfgMsgRspCb, "HalClientInterestNotificationCfgRsp": self.sendInterestedNotificationsRspCb, "HalNotification": self.recvNotificationCb, "HalConfig": self.recvCfgMsgCb, } self.notifyHandler = notifyCb self.dispatcher = dispatcher self.supportedNotificationMsgs = list(supportedNotification) self.dispatcher.timer_register(1, self.checkPtpStatus, timer_type=1) self.ptp_result = t_GeneralNotification.PTPACQUIRE def checkPtpStatus(self, fd): self.sendCfgMsg(MsgTypePtpStatusGet, "GetPtpStatus") def start(self): """Start polling the transport socket.""" self.logger.debug("Start the client poll...") self.connectionSetup(self.dispatcher) self.register(self.clientID) def connectionSetup(self, disp=None): """Create the connection to the mgr and setup the poller.""" self.logger.debug("Create the connection to the mgr....") # Create a connection to Hal driver mgr self.mgrConnection = HalTransport( HalTransport.HalTransportClientMgr, HalTransport.HalClientMode, disconnectHandlerCb=self.connectionDisconnectCb) # register the mgr socket disp.fd_register(self.mgrConnection.socket, zmq.POLLIN, self.ptp_hal_cb) disp.fd_register(self.mgrConnection.monitor, zmq.POLLIN, self.ptp_hal_cb) def connectionDisconnectCb(self, msg): """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.debug("A previous event has been processed, skip it!") return self.logger.debug("Detected disconnected, register again") # clean up the push and pull socket if 1: self.pushSock.close() self.pullSock.close() self.dispatcher.fd_unregister(self.pullSock.socket) self.dispatcher.fd_unregister(self.pullSock.monitor) self.dispatcher.fd_unregister(self.pullSock.monitor) self.pushSock = None self.pullSock = None self.mgrConnection = None # self.clientID = None #will not set it to none since self.connectionSetup(self.dispatcher) 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 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.clientID = 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.ptp_hal_cb) self.dispatcher.fd_register(self.pushSock.monitor, zmq.POLLIN, self.ptp_hal_cb) self.dispatcher.fd_register(self.pullSock.monitor, zmq.POLLIN, self.ptp_hal_cb) # send Hello To Hal self.sayHelloToHal() self.sendInterestedNotifications(self.interestedNotification) self.disconnected = False return def recvCfgMsgCb(self, cfgMsg): """Receive a configuration message from the Hal, processing it. :param cfgMsg: :return: """ try: msgType = cfgMsg.msg.CfgMsgType if msgType == MsgTypeRpdState: self.getRpdPtpState(cfgMsg) except Exception as e: # pragma: no cover self.logger.error("Got an error:%s, the cfg msg:%s", str(e), cfgMsg) rsp = { "Status": HalCommon_pb2.FAILED, "ErrorDescription": "Process configuration failed, reason:%s" % str(e) } self.sendCfgRspMsg(cfgMsg, rsp) def recvCfgMsgRspCb(self, cfg): """Receive a configuration response message from the Hal, processing it. :param cfg: :return: """ self.logger.debug("Recv a ptp configuration response message:" + str(cfg.msg)) if cfg.msg.CfgMsgType == MsgTypePtpStatusGet: if cfg.msg.CfgMsgPayload in [self.LOS, self.SYNC]: self.notifyHandler(cfg.msg.CfgMsgPayload) self.logger.debug("send %s notification to provision", cfg.msg.CfgMsgPayload) def ptp_hal_cb(self, sock, mask): 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 self.mgrConnection is not None and 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" % msg.msg) if msg.type in self.HalMsgsHandler: handler = self.HalMsgsHandler[msg.type] handler(msg) except zmq.ZMQError as e: self.logger.debug( "Geting an error when trying with nonblock read:" + str(e)) break except Exception as e: self.logger.error("Error happens, reason:%s" % str(e)) break def recvNotificationCb(self, msg): """Receive the notification from ptp hal driver. :param msg: :return: """ self.logger.info("recv the notification from ptp driver") print msg.msg.HalNotificationType print msg.msg.HalNotificationPayLoad if msg.msg.HalNotificationType == MsgTypePtpClockStatus: if msg.msg.HalNotificationPayLoad in [self.LOS, self.SYNC]: self.notifyHandler(msg.msg.HalNotificationPayLoad) print "send %s notification to provision" % msg.msg.HalNotificationPayLoad def getRpdPtpState(self, cfg): rsp = t_RcpMessage() rsp.ParseFromString(cfg.msg.CfgMsgPayload) config = rsp.RpdDataMessage.RpdData try: config.RpdState.LocalPtpSyncStatus = \ True if self.ptp_result == t_GeneralNotification.PTPSYNCHRONIZED else False cfg.CfgMsgPayload = config.SerializeToString() rsp.RpdDataMessage.RpdData.CopyFrom(config) rsp.RcpDataResult = t_RcpMessage.RCP_RESULT_OK payload = rsp.SerializeToString() self.logger.info("Send rpd state LocalPtpSyncStatus response, %s" % rsp) msg = HalMessage("HalConfigRsp", SrcClientID=cfg.msg.SrcClientID, SeqNum=cfg.msg.SeqNum, Rsp={ "Status": HalCommon_pb2.SUCCESS, "ErrorDescription": "PTP LOCALPTPSYNCSTATUS query success" }, CfgMsgType=cfg.msg.CfgMsgType, CfgMsgPayload=payload) self.pushSock.send(msg.Serialize()) except Exception as e: self.logger.error("excpetipn:%s", str(e)) return
class RpdResHalClient(HalDriverClient): __metaclass__ = AddLoggerToClass def __init__(self, appName, appDesc, appVer, disp, supportedMsgType, supportedNotificationMsgs, interestedNotification=None, send_cb=None): super(RpdResHalClient, self).__init__(appName, appDesc, appVer, supportedMsgType, supportedNotificationMsgs, interestedNotification) self.operational = False self.dispatcher = disp self.HalConfigMsgHandlers = { MsgTypeHostResources: self.processHostCfgMsg, MsgTypeRpdCtrl: self.processRpdCtrlCfgMsg, } self.crashFileCtrlHandler = CrashFileCtrlHandler() self.hostResourceHandler = HostResourceHandler() def processRpdCtrlCfgMsg(self, cfgMsg): rcp_msg = t_RcpMessage() rcp_msg.ParseFromString(cfgMsg.msg.CfgMsgPayload) status = HalCommon_pb2.SUCCESS_IGNORE_RESULT recv_rcp_msg = rcp_msg.RpdDataMessage.RpdData if recv_rcp_msg.HasField("RpdCtrl"): rpdCtrl = recv_rcp_msg.RpdCtrl op = rcp_msg.RpdDataMessage.RpdDataOperation rcp_msg.RcpDataResult = t_RcpMessage.RCP_RESULT_OK flag = False if rpdCtrl.HasField("CrashDataServerCtrl"): status = HalCommon_pb2.SUCCESS self.logger.debug("Recv an RpdCtrlCfgMsg op %d, %s:" % (op, rpdCtrl)) if op == t_RpdDataMessage.RPD_CFG_WRITE: self.crashFileCtrlHandler.save_crash_data_server( rpdCtrl.CrashDataServerCtrl) flag = True if op == t_RpdDataMessage.RPD_CFG_READ: self.crashFileCtrlHandler.get_crash_data_server( rpdCtrl.CrashDataServerCtrl) flag = True if len(rpdCtrl.CrashDataFileCtrl ) > 0 and op == t_RpdDataMessage.RPD_CFG_WRITE: flag = True index = 0 for crashDataCtrl in rpdCtrl.CrashDataFileCtrl: if crashDataCtrl.HasField("Index"): index = crashDataCtrl.Index else: rcp_msg.RcpDataResult = t_RcpMessage.RCP_RESULT_GENERAL_ERROR if crashDataCtrl.HasField("FileControl"): fileControl = crashDataCtrl.FileControl if not self.crashFileCtrlHandler.update_pending_file_idx_list( index, fileControl): status = HalCommon_pb2.FAILED rcp_msg.RcpDataResult = t_RcpMessage.RCP_RESULT_GENERAL_ERROR if not flag: status = HalCommon_pb2.SUCCESS_IGNORE_RESULT else: status = HalCommon_pb2.SUCCESS elif rcp_msg.RpdDataMessage.RpdDataOperation == t_RpdDataMessage.RPD_CFG_READ: status = HalCommon_pb2.SUCCESS_IGNORE_RESULT else: status = HalCommon_pb2.FAILED payload = rcp_msg.SerializeToString() msg = HalMessage("HalConfigRsp", SrcClientID=cfgMsg.msg.SrcClientID, SeqNum=cfgMsg.msg.SeqNum, Rsp={ "Status": status, "ErrorDescription": "Get Rpd Control rsp" }, CfgMsgType=cfgMsg.msg.CfgMsgType, CfgMsgPayload=payload) return msg def processHostCfgMsg(self, cfgMsg): rsp = t_RcpMessage() # rsp.ParseFromString(cfgMsg.CfgMsgPayload) req = t_RcpMessage() req.ParseFromString(cfgMsg.msg.CfgMsgPayload) rsp.RpdDataMessage.RpdDataOperation = req.RpdDataMessage.RpdDataOperation rsp.RcpMessageType = req.RcpMessageType # load the rpd host resources information hr = rsp.RpdDataMessage.RpdData.HostResources hr.hrMemorySize = self.hostResourceHandler.getMemorySize() hr.hrProcessorLoad = self.hostResourceHandler.getProcessorLoad() self.hostResourceHandler.getStorages(hr.hrStorages) self.hostResourceHandler.getProcesses(hr.hrProcesses) rsp.RcpDataResult = t_RcpMessage.RCP_RESULT_OK payload = rsp.SerializeToString() msg = HalMessage("HalConfigRsp", SrcClientID=cfgMsg.msg.SrcClientID, SeqNum=cfgMsg.msg.SeqNum, Rsp={ "Status": HalCommon_pb2.SUCCESS, "ErrorDescription": "Host Resource" }, CfgMsgType=cfgMsg.msg.CfgMsgType, CfgMsgPayload=payload) return msg def start(self): """Connection setup. :return: """ self.logger.debug("Start the client setup...") self.connection_setup() self.register(self.drvID) def connection_setup(self): """Create the connection to the mgr and setup the poller. :return: """ self.logger.debug("Create the connection to the mgr....") # Create a connection to Hal driver mgr self.mgrConnection = HalTransport( HalTransport.HalTransportClientMgr, HalTransport.HalClientMode, disconnectHandlerCb=self.connectionDisconnectCb) # create the poller if self.poller is None: self.poller = self.dispatcher.get_poll() # register the mgr socket self.dispatcher.fd_register(self.mgrConnection.socket, self.dispatcher.EV_FD_IN, self.host_management_cb) self.dispatcher.fd_register(self.mgrConnection.monitor, self.dispatcher.EV_FD_IN, self.host_management_cb) def recvRegisterMsgCb(self, cfg): """The callback handler for the configuration message. :param cfg: the configuration message received frm the Hal :return: """ 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 self.pullPath = cfg.msg.PathFromHalToClient self.pushPath = cfg.msg.PathFromClientToHal 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.host_management_cb) self.dispatcher.fd_register(self.pushSock.monitor, zmq.POLLIN, self.host_management_cb) self.dispatcher.fd_register(self.pullSock.monitor, zmq.POLLIN, self.host_management_cb) # send Hello To Hal self.sayHelloToHal() if self.interestedNotification is not None: self.sendInterestedNotifications(self.interestedNotification) self.disconnected = False return def host_management_cb(self, sock, mask): """ :param sock: zmq socket :param mask: event mask :return: """ 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 self.mgrConnection is not None and sock == self.mgrConnection.monitor: self.mgrConnection.monitorHandler(recv_monitor_message(sock)) return while sock.getsockopt(zmq.EVENTS) and zmq.POLLIN: if not self.hal_message_cb(sock): break def hal_message_cb(self, sock): try: bin = sock.recv(flags=zmq.NOBLOCK) msg = HalMessage.DeSerialize(bin) self.logger.debug("###########Got a zmq msg:%s" % msg.msg) if msg.type in self.HalMsgsHandler: handler = self.HalMsgsHandler[msg.type] handler(msg) except zmq.ZMQError as e: self.logger.debug( "Getting an error when trying with nonblock read:" + str(e)) return False except Exception as e: self.logger.error("Error happens, reason:%s" % str(e)) return False return True def recvCfgMsgCb(self, cfg): """Receive a configuration message from the Hal, processing it. :param cfg: :return: """ try: handler = self.HalConfigMsgHandlers[cfg.msg.CfgMsgType] msg = handler(cfg) if self.pushSock: self.pushSock.send(msg.Serialize()) self.logger.debug( "Recv a configuration message, send the rsp to it") except Exception as e: self.logger.error("Got an error:%s, the cfg msg:%s", str(e), cfg.msg)