Make ptp-notification parameters configurable
To allow more flexibility to the user, The following PTP parameters are being exposed to Helm Charts overrides configuration: ptp-notification-v1: - ptp4lClockClassLockedList ptp-notification-v2: - ptp4lClockClassLockedList - phc2sysToleranceThreshold Test Plan: PASS: Build containers and helm charts PASS: Deploy ptp-notification PASS: v1 api - test ptp4lClockClassLockedList with the default, non-default and invalid lists PASS: v2 api - test ptp4lClockClassLockedList with the default, non-default and invalid lists PASS: v2 api - test phc2sysToleranceThreshold with commandline option PASS: v2 api - test phc2sysToleranceThreshold with config file Closes-bug: 2033539 Change-Id: I7dc915d99a91ff405c4cca4f1e1c1bf3a3559a4e Signed-off-by: Caio Bruchert <caio.bruchert@windriver.com>
This commit is contained in:
parent
0dae44b92d
commit
63ba400fcd
@ -28,6 +28,8 @@ TIME_IS_TRACEABLE1 = "1"
|
||||
TIME_IS_TRACEABLE2 = "true"
|
||||
GM_IS_PRESENT = "true"
|
||||
CLOCK_CLASS_VALUE6 = "6"
|
||||
CLOCK_CLASS_VALUE7 = "7"
|
||||
CLOCK_CLASS_LOCKED_LIST = [CLOCK_CLASS_VALUE6, CLOCK_CLASS_VALUE7]
|
||||
# ts2phc constants
|
||||
NMEA_SERIALPORT = "ts2phc.nmea_serialport"
|
||||
GNSS_PIN = "GNSS-1PPS"
|
||||
@ -54,6 +56,7 @@ CLOCK_REALTIME = "CLOCK_REALTIME"
|
||||
|
||||
PHC2SYS_TOLERANCE_LOW = 36999999000
|
||||
PHC2SYS_TOLERANCE_HIGH = 37000001000
|
||||
PHC2SYS_TOLERANCE_THRESHOLD = 1000
|
||||
|
||||
PTP_V1_KEY = "ptp_notification_v1"
|
||||
|
||||
|
@ -19,6 +19,8 @@ from trackingfunctionsdk.model.dto.osclockstate import OsClockState
|
||||
LOG = logging.getLogger(__name__)
|
||||
log_helper.config_logger(LOG)
|
||||
|
||||
PLUGIN_STATUS_QUERY_EXEC = '/usr/sbin/pmc'
|
||||
|
||||
|
||||
class OsClockMonitor:
|
||||
|
||||
@ -34,6 +36,16 @@ class OsClockMonitor:
|
||||
self.phc2sys_ha_enabled = False
|
||||
self.phc2sys_com_socket = None
|
||||
|
||||
self.phc2sys_tolerance_low = constants.PHC2SYS_TOLERANCE_LOW
|
||||
self.phc2sys_tolerance_high = constants.PHC2SYS_TOLERANCE_HIGH
|
||||
self.phc2sys_tolerance_threshold = constants.PHC2SYS_TOLERANCE_THRESHOLD
|
||||
try:
|
||||
self.phc2sys_tolerance_threshold = int(os.environ.get('PHC2SYS_TOLERANCE_THRESHOLD',
|
||||
self.phc2sys_tolerance_threshold))
|
||||
except:
|
||||
LOG.error('Unable to convert PHC2SYS_TOLERANCE_THRESHOLD to integer,'
|
||||
' using the default.')
|
||||
|
||||
self.set_phc2sys_instance()
|
||||
|
||||
"""Normally initialize all fields, but allow these to be skipped to
|
||||
@ -52,6 +64,7 @@ class OsClockMonitor:
|
||||
self.set_phc2sys_ha_interface_and_phc
|
||||
else:
|
||||
self.get_os_clock_time_source()
|
||||
self.set_utc_offset()
|
||||
self.get_os_clock_offset()
|
||||
self.set_os_clock_state()
|
||||
|
||||
@ -111,10 +124,53 @@ class OsClockMonitor:
|
||||
|
||||
LOG.debug("Phc2sys HA interface: %s ptp_device: %s" % (self.phc_interface, self.ptp_device))
|
||||
|
||||
def set_utc_offset(self, pidfile_path="/var/run/"):
|
||||
# Check command line options for offset
|
||||
utc_offset = self._get_phc2sys_command_line_option(pidfile_path, '-O')
|
||||
|
||||
# If not, check config file for uds_address and domainNumber
|
||||
# If uds_address, get utc_offset from TIME_PROPERTIES_DATA_SET using the phc2sys config
|
||||
if not utc_offset:
|
||||
utc_offset = constants.UTC_OFFSET
|
||||
utc_offset_valid = False
|
||||
|
||||
if self.config.has_section('global') \
|
||||
and 'domainNumber' in self.config['global'].keys() \
|
||||
and 'uds_address' in self.config['global'].keys():
|
||||
#
|
||||
# sudo /usr/sbin/pmc -u -b 0 'GET TIME_PROPERTIES_DATA_SET'
|
||||
#
|
||||
data = subprocess.check_output(
|
||||
[PLUGIN_STATUS_QUERY_EXEC, '-f', self.phc2sys_config, '-u', '-b', '0',
|
||||
'GET TIME_PROPERTIES_DATA_SET']).decode()
|
||||
|
||||
for line in data.split('\n'):
|
||||
if 'currentUtcOffset ' in line:
|
||||
utc_offset = line.split()[1]
|
||||
if 'currentUtcOffsetValid ' in line:
|
||||
utc_offset_valid = bool(int(line.split()[1]))
|
||||
|
||||
if not utc_offset_valid:
|
||||
utc_offset = constants.UTC_OFFSET
|
||||
LOG.warning('currentUtcOffsetValid is %s, using the default currentUtcOffset %s'
|
||||
% (utc_offset_valid, utc_offset))
|
||||
|
||||
utc_offset_nanoseconds = abs(int(utc_offset)) * 1000000000
|
||||
self.phc2sys_tolerance_low = utc_offset_nanoseconds - 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'
|
||||
% (utc_offset_nanoseconds, self.phc2sys_tolerance_threshold))
|
||||
LOG.info('phc2sys_tolerance_low is %s, phc2sys_tolerance_high is %s'
|
||||
% (self.phc2sys_tolerance_low, self.phc2sys_tolerance_high))
|
||||
|
||||
def get_os_clock_time_source(self, pidfile_path="/var/run/"):
|
||||
"""Determine which PHC is disciplining the OS clock"""
|
||||
self.phc_interface = None
|
||||
self.phc_interface = self._check_command_line_interface(pidfile_path)
|
||||
self.phc_interface = self._get_phc2sys_command_line_option(pidfile_path, '-s')
|
||||
if self.phc_interface == constants.CLOCK_REALTIME:
|
||||
LOG.info("PHC2SYS is using CLOCK_REALTIME, OS Clock is not being "
|
||||
"disciplined by a PHC")
|
||||
self.phc_interface = None
|
||||
if self.phc_interface is None:
|
||||
self.phc_interface = self._check_config_file_interface()
|
||||
if self.phc_interface is None:
|
||||
@ -123,30 +179,30 @@ class OsClockMonitor:
|
||||
else:
|
||||
self.ptp_device = self._get_interface_phc_device()
|
||||
|
||||
def _check_command_line_interface(self, pidfile_path):
|
||||
def _get_phc2sys_command_line_option(self, pidfile_path, flag):
|
||||
pidfile = pidfile_path + "phc2sys-" + self.phc2sys_instance + ".pid"
|
||||
with open(pidfile, 'r') as f:
|
||||
pid = f.readline().strip()
|
||||
# Get command line params
|
||||
cmdline_file = "/host/proc/" + pid + "/cmdline"
|
||||
with open(cmdline_file, 'r') as f:
|
||||
cmdline_args = f.readline().strip()
|
||||
cmdline_args = cmdline_args.split("\x00")
|
||||
|
||||
# The interface will be at the index after "-s"
|
||||
try:
|
||||
interface_index = cmdline_args.index('-s')
|
||||
except ValueError as ex:
|
||||
LOG.error("No interface found in cmdline args. %s" % ex)
|
||||
with open(pidfile, 'r') as f:
|
||||
pid = f.readline().strip()
|
||||
# Get command line params
|
||||
cmdline_file = "/host/proc/" + pid + "/cmdline"
|
||||
with open(cmdline_file, 'r') as f:
|
||||
cmdline_args = f.readline().strip()
|
||||
cmdline_args = cmdline_args.split("\x00")
|
||||
except OSError as ex:
|
||||
LOG.warning("Cannot open file. %s" % ex)
|
||||
return None
|
||||
|
||||
phc_interface = cmdline_args[interface_index + 1]
|
||||
if phc_interface == constants.CLOCK_REALTIME:
|
||||
LOG.info("PHC2SYS is using CLOCK_REALTIME, OS Clock is not being "
|
||||
"disciplined by a PHC")
|
||||
# The option value will be at the index after the flag
|
||||
try:
|
||||
index = cmdline_args.index(flag)
|
||||
except ValueError as ex:
|
||||
LOG.debug("Flag not found in cmdline args. %s" % ex)
|
||||
return None
|
||||
LOG.debug("PHC interface is %s" % phc_interface)
|
||||
return phc_interface
|
||||
|
||||
value = cmdline_args[index + 1]
|
||||
LOG.debug("%s value is %s" % (flag, value))
|
||||
return value
|
||||
|
||||
def _check_config_file_interface(self):
|
||||
with open(self.phc2sys_config, 'r') as f:
|
||||
@ -220,8 +276,8 @@ class OsClockMonitor:
|
||||
|
||||
def set_os_clock_state(self):
|
||||
offset_int = int(self.offset)
|
||||
if offset_int > constants.PHC2SYS_TOLERANCE_HIGH or \
|
||||
offset_int < constants.PHC2SYS_TOLERANCE_LOW:
|
||||
if offset_int > self.phc2sys_tolerance_high or \
|
||||
offset_int < self.phc2sys_tolerance_low:
|
||||
LOG.warning("PHC2SYS offset is outside of tolerance, "
|
||||
"handling state change.")
|
||||
self._state = OsClockState.Freerun
|
||||
@ -241,6 +297,7 @@ class OsClockMonitor:
|
||||
time_in_holdover = round(current_time - event_time)
|
||||
max_holdover_time = (holdover_time - freq * 2)
|
||||
|
||||
self.set_utc_offset()
|
||||
self.get_os_clock_offset()
|
||||
self.set_os_clock_state()
|
||||
|
||||
|
@ -23,6 +23,15 @@ LOG = logging.getLogger(__name__)
|
||||
log_helper.config_logger(LOG)
|
||||
|
||||
|
||||
ptp4l_clock_class_locked = constants.CLOCK_CLASS_LOCKED_LIST
|
||||
try:
|
||||
tmp = os.environ.get('PTP4L_CLOCK_CLASS_LOCKED_LIST', ','.join(ptp4l_clock_class_locked))
|
||||
ptp4l_clock_class_locked = sorted([str(int(e)) for e in tmp.split(',')])
|
||||
except:
|
||||
LOG.error('Unable to convert PTP4L_CLOCK_CLASS_LOCKED_LIST to a list of integers,'
|
||||
' using the default.')
|
||||
|
||||
|
||||
# run subprocess and returns out, err, errcode
|
||||
def run_shell2(dir, ctx, args):
|
||||
cwd = os.getcwd()
|
||||
@ -82,11 +91,16 @@ def check_results(result, total_ptp_keywords, port_count):
|
||||
break
|
||||
else:
|
||||
sync_state = constants.FREERUN_PHC_STATE
|
||||
if (result[constants.TIME_TRACEABLE] != constants.TIME_IS_TRACEABLE1
|
||||
|
||||
# We can only expect timeTraceable=1 to be set when the clockClass list is the default.
|
||||
# If the user has elected to override the Locked clockClasses, then it is necessary
|
||||
# to ignore the timeTraceable property and define the lock state based only on the
|
||||
# configured clockClasses.
|
||||
if (ptp4l_clock_class_locked == constants.CLOCK_CLASS_LOCKED_LIST
|
||||
and result[constants.TIME_TRACEABLE] != constants.TIME_IS_TRACEABLE1
|
||||
and result[constants.TIME_TRACEABLE].lower != constants.TIME_IS_TRACEABLE2):
|
||||
sync_state = constants.FREERUN_PHC_STATE
|
||||
if (result[constants.GM_CLOCK_CLASS] not in
|
||||
[constants.CLOCK_CLASS_VALUE6]):
|
||||
if (result[constants.GM_CLOCK_CLASS] not in ptp4l_clock_class_locked):
|
||||
sync_state = constants.FREERUN_PHC_STATE
|
||||
return sync_state
|
||||
|
||||
|
@ -49,14 +49,14 @@ class OsClockMonitorTests(unittest.TestCase):
|
||||
"/ptpinstance/phc2sys-phc "
|
||||
"-inst1.conf\x00-w\x00-s\x00ens1f0\x00").return_value)
|
||||
mo.side_effect = handlers
|
||||
self.assertEqual(self.clockmon._check_command_line_interface("/var/run/"), "ens1f0")
|
||||
self.assertEqual(self.clockmon._get_phc2sys_command_line_option("/var/run/", "-s"), "ens1f0")
|
||||
|
||||
# Failure path - no interface in command line params
|
||||
handlers = (mo.return_value,
|
||||
mock_open(read_data="/usr/sbin/phc2sys\x00-f\x00/etc/ptpinstance/phc2sys-phc"
|
||||
"-inst1.conf\x00-w\x00").return_value)
|
||||
mo.side_effect = handlers
|
||||
self.assertEqual(self.clockmon._check_command_line_interface("/var/run/"), None)
|
||||
self.assertEqual(self.clockmon._get_phc2sys_command_line_option("/var/run/", "-s"), None)
|
||||
|
||||
@mock.patch('trackingfunctionsdk.common.helpers.os_clock_monitor.glob',
|
||||
side_effect=[['/hostsys/class/net/ens1f0/device/ptp/ptp0'],
|
||||
|
@ -26,6 +26,8 @@ TIME_IS_TRACEABLE1 = "1"
|
||||
TIME_IS_TRACEABLE2 = "true"
|
||||
GM_IS_PRESENT = "true"
|
||||
CLOCK_CLASS_VALUE6 = "6"
|
||||
CLOCK_CLASS_VALUE7 = "7"
|
||||
CLOCK_CLASS_LOCKED_LIST = [CLOCK_CLASS_VALUE6, CLOCK_CLASS_VALUE7]
|
||||
|
||||
if path.exists('/ptp/linuxptp/ptpinstance'):
|
||||
LINUXPTP_CONFIG_PATH = '/ptp/linuxptp/ptpinstance/'
|
||||
|
@ -42,6 +42,15 @@ phc2sys_com_socket = os.environ.get('PHC2SYS_COM_SOCKET', "false")
|
||||
phc2sys_config_file_path = '%sphc2sys-%s.conf' % (constants.LINUXPTP_CONFIG_PATH,
|
||||
phc2sys_service_name)
|
||||
|
||||
ptp4l_clock_class_locked = constants.CLOCK_CLASS_LOCKED_LIST
|
||||
try:
|
||||
tmp = os.environ.get('PTP4L_CLOCK_CLASS_LOCKED_LIST', ','.join(ptp4l_clock_class_locked))
|
||||
ptp4l_clock_class_locked = sorted([str(int(e)) for e in tmp.split(',')])
|
||||
except:
|
||||
LOG.error('Unable to convert PTP4L_CLOCK_CLASS_LOCKED_LIST to a list of integers,'
|
||||
' using the default.')
|
||||
|
||||
|
||||
# run subprocess and returns out, err, errcode
|
||||
def run_shell2(dir, ctx, args):
|
||||
cwd = os.getcwd()
|
||||
@ -129,11 +138,16 @@ def check_results(result, total_ptp_keywords, port_count):
|
||||
break
|
||||
else:
|
||||
sync_state = constants.FREERUN_PHC_STATE
|
||||
if (result[constants.TIME_TRACEABLE] != constants.TIME_IS_TRACEABLE1
|
||||
|
||||
# We can only expect timeTraceable=1 to be set when the clockClass list is the default.
|
||||
# If the user has elected to override the Locked clockClasses, then it is necessary
|
||||
# to ignore the timeTraceable property and define the lock state based only on the
|
||||
# configured clockClasses.
|
||||
if (ptp4l_clock_class_locked == constants.CLOCK_CLASS_LOCKED_LIST
|
||||
and result[constants.TIME_TRACEABLE] != constants.TIME_IS_TRACEABLE1
|
||||
and result[constants.TIME_TRACEABLE].lower != constants.TIME_IS_TRACEABLE2):
|
||||
sync_state = constants.FREERUN_PHC_STATE
|
||||
if (result[constants.GM_CLOCK_CLASS] not in
|
||||
[constants.CLOCK_CLASS_VALUE6]):
|
||||
if (result[constants.GM_CLOCK_CLASS] not in ptp4l_clock_class_locked):
|
||||
sync_state = constants.FREERUN_PHC_STATE
|
||||
return sync_state
|
||||
|
||||
|
@ -134,8 +134,14 @@ spec:
|
||||
value: "registration.{{.Values.global.namespace}}.svc.cluster.local"
|
||||
- name: PTP4L_SERVICE_NAME
|
||||
value: "{{ .Values.ptptrackingv2.ptp4lServiceName }}"
|
||||
- name: PTP4L_CLOCK_CLASS_LOCKED_LIST
|
||||
value: "{{ .Values.ptptrackingv2.ptp4lClockClassLockedList }}"
|
||||
- name: PTP4L_UTC_OFFSET
|
||||
value: "{{ .Values.ptptrackingv2.ptp4lUtcOffset }}"
|
||||
- name: PHC2SYS_SERVICE_NAME
|
||||
value: "{{ .Values.ptptrackingv2.phc2sysServiceName }}"
|
||||
- name: PHC2SYS_TOLERANCE_THRESHOLD
|
||||
value: "{{ .Values.ptptrackingv2.phc2sysToleranceThreshold }}"
|
||||
- name: TS2PHC_SERVICE_NAME
|
||||
value: "{{ .Values.ptptrackingv2.ts2phcServiceName }}"
|
||||
- name: LOGGING_LEVEL
|
||||
@ -217,6 +223,8 @@ spec:
|
||||
value: "registration.{{.Values.global.namespace}}.svc.cluster.local"
|
||||
- name: PTP4L_SERVICE_NAME
|
||||
value: "{{ .Values.ptptracking.ptp4lServiceName }}"
|
||||
- name: PTP4L_CLOCK_CLASS_LOCKED_LIST
|
||||
value: "{{ .Values.ptptracking.ptp4lClockClassLockedList }}"
|
||||
- name: PHC2SYS_SERVICE_NAME
|
||||
value: "{{ .Values.ptptracking.phc2sysServiceName }}"
|
||||
- name: PHC2SYS_COM_SOCKET
|
||||
|
@ -70,6 +70,7 @@ ptptracking:
|
||||
imagePullSecrets: default-registry-key
|
||||
ptp4lSocket: /var/run/ptp4l-ptp4l-legacy
|
||||
ptp4lServiceName: ptp4l-legacy
|
||||
ptp4lClockClassLockedList: "6,7"
|
||||
phc2sysServiceName: phc2sys-legacy
|
||||
phc2sysComSocket: False
|
||||
logging_level: INFO
|
||||
@ -87,7 +88,9 @@ ptptrackingv2:
|
||||
imagePullSecrets: default-registry-key
|
||||
ptp4lSocket: /var/run/ptp4l-ptp4l-legacy
|
||||
ptp4lServiceName: True
|
||||
ptp4lClockClassLockedList: "6,7"
|
||||
phc2sysServiceName: True
|
||||
phc2sysToleranceThreshold: 1000
|
||||
ts2phcServiceName: True
|
||||
log_level: INFO
|
||||
image:
|
||||
|
Loading…
x
Reference in New Issue
Block a user