1
0
mirror of https://github.com/dkmstr/openuds.git synced 2025-01-03 01:17:56 +03:00

Upgrading the UserServiceOpChecker to a new & clearer one

This commit is contained in:
Adolfo Gómez García 2015-11-06 12:04:44 +01:00
parent 7b85adaddf
commit 19fdcadbcd
2 changed files with 112 additions and 46 deletions

View File

@ -57,6 +57,100 @@ logger = logging.getLogger(__name__)
USERSERVICE_TAG = 'cm-'
class StateUpdater(object):
def __init__(self, userService, userServiceInstance=None):
self.userService = userService
self.userServiceInstance = userServiceInstance if userServiceInstance is not None else userService.getInstance()
def setError(self, msg=None):
self.userService.setState(State.ERROR)
self.userService.save()
if msg is not None:
log.doLog(self.userService, log.ERROR, msg, log.INTERNAL)
def save(self, newState=None):
if newState is not None:
self.userService.setState(newState)
self.userService.updateData(self.userServiceInstance)
self.userService.save()
def checkLater(self):
UserServiceOpChecker.checkLater(self.userService, self.userServiceInstance)
def run(self, state):
executor = {
State.RUNNING: self.running,
State.ERROR: self.error,
State.FINISHED: self.finish
}.get(state, self.error)
try:
executor()
except Exception as e:
self.setError('Exception: {}'.format(e))
def finish(self):
raise NotImplementedError('finish method must be overriden')
def running(self):
raise NotImplementedError('running method must be overriden')
def error(self):
self.setError(self.userServiceInstance.reasonOfError())
class UpdateFromPreparing(StateUpdater):
def finish(self):
self.userServiceInstance.finish()
osManager = self.userServiceInstance.osmanager()
state = State.REMOVABLE # By default, if not valid publication, service will be marked for removal on preparation finished
if self.userService.isValidPublication():
logger.debug('Publication is valid for {}'.format(self.userService.friendly_name))
state = State.USABLE
# and make this usable if os manager says that it is usable, else it pass to configuring state
if osManager is not None and State.isPreparing(self.userService.os_state):
logger.debug('Has valid osmanager for {}'.format(self.userService.friendly_name))
stateOs = osManager.checkState(self.userService)
# If state is finish, we need to notify the userService again that os has finished
if State.isFinished(stateOs):
state = self.userServiceInstance.notifyReadyFromOsManager('')
else:
stateOs = State.FINISHED
logger.debug('State {}, StateOS {} for {}'.format(State.toString(state), State.toString(stateOs), self.userService.friendly_name))
if State.isRuning(stateOs):
self.userService.setOsState(State.PREPARING)
else:
self.userService.setOsState(State.USABLE)
self.save(state)
def running(self):
self.checkLater()
class UpdateFromRemoving(StateUpdater):
def finish(self):
pass
def running(self):
pass
class UpdateFromCanceling(StateUpdater):
def finish(self):
self.save(State.CANCELED)
def running(self):
self.checkLater()
class UpdateFromOther(StateUpdater):
def finish(self):
self.setError('Unknown running transition from {}'.format(State.toString(self.userService.state)))
def running(self):
self.setError('Unknown running transition from {}'.format(State.toString(self.userService.state)))
class UserServiceOpChecker(DelayedTask):
def __init__(self, service):
@ -79,52 +173,18 @@ class UserServiceOpChecker(DelayedTask):
Return True if it has to continue checking, False if finished
'''
try:
prevState = userService.state
# Fills up basic data
userService.unique_id = userServiceInstance.getUniqueId() # Updates uniqueId
userService.friendly_name = userServiceInstance.getName() # And name, both methods can modify serviceInstance, so we save it later
if State.isFinished(state):
checkLater = False
userServiceInstance.finish()
if State.isPreparing(prevState):
if userServiceInstance.service().publicationType is None or userService.publication == userService.deployed_service.activePublication():
userService.setState(State.USABLE)
# and make this usable if os manager says that it is usable, else it pass to configuring state
if userServiceInstance.osmanager() is not None and userService.os_state == State.PREPARING: # If state is already "Usable", do not recheck it
stateOs = userServiceInstance.osmanager().checkState(userService)
# If state is finish, we need to notify the userService again that os has finished
if State.isFinished(stateOs):
state = userServiceInstance.notifyReadyFromOsManager('')
userService.updateData(userServiceInstance)
else:
stateOs = State.FINISHED
if State.isRuning(stateOs):
userService.setOsState(State.PREPARING)
else:
userService.setOsState(State.USABLE)
else:
# We ignore OsManager info and if userService don't belong to "current" publication, mark it as removable
userService.setState(State.REMOVABLE)
elif State.isRemoving(prevState):
if userServiceInstance.osmanager() is not None:
userServiceInstance.osmanager().release(userService)
userService.setState(State.REMOVED)
else:
# Canceled,
logger.debug("Canceled us {2}: {0}, {1}".format(prevState, State.toString(state), State.toString(userService)))
userService.setState(State.CANCELED)
userServiceInstance.osmanager().release(userService)
userService.updateData(userServiceInstance)
elif State.isErrored(state):
checkLater = False
userService.updateData(userServiceInstance)
userService.setState(State.ERROR)
else:
checkLater = True # The task is running
userService.updateData(userServiceInstance)
userService.save()
if checkLater:
UserServiceOpChecker.checkLater(userService, userServiceInstance)
updater = {
State.PREPARING: UpdateFromPreparing,
State.REMOVING: UpdateFromRemoving,
State.CANCELING: UpdateFromCanceling
}.get(userService.state, UpdateFromOther)
updater(userService, userServiceInstance).run(state)
except Exception as e:
logger.exception('Checking service state')
log.doLog(userService, log.ERROR, 'Exception: {0}'.format(e), log.INTERNAL)
@ -139,9 +199,9 @@ class UserServiceOpChecker(DelayedTask):
@param pi: Instance of Publication manager for the object
'''
# Do not add task if already exists one that updates this service
if DelayedTaskRunner.runner().checkExists(USERSERVICE_TAG + str(userService.id)):
if DelayedTaskRunner.runner().checkExists(USERSERVICE_TAG + userService.uuid):
return
DelayedTaskRunner.runner().insert(UserServiceOpChecker(userService), ci.suggestedTime, USERSERVICE_TAG + str(userService.id))
DelayedTaskRunner.runner().insert(UserServiceOpChecker(userService), ci.suggestedTime, USERSERVICE_TAG + userService.uuid)
def run(self):
logger.debug('Checking user service finished {0}'.format(self._svrId))

View File

@ -55,7 +55,7 @@ from uds.models.Util import getSqlDatetime
import logging
__updated__ = '2015-10-05'
__updated__ = '2015-11-06'
logger = logging.getLogger(__name__)
@ -463,6 +463,12 @@ class UserService(UUIDModel):
def getLoggedIP(self):
return self.getProperty('ip', '0.0.0.0')
def isValidPublication(self):
'''
Returns True if this user service does not needs an publication, or if this deployed service publication is the current one
'''
return self.deployed_service.service.getType().publicationType is None or self.publication == self.deployed_service.activePublication()
def __str__(self):
return "User service {0}, cache_level {1}, user {2}, name {3}, state {4}:{5}".format(self.id, self.cache_level, self.user, self.friendly_name,
State.toString(self.state), State.toString(self.os_state))