Skip to content

Commit

Permalink
Use monotonic time in Python3 to avoid timeouts during NTP changes
Browse files Browse the repository at this point in the history
Avoids authentication timeouts and session timeouts when the time jumps
forward, either by chrony (NTP) or manual time changes
  • Loading branch information
Gerald Elder-Vass committed Feb 22, 2024
1 parent 0ef1e7e commit a530366
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 10 deletions.
13 changes: 10 additions & 3 deletions XSConsoleAuth.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@

import XenAPI


if sys.version_info >= (3, 0):
getTimeStamp = time.monotonic
else:
getTimeStamp = time.time


class Auth:
instance = None

Expand Down Expand Up @@ -68,7 +75,7 @@ def IsTestMode(self):

def AuthAge(self):
if self.isAuthenticated:
retVal = time.time() - self.authTimestampSeconds
retVal = getTimeStamp() - self.authTimestampSeconds
else:
raise Exception("Cannot get age - not authenticated")
return retVal
Expand All @@ -77,7 +84,7 @@ def KeepAlive(self):
if self.isAuthenticated:
if self.AuthAge() <= State.Inst().AuthTimeoutSeconds():
# Auth still valid, so update timestamp to now
self.authTimestampSeconds = time.time()
self.authTimestampSeconds = getTimeStamp()

def LoggedInUsername(self):
if (self.isAuthenticated):
Expand Down Expand Up @@ -126,7 +133,7 @@ def ProcessLogin(self, inUsername, inPassword):
if self.testingHost is not None:
# Store password when testing only
self.loggedInPassword = inPassword
self.authTimestampSeconds = time.time()
self.authTimestampSeconds = getTimeStamp()
self.isAuthenticated = True
XSLog('User authenticated successfully')

Expand Down
21 changes: 14 additions & 7 deletions XSConsoleTerm.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
from XSConsoleRootDialogue import *
from XSConsoleState import *


if sys.version_info >= (3, 0):
getTimeStamp = time.monotonic
else:
getTimeStamp = time.time


class App:
__instance = None

Expand All @@ -53,9 +60,9 @@ def Build(self, inDirs = None):
Importer.ImportRelativeDir(dir)

def Enter(self):
startTime = time.time()
startTime = getTimeStamp()
Data.Inst().Update()
elapsedTime = time.time() - startTime
elapsedTime = getTimeStamp() - startTime
XSLog('Loaded initial xapi and system data in %.3f seconds' % elapsedTime)

doQuit = False
Expand Down Expand Up @@ -158,7 +165,7 @@ def NeedsRefresh(self):
def HandleKeypress(self, inKeypress):
handled = True
Auth.Inst().KeepAlive()
self.lastWakeSeconds = time.time()
self.lastWakeSeconds = getTimeStamp()
if self.layout.TopDialogue().HandleKey(inKeypress):
State.Inst().SaveIfRequired()
self.needsRefresh = True
Expand All @@ -180,7 +187,7 @@ def HandleKeypress(self, inKeypress):

def MainLoop(self):
doQuit= False
startSeconds = time.time()
startSeconds = getTimeStamp()
lastDataUpdateSeconds = startSeconds
lastScreenUpdateSeconds = startSeconds
lastGarbageCollectSeconds = startSeconds
Expand All @@ -193,7 +200,7 @@ def MainLoop(self):
while not doQuit:
self.needsRefresh = False
gotTestCommand = RemoteTest.Inst().Poll()
secondsNow = time.time()
secondsNow = getTimeStamp()
try:
if gotTestCommand:
gotKey = None # Prevent delay whilst waiting for a keypress
Expand All @@ -205,7 +212,7 @@ def MainLoop(self):
XSLog('Entering sleep due to inactivity - xsconsole is now blocked waiting for a keypress')
self.layout.Window(Layout.WIN_MAIN).GetKeyBlocking()
XSLog('Exiting sleep')
self.lastWakeSeconds = time.time()
self.lastWakeSeconds = getTimeStamp()
self.needsRefresh = True
Layout.Inst().PopDialogue()
else:
Expand Down Expand Up @@ -234,7 +241,7 @@ def MainLoop(self):
gotKey = None
break

secondsNow = time.time()
secondsNow = getTimeStamp()
secondsRunning = secondsNow - startSeconds

if data.host.address('') == '' or len(data.derived.managementpifs([])) == 0:
Expand Down

0 comments on commit a530366

Please sign in to comment.