Update logic for checking HA Phc2sys sources
Ensure that ptp-notification is correctly transitioning state when HA phc2sys is in use and there are no valid source interfaces. For v2 API, this means that the os_clock status state is changed when all valid phc2sys sources are lost/returned. For v1 API, support the option to log a warning when phc2sys HA has no valid sources, but do not change state, as phc2sys sync is not considered for the sync state in the v1 API. Test plan: PASS: Build and deploy images PASS: Verify that v2 API state changes when HA phc2sys loses valid sources PASS: Verify that v2 API returns to LOCKED when valid sources return PASS: Verify that v1 API can log a warning when no valid HA phc2sys sources are present Story: 2010723 Task: 49205 Signed-off-by: Cole Walker <cole.walker@windriver.com> Change-Id: I43c499d62f352147994d134d867f042186cd8e35
This commit is contained in:
parent
adfae0d2a8
commit
c23e19a1ce
@ -35,6 +35,7 @@ class OsClockMonitor:
|
|||||||
self.config = None
|
self.config = None
|
||||||
self.phc2sys_ha_enabled = False
|
self.phc2sys_ha_enabled = False
|
||||||
self.phc2sys_com_socket = None
|
self.phc2sys_com_socket = None
|
||||||
|
self.valid_phc_interfaces = None
|
||||||
|
|
||||||
self.phc2sys_tolerance_low = constants.PHC2SYS_TOLERANCE_LOW
|
self.phc2sys_tolerance_low = constants.PHC2SYS_TOLERANCE_LOW
|
||||||
self.phc2sys_tolerance_high = constants.PHC2SYS_TOLERANCE_HIGH
|
self.phc2sys_tolerance_high = constants.PHC2SYS_TOLERANCE_HIGH
|
||||||
@ -44,7 +45,7 @@ class OsClockMonitor:
|
|||||||
self.phc2sys_tolerance_threshold))
|
self.phc2sys_tolerance_threshold))
|
||||||
except:
|
except:
|
||||||
LOG.error('Unable to convert PHC2SYS_TOLERANCE_THRESHOLD to integer,'
|
LOG.error('Unable to convert PHC2SYS_TOLERANCE_THRESHOLD to integer,'
|
||||||
' using the default.')
|
' using the default.')
|
||||||
|
|
||||||
self.set_phc2sys_instance()
|
self.set_phc2sys_instance()
|
||||||
|
|
||||||
@ -58,7 +59,8 @@ class OsClockMonitor:
|
|||||||
elif 'ha_enabled' in self.config['global'].keys() \
|
elif 'ha_enabled' in self.config['global'].keys() \
|
||||||
and self.config['global']['ha_enabled'] == '1':
|
and self.config['global']['ha_enabled'] == '1':
|
||||||
self.phc2sys_ha_enabled = True
|
self.phc2sys_ha_enabled = True
|
||||||
self.phc2sys_com_socket = self.config['global'].get('ha_phc2sys_com_socket', None)
|
self.phc2sys_com_socket = self.config['global'].get(
|
||||||
|
'ha_phc2sys_com_socket', None)
|
||||||
|
|
||||||
if self.phc2sys_ha_enabled is True:
|
if self.phc2sys_ha_enabled is True:
|
||||||
self.set_phc2sys_ha_interface_and_phc
|
self.set_phc2sys_ha_interface_and_phc
|
||||||
@ -84,7 +86,8 @@ class OsClockMonitor:
|
|||||||
def query_phc2sys_socket(self, query, unix_socket=None):
|
def query_phc2sys_socket(self, query, unix_socket=None):
|
||||||
if unix_socket:
|
if unix_socket:
|
||||||
try:
|
try:
|
||||||
client_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
client_socket = socket.socket(
|
||||||
|
socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
client_socket.connect(unix_socket)
|
client_socket.connect(unix_socket)
|
||||||
client_socket.send(query.encode())
|
client_socket.send(query.encode())
|
||||||
response = client_socket.recv(1024)
|
response = client_socket.recv(1024)
|
||||||
@ -104,25 +107,30 @@ class OsClockMonitor:
|
|||||||
if hasattr(client_socket, 'close'):
|
if hasattr(client_socket, 'close'):
|
||||||
client_socket.close()
|
client_socket.close()
|
||||||
else:
|
else:
|
||||||
LOG.warning("No socket path supplied for instance %s" % self.phc2sys_instance)
|
LOG.warning("No socket path supplied for instance %s" %
|
||||||
|
self.phc2sys_instance)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def set_phc2sys_ha_interface_and_phc(self):
|
def set_phc2sys_ha_interface_and_phc(self):
|
||||||
update_phc_interface = self.query_phc2sys_socket('valid sources', self.phc2sys_com_socket)
|
self.valid_phc_interfaces = self.query_phc2sys_socket(
|
||||||
if update_phc_interface is None:
|
'valid sources', self.phc2sys_com_socket)
|
||||||
LOG.info("No PHC device found for HA phc2sys, status is FREERUN.")
|
selected_phc_interface = self.query_phc2sys_socket(
|
||||||
|
'clock source', self.phc2sys_com_socket)
|
||||||
|
if str(self.valid_phc_interfaces) == 'None':
|
||||||
|
LOG.info("No valid PHC device found for HA phc2sys selection.")
|
||||||
self._state = OsClockState.Freerun
|
self._state = OsClockState.Freerun
|
||||||
self.phc_interface = update_phc_interface
|
self.phc_interface = selected_phc_interface
|
||||||
self.ptp_device = None
|
self.ptp_device = None
|
||||||
elif update_phc_interface != self.phc_interface:
|
elif selected_phc_interface != self.phc_interface:
|
||||||
LOG.info("Phc2sys source interface changed from %s to %s"
|
LOG.info("Phc2sys source interface changed from %s to %s"
|
||||||
% (self.phc_interface, update_phc_interface))
|
% (self.phc_interface, self.valid_phc_interfaces))
|
||||||
self.phc_interface = update_phc_interface
|
self.phc_interface = selected_phc_interface
|
||||||
|
|
||||||
if self.phc_interface is not None:
|
if self.phc_interface is not None:
|
||||||
self.ptp_device = self._get_interface_phc_device()
|
self.ptp_device = self._get_interface_phc_device()
|
||||||
|
|
||||||
LOG.debug("Phc2sys HA interface: %s ptp_device: %s" % (self.phc_interface, self.ptp_device))
|
LOG.debug("Phc2sys HA interface: %s ptp_device: %s" %
|
||||||
|
(self.phc_interface, self.ptp_device))
|
||||||
|
|
||||||
def set_utc_offset(self, pidfile_path="/var/run/"):
|
def set_utc_offset(self, pidfile_path="/var/run/"):
|
||||||
# Check command line options for offset
|
# Check command line options for offset
|
||||||
@ -137,18 +145,22 @@ class OsClockMonitor:
|
|||||||
utc_offset_valid = False
|
utc_offset_valid = False
|
||||||
|
|
||||||
if self.config.has_section(self.phc_interface) \
|
if self.config.has_section(self.phc_interface) \
|
||||||
and 'ha_domainNumber' in self.config[self.phc_interface].keys():
|
and 'ha_domainNumber' in self.config[self.phc_interface].keys():
|
||||||
domain_number = self.config[self.phc_interface].get('ha_domainNumber')
|
domain_number = self.config[self.phc_interface].get(
|
||||||
LOG.debug("set_utc_offset: ha_domainNumber is %s" % domain_number)
|
'ha_domainNumber')
|
||||||
|
LOG.debug("set_utc_offset: ha_domainNumber is %s" %
|
||||||
|
domain_number)
|
||||||
|
|
||||||
if self.config.has_section('global') \
|
if self.config.has_section('global') \
|
||||||
and 'uds_address' in self.config['global'].keys():
|
and 'uds_address' in self.config['global'].keys():
|
||||||
uds_addr = self.config['global']['uds_address']
|
uds_addr = self.config['global']['uds_address']
|
||||||
LOG.debug("set_utc_offset: uds_addr is %s" % uds_addr)
|
LOG.debug("set_utc_offset: uds_addr is %s" % uds_addr)
|
||||||
|
|
||||||
if domain_number is None:
|
if domain_number is None:
|
||||||
domain_number = self.config['global'].get('domainNumber', '0')
|
domain_number = self.config['global'].get(
|
||||||
LOG.debug("set_utc_offset: domainNumber is %s" % domain_number)
|
'domainNumber', '0')
|
||||||
|
LOG.debug("set_utc_offset: domainNumber is %s" %
|
||||||
|
domain_number)
|
||||||
|
|
||||||
#
|
#
|
||||||
# sudo /usr/sbin/pmc -u -b 0 'GET TIME_PROPERTIES_DATA_SET'
|
# sudo /usr/sbin/pmc -u -b 0 'GET TIME_PROPERTIES_DATA_SET'
|
||||||
@ -166,11 +178,13 @@ class OsClockMonitor:
|
|||||||
if not utc_offset_valid:
|
if not utc_offset_valid:
|
||||||
utc_offset = constants.UTC_OFFSET
|
utc_offset = constants.UTC_OFFSET
|
||||||
LOG.warning('currentUtcOffsetValid is %s, using the default currentUtcOffset %s'
|
LOG.warning('currentUtcOffsetValid is %s, using the default currentUtcOffset %s'
|
||||||
% (utc_offset_valid, utc_offset))
|
% (utc_offset_valid, utc_offset))
|
||||||
|
|
||||||
utc_offset_nanoseconds = abs(int(utc_offset)) * 1000000000
|
utc_offset_nanoseconds = abs(int(utc_offset)) * 1000000000
|
||||||
self.phc2sys_tolerance_low = utc_offset_nanoseconds - self.phc2sys_tolerance_threshold
|
self.phc2sys_tolerance_low = utc_offset_nanoseconds - \
|
||||||
self.phc2sys_tolerance_high = utc_offset_nanoseconds + self.phc2sys_tolerance_threshold
|
self.phc2sys_tolerance_threshold
|
||||||
|
self.phc2sys_tolerance_high = utc_offset_nanoseconds + \
|
||||||
|
self.phc2sys_tolerance_threshold
|
||||||
LOG.debug('utc_offset_nanoseconds is %s, phc2sys_tolerance_threshold is %s'
|
LOG.debug('utc_offset_nanoseconds is %s, phc2sys_tolerance_threshold is %s'
|
||||||
% (utc_offset_nanoseconds, self.phc2sys_tolerance_threshold))
|
% (utc_offset_nanoseconds, self.phc2sys_tolerance_threshold))
|
||||||
LOG.info('phc2sys_tolerance_low is %s, phc2sys_tolerance_high is %s'
|
LOG.info('phc2sys_tolerance_low is %s, phc2sys_tolerance_high is %s'
|
||||||
@ -179,7 +193,8 @@ class OsClockMonitor:
|
|||||||
def get_os_clock_time_source(self, pidfile_path="/var/run/"):
|
def get_os_clock_time_source(self, pidfile_path="/var/run/"):
|
||||||
"""Determine which PHC is disciplining the OS clock"""
|
"""Determine which PHC is disciplining the OS clock"""
|
||||||
self.phc_interface = None
|
self.phc_interface = None
|
||||||
self.phc_interface = self._get_phc2sys_command_line_option(pidfile_path, '-s')
|
self.phc_interface = self._get_phc2sys_command_line_option(
|
||||||
|
pidfile_path, '-s')
|
||||||
if self.phc_interface == constants.CLOCK_REALTIME:
|
if self.phc_interface == constants.CLOCK_REALTIME:
|
||||||
LOG.info("PHC2SYS is using CLOCK_REALTIME, OS Clock is not being "
|
LOG.info("PHC2SYS is using CLOCK_REALTIME, OS Clock is not being "
|
||||||
"disciplined by a PHC")
|
"disciplined by a PHC")
|
||||||
@ -187,7 +202,7 @@ class OsClockMonitor:
|
|||||||
if self.phc_interface is None:
|
if self.phc_interface is None:
|
||||||
self.phc_interface = self._check_config_file_interface()
|
self.phc_interface = self._check_config_file_interface()
|
||||||
if self.phc_interface is None:
|
if self.phc_interface is None:
|
||||||
LOG.info("No PHC device found for phc2sys, status is FREERUN.")
|
LOG.info("No PHC device found for phc2sys")
|
||||||
self._state = OsClockState.Freerun
|
self._state = OsClockState.Freerun
|
||||||
else:
|
else:
|
||||||
self.ptp_device = self._get_interface_phc_device()
|
self.ptp_device = self._get_interface_phc_device()
|
||||||
@ -239,7 +254,7 @@ class OsClockMonitor:
|
|||||||
# Try the 0th interface instead, required for some NIC types
|
# Try the 0th interface instead, required for some NIC types
|
||||||
phc_interface_base = self.phc_interface[:-1] + "0"
|
phc_interface_base = self.phc_interface[:-1] + "0"
|
||||||
LOG.info("No ptp device found at %s trying %s instead"
|
LOG.info("No ptp device found at %s trying %s instead"
|
||||||
% (pattern, phc_interface_base))
|
% (pattern, phc_interface_base))
|
||||||
pattern = "/hostsys/class/net/" + phc_interface_base + \
|
pattern = "/hostsys/class/net/" + phc_interface_base + \
|
||||||
"/device/ptp/*"
|
"/device/ptp/*"
|
||||||
ptp_device = glob(pattern)
|
ptp_device = glob(pattern)
|
||||||
@ -270,7 +285,7 @@ class OsClockMonitor:
|
|||||||
ptp_device_path = "/dev/" + self.ptp_device
|
ptp_device_path = "/dev/" + self.ptp_device
|
||||||
offset = subprocess.check_output(
|
offset = subprocess.check_output(
|
||||||
[constants.PHC_CTL_PATH, ptp_device_path, 'cmp']
|
[constants.PHC_CTL_PATH, ptp_device_path, 'cmp']
|
||||||
).decode().split()[-1]
|
).decode().split()[-1]
|
||||||
offset = offset.strip("-ns")
|
offset = offset.strip("-ns")
|
||||||
LOG.debug("PHC offset is %s" % offset)
|
LOG.debug("PHC offset is %s" % offset)
|
||||||
self.offset = offset
|
self.offset = offset
|
||||||
@ -291,14 +306,18 @@ class OsClockMonitor:
|
|||||||
offset_int = int(self.offset)
|
offset_int = int(self.offset)
|
||||||
if offset_int > self.phc2sys_tolerance_high or \
|
if offset_int > self.phc2sys_tolerance_high or \
|
||||||
offset_int < self.phc2sys_tolerance_low:
|
offset_int < self.phc2sys_tolerance_low:
|
||||||
LOG.warning("PHC2SYS offset is outside of tolerance, "
|
LOG.warning("PHC2SYS offset is outside of tolerance")
|
||||||
"handling state change.")
|
|
||||||
self._state = OsClockState.Freerun
|
self._state = OsClockState.Freerun
|
||||||
else:
|
else:
|
||||||
LOG.info("PHC2SYS offset is within tolerance, "
|
LOG.info("PHC2SYS offset is within tolerance")
|
||||||
"OS clock state is LOCKED")
|
|
||||||
self._state = OsClockState.Locked
|
self._state = OsClockState.Locked
|
||||||
|
|
||||||
|
# Perform an extra check for HA Phc2sys to ensure we have a source interface
|
||||||
|
if self.phc2sys_ha_enabled:
|
||||||
|
if str(self.valid_phc_interfaces) == 'None':
|
||||||
|
LOG.warning("No valid PHC device selected for HA phc2sys")
|
||||||
|
self._state = OsClockState.Freerun
|
||||||
|
|
||||||
def get_os_clock_state(self):
|
def get_os_clock_state(self):
|
||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ def check_critical_resources():
|
|||||||
# Log that phc2sys has no sources, but allow state checking to proceed
|
# Log that phc2sys has no sources, but allow state checking to proceed
|
||||||
LOG.info("HA phc2sys has no valid sources to select")
|
LOG.info("HA phc2sys has no valid sources to select")
|
||||||
else:
|
else:
|
||||||
LOG.info("HA phc2sys has valid sources: %s" % phc2sys_source_clock)
|
LOG.debug("HA phc2sys has valid sources: %s" % phc2sys_source_clock)
|
||||||
return pmc, ptp4l, phc2sys, ptp4lconf
|
return pmc, ptp4l, phc2sys, ptp4lconf
|
||||||
|
|
||||||
def check_phc2sys_ha_source():
|
def check_phc2sys_ha_source():
|
||||||
@ -100,7 +100,7 @@ def check_phc2sys_ha_source():
|
|||||||
client_socket.send(query.encode())
|
client_socket.send(query.encode())
|
||||||
response = client_socket.recv(1024)
|
response = client_socket.recv(1024)
|
||||||
response = response.decode().strip()
|
response = response.decode().strip()
|
||||||
if response == "None":
|
if str(response) == "None":
|
||||||
response = None
|
response = None
|
||||||
return response
|
return response
|
||||||
except ConnectionRefusedError as err:
|
except ConnectionRefusedError as err:
|
||||||
|
Loading…
Reference in New Issue
Block a user