Fix bad GNSS status reported by PTP tracker

A "FAILURE-NOFIX" GNSS status was being reported because the new ICE
driver reports "locked_ho_acq" status instead of "locked_ho_ack" as
before. Now the logic takes both variations into account to decide upon
the GNSS status.

BONUS: Found an issue (bad indentation with subsequent logic error) with
the threading lockers for ptp4l and ts2phc handlers in the sidecar
(notificationclient), that could lead to an exception.

Test Plan:
PASS: Checked with synchronized GNSS status.

Closes-Bug: #1996179
Signed-off-by: Douglas Henrique Koerich <douglashenrique.koerich@windriver.com>
Change-Id: I1ad3c4c9ad9e1428685bf6729c77ba29b470ece3
This commit is contained in:
Douglas Henrique Koerich 2022-11-10 11:26:14 -03:00
parent db31ab00ba
commit 3a365e737a
3 changed files with 265 additions and 201 deletions

View File

@ -32,6 +32,7 @@ CLOCK_CLASS_VALUE6 = "6"
NMEA_SERIALPORT = "ts2phc.nmea_serialport"
GNSS_PIN = "GNSS-1PPS"
GNSS_LOCKED_HO_ACK = 'locked_ho_ack'
GNSS_LOCKED_HO_ACQ = 'locked_ho_acq'
GNSS_DPLL_0 = "DPLL0"
GNSS_DPLL_1 = "DPLL1"

View File

@ -68,11 +68,15 @@ class GnssMonitor(Observer):
}
# Initialize status
if self.gnss_cgu_handler.cgu_output_parsed['EEC DPLL']['Current reference'] == 'GNSS-1PPS':
self.gnss_eec_state = self.gnss_cgu_handler.cgu_output_parsed['EEC DPLL']['Status']
if self.gnss_cgu_handler.cgu_output_parsed[
'EEC DPLL']['Current reference'] == 'GNSS-1PPS':
self.gnss_eec_state = \
self.gnss_cgu_handler.cgu_output_parsed['EEC DPLL']['Status']
if self.gnss_cgu_handler.cgu_output_parsed['PPS DPLL']['Current reference'] == 'GNSS-1PPS':
self.gnss_pps_state = self.gnss_cgu_handler.cgu_output_parsed['PPS DPLL']['Status']
if self.gnss_cgu_handler.cgu_output_parsed[
'PPS DPLL']['Current reference'] == 'GNSS-1PPS':
self.gnss_pps_state = \
self.gnss_cgu_handler.cgu_output_parsed['PPS DPLL']['Status']
def update(self, subject, matched_line) -> None:
LOG.info("Kernel event detected. %s" % matched_line)
@ -92,11 +96,16 @@ class GnssMonitor(Observer):
self.gnss_cgu_handler.cgu_output_to_dict()
self.gnss_eec_state = self.gnss_eec_state = \
self.gnss_cgu_handler.cgu_output_parsed['EEC DPLL']['Status']
self.gnss_pps_state = self.gnss_cgu_handler.cgu_output_parsed['PPS DPLL']['Status']
self.gnss_pps_state = \
self.gnss_cgu_handler.cgu_output_parsed['PPS DPLL']['Status']
LOG.debug("GNSS EEC Status is: %s" % self.gnss_eec_state)
LOG.debug("GNSS PPS Status is: %s" % self.gnss_pps_state)
if self.gnss_pps_state == 'locked_ho_ack' and \
self.gnss_eec_state == 'locked_ho_ack':
if self.gnss_pps_state in [
constants.GNSS_LOCKED_HO_ACK,
constants.GNSS_LOCKED_HO_ACQ] and \
self.gnss_eec_state in [
constants.GNSS_LOCKED_HO_ACK,
constants.GNSS_LOCKED_HO_ACQ]:
self._state = GnssState.Synchronized
else:
self._state = GnssState.Failure_Nofix

View File

@ -33,23 +33,32 @@ THIS_NODE_NAME = os.environ.get("THIS_NODE_NAME", 'controller-0')
# Event source to event type mapping
source_type = {
'/sync/gnss-status/gnss-sync-status': 'event.sync.gnss-status.gnss-state-change',
'/sync/ptp-status/clock-class': 'event.sync.ptp-status.ptp-clock-class-change',
'/sync/ptp-status/lock-state': 'event.sync.ptp-status.ptp-state-change',
'/sync/sync-status/os-clock-sync-state': 'event.sync.sync-status.os-clock-sync-state-change',
'/sync/sync-status/sync-state': 'event.sync.sync-status.synchronization-state-change',
'/sync/synce-status/clock-quality': 'event.sync.synce-status.synce-clock-quality-change',
'/sync/synce-status/lock-state-extended': 'event.sync.synce-status.synce-state-change-extended',
'/sync/synce-status/lock-state': 'event.sync.synce-status.synce-state-change',
'/sync/gnss-status/gnss-sync-status':
'event.sync.gnss-status.gnss-state-change',
'/sync/ptp-status/clock-class':
'event.sync.ptp-status.ptp-clock-class-change',
'/sync/ptp-status/lock-state':
'event.sync.ptp-status.ptp-state-change',
'/sync/sync-status/os-clock-sync-state':
'event.sync.sync-status.os-clock-sync-state-change',
'/sync/sync-status/sync-state':
'event.sync.sync-status.synchronization-state-change',
'/sync/synce-status/clock-quality':
'event.sync.synce-status.synce-clock-quality-change',
'/sync/synce-status/lock-state-extended':
'event.sync.synce-status.synce-state-change-extended',
'/sync/synce-status/lock-state':
'event.sync.synce-status.synce-state-change',
}
'''Entry point of Default Process Worker'''
def ProcessWorkerDefault(event, sqlalchemy_conf_json, broker_transport_endpoint):
worker = PtpWatcherDefault(event, sqlalchemy_conf_json, broker_transport_endpoint)
def ProcessWorkerDefault(event, sqlalchemy_conf_json,
broker_transport_endpoint):
worker = PtpWatcherDefault(event, sqlalchemy_conf_json,
broker_transport_endpoint)
worker.run()
return
class PtpWatcherDefault:
@ -79,7 +88,8 @@ class PtpWatcherDefault:
self.init_time = time.time()
self.daemon_context = daemon_context
def _build_event_response(self, resource_path, last_event_time, resource_address,
def _build_event_response(
self, resource_path, last_event_time, resource_address,
sync_state, value_type=constants.VALUE_TYPE_ENUMERATION):
if resource_path in [constants.SOURCE_SYNC_PTP_CLOCK_CLASS,
constants.SOURCE_SYNCE_CLOCK_QUALITY]:
@ -111,109 +121,108 @@ class PtpWatcherDefault:
resource_address = rpc_kwargs.get('ResourceAddress', None)
optional = rpc_kwargs.get('optional', None)
if resource_address:
_, nodename, resource_path = utils.parse_resource_address(resource_address)
_, nodename, resource_path = utils.parse_resource_address(
resource_address)
if resource_path == constants.SOURCE_SYNC_ALL:
resource_path = constants.SOURCE_SYNC_SYNC_STATE
if resource_path == constants.SOURCE_SYNC_GNSS_SYNC_STATUS:
self.watcher.gnsstracker_context_lock.acquire()
if optional:
sync_state = self.watcher.gnsstracker_context[optional]. \
get('sync_state', GnssState.Failure_Nofix)
last_event_time = self.watcher.gnsstracker_context[optional].get(
'last_event_time',
time.time())
lastStatus[optional] = self._build_event_response(resource_path,
last_event_time,
resource_address,
sync_state = \
self.watcher.gnsstracker_context[optional].get(
'sync_state', GnssState.Failure_Nofix)
last_event_time = \
self.watcher.gnsstracker_context[optional].get(
'last_event_time', time.time())
lastStatus[optional] = self._build_event_response(
resource_path, last_event_time, resource_address,
sync_state)
else:
for config in self.daemon_context['GNSS_INSTANCES']:
sync_state = self.watcher.gnsstracker_context[config] \
.get('sync_state', GnssState.Failure_Nofix)
last_event_time = self.watcher.gnsstracker_context[config].get(
'last_event_time',
time.time())
lastStatus[config] = self._build_event_response(resource_path,
last_event_time,
resource_address,
sync_state)
sync_state = \
self.watcher.gnsstracker_context[config].get(
'sync_state', GnssState.Failure_Nofix)
last_event_time = \
self.watcher.gnsstracker_context[config].get(
'last_event_time', time.time())
lastStatus[config] = self._build_event_response(
resource_path, last_event_time,
resource_address, sync_state)
self.watcher.gnsstracker_context_lock.release()
elif resource_path == constants.SOURCE_SYNC_PTP_CLOCK_CLASS:
self.watcher.ptptracker_context_lock.acquire()
if optional:
clock_class = self.watcher.ptptracker_context[optional].get('clock_class',
'248')
last_clock_class_event_time = self.watcher.ptptracker_context[optional].get(
'last_clock_class_event_time',
time.time())
lastStatus[optional] = \
self._build_event_response(resource_path,
last_clock_class_event_time,
resource_address,
clock_class,
clock_class = \
self.watcher.ptptracker_context[optional].get(
'clock_class', '248')
last_clock_class_event_time = \
self.watcher.ptptracker_context[optional].get(
'last_clock_class_event_time', time.time())
lastStatus[optional] = self._build_event_response(
resource_path, last_clock_class_event_time,
resource_address, clock_class,
constants.VALUE_TYPE_METRIC)
else:
for config in self.daemon_context['PTP4L_INSTANCES']:
clock_class = self.watcher.ptptracker_context[config].get('clock_class',
'248')
clock_class = \
self.watcher.ptptracker_context[config].get(
'clock_class', '248')
last_clock_class_event_time = \
self.watcher.ptptracker_context[config].get(
'last_clock_class_event_time',
time.time())
lastStatus[config] = \
self._build_event_response(resource_path,
last_clock_class_event_time,
resource_address,
clock_class,
lastStatus[config] = self._build_event_response(
resource_path, last_clock_class_event_time,
resource_address, clock_class,
constants.VALUE_TYPE_METRIC)
self.watcher.ptptracker_context_lock.release()
elif resource_path == constants.SOURCE_SYNC_PTP_LOCK_STATE:
self.watcher.ptptracker_context_lock.acquire()
if optional:
sync_state = self.watcher.ptptracker_context[optional].get('sync_state',
PtpState.Freerun)
last_event_time = self.watcher.ptptracker_context[optional].get(
'last_event_time',
time.time())
lastStatus[optional] = self._build_event_response(resource_path,
last_event_time,
resource_address,
sync_state = \
self.watcher.ptptracker_context[optional].get(
'sync_state', PtpState.Freerun)
last_event_time = \
self.watcher.ptptracker_context[optional].get(
'last_event_time', time.time())
lastStatus[optional] = self._build_event_response(
resource_path, last_event_time, resource_address,
sync_state)
else:
for config in self.daemon_context['PTP4L_INSTANCES']:
sync_state = \
self.watcher.ptptracker_context[config].get('sync_state',
PtpState.Freerun)
last_event_time = self.watcher.ptptracker_context[config].get(
'last_event_time',
time.time())
lastStatus[config] = self._build_event_response(resource_path,
last_event_time,
resource_address,
sync_state)
self.watcher.ptptracker_context[config].get(
'sync_state', PtpState.Freerun)
last_event_time = \
self.watcher.ptptracker_context[config].get(
'last_event_time', time.time())
lastStatus[config] = self._build_event_response(
resource_path, last_event_time,
resource_address, sync_state)
self.watcher.ptptracker_context_lock.release()
elif resource_path == constants.SOURCE_SYNC_OS_CLOCK:
self.watcher.osclocktracker_context_lock.acquire()
sync_state = self.watcher.osclocktracker_context.get('sync_state',
OsClockState.Freerun)
last_event_time = self.watcher.osclocktracker_context.get('last_event_time',
time.time())
sync_state = \
self.watcher.osclocktracker_context.get(
'sync_state', OsClockState.Freerun)
last_event_time = \
self.watcher.osclocktracker_context.get(
'last_event_time', time.time())
self.watcher.osclocktracker_context_lock.release()
lastStatus['os_clock_status'] = self._build_event_response(resource_path,
last_event_time,
resource_address,
lastStatus['os_clock_status'] = self._build_event_response(
resource_path, last_event_time, resource_address,
sync_state)
elif resource_path == constants.SOURCE_SYNC_SYNC_STATE:
self.watcher.overalltracker_context_lock.acquire()
sync_state = self.watcher.overalltracker_context.get('sync_state',
OverallClockState.Freerun)
last_event_time = self.watcher.overalltracker_context.get('last_event_time',
time.time())
sync_state = self.watcher.overalltracker_context.get(
'sync_state', OverallClockState.Freerun)
last_event_time = self.watcher.overalltracker_context.get(
'last_event_time', time.time())
self.watcher.overalltracker_context_lock.release()
lastStatus['overall_sync_status'] = self._build_event_response(resource_path,
last_event_time,
resource_address,
lastStatus['overall_sync_status'] = \
self._build_event_response(
resource_path, last_event_time, resource_address,
sync_state)
LOG.debug("query_status: {}".format(lastStatus))
else:
@ -221,13 +230,14 @@ class PtpWatcherDefault:
# PTP v1 only supports single instance ptp
instance = self.daemon_context['PTP4L_INSTANCES'][0]
if len(self.daemon_context['PTP4L_INSTANCES']) > 1:
LOG.warning(
"Multiple ptp4l instances configured, retrieving status for %s" % instance)
LOG.warning("Multiple ptp4l instances configured, "
"retrieving status for %s" % instance)
self.watcher.ptptracker_context_lock.acquire()
sync_state = self.watcher.ptptracker_context[instance].get('sync_state',
PtpState.Freerun)
last_event_time = self.watcher.ptptracker_context[instance].get('last_event_time',
time.time())
sync_state = self.watcher.ptptracker_context[instance].get(
'sync_state', PtpState.Freerun)
last_event_time = \
self.watcher.ptptracker_context[instance].get(
'last_event_time', time.time())
lastStatus[constants.PTP_V1_KEY] = {
'ResourceType': ResourceType.TypePTP,
'EventData': {
@ -246,7 +256,6 @@ class PtpWatcherDefault:
def trigger_delivery(self, **rpc_kwargs):
self.watcher.forced_publishing = True
self.watcher.signal_ptp_event()
pass
def __init__(self, event, sqlalchemy_conf_json, daemon_context_json):
self.sqlalchemy_conf = json.loads(sqlalchemy_conf_json)
@ -258,92 +267,109 @@ class PtpWatcherDefault:
# PTP Context
self.ptptracker_context = {}
for config in self.daemon_context['PTP4L_INSTANCES']:
self.ptptracker_context[config] = PtpWatcherDefault.DEFAULT_PTPTRACKER_CONTEXT.copy()
self.ptptracker_context[config] = \
PtpWatcherDefault.DEFAULT_PTPTRACKER_CONTEXT.copy()
self.ptptracker_context[config]['sync_state'] = PtpState.Freerun
self.ptptracker_context[config]['last_event_time'] = self.init_time
self.ptptracker_context[config]['holdover_seconds'] = os.environ.get("PTP_HOLDOVER_SECONDS", 30)
self.ptptracker_context[config]['poll_freq_seconds'] = os.environ.get(
"CONTROL_TIMEOUT", 2)
self.ptp_device_simulated = "true" == self.ptptracker_context[config].get(
'device_simulated',
"False")
self.ptptracker_context[config]['holdover_seconds'] = \
os.environ.get("PTP_HOLDOVER_SECONDS", 30)
self.ptptracker_context[config]['poll_freq_seconds'] = \
os.environ.get("CONTROL_TIMEOUT", 2)
self.ptp_device_simulated = \
"true" == self.ptptracker_context[config].get(
'device_simulated', "False")
self.ptptracker_context_lock = threading.Lock()
LOG.debug("ptptracker_context: %s" % self.ptptracker_context)
# GNSS Context
self.gnsstracker_context = {}
for config in self.daemon_context['GNSS_INSTANCES']:
self.gnsstracker_context[config] = PtpWatcherDefault.DEFAULT_GNSSTRACKER_CONTEXT.copy()
self.gnsstracker_context[config]['sync_state'] = GnssState.Failure_Nofix
self.gnsstracker_context[config]['last_event_time'] = self.init_time
self.gnsstracker_context[config]['holdover_seconds'] = os.environ.get("GNSS_HOLDOVER_SECONDS", 30)
self.gnsstracker_context[config]['poll_freq_seconds'] = os.environ.get(
"CONTROL_TIMEOUT", 2)
self.gnsstracker_context[config] = \
PtpWatcherDefault.DEFAULT_GNSSTRACKER_CONTEXT.copy()
self.gnsstracker_context[config]['sync_state'] = \
GnssState.Failure_Nofix
self.gnsstracker_context[config]['last_event_time'] = \
self.init_time
self.gnsstracker_context[config]['holdover_seconds'] = \
os.environ.get("GNSS_HOLDOVER_SECONDS", 30)
self.gnsstracker_context[config]['poll_freq_seconds'] = \
os.environ.get("CONTROL_TIMEOUT", 2)
self.gnsstracker_context_lock = threading.Lock()
LOG.debug("gnsstracker_context: %s" % self.gnsstracker_context)
# OS Clock Context
self.osclocktracker_context = {}
self.osclocktracker_context = PtpWatcherDefault.DEFAULT_OS_CLOCK_TRACKER_CONTEXT.copy()
self.osclocktracker_context = \
PtpWatcherDefault.DEFAULT_OS_CLOCK_TRACKER_CONTEXT.copy()
self.osclocktracker_context['sync_state'] = OsClockState.Freerun
self.osclocktracker_context['last_event_time'] = self.init_time
self.osclocktracker_context['holdover_seconds'] = os.environ.get("OS_CLOCK_HOLDOVER_SECONDS", 30)
self.osclocktracker_context['poll_freq_seconds'] = os.environ.get(
"CONTROL_TIMEOUT", 2)
self.osclocktracker_context['holdover_seconds'] = \
os.environ.get("OS_CLOCK_HOLDOVER_SECONDS", 30)
self.osclocktracker_context['poll_freq_seconds'] = \
os.environ.get("CONTROL_TIMEOUT", 2)
self.osclocktracker_context_lock = threading.Lock()
# Overall Sync Context
self.overalltracker_context = {}
self.overalltracker_context = PtpWatcherDefault.DEFAULT_OVERALL_SYNC_TRACKER_CONTEXT.copy()
self.overalltracker_context = \
PtpWatcherDefault.DEFAULT_OVERALL_SYNC_TRACKER_CONTEXT.copy()
self.overalltracker_context['sync_state'] = OverallClockState.Freerun
self.overalltracker_context['last_event_time'] = self.init_time
self.overalltracker_context['holdover_seconds'] = os.environ.get("OVERALL_HOLDOVER_SECONDS", 30)
self.overalltracker_context['poll_freq_seconds'] = os.environ.get(
"CONTROL_TIMEOUT", 2)
self.overalltracker_context['holdover_seconds'] = \
os.environ.get("OVERALL_HOLDOVER_SECONDS", 30)
self.overalltracker_context['poll_freq_seconds'] = \
os.environ.get("CONTROL_TIMEOUT", 2)
self.overalltracker_context_lock = threading.Lock()
self.event_timeout = float(os.environ.get('CONTROL_TIMEOUT', 2))
self.node_name = self.daemon_context['THIS_NODE_NAME']
self.namespace = self.daemon_context.get('THIS_NAMESPACE', 'notification')
self.namespace = self.daemon_context.get(
'THIS_NAMESPACE', 'notification')
broker_transport_endpoint = self.daemon_context['NOTIFICATION_TRANSPORT_ENDPOINT']
broker_transport_endpoint = \
self.daemon_context['NOTIFICATION_TRANSPORT_ENDPOINT']
registration_transport_endpoint = self.daemon_context['REGISTRATION_TRANSPORT_ENDPOINT']
registration_transport_endpoint = \
self.daemon_context['REGISTRATION_TRANSPORT_ENDPOINT']
self.broker_endpoint = RpcEndpointInfo(broker_transport_endpoint)
self.registration_broker_endpoint = RpcEndpointInfo(registration_transport_endpoint)
self.registration_broker_endpoint = \
RpcEndpointInfo(registration_transport_endpoint)
self.ptpeventproducer = PtpEventProducer(
self.node_name,
self.broker_endpoint.TransportEndpoint,
self.registration_broker_endpoint.TransportEndpoint)
self.__ptprequest_handler = PtpWatcherDefault.PtpRequestHandlerDefault(self,
self.daemon_context)
self.__ptprequest_handler = \
PtpWatcherDefault.PtpRequestHandlerDefault(
self, self.daemon_context)
# Set forced_publishing to True so that initial states are published
# Main loop in run() sets it to false after the first iteration
self.forced_publishing = True
self.observer_list = [GnssMonitor(i) for i in self.daemon_context['GNSS_CONFIGS']]
self.observer_list = [
GnssMonitor(i) for i in self.daemon_context['GNSS_CONFIGS']]
# Setup OS Clock monitor
self.os_clock_monitor = OsClockMonitor(phc2sys_config=self.daemon_context['PHC2SYS_CONFIG'])
self.os_clock_monitor = OsClockMonitor(
phc2sys_config=self.daemon_context['PHC2SYS_CONFIG'])
# Setup PTP Monitor(s)
self.ptp_monitor_list = [
PtpMonitor(config, self.ptptracker_context[config]['holdover_seconds'],
PtpMonitor(config,
self.ptptracker_context[config]['holdover_seconds'],
self.ptptracker_context[config]['poll_freq_seconds'],
self.daemon_context['PHC2SYS_SERVICE_NAME']) for config in
self.daemon_context['PTP4L_INSTANCES']]
self.daemon_context['PHC2SYS_SERVICE_NAME'])
for config in self.daemon_context['PTP4L_INSTANCES']]
def signal_ptp_event(self):
if self.event:
self.event.set()
else:
LOG.warning("Unable to assert ptp event")
pass
def run(self):
# start location listener
@ -364,7 +390,6 @@ class PtpWatcherDefault:
self.event.clear()
else:
LOG.debug("daemon control event is timeout")
pass
continue
self.__stop_listener()
@ -376,27 +401,29 @@ class PtpWatcherDefault:
self.ptpeventproducer.start_status_listener(
self.__ptprequest_handler
)
return
def __stop_listener(self):
LOG.debug("stop listener to answer location querying")
self.ptpeventproducer.stop_status_listener(self.location_info)
return
def __get_gnss_status(self, holdover_time, freq, sync_state, last_event_time, gnss_monitor):
def __get_gnss_status(self, holdover_time, freq, sync_state,
last_event_time, gnss_monitor):
new_event, sync_state, new_event_time = gnss_monitor.get_gnss_status(
holdover_time, freq, sync_state, last_event_time)
LOG.debug("Getting GNSS status.")
return new_event, sync_state, new_event_time
def __get_os_clock_status(self, holdover_time, freq, sync_state, last_event_time):
new_event, sync_state, new_event_time = self.os_clock_monitor.os_clock_status(
def __get_os_clock_status(self, holdover_time, freq, sync_state,
last_event_time):
new_event, sync_state, new_event_time = \
self.os_clock_monitor.os_clock_status(
holdover_time, freq, sync_state, last_event_time)
LOG.debug("Getting os clock status.")
return new_event, sync_state, new_event_time
def __get_overall_sync_state(self, holdover_time, freq, sync_state, last_event_time):
def __get_overall_sync_state(self, holdover_time, freq, sync_state,
last_event_time):
new_event = False
new_event_time = last_event_time
previous_sync_state = sync_state
@ -411,36 +438,44 @@ class PtpWatcherDefault:
LOG.debug("Getting overall sync state.")
for gnss in self.observer_list:
if gnss._state == constants.UNKNOWN_PHC_STATE or gnss._state == GnssState.Failure_Nofix:
if gnss._state == constants.UNKNOWN_PHC_STATE or \
gnss._state == GnssState.Failure_Nofix:
gnss_state = GnssState.Failure_Nofix
elif gnss._state == GnssState.Synchronized and gnss_state != GnssState.Failure_Nofix:
elif gnss._state == GnssState.Synchronized and \
gnss_state != GnssState.Failure_Nofix:
gnss_state = GnssState.Synchronized
for ptp4l in self.ptp_monitor_list:
_, read_state, _ = ptp4l.get_ptp_sync_state()
if read_state == PtpState.Holdover or read_state == PtpState.Freerun or \
if read_state == PtpState.Holdover or \
read_state == PtpState.Freerun or \
read_state == constants.UNKNOWN_PHC_STATE:
ptp_state = PtpState.Freerun
elif read_state == PtpState.Locked and ptp_state != PtpState.Freerun:
elif read_state == PtpState.Locked and \
ptp_state != PtpState.Freerun:
ptp_state = PtpState.Locked
os_clock_state = self.os_clock_monitor.get_os_clock_state()
if gnss_state is GnssState.Failure_Nofix or os_clock_state is OsClockState.Freerun or \
if gnss_state is GnssState.Failure_Nofix or \
os_clock_state is OsClockState.Freerun or \
ptp_state is PtpState.Freerun:
sync_state = OverallClockState.Freerun
else:
sync_state = OverallClockState.Locked
if sync_state == OverallClockState.Freerun:
if previous_sync_state in [constants.UNKNOWN_PHC_STATE, constants.FREERUN_PHC_STATE]:
if previous_sync_state in [
constants.UNKNOWN_PHC_STATE,
constants.FREERUN_PHC_STATE]:
sync_state = OverallClockState.Freerun
elif previous_sync_state == constants.LOCKED_PHC_STATE:
sync_state = OverallClockState.Holdover
elif previous_sync_state == constants.HOLDOVER_PHC_STATE and \
time_in_holdover < max_holdover_time:
LOG.debug("Overall sync: Time in holdover is %s Max time in holdover is %s" % (
time_in_holdover, max_holdover_time))
LOG.debug("Overall sync: Time in holdover is %s "
"Max time in holdover is %s"
% (time_in_holdover, max_holdover_time))
sync_state = OverallClockState.Holdover
else:
sync_state = OverallClockState.Freerun
@ -450,7 +485,8 @@ class PtpWatcherDefault:
new_event_time = datetime.datetime.utcnow().timestamp()
return new_event, sync_state, new_event_time
def __get_ptp_status(self, holdover_time, freq, sync_state, last_event_time, ptp_monitor):
def __get_ptp_status(self, holdover_time, freq, sync_state,
last_event_time, ptp_monitor):
new_event = False
new_event_time = last_event_time
ptp_monitor.set_ptp_sync_state()
@ -469,7 +505,8 @@ class PtpWatcherDefault:
else:
sync_state = PtpState.Freerun
else:
new_event, sync_state, new_event_time = ptp_monitor.get_ptp_sync_state()
new_event, sync_state, new_event_time = \
ptp_monitor.get_ptp_sync_state()
return new_event, sync_state, new_event_time
'''announce location'''
@ -478,12 +515,14 @@ class PtpWatcherDefault:
holdover_time = float(self.osclocktracker_context['holdover_seconds'])
freq = float(self.osclocktracker_context['poll_freq_seconds'])
sync_state = self.osclocktracker_context.get('sync_state', 'Unknown')
last_event_time = self.osclocktracker_context.get('last_event_time', time.time())
last_event_time = self.osclocktracker_context.get('last_event_time',
time.time())
lastStatus = {}
new_event, sync_state, new_event_time = self.__get_os_clock_status(
holdover_time, freq, sync_state, last_event_time)
LOG.info("os_clock_status: state is %s, new_event is %s " % (sync_state, new_event))
LOG.info("os_clock_status: state is %s, new_event is %s "
% (sync_state, new_event))
if new_event or forced:
self.osclocktracker_context_lock.acquire()
self.osclocktracker_context['sync_state'] = sync_state
@ -512,20 +551,23 @@ class PtpWatcherDefault:
]
}
}
self.ptpeventproducer.publish_status(lastStatus, constants.SOURCE_SYNC_OS_CLOCK)
self.ptpeventproducer.publish_status(lastStatus, constants.SOURCE_SYNC_ALL)
return
self.ptpeventproducer.publish_status(
lastStatus, constants.SOURCE_SYNC_OS_CLOCK)
self.ptpeventproducer.publish_status(
lastStatus, constants.SOURCE_SYNC_ALL)
def __publish_overall_sync_status(self, forced=False):
lastStatus = {}
holdover_time = float(self.overalltracker_context['holdover_seconds'])
freq = float(self.overalltracker_context['poll_freq_seconds'])
sync_state = self.overalltracker_context.get('sync_state', 'Unknown')
last_event_time = self.overalltracker_context.get('last_event_time', time.time())
last_event_time = self.overalltracker_context.get('last_event_time',
time.time())
new_event, sync_state, new_event_time = self.__get_overall_sync_state(
holdover_time, freq, sync_state, last_event_time)
LOG.info("overall_sync_state: state is %s, new_event is %s " % (sync_state, new_event))
LOG.info("overall_sync_state: state is %s, new_event is %s "
% (sync_state, new_event))
if new_event or forced:
# Update context
@ -555,30 +597,36 @@ class PtpWatcherDefault:
]
}
}
self.ptpeventproducer.publish_status(lastStatus, constants.SOURCE_SYNC_SYNC_STATE)
self.ptpeventproducer.publish_status(lastStatus, constants.SOURCE_SYNC_ALL)
self.ptpeventproducer.publish_status(
lastStatus, constants.SOURCE_SYNC_SYNC_STATE)
self.ptpeventproducer.publish_status(
lastStatus, constants.SOURCE_SYNC_ALL)
def __publish_gnss_status(self, forced=False):
lastStatus = {}
for gnss in self.observer_list:
holdover_time = float(
self.gnsstracker_context[gnss.ts2phc_service_name]['holdover_seconds'])
freq = float(self.gnsstracker_context[gnss.ts2phc_service_name]['poll_freq_seconds'])
sync_state = self.gnsstracker_context[gnss.ts2phc_service_name].get('sync_state',
'Unknown')
last_event_time = self.gnsstracker_context[gnss.ts2phc_service_name].get(
'last_event_time',
time.time())
self.gnsstracker_context[
gnss.ts2phc_service_name]['holdover_seconds'])
freq = float(self.gnsstracker_context[
gnss.ts2phc_service_name]['poll_freq_seconds'])
sync_state = \
self.gnsstracker_context[gnss.ts2phc_service_name].get(
'sync_state', 'Unknown')
last_event_time = \
self.gnsstracker_context[gnss.ts2phc_service_name].get(
'last_event_time', time.time())
new_event, sync_state, new_event_time = self.__get_gnss_status(
holdover_time, freq, sync_state, last_event_time, gnss)
LOG.info("%s gnss_status: state is %s, new_event is %s" % (
gnss.ts2phc_service_name, sync_state, new_event))
LOG.info("%s gnss_status: state is %s, new_event is %s"
% (gnss.ts2phc_service_name, sync_state, new_event))
if new_event or forced:
# update context
self.gnsstracker_context_lock.acquire()
self.gnsstracker_context[gnss.ts2phc_service_name]['sync_state'] = sync_state
self.gnsstracker_context[
gnss.ts2phc_service_name]['sync_state'] = sync_state
self.gnsstracker_context[gnss.ts2phc_service_name][
'last_event_time'] = new_event_time
self.gnsstracker_context_lock.release()
@ -592,7 +640,8 @@ class PtpWatcherDefault:
'id': uuidutils.generate_uuid(),
'specversion': constants.SPEC_VERSION,
'source': constants.SOURCE_SYNC_GNSS_SYNC_STATUS,
'type': source_type[constants.SOURCE_SYNC_GNSS_SYNC_STATUS],
'type': source_type[
constants.SOURCE_SYNC_GNSS_SYNC_STATUS],
'time': new_event_time,
'data': {
'version': constants.DATA_VERSION,
@ -606,23 +655,25 @@ class PtpWatcherDefault:
]
}
}
self.ptpeventproducer.publish_status(lastStatus,
constants.SOURCE_SYNC_GNSS_SYNC_STATUS)
self.ptpeventproducer.publish_status(lastStatus, constants.SOURCE_SYNC_ALL)
return
self.ptpeventproducer.publish_status(
lastStatus, constants.SOURCE_SYNC_GNSS_SYNC_STATUS)
self.ptpeventproducer.publish_status(
lastStatus, constants.SOURCE_SYNC_ALL)
def __publish_ptpstatus(self, forced=False):
lastStatus = {}
lastClockClassStatus = {}
for ptp_monitor in self.ptp_monitor_list:
holdover_time = \
float(self.ptptracker_context[ptp_monitor.ptp4l_service_name]['holdover_seconds'])
freq = float(
self.ptptracker_context[ptp_monitor.ptp4l_service_name]['poll_freq_seconds'])
sync_state = self.ptptracker_context[ptp_monitor.ptp4l_service_name]. \
get('sync_state', 'Unknown')
last_event_time = self.ptptracker_context[ptp_monitor.ptp4l_service_name] \
.get('last_event_time', time.time())
holdover_time = float(self.ptptracker_context[
ptp_monitor.ptp4l_service_name]['holdover_seconds'])
freq = float(self.ptptracker_context[
ptp_monitor.ptp4l_service_name]['poll_freq_seconds'])
sync_state = \
self.ptptracker_context[ptp_monitor.ptp4l_service_name].get(
'sync_state', 'Unknown')
last_event_time = \
self.ptptracker_context[ptp_monitor.ptp4l_service_name].get(
'last_event_time', time.time())
new_event, sync_state, new_event_time = self.__get_ptp_status(
holdover_time, freq, sync_state, last_event_time, ptp_monitor)
@ -631,12 +682,14 @@ class PtpWatcherDefault:
new_clock_class_event, clock_class, clock_class_event_time = \
ptp_monitor.get_ptp_clock_class()
LOG.info("%s PTP clock class: clockClass is %s, new_event is %s" % (
ptp_monitor.ptp4l_service_name, clock_class, new_clock_class_event))
LOG.info("%s PTP clock class: clockClass is %s, new_event is %s"
% (ptp_monitor.ptp4l_service_name, clock_class,
new_clock_class_event))
if new_event or forced:
# update context
self.ptptracker_context_lock.acquire()
self.ptptracker_context[ptp_monitor.ptp4l_service_name]['sync_state'] = sync_state
self.ptptracker_context[ptp_monitor.ptp4l_service_name][
'sync_state'] = sync_state
self.ptptracker_context[ptp_monitor.ptp4l_service_name][
'last_event_time'] = new_event_time
@ -676,19 +729,20 @@ class PtpWatcherDefault:
}
}
self.ptptracker_context_lock.release()
self.ptpeventproducer.publish_status(lastStatus,
constants.SOURCE_SYNC_PTP_LOCK_STATE)
self.ptpeventproducer.publish_status(lastStatus, constants.SOURCE_SYNC_ALL)
self.ptpeventproducer.publish_status(
lastStatus, constants.SOURCE_SYNC_PTP_LOCK_STATE)
self.ptpeventproducer.publish_status(
lastStatus, constants.SOURCE_SYNC_ALL)
if new_clock_class_event or forced:
# update context
self.ptptracker_context_lock.acquire()
self.ptptracker_context[ptp_monitor.ptp4l_service_name]['clock_class'] = clock_class
self.ptptracker_context[ptp_monitor.ptp4l_service_name][
'clock_class'] = clock_class
self.ptptracker_context[ptp_monitor.ptp4l_service_name][
'last_clock_class_event_time'] \
= clock_class_event_time
resource_address = utils.format_resource_address(
self.node_name, constants.SOURCE_SYNC_PTP_CLOCK_CLASS)
@ -711,19 +765,19 @@ class PtpWatcherDefault:
}
}
self.ptptracker_context_lock.release()
LOG.info("Publishing clockClass for %s: %s" % (ptp_monitor.ptp4l_service_name,
clock_class))
self.ptpeventproducer.publish_status(lastClockClassStatus,
LOG.info("Publishing clockClass for %s: %s"
% (ptp_monitor.ptp4l_service_name, clock_class))
self.ptpeventproducer.publish_status(
lastClockClassStatus,
constants.SOURCE_SYNC_PTP_CLOCK_CLASS)
self.ptpeventproducer.publish_status(lastClockClassStatus,
constants.SOURCE_SYNC_ALL)
return
class DaemonControl(object):
def __init__(self, sqlalchemy_conf_json, daemon_context_json, process_worker=None):
def __init__(self, sqlalchemy_conf_json, daemon_context_json,
process_worker=None):
self.event = mp.Event()
self.daemon_context = json.loads(daemon_context_json)
self.node_name = self.daemon_context['THIS_NODE_NAME']
@ -733,8 +787,8 @@ class DaemonControl(object):
self.sqlalchemy_conf_json = sqlalchemy_conf_json
self.daemon_context_json = daemon_context_json
self.process_worker = process_worker
return
def refresh(self):
self.process_worker(self.event, self.sqlalchemy_conf_json, self.daemon_context_json)
self.process_worker(self.event, self.sqlalchemy_conf_json,
self.daemon_context_json)
self.event.set()