From 4401985f3ca6af7ed63c8018914f93d9bf9699ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez=20Garc=C3=ADa?= Date: Thu, 12 Jan 2017 03:27:42 +0100 Subject: [PATCH] Adding constraints to cache and advancing so we can make use efficiently a predefined pool with uds & uds actor --- actors/src/udsactor/REST.py | 12 ++++++++---- actors/src/udsactor/__init__.py | 2 +- actors/src/udsactor/httpserver.py | 5 +++++ actors/src/udsactor/service.py | 10 ++++++++-- server/src/uds/REST/methods/services.py | 2 +- server/src/uds/REST/methods/services_pools.py | 17 +++++++++++++++-- .../src/uds/core/services/BasePublication.py | 3 ++- server/src/uds/core/services/BaseService.py | 5 ++++- .../src/uds/models/ServicesPoolPublication.py | 4 ++-- server/src/uds/models/UserService.py | 4 ++-- .../LinuxOsManager/LinuxOsManager.py | 19 +++++++++++-------- .../WindowsOsManager/WindowsOsManager.py | 19 +++++++++++-------- 12 files changed, 70 insertions(+), 32 deletions(-) diff --git a/actors/src/udsactor/REST.py b/actors/src/udsactor/REST.py index c71cf5f4..d7e82d82 100644 --- a/actors/src/udsactor/REST.py +++ b/actors/src/udsactor/REST.py @@ -76,7 +76,7 @@ class OsManagerError(RESTError): # Disable warnings log messages try: - import urllib3 # @UnusedImport + import urllib3 # @UnusedImport @UnresolvedImport except Exception: from requests.packages import urllib3 # @Reimport @@ -84,7 +84,7 @@ try: urllib3.disable_warnings() # @UndefinedVariable warnings.simplefilter("ignore") except Exception: - pass # In fact, isn't too important, but wil log warns to logging file + pass # In fact, isn't too important, but will log warns to logging file def ensureResultIsOk(result): @@ -221,9 +221,13 @@ class Api(object): logger.debug('Requesting information'.format()) return self.postMessage('information', '') - def setReady(self, ipsInfo): + def setReady(self, ipsInfo, hostName=None): logger.debug('Notifying readyness: {}'.format(ipsInfo)) - data = ','.join(['{}={}'.format(v[0], v[1]) for v in ipsInfo]) + # data = ','.join(['{}={}'.format(v[0], v[1]) for v in ipsInfo]) + data = { + 'ips': ipsInfo, + 'hostname': hostName + } return self.postMessage('ready', data) def notifyIpChanges(self, ipsInfo): diff --git a/actors/src/udsactor/__init__.py b/actors/src/udsactor/__init__.py index c76e9ab5..a69560c7 100644 --- a/actors/src/udsactor/__init__.py +++ b/actors/src/udsactor/__init__.py @@ -34,7 +34,7 @@ from __future__ import unicode_literals # On centos, old six release does not includes byte2int, nor six.PY2 import six -VERSION = '2.1.0' +VERSION = '2.5.0' __title__ = 'udsactor' __version__ = VERSION diff --git a/actors/src/udsactor/httpserver.py b/actors/src/udsactor/httpserver.py index 7b4c3d16..8fd7160a 100644 --- a/actors/src/udsactor/httpserver.py +++ b/actors/src/udsactor/httpserver.py @@ -174,6 +174,11 @@ class HTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler): # TODO: Return something useful? :) return 'Up and running' + def get_refresh(self, params): + ''' + Requests a refresh of own information offered from UDS Server + ''' + def get_uuid(self, params): return self.service.api.uuid diff --git a/actors/src/udsactor/service.py b/actors/src/udsactor/service.py index 645a76be..30a6a940 100644 --- a/actors/src/udsactor/service.py +++ b/actors/src/udsactor/service.py @@ -85,8 +85,8 @@ class CommonService(object): def reboot(self): self.rebootRequested = True - def setReady(self): - self.api.setReady([(v.mac, v.ip) for v in operations.getNetworkInfo()]) + def setReady(self, hostName=None): + self.api.setReady([(v.mac, v.ip) for v in operations.getNetworkInfo()], hostName) def interactWithBroker(self): ''' @@ -171,6 +171,9 @@ class CommonService(object): return False # Stop running service self.joinDomain(params[0], params[1], params[2], params[3], params[4]) break + elif data[0] == 'notify': # Broker is just requesting local information, no rename nor domain is requested + self.notifyLocalInfo() + break else: logger.error('Unrecognized action sent from broker: {}'.format(data[0])) return False # Stop running service @@ -310,6 +313,9 @@ class CommonService(object): # **************************************** # Methods that CAN BE overriden by actors # **************************************** + def notifyLocal(self): + self.setReady(operations.getComputerName()) + def doWait(self, miliseconds): ''' Invoked to wait a bit diff --git a/server/src/uds/REST/methods/services.py b/server/src/uds/REST/methods/services.py index da2e780b..d1da2876 100644 --- a/server/src/uds/REST/methods/services.py +++ b/server/src/uds/REST/methods/services.py @@ -66,7 +66,7 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods 'icon': info.icon().replace('\n', ''), 'needs_publication': info.publicationType is not None, 'max_deployed': info.maxDeployed, - 'uses_cache': info.usesCache, + 'uses_cache': info.usesCache and info.cacheConstains == None, 'uses_cache_l2': info.usesCache_L2, 'cache_tooltip': _(info.cacheTooltip), 'cache_tooltip_l2': _(info.cacheTooltip_L2), diff --git a/server/src/uds/REST/methods/services_pools.py b/server/src/uds/REST/methods/services_pools.py index 581635da..4954359b 100644 --- a/server/src/uds/REST/methods/services_pools.py +++ b/server/src/uds/REST/methods/services_pools.py @@ -239,7 +239,7 @@ class ServicesPools(ModelHandler): raise RequestError(ugettext('Base service does not exist anymore')) try: - serviceType = service.getType() + serviceType = service.getInstance() if serviceType.publicationType is None: self._params['publish_on_save'] = False @@ -250,6 +250,15 @@ class ServicesPools(ModelHandler): else: del fields['osmanager_id'] + if serviceType.cacheConstains is not None: + for k, v in serviceType.cacheConstains.iteritems(): + fields[k] = v + + if serviceType.maxDeployed != -1: + fields['max_srvs'] = min((int(fields['max_srvs']), serviceType.maxDeployed)) + fields['initial_srvs'] = min(int(fields['initial_srvs']), serviceType.maxDeployed) + fields['cache_l1_srvs'] = min(int(fields['cache_l1_srvs']), serviceType.maxDeployed) + if serviceType.usesCache is False: for k in ('initial_srvs', 'cache_l1_srvs', 'cache_l2_srvs', 'max_srvs'): fields[k] = 0 @@ -257,6 +266,7 @@ class ServicesPools(ModelHandler): except Exception: raise RequestError(ugettext('This service requires an OS Manager')) + # If max < initial or cache_1 or cache_l2 fields['max_srvs'] = max((int(fields['initial_srvs']), int(fields['cache_l1_srvs']), int(fields['max_srvs']))) @@ -288,7 +298,10 @@ class ServicesPools(ModelHandler): def afterSave(self, item): if self._params.get('publish_on_save', False) is True: - item.publish() + try: + item.publish() + except Exception: + pass def deleteItem(self, item): item.remove() # This will mark it for deletion, but in fact will not delete it directly diff --git a/server/src/uds/core/services/BasePublication.py b/server/src/uds/core/services/BasePublication.py index c5b872c5..5f7c5d03 100644 --- a/server/src/uds/core/services/BasePublication.py +++ b/server/src/uds/core/services/BasePublication.py @@ -35,7 +35,7 @@ from __future__ import unicode_literals from uds.core import Environmentable from uds.core import Serializable -__updated__ = '2016-02-26' +__updated__ = '2017-01-12' class Publication(Environmentable, Serializable): @@ -89,6 +89,7 @@ class Publication(Environmentable, Serializable): self._osManager = kwargs.get('osManager', None) self._service = kwargs['service'] # Raises an exception if service is not included self._revision = kwargs.get('revision', -1) + self._dbPublication = kwargs.get('dbPublication') self._dsName = kwargs.get('dsName', 'Unknown') self.initialize() diff --git a/server/src/uds/core/services/BaseService.py b/server/src/uds/core/services/BaseService.py index d7820f93..e6645da8 100644 --- a/server/src/uds/core/services/BaseService.py +++ b/server/src/uds/core/services/BaseService.py @@ -37,7 +37,7 @@ from uds.core import Module from uds.core.transports import protocols from . import types -__updated__ = '2016-03-09' +__updated__ = '2017-01-12' class Service(Module): @@ -112,6 +112,9 @@ class Service(Module): # : modified at instance level, core will access always to it using an instance object. maxDeployed = UNLIMITED # : If the service provides more than 1 "provided service" (-1 = no limit, 0 = ???? (do not use it!!!), N = max number to deploy + # : If this item "has constains", on deployed service edition, defined keys will overwrite defined ones + cacheConstains = None + # : If this class uses cache or not. If uses cache is true, means that the # : service can "prepare" some user deployments to allow quicker user access # : to services if he already do not have one. diff --git a/server/src/uds/models/ServicesPoolPublication.py b/server/src/uds/models/ServicesPoolPublication.py index 251a556b..98c1ad03 100644 --- a/server/src/uds/models/ServicesPoolPublication.py +++ b/server/src/uds/models/ServicesPoolPublication.py @@ -47,7 +47,7 @@ from uds.models.UUIDModel import UUIDModel import logging -__updated__ = '2016-03-29' +__updated__ = '2017-01-12' logger = logging.getLogger(__name__) @@ -134,7 +134,7 @@ class DeployedServicePublication(UUIDModel): if serviceInstance.publicationType is None: raise Exception('Class {0} do not have defined publicationType but needs to be published!!!'.format(serviceInstance.__class__)) - dpl = serviceInstance.publicationType(self.getEnvironment(), service=serviceInstance, osManager=osManagerInstance, revision=self.revision, dsName=self.deployed_service.name) + dpl = serviceInstance.publicationType(self.getEnvironment(), service=serviceInstance, osManager=osManagerInstance, revision=self.revision, dsName=self.deployed_service.name, dbPublication=self) # Only invokes deserialization if data has something. '' is nothing if self.data != '' and self.data is not None: dpl.unserialize(self.data) diff --git a/server/src/uds/models/UserService.py b/server/src/uds/models/UserService.py index 91a037d6..93a4beb1 100644 --- a/server/src/uds/models/UserService.py +++ b/server/src/uds/models/UserService.py @@ -57,7 +57,7 @@ import six import pickle import logging -__updated__ = '2016-09-21' +__updated__ = '2017-01-12' logger = logging.getLogger(__name__) @@ -415,7 +415,7 @@ class UserService(UUIDModel): def release(self): ''' - A much more convenient method that "remove" + A much more convenient method that "remove" for some situations.. ''' self.remove() diff --git a/server/src/uds/osmanagers/LinuxOsManager/LinuxOsManager.py b/server/src/uds/osmanagers/LinuxOsManager/LinuxOsManager.py index e527d610..7582cb15 100644 --- a/server/src/uds/osmanagers/LinuxOsManager/LinuxOsManager.py +++ b/server/src/uds/osmanagers/LinuxOsManager/LinuxOsManager.py @@ -105,15 +105,13 @@ class LinuxOsManager(osmanagers.OSManager): def notifyIp(self, uid, service, data): si = service.getInstance() - ip = '' + # Notifies IP to deployed - pairs = data.split(',') - for p in pairs: - key, val = p.split('=') - if key.lower() == uid.lower(): - si.setIp(val) - ip = val + for p in data['ips']: + if p[0].lower() == uid.lower(): + si.setIp(p[1]) + ip = p[1] break self.logKnownIp(service, ip) @@ -168,6 +166,11 @@ class LinuxOsManager(osmanagers.OSManager): doRemove = True elif msg == "ip": # This ocurss on main loop inside machine, so userService is usable + if not isinstance(data, dict): # Old actors, previous to 2.5, convert it information.. + data = { + 'ips': [v.split('=') for v in data.split(',')], + 'hostname': userService.friendly_name + } state = State.USABLE self.notifyIp(userService.unique_id, userService, data) elif msg == "ready": @@ -195,7 +198,7 @@ class LinuxOsManager(osmanagers.OSManager): This function can update userService values. Normal operation will be remove machines if this state is not valid ''' if self._onLogout == 'remove': - userService.remove() + userService.release() def checkState(self, service): logger.debug('Checking state for service {0}'.format(service)) diff --git a/server/src/uds/osmanagers/WindowsOsManager/WindowsOsManager.py b/server/src/uds/osmanagers/WindowsOsManager/WindowsOsManager.py index ed55e584..d12216fe 100644 --- a/server/src/uds/osmanagers/WindowsOsManager/WindowsOsManager.py +++ b/server/src/uds/osmanagers/WindowsOsManager/WindowsOsManager.py @@ -112,15 +112,13 @@ class WindowsOsManager(osmanagers.OSManager): def notifyIp(self, uid, service, data): si = service.getInstance() - ip = '' + # Notifies IP to deployed - pairs = data.split(',') - for p in pairs: - key, val = p.split('=') - if key.lower() == uid.lower(): - si.setIp(val) - ip = val + for p in data['ips']: + if p[0].lower() == uid.lower(): + si.setIp(p[1]) + ip = p[1] break self.logKnownIp(service, ip) @@ -181,6 +179,11 @@ class WindowsOsManager(osmanagers.OSManager): doRemove = True elif msg == "ip": # This ocurss on main loop inside machine, so userService is usable + if not isinstance(data, dict): # Old actors, previous to 2.5 + data = { + 'ips': [v.split('=') for v in data.split(',')], + 'hostname': userService.friendly_name + } state = State.USABLE self.notifyIp(userService.unique_id, userService, data) elif msg == "ready": @@ -230,7 +233,7 @@ class WindowsOsManager(osmanagers.OSManager): This function can update userService values. Normal operation will be remove machines if this state is not valid ''' if self._onLogout == 'remove': - userService.remove() + userService.release() def checkState(self, service): logger.debug('Checking state for service {0}'.format(service))