621 lines
23 KiB
Diff
621 lines
23 KiB
Diff
From 15d2b2fb568df2c1a77cfb2baa703ae9f3da0f30 Mon Sep 17 00:00:00 2001
|
|
From: Vendula Poncova <vponcova@redhat.com>
|
|
Date: Fri, 3 Jul 2020 13:38:10 +0200
|
|
Subject: [PATCH] Use the structure for time sources in GUI
|
|
|
|
Modify GUI to work with TimeSourceData instead of strings.
|
|
---
|
|
pyanaconda/ui/gui/spokes/datetime_spoke.glade | 4 +
|
|
pyanaconda/ui/gui/spokes/datetime_spoke.py | 385 +++++++++---------
|
|
2 files changed, 187 insertions(+), 202 deletions(-)
|
|
|
|
diff --git a/pyanaconda/ui/gui/spokes/datetime_spoke.glade b/pyanaconda/ui/gui/spokes/datetime_spoke.glade
|
|
index 37c7c6edc0..49e33776f5 100644
|
|
--- a/pyanaconda/ui/gui/spokes/datetime_spoke.glade
|
|
+++ b/pyanaconda/ui/gui/spokes/datetime_spoke.glade
|
|
@@ -87,6 +87,8 @@
|
|
<column type="gint"/>
|
|
<!-- column-name use -->
|
|
<column type="gboolean"/>
|
|
+ <!-- column-name object -->
|
|
+ <column type="PyObject"/>
|
|
</columns>
|
|
</object>
|
|
<object class="GtkDialog" id="ntpConfigDialog">
|
|
@@ -242,6 +244,8 @@
|
|
<object class="GtkCellRendererText" id="hostnameRenderer">
|
|
<property name="editable">True</property>
|
|
<signal name="edited" handler="on_server_edited" swapped="no"/>
|
|
+ <signal name="editing-started" handler="on_server_editing_started" swapped="no"/>
|
|
+ <signal name="editing-canceled" handler="on_server_editing_canceled" swapped="no"/>
|
|
</object>
|
|
<attributes>
|
|
<attribute name="text">0</attribute>
|
|
diff --git a/pyanaconda/ui/gui/spokes/datetime_spoke.py b/pyanaconda/ui/gui/spokes/datetime_spoke.py
|
|
index 00b1bd9d56..ea121e7e4d 100644
|
|
--- a/pyanaconda/ui/gui/spokes/datetime_spoke.py
|
|
+++ b/pyanaconda/ui/gui/spokes/datetime_spoke.py
|
|
@@ -16,47 +16,48 @@
|
|
# License and may only be used or replicated with the express permission of
|
|
# Red Hat, Inc.
|
|
#
|
|
+import datetime
|
|
+import re
|
|
+import time
|
|
+import locale as locale_mod
|
|
+import functools
|
|
+import copy
|
|
|
|
+from pyanaconda import isys
|
|
+from pyanaconda import network
|
|
+from pyanaconda import ntp
|
|
+from pyanaconda import flags
|
|
from pyanaconda.anaconda_loggers import get_module_logger
|
|
-log = get_module_logger(__name__)
|
|
-
|
|
-import gi
|
|
-gi.require_version("Gdk", "3.0")
|
|
-gi.require_version("Gtk", "3.0")
|
|
-gi.require_version("TimezoneMap", "1.0")
|
|
-
|
|
-from gi.repository import Gdk, Gtk, TimezoneMap
|
|
-
|
|
+from pyanaconda.core import util, constants
|
|
+from pyanaconda.core.async_utils import async_action_wait, async_action_nowait
|
|
+from pyanaconda.core.configuration.anaconda import conf
|
|
+from pyanaconda.core.constants import TIME_SOURCE_POOL, TIME_SOURCE_SERVER
|
|
+from pyanaconda.core.i18n import _, CN_
|
|
+from pyanaconda.core.timer import Timer
|
|
+from pyanaconda.localization import get_xlated_timezone, resolve_date_format
|
|
+from pyanaconda.modules.common.structures.timezone import TimeSourceData
|
|
+from pyanaconda.modules.common.constants.services import TIMEZONE, NETWORK
|
|
+from pyanaconda.ntp import NTPServerStatusCache
|
|
from pyanaconda.ui.communication import hubQ
|
|
from pyanaconda.ui.common import FirstbootSpokeMixIn
|
|
from pyanaconda.ui.gui import GUIObject
|
|
from pyanaconda.ui.gui.spokes import NormalSpoke
|
|
from pyanaconda.ui.categories.localization import LocalizationCategory
|
|
-from pyanaconda.ui.gui.utils import gtk_call_once, override_cell_property
|
|
+from pyanaconda.ui.gui.utils import override_cell_property
|
|
from pyanaconda.ui.gui.utils import blockedHandler
|
|
from pyanaconda.ui.gui.helpers import GUIDialogInputCheckHandler
|
|
from pyanaconda.ui.helpers import InputCheck
|
|
-
|
|
-from pyanaconda.core import util, constants
|
|
-from pyanaconda.core.configuration.anaconda import conf
|
|
-from pyanaconda import isys
|
|
-from pyanaconda import network
|
|
-from pyanaconda import ntp
|
|
-from pyanaconda import flags
|
|
-from pyanaconda.modules.common.constants.services import TIMEZONE, NETWORK
|
|
-from pyanaconda.threading import threadMgr, AnacondaThread
|
|
-from pyanaconda.core.i18n import _, CN_
|
|
-from pyanaconda.core.async_utils import async_action_wait, async_action_nowait
|
|
from pyanaconda.timezone import NTP_SERVICE, get_all_regions_and_timezones, get_timezone, is_valid_timezone
|
|
-from pyanaconda.localization import get_xlated_timezone, resolve_date_format
|
|
-from pyanaconda.core.timer import Timer
|
|
+from pyanaconda.threading import threadMgr, AnacondaThread
|
|
|
|
-import datetime
|
|
-import re
|
|
-import threading
|
|
-import time
|
|
-import locale as locale_mod
|
|
-import functools
|
|
+import gi
|
|
+gi.require_version("Gdk", "3.0")
|
|
+gi.require_version("Gtk", "3.0")
|
|
+gi.require_version("TimezoneMap", "1.0")
|
|
+
|
|
+from gi.repository import Gdk, Gtk, TimezoneMap
|
|
+
|
|
+log = get_module_logger(__name__)
|
|
|
|
__all__ = ["DatetimeSpoke"]
|
|
|
|
@@ -64,6 +65,7 @@
|
|
SERVER_POOL = 1
|
|
SERVER_WORKING = 2
|
|
SERVER_USE = 3
|
|
+SERVER_OBJECT = 4
|
|
|
|
DEFAULT_TZ = "Asia/Shanghai"
|
|
|
|
@@ -156,97 +158,49 @@ def _new_date_field_box(store):
|
|
return (box, combo, suffix_label)
|
|
|
|
|
|
-class NTPconfigDialog(GUIObject, GUIDialogInputCheckHandler):
|
|
+class NTPConfigDialog(GUIObject, GUIDialogInputCheckHandler):
|
|
builderObjects = ["ntpConfigDialog", "addImage", "serversStore"]
|
|
mainWidgetName = "ntpConfigDialog"
|
|
uiFile = "spokes/datetime_spoke.glade"
|
|
|
|
- def __init__(self, data, timezone_module):
|
|
+ def __init__(self, data, servers, states):
|
|
GUIObject.__init__(self, data)
|
|
+ self._servers = servers
|
|
+ self._active_server = None
|
|
+ self._states = states
|
|
|
|
# Use GUIDIalogInputCheckHandler to manipulate the sensitivity of the
|
|
# add button, and check for valid input in on_entry_activated
|
|
add_button = self.builder.get_object("addButton")
|
|
GUIDialogInputCheckHandler.__init__(self, add_button)
|
|
|
|
- #epoch is increased when serversStore is repopulated
|
|
- self._epoch = 0
|
|
- self._epoch_lock = threading.Lock()
|
|
- self._timezone_module = timezone_module
|
|
-
|
|
- @property
|
|
- def working_server(self):
|
|
- for row in self._serversStore:
|
|
- if row[SERVER_WORKING] == constants.NTP_SERVER_OK and row[SERVER_USE]:
|
|
- #server is checked and working
|
|
- return row[SERVER_HOSTNAME]
|
|
-
|
|
- return None
|
|
-
|
|
- @property
|
|
- def pools_servers(self):
|
|
- pools = list()
|
|
- servers = list()
|
|
-
|
|
- for used_row in (row for row in self._serversStore if row[SERVER_USE]):
|
|
- if used_row[SERVER_POOL]:
|
|
- pools.append(used_row[SERVER_HOSTNAME])
|
|
- else:
|
|
- servers.append(used_row[SERVER_HOSTNAME])
|
|
-
|
|
- return (pools, servers)
|
|
-
|
|
- def _render_working(self, column, renderer, model, itr, user_data=None):
|
|
- value = model[itr][SERVER_WORKING]
|
|
-
|
|
- if value == constants.NTP_SERVER_QUERY:
|
|
- return "dialog-question"
|
|
- elif value == constants.NTP_SERVER_OK:
|
|
- return "emblem-default"
|
|
- else:
|
|
- return "dialog-error"
|
|
-
|
|
- def initialize(self):
|
|
self.window.set_size_request(500, 400)
|
|
|
|
- workingColumn = self.builder.get_object("workingColumn")
|
|
- workingRenderer = self.builder.get_object("workingRenderer")
|
|
- override_cell_property(workingColumn, workingRenderer, "icon-name",
|
|
- self._render_working)
|
|
+ working_column = self.builder.get_object("workingColumn")
|
|
+ working_renderer = self.builder.get_object("workingRenderer")
|
|
+ override_cell_property(working_column, working_renderer, "icon-name", self._render_working)
|
|
|
|
self._serverEntry = self.builder.get_object("serverEntry")
|
|
self._serversStore = self.builder.get_object("serversStore")
|
|
-
|
|
self._addButton = self.builder.get_object("addButton")
|
|
-
|
|
self._poolCheckButton = self.builder.get_object("poolCheckButton")
|
|
|
|
- # Validate the server entry box
|
|
- self._serverCheck = self.add_check(self._serverEntry, self._validateServer)
|
|
+ self._serverCheck = self.add_check(self._serverEntry, self._validate_server)
|
|
self._serverCheck.update_check_status()
|
|
|
|
- self._initialize_store_from_config()
|
|
-
|
|
- def _initialize_store_from_config(self):
|
|
- self._serversStore.clear()
|
|
+ self._update_timer = Timer()
|
|
|
|
- kickstart_ntp_servers = self._timezone_module.NTPServers
|
|
+ def _render_working(self, column, renderer, model, itr, user_data=None):
|
|
+ value = self._serversStore[itr][SERVER_WORKING]
|
|
|
|
- if kickstart_ntp_servers:
|
|
- pools, servers = ntp.internal_to_pools_and_servers(kickstart_ntp_servers)
|
|
+ if value == constants.NTP_SERVER_QUERY:
|
|
+ return "dialog-question"
|
|
+ elif value == constants.NTP_SERVER_OK:
|
|
+ return "emblem-default"
|
|
else:
|
|
- try:
|
|
- pools, servers = ntp.get_servers_from_config()
|
|
- except ntp.NTPconfigError:
|
|
- log.warning("Failed to load NTP servers configuration")
|
|
- return
|
|
-
|
|
- for pool in pools:
|
|
- self._add_server(pool, True)
|
|
- for server in servers:
|
|
- self._add_server(server, False)
|
|
+ return "dialog-error"
|
|
|
|
- def _validateServer(self, inputcheck):
|
|
+ def _validate_server(self, inputcheck):
|
|
server = self.get_input(inputcheck.input_obj)
|
|
|
|
# If not set, fail the check to keep the button insensitive, but don't
|
|
@@ -261,108 +215,97 @@ def _validateServer(self, inputcheck):
|
|
return InputCheck.CHECK_OK
|
|
|
|
def refresh(self):
|
|
- self._initialize_store_from_config()
|
|
- self._serverEntry.grab_focus()
|
|
+ # Update the store.
|
|
+ self._serversStore.clear()
|
|
|
|
- def refresh_servers_state(self):
|
|
- itr = self._serversStore.get_iter_first()
|
|
- while itr:
|
|
- self._refresh_server_working(itr)
|
|
- itr = self._serversStore.iter_next(itr)
|
|
+ for server in self._servers:
|
|
+ self._add_row(server)
|
|
+
|
|
+ # Start to update the status.
|
|
+ self._update_timer.timeout_sec(1, self._update_rows)
|
|
+
|
|
+ # Focus on the server entry.
|
|
+ self._serverEntry.grab_focus()
|
|
|
|
def run(self):
|
|
self.window.show()
|
|
rc = self.window.run()
|
|
self.window.hide()
|
|
|
|
- #OK clicked
|
|
+ # OK clicked
|
|
if rc == 1:
|
|
- new_pools, new_servers = self.pools_servers
|
|
+ # Remove servers.
|
|
+ for row in self._serversStore:
|
|
+ if not row[SERVER_USE]:
|
|
+ server = row[SERVER_OBJECT]
|
|
+ self._servers.remove(server)
|
|
|
|
+ # Restart the NTP service.
|
|
if conf.system.can_set_time_synchronization:
|
|
- ntp.save_servers_to_config(new_pools, new_servers)
|
|
+ ntp.save_servers_to_config(self._servers)
|
|
util.restart_service(NTP_SERVICE)
|
|
|
|
- #Cancel clicked, window destroyed...
|
|
- else:
|
|
- self._epoch_lock.acquire()
|
|
- self._epoch += 1
|
|
- self._epoch_lock.release()
|
|
-
|
|
return rc
|
|
|
|
- def _set_server_ok_nok(self, itr, epoch_started):
|
|
- """
|
|
- If the server is working, set its data to NTP_SERVER_OK, otherwise set its
|
|
- data to NTP_SERVER_NOK.
|
|
-
|
|
- :param itr: iterator of the $server's row in the self._serversStore
|
|
+ def _add_row(self, server):
|
|
+ """Add a new row for the given NTP server.
|
|
|
|
+ :param server: an NTP server
|
|
+ :type server: an instance of TimeSourceData
|
|
"""
|
|
+ itr = self._serversStore.append([
|
|
+ "",
|
|
+ False,
|
|
+ constants.NTP_SERVER_QUERY,
|
|
+ True,
|
|
+ server
|
|
+ ])
|
|
+
|
|
+ self._refresh_row(itr)
|
|
+
|
|
+ def _refresh_row(self, itr):
|
|
+ """Refresh the given row."""
|
|
+ server = self._serversStore[itr][SERVER_OBJECT]
|
|
+ self._serversStore.set_value(itr, SERVER_HOSTNAME, server.hostname)
|
|
+ self._serversStore.set_value(itr, SERVER_POOL, server.type == TIME_SOURCE_POOL)
|
|
+
|
|
+ def _update_rows(self):
|
|
+ """Periodically update the status of all rows.
|
|
+
|
|
+ :return: True to repeat, otherwise False
|
|
+ """
|
|
+ for row in self._serversStore:
|
|
+ server = row[SERVER_OBJECT]
|
|
|
|
- @async_action_nowait
|
|
- def set_store_value(arg_tuple):
|
|
- """
|
|
- We need a function for this, because this way it can be added to
|
|
- the MainLoop with thread-safe async_action_nowait (but only with one
|
|
- argument).
|
|
-
|
|
- :param arg_tuple: (store, itr, column, value)
|
|
-
|
|
- """
|
|
-
|
|
- (store, itr, column, value) = arg_tuple
|
|
- store.set_value(itr, column, value)
|
|
-
|
|
- orig_hostname = self._serversStore[itr][SERVER_HOSTNAME]
|
|
- server_working = ntp.ntp_server_working(self._serversStore[itr][SERVER_HOSTNAME])
|
|
-
|
|
- #do not let dialog change epoch while we are modifying data
|
|
- self._epoch_lock.acquire()
|
|
-
|
|
- #check if we are in the same epoch as the dialog (and the serversStore)
|
|
- #and if the server wasn't changed meanwhile
|
|
- if epoch_started == self._epoch:
|
|
- actual_hostname = self._serversStore[itr][SERVER_HOSTNAME]
|
|
+ if server is self._active_server:
|
|
+ continue
|
|
|
|
- if orig_hostname == actual_hostname:
|
|
- if server_working:
|
|
- set_store_value((self._serversStore,
|
|
- itr, SERVER_WORKING, constants.NTP_SERVER_OK))
|
|
- else:
|
|
- set_store_value((self._serversStore,
|
|
- itr, SERVER_WORKING, constants.NTP_SERVER_NOK))
|
|
- self._epoch_lock.release()
|
|
+ status = self._states.get_status(server)
|
|
+ row[SERVER_WORKING] = status
|
|
|
|
- @async_action_nowait
|
|
- def _refresh_server_working(self, itr):
|
|
- """ Runs a new thread with _set_server_ok_nok(itr) as a taget. """
|
|
-
|
|
- self._serversStore.set_value(itr, SERVER_WORKING, constants.NTP_SERVER_QUERY)
|
|
- threadMgr.add(AnacondaThread(prefix=constants.THREAD_NTP_SERVER_CHECK,
|
|
- target=self._set_server_ok_nok,
|
|
- args=(itr, self._epoch)))
|
|
+ return True
|
|
|
|
- def _add_server(self, server, pool=False):
|
|
- """
|
|
- Checks if a given server is a valid hostname and if yes, adds it
|
|
- to the list of servers.
|
|
+ def on_entry_activated(self, entry, *args):
|
|
+ # Check that the input check has passed
|
|
+ if self._serverCheck.check_status != InputCheck.CHECK_OK:
|
|
+ return
|
|
|
|
- :param server: string containing hostname
|
|
+ server = TimeSourceData()
|
|
|
|
- """
|
|
+ if self._poolCheckButton.get_active():
|
|
+ server.type = TIME_SOURCE_POOL
|
|
+ else:
|
|
+ server.type = TIME_SOURCE_SERVER
|
|
|
|
- itr = self._serversStore.append([server, pool, constants.NTP_SERVER_QUERY, True])
|
|
+ server.hostname = entry.get_text()
|
|
+ server.options = ["iburst"]
|
|
|
|
- #do not block UI while starting thread (may take some time)
|
|
- self._refresh_server_working(itr)
|
|
+ self._servers.append(server)
|
|
+ self._states.check_status(server)
|
|
+ self._add_row(server)
|
|
|
|
- def on_entry_activated(self, entry, *args):
|
|
- # Check that the input check has passed
|
|
- if self._serverCheck.check_status == InputCheck.CHECK_OK:
|
|
- self._add_server(entry.get_text(), self._poolCheckButton.get_active())
|
|
- entry.set_text("")
|
|
- self._poolCheckButton.set_active(False)
|
|
+ entry.set_text("")
|
|
+ self._poolCheckButton.set_active(False)
|
|
|
|
def on_add_clicked(self, *args):
|
|
self._serverEntry.emit("activate")
|
|
@@ -370,16 +313,29 @@ def on_add_clicked(self, *args):
|
|
def on_use_server_toggled(self, renderer, path, *args):
|
|
itr = self._serversStore.get_iter(path)
|
|
old_value = self._serversStore[itr][SERVER_USE]
|
|
-
|
|
self._serversStore.set_value(itr, SERVER_USE, not old_value)
|
|
|
|
def on_pool_toggled(self, renderer, path, *args):
|
|
itr = self._serversStore.get_iter(path)
|
|
- old_value = self._serversStore[itr][SERVER_POOL]
|
|
+ server = self._serversStore[itr][SERVER_OBJECT]
|
|
+
|
|
+ if server.type == TIME_SOURCE_SERVER:
|
|
+ server.type = TIME_SOURCE_POOL
|
|
+ else:
|
|
+ server.type = TIME_SOURCE_SERVER
|
|
+
|
|
+ self._refresh_row(itr)
|
|
+
|
|
+ def on_server_editing_started(self, renderer, editable, path):
|
|
+ itr = self._serversStore.get_iter(path)
|
|
+ self._active_server = self._serversStore[itr][SERVER_OBJECT]
|
|
|
|
- self._serversStore.set_value(itr, SERVER_POOL, not old_value)
|
|
+ def on_server_editing_canceled(self, renderer):
|
|
+ self._active_server = None
|
|
|
|
def on_server_edited(self, renderer, path, new_text, *args):
|
|
+ self._active_server = None
|
|
+
|
|
if not path:
|
|
return
|
|
|
|
@@ -389,14 +345,14 @@ def on_server_edited(self, renderer, path, new_text, *args):
|
|
return
|
|
|
|
itr = self._serversStore.get_iter(path)
|
|
+ server = self._serversStore[itr][SERVER_OBJECT]
|
|
|
|
- if self._serversStore[itr][SERVER_HOSTNAME] == new_text:
|
|
+ if server.hostname == new_text:
|
|
return
|
|
|
|
- self._serversStore.set_value(itr, SERVER_HOSTNAME, new_text)
|
|
- self._serversStore.set_value(itr, SERVER_WORKING, constants.NTP_SERVER_QUERY)
|
|
-
|
|
- self._refresh_server_working(itr)
|
|
+ server.hostname = new_text
|
|
+ self._states.check_status(server)
|
|
+ self._refresh_row(itr)
|
|
|
|
|
|
class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
|
|
@@ -440,6 +396,9 @@ def __init__(self, *args):
|
|
self._timezone_module = TIMEZONE.get_proxy()
|
|
self._network_module = NETWORK.get_proxy()
|
|
|
|
+ self._ntp_servers = []
|
|
+ self._ntp_servers_states = NTPServerStatusCache()
|
|
+
|
|
def initialize(self):
|
|
NormalSpoke.initialize(self)
|
|
self.initialize_start()
|
|
@@ -512,9 +471,6 @@ def initialize(self):
|
|
if not conf.system.can_set_system_clock:
|
|
self._hide_date_time_setting()
|
|
|
|
- self._config_dialog = NTPconfigDialog(self.data, self._timezone_module)
|
|
- self._config_dialog.initialize()
|
|
-
|
|
threadMgr.add(AnacondaThread(name=constants.THREAD_DATE_TIME,
|
|
target=self._initialize))
|
|
|
|
@@ -634,12 +590,27 @@ def refresh(self):
|
|
|
|
self._update_datetime()
|
|
|
|
+ # update the ntp configuration
|
|
+ self._ntp_servers = TimeSourceData.from_structure_list(
|
|
+ self._timezone_module.TimeSources
|
|
+ )
|
|
+
|
|
+ if not self._ntp_servers:
|
|
+ try:
|
|
+ self._ntp_servers = ntp.get_servers_from_config()
|
|
+ except ntp.NTPconfigError:
|
|
+ log.warning("Failed to load NTP servers configuration")
|
|
+
|
|
+ self._ntp_servers_states = NTPServerStatusCache()
|
|
has_active_network = self._network_module.Connected
|
|
+
|
|
if not has_active_network:
|
|
self._show_no_network_warning()
|
|
else:
|
|
self.clear_info()
|
|
- gtk_call_once(self._config_dialog.refresh_servers_state)
|
|
+
|
|
+ for server in self._ntp_servers:
|
|
+ self._ntp_servers_states.check_status(server)
|
|
|
|
if conf.system.can_set_time_synchronization:
|
|
ntp_working = has_active_network and util.service_running(NTP_SERVICE)
|
|
@@ -867,13 +838,10 @@ def _set_combo_selection(self, combo, item):
|
|
return False
|
|
|
|
def _get_combo_selection(self, combo):
|
|
- """
|
|
- Get the selected item of the combobox.
|
|
+ """Get the selected item of the combobox.
|
|
|
|
:return: selected item or None
|
|
-
|
|
"""
|
|
-
|
|
model = combo.get_model()
|
|
itr = combo.get_active_iter()
|
|
if not itr or not model:
|
|
@@ -946,9 +914,7 @@ def on_updown_ampm_clicked(self, *args):
|
|
def on_region_changed(self, combo, *args):
|
|
"""
|
|
:see: on_city_changed
|
|
-
|
|
"""
|
|
-
|
|
region = self._get_active_region()
|
|
|
|
if not region or region == self._old_region:
|
|
@@ -974,9 +940,7 @@ def on_city_changed(self, combo, *args):
|
|
hit etc.; 'London' chosen in the expanded combobox => update timezone
|
|
map and do all necessary actions). Fortunately when entry is being
|
|
edited, self._get_active_city returns None.
|
|
-
|
|
"""
|
|
-
|
|
timezone = None
|
|
|
|
region = self._get_active_region()
|
|
@@ -1107,8 +1071,17 @@ def _set_date_time_setting_sensitive(self, sensitive):
|
|
footer_alignment = self.builder.get_object("footerAlignment")
|
|
footer_alignment.set_sensitive(sensitive)
|
|
|
|
+ def _get_working_server(self):
|
|
+ """Get a working NTP server."""
|
|
+ for server in self._ntp_servers:
|
|
+ status = self._ntp_servers_states.get_status(server)
|
|
+ if status == constants.NTP_SERVER_OK:
|
|
+ return server
|
|
+
|
|
+ return None
|
|
+
|
|
def _show_no_network_warning(self):
|
|
- self.set_warning(_("You need to set up networking first if you "\
|
|
+ self.set_warning(_("You need to set up networking first if you "
|
|
"want to use NTP"))
|
|
|
|
def _show_no_ntp_server_warning(self):
|
|
@@ -1127,13 +1100,13 @@ def on_ntp_switched(self, switch, *args):
|
|
return
|
|
else:
|
|
self.clear_info()
|
|
+ working_server = self._get_working_server()
|
|
|
|
- working_server = self._config_dialog.working_server
|
|
if working_server is None:
|
|
self._show_no_ntp_server_warning()
|
|
else:
|
|
- #we need a one-time sync here, because chronyd would not change
|
|
- #the time as drastically as we need
|
|
+ # We need a one-time sync here, because chronyd would
|
|
+ # not change the time as drastically as we need.
|
|
ntp.one_time_sync_async(working_server)
|
|
|
|
ret = util.start_service(NTP_SERVICE)
|
|
@@ -1161,16 +1134,24 @@ def on_ntp_switched(self, switch, *args):
|
|
self.clear_info()
|
|
|
|
def on_ntp_config_clicked(self, *args):
|
|
- self._config_dialog.refresh()
|
|
+ servers = copy.deepcopy(self._ntp_servers)
|
|
+ states = self._ntp_servers_states
|
|
|
|
- with self.main_window.enlightbox(self._config_dialog.window):
|
|
- response = self._config_dialog.run()
|
|
+ dialog = NTPConfigDialog(self.data, servers, states)
|
|
+ dialog.refresh()
|
|
+
|
|
+ with self.main_window.enlightbox(dialog.window):
|
|
+ response = dialog.run()
|
|
|
|
if response == 1:
|
|
- pools, servers = self._config_dialog.pools_servers
|
|
- self._timezone_module.SetNTPServers(ntp.pools_servers_to_internal(pools, servers))
|
|
+ self._timezone_module.SetTimeSources(
|
|
+ TimeSourceData.to_structure_list(servers)
|
|
+ )
|
|
+
|
|
+ self._ntp_servers = servers
|
|
+ working_server = self._get_working_server()
|
|
|
|
- if self._config_dialog.working_server is None:
|
|
+ if working_server is None:
|
|
self._show_no_ntp_server_warning()
|
|
else:
|
|
self.clear_info()
|
|
--
|
|
2.23.0
|