Skip to content

Commit

Permalink
Merge pull request #3395 from vyos/mergify/bp/sagitta/pr-3307
Browse files Browse the repository at this point in the history
ntp: T4909 rewrite NTP op mode in the new format (backport #3307)
  • Loading branch information
dmbaturin authored May 2, 2024
2 parents e019155 + e2f0643 commit 44008b1
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 2 deletions.
16 changes: 14 additions & 2 deletions op-mode-definitions/ntp.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,25 @@
<properties>
<help>Show peer status of NTP daemon</help>
</properties>
<command>${vyos_op_scripts_dir}/show_ntp.sh --sourcestats</command>
<command>${vyos_op_scripts_dir}/ntp.py show_sourcestats</command>
<children>
<node name="activity">
<properties>
<help>Report the number of servers and peers that are online and offline</help>
</properties>
<command>${vyos_op_scripts_dir}/ntp.py show_activity</command>
</node>
<node name="sources">
<properties>
<help>Show information about the current time sources being accessed</help>
</properties>
<command>${vyos_op_scripts_dir}/ntp.py show_sources</command>
</node>
<node name="system">
<properties>
<help>Show parameters about the system clock performance</help>
</properties>
<command>${vyos_op_scripts_dir}/show_ntp.sh --tracking</command>
<command>${vyos_op_scripts_dir}/ntp.py show_tracking</command>
</node>
</children>
</node>
Expand Down
164 changes: 164 additions & 0 deletions src/op_mode/ntp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
#!/usr/bin/env python3
#
# Copyright (C) 2024 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import csv
import sys
from itertools import chain

import vyos.opmode
from vyos.configquery import ConfigTreeQuery
from vyos.utils.process import cmd

def _get_raw_data(command: str) -> dict:
# Returns returns chronyc output as a dictionary

# Initialize dictionary keys to align with output of
# chrony -c. From some commands, its -c switch outputs
# more parameters, make sure to include them all below.
# See to chronyc(1) for definition of key variables
match command:
case "chronyc -c activity":
keys: list = [
'sources_online',
'sources_offline',
'sources_doing_burst_return_online',
'sources_doing_burst_return_offline',
'sources_with_unknown_address'
]

case "chronyc -c sources":
keys: list = [
'm',
's',
'name_ip_address',
'stratum',
'poll',
'reach',
'last_rx',
'last_sample_adj_offset',
'last_sample_mes_offset',
'last_sample_est_error'
]

case "chronyc -c sourcestats":
keys: list = [
'name_ip_address',
'np',
'nr',
'span',
'frequency',
'freq_skew',
'offset',
'std_dev'
]

case "chronyc -c tracking":
keys: list = [
'ref_id',
'ref_id_name',
'stratum',
'ref_time',
'system_time',
'last_offset',
'rms_offset',
'frequency',
'residual_freq',
'skew',
'root_delay',
'root_dispersion',
'update_interval',
'leap_status'
]

case _:
raise ValueError(f"Raw mode: of {command} is not implemented")

# Get -c option command line output, splitlines,
# and save comma-separated values as a flat list
output = cmd(command).splitlines()
values = csv.reader(output)
values = list(chain.from_iterable(values))

# Divide values into chunks of size keys and transpose
if len(values) > len(keys):
values = _chunk_list(values,keys)
values = zip(*values)

return dict(zip(keys, values))

def _chunk_list(in_list, n):
# Yields successive n-sized chunks from in_list
for i in range(0, len(in_list), len(n)):
yield in_list[i:i + len(n)]

def _is_configured():
# Check if ntp is configured
config = ConfigTreeQuery()
if not config.exists("service ntp"):
raise vyos.opmode.UnconfiguredSubsystem("NTP service is not enabled.")

def show_activity(raw: bool):
_is_configured()
command = f'chronyc'

if raw:
command += f" -c activity"
return _get_raw_data(command)
else:
command += f" activity"
return cmd(command)

def show_sources(raw: bool):
_is_configured()
command = f'chronyc'

if raw:
command += f" -c sources"
return _get_raw_data(command)
else:
command += f" sources -v"
return cmd(command)

def show_tracking(raw: bool):
_is_configured()
command = f'chronyc'

if raw:
command += f" -c tracking"
return _get_raw_data(command)
else:
command += f" tracking"
return cmd(command)

def show_sourcestats(raw: bool):
_is_configured()
command = f'chronyc'

if raw:
command += f" -c sourcestats"
return _get_raw_data(command)
else:
command += f" sourcestats -v"
return cmd(command)

if __name__ == '__main__':
try:
res = vyos.opmode.run(sys.modules[__name__])
if res:
print(res)
except (ValueError, vyos.opmode.Error) as e:
print(e)
sys.exit(1)

0 comments on commit 44008b1

Please sign in to comment.