added idle checking

This commit is contained in:
Adolfo Gómez García 2019-12-16 12:27:00 +01:00
parent 633671d12c
commit 97e84c968a
6 changed files with 76 additions and 14 deletions

View File

@ -30,8 +30,9 @@
'''
import threading
import time
import typing
import datetime
import signal
import typing
from PyQt5.QtWidgets import QApplication, QMessageBox
from PyQt5.QtCore import QByteArray, QBuffer, QIODevice, pyqtSignal
@ -90,8 +91,11 @@ class UDSActorClient(threading.Thread):
_running: bool
_forceLogoff: bool
_qApp: UDSClientQApp
api: rest.UDSClientApi
_listener: client.HTTPServerThread
_loginInfo: typing.Optional[types.LoginResultInfoType]
_notified: bool
_sessionStartTime: datetime.datetime
api: rest.UDSClientApi
def __init__(self, qApp: QApplication):
super().__init__()
@ -101,6 +105,8 @@ class UDSActorClient(threading.Thread):
self._running = False
self._forceLogoff = False
self._listener = client.HTTPServerThread(self)
self._loginInfo = None
self._notified = False
# Capture stop signals..
logger.debug('Setting signals...')
@ -111,20 +117,66 @@ class UDSActorClient(threading.Thread):
logger.info('Stop signal received')
self.stop()
def checkDeadLine(self):
if self._userInfo is None or not self._userInfo.dead_line: # No deadline check
return
remainingTime = self._loginInfo.dead_line - (datetime.datetime.now() - self._sessionStartTime).total_seconds()
logger.debug('Remaining time: {}'.format(remainingTime))
if not self._notified and remainingTime < 300: # With five minutes, show a warning message
self._notified = True
self._showMessage('Your session will expire in less that 5 minutes. Please, save your work and disconnect.')
return
if remainingTime <= 0:
logger.debug('Session dead line reached. Logging out')
self._running = False
self._forceLogoff = True
def checkIdle(self):
if self._userInfo is None or not self._userInfo.max_idle: # No idle check
return
idleTime = platform.operations.getIdleDuration()
remainingTime = self._loginInfo.max_idle - idleTime
if remainingTime > 120: # Reset show Warning dialog if we have more than 5 minutes left
self._notified = False
return
logger.debug('User has been idle for: {}'.format(idleTime))
if not self._idleNotified and remainingTime < 120: # With two minutes, show a warning message
self._notified = True
self._showMessage('You have been idle for too long. The session will end if you don\'t resume operations.')
if remainingTime <= 0:
logger.info('User has been idle for too long, exiting from session')
self._running = False
self._forceLogoff = True
def run(self):
logger.debug('UDS Actor thread')
self._listener.start() # async listener for service
self._running = True
self._sessionStartTime = datetime.datetime.now()
time.sleep(0.4) # Wait a bit before sending login
try:
# Notify loging and mark it
self.api.login(platform.operations.getCurrentUser())
self._loginInfo = self.api.login(platform.operations.getCurrentUser())
while self._running:
time.sleep(1.1) # Sleeps between loop iterations
# Check Idle & dead line
self.checkIdle()
self.checkDeadLine()
self._loginInfo = None
self.api.logout(platform.operations.getCurrentUser())
except Exception as e:
logger.error('Error on client loop: %s', e)
@ -135,6 +187,7 @@ class UDSActorClient(threading.Thread):
QApplication.quit()
if self._forceLogoff:
time.sleep(1.3) # Wait a bit before forcing logoff
platform.operations.loggoff()
def _showMessage(self, message: str) -> None:

View File

@ -41,12 +41,12 @@ class UDSActorClientPool:
def __init__(self) -> None:
self._clientUrl = []
def _post(self, method: str, data: typing.MutableMapping[str, str]) -> typing.List[requests.Response]:
def _post(self, method: str, data: typing.MutableMapping[str, str], timeout=2) -> typing.List[requests.Response]:
removables: typing.List[str] = []
result: typing.List[typing.Any] = []
for clientUrl in self._clientUrl:
try:
result.append(requests.post(clientUrl + '/' + method, data=json.dumps(data), verify=False))
result.append(requests.post(clientUrl + '/' + method, data=json.dumps(data), verify=False, timeout=timeout))
except Exception as e:
# If cannot request to a clientUrl, remove it from list
logger.info('Could not coneect with client %s: %s. Removed from registry.', e, clientUrl)
@ -68,7 +68,7 @@ class UDSActorClientPool:
self._clientUrl = list((i for i in self._clientUrl if i != clientUrl))
def executeScript(self, script: str) -> None:
self._post('script', {'script': script})
self._post('script', {'script': script}, timeout=30)
def logout(self) -> None:
self._post('logout', {})
@ -77,11 +77,11 @@ class UDSActorClientPool:
self._post('message', {'message': message})
def ping(self) -> bool:
self._post('ping', {})
self._post('ping', {}, timeout=1)
return bool(self._clientUrl) # if no clients available
def screenshot(self) -> typing.Optional[str]: # Screenshot are returned as base64
for r in self._post('screenshot', {}):
for r in self._post('screenshot', {}, timeout=3):
try:
return r.json()['result']
except Exception:

View File

@ -86,8 +86,8 @@ class UDSActorSvc(daemon.Daemon, CommonService):
while self._isAlive:
counter += 1
try:
if counter % 10 == 0:
self.checkIpsChanged()
if counter % 5 == 0:
self.loop()
except Exception as e:
logger.error('Got exception on main loop: %s', e)
# In milliseconds, will break

View File

@ -324,6 +324,16 @@ class CommonService: # pylint: disable=too-many-instance-attributes
if platform.operations.renameComputer(name):
self.reboot()
def loop(self):
# Main common luop
# Checks if ips has changed
self.checkIpsChanged()
# Now check if every registered client is already there (if logged in OFC)
if self._loggedIn and self._clientsPool.ping():
self.logout('client_unavailable')
# ******************************************************
# Methods that can be overriden by linux & windows Actor
# ******************************************************

View File

@ -257,9 +257,8 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
# Process SENS messages, This will be a bit asyncronous (1 second delay)
pythoncom.PumpWaitingMessages() # pylint: disable=no-member
if counter >= 10: # Once every 10 seconds
counter = 0
self.checkIpsChanged()
if counter % 5 == 0: # Once every 5 seconds
self.loop()
except Exception as e:
logger.error('Got exception on main loop: %s', e)

View File

@ -62,7 +62,7 @@ def _requestActor(
if version >= '3.0.0':
js = js['result']
logger.debug('Requested %s to actor. Url=%s, Result=%s', method, url, js)
logger.debug('Requested %s to actor. Url=%s', method, url)
except Exception as e:
logger.warning('Request %s failed: %s. Check connection on destination machine: %s', method, e, url)
js = None