Skip to content

Commit 884fb1c

Browse files
committed
CP-308543 Use xenapi to manage timezone and NTP
xenapi host.set_timezone to config the timezone of the host. host.set_ntp_mode to manage the NTP. The NTP mode mapping to xsconsole is: DHCP - dhcp Factory - default Custom - manual Disabled - none host.set_ntp_custom_servers to configure the NTP servers that used in Custom mode. Signed-off-by: Changlei Li <changlei.li@cloud.com>
1 parent 4d00b2a commit 884fb1c

3 files changed

Lines changed: 37 additions & 115 deletions

File tree

XSConsoleConstants.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Default NTP domains are <int>.[centos|xenserver].pool.ntp.org
22
CENTOS_NTP_POOL_DOMAIN = "centos.pool.ntp.org"
3-
DEFAULT_NTP_DOMAINS = [CENTOS_NTP_POOL_DOMAIN, "xenserver.pool.ntp.org"]
3+
XENSERVER_NTP_POOL_DOMAIN = "xenserver.pool.ntp.org"
4+
DEFAULT_NTP_DOMAINS = [CENTOS_NTP_POOL_DOMAIN, XENSERVER_NTP_POOL_DOMAIN]
45

56
NUM_DEFAULT_NTP_SERVERS = 4
67

7-
DEFAULT_NTP_SERVERS = ["%d.%s" % (i, CENTOS_NTP_POOL_DOMAIN) for i in range(NUM_DEFAULT_NTP_SERVERS)]
8+
DEFAULT_NTP_SERVERS = ["%d.%s" % (i, XENSERVER_NTP_POOL_DOMAIN) for i in range(NUM_DEFAULT_NTP_SERVERS)]

XSConsoleData.py

Lines changed: 14 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -570,100 +570,27 @@ def SaveToSysconfig(self):
570570
if file is not None: file.close()
571571
self.UpdateFromSysconfig()
572572

573-
def SaveToNTPConf(self):
574-
# Double-check authentication
573+
def SetNTPMode(self, inMode):
575574
Auth.Inst().AssertAuthenticated()
575+
self.RequireSession()
576+
self.session.xenapi.host.set_ntp_mode(self.host.opaqueref(), inMode)
576577

577-
try:
578-
with open("/etc/chrony.conf", "w") as confFile:
579-
for other in self.ntp.othercontents([]):
580-
confFile.write(other + "\n")
581-
for server in self.ntp.servers([]):
582-
confFile.write("server " + server + " iburst\n")
583-
finally:
584-
self.UpdateFromNTPConf()
585-
586-
# Force chronyd to update the time
587-
if self.data['ntp']['method'] != "Disabled":
588-
# Prompt chrony to update the time immediately
589-
getoutput("chronyc makestep")
590-
# Write the system time (set by the single shot NTP) to the HW clock
591-
getoutput("hwclock -w")
592-
593-
def AddDHCPNTP(self):
594-
# Double-check authentication
578+
def SetNTPManualServers(self, inServers):
595579
Auth.Inst().AssertAuthenticated()
596-
597-
oldPermissions = os.stat("/etc/dhcp/dhclient.d/chrony.sh").st_mode
598-
newPermissions = oldPermissions | (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
599-
os.chmod("/etc/dhcp/dhclient.d/chrony.sh", newPermissions)
600-
601-
interfaces = self.GetDHClientInterfaces()
602-
for interface in interfaces:
603-
ntpServer = self.GetDHCPNTPServer(interface)
604-
605-
with open("/run/chrony-dhcp/%s.sources" % interface, "w") as chronyFile:
606-
chronyFile.write("server %s iburst prefer\n" % ntpServer)
607-
608-
# Ensure chrony is enabled
609-
self.EnableService("chronyd")
610-
self.EnableService("chrony-wait")
580+
self.RequireSession()
581+
self.session.xenapi.host.set_ntp_custom_servers(self.host.opaqueref(), inServers)
611582

612583
def ResetDefaultNTPServers(self):
613584
# Double-check authentication
614585
Auth.Inst().AssertAuthenticated()
615586
Data.Inst().NTPServersSet(DEFAULT_NTP_SERVERS)
616587

617-
def GetDHClientInterfaces(self):
618-
try:
619-
leases = [filename for filename in os.listdir("/var/lib/xcp") if "leases" in filename]
620-
except OSError:
621-
return []
622-
623-
pattern = "dhclient-(.*).leases"
624-
interfaces = []
625-
for dhclientFile in leases:
626-
match = re.match(pattern, dhclientFile)
627-
if match:
628-
interfaces.append(match.group(1))
629-
630-
return interfaces
631-
632-
def GetDHCPNTPServer(self, interface):
633-
expectedLeaseFile = "/var/lib/xcp/dhclient-%s.leases" % interface
634-
if not os.path.isfile(expectedLeaseFile):
635-
return None
636-
637-
with open(expectedLeaseFile, "r") as leaseFile:
638-
data = leaseFile.read().splitlines()
639-
640-
ntpServerLines = [line for line in data if "ntp-servers" in line]
641-
642-
# Extract <ip-addr> from " option ntp-servers <ip-addr>;"
643-
try:
644-
ntpServer = ntpServerLines[-1].split()[-1][:-1]
645-
except:
646-
ntpServer = None
647-
648-
return ntpServer
649-
650-
def RemoveDHCPNTP(self):
651-
# Double-check authentication
652-
Auth.Inst().AssertAuthenticated()
653-
654-
oldPermissions = os.stat("/etc/dhcp/dhclient.d/chrony.sh").st_mode
655-
newPermissions = oldPermissions & ~(stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
656-
os.chmod("/etc/dhcp/dhclient.d/chrony.sh", newPermissions)
657-
658-
getstatusoutput("rm -f /run/chrony-dhcp/*.sources")
659-
660588
def SetTimeManually(self, date):
661589
# Double-check authentication
662590
Auth.Inst().AssertAuthenticated()
663591

664592
self.NTPServersSet([])
665-
self.RemoveDHCPNTP()
666-
self.SaveToNTPConf()
593+
self.SetNTPMode('Disabled')
667594

668595
self.DisableService("chrony-wait")
669596
self.DisableService("chronyd")
@@ -923,22 +850,9 @@ def UpdateFromTimezone(self):
923850
file.close()
924851

925852
def TimezoneSet(self, inTimezone):
926-
localtimeFile = '/etc/localtime'
927-
if os.path.isfile(localtimeFile):
928-
os.remove(localtimeFile)
929-
os.symlink(self.timezones.cities({})[inTimezone], localtimeFile)
930-
931-
file = open('/etc/timezone', 'w')
932-
file.write(inTimezone+"\n")
933-
file.close()
934-
935-
if os.path.exists('/etc/sysconfig/clock'):
936-
cfg = SimpleConfigFile()
937-
cfg.read('/etc/sysconfig/clock')
938-
cfg.info["ZONE"] = inTimezone
939-
cfg.write('/etc/sysconfig/clock')
940-
941-
time.tzset()
853+
Auth.Inst().AssertAuthenticated()
854+
self.RequireSession()
855+
self.session.xenapi.host.set_timezone(self.host.opaqueref(), inTimezone)
942856

943857
def CurrentTimeString(self):
944858
return getoutput('/bin/date -R')
@@ -1099,10 +1013,12 @@ def DisableManagement(self):
10991013
self.session = Auth.Inst().CloseSession(self.session)
11001014

11011015
def AdjustNTPForStaticNetwork(self):
1102-
self.RemoveDHCPNTP()
11031016
if not self.data['ntp']['servers']: # No NTP servers after removing DHCP
11041017
self.ResetDefaultNTPServers()
1105-
self.SaveToNTPConf()
1018+
self.SetNTPMode('Factory')
1019+
else:
1020+
self.SetNTPManualServers(self.data['ntp']['servers'])
1021+
self.SetNTPMode('Custom')
11061022

11071023
def LocalHostEnable(self):
11081024
Auth.Inst().AssertAuthenticatedOrPasswordUnset()

plugins-base/XSFeatureNTP.py

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -232,15 +232,13 @@ def HandleInitialChoice(self, inChoice): # type: (str) -> None
232232
Layout.Inst().PopDialogue()
233233
Layout.Inst().TransientBanner(Lang("Enabling DHCP NTP Server..."))
234234
data.NTPServersSet([])
235-
data.AddDHCPNTP()
236-
self.Commit(Lang("DHCP NTP Time Synchronization Enabled"))
235+
self.Commit(Lang("DHCP NTP Time Synchronization Enabled"), inChoice)
237236

238237
elif inChoice == "DEFAULT":
239238
Layout.Inst().PopDialogue()
240239
Layout.Inst().TransientBanner(Lang("Enabling Default NTP Servers..."))
241240
data.ResetDefaultNTPServers()
242-
data.RemoveDHCPNTP()
243-
self.Commit(Lang("Default NTP Time Synchronization Enabled"))
241+
self.Commit(Lang("Default NTP Time Synchronization Enabled"), inChoice)
244242

245243
elif inChoice == "MANUAL":
246244
self.ChangeState("MANUAL")
@@ -269,7 +267,7 @@ def HandleManualChoice(self, inChoice):
269267
Layout.Inst().PopDialogue()
270268
Layout.Inst().TransientBanner(Lang("Removing All NTP Servers..."))
271269
data.NTPServersSet([])
272-
self.Commit(Lang("All server entries deleted"))
270+
self.Commit(Lang("All server entries deleted"), "MANUAL")
273271

274272
except Exception as e:
275273
Layout.Inst().PushDialogue(InfoDialogue( Lang("Operation Failed"), Lang(e)))
@@ -291,7 +289,7 @@ def HandleRemoveChoice(self, inChoice):
291289

292290
del servers[inChoice]
293291
data.NTPServersSet(servers)
294-
self.Commit(Lang("NTP server %s deleted" % thisServer))
292+
self.Commit(Lang("NTP server %s deleted" % thisServer), "MANUAL")
295293
data.Update()
296294

297295
def HandleKey(self, inKey):
@@ -343,10 +341,9 @@ def HandleKeyNONE(self, inKey):
343341

344342
Layout.Inst().TransientBanner(Lang("Setting Time..."))
345343
data = Data.Inst()
346-
data.RemoveDHCPNTP()
347344
data.SetTimeManually(date)
348345

349-
self.Commit(Lang("Time Set Manually"), restartChronyd=False)
346+
self.Commit(Lang("Time Set Manually"), "NONE")
350347
except Exception as e:
351348
Layout.Inst().PushDialogue(InfoDialogue(Lang(e)))
352349

@@ -377,12 +374,11 @@ def HandleKeyADD(self, inKey):
377374
IPUtils.AssertValidNetworkName(inputValues['name'])
378375

379376
data=Data.Inst()
380-
data.RemoveDHCPNTP()
381377

382378
servers = data.ntp.servers([])
383379
servers.append(inputValues['name'])
384380
data.NTPServersSet(servers)
385-
self.Commit(Lang("NTP server")+" "+inputValues['name']+" "+Lang("added"))
381+
self.Commit(Lang("NTP server")+" "+inputValues['name']+" "+Lang("added"), "MANUAL")
386382
except Exception as e:
387383
Layout.Inst().PushDialogue(InfoDialogue(Lang(e)))
388384

@@ -395,13 +391,22 @@ def HandleKeyADD(self, inKey):
395391
def HandleKeyREMOVE(self, inKey):
396392
return self.removeMenu.HandleKey(inKey)
397393

398-
def Commit(self, inMessage, restartChronyd=True):
394+
def Commit(self, inMessage, inChoice):
399395
data=Data.Inst()
400396
try:
401-
data.SaveToNTPConf()
402-
if restartChronyd:
403-
Layout.Inst().TransientBanner(Lang("Restarting NTP daemon with new configuration..."))
404-
data.RestartService('chronyd')
397+
ntpmode_map = {
398+
"DHCP": "DHCP",
399+
"DEFAULT": "Factory",
400+
"MANUAL": "Custom",
401+
"NONE": "Disabled"
402+
}
403+
mode = ntpmode_map.get(inChoice)
404+
if mode is None:
405+
raise ValueError("Unknown NTP choice: {}".format(inChoice))
406+
if inChoice == "MANUAL":
407+
data.SetNTPManualServers(data.ntp.servers([]))
408+
409+
data.SetNTPMode(mode)
405410
Layout.Inst().PushDialogue(InfoDialogue( inMessage))
406411
except Exception as e:
407412
Layout.Inst().PushDialogue(InfoDialogue( Lang("Update failed: ")+Lang(e)))

0 commit comments

Comments
 (0)