291 lines
10 KiB
Diff
291 lines
10 KiB
Diff
From a645a1b8d17310533ef2d9232855c1852558e2b8 Mon Sep 17 00:00:00 2001
|
|
From: Vendula Poncova <vponcova@redhat.com>
|
|
Date: Fri, 3 Jul 2020 12:04:04 +0200
|
|
Subject: [PATCH] Use the structure for time sources in ntp.py
|
|
|
|
Modify ntp.py to work with TimeSourceData instead of strings and clean up
|
|
its functions a little.
|
|
---
|
|
pyanaconda/ntp.py | 174 +++++++++++++++++++---------------------------
|
|
1 file changed, 73 insertions(+), 101 deletions(-)
|
|
|
|
diff --git a/pyanaconda/ntp.py b/pyanaconda/ntp.py
|
|
index 16eece65e4..1b74ac9433 100644
|
|
--- a/pyanaconda/ntp.py
|
|
+++ b/pyanaconda/ntp.py
|
|
@@ -31,6 +31,7 @@
|
|
from pyanaconda import isys
|
|
from pyanaconda.threading import threadMgr, AnacondaThread
|
|
from pyanaconda.core.constants import THREAD_SYNC_TIME_BASENAME
|
|
+from pyanaconda.modules.common.structures.timezone import TimeSourceData
|
|
|
|
NTP_CONFIG_FILE = "/etc/chrony.conf"
|
|
|
|
@@ -47,21 +48,18 @@ class NTPconfigError(Exception):
|
|
pass
|
|
|
|
|
|
-def ntp_server_working(server):
|
|
- """
|
|
- Tries to do an NTP request to the $server (timeout may take some time).
|
|
+def ntp_server_working(server_hostname):
|
|
+ """Tries to do an NTP request to the server (timeout may take some time).
|
|
|
|
- :param server: hostname or IP address of an NTP server
|
|
- :type server: string
|
|
+ :param server_hostname: a host name or an IP address of an NTP server
|
|
+ :type server_hostname: string
|
|
:return: True if the given server is reachable and working, False otherwise
|
|
:rtype: bool
|
|
-
|
|
"""
|
|
-
|
|
client = ntplib.NTPClient()
|
|
|
|
try:
|
|
- client.request(server)
|
|
+ client.request(server_hostname)
|
|
except ntplib.NTPException:
|
|
return False
|
|
# address related error
|
|
@@ -75,118 +73,89 @@ def ntp_server_working(server):
|
|
return True
|
|
|
|
|
|
-def pools_servers_to_internal(pools, servers):
|
|
- ret = []
|
|
- for pool in pools:
|
|
- ret.extend(SERVERS_PER_POOL * [pool])
|
|
- ret.extend(servers)
|
|
-
|
|
- return ret
|
|
-
|
|
-
|
|
-def internal_to_pools_and_servers(pools_servers):
|
|
- server_nums = dict()
|
|
- pools = []
|
|
- servers = []
|
|
-
|
|
- for item in pools_servers:
|
|
- server_nums[item] = server_nums.get(item, 0) + 1
|
|
-
|
|
- for item in server_nums.keys():
|
|
- if server_nums[item] >= SERVERS_PER_POOL:
|
|
- pools.extend((server_nums[item] // SERVERS_PER_POOL) * [item])
|
|
- servers.extend((server_nums[item] % SERVERS_PER_POOL) * [item])
|
|
- else:
|
|
- servers.extend(server_nums[item] * [item])
|
|
+def get_servers_from_config(conf_file_path=NTP_CONFIG_FILE):
|
|
+ """Get NTP servers from a configuration file.
|
|
|
|
- return (pools, servers)
|
|
-
|
|
-
|
|
-def get_servers_from_config(conf_file_path=NTP_CONFIG_FILE,
|
|
- srv_regexp=SRV_LINE_REGEXP):
|
|
- """
|
|
Goes through the chronyd's configuration file looking for lines starting
|
|
with 'server'.
|
|
|
|
+ :param conf_file_path: a path to the chronyd's configuration file
|
|
:return: servers found in the chronyd's configuration
|
|
- :rtype: list
|
|
-
|
|
+ :rtype: a list of TimeSourceData instances
|
|
"""
|
|
-
|
|
- pools = list()
|
|
- servers = list()
|
|
+ servers = []
|
|
|
|
try:
|
|
with open(conf_file_path, "r") as conf_file:
|
|
for line in conf_file:
|
|
- match = srv_regexp.match(line)
|
|
- if match:
|
|
- if match.group(1) == "pool":
|
|
- pools.append(match.group(2))
|
|
- else:
|
|
- servers.append(match.group(2))
|
|
+ match = SRV_LINE_REGEXP.match(line)
|
|
+
|
|
+ if not match:
|
|
+ continue
|
|
+
|
|
+ server = TimeSourceData()
|
|
+ server.type = match.group(1).upper()
|
|
+ server.hostname = match.group(2)
|
|
+ server.options = ["iburst"]
|
|
+ servers.append(server)
|
|
|
|
except IOError as ioerr:
|
|
- msg = "Cannot open config file %s for reading (%s)" % (conf_file_path,
|
|
- ioerr.strerror)
|
|
- raise NTPconfigError(msg)
|
|
+ msg = "Cannot open config file {} for reading ({})."
|
|
+ raise NTPconfigError(msg.format(conf_file_path, ioerr.strerror))
|
|
|
|
- return (pools, servers)
|
|
+ return servers
|
|
|
|
|
|
-def save_servers_to_config(pools, servers, conf_file_path=NTP_CONFIG_FILE,
|
|
- srv_regexp=SRV_LINE_REGEXP, out_file_path=None):
|
|
- """
|
|
+def save_servers_to_config(servers, conf_file_path=NTP_CONFIG_FILE, out_file_path=None):
|
|
+ """Save NTP servers to a configuration file.
|
|
+
|
|
Replaces the pools and servers defined in the chronyd's configuration file
|
|
with the given ones. If the out_file is not None, then it is used for the
|
|
resulting config.
|
|
|
|
- :type pools: iterable
|
|
- :type servers: iterable
|
|
- :param out_file_path: path to the file used for the resulting config
|
|
-
|
|
+ :param servers: a list of NTP servers and pools
|
|
+ :type servers: a list of TimeSourceData instances
|
|
+ :param conf_file_path: a path to the chronyd's configuration file
|
|
+ :param out_file_path: a path to the file used for the resulting config
|
|
"""
|
|
+ temp_path = None
|
|
|
|
try:
|
|
old_conf_file = open(conf_file_path, "r")
|
|
-
|
|
except IOError as ioerr:
|
|
- msg = "Cannot open config file %s for reading (%s)" % (conf_file_path,
|
|
- ioerr.strerror)
|
|
- raise NTPconfigError(msg)
|
|
+ msg = "Cannot open config file {} for reading ({})."
|
|
+ raise NTPconfigError(msg.format(conf_file_path, ioerr.strerror))
|
|
|
|
- try:
|
|
- if out_file_path:
|
|
+ if out_file_path:
|
|
+ try:
|
|
new_conf_file = open(out_file_path, "w")
|
|
- else:
|
|
- (fildes, temp_path) = tempfile.mkstemp()
|
|
- new_conf_file = os.fdopen(fildes, "w")
|
|
-
|
|
- except IOError as ioerr:
|
|
- if out_file_path:
|
|
- msg = "Cannot open new config file %s "\
|
|
- "for writing (%s)" % (out_file_path, ioerr.strerror)
|
|
- else:
|
|
- msg = "Cannot open temporary file %s "\
|
|
- "for writing (%s)" % (temp_path, ioerr.strerror)
|
|
-
|
|
- raise NTPconfigError(msg)
|
|
+ except IOError as ioerr:
|
|
+ msg = "Cannot open new config file {} for writing ({})."
|
|
+ raise NTPconfigError(msg.format(out_file_path, ioerr.strerror))
|
|
+ else:
|
|
+ try:
|
|
+ (fields, temp_path) = tempfile.mkstemp()
|
|
+ new_conf_file = os.fdopen(fields, "w")
|
|
+ except IOError as ioerr:
|
|
+ msg = "Cannot open temporary file {} for writing ({})."
|
|
+ raise NTPconfigError(msg.format(temp_path, ioerr.strerror))
|
|
|
|
heading = "# These servers were defined in the installation:\n"
|
|
|
|
- #write info about the origin of the following lines
|
|
+ # write info about the origin of the following lines
|
|
new_conf_file.write(heading)
|
|
|
|
- #write new servers and pools
|
|
- for pool in pools:
|
|
- new_conf_file.write("pool " + pool + " iburst\n")
|
|
-
|
|
+ # write new servers and pools
|
|
for server in servers:
|
|
- new_conf_file.write("server " + server + " iburst\n")
|
|
+ args = [server.type.lower(), server.hostname] + server.options
|
|
+ line = " ".join(args) + "\n"
|
|
+ new_conf_file.write(line)
|
|
|
|
- #copy non-server lines from the old config and skip our heading
|
|
+ new_conf_file.write("\n")
|
|
+
|
|
+ # copy non-server lines from the old config and skip our heading
|
|
for line in old_conf_file:
|
|
- if not srv_regexp.match(line) and line != heading:
|
|
+ if not SRV_LINE_REGEXP.match(line) and line != heading:
|
|
new_conf_file.write(line)
|
|
|
|
old_conf_file.close()
|
|
@@ -199,28 +168,27 @@ def save_servers_to_config(pools, servers, conf_file_path=NTP_CONFIG_FILE,
|
|
os.unlink(temp_path)
|
|
|
|
except OSError as oserr:
|
|
- msg = "Cannot replace the old config with "\
|
|
- "the new one (%s)" % (oserr.strerror)
|
|
+ msg = "Cannot replace the old config with the new one ({})."
|
|
+ raise NTPconfigError(msg.format(oserr.strerror))
|
|
|
|
- raise NTPconfigError(msg)
|
|
|
|
+def _one_time_sync(server, callback=None):
|
|
+ """Synchronize the system time with a given NTP server.
|
|
|
|
-def one_time_sync(server, callback=None):
|
|
- """
|
|
Synchronize the system time with a given NTP server. Note that this
|
|
function is blocking and will not return until the time gets synced or
|
|
querying server fails (may take some time before timeouting).
|
|
|
|
- :param server: NTP server
|
|
+ :param server: an NTP server
|
|
+ :type server: an instance of TimeSourceData
|
|
:param callback: callback function to run after sync or failure
|
|
:type callback: a function taking one boolean argument (success)
|
|
:return: True if the sync was successful, False otherwise
|
|
-
|
|
"""
|
|
|
|
client = ntplib.NTPClient()
|
|
try:
|
|
- results = client.request(server)
|
|
+ results = client.request(server.hostname)
|
|
isys.set_system_time(int(results.tx_time))
|
|
success = True
|
|
except ntplib.NTPException:
|
|
@@ -235,22 +203,26 @@ def one_time_sync(server, callback=None):
|
|
|
|
|
|
def one_time_sync_async(server, callback=None):
|
|
- """
|
|
+ """Asynchronously synchronize the system time with a given NTP server.
|
|
+
|
|
Asynchronously synchronize the system time with a given NTP server. This
|
|
function is non-blocking it starts a new thread for synchronization and
|
|
returns. Use callback argument to specify the function called when the
|
|
new thread finishes if needed.
|
|
|
|
- :param server: NTP server
|
|
+ :param server: an NTP server
|
|
+ :type server: an instance of TimeSourceData
|
|
:param callback: callback function to run after sync or failure
|
|
:type callback: a function taking one boolean argument (success)
|
|
-
|
|
"""
|
|
+ thread_name = "%s_%s" % (THREAD_SYNC_TIME_BASENAME, server.hostname)
|
|
|
|
- thread_name = "%s_%s" % (THREAD_SYNC_TIME_BASENAME, server)
|
|
+ # syncing with the same server running
|
|
if threadMgr.get(thread_name):
|
|
- #syncing with the same server running
|
|
return
|
|
|
|
- threadMgr.add(AnacondaThread(name=thread_name, target=one_time_sync,
|
|
- args=(server, callback)))
|
|
+ threadMgr.add(AnacondaThread(
|
|
+ name=thread_name,
|
|
+ target=_one_time_sync,
|
|
+ args=(server, callback)
|
|
+ ))
|
|
--
|
|
2.23.0
|