mirror of
https://github.com/dkmstr/openuds.git
synced 2025-01-11 05:17:55 +03:00
BIG work on pep8 adaption (easier to read, easier to maintain, etc..)
This commit is contained in:
parent
89addaf585
commit
06ff8e32be
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -32,7 +32,7 @@
|
|||||||
'''
|
'''
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
#from django.utils import simplejson as json
|
# from django.utils import simplejson as json
|
||||||
import ujson as json
|
import ujson as json
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
@ -47,26 +47,26 @@ logger = logging.getLogger(__name__)
|
|||||||
class ParametersException(Exception):
|
class ParametersException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ContentProcessor(object):
|
class ContentProcessor(object):
|
||||||
mime_type = None
|
mime_type = None
|
||||||
extensions = None
|
extensions = None
|
||||||
|
|
||||||
def __init__(self, request):
|
def __init__(self, request):
|
||||||
self._request = request
|
self._request = request
|
||||||
|
|
||||||
def processGetParameters(self):
|
def processGetParameters(self):
|
||||||
if self._request.method != 'GET':
|
if self._request.method != 'GET':
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
return self._request.GET.copy()
|
return self._request.GET.copy()
|
||||||
|
|
||||||
|
|
||||||
def processParameters(self):
|
def processParameters(self):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def getResponse(self, obj):
|
def getResponse(self, obj):
|
||||||
return http.HttpResponse(content = self.render(obj), content_type=self.mime_type + "; charset=utf-8")
|
return http.HttpResponse(content=self.render(obj), content_type=self.mime_type + "; charset=utf-8")
|
||||||
|
|
||||||
def render(self, obj):
|
def render(self, obj):
|
||||||
return unicode(obj)
|
return unicode(obj)
|
||||||
|
|
||||||
@ -93,13 +93,14 @@ class ContentProcessor(object):
|
|||||||
return int(time.mktime(obj.timetuple()))
|
return int(time.mktime(obj.timetuple()))
|
||||||
return unicode(obj)
|
return unicode(obj)
|
||||||
|
|
||||||
|
|
||||||
# ---------------
|
# ---------------
|
||||||
# Json Processor
|
# Json Processor
|
||||||
# ---------------
|
# ---------------
|
||||||
class JsonProcessor(ContentProcessor):
|
class JsonProcessor(ContentProcessor):
|
||||||
mime_type = 'application/json'
|
mime_type = 'application/json'
|
||||||
extensions = ['json']
|
extensions = ['json']
|
||||||
|
|
||||||
def processParameters(self):
|
def processParameters(self):
|
||||||
try:
|
try:
|
||||||
if len(self._request.body) == 0:
|
if len(self._request.body) == 0:
|
||||||
@ -111,22 +112,22 @@ class JsonProcessor(ContentProcessor):
|
|||||||
logger.error('parsing json: {0}'.format(e))
|
logger.error('parsing json: {0}'.format(e))
|
||||||
raise ParametersException(unicode(e))
|
raise ParametersException(unicode(e))
|
||||||
|
|
||||||
|
|
||||||
def render(self, obj):
|
def render(self, obj):
|
||||||
return json.dumps( ContentProcessor.procesForRender(obj))
|
return json.dumps(ContentProcessor.procesForRender(obj))
|
||||||
#return json.dumps(obj)
|
# return json.dumps(obj)
|
||||||
|
|
||||||
|
|
||||||
# ---------------
|
# ---------------
|
||||||
# Json Processor
|
# XML Processor
|
||||||
# ---------------
|
# ---------------
|
||||||
class XMLProcessor(ContentProcessor):
|
class XMLProcessor(ContentProcessor):
|
||||||
mime_type = 'application/xml'
|
mime_type = 'application/xml'
|
||||||
extensions = ['xml']
|
extensions = ['xml']
|
||||||
|
|
||||||
def processParameters(self):
|
def processParameters(self):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
processors_list = (JsonProcessor,XMLProcessor)
|
processors_list = (JsonProcessor, XMLProcessor)
|
||||||
default_processor = JsonProcessor
|
default_processor = JsonProcessor
|
||||||
available_processors_mime_dict = dict((cls.mime_type, cls) for cls in processors_list)
|
available_processors_mime_dict = dict((cls.mime_type, cls) for cls in processors_list)
|
||||||
available_processors_ext_dict = {}
|
available_processors_ext_dict = {}
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -36,36 +36,40 @@ from django.utils.translation import ugettext as _
|
|||||||
from uds.core.ui.UserInterface import UserInterface
|
from uds.core.ui.UserInterface import UserInterface
|
||||||
from uds.core import Environmentable
|
from uds.core import Environmentable
|
||||||
from uds.core import Serializable
|
from uds.core import Serializable
|
||||||
import base64, os.path, sys, logging
|
import base64
|
||||||
|
import os.path
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Module(UserInterface, Environmentable, Serializable):
|
class Module(UserInterface, Environmentable, Serializable):
|
||||||
'''
|
'''
|
||||||
Base class for all modules used by UDS.
|
Base class for all modules used by UDS.
|
||||||
This base module provides all the needed methods that modules must implement
|
This base module provides all the needed methods that modules must implement
|
||||||
|
|
||||||
All modules must, at least, implement the following:
|
All modules must, at least, implement the following:
|
||||||
|
|
||||||
* Attributes:
|
* Attributes:
|
||||||
* :py:attr:`.typeName`:
|
* :py:attr:`.typeName`:
|
||||||
Name for this type of module (human readable) to assign to the module (string)
|
Name for this type of module (human readable) to assign to the module (string)
|
||||||
This name will be used to let the administrator identify this module.
|
This name will be used to let the administrator identify this module.
|
||||||
* :py:attr:`.typeType`:
|
* :py:attr:`.typeType`:
|
||||||
Name for this type of module (machine only) to assing to the module (string)
|
Name for this type of module (machine only) to assing to the module (string)
|
||||||
This name will be used internally to identify when a serialized module corresponds with this class.
|
This name will be used internally to identify when a serialized module corresponds with this class.
|
||||||
* :py:attr:`.typeDescription`:
|
* :py:attr:`.typeDescription`:
|
||||||
Description for this type of module.
|
Description for this type of module.
|
||||||
This descriptio will be used to let the administrator identify what this module provides
|
This descriptio will be used to let the administrator identify what this module provides
|
||||||
* :py:attr:`.iconFile`: This is an icon file, in png format, used at administration client to identify this module.
|
* :py:attr:`.iconFile`: This is an icon file, in png format, used at administration client to identify this module.
|
||||||
This parameter may be optionall if you override the "icon" method.
|
This parameter may be optionall if you override the "icon" method.
|
||||||
* Own Methods:
|
* Own Methods:
|
||||||
* :py:meth:`.__init__`
|
* :py:meth:`.__init__`
|
||||||
The default constructor. The environment value is always provided (see Environment), but the
|
The default constructor. The environment value is always provided (see Environment), but the
|
||||||
default values provided can be None.
|
default values provided can be None.
|
||||||
Remember to allow the instantiation of the module with default params, because when deserialization is done,
|
Remember to allow the instantiation of the module with default params, because when deserialization is done,
|
||||||
the process is first instatiate with an environment but no parameters and then call "unmarshal" from Serializable.
|
the process is first instatiate with an environment but no parameters and then call "unmarshal" from Serializable.
|
||||||
* :py:meth:`.test`
|
* :py:meth:`.test`
|
||||||
* :py:meth:`.check`
|
* :py:meth:`.check`
|
||||||
* :py:meth:`.destroy`: Optional
|
* :py:meth:`.destroy`: Optional
|
||||||
* :py:meth:`.icon`: Optional, if you provide an icon file, this method loads it from module folder,
|
* :py:meth:`.icon`: Optional, if you provide an icon file, this method loads it from module folder,
|
||||||
@ -73,101 +77,100 @@ class Module(UserInterface, Environmentable, Serializable):
|
|||||||
* :py:meth:`.marshal`
|
* :py:meth:`.marshal`
|
||||||
By default, this method serializes the values provided by user in form fields. You can override it,
|
By default, this method serializes the values provided by user in form fields. You can override it,
|
||||||
but now it's not needed because you can access config vars using Form Fields.
|
but now it's not needed because you can access config vars using Form Fields.
|
||||||
|
|
||||||
Anyway, if you override this method, you must also override next one
|
Anyway, if you override this method, you must also override next one
|
||||||
* :py:meth:`.unmarshal`
|
* :py:meth:`.unmarshal`
|
||||||
By default, this method de-serializes the values provided by user in form fields. You can override it,
|
By default, this method de-serializes the values provided by user in form fields. You can override it,
|
||||||
but now it's not needed because you can access config vars using Form Fields.
|
but now it's not needed because you can access config vars using Form Fields.
|
||||||
|
|
||||||
Anyway, if you override this method, you must also override previous one
|
Anyway, if you override this method, you must also override previous one
|
||||||
|
|
||||||
* UserInterface Methods:
|
* UserInterface Methods:
|
||||||
* :py:meth:`uds.core.ui.UserInterface.UserInterface.valuesDict`
|
* :py:meth:`uds.core.ui.UserInterface.UserInterface.valuesDict`
|
||||||
This method, by default, provides the values contained in the form fields. If you don't override the marshal and
|
This method, by default, provides the values contained in the form fields. If you don't override the marshal and
|
||||||
unmarshal, this method should be fine as is for you also.
|
unmarshal, this method should be fine as is for you also.
|
||||||
|
|
||||||
|
|
||||||
Environmentable is a base class that provides utility method to access a separate Environment for every single
|
Environmentable is a base class that provides utility method to access a separate Environment for every single
|
||||||
module.
|
module.
|
||||||
'''
|
'''
|
||||||
#: Which coded to use to encode module by default.
|
# : Which coded to use to encode module by default.
|
||||||
#: This overrides the Environmentable and Serializable Attribute, but in all cases we are using 'base64'
|
# : This overrides the Environmentable and Serializable Attribute, but in all cases we are using 'base64'
|
||||||
CODEC = 'base64' # Can be zip, hez, bzip, base64, uuencoded
|
CODEC = 'base64' # Can be zip, hez, bzip, base64, uuencoded
|
||||||
|
|
||||||
#: Basic name used to provide the administrator an "huma readable" form for the module
|
# : Basic name used to provide the administrator an "huma readable" form for the module
|
||||||
typeName = 'Base Module'
|
typeName = 'Base Module'
|
||||||
#: Internal type name, used by system to locate this module
|
# : Internal type name, used by system to locate this module
|
||||||
typeType = 'BaseModule'
|
typeType = 'BaseModule'
|
||||||
#: Description of this module, used at admin level
|
# : Description of this module, used at admin level
|
||||||
typeDescription = 'Base Module'
|
typeDescription = 'Base Module'
|
||||||
#: Icon file, relative to module folders
|
# : Icon file, relative to module folders
|
||||||
iconFile = 'base.png' # This is expected to be png, use this format always
|
iconFile = 'base.png' # This is expected to be png, use this format always
|
||||||
|
|
||||||
class ValidationException(Exception):
|
class ValidationException(Exception):
|
||||||
'''
|
'''
|
||||||
Exception used to indicate that the params assigned are invalid
|
Exception used to indicate that the params assigned are invalid
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def name(cls):
|
def name(cls):
|
||||||
'''
|
'''
|
||||||
Returns "translated" typeName, using ugettext for transforming
|
Returns "translated" typeName, using ugettext for transforming
|
||||||
cls.typeName
|
cls.typeName
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
cls: This is a class method, so cls is the class
|
cls: This is a class method, so cls is the class
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Translated type name (using ugettext)
|
Translated type name (using ugettext)
|
||||||
'''
|
'''
|
||||||
return _(cls.typeName)
|
return _(cls.typeName)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def type(cls):
|
def type(cls):
|
||||||
'''
|
'''
|
||||||
Returns typeType
|
Returns typeType
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
cls: This is a class method, so cls is the class
|
cls: This is a class method, so cls is the class
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
the typeType of this class (or derived class)
|
the typeType of this class (or derived class)
|
||||||
'''
|
'''
|
||||||
return cls.typeType
|
return cls.typeType
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def description(cls):
|
def description(cls):
|
||||||
'''
|
'''
|
||||||
This method returns the "translated" description, that is, using
|
This method returns the "translated" description, that is, using
|
||||||
ugettext for transforming cls.typeDescription.
|
ugettext for transforming cls.typeDescription.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
cls: This is a class method, so cls is the class
|
cls: This is a class method, so cls is the class
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Translated description (using ugettext)
|
Translated description (using ugettext)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
return _(cls.typeDescription)
|
return _(cls.typeDescription)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def icon(cls, inBase64 = True):
|
def icon(cls, inBase64=True):
|
||||||
'''
|
'''
|
||||||
Reads the file specified by iconFile at module folder, and returns it content.
|
Reads the file specified by iconFile at module folder, and returns it content.
|
||||||
This is used to obtain an icon so administration can represent it.
|
This is used to obtain an icon so administration can represent it.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
cls: Class
|
cls: Class
|
||||||
|
|
||||||
inBase64: If true, the image will be returned as base 64 encoded
|
inBase64: If true, the image will be returned as base 64 encoded
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Base 64 encoded or raw image, obtained from the specified file at
|
Base 64 encoded or raw image, obtained from the specified file at
|
||||||
'iconFile' class attribute
|
'iconFile' class attribute
|
||||||
'''
|
'''
|
||||||
logger.debug('Loading icon for class {0} ({1})'.format(cls, cls.iconFile))
|
logger.debug('Loading icon for class {0} ({1})'.format(cls, cls.iconFile))
|
||||||
file_ = open( os.path.dirname(sys.modules[cls.__module__].__file__) + '/' + cls.iconFile, 'rb')
|
file_ = open(os.path.dirname(sys.modules[cls.__module__].__file__) + '/' + cls.iconFile, 'rb')
|
||||||
data = file_.read()
|
data = file_.read()
|
||||||
file_.close()
|
file_.close()
|
||||||
if inBase64 == True:
|
if inBase64 == True:
|
||||||
@ -179,101 +182,100 @@ class Module(UserInterface, Environmentable, Serializable):
|
|||||||
def test(env, data):
|
def test(env, data):
|
||||||
'''
|
'''
|
||||||
Test if the connection data is ok.
|
Test if the connection data is ok.
|
||||||
|
|
||||||
Returns an array, first value indicates "Ok" if true, "Bad" or "Error"
|
Returns an array, first value indicates "Ok" if true, "Bad" or "Error"
|
||||||
if false. Second is a string describing operation
|
if false. Second is a string describing operation
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
env: environment passed for testing (temporal environment passed)
|
env: environment passed for testing (temporal environment passed)
|
||||||
|
|
||||||
data: data passed for testing (data obtained from the form
|
data: data passed for testing (data obtained from the form
|
||||||
definition)
|
definition)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Array of two elements, first is True of False, depending on test
|
Array of two elements, first is True of False, depending on test
|
||||||
(True is all right, false is error),
|
(True is all right, false is error),
|
||||||
second is an String with error, preferably internacionalizated..
|
second is an String with error, preferably internacionalizated..
|
||||||
'''
|
'''
|
||||||
return [True, _("No connection checking method is implemented.")]
|
return [True, _("No connection checking method is implemented.")]
|
||||||
|
|
||||||
def __init__(self, environment, values = None):
|
def __init__(self, environment, values=None):
|
||||||
'''
|
'''
|
||||||
Do not forget to invoke this in your derived class using
|
Do not forget to invoke this in your derived class using
|
||||||
"super(self.__class__, self).__init__(environment, values)".
|
"super(self.__class__, self).__init__(environment, values)".
|
||||||
|
|
||||||
We want to use the env, cache and storage methods outside class.
|
We want to use the env, cache and storage methods outside class.
|
||||||
If not called, you must implement your own methods.
|
If not called, you must implement your own methods.
|
||||||
|
|
||||||
cache and storage are "convenient" methods to access _env.cache() and
|
cache and storage are "convenient" methods to access _env.cache() and
|
||||||
_env.storage()
|
_env.storage()
|
||||||
|
|
||||||
The values param is passed directly to UserInterface base.
|
The values param is passed directly to UserInterface base.
|
||||||
|
|
||||||
The environment param is passed directly to environment.
|
The environment param is passed directly to environment.
|
||||||
|
|
||||||
Values are passed to __initialize__ method. It this is not None,
|
Values are passed to __initialize__ method. It this is not None,
|
||||||
the values contains a dictionary of values received from administration gui,
|
the values contains a dictionary of values received from administration gui,
|
||||||
that contains the form data requested from user.
|
that contains the form data requested from user.
|
||||||
|
|
||||||
If you override marshal, unmarshal and inherited UserInterface method
|
If you override marshal, unmarshal and inherited UserInterface method
|
||||||
valuesDict, you must also take account of values (dict) provided at the
|
valuesDict, you must also take account of values (dict) provided at the
|
||||||
__init__ method of your class.
|
__init__ method of your class.
|
||||||
'''
|
'''
|
||||||
#
|
#
|
||||||
UserInterface.__init__(self, values)
|
UserInterface.__init__(self, values)
|
||||||
Environmentable.__init__(self, environment)
|
Environmentable.__init__(self, environment)
|
||||||
Serializable.__init__(self)
|
Serializable.__init__(self)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Base Module"
|
return "Base Module"
|
||||||
|
|
||||||
def isDirty(self):
|
def isDirty(self):
|
||||||
'''
|
'''
|
||||||
This method informs the core if the module has changed serializable data,
|
This method informs the core if the module has changed serializable data,
|
||||||
and that must be re-serialized
|
and that must be re-serialized
|
||||||
|
|
||||||
Default implemetation is that on every method call, module will be dirty
|
Default implemetation is that on every method call, module will be dirty
|
||||||
|
|
||||||
Note: The implementation of this is a work in progress, so right now the module will be serialized out on every acess
|
Note: The implementation of this is a work in progress, so right now the module will be serialized out on every acess
|
||||||
'''
|
'''
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def marshal(self):
|
def marshal(self):
|
||||||
'''
|
'''
|
||||||
By default and if not overriden by descendants, this method, overridden
|
By default and if not overriden by descendants, this method, overridden
|
||||||
from Serializable, and returns the serialization of
|
from Serializable, and returns the serialization of
|
||||||
form field stored values.
|
form field stored values.
|
||||||
'''
|
'''
|
||||||
return self.serializeForm()
|
return self.serializeForm()
|
||||||
|
|
||||||
def unmarshal(self, str_):
|
def unmarshal(self, str_):
|
||||||
'''
|
'''
|
||||||
By default and if not overriden by descendants, this method recovers
|
By default and if not overriden by descendants, this method recovers
|
||||||
data serialized using serializeForm
|
data serialized using serializeForm
|
||||||
'''
|
'''
|
||||||
self.unserializeForm(str_)
|
self.unserializeForm(str_)
|
||||||
|
|
||||||
def check(self):
|
def check(self):
|
||||||
'''
|
'''
|
||||||
Method that will provide the "check" capability for the module.
|
Method that will provide the "check" capability for the module.
|
||||||
|
|
||||||
The return value that this method must provide is simply an string,
|
The return value that this method must provide is simply an string,
|
||||||
preferable internacionalizated.
|
preferable internacionalizated.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Internacionalized (using ugettext) string of result of the check.
|
Internacionalized (using ugettext) string of result of the check.
|
||||||
'''
|
'''
|
||||||
return _("No check method provided.")
|
return _("No check method provided.")
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
'''
|
'''
|
||||||
Invoked before deleting an module from database.
|
Invoked before deleting an module from database.
|
||||||
|
|
||||||
Do whatever needed here, as deleting associated data if needed
|
Do whatever needed here, as deleting associated data if needed
|
||||||
(no example come to my head right now... :-) )
|
(no example come to my head right now... :-) )
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Nothing
|
Nothing
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -35,74 +35,73 @@ from __future__ import unicode_literals
|
|||||||
TEMP_ENV = 'temporary'
|
TEMP_ENV = 'temporary'
|
||||||
GLOBAL_ENV = 'global'
|
GLOBAL_ENV = 'global'
|
||||||
|
|
||||||
|
|
||||||
class Environment(object):
|
class Environment(object):
|
||||||
'''
|
'''
|
||||||
Class to manipulate the associated environment with "environmentable" classes (mainly modules).
|
Class to manipulate the associated environment with "environmentable" classes (mainly modules).
|
||||||
It purpose is to provide an "object owned" environment, so every db record can contain associated values
|
It purpose is to provide an "object owned" environment, so every db record can contain associated values
|
||||||
not stored with main module data.
|
not stored with main module data.
|
||||||
The environment is composed of a "cache" and a "storage". First are volatile data, while second are persistent data.
|
The environment is composed of a "cache" and a "storage". First are volatile data, while second are persistent data.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, uniqueKey, idGenerators = {}):
|
def __init__(self, uniqueKey, idGenerators={}):
|
||||||
'''
|
'''
|
||||||
Initialized the Environment for the specified id
|
Initialized the Environment for the specified id
|
||||||
@param uniqueId: Key for this environment
|
@param uniqueId: Key for this environment
|
||||||
@param idGenerators: Hash of generators of ids for this environment. This "generators of ids" feature
|
@param idGenerators: Hash of generators of ids for this environment. This "generators of ids" feature
|
||||||
is used basically at User Services to auto-create ids for macs or names, using
|
is used basically at User Services to auto-create ids for macs or names, using
|
||||||
{'mac' : UniqueMacGenerator, 'name' : UniqueNameGenerator } as argument.
|
{'mac' : UniqueMacGenerator, 'name' : UniqueNameGenerator } as argument.
|
||||||
'''
|
'''
|
||||||
from uds.core.util.Cache import Cache
|
from uds.core.util.Cache import Cache
|
||||||
from uds.core.util.Storage import Storage
|
from uds.core.util.Storage import Storage
|
||||||
self._key = uniqueKey
|
self._key = uniqueKey
|
||||||
self._cache = Cache(uniqueKey)
|
self._cache = Cache(uniqueKey)
|
||||||
self._storage = Storage(uniqueKey)
|
self._storage = Storage(uniqueKey)
|
||||||
self._idGenerators = idGenerators
|
self._idGenerators = idGenerators
|
||||||
|
|
||||||
def cache(self):
|
def cache(self):
|
||||||
'''
|
'''
|
||||||
Method to acces the cache of the environment.
|
Method to acces the cache of the environment.
|
||||||
@return: a referente to a Cache instance
|
@return: a referente to a Cache instance
|
||||||
'''
|
'''
|
||||||
return self._cache
|
return self._cache
|
||||||
|
|
||||||
def storage(self):
|
def storage(self):
|
||||||
'''
|
'''
|
||||||
Method to acces the cache of the environment.
|
Method to acces the cache of the environment.
|
||||||
@return: a referente to an Storage Instance
|
@return: a referente to an Storage Instance
|
||||||
'''
|
'''
|
||||||
return self._storage
|
return self._storage
|
||||||
|
|
||||||
def idGenerators(self, generatorId):
|
def idGenerators(self, generatorId):
|
||||||
'''
|
'''
|
||||||
The idea of generator of id is to obtain at some moment Ids with a proper generator.
|
The idea of generator of id is to obtain at some moment Ids with a proper generator.
|
||||||
If the environment do not contains generators of id, this method will return None.
|
If the environment do not contains generators of id, this method will return None.
|
||||||
The id generator feature is used by User Services to obtain different auto-id generators, as macs or names
|
The id generator feature is used by User Services to obtain different auto-id generators, as macs or names
|
||||||
@param generatorId: Id of the generator to obtain
|
@param generatorId: Id of the generator to obtain
|
||||||
@return: Generator for that id, or None if no generator for that id is found
|
@return: Generator for that id, or None if no generator for that id is found
|
||||||
'''
|
'''
|
||||||
if self._idGenerators.has_key(generatorId):
|
return self._idGenerators.get(generatorId, None)
|
||||||
return self._idGenerators[generatorId]
|
|
||||||
return None
|
|
||||||
|
|
||||||
def key(self):
|
def key(self):
|
||||||
'''
|
'''
|
||||||
@return: the key used for this environment
|
@return: the key used for this environment
|
||||||
'''
|
'''
|
||||||
return self._key
|
return self._key
|
||||||
|
|
||||||
def clearRelatedData(self):
|
def clearRelatedData(self):
|
||||||
'''
|
'''
|
||||||
Removes all related information from database for this environment.
|
Removes all related information from database for this environment.
|
||||||
'''
|
'''
|
||||||
from uds.core.util.Cache import Cache
|
from uds.core.util.Cache import Cache
|
||||||
from uds.core.util.Storage import Storage
|
from uds.core.util.Storage import Storage
|
||||||
Cache.delete(self._key)
|
Cache.delete(self._key)
|
||||||
Storage.delete(self._key)
|
Storage.delete(self._key)
|
||||||
for __, v in self._idGenerators.iteritems():
|
for __, v in self._idGenerators.iteritems():
|
||||||
v.release()
|
v.release()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getEnvForTableElement(tblName, id_, idGeneratorsTypes = {}):
|
def getEnvForTableElement(tblName, id_, idGeneratorsTypes={}):
|
||||||
'''
|
'''
|
||||||
From a table name, and a id, tries to load the associated environment or creates a new
|
From a table name, and a id, tries to load the associated environment or creates a new
|
||||||
one if no environment exists at database. The table name and the id are used to obtain the key
|
one if no environment exists at database. The table name and the id are used to obtain the key
|
||||||
@ -114,10 +113,10 @@ class Environment(object):
|
|||||||
'''
|
'''
|
||||||
name = 't-' + tblName + '-' + str(id_)
|
name = 't-' + tblName + '-' + str(id_)
|
||||||
idGenerators = {}
|
idGenerators = {}
|
||||||
for k,v in idGeneratorsTypes.iteritems():
|
for k, v in idGeneratorsTypes.iteritems():
|
||||||
idGenerators[k] = v(name)
|
idGenerators[k] = v(name)
|
||||||
return Environment(name, idGenerators)
|
return Environment(name, idGenerators)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getEnvForType(type_):
|
def getEnvForType(type_):
|
||||||
'''
|
'''
|
||||||
@ -125,82 +124,82 @@ class Environment(object):
|
|||||||
@param type_: Type
|
@param type_: Type
|
||||||
@return Associated Environment
|
@return Associated Environment
|
||||||
'''
|
'''
|
||||||
return Environment('type-'+str(type_))
|
return Environment('type-' + str(type_))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getTempEnv():
|
def getTempEnv():
|
||||||
'''
|
'''
|
||||||
Provides a temporary environment needed in some calls (test provider, for example)
|
Provides a temporary environment needed in some calls (test provider, for example)
|
||||||
It will not make environment persistent
|
It will not make environment persistent
|
||||||
'''
|
'''
|
||||||
return Environment(TEMP_ENV) # TODO: In fact, we should provide a "null" cache and a "null" storage, but for now this is right
|
return Environment(TEMP_ENV) # TODO: In fact, we should provide a "null" cache and a "null" storage, but for now this is right
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getGlobalEnv():
|
def getGlobalEnv():
|
||||||
'''
|
'''
|
||||||
Provides global environment
|
Provides global environment
|
||||||
'''
|
'''
|
||||||
return Environment(GLOBAL_ENV) # This environment is a global environment for general utility.
|
return Environment(GLOBAL_ENV) # This environment is a global environment for general utility.
|
||||||
|
|
||||||
|
|
||||||
class Environmentable(object):
|
class Environmentable(object):
|
||||||
'''
|
'''
|
||||||
This is a base class provided for all objects that have an environment associated. These are mainly modules
|
This is a base class provided for all objects that have an environment associated. These are mainly modules
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, environment):
|
def __init__(self, environment):
|
||||||
'''
|
'''
|
||||||
Initialized the element
|
Initialized the element
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
environment: Environment to associate with
|
environment: Environment to associate with
|
||||||
'''
|
'''
|
||||||
self._env = environment
|
self._env = environment
|
||||||
|
|
||||||
def setEnv(self, environment):
|
def setEnv(self, environment):
|
||||||
'''
|
'''
|
||||||
Assigns a new environment
|
Assigns a new environment
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
environment: Environment to assign
|
environment: Environment to assign
|
||||||
'''
|
'''
|
||||||
self._env = environment
|
self._env = environment
|
||||||
|
|
||||||
def env(self):
|
def env(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access the envionment contained by this object
|
Utility method to access the envionment contained by this object
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Environmnet for the object
|
Environmnet for the object
|
||||||
'''
|
'''
|
||||||
return self._env
|
return self._env
|
||||||
|
|
||||||
def cache(self):
|
def cache(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access the cache of the environment containe by this object
|
Utility method to access the cache of the environment containe by this object
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Cache for the object
|
Cache for the object
|
||||||
'''
|
'''
|
||||||
return self._env.cache()
|
return self._env.cache()
|
||||||
|
|
||||||
def storage(self):
|
def storage(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access the storage of the environment containe by this object
|
Utility method to access the storage of the environment containe by this object
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Storage for the object
|
Storage for the object
|
||||||
'''
|
'''
|
||||||
return self._env.storage()
|
return self._env.storage()
|
||||||
|
|
||||||
def idGenerators(self, generatorId):
|
def idGenerators(self, generatorId):
|
||||||
'''
|
'''
|
||||||
Utility method to access the id generator of the environment containe by this object
|
Utility method to access the id generator of the environment containe by this object
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
generatorId: Id of the generator to obtain
|
generatorId: Id of the generator to obtain
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Generator for the object and the id specified
|
Generator for the object and the id specified
|
||||||
'''
|
'''
|
||||||
return self._env.idGenerators(generatorId)
|
return self._env.idGenerators(generatorId)
|
||||||
|
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -36,7 +36,7 @@ from __future__ import unicode_literals
|
|||||||
class Serializable(object):
|
class Serializable(object):
|
||||||
'''
|
'''
|
||||||
This class represents the interface that all serializable objects must provide.
|
This class represents the interface that all serializable objects must provide.
|
||||||
|
|
||||||
Every single serializable class must implement marshall & unmarshall methods. Also, the class must allow
|
Every single serializable class must implement marshall & unmarshall methods. Also, the class must allow
|
||||||
to be initialized without parameters, so we can:
|
to be initialized without parameters, so we can:
|
||||||
- Initialize the object with default values
|
- Initialize the object with default values
|
||||||
@ -44,53 +44,52 @@ class Serializable(object):
|
|||||||
'''
|
'''
|
||||||
# Codify codec constant
|
# Codify codec constant
|
||||||
CODEC = 'base64' # Can be zip, hez, bzip, base64, uuencoded
|
CODEC = 'base64' # Can be zip, hez, bzip, base64, uuencoded
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def marshal(self):
|
def marshal(self):
|
||||||
'''
|
'''
|
||||||
This is the method that must be overriden in order to serialize an object.
|
This is the method that must be overriden in order to serialize an object.
|
||||||
|
|
||||||
The system will use in fact 'seralize' and 'deserialize' methods, but theese are
|
The system will use in fact 'seralize' and 'deserialize' methods, but theese are
|
||||||
only suitable methods to "codify" serialized values
|
only suitable methods to "codify" serialized values
|
||||||
|
|
||||||
:note: This method must be overridden
|
:note: This method must be overridden
|
||||||
'''
|
'''
|
||||||
raise Exception('Base marshaler called!!!')
|
raise Exception('Base marshaler called!!!')
|
||||||
|
|
||||||
def unmarshal(self, str_):
|
def unmarshal(self, str_):
|
||||||
'''
|
'''
|
||||||
This is the method that must be overriden in order to unserialize an object.
|
This is the method that must be overriden in order to unserialize an object.
|
||||||
|
|
||||||
The system will use in fact 'seralize' and 'deserialize' methods, but theese are
|
The system will use in fact 'seralize' and 'deserialize' methods, but theese are
|
||||||
only convenients methods to "codify" serialized values.
|
only convenients methods to "codify" serialized values.
|
||||||
|
|
||||||
Take into account that _str can be '' (empty string), but hopefully it will never be none.
|
Take into account that _str can be '' (empty string), but hopefully it will never be none.
|
||||||
In that case, initialize the object with default values
|
In that case, initialize the object with default values
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
str_ _ : String readed from persistent storage to deseralilize
|
str_ _ : String readed from persistent storage to deseralilize
|
||||||
|
|
||||||
:note: This method must be overridden
|
:note: This method must be overridden
|
||||||
'''
|
'''
|
||||||
raise Exception('Base unmarshaler called!!!')
|
raise Exception('Base unmarshaler called!!!')
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
'''
|
'''
|
||||||
Serializes and "obfuscates' the data.
|
Serializes and "obfuscates' the data.
|
||||||
|
|
||||||
The codec used to encode the string is obtained from the instance CODEC, so derived classes can
|
The codec used to encode the string is obtained from the instance CODEC, so derived classes can
|
||||||
overwrite this attribute to set another codec
|
overwrite this attribute to set another codec
|
||||||
'''
|
'''
|
||||||
return self.marshal().encode(self.CODEC)
|
return self.marshal().encode(self.CODEC)
|
||||||
|
|
||||||
def unserialize(self, str_):
|
def unserialize(self, str_):
|
||||||
'''
|
'''
|
||||||
des-obfuscates the data and then de-serializes it via unmarshal method
|
des-obfuscates the data and then de-serializes it via unmarshal method
|
||||||
|
|
||||||
The codec used to decode the string is obtained from the instance CODEC, so derived classes can
|
The codec used to decode the string is obtained from the instance CODEC, so derived classes can
|
||||||
overwrite this attribute to set another codec
|
overwrite this attribute to set another codec
|
||||||
'''
|
'''
|
||||||
return self.unmarshal(str_.decode(self.CODEC))
|
return self.unmarshal(str_.decode(self.CODEC))
|
||||||
|
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -32,6 +32,7 @@ Core of UDS.
|
|||||||
This package contains all core-related code for UDS
|
This package contains all core-related code for UDS
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
# Core needs tasks manager to register scheduled jobs, so we ensure of that here
|
# Core needs tasks manager to register scheduled jobs, so we ensure of that here
|
||||||
from Environment import Environmentable
|
from Environment import Environmentable
|
||||||
@ -40,4 +41,3 @@ from BaseModule import Module
|
|||||||
import services
|
import services
|
||||||
import auths
|
import auths
|
||||||
import transports
|
import transports
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ class JobsFactory(object):
|
|||||||
return self._jobs
|
return self._jobs
|
||||||
|
|
||||||
def insert(self, name, type_):
|
def insert(self, name, type_):
|
||||||
logger.debug('Inserting job {0} of type {1}'.format(name, type_))
|
logger.debug('Inserting job {0} of type_ {1}'.format(name, type_))
|
||||||
try:
|
try:
|
||||||
self._jobs[name] = type_
|
self._jobs[name] = type_
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -36,7 +36,8 @@ from django.conf import settings
|
|||||||
from Crypto.PublicKey import RSA
|
from Crypto.PublicKey import RSA
|
||||||
from OpenSSL import crypto
|
from OpenSSL import crypto
|
||||||
from Crypto.Random import atfork
|
from Crypto.Random import atfork
|
||||||
import hashlib, array
|
import hashlib
|
||||||
|
import array
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -48,24 +49,25 @@ logger = logging.getLogger(__name__)
|
|||||||
# import os
|
# import os
|
||||||
# RSA.generate(1024, os.urandom).exportKey()
|
# RSA.generate(1024, os.urandom).exportKey()
|
||||||
|
|
||||||
|
|
||||||
class CryptoManager(object):
|
class CryptoManager(object):
|
||||||
CODEC = 'base64'
|
CODEC = 'base64'
|
||||||
|
|
||||||
instance = None
|
instance = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._rsa = RSA.importKey(settings.RSA_KEY)
|
self._rsa = RSA.importKey(settings.RSA_KEY)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def manager():
|
def manager():
|
||||||
if CryptoManager.instance is None:
|
if CryptoManager.instance is None:
|
||||||
CryptoManager.instance = CryptoManager()
|
CryptoManager.instance = CryptoManager()
|
||||||
return CryptoManager.instance
|
return CryptoManager.instance
|
||||||
|
|
||||||
def encrypt(self, string):
|
def encrypt(self, string):
|
||||||
atfork()
|
atfork()
|
||||||
return self._rsa.encrypt(string.encode('utf-8'), '')[0].encode(CryptoManager.CODEC)
|
return self._rsa.encrypt(string.encode('utf-8'), '')[0].encode(CryptoManager.CODEC)
|
||||||
|
|
||||||
def decrypt(self, string):
|
def decrypt(self, string):
|
||||||
try:
|
try:
|
||||||
atfork()
|
atfork()
|
||||||
@ -73,32 +75,31 @@ class CryptoManager(object):
|
|||||||
except:
|
except:
|
||||||
logger.exception('Decripting')
|
logger.exception('Decripting')
|
||||||
return 'decript error'
|
return 'decript error'
|
||||||
|
|
||||||
def xor(self, s1, s2):
|
def xor(self, s1, s2):
|
||||||
s1, s2 = s1.encode('utf-8'), s2.encode('utf-8')
|
s1, s2 = s1.encode('utf-8'), s2.encode('utf-8')
|
||||||
mult = (len(s1)/len(s2)) + 1
|
mult = (len(s1) / len(s2)) + 1
|
||||||
s1 = array.array(b'B', s1)
|
s1 = array.array(b'B', s1)
|
||||||
s2 = array.array(b'B', s2 * mult)
|
s2 = array.array(b'B', s2 * mult)
|
||||||
return array.array(b'B', (s1[i] ^ s2[i] for i in range(len(s1)))).tostring()
|
return array.array(b'B', (s1[i] ^ s2[i] for i in range(len(s1)))).tostring()
|
||||||
|
|
||||||
def loadPrivateKey(self, rsaKey):
|
def loadPrivateKey(self, rsaKey):
|
||||||
try:
|
try:
|
||||||
pk = RSA.importKey(rsaKey)
|
pk = RSA.importKey(rsaKey)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise e
|
raise e
|
||||||
return pk
|
return pk
|
||||||
|
|
||||||
def loadCertificate(self,certificate):
|
def loadCertificate(self, certificate):
|
||||||
try:
|
try:
|
||||||
cert = crypto.load_certificate(crypto.FILETYPE_PEM, certificate)
|
cert = crypto.load_certificate(crypto.FILETYPE_PEM, certificate)
|
||||||
except crypto.Error as e:
|
except crypto.Error as e:
|
||||||
raise Exception(e.message[0][2])
|
raise Exception(e.message[0][2])
|
||||||
return cert
|
return cert
|
||||||
|
|
||||||
def certificateString(self, certificate):
|
def certificateString(self, certificate):
|
||||||
return certificate.replace('-----BEGIN CERTIFICATE-----', '').replace('-----END CERTIFICATE-----', '').replace('\n', '')
|
return certificate.replace('-----BEGIN CERTIFICATE-----', '').replace('-----END CERTIFICATE-----', '').replace('\n', '')
|
||||||
|
|
||||||
|
|
||||||
def hash(self, string):
|
def hash(self, string):
|
||||||
if string is '' or string is None:
|
if string is '' or string is None:
|
||||||
return ''
|
return ''
|
||||||
|
@ -4,92 +4,92 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import os, tempfile, zipfile, uuid
|
import os
|
||||||
|
import uuid
|
||||||
from django.http import HttpResponse, Http404
|
from django.http import HttpResponse, Http404
|
||||||
from django.core.servers.basehttp import FileWrapper
|
from django.core.servers.basehttp import FileWrapper
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DownloadsManager(object):
|
class DownloadsManager(object):
|
||||||
'''
|
'''
|
||||||
Manager so connectors can register their own downloadables
|
Manager so connectors can register their own downloadables
|
||||||
For registering, use at __init__.py of the conecto something like this:
|
For registering, use at __init__.py of the conecto something like this:
|
||||||
from uds.core.managers.DownloadsManager import DownloadsManager
|
from uds.core.managers.DownloadsManager import DownloadsManager
|
||||||
import os.path, sys
|
import os.path, sys
|
||||||
DownloadsManager.manager().registerDownloadable('test.exe',
|
DownloadsManager.manager().registerDownloadable('test.exe',
|
||||||
_('comments for test'),
|
_('comments for test'),
|
||||||
os.path.dirname(sys.modules[__package__].__file__) + '/files/test.exe',
|
os.path.dirname(sys.modules[__package__].__file__) + '/files/test.exe',
|
||||||
'application/x-msdos-program')
|
'application/x-msdos-program')
|
||||||
'''
|
'''
|
||||||
_manager = None
|
_manager = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._downloadables = {}
|
self._downloadables = {}
|
||||||
self._namespace = uuid.UUID('627a37a5-e8db-431a-b783-73f7d20b4934')
|
self._namespace = uuid.UUID('627a37a5-e8db-431a-b783-73f7d20b4934')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def manager():
|
def manager():
|
||||||
if DownloadsManager._manager == None:
|
if DownloadsManager._manager == None:
|
||||||
DownloadsManager._manager = DownloadsManager()
|
DownloadsManager._manager = DownloadsManager()
|
||||||
return DownloadsManager._manager
|
return DownloadsManager._manager
|
||||||
|
|
||||||
|
|
||||||
def registerDownloadable(self, name, comment, path, mime = 'application/octet-stream'):
|
def registerDownloadable(self, name, comment, path, mime='application/octet-stream'):
|
||||||
'''
|
'''
|
||||||
Registers a downloadable file.
|
Registers a downloadable file.
|
||||||
@param name: name shown
|
@param name: name shown
|
||||||
@param path: path to file
|
@param path: path to file
|
||||||
@params zip: If download as zip
|
@params zip: If download as zip
|
||||||
'''
|
'''
|
||||||
_id = str(uuid.uuid5(self._namespace, name))
|
_id = str(uuid.uuid5(self._namespace, name))
|
||||||
self._downloadables[_id] = { 'name': name, 'comment' : comment, 'path' : path, 'mime' : mime }
|
self._downloadables[_id] = {'name': name, 'comment': comment, 'path': path, 'mime': mime}
|
||||||
|
|
||||||
def getDownloadables(self):
|
def getDownloadables(self):
|
||||||
return self._downloadables
|
return self._downloadables
|
||||||
|
|
||||||
|
|
||||||
def send(self, request, _id):
|
def send(self, request, _id):
|
||||||
if self._downloadables.has_key(_id) is False:
|
if _id not in self._downloadables:
|
||||||
return Http404()
|
return Http404()
|
||||||
return self.__send_file(request, self._downloadables[_id]['name'], self._downloadables[_id]['path'], self._downloadables[_id]['mime']);
|
return self.__send_file(request, self._downloadables[_id]['name'], self._downloadables[_id]['path'], self._downloadables[_id]['mime'])
|
||||||
|
|
||||||
def __send_file(self, request, name, filename, mime):
|
def __send_file(self, request, name, filename, mime):
|
||||||
"""
|
"""
|
||||||
Send a file through Django without loading the whole file into
|
Send a file through Django without loading the whole file into
|
||||||
memory at once. The FileWrapper will turn the file object into an
|
memory at once. The FileWrapper will turn the file object into an
|
||||||
iterator for chunks of 8KB.
|
iterator for chunks of 8KB.
|
||||||
"""
|
"""
|
||||||
wrapper = FileWrapper(file(filename))
|
wrapper = FileWrapper(file(filename))
|
||||||
response = HttpResponse(wrapper, content_type=mime)
|
response = HttpResponse(wrapper, content_type=mime)
|
||||||
response['Content-Length'] = os.path.getsize(filename)
|
response['Content-Length'] = os.path.getsize(filename)
|
||||||
response['Content-Disposition'] = 'attachment; filename=' + name
|
response['Content-Disposition'] = 'attachment; filename=' + name
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
@ -3,33 +3,33 @@
|
|||||||
# Copyright (c) 2013 Virtual Cable S.L.
|
# Copyright (c) 2013 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from uds.models import UserService
|
from uds.models import UserService
|
||||||
from uds.models import DeployedServicePublication
|
from uds.models import DeployedServicePublication
|
||||||
@ -52,25 +52,26 @@ OT_USERSERVICE, OT_PUBLICATION, OT_DEPLOYED_SERVICE, OT_SERVICE, OT_PROVIDER, OT
|
|||||||
|
|
||||||
# Dict for translations
|
# Dict for translations
|
||||||
transDict = {
|
transDict = {
|
||||||
UserService : OT_USERSERVICE,
|
UserService: OT_USERSERVICE,
|
||||||
DeployedServicePublication : OT_PUBLICATION,
|
DeployedServicePublication: OT_PUBLICATION,
|
||||||
DeployedService : OT_DEPLOYED_SERVICE,
|
DeployedService: OT_DEPLOYED_SERVICE,
|
||||||
Service : OT_SERVICE,
|
Service: OT_SERVICE,
|
||||||
Provider : OT_PROVIDER,
|
Provider: OT_PROVIDER,
|
||||||
User : OT_USER,
|
User: OT_USER,
|
||||||
Group : OT_GROUP,
|
Group: OT_GROUP,
|
||||||
Authenticator : OT_AUTHENTICATOR
|
Authenticator: OT_AUTHENTICATOR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class LogManager(object):
|
class LogManager(object):
|
||||||
'''
|
'''
|
||||||
Manager for logging (at database) events
|
Manager for logging (at database) events
|
||||||
'''
|
'''
|
||||||
_manager = None
|
_manager = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def manager():
|
def manager():
|
||||||
if LogManager._manager == None:
|
if LogManager._manager == None:
|
||||||
@ -83,87 +84,83 @@ class LogManager(object):
|
|||||||
'''
|
'''
|
||||||
from uds.models import getSqlDatetime
|
from uds.models import getSqlDatetime
|
||||||
from uds.models import Log
|
from uds.models import Log
|
||||||
|
|
||||||
qs = Log.objects.filter(owner_id = owner_id, owner_type = owner_type)
|
qs = Log.objects.filter(owner_id=owner_id, owner_type=owner_type)
|
||||||
# First, ensure we do not have more than requested logs, and we can put one more log item
|
# First, ensure we do not have more than requested logs, and we can put one more log item
|
||||||
if qs.count() >= GlobalConfig.MAX_LOGS_PER_ELEMENT.getInt():
|
if qs.count() >= GlobalConfig.MAX_LOGS_PER_ELEMENT.getInt():
|
||||||
for i in qs.order_by('-created',)[GlobalConfig.MAX_LOGS_PER_ELEMENT.getInt()-1:]:
|
for i in qs.order_by('-created',)[GlobalConfig.MAX_LOGS_PER_ELEMENT.getInt() - 1:]:
|
||||||
i.delete()
|
i.delete()
|
||||||
|
|
||||||
if avoidDuplicates is True:
|
if avoidDuplicates is True:
|
||||||
try:
|
try:
|
||||||
lg = Log.objects.filter(owner_id = owner_id, owner_type = owner_type, level = level, source = source).order_by('-created', '-id')[0]
|
lg = Log.objects.filter(owner_id=owner_id, owner_type=owner_type, level=level, source=source).order_by('-created', '-id')[0]
|
||||||
if lg.message == message:
|
if lg.message == message:
|
||||||
# Do not log again, already logged
|
# Do not log again, already logged
|
||||||
return
|
return
|
||||||
except: # Do not exists log
|
except: # Do not exists log
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# now, we add new log
|
# now, we add new log
|
||||||
try:
|
try:
|
||||||
Log.objects.create(owner_type = owner_type, owner_id = owner_id, created = getSqlDatetime(), source = source, level = level, data = message)
|
Log.objects.create(owner_type=owner_type, owner_id=owner_id, created=getSqlDatetime(), source=source, level=level, data=message)
|
||||||
except:
|
except:
|
||||||
# Some objects will not get logged, such as System administrator objects
|
# Some objects will not get logged, such as System administrator objects
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def __getLogs(self, owner_type, owner_id, limit):
|
def __getLogs(self, owner_type, owner_id, limit):
|
||||||
'''
|
'''
|
||||||
Get all logs associated with an user service, ordered by date
|
Get all logs associated with an user service, ordered by date
|
||||||
'''
|
'''
|
||||||
from uds.models import Log
|
from uds.models import Log
|
||||||
|
|
||||||
qs = Log.objects.filter(owner_id = owner_id, owner_type = owner_type)
|
qs = Log.objects.filter(owner_id=owner_id, owner_type=owner_type)
|
||||||
return [{'date': x.created, 'level': x.level, 'source': x.source, 'message': x.data} for x in reversed(qs.order_by('-created', '-id')[:limit])]
|
return [{'date': x.created, 'level': x.level, 'source': x.source, 'message': x.data} for x in reversed(qs.order_by('-created', '-id')[:limit])]
|
||||||
|
|
||||||
def __clearLogs(self, owner_type, owner_id):
|
def __clearLogs(self, owner_type, owner_id):
|
||||||
'''
|
'''
|
||||||
Clears all logs related to user service
|
Clears all logs related to user service
|
||||||
'''
|
'''
|
||||||
from uds.models import Log
|
from uds.models import Log
|
||||||
|
|
||||||
Log.objects.filter(owner_id = owner_id, owner_type = owner_type).delete()
|
Log.objects.filter(owner_id=owner_id, owner_type=owner_type).delete()
|
||||||
|
|
||||||
|
def doLog(self, wichObject, level, message, source, avoidDuplicates=True):
|
||||||
|
|
||||||
def doLog(self, wichObject, level, message, source, avoidDuplicates = True):
|
|
||||||
'''
|
'''
|
||||||
Do the logging for the requested object.
|
Do the logging for the requested object.
|
||||||
|
|
||||||
If the object provided do not accepts associated loggin, it simply ignores the request
|
If the object provided do not accepts associated loggin, it simply ignores the request
|
||||||
'''
|
'''
|
||||||
if type(level) is not int:
|
if type(level) is not int:
|
||||||
level = log.logLevelFromStr(level)
|
level = log.logLevelFromStr(level)
|
||||||
|
|
||||||
owner_type = transDict.get(type(wichObject), None)
|
owner_type = transDict.get(type(wichObject), None)
|
||||||
if owner_type is not None:
|
if owner_type is not None:
|
||||||
self.__log(owner_type, wichObject.id, level, message, source, avoidDuplicates)
|
self.__log(owner_type, wichObject.id, level, message, source, avoidDuplicates)
|
||||||
else:
|
else:
|
||||||
logger.debug('Requested doLog for a type of object not covered: {0}'.format(wichObject))
|
logger.debug('Requested doLog for a type of object not covered: {0}'.format(wichObject))
|
||||||
|
|
||||||
|
|
||||||
def getLogs(self, wichObject, limit):
|
def getLogs(self, wichObject, limit):
|
||||||
'''
|
'''
|
||||||
Get the logs associated with "wichObject", limiting to "limit" (default is GlobalConfig.MAX_LOGS_PER_ELEMENT)
|
Get the logs associated with "wichObject", limiting to "limit" (default is GlobalConfig.MAX_LOGS_PER_ELEMENT)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
owner_type = transDict.get(type(wichObject), None)
|
owner_type = transDict.get(type(wichObject), None)
|
||||||
|
|
||||||
if owner_type is not None:
|
if owner_type is not None:
|
||||||
return self.__getLogs(owner_type, wichObject.id, limit)
|
return self.__getLogs(owner_type, wichObject.id, limit)
|
||||||
else:
|
else:
|
||||||
logger.debug('Requested getLogs for a type of object not covered: {0}'.format(wichObject))
|
logger.debug('Requested getLogs for a type of object not covered: {0}'.format(wichObject))
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def clearLogs(self, wichObject):
|
def clearLogs(self, wichObject):
|
||||||
'''
|
'''
|
||||||
Clears all logs related to wichObject
|
Clears all logs related to wichObject
|
||||||
|
|
||||||
Used mainly at object database removal (parent object)
|
Used mainly at object database removal (parent object)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
owner_type = transDict.get(type(wichObject), None)
|
owner_type = transDict.get(type(wichObject), None)
|
||||||
if owner_type is not None:
|
if owner_type is not None:
|
||||||
self.__clearLogs(owner_type, wichObject.id)
|
self.__clearLogs(owner_type, wichObject.id)
|
||||||
else:
|
else:
|
||||||
logger.debug('Requested clearLogs for a type of object not covered: {0}'.format(wichObject))
|
logger.debug('Requested clearLogs for a type of object not covered: {0}'.format(wichObject))
|
||||||
|
@ -3,27 +3,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -44,18 +44,19 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
PUBTAG = 'pm-'
|
PUBTAG = 'pm-'
|
||||||
|
|
||||||
|
|
||||||
class PublicationOldMachinesCleaner(DelayedTask):
|
class PublicationOldMachinesCleaner(DelayedTask):
|
||||||
def __init__(self, publicationId):
|
def __init__(self, publicationId):
|
||||||
super(PublicationOldMachinesCleaner,self).__init__()
|
super(PublicationOldMachinesCleaner, self).__init__()
|
||||||
self._id = publicationId
|
self._id = publicationId
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
dsp = DeployedServicePublication.objects.get(pk=self._id)
|
dsp = DeployedServicePublication.objects.get(pk=self._id)
|
||||||
if (dsp.state!=State.REMOVABLE):
|
if (dsp.state != State.REMOVABLE):
|
||||||
logger.info('Already removed')
|
logger.info('Already removed')
|
||||||
|
|
||||||
now = getSqlDatetime()
|
now = getSqlDatetime()
|
||||||
activePub = dsp.deployed_service.activePublication()
|
activePub = dsp.deployed_service.activePublication()
|
||||||
dsp.deployed_service.userServices.filter(in_use=True).update(in_use=False, state_date=now)
|
dsp.deployed_service.userServices.filter(in_use=True).update(in_use=False, state_date=now)
|
||||||
@ -65,17 +66,18 @@ class PublicationOldMachinesCleaner(DelayedTask):
|
|||||||
# Removed provider, no problem at all, no update is done
|
# Removed provider, no problem at all, no update is done
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class PublicationLauncher(DelayedTask):
|
class PublicationLauncher(DelayedTask):
|
||||||
def __init__(self, publish):
|
def __init__(self, publish):
|
||||||
super(PublicationLauncher,self).__init__()
|
super(PublicationLauncher, self).__init__()
|
||||||
self._publishId = publish.id
|
self._publishId = publish.id
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
logger.debug('Publishing')
|
logger.debug('Publishing')
|
||||||
try:
|
try:
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
dsp = DeployedServicePublication.objects.select_for_update().get(pk=self._publishId)
|
dsp = DeployedServicePublication.objects.select_for_update().get(pk=self._publishId)
|
||||||
if dsp.state != State.LAUNCHING: # If not preparing (may has been canceled by user) just return
|
if dsp.state != State.LAUNCHING: # If not preparing (may has been canceled by user) just return
|
||||||
return
|
return
|
||||||
dsp.state = State.PREPARING
|
dsp.state = State.PREPARING
|
||||||
dsp.save()
|
dsp.save()
|
||||||
@ -85,16 +87,16 @@ class PublicationLauncher(DelayedTask):
|
|||||||
deployedService.current_pub_revision += 1
|
deployedService.current_pub_revision += 1
|
||||||
deployedService.save()
|
deployedService.save()
|
||||||
PublicationFinishChecker.checkAndUpdateState(dsp, pi, state)
|
PublicationFinishChecker.checkAndUpdateState(dsp, pi, state)
|
||||||
except Exception as e:
|
except Exception:
|
||||||
logger.exception("Exception launching publication")
|
logger.exception("Exception launching publication")
|
||||||
dsp.state = State.ERROR
|
dsp.state = State.ERROR
|
||||||
dsp.save()
|
dsp.save()
|
||||||
|
|
||||||
|
|
||||||
# Delayed Task that checks if a publication is done
|
# Delayed Task that checks if a publication is done
|
||||||
class PublicationFinishChecker(DelayedTask):
|
class PublicationFinishChecker(DelayedTask):
|
||||||
def __init__(self, publish):
|
def __init__(self, publish):
|
||||||
super(PublicationFinishChecker,self).__init__()
|
super(PublicationFinishChecker, self).__init__()
|
||||||
self._publishId = publish.id
|
self._publishId = publish.id
|
||||||
self._state = publish.state
|
self._state = publish.state
|
||||||
|
|
||||||
@ -111,48 +113,48 @@ class PublicationFinishChecker(DelayedTask):
|
|||||||
# Now we mark, if it exists, the previous usable publication as "Removable"
|
# Now we mark, if it exists, the previous usable publication as "Removable"
|
||||||
if State.isPreparing(prevState):
|
if State.isPreparing(prevState):
|
||||||
for old in dsp.deployed_service.publications.filter(state=State.USABLE):
|
for old in dsp.deployed_service.publications.filter(state=State.USABLE):
|
||||||
old.state=State.REMOVABLE
|
old.state = State.REMOVABLE
|
||||||
old.save()
|
old.save()
|
||||||
pc = PublicationOldMachinesCleaner(old.id)
|
pc = PublicationOldMachinesCleaner(old.id)
|
||||||
pc.register(GlobalConfig.SESSION_EXPIRE_TIME.getInt(True)*3600, 'pclean-'+str(old.id), True)
|
pc.register(GlobalConfig.SESSION_EXPIRE_TIME.getInt(True) * 3600, 'pclean-' + str(old.id), True)
|
||||||
|
|
||||||
dsp.setState(State.USABLE)
|
dsp.setState(State.USABLE)
|
||||||
dsp.deployed_service.markOldUserServicesAsRemovables(dsp)
|
dsp.deployed_service.markOldUserServicesAsRemovables(dsp)
|
||||||
elif State.isRemoving(prevState):
|
elif State.isRemoving(prevState):
|
||||||
dsp.setState(State.REMOVED)
|
dsp.setState(State.REMOVED)
|
||||||
else: # State is canceling
|
else: # State is canceling
|
||||||
dsp.setState(State.CANCELED)
|
dsp.setState(State.CANCELED)
|
||||||
# Mark all previous publications deployed services as removables
|
# Mark all previous publications deployed services as removables
|
||||||
# and make this usable
|
# and make this usable
|
||||||
pi.finish()
|
pi.finish()
|
||||||
dsp.updateData(pi)
|
dsp.updateData(pi)
|
||||||
elif State.isErrored(state):
|
elif State.isErrored(state):
|
||||||
dsp.updateData(pi)
|
dsp.updateData(pi)
|
||||||
dsp.state = State.ERROR
|
dsp.state = State.ERROR
|
||||||
else:
|
else:
|
||||||
checkLater = True # The task is running
|
checkLater = True # The task is running
|
||||||
dsp.updateData(pi)
|
dsp.updateData(pi)
|
||||||
|
|
||||||
dsp.save()
|
dsp.save()
|
||||||
if checkLater:
|
if checkLater:
|
||||||
PublicationFinishChecker.checkLater(dsp, pi)
|
PublicationFinishChecker.checkLater(dsp, pi)
|
||||||
except:
|
except:
|
||||||
logger.exception('At checkAndUpdate for publication')
|
logger.exception('At checkAndUpdate for publication')
|
||||||
PublicationFinishChecker.checkLater(dsp, pi)
|
PublicationFinishChecker.checkLater(dsp, pi)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def checkLater(dsp, pi):
|
def checkLater(dsp, pi):
|
||||||
'''
|
'''
|
||||||
Inserts a task in the delayedTaskRunner so we can check the state of this publication
|
Inserts a task in the delayedTaskRunner so we can check the state of this publication
|
||||||
@param dps: Database object for DeployedServicePublication
|
@param dps: Database object for DeployedServicePublication
|
||||||
@param pi: Instance of Publication manager for the object
|
@param pi: Instance of Publication manager for the object
|
||||||
'''
|
'''
|
||||||
DelayedTaskRunner.runner().insert(PublicationFinishChecker(dsp), pi.suggestedTime, PUBTAG + str(dsp.id))
|
DelayedTaskRunner.runner().insert(PublicationFinishChecker(dsp), pi.suggestedTime, PUBTAG + str(dsp.id))
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def run(self):
|
def run(self):
|
||||||
logger.debug('Checking publication finished {0}'.format(self._publishId))
|
logger.debug('Checking publication finished {0}'.format(self._publishId))
|
||||||
try :
|
try:
|
||||||
dsp = DeployedServicePublication.objects.select_for_update().get(pk=self._publishId)
|
dsp = DeployedServicePublication.objects.select_for_update().get(pk=self._publishId)
|
||||||
if dsp.state != self._state:
|
if dsp.state != self._state:
|
||||||
logger.debug('Task overrided by another task (state of item changed)')
|
logger.debug('Task overrided by another task (state of item changed)')
|
||||||
@ -164,42 +166,42 @@ class PublicationFinishChecker(DelayedTask):
|
|||||||
except Exception, e:
|
except Exception, e:
|
||||||
logger.debug('Deployed service not found (erased from database) {0} : {1}'.format(e.__class__, e))
|
logger.debug('Deployed service not found (erased from database) {0} : {1}'.format(e.__class__, e))
|
||||||
|
|
||||||
|
|
||||||
class PublicationManager(object):
|
class PublicationManager(object):
|
||||||
_manager = None
|
_manager = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def manager():
|
def manager():
|
||||||
if PublicationManager._manager == None:
|
if PublicationManager._manager == None:
|
||||||
PublicationManager._manager = PublicationManager()
|
PublicationManager._manager = PublicationManager()
|
||||||
return PublicationManager._manager
|
return PublicationManager._manager
|
||||||
|
|
||||||
|
|
||||||
def publish(self, deployedService):
|
def publish(self, deployedService):
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
if deployedService.publications.select_for_update().filter(state__in=State.PUBLISH_STATES).count() > 0:
|
if deployedService.publications.select_for_update().filter(state__in=State.PUBLISH_STATES).count() > 0:
|
||||||
raise PublishException(_('Already publishing. Wait for previous publication to finish and try again'))
|
raise PublishException(_('Already publishing. Wait for previous publication to finish and try again'))
|
||||||
try:
|
try:
|
||||||
now = getSqlDatetime()
|
now = getSqlDatetime()
|
||||||
dsp = deployedService.publications.create(state = State.LAUNCHING, state_date = now, publish_date = now, revision = deployedService.current_pub_revision)
|
dsp = deployedService.publications.create(state=State.LAUNCHING, state_date=now, publish_date=now, revision=deployedService.current_pub_revision)
|
||||||
DelayedTaskRunner.runner().insert(PublicationLauncher(dsp), 4, PUBTAG + str(dsp.id))
|
DelayedTaskRunner.runner().insert(PublicationLauncher(dsp), 4, PUBTAG + str(dsp.id))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug('Caught exception at publish: {0}'.format(e))
|
logger.debug('Caught exception at publish: {0}'.format(e))
|
||||||
raise PublishException(str(e))
|
raise PublishException(str(e))
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def cancel(self,dsp):
|
def cancel(self, dsp):
|
||||||
dsp = DeployedServicePublication.objects.select_for_update().get(id=dsp.id)
|
dsp = DeployedServicePublication.objects.select_for_update().get(id=dsp.id)
|
||||||
if dsp.state not in State.PUBLISH_STATES:
|
if dsp.state not in State.PUBLISH_STATES:
|
||||||
raise PublishException(_('Can\'t cancel non running publication'))
|
raise PublishException(_('Can\'t cancel non running publication'))
|
||||||
|
|
||||||
if dsp.state == State.LAUNCHING:
|
if dsp.state == State.LAUNCHING:
|
||||||
dsp.state = State.CANCELED
|
dsp.state = State.CANCELED
|
||||||
dsp.save()
|
dsp.save()
|
||||||
return dsp
|
return dsp
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pi = dsp.getInstance()
|
pi = dsp.getInstance()
|
||||||
state = pi.cancel()
|
state = pi.cancel()
|
||||||
@ -208,7 +210,7 @@ class PublicationManager(object):
|
|||||||
return dsp
|
return dsp
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
raise PublishException(str(e))
|
raise PublishException(str(e))
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def unpublish(self, dsp):
|
def unpublish(self, dsp):
|
||||||
if State.isUsable(dsp.state) == False and State.isRemovable(dsp.state) == False:
|
if State.isUsable(dsp.state) == False and State.isRemovable(dsp.state) == False:
|
||||||
@ -223,4 +225,3 @@ class PublicationManager(object):
|
|||||||
PublicationFinishChecker.checkAndUpdateState(dsp, pi, state)
|
PublicationFinishChecker.checkAndUpdateState(dsp, pi, state)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
raise PublishException(str(e))
|
raise PublishException(str(e))
|
||||||
|
|
||||||
|
@ -3,34 +3,35 @@
|
|||||||
# Copyright (c) 2013 Virtual Cable S.L.
|
# Copyright (c) 2013 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from uds.core.util.Config import GlobalConfig
|
from uds.core.util.Config import GlobalConfig
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -40,33 +41,32 @@ logger = logging.getLogger(__name__)
|
|||||||
class StatsManager(object):
|
class StatsManager(object):
|
||||||
'''
|
'''
|
||||||
Manager for loggins statistics, so we can provide usefull info about platform usage
|
Manager for loggins statistics, so we can provide usefull info about platform usage
|
||||||
|
|
||||||
Right now, we are going to provide an interface to "counter stats", that is, statistics
|
Right now, we are going to provide an interface to "counter stats", that is, statistics
|
||||||
that has counters (such as how many users is at a time active at platform, how many services
|
that has counters (such as how many users is at a time active at platform, how many services
|
||||||
are assigned, are in use, in cache, etc...
|
are assigned, are in use, in cache, etc...
|
||||||
'''
|
'''
|
||||||
_manager = None
|
_manager = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def manager():
|
def manager():
|
||||||
if StatsManager._manager == None:
|
if StatsManager._manager == None:
|
||||||
StatsManager._manager = StatsManager()
|
StatsManager._manager = StatsManager()
|
||||||
return StatsManager._manager
|
return StatsManager._manager
|
||||||
|
|
||||||
|
|
||||||
def __doCleanup(self, dbTable):
|
def __doCleanup(self, dbTable):
|
||||||
from uds.models import getSqlDatetime, optimizeTable
|
from uds.models import getSqlDatetime, optimizeTable
|
||||||
from django.db import connection, transaction
|
from django.db import connection
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
|
|
||||||
minTime = time.mktime( (getSqlDatetime() - datetime.timedelta(days = GlobalConfig.STATS_DURATION.getInt())).timetuple() )
|
minTime = time.mktime((getSqlDatetime() - datetime.timedelta(days=GlobalConfig.STATS_DURATION.getInt())).timetuple())
|
||||||
|
|
||||||
# Don't like how django executes this (recovers all IDS and lauches "DELETE .. WHERE id IN ...)
|
# Don't like how django executes this (recovers all IDS and lauches "DELETE .. WHERE id IN ...)
|
||||||
#StatsCounters.objects.filter(stamp__lt=minTime).delete()
|
# StatsCounters.objects.filter(stamp__lt=minTime).delete()
|
||||||
# Used dict, cause environment says _meta is not known :-)
|
# Used dict, cause environment says _meta is not known :-)
|
||||||
query = 'DELETE FROM {0} where STAMP < {1}'.format(dbTable, minTime)
|
query = 'DELETE FROM {0} where STAMP < {1}'.format(dbTable, minTime)
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
@ -74,15 +74,14 @@ class StatsManager(object):
|
|||||||
# This table will hold a big amount of data, and mayby we erase a a big number of records also.
|
# This table will hold a big amount of data, and mayby we erase a a big number of records also.
|
||||||
# This will ensure table is in "good" shape (testing right now, will see at future)
|
# This will ensure table is in "good" shape (testing right now, will see at future)
|
||||||
optimizeTable(dbTable)
|
optimizeTable(dbTable)
|
||||||
|
|
||||||
|
|
||||||
# Counter stats
|
# Counter stats
|
||||||
def addCounter(self, owner_type, owner_id, counterType, counterValue, stamp = None):
|
def addCounter(self, owner_type, owner_id, counterType, counterValue, stamp=None):
|
||||||
'''
|
'''
|
||||||
Adds a new counter stats to database.
|
Adds a new counter stats to database.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|
||||||
owner_type: type of owner (integer, from internal tables)
|
owner_type: type of owner (integer, from internal tables)
|
||||||
owner_id: id of the owner
|
owner_id: id of the owner
|
||||||
counterType: The type of counter that will receive the value (look at uds.core.util.stats.counters module)
|
counterType: The type of counter that will receive the value (look at uds.core.util.stats.counters module)
|
||||||
@ -91,115 +90,111 @@ class StatsManager(object):
|
|||||||
(this has a granurality of seconds)
|
(this has a granurality of seconds)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
Nothing
|
Nothing
|
||||||
'''
|
'''
|
||||||
from uds.models import getSqlDatetime, StatsCounters
|
from uds.models import getSqlDatetime, StatsCounters
|
||||||
import time
|
import time
|
||||||
|
|
||||||
if stamp is None:
|
if stamp is None:
|
||||||
stamp = getSqlDatetime()
|
stamp = getSqlDatetime()
|
||||||
|
|
||||||
# To Unix epoch
|
# To Unix epoch
|
||||||
stamp = int(time.mktime(stamp.timetuple()))
|
stamp = int(time.mktime(stamp.timetuple()))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
StatsCounters.objects.create(owner_type=owner_type, owner_id=owner_id, counter_type=counterType, value=counterValue, stamp=stamp)
|
StatsCounters.objects.create(owner_type=owner_type, owner_id=owner_id, counter_type=counterType, value=counterValue, stamp=stamp)
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
logger.error('Exception handling counter stats saving (maybe database is full?)')
|
logger.error('Exception handling counter stats saving (maybe database is full?)')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def getCounters(self, ownerType, counterType, ownerIds, since, to, limit, use_max=False):
|
||||||
def getCounters(self, ownerType, counterType, ownerIds, since, to, limit, use_max = False):
|
|
||||||
'''
|
'''
|
||||||
Retrieves counters from item
|
Retrieves counters from item
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|
||||||
counterTye: Type of counter to get values
|
counterTye: Type of counter to get values
|
||||||
counterId: (optional), if specified, limit counter to only this id, all ids for specidied type if not
|
counterId: (optional), if specified, limit counter to only this id, all ids for specidied type if not
|
||||||
maxElements: (optional) Maximum number of elements to retrieve, all if nothing specified
|
maxElements: (optional) Maximum number of elements to retrieve, all if nothing specified
|
||||||
from: date from what to obtain counters. Unlimited if not specified
|
from: date from what to obtain counters. Unlimited if not specified
|
||||||
to: date until obtain counters. Unlimited if not specified
|
to: date until obtain counters. Unlimited if not specified
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
Iterator, containing (date, counter) each element
|
Iterator, containing (date, counter) each element
|
||||||
'''
|
'''
|
||||||
from uds.models import StatsCounters
|
from uds.models import StatsCounters
|
||||||
import time
|
import time
|
||||||
|
|
||||||
# To Unix epoch
|
# To Unix epoch
|
||||||
since = int(time.mktime(since.timetuple()))
|
since = int(time.mktime(since.timetuple()))
|
||||||
to = int(time.mktime(to.timetuple()))
|
to = int(time.mktime(to.timetuple()))
|
||||||
|
|
||||||
return StatsCounters.get_grouped(ownerType, counterType, owner_id = ownerIds, since = since, to = to, limit = limit, use_max = use_max)
|
return StatsCounters.get_grouped(ownerType, counterType, owner_id=ownerIds, since=since, to=to, limit=limit, use_max=use_max)
|
||||||
|
|
||||||
|
|
||||||
def cleanupCounters(self):
|
def cleanupCounters(self):
|
||||||
'''
|
'''
|
||||||
Removes all counters previous to configured max keep time for stat information from database.
|
Removes all counters previous to configured max keep time for stat information from database.
|
||||||
'''
|
'''
|
||||||
from uds.models import StatsCounters
|
from uds.models import StatsCounters
|
||||||
|
|
||||||
self.__doCleanup(StatsCounters.__dict__['_meta'].db_table)
|
self.__doCleanup(StatsCounters.__dict__['_meta'].db_table)
|
||||||
|
|
||||||
# Event stats
|
# Event stats
|
||||||
# Counter stats
|
# Counter stats
|
||||||
def addEvent(self, owner_type, owner_id, eventType, stamp = None):
|
def addEvent(self, owner_type, owner_id, eventType, stamp=None):
|
||||||
'''
|
'''
|
||||||
Adds a new event stat to database.
|
Adds a new event stat to database.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|
||||||
toWhat: if of the counter
|
toWhat: if of the counter
|
||||||
stamp: if not None, this will be used as date for cuounter, else current date/time will be get
|
stamp: if not None, this will be used as date for cuounter, else current date/time will be get
|
||||||
(this has a granurality of seconds)
|
(this has a granurality of seconds)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
Nothing
|
Nothing
|
||||||
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
from uds.models import getSqlDatetime, StatsEvents
|
from uds.models import getSqlDatetime, StatsEvents
|
||||||
import time
|
import time
|
||||||
|
|
||||||
if stamp is None:
|
if stamp is None:
|
||||||
stamp = getSqlDatetime()
|
stamp = getSqlDatetime()
|
||||||
|
|
||||||
# To Unix epoch
|
# To Unix epoch
|
||||||
stamp = int(time.mktime(stamp.timetuple()))
|
stamp = int(time.mktime(stamp.timetuple()))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
StatsEvents.objects.create(owner_type=owner_type, owner_id=owner_id, event_type=eventType, stamp=stamp)
|
StatsEvents.objects.create(owner_type=owner_type, owner_id=owner_id, event_type=eventType, stamp=stamp)
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
logger.error('Exception handling event stats saving (maybe database is full?)')
|
logger.error('Exception handling event stats saving (maybe database is full?)')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def getEvents(self, fromWhat, **kwargs):
|
def getEvents(self, fromWhat, **kwargs):
|
||||||
'''
|
'''
|
||||||
Retrieves counters from item
|
Retrieves counters from item
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|
||||||
fromWhat: From what object to get counters
|
fromWhat: From what object to get counters
|
||||||
maxElements: (optional) Maximum number of elements to retrieve
|
maxElements: (optional) Maximum number of elements to retrieve
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
Array of lists, containing (date, counter)
|
Array of lists, containing (date, counter)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def cleanupEvents(self):
|
def cleanupEvents(self):
|
||||||
'''
|
'''
|
||||||
Removes all events previous to configured max keep time for stat information from database.
|
Removes all events previous to configured max keep time for stat information from database.
|
||||||
'''
|
'''
|
||||||
from uds.models import StatsEvents
|
from uds.models import StatsEvents
|
||||||
|
|
||||||
self.__doCleanup(StatsEvents.__dict__['_meta'].db_table)
|
|
||||||
|
|
||||||
|
self.__doCleanup(StatsEvents.__dict__['_meta'].db_table)
|
||||||
|
@ -4,48 +4,54 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from uds.core.jobs.Scheduler import Scheduler
|
from uds.core.jobs.Scheduler import Scheduler
|
||||||
from uds.core.jobs.DelayedTaskRunner import DelayedTaskRunner
|
from uds.core.jobs.DelayedTaskRunner import DelayedTaskRunner
|
||||||
from uds.core import jobs
|
from uds.core import jobs
|
||||||
from uds.core.util.Config import GlobalConfig
|
from uds.core.util.Config import GlobalConfig
|
||||||
import threading, time, signal
|
import threading
|
||||||
|
import time
|
||||||
|
import signal
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SchedulerThread(threading.Thread):
|
class SchedulerThread(threading.Thread):
|
||||||
def run(self):
|
def run(self):
|
||||||
Scheduler.scheduler().run()
|
Scheduler.scheduler().run()
|
||||||
|
|
||||||
def notifyTermination(self):
|
def notifyTermination(self):
|
||||||
Scheduler.scheduler().notifyTermination()
|
Scheduler.scheduler().notifyTermination()
|
||||||
|
|
||||||
|
|
||||||
class DelayedTaskThread(threading.Thread):
|
class DelayedTaskThread(threading.Thread):
|
||||||
def run(self):
|
def run(self):
|
||||||
DelayedTaskRunner.runner().run()
|
DelayedTaskRunner.runner().run()
|
||||||
@ -56,7 +62,7 @@ class DelayedTaskThread(threading.Thread):
|
|||||||
|
|
||||||
class TaskManager(object):
|
class TaskManager(object):
|
||||||
keepRunning = True
|
keepRunning = True
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sigTerm(sigNum, frame):
|
def sigTerm(sigNum, frame):
|
||||||
'''
|
'''
|
||||||
@ -69,59 +75,56 @@ class TaskManager(object):
|
|||||||
'''
|
'''
|
||||||
logger.info("Caught term signal, finishing task manager")
|
logger.info("Caught term signal, finishing task manager")
|
||||||
TaskManager.keepRunning = False
|
TaskManager.keepRunning = False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def registerJob(jobType):
|
def registerJob(jobType):
|
||||||
jobName = jobType.friendly_name
|
jobName = jobType.friendly_name
|
||||||
jobs.factory().insert(jobName, jobType)
|
jobs.factory().insert(jobName, jobType)
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def registerScheduledTasks():
|
def registerScheduledTasks():
|
||||||
|
|
||||||
logger.info("Registering sheduled tasks")
|
logger.info("Registering sheduled tasks")
|
||||||
from uds.core import workers
|
# Simply import this to make workers "auto import"
|
||||||
|
from uds.core import workers # @UnusedImport
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run():
|
def run():
|
||||||
TaskManager.keepRunning = True
|
TaskManager.keepRunning = True
|
||||||
# Runs Scheduler in a separate thread and DelayedTasks here
|
# Runs Scheduler in a separate thread and DelayedTasks here
|
||||||
|
|
||||||
TaskManager.registerScheduledTasks()
|
TaskManager.registerScheduledTasks()
|
||||||
|
|
||||||
noSchedulers = GlobalConfig.SCHEDULER_THREADS.getInt()
|
noSchedulers = GlobalConfig.SCHEDULER_THREADS.getInt()
|
||||||
noDelayedTasks = GlobalConfig.DELAYED_TASKS_THREADS.getInt()
|
noDelayedTasks = GlobalConfig.DELAYED_TASKS_THREADS.getInt()
|
||||||
|
|
||||||
logger.info('Starting {0} schedulers and {1} task executors'.format(noSchedulers, noDelayedTasks))
|
logger.info('Starting {0} schedulers and {1} task executors'.format(noSchedulers, noDelayedTasks))
|
||||||
|
|
||||||
threads = []
|
threads = []
|
||||||
for n in range(noSchedulers):
|
for _ in range(noSchedulers):
|
||||||
thread = SchedulerThread()
|
thread = SchedulerThread()
|
||||||
thread.start()
|
thread.start()
|
||||||
threads.append(thread)
|
threads.append(thread)
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
for n in range(noDelayedTasks):
|
for _ in range(noDelayedTasks):
|
||||||
thread = DelayedTaskThread()
|
thread = DelayedTaskThread()
|
||||||
thread.start()
|
thread.start()
|
||||||
threads.append(thread)
|
threads.append(thread)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
signal.signal(signal.SIGTERM, TaskManager.sigTerm)
|
|
||||||
|
|
||||||
|
|
||||||
# Debugging stuff
|
|
||||||
#import guppy
|
|
||||||
#from guppy.heapy import Remote
|
|
||||||
#Remote.on()
|
|
||||||
|
|
||||||
#gc.set_debug(gc.DEBUG_LEAK)
|
signal.signal(signal.SIGTERM, TaskManager.sigTerm)
|
||||||
while( TaskManager.keepRunning ):
|
|
||||||
|
# Debugging stuff
|
||||||
|
# import guppy
|
||||||
|
# from guppy.heapy import Remote
|
||||||
|
# Remote.on()
|
||||||
|
|
||||||
|
# gc.set_debug(gc.DEBUG_LEAK)
|
||||||
|
while(TaskManager.keepRunning):
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
for thread in threads:
|
for thread in threads:
|
||||||
thread.notifyTermination()
|
thread.notifyTermination()
|
||||||
|
|
||||||
# The join of threads will happen before termination, so its fine to just return here
|
# The join of threads will happen before termination, so its fine to just return here
|
||||||
|
|
||||||
|
@ -4,32 +4,33 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||||
@ -39,27 +40,28 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class UserPrefsManager(object):
|
class UserPrefsManager(object):
|
||||||
_manager = None
|
_manager = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._prefs = {}
|
self._prefs = {}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def manager():
|
def manager():
|
||||||
if UserPrefsManager._manager == None:
|
if UserPrefsManager._manager == None:
|
||||||
UserPrefsManager._manager = UserPrefsManager()
|
UserPrefsManager._manager = UserPrefsManager()
|
||||||
return UserPrefsManager._manager
|
return UserPrefsManager._manager
|
||||||
|
|
||||||
def __nameFor(self, module, name):
|
def __nameFor(self, module, name):
|
||||||
return module + "_" + name
|
return module + "_" + name
|
||||||
|
|
||||||
def registerPrefs(self, modName, friendlyModName, prefs):
|
def registerPrefs(self, modName, friendlyModName, prefs):
|
||||||
'''
|
'''
|
||||||
Register an array of preferences for a module
|
Register an array of preferences for a module
|
||||||
'''
|
'''
|
||||||
self._prefs[modName] = { 'friendlyName' : friendlyModName, 'prefs' : prefs }
|
self._prefs[modName] = {'friendlyName': friendlyModName, 'prefs': prefs}
|
||||||
|
|
||||||
def getPreferencesForUser(self, modName, user):
|
def getPreferencesForUser(self, modName, user):
|
||||||
'''
|
'''
|
||||||
Gets the preferences for an specified module for the user
|
Gets the preferences for an specified module for the user
|
||||||
@ -68,10 +70,10 @@ class UserPrefsManager(object):
|
|||||||
for up in user.preferences.filter(module=modName):
|
for up in user.preferences.filter(module=modName):
|
||||||
prefs[up.name] = up.value
|
prefs[up.name] = up.value
|
||||||
for p in self._prefs[modName]['prefs']:
|
for p in self._prefs[modName]['prefs']:
|
||||||
if prefs.has_key(p.getName()) is False:
|
if p.getName() not in prefs:
|
||||||
prefs[p.getName()] = p.getDefValue()
|
prefs[p.getName()] = p.getDefValue()
|
||||||
return prefs
|
return prefs
|
||||||
|
|
||||||
def getHtmlForUserPreferences(self, user):
|
def getHtmlForUserPreferences(self, user):
|
||||||
# First fill data for all preferences
|
# First fill data for all preferences
|
||||||
data = {}
|
data = {}
|
||||||
@ -82,11 +84,11 @@ class UserPrefsManager(object):
|
|||||||
form = forms.Form()
|
form = forms.Form()
|
||||||
for p in v['prefs']:
|
for p in v['prefs']:
|
||||||
name = self.__nameFor(mod, p.getName())
|
name = self.__nameFor(mod, p.getName())
|
||||||
val = data[name] if data.has_key(name) else p.getDefValue()
|
val = data[name] if name in data else p.getDefValue()
|
||||||
form.fields[ name ] = p.formField(val)
|
form.fields[name] = p.formField(val)
|
||||||
res += '<fieldset class="prefset"><legend>' + v['friendlyName'] + '</legend>' + form.as_p() + '</fieldset>'
|
res += '<fieldset class="prefset"><legend>' + v['friendlyName'] + '</legend>' + form.as_p() + '</fieldset>'
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getGuiForUserPreferences(self, user=None):
|
def getGuiForUserPreferences(self, user=None):
|
||||||
data = {}
|
data = {}
|
||||||
if user is not None:
|
if user is not None:
|
||||||
@ -97,12 +99,11 @@ class UserPrefsManager(object):
|
|||||||
grp = []
|
grp = []
|
||||||
for p in v['prefs']:
|
for p in v['prefs']:
|
||||||
name = self.__nameFor(mod, p.getName())
|
name = self.__nameFor(mod, p.getName())
|
||||||
val = data[name] if data.has_key(name) else p.getDefValue()
|
val = data[name] if name in data else p.getDefValue()
|
||||||
grp.append( { 'name' : name, 'gui' : p.guiField(val).guiDescription(), 'value' : val } )
|
grp.append({'name': name, 'gui': p.guiField(val).guiDescription(), 'value': val})
|
||||||
res.append( {'moduleLabel': v['friendlyName'], 'prefs': grp} )
|
res.append({'moduleLabel': v['friendlyName'], 'prefs': grp})
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
def processRequestForUserPreferences(self, user, data):
|
def processRequestForUserPreferences(self, user, data):
|
||||||
'''
|
'''
|
||||||
Returns a list of errors in case of error, else return None
|
Returns a list of errors in case of error, else return None
|
||||||
@ -122,12 +123,12 @@ class UserPrefsManager(object):
|
|||||||
for p in v['prefs']:
|
for p in v['prefs']:
|
||||||
name = self.__nameFor(mod, p.getName())
|
name = self.__nameFor(mod, p.getName())
|
||||||
logger.debug(name)
|
logger.debug(name)
|
||||||
prefs.append({ 'module': mod, 'name': p.getName(), 'value': form.cleaned_data[name] } )
|
prefs.append({'module': mod, 'name': p.getName(), 'value': form.cleaned_data[name]})
|
||||||
user.preferences.all().delete()
|
user.preferences.all().delete()
|
||||||
for p in prefs:
|
for p in prefs:
|
||||||
user.preferences.create(module=p['module'], name=p['name'], value=p['value'])
|
user.preferences.create(module=p['module'], name=p['name'], value=p['value'])
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def processGuiForUserPreferences(self, user, data):
|
def processGuiForUserPreferences(self, user, data):
|
||||||
'''
|
'''
|
||||||
'''
|
'''
|
||||||
@ -137,85 +138,91 @@ class UserPrefsManager(object):
|
|||||||
logger.debug(mod)
|
logger.debug(mod)
|
||||||
for p in v['prefs']:
|
for p in v['prefs']:
|
||||||
name = self.__nameFor(mod, p.getName())
|
name = self.__nameFor(mod, p.getName())
|
||||||
if data.has_key(name):
|
if name in data:
|
||||||
prefs.append( { 'module': mod, 'name': p.getName(), 'value': data[name] } )
|
prefs.append({'module': mod, 'name': p.getName(), 'value': data[name]})
|
||||||
user.preferences.all().delete()
|
user.preferences.all().delete()
|
||||||
for p in prefs:
|
for p in prefs:
|
||||||
user.preferences.create(module=p['module'], name=p['name'], value=p['value'])
|
user.preferences.create(module=p['module'], name=p['name'], value=p['value'])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class UserPreference(object):
|
class UserPreference(object):
|
||||||
TYPE = 'abstract'
|
TYPE = 'abstract'
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self._name = kwargs['name']
|
self._name = kwargs['name']
|
||||||
self._label = kwargs['label']
|
self._label = kwargs['label']
|
||||||
self._defValue = kwargs['defvalue'] if kwargs.has_key('defvalue') else None
|
self._defValue = kwargs.get('defvalue', None)
|
||||||
self._css = 'form-control'
|
self._css = 'form-control'
|
||||||
|
|
||||||
def getName(self):
|
def getName(self):
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
def getDefValue(self):
|
def getDefValue(self):
|
||||||
return self._defValue
|
return self._defValue
|
||||||
|
|
||||||
def formField(self, value):
|
def formField(self, value):
|
||||||
'''
|
'''
|
||||||
Returns a form field to add to the preferences form
|
Returns a form field to add to the preferences form
|
||||||
'''
|
'''
|
||||||
raise NameError('Can\'t create an abstract preference!!!')
|
raise NameError('Can\'t create an abstract preference!!!')
|
||||||
|
|
||||||
def guiField(self):
|
def guiField(self):
|
||||||
'''
|
'''
|
||||||
'''
|
'''
|
||||||
raise NameError('Can\'t create an abstract preference!!!')
|
raise NameError('Can\'t create an abstract preference!!!')
|
||||||
|
|
||||||
|
|
||||||
class UserTextPreference(UserPreference):
|
class UserTextPreference(UserPreference):
|
||||||
TYPE = 'text'
|
TYPE = 'text'
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(self.__class__,self).__init__(**kwargs)
|
super(self.__class__, self).__init__(**kwargs)
|
||||||
self._length = kwargs['length'] if kwargs.has_key('length') else None
|
self._length = kwargs.get('length', None)
|
||||||
|
|
||||||
def formField(self, value):
|
|
||||||
return forms.CharField(label = _(self._label), initial = value, attrs = {'class': self._css})
|
|
||||||
|
|
||||||
|
|
||||||
class UserNumericPreference(UserPreference):
|
|
||||||
TYPE = 'numeric'
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
super(self.__class__,self).__init__(**kwargs)
|
|
||||||
self._min = kwargs['minvalue'] if kwargs.has_key('minvalue') else None
|
|
||||||
self._max = kwargs['maxvalue'] if kwargs.has_key('maxvalue') else None
|
|
||||||
|
|
||||||
def formField(self, value):
|
def formField(self, value):
|
||||||
return forms.IntegerField(label = _(self._label), initial = value, min_value = self._min, max_value = self._max,
|
return forms.CharField(label=_(self._label), initial=value, attrs={'class': self._css})
|
||||||
widget = forms.TextInput(attrs = {'class': self._css}))
|
|
||||||
|
|
||||||
|
class UserNumericPreference(UserPreference):
|
||||||
|
TYPE = 'numeric'
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(self.__class__, self).__init__(**kwargs)
|
||||||
|
self._min = kwargs.get('minvalue', None)
|
||||||
|
self._max = kwargs.get('maxvalue', None)
|
||||||
|
|
||||||
|
def formField(self, value):
|
||||||
|
return forms.IntegerField(label=_(self._label), initial=value, min_value=self._min, max_value=self._max,
|
||||||
|
widget=forms.TextInput(attrs={'class': self._css}))
|
||||||
|
|
||||||
|
|
||||||
class UserChoicePreference(UserPreference):
|
class UserChoicePreference(UserPreference):
|
||||||
TYPE = 'choice'
|
TYPE = 'choice'
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(self.__class__,self).__init__(**kwargs)
|
super(self.__class__, self).__init__(**kwargs)
|
||||||
'''
|
'''
|
||||||
Values are a tuple of
|
Values are a tuple of
|
||||||
'''
|
'''
|
||||||
self._values = kwargs['values']
|
self._values = kwargs['values']
|
||||||
|
|
||||||
def formField(self, value):
|
def formField(self, value):
|
||||||
return forms.ChoiceField(label = _(self._label), initial = value, choices = self._values,
|
return forms.ChoiceField(label=_(self._label), initial=value, choices=self._values,
|
||||||
widget = forms.Select(attrs = {'class': self._css}))
|
widget=forms.Select(attrs={'class': self._css}))
|
||||||
|
|
||||||
def guiField(self, value):
|
def guiField(self, value):
|
||||||
vals = []
|
vals = []
|
||||||
for v in self._values:
|
for v in self._values:
|
||||||
vals.append( { 'id': v[0], 'text': _(v[1]) } )
|
vals.append({'id': v[0], 'text': _(v[1])})
|
||||||
return gui.ChoiceField(label = _(self._label), rdonly = False, values = vals, defvalue=value, tooltip = _(self._label))
|
return gui.ChoiceField(label=_(self._label), rdonly=False, values=vals, defvalue=value, tooltip=_(self._label))
|
||||||
|
|
||||||
|
|
||||||
class UserCheckboxPreference(UserPreference):
|
class UserCheckboxPreference(UserPreference):
|
||||||
TYPE = 'checkbox'
|
TYPE = 'checkbox'
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(self.__class__,self).__init__(**kwargs)
|
super(self.__class__, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class CommonPrefs(object):
|
class CommonPrefs(object):
|
||||||
SZ_PREF = 'screenSize'
|
SZ_PREF = 'screenSize'
|
||||||
@ -223,49 +230,51 @@ class CommonPrefs(object):
|
|||||||
SZ_800x600 = '2'
|
SZ_800x600 = '2'
|
||||||
SZ_1024x768 = '3'
|
SZ_1024x768 = '3'
|
||||||
SZ_FULLSCREEN = 'F'
|
SZ_FULLSCREEN = 'F'
|
||||||
|
|
||||||
DEPTH_PREF = 'screenDepth'
|
DEPTH_PREF = 'screenDepth'
|
||||||
DEPTH_8 = '1'
|
DEPTH_8 = '1'
|
||||||
DEPTH_16 = '2'
|
DEPTH_16 = '2'
|
||||||
DEPTH_24 = '3'
|
DEPTH_24 = '3'
|
||||||
DEPTH_32 = '4'
|
DEPTH_32 = '4'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getWidthHeight(prefsDict):
|
def getWidthHeight(prefsDict):
|
||||||
'''
|
'''
|
||||||
Get width based on screenSizePref value
|
Get width based on screenSizePref value
|
||||||
'''
|
'''
|
||||||
return { CommonPrefs.SZ_640x480 : (640, 480),
|
return {
|
||||||
CommonPrefs.SZ_800x600 : (800, 600),
|
CommonPrefs.SZ_640x480: (640, 480),
|
||||||
CommonPrefs.SZ_1024x768 : (1024, 768),
|
CommonPrefs.SZ_800x600: (800, 600),
|
||||||
CommonPrefs.SZ_FULLSCREEN : (-1, -1)
|
CommonPrefs.SZ_1024x768: (1024, 768),
|
||||||
}[prefsDict[CommonPrefs.SZ_PREF]]
|
CommonPrefs.SZ_FULLSCREEN: (-1, -1)
|
||||||
|
}[prefsDict[CommonPrefs.SZ_PREF]]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getDepth(prefsDict):
|
def getDepth(prefsDict):
|
||||||
'''
|
'''
|
||||||
Get depth based on depthPref value
|
Get depth based on depthPref value
|
||||||
'''
|
'''
|
||||||
return { CommonPrefs.DEPTH_8 : 8,
|
return {
|
||||||
CommonPrefs.DEPTH_16 : 16,
|
CommonPrefs.DEPTH_8: 8,
|
||||||
CommonPrefs.DEPTH_24 : 24,
|
CommonPrefs.DEPTH_16: 16,
|
||||||
CommonPrefs.DEPTH_32 : 32 }[ prefsDict[CommonPrefs.DEPTH_PREF] ]
|
CommonPrefs.DEPTH_24: 24,
|
||||||
|
CommonPrefs.DEPTH_32: 32
|
||||||
|
}[prefsDict[CommonPrefs.DEPTH_PREF]]
|
||||||
|
|
||||||
|
screenSizePref = UserChoicePreference(name=SZ_PREF,
|
||||||
screenSizePref = UserChoicePreference(name = SZ_PREF, label = ugettext_lazy('Screen Size'), defvalue = SZ_FULLSCREEN, values = (
|
label=ugettext_lazy('Screen Size'),
|
||||||
(SZ_640x480, '640x480'),
|
defvalue=SZ_FULLSCREEN,
|
||||||
(SZ_800x600, '800x600'),
|
values=(
|
||||||
(SZ_1024x768, '1024x768'),
|
(SZ_640x480, '640x480'),
|
||||||
(SZ_FULLSCREEN, ugettext_lazy('Full Screen'))
|
(SZ_800x600, '800x600'),
|
||||||
)
|
(SZ_1024x768, '1024x768'),
|
||||||
|
(SZ_FULLSCREEN, ugettext_lazy('Full Screen'))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
depthPref = UserChoicePreference(name=DEPTH_PREF, label=ugettext_lazy('Screen colors'), defvalue=DEPTH_24, values=(
|
||||||
|
(DEPTH_8, ugettext_lazy('8 bits')),
|
||||||
|
(DEPTH_16, ugettext_lazy('16 bits')),
|
||||||
|
(DEPTH_24, ugettext_lazy('24 bits')),
|
||||||
|
(DEPTH_32, ugettext_lazy('32 bits')),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
depthPref = UserChoicePreference(name = DEPTH_PREF, label = ugettext_lazy('Screen colors'), defvalue = DEPTH_24, values = (
|
|
||||||
(DEPTH_8, ugettext_lazy('8 bits')),
|
|
||||||
(DEPTH_16, ugettext_lazy('16 bits')),
|
|
||||||
(DEPTH_24, ugettext_lazy('24 bits')),
|
|
||||||
(DEPTH_32, ugettext_lazy('32 bits')),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
@ -4,32 +4,33 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
@ -50,9 +51,10 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
USERSERVICE_TAG = 'cm-'
|
USERSERVICE_TAG = 'cm-'
|
||||||
|
|
||||||
|
|
||||||
class UserServiceOpChecker(DelayedTask):
|
class UserServiceOpChecker(DelayedTask):
|
||||||
def __init__(self, service):
|
def __init__(self, service):
|
||||||
super(UserServiceOpChecker,self).__init__()
|
super(UserServiceOpChecker, self).__init__()
|
||||||
self._svrId = service.id
|
self._svrId = service.id
|
||||||
self._state = service.state
|
self._state = service.state
|
||||||
|
|
||||||
@ -60,10 +62,10 @@ class UserServiceOpChecker(DelayedTask):
|
|||||||
def makeUnique(userService, userServiceInstance, state):
|
def makeUnique(userService, userServiceInstance, state):
|
||||||
'''
|
'''
|
||||||
This method makes sure that there will be only one delayedtask related to the userService indicated
|
This method makes sure that there will be only one delayedtask related to the userService indicated
|
||||||
'''
|
'''
|
||||||
DelayedTaskRunner.runner().remove(USERSERVICE_TAG + str(userService.id))
|
DelayedTaskRunner.runner().remove(USERSERVICE_TAG + str(userService.id))
|
||||||
UserServiceOpChecker.checkAndUpdateState(userService, userServiceInstance, state)
|
UserServiceOpChecker.checkAndUpdateState(userService, userServiceInstance, state)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def checkAndUpdateState(userService, userServiceInstance, state):
|
def checkAndUpdateState(userService, userServiceInstance, state):
|
||||||
'''
|
'''
|
||||||
@ -81,7 +83,7 @@ class UserServiceOpChecker(DelayedTask):
|
|||||||
if userServiceInstance.service().publicationType is None or userService.publication == userService.deployed_service.activePublication():
|
if userServiceInstance.service().publicationType is None or userService.publication == userService.deployed_service.activePublication():
|
||||||
userService.setState(State.USABLE)
|
userService.setState(State.USABLE)
|
||||||
# and make this usable if os manager says that it is usable, else it pass to configuring state
|
# 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
|
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)
|
stateOs = userServiceInstance.osmanager().checkState(userService)
|
||||||
# If state is finish, we need to notify the userService again that os has finished
|
# If state is finish, we need to notify the userService again that os has finished
|
||||||
if State.isFinished(stateOs):
|
if State.isFinished(stateOs):
|
||||||
@ -89,7 +91,7 @@ class UserServiceOpChecker(DelayedTask):
|
|||||||
userService.updateData(userServiceInstance)
|
userService.updateData(userServiceInstance)
|
||||||
else:
|
else:
|
||||||
stateOs = State.FINISHED
|
stateOs = State.FINISHED
|
||||||
|
|
||||||
if State.isRuning(stateOs):
|
if State.isRuning(stateOs):
|
||||||
userService.setOsState(State.PREPARING)
|
userService.setOsState(State.PREPARING)
|
||||||
else:
|
else:
|
||||||
@ -118,17 +120,17 @@ class UserServiceOpChecker(DelayedTask):
|
|||||||
if checkLater:
|
if checkLater:
|
||||||
UserServiceOpChecker.checkLater(userService, userServiceInstance)
|
UserServiceOpChecker.checkLater(userService, userServiceInstance)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception('Checkin service state')
|
logger.exception('Checking service state')
|
||||||
log.doLog(userService, log.ERROR, 'Exception: {0}'.format(e), log.INTERNAL)
|
log.doLog(userService, log.ERROR, 'Exception: {0}'.format(e), log.INTERNAL)
|
||||||
userService.setState(State.ERROR)
|
userService.setState(State.ERROR)
|
||||||
userService.save()
|
userService.save()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def checkLater(userService, ci):
|
def checkLater(userService, ci):
|
||||||
'''
|
'''
|
||||||
Inserts a task in the delayedTaskRunner so we can check the state of this publication
|
Inserts a task in the delayedTaskRunner so we can check the state of this publication
|
||||||
@param dps: Database object for DeployedServicePublication
|
@param dps: Database object for DeployedServicePublication
|
||||||
@param pi: Instance of Publication manager for the object
|
@param pi: Instance of Publication manager for the object
|
||||||
'''
|
'''
|
||||||
# Do not add task if already exists one that updates this service
|
# 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 + str(userService.id)):
|
||||||
@ -164,17 +166,17 @@ class UserServiceOpChecker(DelayedTask):
|
|||||||
|
|
||||||
class UserServiceManager(object):
|
class UserServiceManager(object):
|
||||||
_manager = None
|
_manager = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def manager():
|
def manager():
|
||||||
if UserServiceManager._manager == None:
|
if UserServiceManager._manager == None:
|
||||||
UserServiceManager._manager = UserServiceManager()
|
UserServiceManager._manager = UserServiceManager()
|
||||||
return UserServiceManager._manager
|
return UserServiceManager._manager
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getCacheStateFilter(level):
|
def getCacheStateFilter(level):
|
||||||
return Q(cache_level=level) & UserServiceManager.getStateFilter()
|
return Q(cache_level=level) & UserServiceManager.getStateFilter()
|
||||||
|
|
||||||
@ -191,15 +193,13 @@ class UserServiceManager(object):
|
|||||||
# Early return, so no database count is needed
|
# Early return, so no database count is needed
|
||||||
if serviceInstance.maxDeployed == Service.UNLIMITED:
|
if serviceInstance.maxDeployed == Service.UNLIMITED:
|
||||||
return
|
return
|
||||||
|
|
||||||
numberOfServices = deployedService.userServices.select_for_update().filter(
|
numberOfServices = deployedService.userServices.select_for_update().filter(
|
||||||
state__in=[State.PREPARING, State.USABLE]).count()
|
state__in=[State.PREPARING, State.USABLE]).count()
|
||||||
|
|
||||||
if serviceInstance.maxDeployed <= numberOfServices:
|
if serviceInstance.maxDeployed <= numberOfServices:
|
||||||
raise MaxServicesReachedException(
|
raise MaxServicesReachedException('Max number of allowed deployments for service reached')
|
||||||
'Max number of allowed deployments for service reached'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def __createCacheAtDb(self, deployedServicePublication, cacheLevel):
|
def __createCacheAtDb(self, deployedServicePublication, cacheLevel):
|
||||||
'''
|
'''
|
||||||
Private method to instatiate a cache element at database with default states
|
Private method to instatiate a cache element at database with default states
|
||||||
@ -207,10 +207,10 @@ class UserServiceManager(object):
|
|||||||
# Checks if maxDeployed has been reached and if so, raises an exception
|
# Checks if maxDeployed has been reached and if so, raises an exception
|
||||||
self.__checkMaxDeployedReached(deployedServicePublication.deployed_service)
|
self.__checkMaxDeployedReached(deployedServicePublication.deployed_service)
|
||||||
now = getSqlDatetime()
|
now = getSqlDatetime()
|
||||||
return deployedServicePublication.userServices.create(cache_level = cacheLevel, state = State.PREPARING, os_state = State.PREPARING,
|
return deployedServicePublication.userServices.create(cache_level=cacheLevel, state=State.PREPARING, os_state=State.PREPARING,
|
||||||
state_date=now, creation_date=now, data = '', deployed_service = deployedServicePublication.deployed_service,
|
state_date=now, creation_date=now, data='', deployed_service=deployedServicePublication.deployed_service,
|
||||||
user = None, in_use = False )
|
user=None, in_use=False)
|
||||||
|
|
||||||
def __createAssignedAtDb(self, deployedServicePublication, user):
|
def __createAssignedAtDb(self, deployedServicePublication, user):
|
||||||
'''
|
'''
|
||||||
Private method to instatiate an assigned element at database with default state
|
Private method to instatiate an assigned element at database with default state
|
||||||
@ -219,7 +219,7 @@ class UserServiceManager(object):
|
|||||||
now = getSqlDatetime()
|
now = getSqlDatetime()
|
||||||
return deployedServicePublication.userServices.create(cache_level=0, state=State.PREPARING, os_state=State.PREPARING,
|
return deployedServicePublication.userServices.create(cache_level=0, state=State.PREPARING, os_state=State.PREPARING,
|
||||||
state_date=now, creation_date=now, data='', deployed_service=deployedServicePublication.deployed_service, user=user, in_use=False)
|
state_date=now, creation_date=now, data='', deployed_service=deployedServicePublication.deployed_service, user=user, in_use=False)
|
||||||
|
|
||||||
def __createAssignedAtDbForNoPublication(self, deployedService, user):
|
def __createAssignedAtDbForNoPublication(self, deployedService, user):
|
||||||
'''
|
'''
|
||||||
__createCacheAtDb and __createAssignedAtDb uses a publication for create the UserService.
|
__createCacheAtDb and __createAssignedAtDb uses a publication for create the UserService.
|
||||||
@ -230,8 +230,7 @@ class UserServiceManager(object):
|
|||||||
now = getSqlDatetime()
|
now = getSqlDatetime()
|
||||||
return deployedService.userServices.create(cache_level=0, state=State.PREPARING, os_state=State.PREPARING,
|
return deployedService.userServices.create(cache_level=0, state=State.PREPARING, os_state=State.PREPARING,
|
||||||
state_date=now, creation_date=now, data='', publication=None, user=user, in_use=False)
|
state_date=now, creation_date=now, data='', publication=None, user=user, in_use=False)
|
||||||
|
|
||||||
|
|
||||||
def createCacheFor(self, deployedServicePublication, cacheLevel):
|
def createCacheFor(self, deployedServicePublication, cacheLevel):
|
||||||
'''
|
'''
|
||||||
Creates a new cache for the deployed service publication at level indicated
|
Creates a new cache for the deployed service publication at level indicated
|
||||||
@ -240,10 +239,10 @@ class UserServiceManager(object):
|
|||||||
cache = self.__createCacheAtDb(deployedServicePublication, cacheLevel)
|
cache = self.__createCacheAtDb(deployedServicePublication, cacheLevel)
|
||||||
ci = cache.getInstance()
|
ci = cache.getInstance()
|
||||||
state = ci.deployForCache(cacheLevel)
|
state = ci.deployForCache(cacheLevel)
|
||||||
|
|
||||||
UserServiceOpChecker.checkAndUpdateState(cache, ci, state)
|
UserServiceOpChecker.checkAndUpdateState(cache, ci, state)
|
||||||
return cache
|
return cache
|
||||||
|
|
||||||
def createAssignedFor(self, ds, user):
|
def createAssignedFor(self, ds, user):
|
||||||
'''
|
'''
|
||||||
Creates a new assigned deployed service for the publication and user indicated
|
Creates a new assigned deployed service for the publication and user indicated
|
||||||
@ -254,15 +253,15 @@ class UserServiceManager(object):
|
|||||||
assigned = self.__createAssignedAtDb(dsp, user)
|
assigned = self.__createAssignedAtDb(dsp, user)
|
||||||
else:
|
else:
|
||||||
logger.debug('Creating a new assigned element for user {0}'.format(user))
|
logger.debug('Creating a new assigned element for user {0}'.format(user))
|
||||||
assigned = self.__createAssignedAtDbForNoPublication(ds, user)
|
assigned = self.__createAssignedAtDbForNoPublication(ds, user)
|
||||||
|
|
||||||
ai = assigned.getInstance()
|
ai = assigned.getInstance()
|
||||||
state = ai.deployForUser(user)
|
state = ai.deployForUser(user)
|
||||||
|
|
||||||
UserServiceOpChecker.makeUnique(assigned, ai, state)
|
UserServiceOpChecker.makeUnique(assigned, ai, state)
|
||||||
|
|
||||||
return assigned
|
return assigned
|
||||||
|
|
||||||
def createAssignable(self, ds, deployed, user):
|
def createAssignable(self, ds, deployed, user):
|
||||||
'''
|
'''
|
||||||
Creates an assignable service
|
Creates an assignable service
|
||||||
@ -277,9 +276,7 @@ class UserServiceManager(object):
|
|||||||
logger.exception("Exception {0}".format(e))
|
logger.exception("Exception {0}".format(e))
|
||||||
logger.debug("Assignable: {0}".format(assignable))
|
logger.debug("Assignable: {0}".format(assignable))
|
||||||
return assignable
|
return assignable
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def moveToLevel(self, cache, cacheLevel):
|
def moveToLevel(self, cache, cacheLevel):
|
||||||
'''
|
'''
|
||||||
Moves a cache element from one level to another
|
Moves a cache element from one level to another
|
||||||
@ -293,9 +290,9 @@ class UserServiceManager(object):
|
|||||||
logger.debug('Service State: {0} {1} {2}'.format(State.toString(state), State.toString(cache.state), State.toString(cache.os_state)))
|
logger.debug('Service State: {0} {1} {2}'.format(State.toString(state), State.toString(cache.state), State.toString(cache.os_state)))
|
||||||
if State.isRuning(state) and cache.isUsable():
|
if State.isRuning(state) and cache.isUsable():
|
||||||
cache.setState(State.PREPARING)
|
cache.setState(State.PREPARING)
|
||||||
|
|
||||||
UserServiceOpChecker.makeUnique(cache, ci, state)
|
UserServiceOpChecker.makeUnique(cache, ci, state)
|
||||||
|
|
||||||
def cancel(self, uService):
|
def cancel(self, uService):
|
||||||
'''
|
'''
|
||||||
Cancels a user service creation
|
Cancels a user service creation
|
||||||
@ -306,7 +303,7 @@ class UserServiceManager(object):
|
|||||||
if uService.isPreparing() == False:
|
if uService.isPreparing() == False:
|
||||||
logger.INFO(_('Cancel requested for a non running operation, doing remove instead'))
|
logger.INFO(_('Cancel requested for a non running operation, doing remove instead'))
|
||||||
return self.remove(uService)
|
return self.remove(uService)
|
||||||
|
|
||||||
ui = uService.getInstance()
|
ui = uService.getInstance()
|
||||||
# We simply notify service that it should cancel operation
|
# We simply notify service that it should cancel operation
|
||||||
state = ui.cancel()
|
state = ui.cancel()
|
||||||
@ -315,7 +312,6 @@ class UserServiceManager(object):
|
|||||||
UserServiceOpChecker.makeUnique(uService, ui, state)
|
UserServiceOpChecker.makeUnique(uService, ui, state)
|
||||||
return uService
|
return uService
|
||||||
|
|
||||||
|
|
||||||
def remove(self, uService):
|
def remove(self, uService):
|
||||||
'''
|
'''
|
||||||
Removes a uService element
|
Removes a uService element
|
||||||
@ -325,12 +321,12 @@ class UserServiceManager(object):
|
|||||||
logger.debug('Removing uService {0}'.format(uService))
|
logger.debug('Removing uService {0}'.format(uService))
|
||||||
if uService.isUsable() == False and State.isRemovable(uService.state) == False:
|
if uService.isUsable() == False and State.isRemovable(uService.state) == False:
|
||||||
raise OperationException(_('Can\'t remove a non active element'))
|
raise OperationException(_('Can\'t remove a non active element'))
|
||||||
|
|
||||||
ci = uService.getInstance()
|
ci = uService.getInstance()
|
||||||
state = ci.destroy()
|
state = ci.destroy()
|
||||||
uService.setState(State.REMOVING)
|
uService.setState(State.REMOVING)
|
||||||
UserServiceOpChecker.makeUnique(uService, ci, state)
|
UserServiceOpChecker.makeUnique(uService, ci, state)
|
||||||
|
|
||||||
def removeOrCancel(self, uService):
|
def removeOrCancel(self, uService):
|
||||||
if uService.isUsable() or State.isRemovable(uService.state):
|
if uService.isUsable() or State.isRemovable(uService.state):
|
||||||
return self.remove(uService)
|
return self.remove(uService)
|
||||||
@ -338,38 +334,37 @@ class UserServiceManager(object):
|
|||||||
return self.cancel(uService)
|
return self.cancel(uService)
|
||||||
else:
|
else:
|
||||||
raise OperationException(_('Can\'t remove nor cancel {0} cause its states doesn\'t allows it'))
|
raise OperationException(_('Can\'t remove nor cancel {0} cause its states doesn\'t allows it'))
|
||||||
|
|
||||||
def removeInfoItems(self, dsp):
|
def removeInfoItems(self, dsp):
|
||||||
dsp.cachedDeployedService.select_for_update().filter(state__in=State.INFO_STATES).delete()
|
dsp.cachedDeployedService.select_for_update().filter(state__in=State.INFO_STATES).delete()
|
||||||
|
|
||||||
|
|
||||||
def getAssignationForUser(self, ds, user):
|
def getAssignationForUser(self, ds, user):
|
||||||
# First, we try to locate an already assigned service
|
# First, we try to locate an already assigned service
|
||||||
existing = ds.assignedUserServices().filter(user=user,state__in=State.VALID_STATES)
|
existing = ds.assignedUserServices().filter(user=user, state__in=State.VALID_STATES)
|
||||||
lenExisting = existing.count()
|
lenExisting = existing.count()
|
||||||
if lenExisting > 0: # Already has 1 assigned
|
if lenExisting > 0: # Already has 1 assigned
|
||||||
logger.debug('Found assigned service from {0} to user {1}'.format(ds, user.name))
|
logger.debug('Found assigned service from {0} to user {1}'.format(ds, user.name))
|
||||||
return existing[0]
|
return existing[0]
|
||||||
#if existing[0].state == State.ERROR:
|
# if existing[0].state == State.ERROR:
|
||||||
# if lenExisting > 1:
|
# if lenExisting > 1:
|
||||||
# return existing[1]
|
# return existing[1]
|
||||||
#else:
|
# else:
|
||||||
# return existing[0]
|
# return existing[0]
|
||||||
|
|
||||||
# Now try to locate 1 from cache already "ready" (must be usable and at level 1)
|
# Now try to locate 1 from cache already "ready" (must be usable and at level 1)
|
||||||
cache = ds.cachedUserServices().select_for_update().filter(cache_level = services.UserDeployment.L1_CACHE, state = State.USABLE)[:1]
|
cache = ds.cachedUserServices().select_for_update().filter(cache_level=services.UserDeployment.L1_CACHE, state=State.USABLE)[:1]
|
||||||
if len(cache) > 0:
|
if len(cache) > 0:
|
||||||
cache = cache[0] # Database object
|
cache = cache[0] # Database object
|
||||||
cache.assignToUser(user)
|
cache.assignToUser(user)
|
||||||
cache.save() # Store assigned ASAP, we do not know how long assignToUser method of instance will take
|
cache.save() # Store assigned ASAP, we do not know how long assignToUser method of instance will take
|
||||||
logger.debug('Found a cached-ready service from {0} for user {1}, item {2}'.format(ds, user, cache))
|
logger.debug('Found a cached-ready service from {0} for user {1}, item {2}'.format(ds, user, cache))
|
||||||
ci = cache.getInstance() # User Deployment instance
|
ci = cache.getInstance() # User Deployment instance
|
||||||
ci.assignToUser(user)
|
ci.assignToUser(user)
|
||||||
cache.updateData(ci)
|
cache.updateData(ci)
|
||||||
cache.save()
|
cache.save()
|
||||||
return cache
|
return cache
|
||||||
# Now find if there is a preparing one
|
# Now find if there is a preparing one
|
||||||
cache = ds.cachedUserServices().select_for_update().filter(cache_level = services.UserDeployment.L1_CACHE, state = State.PREPARING)[:1]
|
cache = ds.cachedUserServices().select_for_update().filter(cache_level=services.UserDeployment.L1_CACHE, state=State.PREPARING)[:1]
|
||||||
if len(cache) > 0:
|
if len(cache) > 0:
|
||||||
cache = cache[0]
|
cache = cache[0]
|
||||||
cache.assignToUser(user)
|
cache.assignToUser(user)
|
||||||
@ -387,13 +382,13 @@ class UserServiceManager(object):
|
|||||||
raise MaxServicesReachedException()
|
raise MaxServicesReachedException()
|
||||||
# Can create new service, create it
|
# Can create new service, create it
|
||||||
return self.createAssignedFor(ds, user)
|
return self.createAssignedFor(ds, user)
|
||||||
|
|
||||||
def getServicesInStateForProvider(self, provider_id, state):
|
def getServicesInStateForProvider(self, provider_id, state):
|
||||||
'''
|
'''
|
||||||
Returns the number of services of a service provider in the state indicated
|
Returns the number of services of a service provider in the state indicated
|
||||||
'''
|
'''
|
||||||
return UserService.objects.filter(deployed_service__service__provider__id=provider_id, state=state).count()
|
return UserService.objects.filter(deployed_service__service__provider__id=provider_id, state=state).count()
|
||||||
|
|
||||||
def canRemoveServiceFromDeployedService(self, ds):
|
def canRemoveServiceFromDeployedService(self, ds):
|
||||||
'''
|
'''
|
||||||
checks if we can do a "remove" from a deployed service
|
checks if we can do a "remove" from a deployed service
|
||||||
@ -411,7 +406,7 @@ class UserServiceManager(object):
|
|||||||
if preparing >= GlobalConfig.MAX_PREPARING_SERVICES.getInt() and GlobalConfig.IGNORE_LIMITS.getBool() == False:
|
if preparing >= GlobalConfig.MAX_PREPARING_SERVICES.getInt() and GlobalConfig.IGNORE_LIMITS.getBool() == False:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def isReady(self, uService):
|
def isReady(self, uService):
|
||||||
UserService.objects.update()
|
UserService.objects.update()
|
||||||
uService = UserService.objects.select_for_update().get(id=uService.id)
|
uService = UserService.objects.select_for_update().get(id=uService.id)
|
||||||
@ -436,14 +431,13 @@ class UserServiceManager(object):
|
|||||||
This method is used by UserService when a request for setInUse(False) is made
|
This method is used by UserService when a request for setInUse(False) is made
|
||||||
This checks that the service can continue existing or not
|
This checks that the service can continue existing or not
|
||||||
'''
|
'''
|
||||||
#uService = UserService.objects.select_for_update().get(id=uService.id)
|
# uService = UserService.objects.select_for_update().get(id=uService.id)
|
||||||
if uService.publication == None:
|
if uService.publication == None:
|
||||||
return
|
return
|
||||||
if uService.publication.id != uService.deployed_service.activePublication().id:
|
if uService.publication.id != uService.deployed_service.activePublication().id:
|
||||||
logger.debug('Old revision of user service, marking as removable: {0}'.format(uService))
|
logger.debug('Old revision of user service, marking as removable: {0}'.format(uService))
|
||||||
uService.remove()
|
uService.remove()
|
||||||
|
|
||||||
|
|
||||||
def notifyReadyFromOsManager(self, uService, data):
|
def notifyReadyFromOsManager(self, uService, data):
|
||||||
ui = uService.getInstance()
|
ui = uService.getInstance()
|
||||||
logger.debug('Notifying user service ready state')
|
logger.debug('Notifying user service ready state')
|
||||||
@ -452,7 +446,6 @@ class UserServiceManager(object):
|
|||||||
uService.updateData(ui)
|
uService.updateData(ui)
|
||||||
if state == State.FINISHED:
|
if state == State.FINISHED:
|
||||||
uService.save()
|
uService.save()
|
||||||
elif uService.state in (State.USABLE, State.PREPARING): # We don't want to get active deleting or deleted machines...
|
elif uService.state in (State.USABLE, State.PREPARING): # We don't want to get active deleting or deleted machines...
|
||||||
uService.setState(State.PREPARING)
|
uService.setState(State.PREPARING)
|
||||||
UserServiceOpChecker.makeUnique(uService, ui, state)
|
UserServiceOpChecker.makeUnique(uService, ui, state)
|
||||||
|
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -32,10 +32,14 @@ UDS managers (downloads, users preferences, publications, ...)
|
|||||||
|
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
__updated__ = '2014-02-19'
|
||||||
|
|
||||||
|
|
||||||
def cryptoManager():
|
def cryptoManager():
|
||||||
from CryptoManager import CryptoManager
|
from CryptoManager import CryptoManager
|
||||||
return CryptoManager.manager()
|
return CryptoManager.manager()
|
||||||
|
|
||||||
|
|
||||||
def taskManager():
|
def taskManager():
|
||||||
@ -47,10 +51,12 @@ def downloadsManager():
|
|||||||
from DownloadsManager import DownloadsManager
|
from DownloadsManager import DownloadsManager
|
||||||
return DownloadsManager.manager()
|
return DownloadsManager.manager()
|
||||||
|
|
||||||
|
|
||||||
def logManager():
|
def logManager():
|
||||||
from LogManager import LogManager
|
from LogManager import LogManager
|
||||||
return LogManager.manager()
|
return LogManager.manager()
|
||||||
|
|
||||||
|
|
||||||
def statsManager():
|
def statsManager():
|
||||||
from StatsManager import StatsManager
|
from StatsManager import StatsManager
|
||||||
return StatsManager.manager()
|
return StatsManager.manager()
|
||||||
|
@ -4,32 +4,33 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.utils.translation import ugettext_noop as _
|
from django.utils.translation import ugettext_noop as _
|
||||||
from uds.core.util.State import State
|
from uds.core.util.State import State
|
||||||
@ -37,45 +38,46 @@ from uds.core import Module
|
|||||||
|
|
||||||
STORAGE_KEY = 'osmk'
|
STORAGE_KEY = 'osmk'
|
||||||
|
|
||||||
|
|
||||||
class OSManager(Module):
|
class OSManager(Module):
|
||||||
'''
|
'''
|
||||||
An OS Manager is responsible for communication the service the different actions to take (i.e. adding a windows machine to a domain)
|
An OS Manager is responsible for communication the service the different actions to take (i.e. adding a windows machine to a domain)
|
||||||
The Service (i.e. virtual machine) communicates with the OSManager via a published web method, that must include the unique ID.
|
The Service (i.e. virtual machine) communicates with the OSManager via a published web method, that must include the unique ID.
|
||||||
In order to make easier to agents identify themselfs, the Unique ID can be a list with various Ids (i.e. the macs of the virtual machine).
|
In order to make easier to agents identify themselfs, the Unique ID can be a list with various Ids (i.e. the macs of the virtual machine).
|
||||||
Server will iterate thought them and look for an identifier associated with the service. This list is a comma separated values (i.e. AA:BB:CC:DD:EE:FF,00:11:22:...)
|
Server will iterate thought them and look for an identifier associated with the service. This list is a comma separated values (i.e. AA:BB:CC:DD:EE:FF,00:11:22:...)
|
||||||
Remember also that we inherit the test and check methods from BaseModule
|
Remember also that we inherit the test and check methods from BaseModule
|
||||||
'''
|
'''
|
||||||
# Service informational related data
|
# Service informational related data
|
||||||
typeName = _('Base OS Manager')
|
typeName = _('Base OS Manager')
|
||||||
typeType = 'BaseOSManager'
|
typeType = 'BaseOSManager'
|
||||||
typeDescription = _('Base Manager')
|
typeDescription = _('Base Manager')
|
||||||
iconFile = 'osmanager.png'
|
iconFile = 'osmanager.png'
|
||||||
|
|
||||||
# If true, this os manager will be invoked with every user service assigned, but not used from time to time
|
# If true, this os manager will be invoked with every user service assigned, but not used from time to time
|
||||||
# Time is defined as a global config
|
# Time is defined as a global config
|
||||||
processUnusedMachines = False
|
processUnusedMachines = False
|
||||||
|
|
||||||
def __init__(self,environment, values):
|
def __init__(self, environment, values):
|
||||||
super(OSManager, self).__init__(environment, values)
|
super(OSManager, self).__init__(environment, values)
|
||||||
self.initialize(values)
|
self.initialize(values)
|
||||||
|
|
||||||
def initialize(self, values):
|
def initialize(self, values):
|
||||||
'''
|
'''
|
||||||
This method will be invoked from __init__ constructor.
|
This method will be invoked from __init__ constructor.
|
||||||
This is provided so you don't have to provide your own __init__ method,
|
This is provided so you don't have to provide your own __init__ method,
|
||||||
and invoke base methods.
|
and invoke base methods.
|
||||||
This will get invoked when all initialization stuff is done
|
This will get invoked when all initialization stuff is done
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
Values: If values is not none, this object is being initialized
|
Values: If values is not none, this object is being initialized
|
||||||
from administration interface, and not unmarshal will be done.
|
from administration interface, and not unmarshal will be done.
|
||||||
If it's None, this is initialized internally, and unmarshal will
|
If it's None, this is initialized internally, and unmarshal will
|
||||||
be called after this.
|
be called after this.
|
||||||
|
|
||||||
Default implementation does nothing
|
Default implementation does nothing
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def release(self, service):
|
def release(self, service):
|
||||||
'''
|
'''
|
||||||
Called by a service that is in Usable state before destroying it so osmanager can release data associated with it
|
Called by a service that is in Usable state before destroying it so osmanager can release data associated with it
|
||||||
@ -83,70 +85,68 @@ class OSManager(Module):
|
|||||||
@return nothing
|
@return nothing
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# These methods must be overriden
|
# These methods must be overriden
|
||||||
def process(self,service, message, data):
|
def process(self, service, message, data):
|
||||||
'''
|
'''
|
||||||
This method must be overriden so your so manager can manage requests and responses from agent.
|
This method must be overriden so your so manager can manage requests and responses from agent.
|
||||||
@param service: Service that sends the request (virtual machine or whatever)
|
@param service: Service that sends the request (virtual machine or whatever)
|
||||||
@param message: message to process (os manager dependent)
|
@param message: message to process (os manager dependent)
|
||||||
@param data: Data for this message
|
@param data: Data for this message
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def checkState(self,service):
|
def checkState(self, service):
|
||||||
'''
|
'''
|
||||||
This method must be overriden so your os manager can respond to requests from system to the current state of the service
|
This method must be overriden so your os manager can respond to requests from system to the current state of the service
|
||||||
This method will be invoked when:
|
This method will be invoked when:
|
||||||
* After service creation has finished, with the service wanting to see if it has to wait for os manager process finalization
|
* After service creation has finished, with the service wanting to see if it has to wait for os manager process finalization
|
||||||
* After call to process method, to check if the state has changed
|
* After call to process method, to check if the state has changed
|
||||||
* Before assigning a service to an user (maybe this is not needed)?
|
* Before assigning a service to an user (maybe this is not needed)?
|
||||||
Notice that the service could be in any state. In fact, what we want with this is return FINISHED if nothing is expected from os o RUNING else
|
Notice that the service could be in any state. In fact, what we want with this is return FINISHED if nothing is expected from os o RUNING else
|
||||||
The state will be updated by actors inside oss, so no more direct checking is needed
|
The state will be updated by actors inside oss, so no more direct checking is needed
|
||||||
@return: RUNNING, FINISHED
|
@return: RUNNING, FINISHED
|
||||||
We do not expect any exception from this method
|
We do not expect any exception from this method
|
||||||
'''
|
'''
|
||||||
return State.FINISHED
|
return State.FINISHED
|
||||||
|
|
||||||
|
|
||||||
def processUnused(self, userService):
|
def processUnused(self, userService):
|
||||||
'''
|
'''
|
||||||
This will be invoked for every assigned and unused user service that has been in this state at least 1/2 of Globalconfig.CHECK_UNUSED_TIME
|
This will be invoked for every assigned and unused user service that has been in this state at least 1/2 of Globalconfig.CHECK_UNUSED_TIME
|
||||||
This function can update userService values. Normal operation will be remove machines if this state is not valid
|
This function can update userService values. Normal operation will be remove machines if this state is not valid
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def transformsUserOrPasswordForService(cls):
|
def transformsUserOrPasswordForService(cls):
|
||||||
'''
|
'''
|
||||||
Helper method that informs if the os manager transforms the username and/or the password.
|
Helper method that informs if the os manager transforms the username and/or the password.
|
||||||
This is used from DeployedService
|
This is used from DeployedService
|
||||||
'''
|
'''
|
||||||
return cls.processUserPassword != OSManager.processUserPassword
|
return cls.processUserPassword != OSManager.processUserPassword
|
||||||
|
|
||||||
def processUserPassword(self, service, username, password):
|
def processUserPassword(self, service, username, password):
|
||||||
'''
|
'''
|
||||||
This will be invoked prior to passsing username/password to Transport.
|
This will be invoked prior to passsing username/password to Transport.
|
||||||
|
|
||||||
This method allows us to "change" username and/or password "on the fly".
|
This method allows us to "change" username and/or password "on the fly".
|
||||||
One example of use of this is an OS Manager that creates a random password for an user.
|
One example of use of this is an OS Manager that creates a random password for an user.
|
||||||
In that case, this method, if the username passed in is the same as the os manager changes the password for, return the changed password.
|
In that case, this method, if the username passed in is the same as the os manager changes the password for, return the changed password.
|
||||||
|
|
||||||
MUST Return:
|
MUST Return:
|
||||||
An array with 2 elements, [newUserName, newPassword].
|
An array with 2 elements, [newUserName, newPassword].
|
||||||
Default method simplt does nothing with in parameters, just returns it. (So, if your os manager does not need this,
|
Default method simplt does nothing with in parameters, just returns it. (So, if your os manager does not need this,
|
||||||
simply do not implement it)
|
simply do not implement it)
|
||||||
|
|
||||||
Note: This method is, right now, invoked by Transports directly. So if you implement a Transport, remember to invoke this
|
Note: This method is, right now, invoked by Transports directly. So if you implement a Transport, remember to invoke this
|
||||||
'''
|
'''
|
||||||
return [username, password]
|
return [username, password]
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
'''
|
'''
|
||||||
Invoked when OS Manager is deleted
|
Invoked when OS Manager is deleted
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Base OS Manager"
|
return "Base OS Manager"
|
||||||
|
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -36,25 +36,26 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class OSManagersFactory(object):
|
class OSManagersFactory(object):
|
||||||
_factory = None
|
_factory = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._jobs = {}
|
self._jobs = {}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def factory():
|
def factory():
|
||||||
if OSManagersFactory._factory == None:
|
if OSManagersFactory._factory == None:
|
||||||
OSManagersFactory._factory = OSManagersFactory()
|
OSManagersFactory._factory = OSManagersFactory()
|
||||||
return OSManagersFactory._factory
|
return OSManagersFactory._factory
|
||||||
|
|
||||||
def providers(self):
|
def providers(self):
|
||||||
return self._jobs
|
return self._jobs
|
||||||
|
|
||||||
def insert(self, type_):
|
def insert(self, type_):
|
||||||
logger.debug('Adding OS Manager {0} as {1}'.format(type_.type(), type_))
|
logger.debug('Adding OS Manager {0} as {1}'.format(type_.type(), type_))
|
||||||
self._jobs[type_.type()] = type_
|
self._jobs[type_.type()] = type_
|
||||||
|
|
||||||
def lookup(self, typeName):
|
def lookup(self, typeName):
|
||||||
try:
|
try:
|
||||||
return self._jobs[typeName]
|
return self._jobs[typeName]
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -32,12 +32,13 @@ UDS os managers related interfaces and classes
|
|||||||
|
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
from BaseOsManager import OSManager
|
from BaseOsManager import OSManager
|
||||||
|
|
||||||
|
|
||||||
def factory():
|
def factory():
|
||||||
'''
|
'''
|
||||||
Returns factory for register/access to authenticators
|
Returns factory for register/access to authenticators
|
||||||
'''
|
'''
|
||||||
from OSManagersFactory import OSManagersFactory
|
from OSManagersFactory import OSManagersFactory
|
||||||
return OSManagersFactory.factory()
|
return OSManagersFactory.factory()
|
||||||
|
|
||||||
|
@ -4,147 +4,141 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from uds.core import Environmentable
|
from uds.core import Environmentable
|
||||||
from uds.core import Serializable
|
from uds.core import Serializable
|
||||||
from uds.core.util.State import State
|
from uds.core.util.State import State
|
||||||
|
|
||||||
|
|
||||||
class UserDeployment(Environmentable, Serializable):
|
class UserDeployment(Environmentable, Serializable):
|
||||||
'''
|
'''
|
||||||
Interface for deployed services.
|
Interface for deployed services.
|
||||||
|
|
||||||
This class provides the needed logic for implementing an "consumable user service",
|
This class provides the needed logic for implementing an "consumable user service",
|
||||||
that are the elements that the user will interact with.
|
that are the elements that the user will interact with.
|
||||||
|
|
||||||
A good way to understand this class is to look at the sample services provided
|
A good way to understand this class is to look at the sample services provided
|
||||||
with the documentation.
|
with the documentation.
|
||||||
|
|
||||||
As with all modules interfaces, if you override __init__ method,
|
As with all modules interfaces, if you override __init__ method,
|
||||||
do not forget to invoke this class __init__ method as this::
|
do not forget to invoke this class __init__ method as this::
|
||||||
|
|
||||||
super(self.__class__, self).__init__(environment, **kwargs)
|
super(self.__class__, self).__init__(environment, **kwargs)
|
||||||
|
|
||||||
This is a MUST (if you override __init___), so internal structured gets filled correctly, so don't forget it!.
|
This is a MUST (if you override __init___), so internal structured gets filled correctly, so don't forget it!.
|
||||||
|
|
||||||
The preferred way of initializing, is to provide :py:meth:`.initialize`, that
|
The preferred way of initializing, is to provide :py:meth:`.initialize`, that
|
||||||
will be invoked just after all initialization stuff is done at __init__.
|
will be invoked just after all initialization stuff is done at __init__.
|
||||||
|
|
||||||
Normally objects of classes deriving from this one, will be serialized, called,
|
Normally objects of classes deriving from this one, will be serialized, called,
|
||||||
deserialized. This means that all that you want to ensure that is keeped inside
|
deserialized. This means that all that you want to ensure that is keeped inside
|
||||||
the class must be serialized and unserialized, because there is no warantee that
|
the class must be serialized and unserialized, because there is no warantee that
|
||||||
the object will get two methods invoked without haven't been remoded from memory
|
the object will get two methods invoked without haven't been remoded from memory
|
||||||
and loaded again, this means, IMPLEMENT marshal and unmarshal with all attributes
|
and loaded again, this means, IMPLEMENT marshal and unmarshal with all attributes
|
||||||
that you want to keep.
|
that you want to keep.
|
||||||
|
|
||||||
|
|
||||||
Things to know about this class:
|
Things to know about this class:
|
||||||
|
|
||||||
* Once a deployment is done, it will never be called again for same instance
|
* Once a deployment is done, it will never be called again for same instance
|
||||||
object
|
object
|
||||||
* The method getUniqueId will be invoked after call to deploys and check.
|
* The method getUniqueId will be invoked after call to deploys and check.
|
||||||
You can change it on the fly, but remember that uniqueId is the "keyword"
|
You can change it on the fly, but remember that uniqueId is the "keyword"
|
||||||
used inside services to communicate with os managers (os manager will
|
used inside services to communicate with os managers (os manager will
|
||||||
receive an instance of UserDeployment, and this will be located via that
|
receive an instance of UserDeployment, and this will be located via that
|
||||||
uniqueId)
|
uniqueId)
|
||||||
|
|
||||||
Uniques ids can be repeated at database level, to let it come at a later
|
Uniques ids can be repeated at database level, to let it come at a later
|
||||||
deployment stage, but if two services has same uniqueid at a time,
|
deployment stage, but if two services has same uniqueid at a time,
|
||||||
os manager will simply not work.
|
os manager will simply not work.
|
||||||
* suggestedTime is always accessed through instance objects, and used after
|
* suggestedTime is always accessed through instance objects, and used after
|
||||||
deployForCache, deployForUser and moveToCache it these methods returns
|
deployForCache, deployForUser and moveToCache it these methods returns
|
||||||
RUNNING
|
RUNNING
|
||||||
* Checks (if a deployment has finished, or the cache movement is finished)
|
* Checks (if a deployment has finished, or the cache movement is finished)
|
||||||
are always done using checkState(). It is secuential, i mean, will only
|
are always done using checkState(). It is secuential, i mean, will only
|
||||||
be called when a deployment,a cache movement or a cancel operation is
|
be called when a deployment,a cache movement or a cancel operation is
|
||||||
running
|
running
|
||||||
* If the service that supports this deployeds do not use L2 cache, the
|
* If the service that supports this deployeds do not use L2 cache, the
|
||||||
moveCache method will never be invoked
|
moveCache method will never be invoked
|
||||||
* The L1 cache should be a fast access cache (i.e. running service but
|
* The L1 cache should be a fast access cache (i.e. running service but
|
||||||
not assigned to an user), while L2 cache should be non consuming or
|
not assigned to an user), while L2 cache should be non consuming or
|
||||||
almost-non-consuming service. This means that if we cannont make an
|
almost-non-consuming service. This means that if we cannont make an
|
||||||
slower an less resources consumable form for a service, this should
|
slower an less resources consumable form for a service, this should
|
||||||
not have an L2 cache (slower is not a must,
|
not have an L2 cache (slower is not a must,
|
||||||
but probably it will be slower to recover from L2 cache than from L1,
|
but probably it will be slower to recover from L2 cache than from L1,
|
||||||
but faster than creating a new service)
|
but faster than creating a new service)
|
||||||
Ofc, if a service has an "Instant" creation, it don't needs cache...
|
Ofc, if a service has an "Instant" creation, it don't needs cache...
|
||||||
* We do not expect any exception from these methods, but if there is an
|
* We do not expect any exception from these methods, but if there is an
|
||||||
error, the method can return "ERROR". To show the reason of error, the
|
error, the method can return "ERROR". To show the reason of error, the
|
||||||
method reasonOfError can be called multiple times, including
|
method reasonOfError can be called multiple times, including
|
||||||
serializations in middle, so remember to include reason of error in serializations
|
serializations in middle, so remember to include reason of error in serializations
|
||||||
'''
|
'''
|
||||||
L1_CACHE = 1 #: Constant for Cache of level 1
|
L1_CACHE = 1 # : Constant for Cache of level 1
|
||||||
L2_CACHE = 2 #: Constant for Cache of level 2
|
L2_CACHE = 2 # : Constant for Cache of level 2
|
||||||
|
|
||||||
#: Suggested time for deployment finishing, in seconds
|
# : Suggested time for deployment finishing, in seconds
|
||||||
#: This allows the manager to, if deployment is no done in 1 step, re-check
|
# : This allows the manager to, if deployment is no done in 1 step, re-check
|
||||||
#: the deployment once this time has passed, i.e. KVM COW deployment takes
|
# : the deployment once this time has passed, i.e. KVM COW deployment takes
|
||||||
#: low time, so we suggest to check at short intervals, but full copys takes
|
# : low time, so we suggest to check at short intervals, but full copys takes
|
||||||
#: a bit more so we can use longer interval checks
|
# : a bit more so we can use longer interval checks
|
||||||
#: This attribute is accessed always through an instance object,
|
# : This attribute is accessed always through an instance object,
|
||||||
#: so u can modify it at your own implementation.
|
# : so u can modify it at your own implementation.
|
||||||
suggestedTime = 10
|
suggestedTime = 10
|
||||||
|
|
||||||
def __init__(self, environment, **kwargs):
|
def __init__(self, environment, **kwargs):
|
||||||
'''
|
'''
|
||||||
Do not forget to invoke this in your derived class using "super(self.__class__, self).__init__(environment, **kwargs)"
|
Do not forget to invoke this in your derived class using "super(self.__class__, self).__init__(environment, **kwargs)"
|
||||||
We want to use the env, service and storage methods outside class. If not called, you must implement your own methods
|
We want to use the env, service and storage methods outside class. If not called, you must implement your own methods
|
||||||
service and storage are "convenient" methods to access _env.service() and _env.storage()
|
service and storage are "convenient" methods to access _env.service() and _env.storage()
|
||||||
|
|
||||||
Invoking this from derived classes is a MUST, again, do not forget it or your
|
Invoking this from derived classes is a MUST, again, do not forget it or your
|
||||||
module will probable never work.
|
module will probable never work.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|
||||||
environment: Environment assigned to this publication
|
environment: Environment assigned to this publication
|
||||||
kwargs: List of arguments that will receive:
|
kwargs: List of arguments that will receive:
|
||||||
service: Parent service (derived from Service) of this deployment (this is an instance, not database object)
|
service: Parent service (derived from Service) of this deployment (this is an instance, not database object)
|
||||||
publication: Parent publication (derived from Publication) of this deployment (optional)(this is an instance, not database object)
|
publication: Parent publication (derived from Publication) of this deployment (optional)(this is an instance, not database object)
|
||||||
osmanager: Parent osmanager (derived from :py:class:`uds.core.osmanagersOSManager`) of this deployment (optional)(this is an instance, not database object)
|
osmanager: Parent osmanager (derived from :py:class:`uds.core.osmanagersOSManager`) of this deployment (optional)(this is an instance, not database object)
|
||||||
dbservice: Database object for this service
|
dbservice: Database object for this service
|
||||||
'''
|
'''
|
||||||
Environmentable.__init__(self, environment)
|
Environmentable.__init__(self, environment)
|
||||||
Serializable.__init__(self)
|
Serializable.__init__(self)
|
||||||
self._service = kwargs['service'] # Raises an exception if service is not included. Parent
|
self._service = kwargs['service'] # Raises an exception if service is not included. Parent
|
||||||
if kwargs.has_key('publication'):
|
self._publication = kwargs.get('publication', None)
|
||||||
self._publication = kwargs['publication']
|
self._osmanager = kwargs.get('osmanager', None)
|
||||||
else:
|
self._dbService = kwargs.get('dbservice', None)
|
||||||
self._publication = None
|
|
||||||
if kwargs.has_key('osmanager'):
|
|
||||||
self._osmanager = kwargs['osmanager']
|
|
||||||
else:
|
|
||||||
self._osmanager = None
|
|
||||||
if kwargs.has_key('dbservice'): # Reference to database service, will be there most time :-)
|
|
||||||
self._dbService = kwargs['dbservice']
|
|
||||||
else:
|
|
||||||
self._dbService = None
|
|
||||||
|
|
||||||
self.initialize()
|
self.initialize()
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
'''
|
'''
|
||||||
This method will be invoked from __init__ constructor.
|
This method will be invoked from __init__ constructor.
|
||||||
@ -155,17 +149,16 @@ class UserDeployment(Environmentable, Serializable):
|
|||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def getName(self):
|
def getName(self):
|
||||||
'''
|
'''
|
||||||
Override this to return a name to display under some circustances
|
Override this to return a name to display under some circustances
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
name, default implementation returns unique id
|
name, default implementation returns unique id
|
||||||
'''
|
'''
|
||||||
return self.getUniqueId()
|
return self.getUniqueId()
|
||||||
|
|
||||||
def service(self):
|
def service(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access parent service. This doesn't need to be override.
|
Utility method to access parent service. This doesn't need to be override.
|
||||||
@ -174,154 +167,154 @@ class UserDeployment(Environmentable, Serializable):
|
|||||||
consumable to the user.
|
consumable to the user.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
Parent service of this User Deployment
|
Parent service of this User Deployment
|
||||||
'''
|
'''
|
||||||
return self._service
|
return self._service
|
||||||
|
|
||||||
def publication(self):
|
def publication(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access publication. This doesn't need to be overriden.
|
Utility method to access publication. This doesn't need to be overriden.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
publication for this user deployment, or None if this deployment has
|
publication for this user deployment, or None if this deployment has
|
||||||
no publication at all.
|
no publication at all.
|
||||||
'''
|
'''
|
||||||
return self._publication
|
return self._publication
|
||||||
|
|
||||||
def osmanager(self):
|
def osmanager(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access os manager. This doesn't need to be overriden.
|
Utility method to access os manager. This doesn't need to be overriden.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
os manager for this user deployment, or None if this deployment has
|
os manager for this user deployment, or None if this deployment has
|
||||||
no os manager.
|
no os manager.
|
||||||
'''
|
'''
|
||||||
return self._osmanager
|
return self._osmanager
|
||||||
|
|
||||||
def dbservice(self):
|
def dbservice(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access database object for the object this represents.
|
Utility method to access database object for the object this represents.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
Database object that got unserialized to obtain this object.
|
Database object that got unserialized to obtain this object.
|
||||||
'''
|
'''
|
||||||
return self._dbService
|
return self._dbService
|
||||||
|
|
||||||
def doLog(self, level, message):
|
def doLog(self, level, message):
|
||||||
'''
|
'''
|
||||||
Logs a message with requested level associated with this service
|
Logs a message with requested level associated with this service
|
||||||
'''
|
'''
|
||||||
from uds.core.util import log
|
from uds.core.util import log
|
||||||
log.doLog(self._dbService, level, message, log.SERVICE)
|
log.doLog(self._dbService, level, message, log.SERVICE)
|
||||||
|
|
||||||
def macGenerator(self):
|
def macGenerator(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access provided macs generator (inside environment)
|
Utility method to access provided macs generator (inside environment)
|
||||||
|
|
||||||
Returns the environment unique mac addresses generator
|
Returns the environment unique mac addresses generator
|
||||||
'''
|
'''
|
||||||
return self.idGenerators('mac')
|
return self.idGenerators('mac')
|
||||||
|
|
||||||
def nameGenerator(self):
|
def nameGenerator(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access provided names generator (inside environment)
|
Utility method to access provided names generator (inside environment)
|
||||||
|
|
||||||
Returns the environment unique name generator
|
Returns the environment unique name generator
|
||||||
'''
|
'''
|
||||||
return self.idGenerators('name')
|
return self.idGenerators('name')
|
||||||
|
|
||||||
def getUniqueId(self):
|
def getUniqueId(self):
|
||||||
'''
|
'''
|
||||||
Obtains an unique id for this deployed service, you MUST override this
|
Obtains an unique id for this deployed service, you MUST override this
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
An unique identifier for this object, that is an string and must be
|
An unique identifier for this object, that is an string and must be
|
||||||
unique.
|
unique.
|
||||||
'''
|
'''
|
||||||
raise Exception('Base getUniqueId for User Deployment called!!!')
|
raise Exception('Base getUniqueId for User Deployment called!!!')
|
||||||
|
|
||||||
def notifyReadyFromOsManager(self, data):
|
def notifyReadyFromOsManager(self, data):
|
||||||
'''
|
'''
|
||||||
This is a task method. As that, the excepted return values are
|
This is a task method. As that, the excepted return values are
|
||||||
State values RUNNING, FINISHED or ERROR.
|
State values RUNNING, FINISHED or ERROR.
|
||||||
|
|
||||||
This method provides a mechanism to let os managers notify readyness
|
This method provides a mechanism to let os managers notify readyness
|
||||||
to deployed services.
|
to deployed services.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|
||||||
Data: Data sent by os manager.
|
Data: Data sent by os manager.
|
||||||
Data is os manager dependant, so check if this data is known by you
|
Data is os manager dependant, so check if this data is known by you
|
||||||
(normally, it will be None, but is os manager dependad as i say)
|
(normally, it will be None, but is os manager dependad as i say)
|
||||||
|
|
||||||
This is a task-initiating method, so if there is something to do,
|
This is a task-initiating method, so if there is something to do,
|
||||||
just return State.RUNNING. If not, return State.FINISHED. In case of
|
just return State.RUNNING. If not, return State.FINISHED. In case of
|
||||||
error, return State.ERROR and be ready to provide error message when
|
error, return State.ERROR and be ready to provide error message when
|
||||||
|
|
||||||
if State.RUNNING is returned, the :py:meth:.checkState method will be
|
if State.RUNNING is returned, the :py:meth:.checkState method will be
|
||||||
used to check when this process has finished.
|
used to check when this process has finished.
|
||||||
|
|
||||||
:note: All task methods, like this one, are expected to handle
|
:note: All task methods, like this one, are expected to handle
|
||||||
all exceptions, and never raise an exception from these methods
|
all exceptions, and never raise an exception from these methods
|
||||||
to the core. Take that into account and handle exceptions inside
|
to the core. Take that into account and handle exceptions inside
|
||||||
this method.
|
this method.
|
||||||
'''
|
'''
|
||||||
return State.FINISHED
|
return State.FINISHED
|
||||||
|
|
||||||
def getIp(self):
|
def getIp(self):
|
||||||
'''
|
'''
|
||||||
All services are "IP" services, so this method is a MUST
|
All services are "IP" services, so this method is a MUST
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
The needed ip to let the user connect to the his deployed service.
|
The needed ip to let the user connect to the his deployed service.
|
||||||
This ip will be managed by transports, without IP there is no connection
|
This ip will be managed by transports, without IP there is no connection
|
||||||
'''
|
'''
|
||||||
raise Exception('Base getIp for User Deployment got called!!!')
|
raise Exception('Base getIp for User Deployment got called!!!')
|
||||||
|
|
||||||
def setIp(self, ip):
|
def setIp(self, ip):
|
||||||
'''
|
'''
|
||||||
This is an utility method, invoked by some os manager to notify what they thinks is the ip for this service.
|
This is an utility method, invoked by some os manager to notify what they thinks is the ip for this service.
|
||||||
If you assign the service IP by your own methods, do not override this
|
If you assign the service IP by your own methods, do not override this
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def setReady(self):
|
def setReady(self):
|
||||||
'''
|
'''
|
||||||
This is a task method. As that, the excepted return values are
|
This is a task method. As that, the excepted return values are
|
||||||
State values RUNNING, FINISHED or ERROR.
|
State values RUNNING, FINISHED or ERROR.
|
||||||
|
|
||||||
The method is invoked whenever a machine is provided to an user, right
|
The method is invoked whenever a machine is provided to an user, right
|
||||||
before presenting it (via transport rendering) to the user.
|
before presenting it (via transport rendering) to the user.
|
||||||
|
|
||||||
This method exist for this kind of situations (i will explain it with a
|
This method exist for this kind of situations (i will explain it with a
|
||||||
sample)
|
sample)
|
||||||
|
|
||||||
Imagine a Service tree (Provider, Service, ...) for virtual machines.
|
Imagine a Service tree (Provider, Service, ...) for virtual machines.
|
||||||
This machines will get created by the UserDeployment implementation, but,
|
This machines will get created by the UserDeployment implementation, but,
|
||||||
at some time, the machine can be put at in an state (suspend, shut down)
|
at some time, the machine can be put at in an state (suspend, shut down)
|
||||||
that will make the transport impossible to connect with it.
|
that will make the transport impossible to connect with it.
|
||||||
|
|
||||||
This method, in this case, will check the state of the machine, and if
|
This method, in this case, will check the state of the machine, and if
|
||||||
it is "ready", that is, powered on and accessible, it will return
|
it is "ready", that is, powered on and accessible, it will return
|
||||||
"State.FINISHED". If the machine is not accessible (has been erased, for
|
"State.FINISHED". If the machine is not accessible (has been erased, for
|
||||||
example), it will return "State.ERROR" and store a reason of error so UDS
|
example), it will return "State.ERROR" and store a reason of error so UDS
|
||||||
can ask for it and present this information to the Administrator.
|
can ask for it and present this information to the Administrator.
|
||||||
|
|
||||||
If the machine powered off, or suspended, or any other state that is not
|
If the machine powered off, or suspended, or any other state that is not
|
||||||
directly usable but can be put in an usable state, it will return
|
directly usable but can be put in an usable state, it will return
|
||||||
"State.RUNNING", and core will use checkState to see when the operation
|
"State.RUNNING", and core will use checkState to see when the operation
|
||||||
has finished.
|
has finished.
|
||||||
|
|
||||||
:note: All task methods, like this one, are expected to handle
|
:note: All task methods, like this one, are expected to handle
|
||||||
all exceptions, and never raise an exception from these methods
|
all exceptions, and never raise an exception from these methods
|
||||||
to the core. Take that into account and handle exceptions inside
|
to the core. Take that into account and handle exceptions inside
|
||||||
this method.
|
this method.
|
||||||
'''
|
'''
|
||||||
return State.FINISHED
|
return State.FINISHED
|
||||||
|
|
||||||
@ -331,13 +324,13 @@ class UserDeployment(Environmentable, Serializable):
|
|||||||
|
|
||||||
This is a task method. As that, the expected return values are
|
This is a task method. As that, the expected return values are
|
||||||
State values RUNNING, FINISHED or ERROR.
|
State values RUNNING, FINISHED or ERROR.
|
||||||
|
|
||||||
The objective of this method is providing a cache copy of an user consumable,
|
The objective of this method is providing a cache copy of an user consumable,
|
||||||
and will be invoked whenever the core need to create a new copy for cache
|
and will be invoked whenever the core need to create a new copy for cache
|
||||||
of the service this UserDeployment manages.
|
of the service this UserDeployment manages.
|
||||||
|
|
||||||
Things to take care with this method are:
|
Things to take care with this method are:
|
||||||
|
|
||||||
* cacheLevel can be L1 or L2 (class constants)
|
* cacheLevel can be L1 or L2 (class constants)
|
||||||
* If a deploy for cache is asked for a L1 cache, the generated
|
* If a deploy for cache is asked for a L1 cache, the generated
|
||||||
element is expected to be all-done for user consume. L1 cache items
|
element is expected to be all-done for user consume. L1 cache items
|
||||||
@ -351,55 +344,54 @@ class UserDeployment(Environmentable, Serializable):
|
|||||||
If your L2 cache consumes the same that L1 cache, L2 cache is in fact not
|
If your L2 cache consumes the same that L1 cache, L2 cache is in fact not
|
||||||
needed.
|
needed.
|
||||||
* This works as :py:meth:.deployForUser, meaning that you can take a look
|
* This works as :py:meth:.deployForUser, meaning that you can take a look
|
||||||
also to that method for more info
|
also to that method for more info
|
||||||
|
|
||||||
:note: If your service uses caching, this method MUST be provided. If it
|
:note: If your service uses caching, this method MUST be provided. If it
|
||||||
do not uses cache, this method will never get called, so you can
|
do not uses cache, this method will never get called, so you can
|
||||||
skip it implementation
|
skip it implementation
|
||||||
|
|
||||||
:note: All task methods, like this one, are expected to handle
|
:note: All task methods, like this one, are expected to handle
|
||||||
all exceptions, and never raise an exception from these methods
|
all exceptions, and never raise an exception from these methods
|
||||||
to the core. Take that into account and handle exceptions inside
|
to the core. Take that into account and handle exceptions inside
|
||||||
this method.
|
this method.
|
||||||
'''
|
'''
|
||||||
raise Exception('Base deploy for cache invoked! for class {0}'.format(self.__class__.__name__))
|
raise Exception('Base deploy for cache invoked! for class {0}'.format(self.__class__.__name__))
|
||||||
|
|
||||||
def deployForUser(self, user):
|
def deployForUser(self, user):
|
||||||
'''
|
'''
|
||||||
Deploys an service instance for an user.
|
Deploys an service instance for an user.
|
||||||
|
|
||||||
This is a task method. As that, the excepted return values are
|
This is a task method. As that, the excepted return values are
|
||||||
State values RUNNING, FINISHED or ERROR.
|
State values RUNNING, FINISHED or ERROR.
|
||||||
|
|
||||||
The user parameter is not realy neded, but provided. It indicates the
|
The user parameter is not realy neded, but provided. It indicates the
|
||||||
Database User Object (see py:mod:`uds.modules`) to which this deployed
|
Database User Object (see py:mod:`uds.modules`) to which this deployed
|
||||||
user service will be assigned to.
|
user service will be assigned to.
|
||||||
|
|
||||||
This method will get called whenever a new deployed service for an user
|
This method will get called whenever a new deployed service for an user
|
||||||
is needed. This will give this class the oportunity to create
|
is needed. This will give this class the oportunity to create
|
||||||
a service that is assigned to an user.
|
a service that is assigned to an user.
|
||||||
|
|
||||||
The way of using this method is as follows:
|
The way of using this method is as follows:
|
||||||
|
|
||||||
If the service gets created in "one step", that is, before the return
|
If the service gets created in "one step", that is, before the return
|
||||||
of this method, the consumable service for the user gets created, it
|
of this method, the consumable service for the user gets created, it
|
||||||
will return "State.FINISH".
|
will return "State.FINISH".
|
||||||
If the service needs more steps (as in this case), we will return
|
If the service needs more steps (as in this case), we will return
|
||||||
"State.RUNNING", and if it has an error, it wil return "State.ERROR" and
|
"State.RUNNING", and if it has an error, it wil return "State.ERROR" and
|
||||||
store an error string so administration interface can show it.
|
store an error string so administration interface can show it.
|
||||||
|
|
||||||
We do not use user for anything, as in most cases will be.
|
We do not use user for anything, as in most cases will be.
|
||||||
|
|
||||||
:note: override ALWAYS this method, or an exception will be raised
|
:note: override ALWAYS this method, or an exception will be raised
|
||||||
|
|
||||||
:note: All task methods, like this one, are expected to handle
|
:note: All task methods, like this one, are expected to handle
|
||||||
all exceptions, and never raise an exception from these methods
|
all exceptions, and never raise an exception from these methods
|
||||||
to the core. Take that into account and handle exceptions inside
|
to the core. Take that into account and handle exceptions inside
|
||||||
this method.
|
this method.
|
||||||
'''
|
'''
|
||||||
raise Exception('Base deploy for user invoked! for class {0}'.format(self.__class__.__name__))
|
raise Exception('Base deploy for user invoked! for class {0}'.format(self.__class__.__name__))
|
||||||
|
|
||||||
|
|
||||||
def checkState(self):
|
def checkState(self):
|
||||||
'''
|
'''
|
||||||
This is a task method. As that, the expected return values are
|
This is a task method. As that, the expected return values are
|
||||||
@ -408,35 +400,35 @@ class UserDeployment(Environmentable, Serializable):
|
|||||||
|
|
||||||
If some of the initiating action tasks returns State.RUNNING. this method
|
If some of the initiating action tasks returns State.RUNNING. this method
|
||||||
will get called until it returns State.FINISH or State.ERROR.
|
will get called until it returns State.FINISH or State.ERROR.
|
||||||
|
|
||||||
In other words, whenever a multi step operation is initiated, this method
|
In other words, whenever a multi step operation is initiated, this method
|
||||||
will get the responsability to check that the operation has finished or
|
will get the responsability to check that the operation has finished or
|
||||||
failed. If the operation continues, but haven't finished yet, it must
|
failed. If the operation continues, but haven't finished yet, it must
|
||||||
return State.RUNNING. If has finished must return State.FINISH and if it
|
return State.RUNNING. If has finished must return State.FINISH and if it
|
||||||
has some kind of error, State.ERROR and also store somewhere the info
|
has some kind of error, State.ERROR and also store somewhere the info
|
||||||
that will be requested using :py:meth:.reasonOfError
|
that will be requested using :py:meth:.reasonOfError
|
||||||
|
|
||||||
:note: override ALWAYS this method, or an exception will be raised
|
:note: override ALWAYS this method, or an exception will be raised
|
||||||
|
|
||||||
:note: All task methods, like this one, are expected to handle
|
:note: All task methods, like this one, are expected to handle
|
||||||
all exceptions, and never raise an exception from these methods
|
all exceptions, and never raise an exception from these methods
|
||||||
to the core. Take that into account and handle exceptions inside
|
to the core. Take that into account and handle exceptions inside
|
||||||
this method.
|
this method.
|
||||||
'''
|
'''
|
||||||
raise Exception('Base check state invoked! for class {0}'.format(self.__class__.__name__))
|
raise Exception('Base check state invoked! for class {0}'.format(self.__class__.__name__))
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
'''
|
'''
|
||||||
Invoked when the core notices that the deployment of a service has finished.
|
Invoked when the core notices that the deployment of a service has finished.
|
||||||
(No matter whether it is for cache or for an user)
|
(No matter whether it is for cache or for an user)
|
||||||
|
|
||||||
This gives the opportunity to make something at that moment.
|
This gives the opportunity to make something at that moment.
|
||||||
|
|
||||||
Default implementation does nothing at all.
|
Default implementation does nothing at all.
|
||||||
|
|
||||||
:note: You can also make these operations at checkState, this is really
|
:note: You can also make these operations at checkState, this is really
|
||||||
not needed, but can be provided (default implementation of base class does
|
not needed, but can be provided (default implementation of base class does
|
||||||
nothing)
|
nothing)
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -446,76 +438,76 @@ class UserDeployment(Environmentable, Serializable):
|
|||||||
This is not a task method right now, simply a notification. This means
|
This is not a task method right now, simply a notification. This means
|
||||||
that L1 cache items must be directly usable (except for the readyness part)
|
that L1 cache items must be directly usable (except for the readyness part)
|
||||||
by users in a single step operation.
|
by users in a single step operation.
|
||||||
|
|
||||||
Note that there will be an setReady call before letting the user consume
|
Note that there will be an setReady call before letting the user consume
|
||||||
this user deployment, so this is more informational (so, if you keep at
|
this user deployment, so this is more informational (so, if you keep at
|
||||||
what cache level is this instance, you can update it) than anything else.
|
what cache level is this instance, you can update it) than anything else.
|
||||||
|
|
||||||
This is not a task method. All level 1 cache items can be dircetly
|
This is not a task method. All level 1 cache items can be dircetly
|
||||||
assigned to an user with no more work needed, but, if something is needed,
|
assigned to an user with no more work needed, but, if something is needed,
|
||||||
here you can do whatever you need.
|
here you can do whatever you need.
|
||||||
|
|
||||||
user is a Database user object.
|
user is a Database user object.
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def moveToCache(self, newLevel):
|
def moveToCache(self, newLevel):
|
||||||
'''
|
'''
|
||||||
This method is invoked whenever the core needs to move from the current
|
This method is invoked whenever the core needs to move from the current
|
||||||
cache level to a new cache level an user deployment.
|
cache level to a new cache level an user deployment.
|
||||||
|
|
||||||
This is a task method. As that, the expected return values are
|
This is a task method. As that, the expected return values are
|
||||||
State values RUNNING, FINISHED or ERROR.
|
State values RUNNING, FINISHED or ERROR.
|
||||||
|
|
||||||
We only provide newLevel, because there is only two cache levels, so if
|
We only provide newLevel, because there is only two cache levels, so if
|
||||||
newLevel is L1, the actual is L2, and if it is L2, the actual is L1.
|
newLevel is L1, the actual is L2, and if it is L2, the actual is L1.
|
||||||
|
|
||||||
Actually there is no possibility to move assigned services again back to
|
Actually there is no possibility to move assigned services again back to
|
||||||
cache. If some service needs that kind of functionallity, this must be
|
cache. If some service needs that kind of functionallity, this must be
|
||||||
provided at service level (for example, when doing publishing creating
|
provided at service level (for example, when doing publishing creating
|
||||||
a number of services that will be used, released and reused by users).
|
a number of services that will be used, released and reused by users).
|
||||||
|
|
||||||
Also, user deployments that are at cache level 2 will never get directly
|
Also, user deployments that are at cache level 2 will never get directly
|
||||||
assigned to user. First, it will pass to L1 and then it will get assigned.
|
assigned to user. First, it will pass to L1 and then it will get assigned.
|
||||||
|
|
||||||
A good sample of a real implementation of this is moving a virtual machine
|
A good sample of a real implementation of this is moving a virtual machine
|
||||||
from a "suspended" state to "running" state to assign it to an user.
|
from a "suspended" state to "running" state to assign it to an user.
|
||||||
|
|
||||||
:note: All task methods, like this one, are expected to handle
|
:note: All task methods, like this one, are expected to handle
|
||||||
all exceptions, and never raise an exception from these methods
|
all exceptions, and never raise an exception from these methods
|
||||||
to the core. Take that into account and handle exceptions inside
|
to the core. Take that into account and handle exceptions inside
|
||||||
this method.
|
this method.
|
||||||
'''
|
'''
|
||||||
return State.FINISHED
|
return State.FINISHED
|
||||||
|
|
||||||
def userLoggedIn(self, username):
|
def userLoggedIn(self, username):
|
||||||
'''
|
'''
|
||||||
This method must be available so os managers can invoke it whenever
|
This method must be available so os managers can invoke it whenever
|
||||||
an user get logged into a service.
|
an user get logged into a service.
|
||||||
|
|
||||||
Default implementation does nothing, so if you are going to do nothing,
|
Default implementation does nothing, so if you are going to do nothing,
|
||||||
you don't need to implement it.
|
you don't need to implement it.
|
||||||
|
|
||||||
The responsibility of notifying it is of os manager actor, and it's
|
The responsibility of notifying it is of os manager actor, and it's
|
||||||
directly invoked by os managers (right now, linux os manager and windows
|
directly invoked by os managers (right now, linux os manager and windows
|
||||||
os manager)
|
os manager)
|
||||||
|
|
||||||
The user provided is just an string, that is provided by actors.
|
The user provided is just an string, that is provided by actors.
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def userLoggedOut(self, username):
|
def userLoggedOut(self, username):
|
||||||
'''
|
'''
|
||||||
This method must be available so os managers can invoke it whenever
|
This method must be available so os managers can invoke it whenever
|
||||||
an user get logged out if a service.
|
an user get logged out if a service.
|
||||||
|
|
||||||
Default implementation does nothing, so if you are going to do nothing,
|
Default implementation does nothing, so if you are going to do nothing,
|
||||||
you don't need to implement it.
|
you don't need to implement it.
|
||||||
|
|
||||||
The responability of notifying it is of os manager actor, and it's
|
The responability of notifying it is of os manager actor, and it's
|
||||||
directly invoked by os managers (right now, linux os manager and windows
|
directly invoked by os managers (right now, linux os manager and windows
|
||||||
os manager)
|
os manager)
|
||||||
|
|
||||||
The user provided is just an string, that is provided by actor.
|
The user provided is just an string, that is provided by actor.
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
@ -523,11 +515,11 @@ class UserDeployment(Environmentable, Serializable):
|
|||||||
def reasonOfError(self):
|
def reasonOfError(self):
|
||||||
'''
|
'''
|
||||||
Returns the reason of the error.
|
Returns the reason of the error.
|
||||||
|
|
||||||
Remember that the class is responsible of returning this whenever asked
|
Remember that the class is responsible of returning this whenever asked
|
||||||
for it, and it will be asked everytime it's needed to be shown to the
|
for it, and it will be asked everytime it's needed to be shown to the
|
||||||
user (when the administation asks for it).
|
user (when the administation asks for it).
|
||||||
|
|
||||||
:note: Remember that you can use ugettext to translate this error to
|
:note: Remember that you can use ugettext to translate this error to
|
||||||
user language whenever it is possible. (This one will get invoked
|
user language whenever it is possible. (This one will get invoked
|
||||||
directly from admin interface and, as so, will have translation
|
directly from admin interface and, as so, will have translation
|
||||||
@ -539,18 +531,18 @@ class UserDeployment(Environmentable, Serializable):
|
|||||||
'''
|
'''
|
||||||
This is a task method. As that, the excepted return values are
|
This is a task method. As that, the excepted return values are
|
||||||
State values RUNNING, FINISHED or ERROR.
|
State values RUNNING, FINISHED or ERROR.
|
||||||
|
|
||||||
This method gives the oportunity to remove associated data (virtual machine,
|
This method gives the oportunity to remove associated data (virtual machine,
|
||||||
...) for the user consumable this instance represents.
|
...) for the user consumable this instance represents.
|
||||||
|
|
||||||
If return value is State.RUNNING, :py:meth:.checkState will be used to
|
If return value is State.RUNNING, :py:meth:.checkState will be used to
|
||||||
check if the destroy operation has finished.
|
check if the destroy operation has finished.
|
||||||
|
|
||||||
:note: All task methods, like this one, are expected to handle
|
:note: All task methods, like this one, are expected to handle
|
||||||
all exceptions, and never raise an exception from these methods
|
all exceptions, and never raise an exception from these methods
|
||||||
to the core. Take that into account and handle exceptions inside
|
to the core. Take that into account and handle exceptions inside
|
||||||
this method.
|
this method.
|
||||||
'''
|
'''
|
||||||
raise Exception('destroy method for class {0} not provided!'.format(self.__class__.__name__))
|
raise Exception('destroy method for class {0} not provided!'.format(self.__class__.__name__))
|
||||||
|
|
||||||
def cancel(self):
|
def cancel(self):
|
||||||
@ -561,14 +553,14 @@ class UserDeployment(Environmentable, Serializable):
|
|||||||
Cancel represents a canceling of the current running operation, and
|
Cancel represents a canceling of the current running operation, and
|
||||||
can be invoked directly by an administration or by the clean up
|
can be invoked directly by an administration or by the clean up
|
||||||
of the deployed service (indirectly).
|
of the deployed service (indirectly).
|
||||||
|
|
||||||
When administrator requests it, the cancel is "delayed" and not
|
When administrator requests it, the cancel is "delayed" and not
|
||||||
invoked directly.
|
invoked directly.
|
||||||
|
|
||||||
:note: All task methods, like this one, are expected to handle
|
:note: All task methods, like this one, are expected to handle
|
||||||
all exceptions, and never raise an exception from these methods
|
all exceptions, and never raise an exception from these methods
|
||||||
to the core. Take that into account and handle exceptions inside
|
to the core. Take that into account and handle exceptions inside
|
||||||
this method.
|
this method.
|
||||||
'''
|
'''
|
||||||
raise Exception('cancel method for class {0} not provided!'.format(self.__class__.__name__))
|
raise Exception('cancel method for class {0} not provided!'.format(self.__class__.__name__))
|
||||||
|
|
||||||
@ -576,4 +568,4 @@ class UserDeployment(Environmentable, Serializable):
|
|||||||
'''
|
'''
|
||||||
Mainly used for debugging purposses
|
Mainly used for debugging purposses
|
||||||
'''
|
'''
|
||||||
return "Base Deployed Service"
|
return "Base Deployed Service"
|
||||||
|
@ -4,53 +4,56 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from uds.core import Environmentable
|
from uds.core import Environmentable
|
||||||
from uds.core import Serializable
|
from uds.core import Serializable
|
||||||
|
|
||||||
|
|
||||||
class Publication(Environmentable, Serializable):
|
class Publication(Environmentable, Serializable):
|
||||||
'''
|
'''
|
||||||
This class is in fact an interface, and defines the logic of a publication
|
This class is in fact an interface, and defines the logic of a publication
|
||||||
for a Service.
|
for a Service.
|
||||||
|
|
||||||
A publication is the preparation of the needs of a service before it can
|
A publication is the preparation of the needs of a service before it can
|
||||||
be provided to users. One good sample of this is, in case of virtual machines,
|
be provided to users. One good sample of this is, in case of virtual machines,
|
||||||
to copy a machine to provide COWS of this copy to users.
|
to copy a machine to provide COWS of this copy to users.
|
||||||
|
|
||||||
As always, do not forget to invoke base class __init__ if you override it as this::
|
As always, do not forget to invoke base class __init__ if you override it as this::
|
||||||
|
|
||||||
super(self.__class__, self).__init__(environment, **kwargs)
|
super(self.__class__, self).__init__(environment, **kwargs)
|
||||||
|
|
||||||
This is a MUST, so internal structured gets filled correctly, so don't forget it!.
|
This is a MUST, so internal structured gets filled correctly, so don't forget it!.
|
||||||
|
|
||||||
The preferred method is not to override init, but provide the :py:meth:`.initialize`,
|
The preferred method is not to override init, but provide the :py:meth:`.initialize`,
|
||||||
that will be invoked just after all internal initialization is completed.
|
that will be invoked just after all internal initialization is completed.
|
||||||
|
|
||||||
Normally objects of classes deriving from this one, will be serialized, called,
|
Normally objects of classes deriving from this one, will be serialized, called,
|
||||||
deserialized. This means that all that you want to ensure that is keeped inside
|
deserialized. This means that all that you want to ensure that is keeped inside
|
||||||
the class must be serialized and unserialized, because there is no warantee that
|
the class must be serialized and unserialized, because there is no warantee that
|
||||||
@ -58,20 +61,20 @@ class Publication(Environmentable, Serializable):
|
|||||||
and loaded again, this means, IMPLEMENT marshal and unmarshal with all attributes
|
and loaded again, this means, IMPLEMENT marshal and unmarshal with all attributes
|
||||||
that you want to keep.
|
that you want to keep.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# Constants for publications
|
# Constants for publications
|
||||||
|
|
||||||
# Description of the publication
|
# Description of the publication
|
||||||
|
|
||||||
#:Suggested time for publication finishing, in seconds
|
# :Suggested time for publication finishing, in seconds
|
||||||
#: This allows the manager to, if publication is no done in 1 step,
|
# : This allows the manager to, if publication is no done in 1 step,
|
||||||
#: re-check the publication once this time has passed, i.e. KVM COW publication
|
# : re-check the publication once this time has passed, i.e. KVM COW publication
|
||||||
#: takes low time, so we suggest to check at short intervals,
|
# : takes low time, so we suggest to check at short intervals,
|
||||||
#: but full clone takes a lot, so we suggest that checks are done more steady.
|
# : but full clone takes a lot, so we suggest that checks are done more steady.
|
||||||
#: This attribute is always accessed using an instance object, so you can
|
# : This attribute is always accessed using an instance object, so you can
|
||||||
#: change suggestedTime in your implementation.
|
# : change suggestedTime in your implementation.
|
||||||
suggestedTime = 10
|
suggestedTime = 10
|
||||||
|
|
||||||
def __init__(self, environment, **kwargs):
|
def __init__(self, environment, **kwargs):
|
||||||
'''
|
'''
|
||||||
Do not forget to invoke this in your derived class using "super(self.__class__, self).__init__(environment, values)"
|
Do not forget to invoke this in your derived class using "super(self.__class__, self).__init__(environment, values)"
|
||||||
@ -82,12 +85,12 @@ class Publication(Environmentable, Serializable):
|
|||||||
Environmentable.__init__(self, environment)
|
Environmentable.__init__(self, environment)
|
||||||
Serializable.__init__(self)
|
Serializable.__init__(self)
|
||||||
self._osManager = kwargs.get('osManager', None)
|
self._osManager = kwargs.get('osManager', None)
|
||||||
self._service = kwargs['service'] # Raises an exception if service is not included
|
self._service = kwargs['service'] # Raises an exception if service is not included
|
||||||
self._revision = kwargs.get('revision', -1)
|
self._revision = kwargs.get('revision', -1)
|
||||||
self._dsName = kwargs.get('dsName', 'Unknown')
|
self._dsName = kwargs.get('dsName', 'Unknown')
|
||||||
|
|
||||||
self.initialize()
|
self.initialize()
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
'''
|
'''
|
||||||
This method will be invoked from __init__ constructor.
|
This method will be invoked from __init__ constructor.
|
||||||
@ -97,13 +100,13 @@ class Publication(Environmentable, Serializable):
|
|||||||
you can here access service, osManager, ...
|
you can here access service, osManager, ...
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def service(self):
|
def service(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access parent service of this publication
|
Utility method to access parent service of this publication
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
|
||||||
Parent service instance object (not database object)
|
Parent service instance object (not database object)
|
||||||
'''
|
'''
|
||||||
return self._service
|
return self._service
|
||||||
@ -111,48 +114,48 @@ class Publication(Environmentable, Serializable):
|
|||||||
def osManager(self):
|
def osManager(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access os manager for this publication.
|
Utility method to access os manager for this publication.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
|
||||||
Parent service instance object (not database object)
|
Parent service instance object (not database object)
|
||||||
The returned value can be None if no Os manager is needed by
|
The returned value can be None if no Os manager is needed by
|
||||||
the service owner of this publication.
|
the service owner of this publication.
|
||||||
'''
|
'''
|
||||||
return self._osManager
|
return self._osManager
|
||||||
|
|
||||||
def revision(self):
|
def revision(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access the revision of this publication
|
Utility method to access the revision of this publication
|
||||||
This is a numeric value, and is set by core
|
This is a numeric value, and is set by core
|
||||||
'''
|
'''
|
||||||
return self._revision
|
return self._revision
|
||||||
|
|
||||||
def dsName(self):
|
def dsName(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access the declared deployed service name.
|
Utility method to access the declared deployed service name.
|
||||||
|
|
||||||
This name is set by core, using the administrator provided data
|
This name is set by core, using the administrator provided data
|
||||||
at administration interface.
|
at administration interface.
|
||||||
'''
|
'''
|
||||||
return self._dsName
|
return self._dsName
|
||||||
|
|
||||||
def publish(self):
|
def publish(self):
|
||||||
'''
|
'''
|
||||||
This method is invoked whenever the administrator requests a new publication.
|
This method is invoked whenever the administrator requests a new publication.
|
||||||
|
|
||||||
The method is not invoked directly (i mean, that the administration request
|
The method is not invoked directly (i mean, that the administration request
|
||||||
do no makes a call to this method), but a DelayedTask is saved witch will
|
do no makes a call to this method), but a DelayedTask is saved witch will
|
||||||
initiate all publication stuff (and, of course, call this method).
|
initiate all publication stuff (and, of course, call this method).
|
||||||
|
|
||||||
You MUST implement it, so the publication do really something.
|
You MUST implement it, so the publication do really something.
|
||||||
All publications can be synchronous or asynchronous.
|
All publications can be synchronous or asynchronous.
|
||||||
|
|
||||||
The main difference between both is that first do whatever needed, (the
|
The main difference between both is that first do whatever needed, (the
|
||||||
action must be fast enough to do not block core), returning State.FINISHED.
|
action must be fast enough to do not block core), returning State.FINISHED.
|
||||||
|
|
||||||
The second (asynchronous) are publications that could block the core, so
|
The second (asynchronous) are publications that could block the core, so
|
||||||
it have to be done in more than one step.
|
it have to be done in more than one step.
|
||||||
|
|
||||||
An example publication could be a copy of a virtual machine, where:
|
An example publication could be a copy of a virtual machine, where:
|
||||||
* First we invoke the copy operation to virtualization provider
|
* First we invoke the copy operation to virtualization provider
|
||||||
* Second, we kept needed values inside instance so we can serialize
|
* Second, we kept needed values inside instance so we can serialize
|
||||||
@ -161,59 +164,59 @@ class Publication(Environmentable, Serializable):
|
|||||||
has started but has to finish sometime later. (We do no check
|
has started but has to finish sometime later. (We do no check
|
||||||
again the state and keep waiting here, because we will block the
|
again the state and keep waiting here, because we will block the
|
||||||
core untill this operation is finished).
|
core untill this operation is finished).
|
||||||
|
|
||||||
:note: This method MUST be provided, an exception is raised if not.
|
:note: This method MUST be provided, an exception is raised if not.
|
||||||
|
|
||||||
:note: All task methods, like this one, are expected to handle
|
:note: All task methods, like this one, are expected to handle
|
||||||
all exceptions, and never raise an exception from these methods
|
all exceptions, and never raise an exception from these methods
|
||||||
to the core. Take that into account and handle exceptions inside
|
to the core. Take that into account and handle exceptions inside
|
||||||
this method.
|
this method.
|
||||||
'''
|
'''
|
||||||
raise Exception('publish method for class {0} not provided! '.format(self.__class__.__name__))
|
raise Exception('publish method for class {0} not provided! '.format(self.__class__.__name__))
|
||||||
|
|
||||||
def checkState(self):
|
def checkState(self):
|
||||||
'''
|
'''
|
||||||
This is a task method. As that, the expected return values are
|
This is a task method. As that, the expected return values are
|
||||||
State values RUNNING, FINISHED or ERROR.
|
State values RUNNING, FINISHED or ERROR.
|
||||||
|
|
||||||
This method will be invoked whenever a publication is started, but it
|
This method will be invoked whenever a publication is started, but it
|
||||||
do not finish in 1 step.
|
do not finish in 1 step.
|
||||||
|
|
||||||
The idea behind this is simple, we can initiate an operation of publishing,
|
The idea behind this is simple, we can initiate an operation of publishing,
|
||||||
that will be done at :py:meth:.publish method.
|
that will be done at :py:meth:.publish method.
|
||||||
|
|
||||||
If this method returns that the operation has been initiated, but not finished
|
If this method returns that the operation has been initiated, but not finished
|
||||||
(State.RUNNING), the core will keep calling this method until checkState
|
(State.RUNNING), the core will keep calling this method until checkState
|
||||||
returns State.FINISHED (or State.error).
|
returns State.FINISHED (or State.error).
|
||||||
|
|
||||||
You MUST always provide this method if you expect the publication no to be
|
You MUST always provide this method if you expect the publication no to be
|
||||||
done in 1 step (meaning this that if publish can return State.RUNNING, this
|
done in 1 step (meaning this that if publish can return State.RUNNING, this
|
||||||
will get called)
|
will get called)
|
||||||
|
|
||||||
:note: All task methods, like this one, are expected to handle
|
:note: All task methods, like this one, are expected to handle
|
||||||
all exceptions, and never raise an exception from these methods
|
all exceptions, and never raise an exception from these methods
|
||||||
to the core. Take that into account and handle exceptions inside
|
to the core. Take that into account and handle exceptions inside
|
||||||
this method.
|
this method.
|
||||||
'''
|
'''
|
||||||
raise Exception('checkState method for class {0} not provided!!!'.format(self.__class__.__name__))
|
raise Exception('checkState method for class {0} not provided!!!'.format(self.__class__.__name__))
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
'''
|
'''
|
||||||
Invoked when Publication manager noticed that the publication has finished.
|
Invoked when Publication manager noticed that the publication has finished.
|
||||||
This give us the opportunity of cleaning up things (as stored vars, etc..)
|
This give us the opportunity of cleaning up things (as stored vars, etc..)
|
||||||
Returned value, if any, is ignored
|
Returned value, if any, is ignored
|
||||||
|
|
||||||
Default implementation does nothing. You can leave default method if you
|
Default implementation does nothing. You can leave default method if you
|
||||||
are going to do nothing.
|
are going to do nothing.
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def reasonOfError(self):
|
def reasonOfError(self):
|
||||||
'''
|
'''
|
||||||
If a publication produces an error, here we must return the reason why
|
If a publication produces an error, here we must return the reason why
|
||||||
it happened. This will be called just after publish or checkPublishingState
|
it happened. This will be called just after publish or checkPublishingState
|
||||||
if they return State.ERROR
|
if they return State.ERROR
|
||||||
|
|
||||||
The returned value, an string, will be used always by administration interface,
|
The returned value, an string, will be used always by administration interface,
|
||||||
meaning this that the translation environment will be ready, and that you
|
meaning this that the translation environment will be ready, and that you
|
||||||
can use ugettext to return a version that can be translated to administration
|
can use ugettext to return a version that can be translated to administration
|
||||||
@ -227,18 +230,18 @@ class Publication(Environmentable, Serializable):
|
|||||||
State values RUNNING, FINISHED or ERROR.
|
State values RUNNING, FINISHED or ERROR.
|
||||||
|
|
||||||
Invoked for destroying a deployed service
|
Invoked for destroying a deployed service
|
||||||
Do whatever needed here, as deleting associated data if needed
|
Do whatever needed here, as deleting associated data if needed
|
||||||
(i.e. a copy of the machine, snapshots, etc...)
|
(i.e. a copy of the machine, snapshots, etc...)
|
||||||
|
|
||||||
This method MUST be provided, even if you do nothing here (in that case,
|
This method MUST be provided, even if you do nothing here (in that case,
|
||||||
simply return State.FINISHED). Default implementation will raise an
|
simply return State.FINISHED). Default implementation will raise an
|
||||||
exception if it gets called
|
exception if it gets called
|
||||||
|
|
||||||
:note: All task methods, like this one, are expected to handle
|
:note: All task methods, like this one, are expected to handle
|
||||||
all exceptions, and never raise an exception from these methods
|
all exceptions, and never raise an exception from these methods
|
||||||
to the core. Take that into account and handle exceptions inside
|
to the core. Take that into account and handle exceptions inside
|
||||||
this method.
|
this method.
|
||||||
'''
|
'''
|
||||||
raise Exception('destroy method for class {0} not provided!'.format(self.__class__.__name__))
|
raise Exception('destroy method for class {0} not provided!'.format(self.__class__.__name__))
|
||||||
|
|
||||||
def cancel(self):
|
def cancel(self):
|
||||||
@ -249,21 +252,20 @@ class Publication(Environmentable, Serializable):
|
|||||||
This method is invoked whenever the core needs a cancelation of current
|
This method is invoked whenever the core needs a cancelation of current
|
||||||
operation. This will happen if we are, for example, preparing the
|
operation. This will happen if we are, for example, preparing the
|
||||||
service for users, but the administration request to stop doing this.
|
service for users, but the administration request to stop doing this.
|
||||||
|
|
||||||
This method MUST be provided, even if you do nothing here (in that case,
|
This method MUST be provided, even if you do nothing here (in that case,
|
||||||
simply return State.FINISHED). Default implementation will raise an
|
simply return State.FINISHED). Default implementation will raise an
|
||||||
exception if it gets called
|
exception if it gets called
|
||||||
|
|
||||||
:note: All task methods, like this one, are expected to handle
|
:note: All task methods, like this one, are expected to handle
|
||||||
all exceptions, and never raise an exception from these methods
|
all exceptions, and never raise an exception from these methods
|
||||||
to the core. Take that into account and handle exceptions inside
|
to the core. Take that into account and handle exceptions inside
|
||||||
this method.
|
this method.
|
||||||
'''
|
'''
|
||||||
raise Exception('cancel method for class {0} not provided!'.format(self.__class__.__name__))
|
raise Exception('cancel method for class {0} not provided!'.format(self.__class__.__name__))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
'''
|
'''
|
||||||
String method, mainly used for debugging purposes
|
String method, mainly used for debugging purposes
|
||||||
'''
|
'''
|
||||||
return "Base Publication"
|
return "Base Publication"
|
||||||
|
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -35,29 +35,30 @@ from __future__ import unicode_literals
|
|||||||
from django.utils.translation import ugettext_noop as _
|
from django.utils.translation import ugettext_noop as _
|
||||||
from uds.core import Module
|
from uds.core import Module
|
||||||
|
|
||||||
|
|
||||||
class Service(Module):
|
class Service(Module):
|
||||||
'''
|
'''
|
||||||
This class is in fact an interface, and represents a service, that is the
|
This class is in fact an interface, and represents a service, that is the
|
||||||
definition of an offering for consumers (users).
|
definition of an offering for consumers (users).
|
||||||
|
|
||||||
Class derived from this one declares the behavior of the service, as well
|
Class derived from this one declares the behavior of the service, as well
|
||||||
as custom parameter that will be needed to provide final consumable elements
|
as custom parameter that will be needed to provide final consumable elements
|
||||||
to users.
|
to users.
|
||||||
|
|
||||||
The behavior attributes must be declared always, although they have default
|
The behavior attributes must be declared always, although they have default
|
||||||
values, this can change in a future and declaring all needed is a good way
|
values, this can change in a future and declaring all needed is a good way
|
||||||
to avoid future problems. Of course, if you declare that do no do something
|
to avoid future problems. Of course, if you declare that do no do something
|
||||||
(i.e. do not uses cache), you will not have to declare related attributes
|
(i.e. do not uses cache), you will not have to declare related attributes
|
||||||
(i.e. cacheTooltip, usesCache_L2 and cacheTooltip_L2)
|
(i.e. cacheTooltip, usesCache_L2 and cacheTooltip_L2)
|
||||||
|
|
||||||
As you derive from this class, if you provide __init__ in your own class,
|
As you derive from this class, if you provide __init__ in your own class,
|
||||||
remember to call ALWAYS at base class __init__ as this:
|
remember to call ALWAYS at base class __init__ as this:
|
||||||
|
|
||||||
super(self.__class__, self).__init__(dbAuth, environment, values)
|
super(self.__class__, self).__init__(dbAuth, environment, values)
|
||||||
|
|
||||||
This is a MUST (if you override __init__), so internal structured gets
|
This is a MUST (if you override __init__), so internal structured gets
|
||||||
filled correctly, so don't forget it!.
|
filled correctly, so don't forget it!.
|
||||||
|
|
||||||
The preferred method of provide initialization is to provide the :py:meth:`.initialize`,
|
The preferred method of provide initialization is to provide the :py:meth:`.initialize`,
|
||||||
and do not override __init__ method. This (initialize) will be invoked after
|
and do not override __init__ method. This (initialize) will be invoked after
|
||||||
all internal initialization, so there will be available parent, environment and storage.
|
all internal initialization, so there will be available parent, environment and storage.
|
||||||
@ -70,90 +71,90 @@ class Service(Module):
|
|||||||
default implementation marshals and unmashals them, so if your case is that you
|
default implementation marshals and unmashals them, so if your case is that you
|
||||||
only need data that is keeped at form fields, marshal and unmarshal and in fact
|
only need data that is keeped at form fields, marshal and unmarshal and in fact
|
||||||
not needed.
|
not needed.
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
#: Constant for indicating that max elements this service can deploy is unlimited.
|
|
||||||
UNLIMITED = -1
|
|
||||||
|
|
||||||
#: Name of type, used at administration interface to identify this
|
|
||||||
#: service (i.e. Xen server, oVirt Server, ...)
|
|
||||||
#: This string will be translated when provided to admin interface
|
|
||||||
#: using ugettext, so you can mark it as "_" at derived classes (using ugettext_noop)
|
|
||||||
#: if you want so it can be translated.
|
|
||||||
typeName = _('Base Service')
|
|
||||||
|
|
||||||
#: Name of type used by Managers to identify this type of service
|
'''
|
||||||
#: We could have used here the Class name, but we decided that the
|
|
||||||
#: module implementator will be the one that will provide a name that
|
# : Constant for indicating that max elements this service can deploy is unlimited.
|
||||||
#: will relation the class (type) and that name.
|
UNLIMITED = -1
|
||||||
|
|
||||||
|
# : Name of type, used at administration interface to identify this
|
||||||
|
# : service (i.e. Xen server, oVirt Server, ...)
|
||||||
|
# : This string will be translated when provided to admin interface
|
||||||
|
# : using ugettext, so you can mark it as "_" at derived classes (using ugettext_noop)
|
||||||
|
# : if you want so it can be translated.
|
||||||
|
typeName = _('Base Service')
|
||||||
|
|
||||||
|
# : Name of type used by Managers to identify this type of service
|
||||||
|
# : We could have used here the Class name, but we decided that the
|
||||||
|
# : module implementator will be the one that will provide a name that
|
||||||
|
# : will relation the class (type) and that name.
|
||||||
typeType = 'BaseService'
|
typeType = 'BaseService'
|
||||||
|
|
||||||
#: Description shown at administration level for this service.
|
# : Description shown at administration level for this service.
|
||||||
#: This string will be translated when provided to admin interface
|
# : This string will be translated when provided to admin interface
|
||||||
#: using ugettext, so you can mark it as "_" at derived classes (using ugettext_noop)
|
# : using ugettext, so you can mark it as "_" at derived classes (using ugettext_noop)
|
||||||
#: if you want so it can be translated.
|
# : if you want so it can be translated.
|
||||||
typeDescription = _('Base Service')
|
typeDescription = _('Base Service')
|
||||||
|
|
||||||
#: Icon file, used to represent this service at administration interface
|
|
||||||
#: This file should be at same folder as this class is, except if you provide
|
|
||||||
#: your own :py:meth:uds.core.BaseModule.BaseModule.icon method.
|
|
||||||
iconFile = 'service.png'
|
|
||||||
|
|
||||||
# Functional related data
|
|
||||||
|
|
||||||
#: Normally set to UNLIMITED. This attribute indicates if the service has some "limitation"
|
|
||||||
#: for providing deployed services to users. This attribute can be set here or
|
|
||||||
#: 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 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.
|
|
||||||
#: If you set this to True, please, provide a _ :py:attr:.cacheToolTip
|
|
||||||
usesCache = False
|
|
||||||
|
|
||||||
#: Tooltip to be used if services uses cache at administration interface, indicated by :py:attr:.usesCache
|
|
||||||
cacheTooltip = _('None') #: Tooltip shown to user when this item is pointed at admin interface
|
|
||||||
|
|
||||||
#: If user deployments can be cached (see :py:attr:.usesCache), may he also can provide a secondary cache,
|
|
||||||
#: that is no more that user deployments that are "almost ready" to be used, but preperably consumes less
|
|
||||||
#: resources than L1 cache. This can give a boost to cache L1 recovering in case of peaks
|
|
||||||
#: in demand. If you set this to True, please, provide also a _ :py:attr:.cacheTooltip_L2
|
|
||||||
usesCache_L2 = False #: If we need to generate a "Level 2" cache for this service (i.e., L1 could be running machines and L2 suspended machines)
|
|
||||||
|
|
||||||
#: Tooltip to be used if services uses L2 cache at administration interface, indicated by :py:attr:.usesCache_L2
|
|
||||||
cacheTooltip_L2 = _('None') #: Tooltip shown to user when this item is pointed at admin interface
|
|
||||||
|
|
||||||
#: If the service needs a o.s. manager (see os managers section)
|
|
||||||
needsManager = False
|
|
||||||
|
|
||||||
#: If the service can be autoassigned or needs to be assigned by administrator
|
|
||||||
#: Not all services are for assigning it. Thing, i.e., a Service that manages
|
|
||||||
#: a number of Server. The desired behavior will be to let administrator
|
|
||||||
#: the service to a user in the administration interface, an not the system
|
|
||||||
#: to assign the service automatically. If this is true, the core will not
|
|
||||||
#: assign the service automatically, so if the user do not have a consumable
|
|
||||||
#: assigned, the user will never get one (of this kind, of course)
|
|
||||||
mustAssignManually = False
|
|
||||||
|
|
||||||
#: Types of publications (preparated data for deploys)
|
# : Icon file, used to represent this service at administration interface
|
||||||
#: If you provide this, UDS will assume that the service needs a preparation.
|
# : This file should be at same folder as this class is, except if you provide
|
||||||
#: If not provided (it is None), UDS will assume that service do not needs
|
# : your own :py:meth:uds.core.BaseModule.BaseModule.icon method.
|
||||||
#: preparation. Take care, if you mark a service as it uses cache, you MUST
|
iconFile = 'service.png'
|
||||||
#: provide a publication type
|
|
||||||
#: This refers to class that provides the logic for publication, you can see
|
# Functional related data
|
||||||
#: :py:class:uds.core.services.Publication
|
|
||||||
|
# : Normally set to UNLIMITED. This attribute indicates if the service has some "limitation"
|
||||||
|
# : for providing deployed services to users. This attribute can be set here or
|
||||||
|
# : 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 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.
|
||||||
|
# : If you set this to True, please, provide a _ :py:attr:.cacheToolTip
|
||||||
|
usesCache = False
|
||||||
|
|
||||||
|
# : Tooltip to be used if services uses cache at administration interface, indicated by :py:attr:.usesCache
|
||||||
|
cacheTooltip = _('None') # : Tooltip shown to user when this item is pointed at admin interface
|
||||||
|
|
||||||
|
# : If user deployments can be cached (see :py:attr:.usesCache), may he also can provide a secondary cache,
|
||||||
|
# : that is no more that user deployments that are "almost ready" to be used, but preperably consumes less
|
||||||
|
# : resources than L1 cache. This can give a boost to cache L1 recovering in case of peaks
|
||||||
|
# : in demand. If you set this to True, please, provide also a _ :py:attr:.cacheTooltip_L2
|
||||||
|
usesCache_L2 = False # : If we need to generate a "Level 2" cache for this service (i.e., L1 could be running machines and L2 suspended machines)
|
||||||
|
|
||||||
|
# : Tooltip to be used if services uses L2 cache at administration interface, indicated by :py:attr:.usesCache_L2
|
||||||
|
cacheTooltip_L2 = _('None') # : Tooltip shown to user when this item is pointed at admin interface
|
||||||
|
|
||||||
|
# : If the service needs a o.s. manager (see os managers section)
|
||||||
|
needsManager = False
|
||||||
|
|
||||||
|
# : If the service can be autoassigned or needs to be assigned by administrator
|
||||||
|
# : Not all services are for assigning it. Thing, i.e., a Service that manages
|
||||||
|
# : a number of Server. The desired behavior will be to let administrator
|
||||||
|
# : the service to a user in the administration interface, an not the system
|
||||||
|
# : to assign the service automatically. If this is true, the core will not
|
||||||
|
# : assign the service automatically, so if the user do not have a consumable
|
||||||
|
# : assigned, the user will never get one (of this kind, of course)
|
||||||
|
mustAssignManually = False
|
||||||
|
|
||||||
|
# : Types of publications (preparated data for deploys)
|
||||||
|
# : If you provide this, UDS will assume that the service needs a preparation.
|
||||||
|
# : If not provided (it is None), UDS will assume that service do not needs
|
||||||
|
# : preparation. Take care, if you mark a service as it uses cache, you MUST
|
||||||
|
# : provide a publication type
|
||||||
|
# : This refers to class that provides the logic for publication, you can see
|
||||||
|
# : :py:class:uds.core.services.Publication
|
||||||
publicationType = None
|
publicationType = None
|
||||||
|
|
||||||
#: Types of deploys (services in cache and/or assigned to users)
|
# : Types of deploys (services in cache and/or assigned to users)
|
||||||
#: This is ALWAYS a MUST. You mast indicate the class responsible
|
# : This is ALWAYS a MUST. You mast indicate the class responsible
|
||||||
#: for managing the user deployments (user consumable services generated
|
# : for managing the user deployments (user consumable services generated
|
||||||
#: from this one). If this attribute is not set, the service will never work
|
# : from this one). If this attribute is not set, the service will never work
|
||||||
#: (core will not know how to handle the user deployments)
|
# : (core will not know how to handle the user deployments)
|
||||||
deployedType = None
|
deployedType = None
|
||||||
|
|
||||||
def __init__(self, environment, parent, values = None):
|
def __init__(self, environment, parent, values=None):
|
||||||
'''
|
'''
|
||||||
Do not forget to invoke this in your derived class using "super(self.__class__, self).__init__(environment, parent, values)".
|
Do not forget to invoke this in your derived class using "super(self.__class__, self).__init__(environment, parent, values)".
|
||||||
We want to use the env, parent methods outside class. If not called, you must implement your own methods
|
We want to use the env, parent methods outside class. If not called, you must implement your own methods
|
||||||
@ -162,64 +163,62 @@ class Service(Module):
|
|||||||
super(Service, self).__init__(environment, values)
|
super(Service, self).__init__(environment, values)
|
||||||
self._provider = parent
|
self._provider = parent
|
||||||
self.initialize(values)
|
self.initialize(values)
|
||||||
|
|
||||||
def initialize(self, values):
|
def initialize(self, values):
|
||||||
'''
|
'''
|
||||||
This method will be invoked from __init__ constructor.
|
This method will be invoked from __init__ constructor.
|
||||||
This is provided so you don't have to provide your own __init__ method,
|
This is provided so you don't have to provide your own __init__ method,
|
||||||
and invoke base methods.
|
and invoke base methods.
|
||||||
This will get invoked when all initialization stuff is done
|
This will get invoked when all initialization stuff is done
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
Values: If values is not none, this object is being initialized
|
Values: If values is not none, this object is being initialized
|
||||||
from administration interface, and not unmarshal will be done.
|
from administration interface, and not unmarshal will be done.
|
||||||
If it's None, this is initialized internally, and unmarshal will
|
If it's None, this is initialized internally, and unmarshal will
|
||||||
be called after this.
|
be called after this.
|
||||||
|
|
||||||
Default implementation does nothing
|
Default implementation does nothing
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def parent(self):
|
def parent(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access parent provider for this service
|
Utility method to access parent provider for this service
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
|
||||||
Parent provider instance object (not database object)
|
Parent provider instance object (not database object)
|
||||||
'''
|
'''
|
||||||
return self._provider
|
return self._provider
|
||||||
|
|
||||||
def requestServicesForAssignation(self, **kwargs):
|
def requestServicesForAssignation(self, **kwargs):
|
||||||
'''
|
'''
|
||||||
override this if mustAssignManualy is True
|
override this if mustAssignManualy is True
|
||||||
@params kwargs: Named arguments
|
@params kwargs: Named arguments
|
||||||
@return an array with the services that we can assign (they must be of type deployedType)
|
@return an array with the services that we can assign (they must be of type deployedType)
|
||||||
We will access the returned array in "name" basis. This means that the service will be assigned by "name", so be care that every single service
|
We will access the returned array in "name" basis. This means that the service will be assigned by "name", so be care that every single service
|
||||||
returned are not repeated... :-)
|
returned are not repeated... :-)
|
||||||
'''
|
'''
|
||||||
raise Exception('The class {0} has been marked as manually asignable but no requestServicesForAssignetion provided!!!'.format(self.__class__.__name__))
|
raise Exception('The class {0} has been marked as manually asignable but no requestServicesForAssignetion provided!!!'.format(self.__class__.__name__))
|
||||||
|
|
||||||
def macGenerator(self):
|
def macGenerator(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access provided macs generator (inside environment)
|
Utility method to access provided macs generator (inside environment)
|
||||||
|
|
||||||
Returns the environment unique mac addresses generator
|
Returns the environment unique mac addresses generator
|
||||||
'''
|
'''
|
||||||
return self.idGenerators('mac')
|
return self.idGenerators('mac')
|
||||||
|
|
||||||
def nameGenerator(self):
|
def nameGenerator(self):
|
||||||
'''
|
'''
|
||||||
Utility method to access provided names generator (inside environment)
|
Utility method to access provided names generator (inside environment)
|
||||||
|
|
||||||
Returns the environment unique name generator
|
Returns the environment unique name generator
|
||||||
'''
|
'''
|
||||||
return self.idGenerators('name')
|
return self.idGenerators('name')
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
'''
|
'''
|
||||||
String method, mainly used for debugging purposes
|
String method, mainly used for debugging purposes
|
||||||
'''
|
'''
|
||||||
return "Base Service Provider"
|
return "Base Service Provider"
|
||||||
|
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -41,21 +41,21 @@ logger = logging.getLogger(__name__)
|
|||||||
class ServiceProvider(Module):
|
class ServiceProvider(Module):
|
||||||
'''
|
'''
|
||||||
Base Service Provider Class.
|
Base Service Provider Class.
|
||||||
|
|
||||||
All classes that will represent a service provider will need to be derived
|
All classes that will represent a service provider will need to be derived
|
||||||
from this class.
|
from this class.
|
||||||
|
|
||||||
The preferred way of using this class is by its alias name, provided
|
The preferred way of using this class is by its alias name, provided
|
||||||
at uds.core.services module, ServiceProvider.
|
at uds.core.services module, ServiceProvider.
|
||||||
|
|
||||||
This is a very basic class, intended to be the root class of services.
|
This is a very basic class, intended to be the root class of services.
|
||||||
This means that services are childs of this class, declared at "offers" attribute.
|
This means that services are childs of this class, declared at "offers" attribute.
|
||||||
|
|
||||||
As you derive from this class, if you provide __init__ in your own class,
|
As you derive from this class, if you provide __init__ in your own class,
|
||||||
remember to call ALWAYS at base class __init__ as this:
|
remember to call ALWAYS at base class __init__ as this:
|
||||||
|
|
||||||
super(...., self).__init__(environment, values)
|
super(...., self).__init__(environment, values)
|
||||||
|
|
||||||
The preferred method of provide initialization is to provide the :py:meth:`.initialize`,
|
The preferred method of provide initialization is to provide the :py:meth:`.initialize`,
|
||||||
and do not overrie __init__ method. This (initialize) will be invoked after
|
and do not overrie __init__ method. This (initialize) will be invoked after
|
||||||
all internal initialization.
|
all internal initialization.
|
||||||
@ -71,50 +71,50 @@ class ServiceProvider(Module):
|
|||||||
only need data that is keeped at form fields, marshal and unmarshal and in fact
|
only need data that is keeped at form fields, marshal and unmarshal and in fact
|
||||||
not needed.
|
not needed.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
#: Services that we offers. Here is a list of service types (python types) that
|
# : Services that we offers. Here is a list of service types (python types) that
|
||||||
#: this class will provide. This types are the python clases, derived from
|
# : this class will provide. This types are the python clases, derived from
|
||||||
#: Service, that are childs of this provider
|
# : Service, that are childs of this provider
|
||||||
offers = []
|
offers = []
|
||||||
|
|
||||||
#: Name of type, used at administration interface to identify this
|
# : Name of type, used at administration interface to identify this
|
||||||
#: provider (i.e. Xen server, oVirt Server, ...)
|
# : provider (i.e. Xen server, oVirt Server, ...)
|
||||||
#: This string will be translated when provided to admin interface
|
# : This string will be translated when provided to admin interface
|
||||||
#: using ugettext, so you can mark it as "translatable" at derived classes (using ugettext_noop)
|
# : using ugettext, so you can mark it as "translatable" at derived classes (using ugettext_noop)
|
||||||
#: if you want so it can be translated.
|
# : if you want so it can be translated.
|
||||||
typeName = 'Base Provider'
|
typeName = 'Base Provider'
|
||||||
|
|
||||||
#: Name of type used by Managers to identify this tipe of service
|
# : Name of type used by Managers to identify this tipe of service
|
||||||
#: We could have used here the Class name, but we decided that the
|
# : We could have used here the Class name, but we decided that the
|
||||||
#: module implementator will be the one that will provide a name that
|
# : module implementator will be the one that will provide a name that
|
||||||
#: will relation the class (type) and that name.
|
# : will relation the class (type) and that name.
|
||||||
typeType = 'BaseServiceProvider'
|
typeType = 'BaseServiceProvider'
|
||||||
|
|
||||||
#: Description shown at administration level for this provider.
|
# : Description shown at administration level for this provider.
|
||||||
#: This string will be translated when provided to admin interface
|
# : This string will be translated when provided to admin interface
|
||||||
#: using ugettext, so you can mark it as "translatable" at derived classes (using ugettext_noop)
|
# : using ugettext, so you can mark it as "translatable" at derived classes (using ugettext_noop)
|
||||||
#: if you want so it can be translated.
|
# : if you want so it can be translated.
|
||||||
typeDescription = 'Base Service Provider'
|
typeDescription = 'Base Service Provider'
|
||||||
|
|
||||||
#: Icon file, used to represent this provider at administration interface
|
# : Icon file, used to represent this provider at administration interface
|
||||||
#: This file should be at same folder as this class is, except if you provide
|
# : This file should be at same folder as this class is, except if you provide
|
||||||
#: your own py:meth:`uds.core.BaseModule.BaseModule.icon` method.
|
# : your own py:meth:`uds.core.BaseModule.BaseModule.icon` method.
|
||||||
iconFile = 'provider.png'
|
iconFile = 'provider.png'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getServicesTypes(cls):
|
def getServicesTypes(cls):
|
||||||
'''
|
'''
|
||||||
Returns what type of services this provider offers
|
Returns what type of services this provider offers
|
||||||
'''
|
'''
|
||||||
return cls.offers
|
return cls.offers
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getServiceByType(cls, typeName):
|
def getServiceByType(cls, typeName):
|
||||||
'''
|
'''
|
||||||
Tries to locate a child service which type corresponds with the
|
Tries to locate a child service which type corresponds with the
|
||||||
one provided.
|
one provided.
|
||||||
Returns None if can't find one.
|
Returns None if can't find one.
|
||||||
|
|
||||||
:note: The type that this method looks for is not the class, but
|
:note: The type that this method looks for is not the class, but
|
||||||
the typeType that Service has.
|
the typeType that Service has.
|
||||||
'''
|
'''
|
||||||
@ -125,8 +125,7 @@ class ServiceProvider(Module):
|
|||||||
break
|
break
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def __init__(self, environment, values=None):
|
||||||
def __init__(self, environment, values = None):
|
|
||||||
'''
|
'''
|
||||||
Do not forget to invoke this in your derived class using "super(self.__class__, self).__init__(environment, values)"
|
Do not forget to invoke this in your derived class using "super(self.__class__, self).__init__(environment, values)"
|
||||||
if you override this method. Better is to provide an "__initialize__" method, that will be invoked
|
if you override this method. Better is to provide an "__initialize__" method, that will be invoked
|
||||||
@ -136,7 +135,6 @@ class ServiceProvider(Module):
|
|||||||
'''
|
'''
|
||||||
super(ServiceProvider, self).__init__(environment, values)
|
super(ServiceProvider, self).__init__(environment, values)
|
||||||
self.initialize(values)
|
self.initialize(values)
|
||||||
|
|
||||||
|
|
||||||
def initialize(self, values):
|
def initialize(self, values):
|
||||||
'''
|
'''
|
||||||
@ -144,21 +142,20 @@ class ServiceProvider(Module):
|
|||||||
This is provided so you don't have to provide your own __init__ method,
|
This is provided so you don't have to provide your own __init__ method,
|
||||||
and invoke base methods.
|
and invoke base methods.
|
||||||
This will get invoked when all initialization stuff is done
|
This will get invoked when all initialization stuff is done
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
Values: If values is not none, this object is being initialized
|
Values: If values is not none, this object is being initialized
|
||||||
from administration interface, and not unmarshal will be done.
|
from administration interface, and not unmarshal will be done.
|
||||||
If it's None, this is initialized internally, and unmarshal will
|
If it's None, this is initialized internally, and unmarshal will
|
||||||
be called after this.
|
be called after this.
|
||||||
|
|
||||||
Default implementation does nothing
|
Default implementation does nothing
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
'''
|
'''
|
||||||
Basic implementation, mostly used for debuging and testing, never used
|
Basic implementation, mostly used for debuging and testing, never used
|
||||||
at user or admin interfaces.
|
at user or admin interfaces.
|
||||||
'''
|
'''
|
||||||
return "Base Service Provider"
|
return "Base Service Provider"
|
||||||
|
|
||||||
|
@ -4,41 +4,43 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
from BasePublication import Publication
|
from BasePublication import Publication
|
||||||
|
|
||||||
|
|
||||||
class ClusteredPublication(Publication):
|
class ClusteredPublication(Publication):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
'''
|
'''
|
||||||
String method, mainly used for debugging purposes
|
String method, mainly used for debugging purposes
|
||||||
'''
|
'''
|
||||||
return "Base Clustered Publication"
|
return "Base Clustered Publication"
|
||||||
|
|
||||||
# These methods must be overriden
|
# These methods must be overriden
|
||||||
def getNode(self):
|
def getNode(self):
|
||||||
@ -46,4 +48,3 @@ class ClusteredPublication(Publication):
|
|||||||
Returns on wich node this publication has been deployed
|
Returns on wich node this publication has been deployed
|
||||||
'''
|
'''
|
||||||
raise Exception('getNode method of ClusteredPublication must be overriden!')
|
raise Exception('getNode method of ClusteredPublication must be overriden!')
|
||||||
|
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -35,12 +35,13 @@ from __future__ import unicode_literals
|
|||||||
from django.utils.translation import ugettext_noop as _
|
from django.utils.translation import ugettext_noop as _
|
||||||
from BaseService import Service
|
from BaseService import Service
|
||||||
|
|
||||||
|
|
||||||
class ClusteredService(Service):
|
class ClusteredService(Service):
|
||||||
typeName = _('Base Clustered Service')
|
typeName = _('Base Clustered Service')
|
||||||
typeType = 'BaseClusteredService'
|
typeType = 'BaseClusteredService'
|
||||||
typeDescription = _('Base Clustered Service')
|
typeDescription = _('Base Clustered Service')
|
||||||
iconFile = 'service.png'
|
iconFile = 'service.png'
|
||||||
|
|
||||||
# Utility methods
|
# Utility methods
|
||||||
def getClusterBestNodeForDeploy(self):
|
def getClusterBestNodeForDeploy(self):
|
||||||
return self.parent().getClusterBestNodeForDeploy()
|
return self.parent().getClusterBestNodeForDeploy()
|
||||||
|
@ -4,34 +4,33 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
#from __future__ import with_statement
|
|
||||||
|
|
||||||
from BaseServiceProvider import ServiceProvider
|
from BaseServiceProvider import ServiceProvider
|
||||||
from uds.core.util.Config import GlobalConfig
|
from uds.core.util.Config import GlobalConfig
|
||||||
@ -42,207 +41,203 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
HEIGHT_OF_CPU = 5
|
HEIGHT_OF_CPU = 5
|
||||||
|
|
||||||
|
|
||||||
class ClusteredServiceProvider(ServiceProvider):
|
class ClusteredServiceProvider(ServiceProvider):
|
||||||
'''
|
'''
|
||||||
This class represents a Clustered Service Provider, that is, a Service provider that forms a Cluster and needs
|
This class represents a Clustered Service Provider, that is, a Service provider that forms a Cluster and needs
|
||||||
"organization".
|
"organization".
|
||||||
|
|
||||||
It adds the needed methods to keep cluster "in good shape"
|
It adds the needed methods to keep cluster "in good shape"
|
||||||
'''
|
'''
|
||||||
typeName = 'Base Clustered Provider'
|
typeName = 'Base Clustered Provider'
|
||||||
typeType = 'BaseClusteredServiceProvider'
|
typeType = 'BaseClusteredServiceProvider'
|
||||||
typeDescription = 'Base Clustered Service Provider'
|
typeDescription = 'Base Clustered Service Provider'
|
||||||
iconFile = 'provider.png'
|
iconFile = 'provider.png'
|
||||||
|
|
||||||
balanceNodes = False # If false, clustered provider will not try to balance nodes (only tries to distribute services on best node on creation)
|
balanceNodes = False # If false, clustered provider will not try to balance nodes (only tries to distribute services on best node on creation)
|
||||||
allowInUseMigration = False # If True, means that we can migrate a service while it is being used
|
allowInUseMigration = False # If True, means that we can migrate a service while it is being used
|
||||||
canRegisterServiceOnNodeFailure = False # If can register a service on another node without accesing original node
|
canRegisterServiceOnNodeFailure = False # If can register a service on another node without accesing original node
|
||||||
|
|
||||||
|
|
||||||
# This methods do not need to be overriden
|
# This methods do not need to be overriden
|
||||||
def clusterStats(self):
|
def clusterStats(self):
|
||||||
stats = self.storage().getPickle('ClusterStats')
|
stats = self.storage().getPickle('ClusterStats')
|
||||||
if stats is None:
|
if stats is None:
|
||||||
stats = {}
|
stats = {}
|
||||||
return stats
|
return stats
|
||||||
|
|
||||||
|
|
||||||
# This method do not need to be overriden, but can be if it is needed (taking care ofc :-) )
|
# This method do not need to be overriden, but can be if it is needed (taking care ofc :-) )
|
||||||
def getClusterOverloadedNodes(self):
|
def getClusterOverloadedNodes(self):
|
||||||
'''
|
'''
|
||||||
Checks if a migration is desired, based on nodes load
|
Checks if a migration is desired, based on nodes load
|
||||||
|
|
||||||
This method will return:
|
This method will return:
|
||||||
Array of NodeName, preferably sorted by priority, with nodes that are "Overloaded".
|
Array of NodeName, preferably sorted by priority, with nodes that are "Overloaded".
|
||||||
This array, ofc, can be "empty"
|
This array, ofc, can be "empty"
|
||||||
'''
|
'''
|
||||||
if self.balanceNodes is False:
|
if self.balanceNodes is False:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
overloadedNodes = []
|
overloadedNodes = []
|
||||||
nodesStats = self.clusterStats()
|
nodesStats = self.clusterStats()
|
||||||
|
|
||||||
maxCpuLoad = GlobalConfig.CLUSTER_MIGRATE_CPULOAD.getInt(True)
|
maxCpuLoad = GlobalConfig.CLUSTER_MIGRATE_CPULOAD.getInt(True)
|
||||||
minFreeMemPercent = GlobalConfig.CLUSTER_MIGRATE_MEMORYLOAD.getInt(True)
|
minFreeMemPercent = GlobalConfig.CLUSTER_MIGRATE_MEMORYLOAD.getInt(True)
|
||||||
|
|
||||||
for nodeName, nodeStats in nodesStats.iteritems():
|
for nodeName, nodeStats in nodesStats.iteritems():
|
||||||
if nodeStats['freeMemory'] is None or nodeStats['totalMemory'] is None or nodeStats['cpuLoad'] is None:
|
if nodeStats['freeMemory'] is None or nodeStats['totalMemory'] is None or nodeStats['cpuLoad'] is None:
|
||||||
continue
|
continue
|
||||||
freeMemPercent = (nodeStats['freeMemory'] * 100) / nodeStats['totalMemory']
|
freeMemPercent = (nodeStats['freeMemory'] * 100) / nodeStats['totalMemory']
|
||||||
if nodeStats['cpuLoad'] > maxCpuLoad or freeMemPercent < minFreeMemPercent:
|
if nodeStats['cpuLoad'] > maxCpuLoad or freeMemPercent < minFreeMemPercent:
|
||||||
overloadedNodes.append(nodeName)
|
overloadedNodes.append(nodeName)
|
||||||
|
|
||||||
# Helper to sort array
|
# Helper to sort array
|
||||||
def getNodeStatsKey(name):
|
def getNodeStatsKey(name):
|
||||||
val = 0
|
val = 0
|
||||||
if nodesStats[name]['cpuLoad']>maxCpuLoad:
|
if nodesStats[name]['cpuLoad'] > maxCpuLoad:
|
||||||
val += HEIGHT_OF_CPU + nodesStats[name]['cpuLoad']
|
val += HEIGHT_OF_CPU + nodesStats[name]['cpuLoad']
|
||||||
val += 100 - (nodeStats['freeMemory'] * 100) / nodeStats['totalMemory']
|
val += 100 - (nodeStats['freeMemory'] * 100) / nodeStats['totalMemory']
|
||||||
return val
|
return val
|
||||||
|
|
||||||
# Here we sort nodes so most overloaded servers are migrated first
|
# Here we sort nodes so most overloaded servers are migrated first
|
||||||
return sorted(overloadedNodes, key=getNodeStatsKey)
|
return sorted(overloadedNodes, key=getNodeStatsKey)
|
||||||
|
|
||||||
|
|
||||||
# Same as before, this method do not need to be overriden,
|
# Same as before, this method do not need to be overriden,
|
||||||
def getClusterUnderloadedNodes(self):
|
def getClusterUnderloadedNodes(self):
|
||||||
'''
|
'''
|
||||||
Checks which nodes of the cluster are elegible for destination of machines
|
Checks which nodes of the cluster are elegible for destination of machines
|
||||||
This method is very similar to getClusterOverloadedNodes, but this returns
|
This method is very similar to getClusterOverloadedNodes, but this returns
|
||||||
a list of nodes where we can migrate the services.
|
a list of nodes where we can migrate the services.
|
||||||
|
|
||||||
This method will return:
|
This method will return:
|
||||||
Array of NodeName, preferably sorted by priority, with nodes that are "Underloaded"
|
Array of NodeName, preferably sorted by priority, with nodes that are "Underloaded"
|
||||||
This array, ofc, can be "empty"
|
This array, ofc, can be "empty"
|
||||||
'''
|
'''
|
||||||
if self.balanceNodes is False:
|
if self.balanceNodes is False:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
underloadedNodes = []
|
underloadedNodes = []
|
||||||
nodesStats = self.clusterStats()
|
nodesStats = self.clusterStats()
|
||||||
|
|
||||||
maxCpuLoad = GlobalConfig.CLUSTER_ELEGIBLE_CPULOAD.getInt(True)
|
maxCpuLoad = GlobalConfig.CLUSTER_ELEGIBLE_CPULOAD.getInt(True)
|
||||||
minFreeMemPercent = GlobalConfig.CLUSTER_ELEGIBLE_MEMORYLOAD.getInt(True)
|
minFreeMemPercent = GlobalConfig.CLUSTER_ELEGIBLE_MEMORYLOAD.getInt(True)
|
||||||
|
|
||||||
for nodeName, nodeStats in nodesStats.iteritems():
|
for nodeName, nodeStats in nodesStats.iteritems():
|
||||||
if nodeStats['freeMemory'] is None or nodeStats['totalMemory'] is None or nodeStats['cpuLoad'] is None:
|
if nodeStats['freeMemory'] is None or nodeStats['totalMemory'] is None or nodeStats['cpuLoad'] is None:
|
||||||
continue
|
continue
|
||||||
freeMemPercent = (nodeStats['freeMemory'] * 100) / nodeStats['totalMemory']
|
freeMemPercent = (nodeStats['freeMemory'] * 100) / nodeStats['totalMemory']
|
||||||
if nodeStats['cpuLoad'] < maxCpuLoad and freeMemPercent > minFreeMemPercent:
|
if nodeStats['cpuLoad'] < maxCpuLoad and freeMemPercent > minFreeMemPercent:
|
||||||
underloadedNodes.append(nodeName)
|
underloadedNodes.append(nodeName)
|
||||||
|
|
||||||
# Helper to sort array
|
# Helper to sort array
|
||||||
def getNodeStatsKey(name):
|
def getNodeStatsKey(name):
|
||||||
ns = nodesStats[name]
|
ns = nodesStats[name]
|
||||||
memUsePercent = (ns['freeMemory'] * 100) / ns['totalMemory']
|
memUsePercent = (ns['freeMemory'] * 100) / ns['totalMemory']
|
||||||
# Percents of cpu is weighted over memory
|
# Percents of cpu is weighted over memory
|
||||||
val = (maxCpuLoad - ns['cpuLoad']) * HEIGHT_OF_CPU + (minFreeMemPercent - memUsePercent)
|
val = (maxCpuLoad - ns['cpuLoad']) * HEIGHT_OF_CPU + (minFreeMemPercent - memUsePercent)
|
||||||
return -val
|
return -val
|
||||||
|
|
||||||
# Here we sort nodes so most overloaded servers are migrated first
|
# Here we sort nodes so most overloaded servers are migrated first
|
||||||
return sorted(underloadedNodes, key=getNodeStatsKey)
|
return sorted(underloadedNodes, key=getNodeStatsKey)
|
||||||
|
|
||||||
def getClusterBestNodeForDeploy(self):
|
def getClusterBestNodeForDeploy(self):
|
||||||
|
|
||||||
nodesStats = self.clusterStats()
|
nodesStats = self.clusterStats()
|
||||||
nodes = [name for name in nodesStats.iterkeys()]
|
nodes = [name for name in nodesStats.iterkeys()]
|
||||||
|
|
||||||
def getNodeStatsKey(name):
|
def getNodeStatsKey(name):
|
||||||
ns = nodesStats[name]
|
ns = nodesStats[name]
|
||||||
if ns['freeMemory'] is None or ns['totalMemory'] is None or ns['cpuLoad'] is None:
|
if ns['freeMemory'] is None or ns['totalMemory'] is None or ns['cpuLoad'] is None:
|
||||||
return 0 # We will put last if do not knwo anything about a node
|
return 0 # We will put last if do not knwo anything about a node
|
||||||
|
|
||||||
memUsePercent = (ns['freeMemory'] * 100) / ns['totalMemory']
|
memUsePercent = (ns['freeMemory'] * 100) / ns['totalMemory']
|
||||||
val = (100-ns['cpuLoad']) * HEIGHT_OF_CPU + (100-memUsePercent)
|
val = (100 - ns['cpuLoad']) * HEIGHT_OF_CPU + (100 - memUsePercent)
|
||||||
return -val
|
return -val
|
||||||
|
|
||||||
return sorted(nodes, key=getNodeStatsKey)
|
return sorted(nodes, key=getNodeStatsKey)
|
||||||
|
|
||||||
def getServicesForBalancing(self, clusterNode):
|
def getServicesForBalancing(self, clusterNode):
|
||||||
'''
|
'''
|
||||||
Select machines from the specified nodes that can be "migrated"
|
Select machines from the specified nodes that can be "migrated"
|
||||||
so we can balance nodes.
|
so we can balance nodes.
|
||||||
|
|
||||||
This method returns a generator
|
This method returns a generator
|
||||||
|
|
||||||
If load balancing is not enabled for this cluster, this method will return an empty generator
|
If load balancing is not enabled for this cluster, this method will return an empty generator
|
||||||
|
|
||||||
If allowInUseMigration is not enabled, this method will only return services not in use
|
If allowInUseMigration is not enabled, this method will only return services not in use
|
||||||
|
|
||||||
Only service "fully ready" (in State "active") are eligible for mitrations
|
Only service "fully ready" (in State "active") are eligible for mitrations
|
||||||
|
|
||||||
This method will return an array of services, db Objects, that are on the specified nodes
|
This method will return an array of services, db Objects, that are on the specified nodes
|
||||||
and are "ready" for migration. The calling method MUST lock for update the record and
|
and are "ready" for migration. The calling method MUST lock for update the record and
|
||||||
update the state so it's not assigned while in migration (balancing operation)
|
update the state so it's not assigned while in migration (balancing operation)
|
||||||
'''
|
'''
|
||||||
from uds.models import UserService
|
from uds.models import UserService
|
||||||
from uds.core.util.State import State
|
from uds.core.util.State import State
|
||||||
|
|
||||||
if self.balanceNodes is False:
|
if self.balanceNodes is False:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
fltr = UserService.objects.filter(cluster_node=clusterNode, state=State.USABLE)
|
fltr = UserService.objects.filter(cluster_node=clusterNode, state=State.USABLE)
|
||||||
|
|
||||||
if self.allowInUseMigration is False:
|
if self.allowInUseMigration is False:
|
||||||
fltr = fltr.filter(in_use=False)
|
fltr = fltr.filter(in_use=False)
|
||||||
|
|
||||||
res = []
|
res = []
|
||||||
for srvc in fltr:
|
for srvc in fltr:
|
||||||
res.append(srvc)
|
res.append(srvc)
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def locateClusterService(self, serviceInstance):
|
def locateClusterService(self, serviceInstance):
|
||||||
'''
|
'''
|
||||||
This method tries to locate a service instance on every node
|
This method tries to locate a service instance on every node
|
||||||
To make this, tries to connect to all nodes and look for service.
|
To make this, tries to connect to all nodes and look for service.
|
||||||
|
|
||||||
This method can be a bit "slow", because it has to ask so we will probably redesign it using ThreadPool
|
This method can be a bit "slow", because it has to ask so we will probably redesign it using ThreadPool
|
||||||
'''
|
'''
|
||||||
from uds.core.util.ThreadPool import ThreadPool
|
from uds.core.util.ThreadPool import ThreadPool
|
||||||
|
|
||||||
node = None
|
node = None
|
||||||
def isInNode(n):
|
def isInNode(n):
|
||||||
if serviceInstance.ensureExistsOnNode(n) is True:
|
if serviceInstance.ensureExistsOnNode(n) is True:
|
||||||
node = n
|
node = n
|
||||||
|
|
||||||
pool = ThreadPool(10)
|
pool = ThreadPool(10)
|
||||||
|
|
||||||
for n in self.getClusterNodes():
|
for n in self.getClusterNodes():
|
||||||
pool.add_task(isInNode, n)
|
pool.add_task(isInNode, n)
|
||||||
|
|
||||||
pool.wait_completion()
|
pool.wait_completion()
|
||||||
return node
|
return node
|
||||||
|
|
||||||
# This methods must be overriden
|
# This methods must be overriden
|
||||||
def getClusterNodes(self):
|
def getClusterNodes(self):
|
||||||
'''
|
'''
|
||||||
This method must be overriden.
|
This method must be overriden.
|
||||||
|
|
||||||
returns the nodes of this clusters as an array dictionaries, with the id of nodes and the is the node is "active".
|
returns the nodes of this clusters as an array dictionaries, with the id of nodes and the is the node is "active".
|
||||||
Active means that it is ready to process services, inactive means that services are not available
|
Active means that it is ready to process services, inactive means that services are not available
|
||||||
|
|
||||||
This ids must be recognized later by nodes methods of ClusteredServiceProvider
|
This ids must be recognized later by nodes methods of ClusteredServiceProvider
|
||||||
Example:
|
Example:
|
||||||
[ { 'id': 'node1', 'active': True }, { 'id': 'node2', 'active': False }]
|
[ { 'id': 'node1', 'active': True }, { 'id': 'node2', 'active': False }]
|
||||||
'''
|
'''
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def getClusterNodeLoad(self, nodeId):
|
def getClusterNodeLoad(self, nodeId):
|
||||||
'''
|
'''
|
||||||
This method must be overriden
|
This method must be overriden
|
||||||
|
|
||||||
Returns the load of a node of the cluster, as a dictionary, with 3 informations used right now:
|
Returns the load of a node of the cluster, as a dictionary, with 3 informations used right now:
|
||||||
{ 'cpuLoad':, 'freeMemory'}
|
{ 'cpuLoad':, 'freeMemory'}
|
||||||
If any value is not known or can't be obtained, this can be not included in resulting dictionary, or
|
If any value is not known or can't be obtained, this can be not included in resulting dictionary, or
|
||||||
it's value can be None
|
it's value can be None
|
||||||
|
|
||||||
The units for elements are:
|
The units for elements are:
|
||||||
* cpuLoad: Load of cpu of Node (use) in %. If server has more than one CPU, average can be used (Integer)
|
* cpuLoad: Load of cpu of Node (use) in %. If server has more than one CPU, average can be used (Integer)
|
||||||
* freeMemory: Unused memory (or usable memory) of node, expressed in Kb (Integer)
|
* freeMemory: Unused memory (or usable memory) of node, expressed in Kb (Integer)
|
||||||
* totalMemory: Total memory of node, expressed in Kb (Integer)
|
* totalMemory: Total memory of node, expressed in Kb (Integer)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
return {'cpuLoad': None, 'freeMemory': None, 'totalMemory': None} # We could have used return {}, but i prefer this "sample template"
|
return {'cpuLoad': None, 'freeMemory': None, 'totalMemory': None} # We could have used return {}, but i prefer this "sample template"
|
||||||
|
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -35,11 +35,12 @@ from __future__ import unicode_literals
|
|||||||
from BaseDeployed import UserDeployment
|
from BaseDeployed import UserDeployment
|
||||||
from uds.core.util.State import State
|
from uds.core.util.State import State
|
||||||
|
|
||||||
|
|
||||||
class ClusteredUserDeployment(UserDeployment):
|
class ClusteredUserDeployment(UserDeployment):
|
||||||
|
|
||||||
def startMigration(self, dstNode):
|
def startMigration(self, dstNode):
|
||||||
return State.FINISHED
|
return State.FINISHED
|
||||||
|
|
||||||
def ensureExistsOnNode(self, node):
|
def ensureExistsOnNode(self, node):
|
||||||
'''
|
'''
|
||||||
Ensure that this method is reentrant, because it can be asked for existence in parallel
|
Ensure that this method is reentrant, because it can be asked for existence in parallel
|
||||||
@ -50,4 +51,4 @@ class ClusteredUserDeployment(UserDeployment):
|
|||||||
'''
|
'''
|
||||||
Mainly used for debugging purposses
|
Mainly used for debugging purposses
|
||||||
'''
|
'''
|
||||||
return "Base Deployed Service"
|
return "Base Deployed Service"
|
||||||
|
@ -4,71 +4,78 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
class UnsupportedException(Exception):
|
class UnsupportedException(Exception):
|
||||||
'''
|
'''
|
||||||
Reflects that we request an operation that is not supported, i.e. Cancel a publication with snapshots
|
Reflects that we request an operation that is not supported, i.e. Cancel a publication with snapshots
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class OperationException(Exception):
|
class OperationException(Exception):
|
||||||
'''
|
'''
|
||||||
Reflects that the operation requested can't be acomplished, i.e. remove an snapshot without snapshot reference, cancel non running operation, etc...
|
Reflects that the operation requested can't be acomplished, i.e. remove an snapshot without snapshot reference, cancel non running operation, etc...
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class PublishException(Exception):
|
class PublishException(Exception):
|
||||||
'''
|
'''
|
||||||
Reflects thate the publication can't be done for causes we don't know in advance
|
Reflects thate the publication can't be done for causes we don't know in advance
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class DeploymentException(Exception):
|
class DeploymentException(Exception):
|
||||||
'''
|
'''
|
||||||
Reflects that a deployment of a service (at cache, or assigned to user) can't be done for causes we don't know in advance
|
Reflects that a deployment of a service (at cache, or assigned to user) can't be done for causes we don't know in advance
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class CancelException(Exception):
|
class CancelException(Exception):
|
||||||
'''
|
'''
|
||||||
Reflects that a "cancel" operation can't be done for some reason
|
Reflects that a "cancel" operation can't be done for some reason
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
class InvalidServiceException(Exception):
|
class InvalidServiceException(Exception):
|
||||||
'''
|
'''
|
||||||
Invalid service specified. The service is not ready
|
Invalid service specified. The service is not ready
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MaxServicesReachedException(Exception):
|
class MaxServicesReachedException(Exception):
|
||||||
'''
|
'''
|
||||||
Number of maximum services has been reached, and no more services
|
Number of maximum services has been reached, and no more services
|
||||||
can be created for users.
|
can be created for users.
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
@ -4,66 +4,69 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ServiceProviderFactory(object):
|
class ServiceProviderFactory(object):
|
||||||
'''
|
'''
|
||||||
This class holds the register of all known service provider modules
|
This class holds the register of all known service provider modules
|
||||||
inside UDS.
|
inside UDS.
|
||||||
|
|
||||||
It provides a way to register and recover providers providers.
|
It provides a way to register and recover providers providers.
|
||||||
'''
|
'''
|
||||||
_factory = None
|
_factory = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
'''
|
'''
|
||||||
Initializes internal dictionary for service providers registration
|
Initializes internal dictionary for service providers registration
|
||||||
'''
|
'''
|
||||||
self._providers = {}
|
self._providers = {}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def factory():
|
def factory():
|
||||||
'''
|
'''
|
||||||
Returns the factory that keeps the register of service providers.
|
Returns the factory that keeps the register of service providers.
|
||||||
'''
|
'''
|
||||||
if ServiceProviderFactory._factory == None:
|
if ServiceProviderFactory._factory == None:
|
||||||
ServiceProviderFactory._factory = ServiceProviderFactory()
|
ServiceProviderFactory._factory = ServiceProviderFactory()
|
||||||
return ServiceProviderFactory._factory
|
return ServiceProviderFactory._factory
|
||||||
|
|
||||||
def providers(self):
|
def providers(self):
|
||||||
'''
|
'''
|
||||||
Returns the list of service providers already registered.
|
Returns the list of service providers already registered.
|
||||||
'''
|
'''
|
||||||
return self._providers
|
return self._providers
|
||||||
|
|
||||||
def insert(self, type_):
|
def insert(self, type_):
|
||||||
'''
|
'''
|
||||||
Inserts type_ as a service provider
|
Inserts type_ as a service provider
|
||||||
@ -72,12 +75,12 @@ class ServiceProviderFactory(object):
|
|||||||
# We could also check if it provides at least a service, but
|
# We could also check if it provides at least a service, but
|
||||||
# for debugging purposes, it's better to not check that
|
# for debugging purposes, it's better to not check that
|
||||||
# We will check that if service provided by "provider" needs
|
# We will check that if service provided by "provider" needs
|
||||||
# cache, but service do not provides publicationType,
|
# cache, but service do not provides publicationType,
|
||||||
# that service will not be registered and it will be informed
|
# that service will not be registered and it will be informed
|
||||||
if self._providers.get(type_.type(), None) is not None:
|
if self._providers.get(type_.type(), None) is not None:
|
||||||
logger.debug('{0} already registered as Service Provider'.format(type_))
|
logger.debug('{0} already registered as Service Provider'.format(type_))
|
||||||
return
|
return
|
||||||
|
|
||||||
offers = []
|
offers = []
|
||||||
for s in type_.offers:
|
for s in type_.offers:
|
||||||
if s.usesCache_L2 is True:
|
if s.usesCache_L2 is True:
|
||||||
@ -87,20 +90,20 @@ class ServiceProviderFactory(object):
|
|||||||
type_, s))
|
type_, s))
|
||||||
continue
|
continue
|
||||||
offers.append(s)
|
offers.append(s)
|
||||||
|
|
||||||
# Only offers valid services
|
# Only offers valid services
|
||||||
type_.offers = offers
|
type_.offers = offers
|
||||||
logger.debug('Adding provider {0} as {1}'.format(type_.type(), type_))
|
logger.debug('Adding provider {0} as {1}'.format(type_.type(), type_))
|
||||||
|
|
||||||
self._providers[type_.type()] = type_
|
self._providers[type_.type()] = type_
|
||||||
|
|
||||||
def lookup(self, typeName):
|
def lookup(self, typeName):
|
||||||
'''
|
'''
|
||||||
Tries to locate a server provider and by its name, and, if
|
Tries to locate a server provider and by its name, and, if
|
||||||
not found, returns None
|
not found, returns None
|
||||||
'''
|
'''
|
||||||
return self._providers.get(typeName, None)
|
return self._providers.get(typeName, None)
|
||||||
|
|
||||||
def servicesThatDoNotNeedPublication(self):
|
def servicesThatDoNotNeedPublication(self):
|
||||||
'''
|
'''
|
||||||
Returns a list of all service providers registered that do not need
|
Returns a list of all service providers registered that do not need
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -42,9 +42,10 @@ from ClusteredServiceProvider import ClusteredServiceProvider
|
|||||||
from ClusteredService import ClusteredService
|
from ClusteredService import ClusteredService
|
||||||
from ClusteredPublication import ClusteredPublication
|
from ClusteredPublication import ClusteredPublication
|
||||||
from ClusteredUserDeployment import ClusteredUserDeployment
|
from ClusteredUserDeployment import ClusteredUserDeployment
|
||||||
|
|
||||||
import Exceptions
|
import Exceptions
|
||||||
|
|
||||||
|
|
||||||
def factory():
|
def factory():
|
||||||
'''
|
'''
|
||||||
Returns factory for register/access to service providers
|
Returns factory for register/access to service providers
|
||||||
|
@ -4,32 +4,33 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from uds.core.util import OsDetector
|
from uds.core.util import OsDetector
|
||||||
@ -45,12 +46,12 @@ class Transport(Module):
|
|||||||
'''
|
'''
|
||||||
An OS Manager is responsible for communication the service the different actions to take (i.e. adding a windows machine to a domain)
|
An OS Manager is responsible for communication the service the different actions to take (i.e. adding a windows machine to a domain)
|
||||||
The Service (i.e. virtual machine) communicates with the OSManager via a published web method, that must include the unique ID.
|
The Service (i.e. virtual machine) communicates with the OSManager via a published web method, that must include the unique ID.
|
||||||
In order to make easier to agents identify themselfs, the Unique ID can be a list with various Ids (i.e. the macs of the virtual machine).
|
In order to make easier to agents identify themselfs, the Unique ID can be a list with various Ids (i.e. the macs of the virtual machine).
|
||||||
Server will iterate thought them and look for an identifier associated with the service. This list is a comma separated values (i.e. AA:BB:CC:DD:EE:FF,00:11:22:...)
|
Server will iterate thought them and look for an identifier associated with the service. This list is a comma separated values (i.e. AA:BB:CC:DD:EE:FF,00:11:22:...)
|
||||||
Remember also that we inherit the test and check methods from BaseModule
|
Remember also that we inherit the test and check methods from BaseModule
|
||||||
'''
|
'''
|
||||||
# Transport informational related data, inherited from BaseModule
|
# Transport informational related data, inherited from BaseModule
|
||||||
typeName = 'Base Transport Manager'
|
typeName = 'Base Transport Manager'
|
||||||
typeType = 'Base Transport'
|
typeType = 'Base Transport'
|
||||||
typeDescription = 'Base Transport'
|
typeDescription = 'Base Transport'
|
||||||
iconFile = 'transport.png'
|
iconFile = 'transport.png'
|
||||||
@ -59,46 +60,46 @@ class Transport(Module):
|
|||||||
# Windows
|
# Windows
|
||||||
# Macintosh
|
# Macintosh
|
||||||
# Linux
|
# Linux
|
||||||
supportedOss = OsDetector.desktopOss # Supported operating systems
|
supportedOss = OsDetector.desktopOss # Supported operating systems
|
||||||
|
|
||||||
# If this transport is visible via Web, via Thick Client or both
|
# If this transport is visible via Web, via Thick Client or both
|
||||||
webTransport = False
|
webTransport = False
|
||||||
tcTransport = False
|
tcTransport = False
|
||||||
|
|
||||||
def __init__(self,environment, values):
|
def __init__(self, environment, values):
|
||||||
super(Transport, self).__init__(environment, values)
|
super(Transport, self).__init__(environment, values)
|
||||||
self.initialize(values)
|
self.initialize(values)
|
||||||
|
|
||||||
def initialize(self, values):
|
def initialize(self, values):
|
||||||
'''
|
'''
|
||||||
This method will be invoked from __init__ constructor.
|
This method will be invoked from __init__ constructor.
|
||||||
This is provided so you don't have to provide your own __init__ method,
|
This is provided so you don't have to provide your own __init__ method,
|
||||||
and invoke base methods.
|
and invoke base methods.
|
||||||
This will get invoked when all initialization stuff is done
|
This will get invoked when all initialization stuff is done
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
Values: If values is not none, this object is being initialized
|
Values: If values is not none, this object is being initialized
|
||||||
from administration interface, and not unmarshal will be done.
|
from administration interface, and not unmarshal will be done.
|
||||||
If it's None, this is initialized internally, and unmarshal will
|
If it's None, this is initialized internally, and unmarshal will
|
||||||
be called after this.
|
be called after this.
|
||||||
|
|
||||||
Default implementation does nothing
|
Default implementation does nothing
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
'''
|
'''
|
||||||
Invoked when Transport is deleted
|
Invoked when Transport is deleted
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def isAvailableFor(self, ip):
|
def isAvailableFor(self, ip):
|
||||||
'''
|
'''
|
||||||
Checks if the transport is available for the requested destination ip
|
Checks if the transport is available for the requested destination ip
|
||||||
Override this in yours transports
|
Override this in yours transports
|
||||||
'''
|
'''
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def supportsOs(cls, osName):
|
def supportsOs(cls, osName):
|
||||||
'''
|
'''
|
||||||
@ -107,17 +108,17 @@ class Transport(Module):
|
|||||||
'''
|
'''
|
||||||
logger.debug('Checking suported os {0} against {1}'.format(osName, cls.supportedOss))
|
logger.debug('Checking suported os {0} against {1}'.format(osName, cls.supportedOss))
|
||||||
return cls.supportedOss.count(osName) > 0
|
return cls.supportedOss.count(osName) > 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def providesConnetionInfo(cls):
|
def providesConnetionInfo(cls):
|
||||||
'''
|
'''
|
||||||
Helper method to check if transport provides information about connection
|
Helper method to check if transport provides information about connection
|
||||||
'''
|
'''
|
||||||
return cls.getConnectionInfo != Transport.getConnectionInfo
|
return cls.getConnectionInfo != Transport.getConnectionInfo
|
||||||
|
|
||||||
def getConnectionInfo(self, service, user, password):
|
def getConnectionInfo(self, service, user, password):
|
||||||
'''
|
'''
|
||||||
This method must provide information about connection.
|
This method must provide information about connection.
|
||||||
We don't have to implement it, but if we wont to allow some types of connections
|
We don't have to implement it, but if we wont to allow some types of connections
|
||||||
(such as Client applications, some kinds of TC, etc... we must provide it or those
|
(such as Client applications, some kinds of TC, etc... we must provide it or those
|
||||||
kind of terminals/application will not work
|
kind of terminals/application will not work
|
||||||
@ -126,20 +127,20 @@ class Transport(Module):
|
|||||||
userService: DeployedUserService for witch we are rendering the connection (db model), or DeployedService (db model)
|
userService: DeployedUserService for witch we are rendering the connection (db model), or DeployedService (db model)
|
||||||
user: user (dbUser) logged in
|
user: user (dbUser) logged in
|
||||||
pass: password used in authentication
|
pass: password used in authentication
|
||||||
|
|
||||||
The expected result from this method is a dictionary, containing at least:
|
The expected result from this method is a dictionary, containing at least:
|
||||||
'protocol': protocol to use, (there are a few standard defined in 'protocols.py', if yours does not fit those, use your own name
|
'protocol': protocol to use, (there are a few standard defined in 'protocols.py', if yours does not fit those, use your own name
|
||||||
'username': username (transformed if needed to) used to login to service
|
'username': username (transformed if needed to) used to login to service
|
||||||
'password': password (transformed if needed to) used to login to service
|
'password': password (transformed if needed to) used to login to service
|
||||||
'domain': domain (extracted from username or wherever) that will be used. (Not necesarily an AD domain)
|
'domain': domain (extracted from username or wherever) that will be used. (Not necesarily an AD domain)
|
||||||
|
|
||||||
:note: The provided service can be an user service or an deployed service (parent of user services).
|
:note: The provided service can be an user service or an deployed service (parent of user services).
|
||||||
I have implemented processUserPassword in both so in most cases we do not need if the service is
|
I have implemented processUserPassword in both so in most cases we do not need if the service is
|
||||||
DeployedService or UserService. In case of processUserPassword for an DeployedService, no transformation
|
DeployedService or UserService. In case of processUserPassword for an DeployedService, no transformation
|
||||||
is done, because there is no relation at that level between user and service.
|
is done, because there is no relation at that level between user and service.
|
||||||
'''
|
'''
|
||||||
return {'protocol': protocols.NONE, 'username': '', 'password': '', 'domain': ''}
|
return {'protocol': protocols.NONE, 'username': '', 'password': '', 'domain': ''}
|
||||||
|
|
||||||
def renderForHtml(self, userService, idUserService, idTransport, ip, os, user, password):
|
def renderForHtml(self, userService, idUserService, idTransport, ip, os, user, password):
|
||||||
'''
|
'''
|
||||||
Requests the html rendering of connector for the destination ip, (dbUser) and password
|
Requests the html rendering of connector for the destination ip, (dbUser) and password
|
||||||
@ -151,16 +152,15 @@ class Transport(Module):
|
|||||||
@param pass: password used in authentication
|
@param pass: password used in authentication
|
||||||
'''
|
'''
|
||||||
return _('Transport empty')
|
return _('Transport empty')
|
||||||
|
|
||||||
def getHtmlComponent(self, id, os, componentId):
|
def getHtmlComponent(self, id, os, componentId): # @ReservedAssignment
|
||||||
'''
|
'''
|
||||||
This is a method to let the transport add own components (images, applets, or whatever) to the rendered html
|
This is a method to let the transport add own components (images, applets, or whatever) to the rendered html
|
||||||
The reference to object will be the access to the uds.web.views.transcomp, with parameters transportId = ourTransportId and
|
The reference to object will be the access to the uds.web.views.transcomp, with parameters transportId = ourTransportId and
|
||||||
componentId = one id recognized by this method
|
componentId = one id recognized by this method
|
||||||
We expect an return array, with first parameter as mime/type and second the content to return
|
We expect an return array, with first parameter as mime/type and second the content to return
|
||||||
'''
|
'''
|
||||||
return ['text/plain', '']
|
return ['text/plain', '']
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Base OS Manager"
|
return "Base OS Manager"
|
||||||
|
|
||||||
|
@ -4,55 +4,58 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class TransportsFactory(object):
|
class TransportsFactory(object):
|
||||||
_factory = None
|
_factory = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._jobs = {}
|
self._jobs = {}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def factory():
|
def factory():
|
||||||
if TransportsFactory._factory == None:
|
if TransportsFactory._factory == None:
|
||||||
TransportsFactory._factory = TransportsFactory()
|
TransportsFactory._factory = TransportsFactory()
|
||||||
return TransportsFactory._factory
|
return TransportsFactory._factory
|
||||||
|
|
||||||
def providers(self):
|
def providers(self):
|
||||||
return self._jobs
|
return self._jobs
|
||||||
|
|
||||||
def insert(self, type):
|
def insert(self, type_):
|
||||||
logger.debug('Adding transport {0} as {1}'.format(type.type(), type))
|
logger.debug('Adding transport {0} as {1}'.format(type_.type(), type_))
|
||||||
self._jobs[type.type()] = type
|
self._jobs[type_.type()] = type_
|
||||||
|
|
||||||
def lookup(self, typeName):
|
def lookup(self, typeName):
|
||||||
try:
|
try:
|
||||||
return self._jobs[typeName]
|
return self._jobs[typeName]
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -32,8 +32,11 @@ UDS Service modules interfaces and classes.
|
|||||||
|
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from BaseTransport import Transport
|
from BaseTransport import Transport
|
||||||
|
|
||||||
|
|
||||||
def factory():
|
def factory():
|
||||||
'''
|
'''
|
||||||
Returns factory for register/access to service providers
|
Returns factory for register/access to service providers
|
||||||
|
@ -4,32 +4,33 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
NONE = ''
|
NONE = ''
|
||||||
RDP = 'rdp'
|
RDP = 'rdp'
|
||||||
@ -42,4 +43,4 @@ HDX = 'hdx'
|
|||||||
ICA = 'ica'
|
ICA = 'ica'
|
||||||
NX = 'nx'
|
NX = 'nx'
|
||||||
X11 = 'x11'
|
X11 = 'x11'
|
||||||
OTHER = 'other'
|
OTHER = 'other'
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2014 Virtual Cable S.L.
|
# Copyright (c) 2014 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -34,11 +34,12 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from uds.core.util.Config import GlobalConfig
|
from uds.core.util.Config import GlobalConfig
|
||||||
|
|
||||||
|
|
||||||
def template(template_name):
|
def template(template_name):
|
||||||
theme_path = GlobalConfig.UDS_THEME.get(True)
|
theme_path = GlobalConfig.UDS_THEME.get(True)
|
||||||
if theme_path == 'default':
|
if theme_path == 'default':
|
||||||
theme_path = ''
|
theme_path = ''
|
||||||
else:
|
else:
|
||||||
theme_path += '/'
|
theme_path += '/'
|
||||||
|
|
||||||
return 'uds/{0}{1}'.format(theme_path, template_name)
|
return 'uds/{0}{1}'.format(theme_path, template_name)
|
||||||
|
@ -4,58 +4,61 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from uds.core.Serializable import Serializable
|
from uds.core.Serializable import Serializable
|
||||||
import cPickle
|
import cPickle
|
||||||
import timeit
|
import timeit
|
||||||
|
|
||||||
|
|
||||||
class Attribute(object):
|
class Attribute(object):
|
||||||
|
|
||||||
def __init__(self, theType, value = None):
|
def __init__(self, theType, value=None):
|
||||||
self._type = theType
|
self._type = theType
|
||||||
self.setValue(value)
|
self.setValue(value)
|
||||||
|
|
||||||
def getType(self):
|
def getType(self):
|
||||||
return self._type
|
return self._type
|
||||||
|
|
||||||
def getValue(self):
|
def getValue(self):
|
||||||
return self._value
|
return self._value
|
||||||
|
|
||||||
def getStrValue(self):
|
def getStrValue(self):
|
||||||
return str(self._value)
|
return str(self._value)
|
||||||
|
|
||||||
def setValue(self, value):
|
def setValue(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
self._value = self._type()
|
self._value = self._type()
|
||||||
else:
|
else:
|
||||||
self._value = self._type(value)
|
self._value = self._type(value)
|
||||||
|
|
||||||
|
|
||||||
class AutoAttributes(Serializable):
|
class AutoAttributes(Serializable):
|
||||||
'''
|
'''
|
||||||
Easy creation of attributes to marshal & unmarshal at modules
|
Easy creation of attributes to marshal & unmarshal at modules
|
||||||
@ -64,45 +67,45 @@ class AutoAttributes(Serializable):
|
|||||||
or with declare(attr1=type,attr2=type,..)
|
or with declare(attr1=type,attr2=type,..)
|
||||||
Access attrs as "self._attr1, self._attr2"
|
Access attrs as "self._attr1, self._attr2"
|
||||||
'''
|
'''
|
||||||
|
|
||||||
#: This codec is not intended to override Serializable codec
|
# : This codec is not intended to override Serializable codec
|
||||||
#: Serializable codec is for encoding marshaled data,
|
# : Serializable codec is for encoding marshaled data,
|
||||||
#: while this codec is for encoding pickled data from autoattributes
|
# : while this codec is for encoding pickled data from autoattributes
|
||||||
ACODEC = 'zip'
|
ACODEC = 'zip'
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.declare(**kwargs)
|
self.declare(**kwargs)
|
||||||
|
|
||||||
def __getattribute__(self, name):
|
def __getattribute__(self, name):
|
||||||
if name.startswith('_') and self.dict.has_key(name[1:]):
|
if name.startswith('_') and self.dict.has_key(name[1:]):
|
||||||
return self.dict[name[1:]].getValue()
|
return self.dict[name[1:]].getValue()
|
||||||
return object.__getattribute__(self, name)
|
return object.__getattribute__(self, name)
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
if name.startswith('_') and self.dict.has_key(name[1:]):
|
if name.startswith('_') and self.dict.has_key(name[1:]):
|
||||||
self.dict[name[1:]].setValue(value)
|
self.dict[name[1:]].setValue(value)
|
||||||
else:
|
else:
|
||||||
object.__setattr__(self, name, value)
|
object.__setattr__(self, name, value)
|
||||||
|
|
||||||
def declare(self, **kwargs):
|
def declare(self, **kwargs):
|
||||||
d = {}
|
d = {}
|
||||||
for key,typ in kwargs.iteritems():
|
for key, typ in kwargs.iteritems():
|
||||||
d[key] = Attribute(typ)
|
d[key] = Attribute(typ)
|
||||||
self.dict = d
|
self.dict = d
|
||||||
|
|
||||||
def marshal(self):
|
def marshal(self):
|
||||||
return '\2'.join( [ '%s\1%s' % (k, cPickle.dumps(v)) for k, v in self.dict.iteritems() ] ).encode(AutoAttributes.ACODEC)
|
return '\2'.join(['%s\1%s' % (k, cPickle.dumps(v)) for k, v in self.dict.iteritems()]).encode(AutoAttributes.ACODEC)
|
||||||
|
|
||||||
def unmarshal(self, data):
|
def unmarshal(self, data):
|
||||||
if data == '': # Can be empty
|
if data == '': # Can be empty
|
||||||
return
|
return
|
||||||
# We keep original data (maybe incomplete)
|
# We keep original data (maybe incomplete)
|
||||||
for pair in data.decode(AutoAttributes.ACODEC).split('\2'):
|
for pair in data.decode(AutoAttributes.ACODEC).split('\2'):
|
||||||
k, v = pair.split('\1')
|
k, v = pair.split('\1')
|
||||||
self.dict[k] = cPickle.loads(v)
|
self.dict[k] = cPickle.loads(v)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
str = '<AutoAttribute '
|
str_ = '<AutoAttribute '
|
||||||
for k, v in self.dict.iteritems():
|
for k, v in self.dict.iteritems():
|
||||||
str += "%s (%s) = %s" % (k, v.getType(), v.getStrValue())
|
str_ += "%s (%s) = %s" % (k, v.getType(), v.getStrValue())
|
||||||
return str + '>'
|
return str_ + '>'
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -40,27 +40,26 @@ import cPickle
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Cache(object):
|
class Cache(object):
|
||||||
DEFAULT_VALIDITY = 60
|
DEFAULT_VALIDITY = 60
|
||||||
CODEC = 'base64' # Can be zip, hez, bzip, base64, uuencoded
|
CODEC = 'base64' # Can be zip, hez, bzip, base64, uuencoded
|
||||||
|
|
||||||
def __init__(self, owner):
|
def __init__(self, owner):
|
||||||
self._owner = owner
|
self._owner = owner
|
||||||
|
|
||||||
|
|
||||||
def __getKey(self, key):
|
def __getKey(self, key):
|
||||||
import os
|
|
||||||
h = hashlib.md5()
|
h = hashlib.md5()
|
||||||
h.update(self._owner + key)
|
h.update(self._owner + key)
|
||||||
return h.hexdigest()
|
return h.hexdigest()
|
||||||
|
|
||||||
def get(self,skey, defValue = None):
|
def get(self, skey, defValue=None):
|
||||||
now = getSqlDatetime()
|
now = getSqlDatetime()
|
||||||
#logger.debug('Requesting key "%s" for cache "%s"' % (skey, self._owner,))
|
# logger.debug('Requesting key "%s" for cache "%s"' % (skey, self._owner,))
|
||||||
try:
|
try:
|
||||||
key = self.__getKey(skey)
|
key = self.__getKey(skey)
|
||||||
c = dbCache.objects.get(pk=key)
|
c = dbCache.objects.get(pk=key)
|
||||||
expired = now > c.created + timedelta(seconds = c.validity)
|
expired = now > c.created + timedelta(seconds=c.validity)
|
||||||
if expired:
|
if expired:
|
||||||
return defValue
|
return defValue
|
||||||
val = cPickle.loads(c.value.decode(Cache.CODEC))
|
val = cPickle.loads(c.value.decode(Cache.CODEC))
|
||||||
@ -68,27 +67,27 @@ class Cache(object):
|
|||||||
except dbCache.DoesNotExist:
|
except dbCache.DoesNotExist:
|
||||||
logger.debug('key not found')
|
logger.debug('key not found')
|
||||||
return defValue
|
return defValue
|
||||||
|
|
||||||
def remove(self,skey):
|
def remove(self, skey):
|
||||||
#logger.debug('Removing key "%s" for uService "%s"' % (skey, self._owner))
|
# logger.debug('Removing key "%s" for uService "%s"' % (skey, self._owner))
|
||||||
try:
|
try:
|
||||||
key = self.__getKey(skey)
|
key = self.__getKey(skey)
|
||||||
dbCache.objects.get(pk=key).delete()
|
dbCache.objects.get(pk=key).delete()
|
||||||
except dbCache.DoesNotExist:
|
except dbCache.DoesNotExist:
|
||||||
logger.debug('key not found')
|
logger.debug('key not found')
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
Cache.delete(self._owner)
|
Cache.delete(self._owner)
|
||||||
|
|
||||||
def put(self, skey, value, validity = None):
|
def put(self, skey, value, validity=None):
|
||||||
#logger.debug('Saving key "%s" for cache "%s"' % (skey, self._owner,))
|
# logger.debug('Saving key "%s" for cache "%s"' % (skey, self._owner,))
|
||||||
if validity == None:
|
if validity == None:
|
||||||
validity = Cache.DEFAULT_VALIDITY
|
validity = Cache.DEFAULT_VALIDITY
|
||||||
key = self.__getKey(skey)
|
key = self.__getKey(skey)
|
||||||
value = cPickle.dumps(value).encode(Cache.CODEC)
|
value = cPickle.dumps(value).encode(Cache.CODEC)
|
||||||
now = getSqlDatetime()
|
now = getSqlDatetime()
|
||||||
try:
|
try:
|
||||||
dbCache.objects.create( owner = self._owner, key = key, value = value, created = now, validity = validity )
|
dbCache.objects.create(owner=self._owner, key=key, value=value, created=now, validity=validity)
|
||||||
except Exception:
|
except Exception:
|
||||||
# Already exists, modify it
|
# Already exists, modify it
|
||||||
c = dbCache.objects.get(pk=key)
|
c = dbCache.objects.get(pk=key)
|
||||||
@ -98,9 +97,9 @@ class Cache(object):
|
|||||||
c.created = datetime.now()
|
c.created = datetime.now()
|
||||||
c.validity = validity
|
c.validity = validity
|
||||||
c.save()
|
c.save()
|
||||||
|
|
||||||
def refresh(self, skey):
|
def refresh(self, skey):
|
||||||
#logger.debug('Refreshing key "%s" for cache "%s"' % (skey, self._owner,))
|
# logger.debug('Refreshing key "%s" for cache "%s"' % (skey, self._owner,))
|
||||||
try:
|
try:
|
||||||
key = self.__getKey(skey)
|
key = self.__getKey(skey)
|
||||||
c = dbCache.objects.get(pk=key)
|
c = dbCache.objects.get(pk=key)
|
||||||
@ -109,21 +108,20 @@ class Cache(object):
|
|||||||
except dbCache.DoesNotExist:
|
except dbCache.DoesNotExist:
|
||||||
logger.debug('Can\'t refresh cache key %s because it don\'t exists' % skey)
|
logger.debug('Can\'t refresh cache key %s because it don\'t exists' % skey)
|
||||||
return
|
return
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def purge():
|
def purge():
|
||||||
dbCache.objects.all().delete()
|
dbCache.objects.all().delete()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def cleanUp():
|
def cleanUp():
|
||||||
dbCache.cleanUp()
|
dbCache.cleanUp()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def delete(owner = None):
|
def delete(owner=None):
|
||||||
#logger.info("Deleting cache items")
|
# logger.info("Deleting cache items")
|
||||||
if owner == None:
|
if owner == None:
|
||||||
objects = dbCache.objects.all()
|
objects = dbCache.objects.all()
|
||||||
else:
|
else:
|
||||||
objects = dbCache.objects.filter(owner=owner)
|
objects = dbCache.objects.filter(owner=owner)
|
||||||
objects.delete()
|
objects.delete()
|
||||||
|
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -43,13 +43,14 @@ GLOBAL_SECTION = 'UDS'
|
|||||||
SECURITY_SECTION = 'Security'
|
SECURITY_SECTION = 'Security'
|
||||||
CLUSTER_SECTION = 'Cluster'
|
CLUSTER_SECTION = 'Cluster'
|
||||||
|
|
||||||
|
|
||||||
class Config(object):
|
class Config(object):
|
||||||
'''
|
'''
|
||||||
Keeps persistend configuration data
|
Keeps persistend configuration data
|
||||||
'''
|
'''
|
||||||
|
|
||||||
class _Value(object):
|
class _Value(object):
|
||||||
def __init__(self, section, key, default = '', crypt = False, longText = False):
|
def __init__(self, section, key, default='', crypt=False, longText=False):
|
||||||
self._section = section
|
self._section = section
|
||||||
self._key = key
|
self._key = key
|
||||||
self._crypt = crypt
|
self._crypt = crypt
|
||||||
@ -59,19 +60,19 @@ class Config(object):
|
|||||||
else:
|
else:
|
||||||
self._default = CryptoManager.manager().encrypt(default)
|
self._default = CryptoManager.manager().encrypt(default)
|
||||||
self._data = None
|
self._data = None
|
||||||
|
|
||||||
def get(self, force = False):
|
def get(self, force=False):
|
||||||
try:
|
try:
|
||||||
if force or self._data is None:
|
if force or self._data is None:
|
||||||
#logger.debug('Accessing db config {0}.{1}'.format(self._section.name(), self._key))
|
# logger.debug('Accessing db config {0}.{1}'.format(self._section.name(), self._key))
|
||||||
readed = dbConfig.objects.filter(section=self._section.name(), key=self._key)[0]
|
readed = dbConfig.objects.filter(section=self._section.name(), key=self._key)[0]
|
||||||
self._data = readed.value
|
self._data = readed.value
|
||||||
self._crypt = [self._crypt, True][readed.crypt] # True has "higher" precedende than False
|
self._crypt = [self._crypt, True][readed.crypt] # True has "higher" precedende than False
|
||||||
self._longText = readed.long
|
self._longText = readed.long
|
||||||
except Exception:
|
except Exception:
|
||||||
# Not found
|
# Not found
|
||||||
if self._default != '' and self._crypt:
|
if self._default != '' and self._crypt:
|
||||||
self.set( CryptoManager.manager().decrypt(self._default) )
|
self.set(CryptoManager.manager().decrypt(self._default))
|
||||||
elif not self._crypt:
|
elif not self._crypt:
|
||||||
self.set(self._default)
|
self.set(self._default)
|
||||||
self._data = self._default
|
self._data = self._default
|
||||||
@ -80,7 +81,7 @@ class Config(object):
|
|||||||
else:
|
else:
|
||||||
return self._data
|
return self._data
|
||||||
|
|
||||||
def getInt(self, force = False):
|
def getInt(self, force=False):
|
||||||
try:
|
try:
|
||||||
return int(self.get(force))
|
return int(self.get(force))
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -90,21 +91,21 @@ class Config(object):
|
|||||||
except:
|
except:
|
||||||
logger.error('Default value for {0}.{1} is also invalid (integer expected)'.format(self._section, self._key))
|
logger.error('Default value for {0}.{1} is also invalid (integer expected)'.format(self._section, self._key))
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def getBool(self, force = False):
|
def getBool(self, force=False):
|
||||||
if self.get(force) == '0':
|
if self.get(force) == '0':
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def key(self):
|
def key(self):
|
||||||
return self._key
|
return self._key
|
||||||
|
|
||||||
def section(self):
|
def section(self):
|
||||||
return self._section.name()
|
return self._section.name()
|
||||||
|
|
||||||
def isCrypted(self):
|
def isCrypted(self):
|
||||||
return self._crypt
|
return self._crypt
|
||||||
|
|
||||||
def isLongText(self):
|
def isLongText(self):
|
||||||
return self._longText
|
return self._longText
|
||||||
|
|
||||||
@ -117,46 +118,44 @@ class Config(object):
|
|||||||
logger.debug('Saving config {0}.{1} as {2}'.format(self._section.name(), self._key, value))
|
logger.debug('Saving config {0}.{1} as {2}'.format(self._section.name(), self._key, value))
|
||||||
try:
|
try:
|
||||||
if dbConfig.objects.filter(section=self._section.name(), key=self._key).update(value=value, crypt=self._crypt, long=self._longText) == 0:
|
if dbConfig.objects.filter(section=self._section.name(), key=self._key).update(value=value, crypt=self._crypt, long=self._longText) == 0:
|
||||||
raise Exception() # Do not exists, create a new one
|
raise Exception() # Do not exists, create a new one
|
||||||
except Exception:
|
except Exception:
|
||||||
try:
|
try:
|
||||||
dbConfig.objects.create(section=self._section.name(), key=self._key, value=value, crypt=self._crypt, long=self._longText)
|
dbConfig.objects.create(section=self._section.name(), key=self._key, value=value, crypt=self._crypt, long=self._longText)
|
||||||
except Exception:
|
except Exception:
|
||||||
# Probably a migration issue, just ignore it
|
# Probably a migration issue, just ignore it
|
||||||
logger.info("Could not save configuration key {0}.{1}".format(self._section.name(), self._key))
|
logger.info("Could not save configuration key {0}.{1}".format(self._section.name(), self._key))
|
||||||
|
|
||||||
class _Section:
|
class _Section:
|
||||||
def __init__(self, sectionName):
|
def __init__(self, sectionName):
|
||||||
self._sectionName = sectionName
|
self._sectionName = sectionName
|
||||||
|
|
||||||
def value(self, key, default = ''):
|
def value(self, key, default=''):
|
||||||
return Config._Value(self, key, default)
|
return Config._Value(self, key, default)
|
||||||
|
|
||||||
def valueCrypt(self, key, default = ''):
|
def valueCrypt(self, key, default=''):
|
||||||
return Config._Value(self, key, default, True)
|
return Config._Value(self, key, default, True)
|
||||||
|
|
||||||
def valueLong(self, key, default = ''):
|
def valueLong(self, key, default=''):
|
||||||
return Config._Value(self, key, default, False, True)
|
return Config._Value(self, key, default, False, True)
|
||||||
|
|
||||||
def name(self):
|
def name(self):
|
||||||
return self._sectionName
|
return self._sectionName
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def section(sectionName):
|
def section(sectionName):
|
||||||
return Config._Section(sectionName)
|
return Config._Section(sectionName)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def enumerate():
|
def enumerate():
|
||||||
for cfg in dbConfig.objects.all():
|
for cfg in dbConfig.objects.all().order_by('key'):
|
||||||
logger.debug('{0}.{1}:{2}'.format(cfg.section, cfg.key, cfg.value))
|
logger.debug('{0}.{1}:{2}'.format(cfg.section, cfg.key, cfg.value))
|
||||||
if cfg.crypt is True:
|
if cfg.crypt is True:
|
||||||
val = Config.section(cfg.section).valueCrypt(cfg.key)
|
val = Config.section(cfg.section).valueCrypt(cfg.key)
|
||||||
else:
|
else:
|
||||||
val = Config.section(cfg.section).value(cfg.key)
|
val = Config.section(cfg.section).value(cfg.key)
|
||||||
yield val
|
yield val
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update(section, key, value):
|
def update(section, key, value):
|
||||||
# If cfg value does not exists, simply ignore request
|
# If cfg value does not exists, simply ignore request
|
||||||
@ -169,14 +168,15 @@ class Config(object):
|
|||||||
logger.debug('Updated value for {0}.{1} to {2}'.format(section, key, value))
|
logger.debug('Updated value for {0}.{1} to {2}'.format(section, key, value))
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class GlobalConfig(object):
|
class GlobalConfig(object):
|
||||||
'''
|
'''
|
||||||
Simple helper to keep track of global configuration
|
Simple helper to keep track of global configuration
|
||||||
'''
|
'''
|
||||||
SESSION_EXPIRE_TIME = Config.section(GLOBAL_SECTION).value('sessionExpireTime', '24') # Max session duration (in use) after a new publishment has been made
|
SESSION_EXPIRE_TIME = Config.section(GLOBAL_SECTION).value('sessionExpireTime', '24') # Max session duration (in use) after a new publishment has been made
|
||||||
# Delay between cache checks. reducing this number will increase cache generation speed but also will load service providers
|
# Delay between cache checks. reducing this number will increase cache generation speed but also will load service providers
|
||||||
CACHE_CHECK_DELAY = Config.section(GLOBAL_SECTION).value('cacheCheckDelay', '19')
|
CACHE_CHECK_DELAY = Config.section(GLOBAL_SECTION).value('cacheCheckDelay', '19')
|
||||||
# Delayed task number of threads PER SERVER, with higher number of threads, deplayed task will complete sooner, but it will give more load to overall system
|
# Delayed task number of threads PER SERVER, with higher number of threads, deplayed task will complete sooner, but it will give more load to overall system
|
||||||
DELAYED_TASKS_THREADS = Config.section(GLOBAL_SECTION).value('delayedTasksThreads', '4')
|
DELAYED_TASKS_THREADS = Config.section(GLOBAL_SECTION).value('delayedTasksThreads', '4')
|
||||||
# Number of scheduler threads running PER SERVER, with higher number of threads, deplayed task will complete sooner, but it will give more load to overall system
|
# Number of scheduler threads running PER SERVER, with higher number of threads, deplayed task will complete sooner, but it will give more load to overall system
|
||||||
@ -184,33 +184,33 @@ class GlobalConfig(object):
|
|||||||
# Waiting time before removing "errored" and "removed" publications, cache, and user assigned machines. Time is in seconds
|
# Waiting time before removing "errored" and "removed" publications, cache, and user assigned machines. Time is in seconds
|
||||||
CLEANUP_CHECK = Config.section(GLOBAL_SECTION).value('cleanupCheck', '3607')
|
CLEANUP_CHECK = Config.section(GLOBAL_SECTION).value('cleanupCheck', '3607')
|
||||||
# Time to maintaing "info state" items before removing it, in seconds
|
# Time to maintaing "info state" items before removing it, in seconds
|
||||||
KEEP_INFO_TIME = Config.section(GLOBAL_SECTION).value('keepInfoTime', '14401') # Defaults to 2 days 172800?? better 4 hours xd
|
KEEP_INFO_TIME = Config.section(GLOBAL_SECTION).value('keepInfoTime', '14401') # Defaults to 2 days 172800?? better 4 hours xd
|
||||||
# Max number of services to be "preparing" at same time
|
# Max number of services to be "preparing" at same time
|
||||||
MAX_PREPARING_SERVICES = Config.section(GLOBAL_SECTION).value('maxPreparingServices', '15') # Defaults to 15 services at once (per service provider)
|
MAX_PREPARING_SERVICES = Config.section(GLOBAL_SECTION).value('maxPreparingServices', '15') # Defaults to 15 services at once (per service provider)
|
||||||
# Max number of service to be at "removal" state at same time
|
# Max number of service to be at "removal" state at same time
|
||||||
MAX_REMOVING_SERVICES = Config.section(GLOBAL_SECTION).value('maxRemovingServices', '15') # Defaults to 15 services at once (per service provider)
|
MAX_REMOVING_SERVICES = Config.section(GLOBAL_SECTION).value('maxRemovingServices', '15') # Defaults to 15 services at once (per service provider)
|
||||||
# If we ignore limits (max....)
|
# If we ignore limits (max....)
|
||||||
IGNORE_LIMITS = Config.section(GLOBAL_SECTION).value('ignoreLimits', '0')
|
IGNORE_LIMITS = Config.section(GLOBAL_SECTION).value('ignoreLimits', '0')
|
||||||
# Number of services to initiate removal per run of CacheCleaner
|
# Number of services to initiate removal per run of CacheCleaner
|
||||||
USER_SERVICE_CLEAN_NUMBER = Config.section(GLOBAL_SECTION).value('userServiceCleanNumber', '3') # Defaults to 3 per wun
|
USER_SERVICE_CLEAN_NUMBER = Config.section(GLOBAL_SECTION).value('userServiceCleanNumber', '3') # Defaults to 3 per wun
|
||||||
# Removal Check time for cache, publications and deployed services
|
# Removal Check time for cache, publications and deployed services
|
||||||
REMOVAL_CHECK = Config.section(GLOBAL_SECTION).value('removalCheck', '31') # Defaults to 30 seconds
|
REMOVAL_CHECK = Config.section(GLOBAL_SECTION).value('removalCheck', '31') # Defaults to 30 seconds
|
||||||
# Login URL
|
# Login URL
|
||||||
LOGIN_URL = Config.section(GLOBAL_SECTION).value('loginUrl', '/login') # Defaults to /login
|
LOGIN_URL = Config.section(GLOBAL_SECTION).value('loginUrl', '/login') # Defaults to /login
|
||||||
# Session duration
|
# Session duration
|
||||||
USER_SESSION_LENGTH = Config.section(SECURITY_SECTION).value('userSessionLength', '14400') # Defaults to 4 hours
|
USER_SESSION_LENGTH = Config.section(SECURITY_SECTION).value('userSessionLength', '14400') # Defaults to 4 hours
|
||||||
# Superuser (do not need to be at database!!!)
|
# Superuser (do not need to be at database!!!)
|
||||||
SUPER_USER_LOGIN = Config.section(SECURITY_SECTION).value('superUser', 'root') # Defaults to 4 hours
|
SUPER_USER_LOGIN = Config.section(SECURITY_SECTION).value('superUser', 'root') # Defaults to 4 hours
|
||||||
# Superuser password (do not need to be at database!!!)
|
# Superuser password (do not need to be at database!!!)
|
||||||
SUPER_USER_PASS = Config.section(SECURITY_SECTION).valueCrypt('rootPass', 'udsmam0')
|
SUPER_USER_PASS = Config.section(SECURITY_SECTION).valueCrypt('rootPass', 'udsmam0')
|
||||||
# Idle time before closing session on admin
|
# Idle time before closing session on admin
|
||||||
SUPER_USER_ALLOW_WEBACCESS = Config.section(SECURITY_SECTION).value('allowRootWebAccess', '1')
|
SUPER_USER_ALLOW_WEBACCESS = Config.section(SECURITY_SECTION).value('allowRootWebAccess', '1')
|
||||||
# Time an admi session can be idle before being "logged out"
|
# Time an admi session can be idle before being "logged out"
|
||||||
ADMIN_IDLE_TIME = Config.section(SECURITY_SECTION).value('adminIdleTime', '14400') # Defaults to 4 hous
|
ADMIN_IDLE_TIME = Config.section(SECURITY_SECTION).value('adminIdleTime', '14400') # Defaults to 4 hous
|
||||||
# Time betwen checks of unused services by os managers
|
# Time betwen checks of unused services by os managers
|
||||||
# Unused services will be invoked for every machine assigned but not in use AND that has been assigned at least this time
|
# Unused services will be invoked for every machine assigned but not in use AND that has been assigned at least this time
|
||||||
# (only if os manager asks for this characteristic)
|
# (only if os manager asks for this characteristic)
|
||||||
CHECK_UNUSED_TIME = Config.section(GLOBAL_SECTION).value('checkUnusedTime', '631') # Defaults to 10 minutes
|
CHECK_UNUSED_TIME = Config.section(GLOBAL_SECTION).value('checkUnusedTime', '631') # Defaults to 10 minutes
|
||||||
# Default CSS Used
|
# Default CSS Used
|
||||||
CSS = Config.section(GLOBAL_SECTION).value('css', settings.STATIC_URL + 'css/uds.css')
|
CSS = Config.section(GLOBAL_SECTION).value('css', settings.STATIC_URL + 'css/uds.css')
|
||||||
# Max logins before blocking an account
|
# Max logins before blocking an account
|
||||||
@ -239,12 +239,12 @@ class GlobalConfig(object):
|
|||||||
STATS_DURATION = Config.section(GLOBAL_SECTION).value('statsDuration', '365')
|
STATS_DURATION = Config.section(GLOBAL_SECTION).value('statsDuration', '365')
|
||||||
# If disallow login using /login url, and must go to an authenticator
|
# If disallow login using /login url, and must go to an authenticator
|
||||||
DISALLOW_GLOBAL_LOGIN = Config.section(GLOBAL_SECTION).value('disallowGlobalLogin', '0')
|
DISALLOW_GLOBAL_LOGIN = Config.section(GLOBAL_SECTION).value('disallowGlobalLogin', '0')
|
||||||
|
|
||||||
# Allowed "trusted sources" for request
|
# Allowed "trusted sources" for request
|
||||||
TRUSTED_SOURCES = Config.section(SECURITY_SECTION).value('Trusted Hosts', '*')
|
TRUSTED_SOURCES = Config.section(SECURITY_SECTION).value('Trusted Hosts', '*')
|
||||||
|
|
||||||
# Clusters related vars
|
# Clusters related vars
|
||||||
|
|
||||||
# Maximum desired CPU Load. If cpu is over this value, a migration of a service is "desirable"
|
# Maximum desired CPU Load. If cpu is over this value, a migration of a service is "desirable"
|
||||||
CLUSTER_MIGRATE_CPULOAD = Config.section(CLUSTER_SECTION).value('Migration CPU Load', '80')
|
CLUSTER_MIGRATE_CPULOAD = Config.section(CLUSTER_SECTION).value('Migration CPU Load', '80')
|
||||||
# Maximum CPU Load for a node to be elegible for destination of a migration
|
# Maximum CPU Load for a node to be elegible for destination of a migration
|
||||||
@ -254,17 +254,17 @@ class GlobalConfig(object):
|
|||||||
CLUSTER_MIGRATE_MEMORYLOAD = Config.section(CLUSTER_SECTION).value('Migration Free Memory', '20')
|
CLUSTER_MIGRATE_MEMORYLOAD = Config.section(CLUSTER_SECTION).value('Migration Free Memory', '20')
|
||||||
# Minimum Free memory for a node to be elegible for a destination of a migration
|
# Minimum Free memory for a node to be elegible for a destination of a migration
|
||||||
CLUSTER_ELEGIBLE_MEMORYLOAD = Config.section(CLUSTER_SECTION).value('Migration Free Memory', '40')
|
CLUSTER_ELEGIBLE_MEMORYLOAD = Config.section(CLUSTER_SECTION).value('Migration Free Memory', '40')
|
||||||
|
|
||||||
# Gui vars
|
# Gui vars
|
||||||
UDS_THEME = Config.section(GLOBAL_SECTION).value('UDS Theme', 'html5')
|
UDS_THEME = Config.section(GLOBAL_SECTION).value('UDS Theme', 'html5')
|
||||||
|
|
||||||
initDone = False
|
initDone = False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def initialize():
|
def initialize():
|
||||||
try:
|
try:
|
||||||
if GlobalConfig.initDone is False:
|
if GlobalConfig.initDone is False:
|
||||||
# All configurations are upper case
|
# All configurations are upper case
|
||||||
# Tries to initialize database data for global config so it is stored asap and get cached for use
|
# Tries to initialize database data for global config so it is stored asap and get cached for use
|
||||||
for v in GlobalConfig.__dict__.itervalues():
|
for v in GlobalConfig.__dict__.itervalues():
|
||||||
if type(v) is Config._Value:
|
if type(v) is Config._Value:
|
||||||
@ -272,10 +272,11 @@ class GlobalConfig(object):
|
|||||||
GlobalConfig.initDone = True
|
GlobalConfig.initDone = True
|
||||||
except:
|
except:
|
||||||
logger.debug('Config table do not exists!!!, maybe we are installing? :-)')
|
logger.debug('Config table do not exists!!!, maybe we are installing? :-)')
|
||||||
|
|
||||||
|
|
||||||
# Context processor
|
# Context processor
|
||||||
def context_processor(request):
|
def context_processor(request):
|
||||||
return { 'css_path' : GlobalConfig.CSS.get() }
|
return {'css_path': GlobalConfig.CSS.get()}
|
||||||
|
|
||||||
# Initialization of global configurations
|
# Initialization of global configurations
|
||||||
GlobalConfig.initialize()
|
GlobalConfig.initialize()
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -39,17 +39,18 @@ from uds.web import errors
|
|||||||
from time import sleep
|
from time import sleep
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
|
|
||||||
# Have to test these decorators before using them
|
# Have to test these decorators before using them
|
||||||
def retryOnException(retries=3, delay = 0):
|
def retryOnException(retries=3, delay=0):
|
||||||
'''
|
'''
|
||||||
Decorator to retry
|
Decorator to retry
|
||||||
'''
|
'''
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def _wrapped_func(*args, **kwargs):
|
def _wrapped_func(*args, **kwargs):
|
||||||
while retries > 0:
|
while retries > 0:
|
||||||
retries -= 1
|
retries -= 1
|
||||||
try:
|
try:
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
except Exception:
|
except Exception:
|
||||||
if retries == 0:
|
if retries == 0:
|
||||||
@ -62,10 +63,10 @@ def retryOnException(retries=3, delay = 0):
|
|||||||
|
|
||||||
# Decorator that protects pages that needs at least a browser version
|
# Decorator that protects pages that needs at least a browser version
|
||||||
# Default is to deny IE < 9
|
# Default is to deny IE < 9
|
||||||
def denyBrowsers(browsers=['ie<9'], errorResponse=lambda request:errors.errorView(request,errors.BROWSER_NOT_SUPPORTED)):
|
def denyBrowsers(browsers=['ie<9'], errorResponse=lambda request: errors.errorView(request, errors.BROWSER_NOT_SUPPORTED)):
|
||||||
'''
|
'''
|
||||||
Decorator to set protection to access page
|
Decorator to set protection to access page
|
||||||
Look for samples at uds.core.web.views
|
Look for samples at uds.core.web.views
|
||||||
'''
|
'''
|
||||||
def wrap(view_func):
|
def wrap(view_func):
|
||||||
@wraps(view_func)
|
@wraps(view_func)
|
||||||
@ -76,7 +77,7 @@ def denyBrowsers(browsers=['ie<9'], errorResponse=lambda request:errors.errorVie
|
|||||||
for b in browsers:
|
for b in browsers:
|
||||||
if checkBrowser(request.META['HTTP_USER_AGENT'], b):
|
if checkBrowser(request.META['HTTP_USER_AGENT'], b):
|
||||||
return errorResponse(request)
|
return errorResponse(request)
|
||||||
|
|
||||||
return view_func(request, *args, **kwargs)
|
return view_func(request, *args, **kwargs)
|
||||||
return _wrapped_view
|
return _wrapped_view
|
||||||
return wrap
|
return wrap
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -42,17 +42,18 @@ Android = 'Android'
|
|||||||
iPad = 'iPad'
|
iPad = 'iPad'
|
||||||
iPhone = 'iPhone'
|
iPhone = 'iPhone'
|
||||||
|
|
||||||
knownOss = [ WindowsPhone, Android, Linux, Windows, Macintosh, iPad, iPhone ] # Android is linux also, so it is cheched on first place
|
knownOss = [WindowsPhone, Android, Linux, Windows, Macintosh, iPad, iPhone] # Android is linux also, so it is cheched on first place
|
||||||
|
|
||||||
allOss = list(knownOss)
|
allOss = list(knownOss)
|
||||||
desktopOss = [Linux, Windows, Macintosh]
|
desktopOss = [Linux, Windows, Macintosh]
|
||||||
mobilesODD = list(set(allOss)-set(desktopOss))
|
mobilesODD = list(set(allOss) - set(desktopOss))
|
||||||
|
|
||||||
|
|
||||||
def getOsFromUA(ua):
|
def getOsFromUA(ua):
|
||||||
'''
|
'''
|
||||||
Basic OS Client detector (very basic indeed :-))
|
Basic OS Client detector (very basic indeed :-))
|
||||||
'''
|
'''
|
||||||
res = {'OS' : 'Unknown', 'Version' : 'unused' }
|
res = {'OS': 'Unknown', 'Version': 'unused'}
|
||||||
for os in knownOss:
|
for os in knownOss:
|
||||||
try:
|
try:
|
||||||
ua.index(os)
|
ua.index(os)
|
||||||
@ -63,4 +64,3 @@ def getOsFromUA(ua):
|
|||||||
logger.debug('User-Agent: {0}'.format(ua))
|
logger.debug('User-Agent: {0}'.format(ua))
|
||||||
logger.debug('Detected OS: {0}'.format(res))
|
logger.debug('Detected OS: {0}'.format(res))
|
||||||
return res
|
return res
|
||||||
|
|
@ -4,36 +4,37 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.utils.translation import ugettext_noop as _, ugettext
|
from django.utils.translation import ugettext_noop as _, ugettext
|
||||||
|
|
||||||
|
|
||||||
# States for different objects. Not all objects supports all States
|
# States for different objects. Not all objects supports all States
|
||||||
class State(object):
|
class State(object):
|
||||||
'''
|
'''
|
||||||
@ -42,32 +43,45 @@ class State(object):
|
|||||||
'''
|
'''
|
||||||
ACTIVE = 'A'
|
ACTIVE = 'A'
|
||||||
BLOCKED = 'B'
|
BLOCKED = 'B'
|
||||||
CANCELED = 'C'
|
CANCELED = 'C'
|
||||||
ERROR = 'E'
|
ERROR = 'E'
|
||||||
FINISHED = 'F'
|
FINISHED = 'F'
|
||||||
BALANCING = 'H'
|
BALANCING = 'H'
|
||||||
INACTIVE = 'I'
|
INACTIVE = 'I'
|
||||||
CANCELING = 'K'
|
CANCELING = 'K'
|
||||||
LAUNCHING = 'L'
|
LAUNCHING = 'L'
|
||||||
REMOVING = 'M'
|
REMOVING = 'M'
|
||||||
PREPARING = 'P'
|
PREPARING = 'P'
|
||||||
REMOVABLE = 'R'
|
REMOVABLE = 'R'
|
||||||
REMOVED = 'S'
|
REMOVED = 'S'
|
||||||
USABLE = 'U'
|
USABLE = 'U'
|
||||||
RUNNING = 'W'
|
RUNNING = 'W'
|
||||||
FOR_EXECUTE = 'X'
|
FOR_EXECUTE = 'X'
|
||||||
|
|
||||||
string = { ACTIVE: _('Active'), INACTIVE: _('Inactive'), BLOCKED: _('Blocked'), LAUNCHING: _('Waiting publication'),
|
string = {
|
||||||
PREPARING: _('In preparation'), USABLE: _('Valid'),
|
ACTIVE: _('Active'),
|
||||||
REMOVABLE: _('Waiting for removal'), REMOVING: _('Removing'), REMOVED: _('Removed'), CANCELED: _('Canceled'),
|
INACTIVE: _('Inactive'),
|
||||||
CANCELING: _('Canceling'), ERROR: _('Error'), RUNNING: _('Running'), FINISHED: _('Finished'), FOR_EXECUTE: _('Waiting execution'),
|
BLOCKED: _('Blocked'),
|
||||||
BALANCING: _('Balancing') }
|
LAUNCHING: _('Waiting publication'),
|
||||||
|
PREPARING: _('In preparation'),
|
||||||
|
USABLE: _('Valid'),
|
||||||
|
REMOVABLE: _('Waiting for removal'),
|
||||||
|
REMOVING: _('Removing'),
|
||||||
|
REMOVED: _('Removed'),
|
||||||
|
CANCELED: _('Canceled'),
|
||||||
|
CANCELING: _('Canceling'),
|
||||||
|
ERROR: _('Error'),
|
||||||
|
RUNNING: _('Running'),
|
||||||
|
FINISHED: _('Finished'),
|
||||||
|
FOR_EXECUTE: _('Waiting execution'),
|
||||||
|
BALANCING: _('Balancing')
|
||||||
|
}
|
||||||
|
|
||||||
# States that are merely for "information" to the user. They don't contain any usable instance
|
# States that are merely for "information" to the user. They don't contain any usable instance
|
||||||
INFO_STATES = [REMOVED, CANCELED, ERROR]
|
INFO_STATES = [REMOVED, CANCELED, ERROR]
|
||||||
|
|
||||||
# States that indicates that the service is "Valid" for a user
|
# States that indicates that the service is "Valid" for a user
|
||||||
VALID_STATES = [USABLE,PREPARING]
|
VALID_STATES = [USABLE, PREPARING]
|
||||||
|
|
||||||
# Publication States
|
# Publication States
|
||||||
PUBLISH_STATES = [LAUNCHING, PREPARING]
|
PUBLISH_STATES = [LAUNCHING, PREPARING]
|
||||||
@ -79,31 +93,31 @@ class State(object):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def isInactive(state):
|
def isInactive(state):
|
||||||
return state == State.INACTIVE
|
return state == State.INACTIVE
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isBlocked(state):
|
def isBlocked(state):
|
||||||
return state == State.BLOCKED
|
return state == State.BLOCKED
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isPreparing(state):
|
def isPreparing(state):
|
||||||
return state == State.PREPARING
|
return state == State.PREPARING
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isUsable(state):
|
def isUsable(state):
|
||||||
return state == State.USABLE
|
return state == State.USABLE
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isRemovable(state):
|
def isRemovable(state):
|
||||||
return state == State.REMOVABLE
|
return state == State.REMOVABLE
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isRemoving(state):
|
def isRemoving(state):
|
||||||
return state == State.REMOVING
|
return state == State.REMOVING
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isRemoved(state):
|
def isRemoved(state):
|
||||||
return state == State.REMOVED
|
return state == State.REMOVED
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isCanceling(state):
|
def isCanceling(state):
|
||||||
return state == State.CANCELING
|
return state == State.CANCELING
|
||||||
@ -115,7 +129,7 @@ class State(object):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def isErrored(state):
|
def isErrored(state):
|
||||||
return state == State.ERROR
|
return state == State.ERROR
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isFinished(state):
|
def isFinished(state):
|
||||||
return state == State.FINISHED
|
return state == State.FINISHED
|
||||||
@ -123,18 +137,18 @@ class State(object):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def isRuning(state):
|
def isRuning(state):
|
||||||
return state == State.RUNNING
|
return state == State.RUNNING
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isForExecute(state):
|
def isForExecute(state):
|
||||||
return state == State.FOR_EXECUTE
|
return state == State.FOR_EXECUTE
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def toString(state):
|
def toString(state):
|
||||||
try:
|
try:
|
||||||
return State.string[state]
|
return State.string[state]
|
||||||
except Exception:
|
except Exception:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def dictionary():
|
def dictionary():
|
||||||
'''
|
'''
|
||||||
@ -144,4 +158,3 @@ class State(object):
|
|||||||
for k, v in State.string.iteritems():
|
for k, v in State.string.iteritems():
|
||||||
res[k] = ugettext(v)
|
res[k] = ugettext(v)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@ -4,76 +4,78 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
||||||
class StateQueue(object):
|
class StateQueue(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
res = '<StateQueue Current: %s, Queue: (%s)>' % (self._current , ','.join( state for state in self._queue ))
|
res = '<StateQueue Current: %s, Queue: (%s)>' % (self._current, ','.join(state for state in self._queue))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def clearQueue(self):
|
def clearQueue(self):
|
||||||
self._queue = []
|
self._queue = []
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
self._queue = []
|
self._queue = []
|
||||||
self._current = None
|
self._current = None
|
||||||
|
|
||||||
def getCurrent(self):
|
def getCurrent(self):
|
||||||
return self._current
|
return self._current
|
||||||
|
|
||||||
def setCurrent(self, newState):
|
def setCurrent(self, newState):
|
||||||
self._current = newState
|
self._current = newState
|
||||||
return self._current
|
return self._current
|
||||||
|
|
||||||
def contains(self, state):
|
def contains(self, state):
|
||||||
#if self._queue.co
|
# if self._queue.co
|
||||||
for s in self._queue:
|
for s in self._queue:
|
||||||
if s == state:
|
if s == state:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def push_back(self, state):
|
def push_back(self, state):
|
||||||
self._queue.append(state)
|
self._queue.append(state)
|
||||||
|
|
||||||
def push_front(self, state):
|
def push_front(self, state):
|
||||||
self._queue.insert(0, state)
|
self._queue.insert(0, state)
|
||||||
|
|
||||||
def pop_front(self):
|
def pop_front(self):
|
||||||
if len(self._queue) > 0:
|
if len(self._queue) > 0:
|
||||||
return self._queue.pop(0)
|
return self._queue.pop(0)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def remove(self, state):
|
def remove(self, state):
|
||||||
try:
|
try:
|
||||||
self._queue.remove(state)
|
self._queue.remove(state)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass # If state not in queue, nothing happens
|
pass # If state not in queue, nothing happens
|
||||||
|
@ -4,32 +4,33 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from uds.models import Storage as dbStorage
|
from uds.models import Storage as dbStorage
|
||||||
@ -39,39 +40,40 @@ import cPickle
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Storage(object):
|
class Storage(object):
|
||||||
CODEC = 'base64' # Can be zip, hez, bzip, base64, uuencoded
|
CODEC = 'base64' # Can be zip, hez, bzip, base64, uuencoded
|
||||||
|
|
||||||
def __init__(self, owner):
|
def __init__(self, owner):
|
||||||
self._owner = owner
|
self._owner = owner
|
||||||
|
|
||||||
def __getKey(self, key):
|
def __getKey(self, key):
|
||||||
h = hashlib.md5()
|
h = hashlib.md5()
|
||||||
h.update(self._owner)
|
h.update(self._owner)
|
||||||
h.update(str(key))
|
h.update(str(key))
|
||||||
return h.hexdigest()
|
return h.hexdigest()
|
||||||
|
|
||||||
def saveData(self, skey, data, attr1 = None):
|
def saveData(self, skey, data, attr1=None):
|
||||||
key = self.__getKey(skey)
|
key = self.__getKey(skey)
|
||||||
data = data.encode(Storage.CODEC)
|
data = data.encode(Storage.CODEC)
|
||||||
attr1 = '' if attr1 == None else attr1
|
attr1 = '' if attr1 == None else attr1
|
||||||
try:
|
try:
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
dbStorage.objects.create(owner = self._owner, key = key, data = data, attr1 = attr1 )
|
dbStorage.objects.create(owner=self._owner, key=key, data=data, attr1=attr1)
|
||||||
except Exception:
|
except Exception:
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
dbStorage.objects.filter(key=key).update(owner = self._owner, data = data, attr1 = attr1)
|
dbStorage.objects.filter(key=key).update(owner=self._owner, data=data, attr1=attr1)
|
||||||
logger.debug('Key saved')
|
logger.debug('Key saved')
|
||||||
|
|
||||||
def put(self, skey, data):
|
def put(self, skey, data):
|
||||||
return self.saveData(skey, data)
|
return self.saveData(skey, data)
|
||||||
|
|
||||||
def putPickle(self, skey, data):
|
def putPickle(self, skey, data):
|
||||||
return self.saveData(skey, cPickle.dumps(data))
|
return self.saveData(skey, cPickle.dumps(data))
|
||||||
|
|
||||||
def updateData(self, skey, data, attr1 = None):
|
def updateData(self, skey, data, attr1=None):
|
||||||
self.saveData(skey, data, attr1)
|
self.saveData(skey, data, attr1)
|
||||||
|
|
||||||
def readData(self, skey):
|
def readData(self, skey):
|
||||||
try:
|
try:
|
||||||
key = self.__getKey(skey)
|
key = self.__getKey(skey)
|
||||||
@ -81,26 +83,26 @@ class Storage(object):
|
|||||||
except dbStorage.DoesNotExist:
|
except dbStorage.DoesNotExist:
|
||||||
logger.debug('key not found')
|
logger.debug('key not found')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get(self, skey):
|
def get(self, skey):
|
||||||
return self.readData(skey)
|
return self.readData(skey)
|
||||||
|
|
||||||
def getPickle(self, skey):
|
def getPickle(self, skey):
|
||||||
return cPickle.loads(self.readData(skey))
|
return cPickle.loads(self.readData(skey))
|
||||||
|
|
||||||
def remove(self, skey):
|
def remove(self, skey):
|
||||||
try:
|
try:
|
||||||
key = self.__getKey(skey)
|
key = self.__getKey(skey)
|
||||||
dbStorage.objects.filter(key=key).delete()
|
dbStorage.objects.filter(key=key).delete()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def lock(self):
|
def lock(self):
|
||||||
'''
|
'''
|
||||||
Use with care. If locked, it must be unlocked before returning
|
Use with care. If locked, it must be unlocked before returning
|
||||||
'''
|
'''
|
||||||
dbStorage.objects.lock()
|
dbStorage.objects.lock()
|
||||||
|
|
||||||
def unlock(self):
|
def unlock(self):
|
||||||
'''
|
'''
|
||||||
Must be used to unlock table
|
Must be used to unlock table
|
||||||
@ -108,7 +110,7 @@ class Storage(object):
|
|||||||
dbStorage.objects.unlock()
|
dbStorage.objects.unlock()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def delete(owner = None):
|
def delete(owner=None):
|
||||||
logger.info("Deleting storage items")
|
logger.info("Deleting storage items")
|
||||||
if owner == None:
|
if owner == None:
|
||||||
objects = dbStorage.objects.all()
|
objects = dbStorage.objects.all()
|
||||||
@ -118,6 +120,6 @@ class Storage(object):
|
|||||||
|
|
||||||
def locateByAttr1(self, attr1):
|
def locateByAttr1(self, attr1):
|
||||||
res = []
|
res = []
|
||||||
for v in dbStorage.objects.filter( attr1 = attr1 ):
|
for v in dbStorage.objects.filter(attr1=attr1):
|
||||||
res.append( v.data.decode(Storage.CODEC) )
|
res.append(v.data.decode(Storage.CODEC))
|
||||||
return res
|
return res
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2013 Virtual Cable S.L.
|
# Copyright (c) 2013 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
@ -36,7 +36,8 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEFAULT_QUEUE_SIZE=32
|
DEFAULT_QUEUE_SIZE = 32
|
||||||
|
|
||||||
|
|
||||||
class Worker(Thread):
|
class Worker(Thread):
|
||||||
def __init__(self, tasks):
|
def __init__(self, tasks):
|
||||||
@ -44,24 +45,25 @@ class Worker(Thread):
|
|||||||
self._tasks = tasks
|
self._tasks = tasks
|
||||||
self._stop = False
|
self._stop = False
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
def notifyStop(self):
|
def notifyStop(self):
|
||||||
self._stop = True
|
self._stop = True
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while self._stop is False:
|
while self._stop is False:
|
||||||
try:
|
try:
|
||||||
func, args, kargs = self._tasks.get(block=True, timeout=1)
|
func, args, kargs = self._tasks.get(block=True, timeout=1)
|
||||||
except Queue.Empty:
|
except Queue.Empty:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
func(*args, **kargs)
|
func(*args, **kargs)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception('ThreadPool Worker')
|
logger.exception('ThreadPool Worker')
|
||||||
|
|
||||||
self._tasks.task_done()
|
self._tasks.task_done()
|
||||||
|
|
||||||
|
|
||||||
class ThreadPool:
|
class ThreadPool:
|
||||||
def __init__(self, num_threads, queueSize=DEFAULT_QUEUE_SIZE):
|
def __init__(self, num_threads, queueSize=DEFAULT_QUEUE_SIZE):
|
||||||
self._tasks = Queue.Queue(queueSize)
|
self._tasks = Queue.Queue(queueSize)
|
||||||
@ -73,7 +75,7 @@ class ThreadPool:
|
|||||||
Add a task to the queue
|
Add a task to the queue
|
||||||
'''
|
'''
|
||||||
if len(self._threads) == 0:
|
if len(self._threads) == 0:
|
||||||
for _ in range(self._numThreads):
|
for _ in range(self._numThreads):
|
||||||
self._threads.append(Worker(self._tasks))
|
self._threads.append(Worker(self._tasks))
|
||||||
|
|
||||||
self._tasks.put((func, args, kargs))
|
self._tasks.put((func, args, kargs))
|
||||||
@ -83,14 +85,14 @@ class ThreadPool:
|
|||||||
Wait for completion of all the tasks in the queue
|
Wait for completion of all the tasks in the queue
|
||||||
'''
|
'''
|
||||||
self._tasks.join()
|
self._tasks.join()
|
||||||
|
|
||||||
# Now we will close all running tasks
|
# Now we will close all running tasks
|
||||||
# In case new tasks are inserted after using this, new threads will be created
|
# In case new tasks are inserted after using this, new threads will be created
|
||||||
# to handle tasks
|
# to handle tasks
|
||||||
for n in self._threads:
|
for n in self._threads:
|
||||||
n.notifyStop()
|
n.notifyStop()
|
||||||
|
|
||||||
for n in self._threads:
|
for n in self._threads:
|
||||||
n.join()
|
n.join()
|
||||||
|
|
||||||
self._threads = []
|
self._threads = []
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -40,42 +40,43 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
MAX_SEQ = 1000000000000000
|
MAX_SEQ = 1000000000000000
|
||||||
|
|
||||||
|
|
||||||
class UniqueIDGenerator(object):
|
class UniqueIDGenerator(object):
|
||||||
|
|
||||||
def __init__(self, typeName, owner, baseName = 'uds'):
|
def __init__(self, typeName, owner, baseName='uds'):
|
||||||
self._owner = owner + typeName
|
self._owner = owner + typeName
|
||||||
self._baseName = baseName
|
self._baseName = baseName
|
||||||
|
|
||||||
def setBaseName(self, newBaseName):
|
def setBaseName(self, newBaseName):
|
||||||
self._baseName = newBaseName
|
self._baseName = newBaseName
|
||||||
|
|
||||||
def __filter(self, rangeStart, rangeEnd=MAX_SEQ):
|
def __filter(self, rangeStart, rangeEnd=MAX_SEQ):
|
||||||
return dbUniqueId.objects.filter( basename = self._baseName, seq__gte=rangeStart, seq__lte=rangeEnd )
|
return dbUniqueId.objects.filter(basename=self._baseName, seq__gte=rangeStart, seq__lte=rangeEnd)
|
||||||
|
|
||||||
def get(self, rangeStart=0, rangeEnd=MAX_SEQ):
|
def get(self, rangeStart=0, rangeEnd=MAX_SEQ):
|
||||||
'''
|
'''
|
||||||
Tries to generate a new unique id in the range provided. This unique id
|
Tries to generate a new unique id in the range provided. This unique id
|
||||||
is global to "unique ids' database
|
is global to "unique ids' database
|
||||||
'''
|
'''
|
||||||
# First look for a name in the range defined
|
# First look for a name in the range defined
|
||||||
stamp = getSqlDatetime(True)
|
stamp = getSqlDatetime(True)
|
||||||
try:
|
try:
|
||||||
dbUniqueId.objects.lock()
|
dbUniqueId.objects.lock()
|
||||||
flt = self.__filter(rangeStart, rangeEnd)
|
flt = self.__filter(rangeStart, rangeEnd)
|
||||||
try:
|
try:
|
||||||
item = flt.filter(assigned=False).order_by('seq')[0]
|
item = flt.filter(assigned=False).order_by('seq')[0]
|
||||||
dbUniqueId.objects.filter(id=item.id).update( owner = self._owner, assigned = True, stamp = stamp )
|
dbUniqueId.objects.filter(id=item.id).update(owner=self._owner, assigned=True, stamp=stamp)
|
||||||
seq = item.seq
|
seq = item.seq
|
||||||
except Exception, e: # No free element found
|
except Exception: # No free element found
|
||||||
try:
|
try:
|
||||||
last = flt.filter(assigned = True)[0] # DB Returns correct order so the 0 item is the last
|
last = flt.filter(assigned=True)[0] # DB Returns correct order so the 0 item is the last
|
||||||
seq = last.seq + 1
|
seq = last.seq + 1
|
||||||
except Exception: # If there is no assigned at database
|
except Exception: # If there is no assigned at database
|
||||||
seq = rangeStart
|
seq = rangeStart
|
||||||
logger.debug('Found seq {0}'.format(seq))
|
logger.debug('Found seq {0}'.format(seq))
|
||||||
if seq > rangeEnd:
|
if seq > rangeEnd:
|
||||||
return -1 # No ids free in range
|
return -1 # No ids free in range
|
||||||
dbUniqueId.objects.create( owner = self._owner, basename = self._baseName, seq = seq, assigned = True, stamp = stamp)
|
dbUniqueId.objects.create(owner=self._owner, basename=self._baseName, seq=seq, assigned=True, stamp=stamp)
|
||||||
return seq
|
return seq
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception('Generating unique id sequence')
|
logger.exception('Generating unique id sequence')
|
||||||
@ -86,55 +87,51 @@ class UniqueIDGenerator(object):
|
|||||||
def transfer(self, seq, toUidGen):
|
def transfer(self, seq, toUidGen):
|
||||||
try:
|
try:
|
||||||
dbUniqueId.objects.lock()
|
dbUniqueId.objects.lock()
|
||||||
|
|
||||||
obj = dbUniqueId.objects.get( owner=self._owner, seq=seq)
|
obj = dbUniqueId.objects.get(owner=self._owner, seq=seq)
|
||||||
obj.owner = toUidGen._owner
|
obj.owner = toUidGen._owner
|
||||||
obj.basename = toUidGen._baseName
|
obj.basename = toUidGen._baseName
|
||||||
obj.stamp = getSqlDatetime(True)
|
obj.stamp = getSqlDatetime(True)
|
||||||
obj.save()
|
obj.save()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
logger.exception('EXCEPTION AT transfer')
|
logger.exception('EXCEPTION AT transfer')
|
||||||
return False
|
return False
|
||||||
finally:
|
finally:
|
||||||
dbUniqueId.objects.unlock()
|
dbUniqueId.objects.unlock()
|
||||||
|
|
||||||
|
|
||||||
def free(self, seq):
|
def free(self, seq):
|
||||||
try:
|
try:
|
||||||
logger.debug('Freeing seq {0} from {1} ({2})'.format(seq, self._owner, self._baseName))
|
logger.debug('Freeing seq {0} from {1} ({2})'.format(seq, self._owner, self._baseName))
|
||||||
dbUniqueId.objects.lock()
|
dbUniqueId.objects.lock()
|
||||||
flt = self.__filter(0).filter(owner = self._owner, seq=seq).update(owner='', assigned=False, stamp = getSqlDatetime(True))
|
flt = self.__filter(0).filter(owner=self._owner, seq=seq).update(owner='', assigned=False, stamp=getSqlDatetime(True))
|
||||||
if flt > 0:
|
if flt > 0:
|
||||||
self.__purge()
|
self.__purge()
|
||||||
finally:
|
finally:
|
||||||
dbUniqueId.objects.unlock()
|
dbUniqueId.objects.unlock()
|
||||||
|
|
||||||
|
|
||||||
def __purge(self):
|
def __purge(self):
|
||||||
try:
|
try:
|
||||||
last = self.__filter(0).filter(assigned=True)[0]
|
last = self.__filter(0).filter(assigned=True)[0]
|
||||||
seq = last.seq+1
|
seq = last.seq + 1
|
||||||
except:
|
except:
|
||||||
seq = 0
|
seq = 0
|
||||||
self.__filter(seq).delete() # Clean ups all unassigned after last assigned in this range
|
self.__filter(seq).delete() # Clean ups all unassigned after last assigned in this range
|
||||||
|
|
||||||
|
|
||||||
def release(self):
|
def release(self):
|
||||||
try:
|
try:
|
||||||
dbUniqueId.objects.lock()
|
dbUniqueId.objects.lock()
|
||||||
dbUniqueId.objects.filter(owner=self._owner).update(assigned=False, owner='', stamp = getSqlDatetime(True))
|
dbUniqueId.objects.filter(owner=self._owner).update(assigned=False, owner='', stamp=getSqlDatetime(True))
|
||||||
self.__purge()
|
self.__purge()
|
||||||
finally:
|
finally:
|
||||||
dbUniqueId.objects.unlock()
|
dbUniqueId.objects.unlock()
|
||||||
|
|
||||||
def releaseOlderThan(self, stamp):
|
def releaseOlderThan(self, stamp):
|
||||||
stamp = getSqlDatetime(True)
|
stamp = getSqlDatetime(True)
|
||||||
try:
|
try:
|
||||||
dbUniqueId.objects.lock()
|
dbUniqueId.objects.lock()
|
||||||
dbUniqueId.objects.filter(owner=self._owner, stamp__lt=stamp).update(assigned=False, owner='', stamp = stamp)
|
dbUniqueId.objects.filter(owner=self._owner, stamp__lt=stamp).update(assigned=False, owner='', stamp=stamp)
|
||||||
self.__purge()
|
self.__purge()
|
||||||
finally:
|
finally:
|
||||||
dbUniqueId.objects.unlock()
|
dbUniqueId.objects.unlock()
|
||||||
|
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -32,33 +32,34 @@
|
|||||||
'''
|
'''
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
||||||
from UniqueIDGenerator import UniqueIDGenerator
|
from UniqueIDGenerator import UniqueIDGenerator
|
||||||
import logging, re
|
import logging
|
||||||
|
import re
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class UniqueMacGenerator(UniqueIDGenerator):
|
class UniqueMacGenerator(UniqueIDGenerator):
|
||||||
|
|
||||||
def __init__(self, owner):
|
def __init__(self, owner):
|
||||||
super(UniqueMacGenerator, self).__init__('mac', owner, '\tmac')
|
super(UniqueMacGenerator, self).__init__('mac', owner, '\tmac')
|
||||||
|
|
||||||
def __toInt(self, mac):
|
def __toInt(self, mac):
|
||||||
return int(mac.replace(':', ''), 16)
|
return int(mac.replace(':', ''), 16)
|
||||||
|
|
||||||
def __toMac(self, seq):
|
def __toMac(self, seq):
|
||||||
return re.sub(r"(..)", r"\1:", "%0*X" % (12, seq))[:-1]
|
return re.sub(r"(..)", r"\1:", "%0*X" % (12, seq))[:-1]
|
||||||
|
|
||||||
def get(self, macRange):
|
def get(self, macRange):
|
||||||
firstMac, lastMac = macRange.split('-')
|
firstMac, lastMac = macRange.split('-')
|
||||||
firstMac = self.__toInt(firstMac)
|
firstMac = self.__toInt(firstMac)
|
||||||
lastMac = self.__toInt(lastMac)
|
lastMac = self.__toInt(lastMac)
|
||||||
return self.__toMac(super(UniqueMacGenerator, self).get(firstMac, lastMac))
|
return self.__toMac(super(UniqueMacGenerator, self).get(firstMac, lastMac))
|
||||||
|
|
||||||
def transfer(self, mac, toUMgen):
|
def transfer(self, mac, toUMgen):
|
||||||
super(UniqueMacGenerator, self).transfer( self.__toInt(mac), toUMgen )
|
super(UniqueMacGenerator, self).transfer(self.__toInt(mac), toUMgen)
|
||||||
|
|
||||||
def free(self, mac):
|
def free(self, mac):
|
||||||
super(UniqueMacGenerator, self).free( self.__toInt(mac) )
|
super(UniqueMacGenerator, self).free(self.__toInt(mac))
|
||||||
|
|
||||||
# Release is inherited, no mod needed
|
# Release is inherited, no mod needed
|
||||||
|
@ -4,58 +4,60 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from UniqueIDGenerator import UniqueIDGenerator
|
from UniqueIDGenerator import UniqueIDGenerator
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class UniqueNameGenerator(UniqueIDGenerator):
|
class UniqueNameGenerator(UniqueIDGenerator):
|
||||||
|
|
||||||
def __init__(self, owner):
|
def __init__(self, owner):
|
||||||
super(UniqueNameGenerator, self).__init__('name', owner, )
|
super(UniqueNameGenerator, self).__init__('name', owner,)
|
||||||
|
|
||||||
def __toName(self, seq, length):
|
def __toName(self, seq, length):
|
||||||
if seq == -1:
|
if seq == -1:
|
||||||
raise KeyError('No more names available. Please, increase service digits.')
|
raise KeyError('No more names available. Please, increase service digits.')
|
||||||
return "%s%0*d" % (self._baseName, length, seq)
|
return "%s%0*d" % (self._baseName, length, seq)
|
||||||
|
|
||||||
def get(self, baseName, length=5):
|
def get(self, baseName, length=5):
|
||||||
self.setBaseName(baseName)
|
self.setBaseName(baseName)
|
||||||
minVal = 0
|
minVal = 0
|
||||||
maxVal = 10**length - 1
|
maxVal = 10 ** length - 1
|
||||||
return self.__toName(super(UniqueNameGenerator, self).get(minVal, maxVal), length)
|
return self.__toName(super(UniqueNameGenerator, self).get(minVal, maxVal), length)
|
||||||
|
|
||||||
def transfer(self, baseName, name, toUNGen):
|
def transfer(self, baseName, name, toUNGen):
|
||||||
self.setBaseName(baseName)
|
self.setBaseName(baseName)
|
||||||
super(UniqueNameGenerator, self).transfer(int(name[len(self._baseName):]), toUNGen)
|
super(UniqueNameGenerator, self).transfer(int(name[len(self._baseName):]), toUNGen)
|
||||||
|
|
||||||
def free(self, baseName, name):
|
def free(self, baseName, name):
|
||||||
self.setBaseName(baseName)
|
self.setBaseName(baseName)
|
||||||
super(UniqueNameGenerator, self).free(int(name[len(self._baseName):]))
|
super(UniqueNameGenerator, self).free(int(name[len(self._baseName):]))
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -37,7 +37,8 @@ import socket
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
def testServer(host, port, timeOut = 4):
|
|
||||||
|
def testServer(host, port, timeOut=4):
|
||||||
try:
|
try:
|
||||||
logger.debug('Checking connection to {0}:{1} with {2} seconds timeout'.format(host, port, timeOut))
|
logger.debug('Checking connection to {0}:{1} with {2} seconds timeout'.format(host, port, timeOut))
|
||||||
sock = socket.create_connection((host, int(port)), timeOut)
|
sock = socket.create_connection((host, int(port)), timeOut)
|
||||||
@ -46,5 +47,3 @@ def testServer(host, port, timeOut = 4):
|
|||||||
logger.debug('Exception checking {0}:{1} with {2} timeout: {3}'.format(host, port, timeOut, e))
|
logger.debug('Exception checking {0}:{1} with {2} timeout: {3}'.format(host, port, timeOut, e))
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2014 Virtual Cable S.L.
|
# Copyright (c) 2014 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -42,14 +42,15 @@ def parseDate(dateToParse):
|
|||||||
import datetime
|
import datetime
|
||||||
from django.utils.translation import get_language
|
from django.utils.translation import get_language
|
||||||
from django.utils import formats
|
from django.utils import formats
|
||||||
|
|
||||||
if get_language() == 'fr':
|
if get_language() == 'fr':
|
||||||
date_format = '%d/%m/%Y'
|
date_format = '%d/%m/%Y'
|
||||||
else:
|
else:
|
||||||
date_format = formats.get_format('SHORT_DATE_FORMAT').replace('Y', '%Y').replace('m','%m').replace('d','%d')
|
date_format = formats.get_format('SHORT_DATE_FORMAT').replace('Y', '%Y').replace('m', '%m').replace('d', '%d')
|
||||||
|
|
||||||
return datetime.datetime.strptime(dateToParse, date_format).date()
|
return datetime.datetime.strptime(dateToParse, date_format).date()
|
||||||
|
|
||||||
|
|
||||||
def dateToLiteral(date):
|
def dateToLiteral(date):
|
||||||
from django.utils.translation import get_language
|
from django.utils.translation import get_language
|
||||||
from django.utils import formats
|
from django.utils import formats
|
||||||
@ -58,16 +59,17 @@ def dateToLiteral(date):
|
|||||||
if get_language() == 'fr':
|
if get_language() == 'fr':
|
||||||
date = date.strftime('%d/%m/%Y')
|
date = date.strftime('%d/%m/%Y')
|
||||||
else:
|
else:
|
||||||
date = formats.date_format(date, 'SHORT_DATE_FORMAT')
|
date = formats.date_format(date, 'SHORT_DATE_FORMAT')
|
||||||
|
|
||||||
return date
|
return date
|
||||||
|
|
||||||
|
|
||||||
def extractKey(dictionary, key, **kwargs):
|
def extractKey(dictionary, key, **kwargs):
|
||||||
|
|
||||||
format_ = kwargs.get('format', '{0}')
|
format_ = kwargs.get('format', '{0}')
|
||||||
default = kwargs.get('default', '')
|
default = kwargs.get('default', '')
|
||||||
|
|
||||||
if dictionary.has_key(key):
|
if key in dictionary:
|
||||||
value = format_.format(dictionary[key])
|
value = format_.format(dictionary[key])
|
||||||
del dictionary[key]
|
del dictionary[key]
|
||||||
else:
|
else:
|
||||||
@ -88,13 +90,14 @@ _chrome = re.compile('Chrome/([0-9]+)\.([0-9]+)')
|
|||||||
_webkit = re.compile('AppleWebKit/([0-9]+)\.([0-9]+)')
|
_webkit = re.compile('AppleWebKit/([0-9]+)\.([0-9]+)')
|
||||||
|
|
||||||
_browsers = {
|
_browsers = {
|
||||||
'ie' : [_trident, _msie],
|
'ie': [_trident, _msie],
|
||||||
'opera': [_opera],
|
'opera': [_opera],
|
||||||
'firefox': [_firefox],
|
'firefox': [_firefox],
|
||||||
'chrome': [_chrome],
|
'chrome': [_chrome],
|
||||||
'webkit': [_webkit],
|
'webkit': [_webkit],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def checkBrowser(user_agent, browser):
|
def checkBrowser(user_agent, browser):
|
||||||
'''
|
'''
|
||||||
Known browsers right now:
|
Known browsers right now:
|
||||||
@ -102,23 +105,22 @@ def checkBrowser(user_agent, browser):
|
|||||||
ie<[version]
|
ie<[version]
|
||||||
'''
|
'''
|
||||||
# Split brwosers we look for
|
# Split brwosers we look for
|
||||||
needs_browser = None
|
|
||||||
needs_version = 0
|
needs_version = 0
|
||||||
needs = ''
|
needs = ''
|
||||||
|
|
||||||
regexs = None
|
regexs = None
|
||||||
|
|
||||||
for b, res in _browsers.iteritems():
|
for b, res in _browsers.iteritems():
|
||||||
if browser.startswith(b):
|
if browser.startswith(b):
|
||||||
logger.debug('Found: {0}'.format(b))
|
logger.debug('Found: {0}'.format(b))
|
||||||
regexs = res
|
regexs = res
|
||||||
browser = browser[len(b):]
|
browser = browser[len(b):]
|
||||||
|
|
||||||
if regexs is None:
|
if regexs is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
browser += ' ' # So we ensure we have at least beowser 0
|
browser += ' ' # So we ensure we have at least beowser 0
|
||||||
|
|
||||||
if browser[0] == '<' or browser[0] == '>' or browser[0] == '=':
|
if browser[0] == '<' or browser[0] == '>' or browser[0] == '=':
|
||||||
needs = browser[0]
|
needs = browser[0]
|
||||||
needs_version = int(browser[1:])
|
needs_version = int(browser[1:])
|
||||||
@ -129,7 +131,7 @@ def checkBrowser(user_agent, browser):
|
|||||||
except:
|
except:
|
||||||
needs = ''
|
needs = ''
|
||||||
needs_version = 0
|
needs_version = 0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
matches = None
|
matches = None
|
||||||
for r in regexs:
|
for r in regexs:
|
||||||
@ -138,7 +140,7 @@ def checkBrowser(user_agent, browser):
|
|||||||
break
|
break
|
||||||
if matches is None:
|
if matches is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
version = int(matches.groups()[0])
|
version = int(matches.groups()[0])
|
||||||
if needs == '<':
|
if needs == '<':
|
||||||
return version < needs_version
|
return version < needs_version
|
||||||
@ -146,12 +148,12 @@ def checkBrowser(user_agent, browser):
|
|||||||
return version > needs_version
|
return version > needs_version
|
||||||
elif needs == '=':
|
elif needs == '=':
|
||||||
return version == needs_version
|
return version == needs_version
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# debug setting in context
|
# debug setting in context
|
||||||
def context(request):
|
def context(request):
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -4,39 +4,40 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
useLogger = logging.getLogger('useLog')
|
useLogger = logging.getLogger('useLog')
|
||||||
|
|
||||||
# Logging levels
|
# Logging levels
|
||||||
OTHER,DEBUG,INFO,WARN,ERROR,FATAL = (10000*(x+1) for x in xrange(6))
|
OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in xrange(6))
|
||||||
|
|
||||||
# Logging sources
|
# Logging sources
|
||||||
INTERNAL, ACTOR, TRANSPORT, OSMANAGER, UNKNOWN, WEB, ADMIN, SERVICE = ('internal', 'actor', 'transport', 'osmanager', 'unknown', 'web', 'admin', 'service')
|
INTERNAL, ACTOR, TRANSPORT, OSMANAGER, UNKNOWN, WEB, ADMIN, SERVICE = ('internal', 'actor', 'transport', 'osmanager', 'unknown', 'web', 'admin', 'service')
|
||||||
@ -54,7 +55,8 @@ __nameLevels = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Reverse dict of names
|
# Reverse dict of names
|
||||||
__valueLevels = dict((v,k) for k, v in __nameLevels.iteritems())
|
__valueLevels = dict((v, k) for k, v in __nameLevels.iteritems())
|
||||||
|
|
||||||
|
|
||||||
def logLevelFromStr(str_):
|
def logLevelFromStr(str_):
|
||||||
'''
|
'''
|
||||||
@ -62,31 +64,33 @@ def logLevelFromStr(str_):
|
|||||||
'''
|
'''
|
||||||
return __nameLevels.get(str_.upper(), OTHER)
|
return __nameLevels.get(str_.upper(), OTHER)
|
||||||
|
|
||||||
|
|
||||||
def logStrFromLevel(level):
|
def logStrFromLevel(level):
|
||||||
return __valueLevels.get(level, 'OTHER')
|
return __valueLevels.get(level, 'OTHER')
|
||||||
|
|
||||||
|
|
||||||
def useLog(type_, serviceUniqueId, serviceIp, username):
|
def useLog(type_, serviceUniqueId, serviceIp, username):
|
||||||
useLogger.info('|'.join([type_, serviceUniqueId, serviceIp, username]))
|
useLogger.info('|'.join([type_, serviceUniqueId, serviceIp, username]))
|
||||||
|
|
||||||
|
|
||||||
def doLog(wichObject, level, message, source = UNKNOWN, avoidDuplicates = True):
|
def doLog(wichObject, level, message, source=UNKNOWN, avoidDuplicates=True):
|
||||||
from uds.core.managers import logManager
|
from uds.core.managers import logManager
|
||||||
logManager().doLog(wichObject, level, message, source, avoidDuplicates)
|
logManager().doLog(wichObject, level, message, source, avoidDuplicates)
|
||||||
|
|
||||||
|
|
||||||
def getLogs(wichObject, limit = None):
|
def getLogs(wichObject, limit=None):
|
||||||
'''
|
'''
|
||||||
Get the logs associated with "wichObject", limiting to "limit" (default is GlobalConfig.MAX_LOGS_PER_ELEMENT)
|
Get the logs associated with "wichObject", limiting to "limit" (default is GlobalConfig.MAX_LOGS_PER_ELEMENT)
|
||||||
'''
|
'''
|
||||||
from uds.core.managers import logManager
|
from uds.core.managers import logManager
|
||||||
from uds.core.util.Config import GlobalConfig
|
from uds.core.util.Config import GlobalConfig
|
||||||
|
|
||||||
if limit is None:
|
if limit is None:
|
||||||
limit = GlobalConfig.MAX_LOGS_PER_ELEMENT.getInt()
|
limit = GlobalConfig.MAX_LOGS_PER_ELEMENT.getInt()
|
||||||
|
|
||||||
return logManager().getLogs(wichObject, limit)
|
return logManager().getLogs(wichObject, limit)
|
||||||
|
|
||||||
|
|
||||||
def clearLogs(wichObject):
|
def clearLogs(wichObject):
|
||||||
'''
|
'''
|
||||||
Clears the logs associated with the object using the logManager
|
Clears the logs associated with the object using the logManager
|
||||||
|
@ -4,43 +4,46 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import os.path, pkgutil
|
import os.path
|
||||||
import sys, imp
|
import pkgutil
|
||||||
|
import sys
|
||||||
|
import imp
|
||||||
import logging
|
import logging
|
||||||
import uds.dispatchers
|
import uds.dispatchers # @UnusedImport
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
patterns = []
|
patterns = []
|
||||||
|
|
||||||
|
|
||||||
def loadModulesUrls():
|
def loadModulesUrls():
|
||||||
logger.debug('Looking for dispatching modules')
|
logger.debug('Looking for dispatching modules')
|
||||||
global patterns
|
global patterns
|
||||||
@ -54,10 +57,9 @@ def loadModulesUrls():
|
|||||||
try:
|
try:
|
||||||
patterns += mod.urlpatterns
|
patterns += mod.urlpatterns
|
||||||
except:
|
except:
|
||||||
logger.info( 'Module {0} has no url patterns'.format(mod))
|
logger.info('Module {0} has no url patterns'.format(mod))
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logger.debug(e)
|
logger.debug(e)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return patterns
|
return patterns
|
||||||
|
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -44,6 +44,7 @@ re3Asterisk = re.compile('^([0-9]{1,3})\.\*\.?\*?\.?\*?$')
|
|||||||
reRange = re.compile('^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})-([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$')
|
reRange = re.compile('^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})-([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$')
|
||||||
reHost = re.compile('^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$')
|
reHost = re.compile('^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$')
|
||||||
|
|
||||||
|
|
||||||
def ipToLong(ip):
|
def ipToLong(ip):
|
||||||
'''
|
'''
|
||||||
convert decimal dotted quad string to long integer
|
convert decimal dotted quad string to long integer
|
||||||
@ -52,8 +53,9 @@ def ipToLong(ip):
|
|||||||
hexn = ''.join(["%02X" % long(i) for i in ip.split('.')])
|
hexn = ''.join(["%02X" % long(i) for i in ip.split('.')])
|
||||||
return long(hexn, 16)
|
return long(hexn, 16)
|
||||||
except:
|
except:
|
||||||
return 0 # Invalid values will map to "0.0.0.0" --> 0
|
return 0 # Invalid values will map to "0.0.0.0" --> 0
|
||||||
|
|
||||||
|
|
||||||
def longToIp(n):
|
def longToIp(n):
|
||||||
'''
|
'''
|
||||||
convert long int to dotted quad string
|
convert long int to dotted quad string
|
||||||
@ -62,19 +64,19 @@ def longToIp(n):
|
|||||||
d = 256 * 256 * 256
|
d = 256 * 256 * 256
|
||||||
q = []
|
q = []
|
||||||
while d > 0:
|
while d > 0:
|
||||||
m,n = divmod(n,d)
|
m, n = divmod(n, d)
|
||||||
q.append(str(m))
|
q.append(str(m))
|
||||||
d = d/256
|
d = d / 256
|
||||||
|
|
||||||
return '.'.join(q)
|
return '.'.join(q)
|
||||||
except:
|
except:
|
||||||
return '0.0.0.0' # Invalid values will map to "0.0.0.0"
|
return '0.0.0.0' # Invalid values will map to "0.0.0.0"
|
||||||
|
|
||||||
|
|
||||||
def networksFromString(strNets, allowMultipleNetworks = True):
|
def networksFromString(strNets, allowMultipleNetworks=True):
|
||||||
'''
|
'''
|
||||||
Parses the network from strings in this forms:
|
Parses the network from strings in this forms:
|
||||||
- A.* (or A.*.* or A.*.*.*)
|
- A.* (or A.*.* or A.*.*.*)
|
||||||
- A.B.* (or A.B.*.* )
|
- A.B.* (or A.B.*.* )
|
||||||
- A.B.C.* (i.e. 192.168.0.*)
|
- A.B.C.* (i.e. 192.168.0.*)
|
||||||
- A.B.C.D/N (i.e. 192.168.0.0/24)
|
- A.B.C.D/N (i.e. 192.168.0.0/24)
|
||||||
@ -84,28 +86,28 @@ def networksFromString(strNets, allowMultipleNetworks = True):
|
|||||||
If allowMultipleNetworks is True, it allows ',' and ';' separators (and, ofc, more than 1 network)
|
If allowMultipleNetworks is True, it allows ',' and ';' separators (and, ofc, more than 1 network)
|
||||||
Returns a list of networks tuples in the form [(start1, end1), (start2, end2) ...]
|
Returns a list of networks tuples in the form [(start1, end1), (start2, end2) ...]
|
||||||
'''
|
'''
|
||||||
|
|
||||||
inputString = strNets
|
inputString = strNets
|
||||||
|
|
||||||
def check(*args):
|
def check(*args):
|
||||||
for n in args:
|
for n in args:
|
||||||
if int(n) < 0 or int(n) > 255:
|
if int(n) < 0 or int(n) > 255:
|
||||||
raise Exception()
|
raise Exception()
|
||||||
|
|
||||||
def toNum(*args):
|
def toNum(*args):
|
||||||
start = 256*256*256
|
start = 256 * 256 * 256
|
||||||
val = 0
|
val = 0
|
||||||
for n in args:
|
for n in args:
|
||||||
val += start*int(n)
|
val += start * int(n)
|
||||||
start /= 256
|
start /= 256
|
||||||
return val
|
return val
|
||||||
|
|
||||||
def maskFromBits(nBits):
|
def maskFromBits(nBits):
|
||||||
v = 0
|
v = 0
|
||||||
for n in xrange(nBits):
|
for n in xrange(nBits):
|
||||||
v |= 1<<(31-n)
|
v |= 1 << (31 - n)
|
||||||
return v
|
return v
|
||||||
|
|
||||||
if allowMultipleNetworks is True:
|
if allowMultipleNetworks is True:
|
||||||
res = []
|
res = []
|
||||||
for strNet in re.split('[;,]', strNets):
|
for strNet in re.split('[;,]', strNets):
|
||||||
@ -114,11 +116,11 @@ def networksFromString(strNets, allowMultipleNetworks = True):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
strNets = strNets.replace(' ', '')
|
strNets = strNets.replace(' ', '')
|
||||||
|
|
||||||
if strNets == '*':
|
if strNets == '*':
|
||||||
return (0, 4294967295)
|
return (0, 4294967295)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Test patterns
|
# Test patterns
|
||||||
m = reCIDR.match(strNets)
|
m = reCIDR.match(strNets)
|
||||||
if m is not None:
|
if m is not None:
|
||||||
@ -129,16 +131,16 @@ def networksFromString(strNets, allowMultipleNetworks = True):
|
|||||||
val = toNum(*m.groups())
|
val = toNum(*m.groups())
|
||||||
bits = maskFromBits(bits)
|
bits = maskFromBits(bits)
|
||||||
noBits = ~bits & 0xffffffff
|
noBits = ~bits & 0xffffffff
|
||||||
return (val&bits, val|noBits)
|
return (val & bits, val | noBits)
|
||||||
|
|
||||||
m = reMask.match(strNets)
|
m = reMask.match(strNets)
|
||||||
if m is not None:
|
if m is not None:
|
||||||
check(*m.groups())
|
check(*m.groups())
|
||||||
val = toNum(*(m.groups()[0:4]))
|
val = toNum(*(m.groups()[0:4]))
|
||||||
bits = toNum(*(m.groups()[4:8]))
|
bits = toNum(*(m.groups()[4:8]))
|
||||||
noBits = ~bits & 0xffffffff
|
noBits = ~bits & 0xffffffff
|
||||||
return (val&bits, val|noBits)
|
return (val & bits, val | noBits)
|
||||||
|
|
||||||
m = reRange.match(strNets)
|
m = reRange.match(strNets)
|
||||||
if m is not None:
|
if m is not None:
|
||||||
check(*m.groups())
|
check(*m.groups())
|
||||||
@ -147,7 +149,7 @@ def networksFromString(strNets, allowMultipleNetworks = True):
|
|||||||
if val2 < val:
|
if val2 < val:
|
||||||
raise Exception()
|
raise Exception()
|
||||||
return (val, val2)
|
return (val, val2)
|
||||||
|
|
||||||
m = reHost.match(strNets)
|
m = reHost.match(strNets)
|
||||||
if m is not None:
|
if m is not None:
|
||||||
check(*m.groups())
|
check(*m.groups())
|
||||||
@ -155,26 +157,26 @@ def networksFromString(strNets, allowMultipleNetworks = True):
|
|||||||
return (val, val)
|
return (val, val)
|
||||||
|
|
||||||
for v in ((re1Asterisk, 3), (re2Asterisk, 2), (re3Asterisk, 1)):
|
for v in ((re1Asterisk, 3), (re2Asterisk, 2), (re3Asterisk, 1)):
|
||||||
m = v[0].match(strNets)
|
m = v[0].match(strNets)
|
||||||
if m is not None:
|
if m is not None:
|
||||||
check(*m.groups())
|
check(*m.groups())
|
||||||
val = toNum(*(m.groups()[0:v[1]+1]))
|
val = toNum(*(m.groups()[0:v[1] + 1]))
|
||||||
bits = maskFromBits(v[1]*8)
|
bits = maskFromBits(v[1] * 8)
|
||||||
noBits = ~bits & 0xffffffff
|
noBits = ~bits & 0xffffffff
|
||||||
return (val&bits, val|noBits)
|
return (val & bits, val | noBits)
|
||||||
|
|
||||||
# No pattern recognized, invalid network
|
# No pattern recognized, invalid network
|
||||||
raise Exception()
|
raise Exception()
|
||||||
except:
|
except:
|
||||||
raise ValueError(inputString)
|
raise ValueError(inputString)
|
||||||
|
|
||||||
|
|
||||||
def ipInNetwork(ip, network):
|
def ipInNetwork(ip, network):
|
||||||
if isinstance(ip,unicode) or isinstance(ip,str):
|
if isinstance(ip, unicode) or isinstance(ip, str):
|
||||||
ip = ipToLong(ip)
|
ip = ipToLong(ip)
|
||||||
if isinstance(network,unicode) or isinstance(network,str):
|
if isinstance(network, unicode) or isinstance(network, str):
|
||||||
network = networksFromString(network)
|
network = networksFromString(network)
|
||||||
|
|
||||||
for net in network:
|
for net in network:
|
||||||
if ip >= net[0] and ip <= net[1]:
|
if ip >= net[0] and ip <= net[1]:
|
||||||
return True
|
return True
|
||||||
|
@ -4,41 +4,43 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
_requests = {}
|
_requests = {}
|
||||||
|
|
||||||
|
|
||||||
def getRequest():
|
def getRequest():
|
||||||
return _requests[threading._get_ident()]
|
return _requests[threading._get_ident()]
|
||||||
|
|
||||||
|
|
||||||
class GlobalRequestMiddleware(object):
|
class GlobalRequestMiddleware(object):
|
||||||
def process_request(self, request):
|
def process_request(self, request):
|
||||||
_requests[threading._get_ident()] = request
|
_requests[threading._get_ident()] = request
|
||||||
return None
|
return None
|
||||||
|
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -43,15 +43,16 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class AssignedAndUnused(Job):
|
|
||||||
|
class AssignedAndUnused(Job):
|
||||||
frecuency = GlobalConfig.CHECK_UNUSED_TIME.getInt()
|
frecuency = GlobalConfig.CHECK_UNUSED_TIME.getInt()
|
||||||
friendly_name = 'Unused services checker'
|
friendly_name = 'Unused services checker'
|
||||||
|
|
||||||
def __init__(self, environment):
|
def __init__(self, environment):
|
||||||
super(AssignedAndUnused,self).__init__(environment)
|
super(AssignedAndUnused, self).__init__(environment)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
since_state = getSqlDatetime() - timedelta( seconds = GlobalConfig.CHECK_UNUSED_TIME.getInt() )
|
since_state = getSqlDatetime() - timedelta(seconds=GlobalConfig.CHECK_UNUSED_TIME.getInt())
|
||||||
for ds in DeployedService.objects.all():
|
for ds in DeployedService.objects.all():
|
||||||
# If do not needs os manager, this is
|
# If do not needs os manager, this is
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
@ -59,11 +60,10 @@ class AssignedAndUnused(Job):
|
|||||||
osm = ds.osmanager.getInstance()
|
osm = ds.osmanager.getInstance()
|
||||||
if osm.processUnusedMachines is True:
|
if osm.processUnusedMachines is True:
|
||||||
logger.debug('Processing unused services for {0}'.format(osm))
|
logger.debug('Processing unused services for {0}'.format(osm))
|
||||||
for us in ds.assignedUserServices().select_for_update().filter(in_use=False,state_date__lt=since_state, state=State.USABLE, os_state=State.USABLE):
|
for us in ds.assignedUserServices().select_for_update().filter(in_use=False, state_date__lt=since_state, state=State.USABLE, os_state=State.USABLE):
|
||||||
logger.debug('Found unused assigned service {0}'.format(us))
|
logger.debug('Found unused assigned service {0}'.format(us))
|
||||||
osm.processUnused(us)
|
osm.processUnused(us)
|
||||||
else: # No os manager, simply remove unused services in specified time
|
else: # No os manager, simply remove unused services in specified time
|
||||||
for us in ds.assignedUserServices().select_for_update().filter(in_use=False,state_date__lt=since_state, state=State.USABLE, os_state=State.USABLE):
|
for us in ds.assignedUserServices().select_for_update().filter(in_use=False, state_date__lt=since_state, state=State.USABLE, os_state=State.USABLE):
|
||||||
logger.debug('Found unused assigned service {0}'.format(us))
|
logger.debug('Found unused assigned service {0}'.format(us))
|
||||||
us.remove()
|
us.remove()
|
||||||
|
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -38,17 +38,16 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class CacheCleaner(Job):
|
class CacheCleaner(Job):
|
||||||
|
|
||||||
frecuency = 3600*24 # Once a day
|
frecuency = 3600 * 24 # Once a day
|
||||||
friendly_name = 'Utility Cache Cleaner'
|
friendly_name = 'Utility Cache Cleaner'
|
||||||
|
|
||||||
def __init__(self, environment):
|
def __init__(self, environment):
|
||||||
super(CacheCleaner,self).__init__(environment)
|
super(CacheCleaner, self).__init__(environment)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
logger.debug('Starting cache cleanup')
|
logger.debug('Starting cache cleanup')
|
||||||
Cache.cleanUp()
|
Cache.cleanUp()
|
||||||
logger.debug('Done cache cleanup')
|
logger.debug('Done cache cleanup')
|
||||||
|
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2013 Virtual Cable S.L.
|
# Copyright (c) 2013 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -47,23 +47,25 @@ GETCLUSTERSTATS_TAG = 'ClstrStats'
|
|||||||
BALANCECLUSTER_TAG = 'ClstrBalance'
|
BALANCECLUSTER_TAG = 'ClstrBalance'
|
||||||
MIGRATETASK_TAG = 'ClstrMigrate'
|
MIGRATETASK_TAG = 'ClstrMigrate'
|
||||||
|
|
||||||
# Utility to get all providers that are derived from
|
|
||||||
|
# Utility to get all providers that are derived from
|
||||||
def getClusteredProvidersFromDB():
|
def getClusteredProvidersFromDB():
|
||||||
#services.ClusteredServiceProvider.
|
# services.ClusteredServiceProvider.
|
||||||
from uds.core import services
|
from uds.core import services
|
||||||
|
|
||||||
p = services.ClusteredServiceProvider
|
p = services.ClusteredServiceProvider
|
||||||
|
|
||||||
for prov in Provider.objects.all():
|
for prov in Provider.objects.all():
|
||||||
for cls in p.__subclasses__():
|
for cls in p.__subclasses__():
|
||||||
if prov.isOfType(cls.typeType):
|
if prov.isOfType(cls.typeType):
|
||||||
yield prov
|
yield prov
|
||||||
|
|
||||||
|
|
||||||
class ClusterUpdateStatsTask(DelayedTask):
|
class ClusterUpdateStatsTask(DelayedTask):
|
||||||
def __init__(self, providerId):
|
def __init__(self, providerId):
|
||||||
super(ClusterUpdateStatsTask,self).__init__()
|
super(ClusterUpdateStatsTask, self).__init__()
|
||||||
self._id = providerId
|
self._id = providerId
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
provider = Provider.objects.get(pk=self._id)
|
provider = Provider.objects.get(pk=self._id)
|
||||||
@ -73,37 +75,41 @@ class ClusterUpdateStatsTask(DelayedTask):
|
|||||||
stats = {}
|
stats = {}
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
s = cluster.getClusterNodeLoad(node['id'])
|
s = cluster.getClusterNodeLoad(node['id'])
|
||||||
stats[node['id']] = { 'cpuLoad': s.get('cpuLoad', None), 'freeMemory': s.get('freeMemory', None),
|
stats[node['id']] = {
|
||||||
'totalMemory': s.get('totalMemory') }
|
'cpuLoad': s.get('cpuLoad', None),
|
||||||
|
'freeMemory': s.get('freeMemory', None),
|
||||||
|
'totalMemory': s.get('totalMemory')
|
||||||
|
}
|
||||||
cluster.storage().putPickle('ClusterStats', stats)
|
cluster.storage().putPickle('ClusterStats', stats)
|
||||||
except:
|
except:
|
||||||
logger.exception('Update Stats Task')
|
logger.exception('Update Stats Task')
|
||||||
# Removed provider, no problem at all, no update is done
|
# Removed provider, no problem at all, no update is done
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
# Job for managing ClusteredServiceProvider
|
# Job for managing ClusteredServiceProvider
|
||||||
class ClusterUpdateStats(Job):
|
class ClusterUpdateStats(Job):
|
||||||
frecuency = 60 # Once every 60 seconds
|
frecuency = 60 # Once every 60 seconds
|
||||||
friendly_name = 'Clustered Providers Statistics Updater'
|
friendly_name = 'Clustered Providers Statistics Updater'
|
||||||
|
|
||||||
def __init__(self, environment):
|
def __init__(self, environment):
|
||||||
super(ClusterUpdateStats,self).__init__(environment)
|
super(ClusterUpdateStats, self).__init__(environment)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
logger.debug('Clustered Service manager started')
|
logger.debug('Clustered Service manager started')
|
||||||
for p in getClusteredProvidersFromDB():
|
for p in getClusteredProvidersFromDB():
|
||||||
logger.debug('Getting stats for clustered provider {0}'.format(p.name))
|
logger.debug('Getting stats for clustered provider {0}'.format(p.name))
|
||||||
ct = ClusterUpdateStatsTask(p.id)
|
ct = ClusterUpdateStatsTask(p.id)
|
||||||
ct.register(0, '{0}_{1}'.format(GETCLUSTERSTATS_TAG, p.id), True)
|
ct.register(0, '{0}_{1}'.format(GETCLUSTERSTATS_TAG, p.id), True)
|
||||||
|
|
||||||
|
|
||||||
# Balancing nodes related
|
# Balancing nodes related
|
||||||
class ClusterMigrationTask(DelayedTask):
|
class ClusterMigrationTask(DelayedTask):
|
||||||
def __init__(self, service):
|
def __init__(self, service):
|
||||||
super(ClusterMigrationTask, self).__init__()
|
super(ClusterMigrationTask, self).__init__()
|
||||||
self._serviceId = service.id
|
self._serviceId = service.id
|
||||||
self._state = service.state
|
self._state = service.state
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def checkAndUpdateState(userService, userServiceInstance, state):
|
def checkAndUpdateState(userService, userServiceInstance, state):
|
||||||
@ -116,7 +122,7 @@ class ClusterMigrationTask(DelayedTask):
|
|||||||
checkLater = False
|
checkLater = False
|
||||||
userServiceInstance.finish()
|
userServiceInstance.finish()
|
||||||
userService.updateData(userServiceInstance)
|
userService.updateData(userServiceInstance)
|
||||||
userService.setState(State.USABLE) # Wi will only migrate fully functional services
|
userService.setState(State.USABLE) # Wi will only migrate fully functional services
|
||||||
elif State.isErrored(state):
|
elif State.isErrored(state):
|
||||||
checkLater = False
|
checkLater = False
|
||||||
userService.updateData(userServiceInstance)
|
userService.updateData(userServiceInstance)
|
||||||
@ -132,22 +138,20 @@ class ClusterMigrationTask(DelayedTask):
|
|||||||
log.doLog(userService, log.ERROR, 'Exception: {0}'.format(e), log.INTERNAL)
|
log.doLog(userService, log.ERROR, 'Exception: {0}'.format(e), log.INTERNAL)
|
||||||
userService.setState(State.ERROR)
|
userService.setState(State.ERROR)
|
||||||
userService.save()
|
userService.save()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def checkLater(userService, userServiceInstance):
|
def checkLater(userService, userServiceInstance):
|
||||||
'''
|
'''
|
||||||
Inserts a task in the delayedTaskRunner so we can check the state of this migration
|
Inserts a task in the delayedTaskRunner so we can check the state of this migration
|
||||||
@param userService: Database object for DeployedServicePublication
|
@param userService: Database object for DeployedServicePublication
|
||||||
@param userServiceInstance: Instance of Publication manager for the object
|
@param userServiceInstance: Instance of Publication manager for the object
|
||||||
'''
|
'''
|
||||||
from uds.core.jobs.DelayedTaskRunner import DelayedTaskRunner
|
from uds.core.jobs.DelayedTaskRunner import DelayedTaskRunner
|
||||||
# Do not add task if already exists one that updates this service
|
# Do not add task if already exists one that updates this service
|
||||||
if DelayedTaskRunner.runner().checkExists(MIGRATETASK_TAG + str(userService.id)):
|
if DelayedTaskRunner.runner().checkExists(MIGRATETASK_TAG + str(userService.id)):
|
||||||
return
|
return
|
||||||
DelayedTaskRunner.runner().insert(ClusterUpdateStats(userService), userServiceInstance.suggestedTime, ClusterUpdateStats + str(userService.id))
|
DelayedTaskRunner.runner().insert(ClusterUpdateStats(userService), userServiceInstance.suggestedTime, ClusterUpdateStats + str(userService.id))
|
||||||
|
|
||||||
|
|
||||||
@transaction.atomic
|
|
||||||
def run(self):
|
def run(self):
|
||||||
logger.debug('Checking user service finished migrating {0}'.format(self._serviceId))
|
logger.debug('Checking user service finished migrating {0}'.format(self._serviceId))
|
||||||
uService = None
|
uService = None
|
||||||
@ -157,7 +161,7 @@ class ClusterMigrationTask(DelayedTask):
|
|||||||
logger.debug('Task overrided by another task (state of item changed)')
|
logger.debug('Task overrided by another task (state of item changed)')
|
||||||
# This item is no longer valid, returning will not check it again (no checkLater called)
|
# This item is no longer valid, returning will not check it again (no checkLater called)
|
||||||
return
|
return
|
||||||
|
|
||||||
ci = uService.getInstance()
|
ci = uService.getInstance()
|
||||||
logger.debug("uService instance class: {0}".format(ci.__class__))
|
logger.debug("uService instance class: {0}".format(ci.__class__))
|
||||||
state = ci.checkState()
|
state = ci.checkState()
|
||||||
@ -174,24 +178,25 @@ class ClusterMigrationTask(DelayedTask):
|
|||||||
uService.save()
|
uService.save()
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.error('Can\'t update state of uService object')
|
logger.error('Can\'t update state of uService object')
|
||||||
|
|
||||||
|
|
||||||
class ClusterBalancingTask(DelayedTask):
|
class ClusterBalancingTask(DelayedTask):
|
||||||
def __init__(self, providerId):
|
def __init__(self, providerId):
|
||||||
super(ClusterBalancingTask, self).__init__()
|
super(ClusterBalancingTask, self).__init__()
|
||||||
self._id = providerId
|
self._id = providerId
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def migrate(serviceId, toNode):
|
def migrate(serviceId, toNode):
|
||||||
try:
|
try:
|
||||||
service = UserService.objects.select_for_update().get(pk=serviceId)
|
service = UserService.objects.select_for_update().get(pk=serviceId)
|
||||||
service.setState(State.BALANCING)
|
service.setState(State.BALANCING)
|
||||||
|
|
||||||
serviceInstance = service.getInstance()
|
serviceInstance = service.getInstance()
|
||||||
|
|
||||||
# Now we will start a new task, similar to those of deploying
|
# Now we will start a new task, similar to those of deploying
|
||||||
state = serviceInstance.startMigration(toNode)
|
state = serviceInstance.startMigration(toNode)
|
||||||
|
|
||||||
ClusterMigrationTask.checkAndUpdateState(service, serviceInstance, state)
|
ClusterMigrationTask.checkAndUpdateState(service, serviceInstance, state)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception('Initializing migration')
|
logger.exception('Initializing migration')
|
||||||
@ -202,7 +207,7 @@ class ClusterBalancingTask(DelayedTask):
|
|||||||
service.save()
|
service.save()
|
||||||
except:
|
except:
|
||||||
logger.exception('Setting error state at migration init')
|
logger.exception('Setting error state at migration init')
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
provider = Provider.objects.get(pk=self._id)
|
provider = Provider.objects.get(pk=self._id)
|
||||||
@ -221,7 +226,7 @@ class ClusterBalancingTask(DelayedTask):
|
|||||||
if node is not None:
|
if node is not None:
|
||||||
s.cluster_node = node
|
s.cluster_node = node
|
||||||
s.save()
|
s.save()
|
||||||
|
|
||||||
if serviceForBalancing is None:
|
if serviceForBalancing is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -230,18 +235,18 @@ class ClusterBalancingTask(DelayedTask):
|
|||||||
logger.debug('Cluster is overloaded, but no underloaded nodes for receiving migration')
|
logger.debug('Cluster is overloaded, but no underloaded nodes for receiving migration')
|
||||||
|
|
||||||
underloadedNode = nodesForDestination[0]
|
underloadedNode = nodesForDestination[0]
|
||||||
|
|
||||||
ClusterBalancingTask.migrate(serviceForBalancing, underloadedNode)
|
ClusterBalancingTask.migrate(serviceForBalancing, underloadedNode)
|
||||||
except:
|
except:
|
||||||
logger.exception('Cluster Balancing Task')
|
logger.exception('Cluster Balancing Task')
|
||||||
|
|
||||||
|
|
||||||
class ClusterBalancingJob(Job):
|
class ClusterBalancingJob(Job):
|
||||||
frecuency = 90
|
frecuency = 90
|
||||||
friendly_name = 'Clustered Providers Balancing job'
|
friendly_name = 'Clustered Providers Balancing job'
|
||||||
|
|
||||||
def __init__(self, environment):
|
def __init__(self, environment):
|
||||||
super(ClusterBalancingJob,self).__init__(environment)
|
super(ClusterBalancingJob, self).__init__(environment)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
'''
|
'''
|
||||||
@ -252,4 +257,3 @@ class ClusterBalancingJob(Job):
|
|||||||
logger.debug('Checking balancing on {0}'.format(p.name))
|
logger.debug('Checking balancing on {0}'.format(p.name))
|
||||||
cb = ClusterBalancingTask(p.id)
|
cb = ClusterBalancingTask(p.id)
|
||||||
cb.register(0, '{0}_{1}'.format(BALANCECLUSTER_TAG, p.id), True)
|
cb.register(0, '{0}_{1}'.format(BALANCECLUSTER_TAG, p.id), True)
|
||||||
|
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -42,30 +42,31 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DeployedServiceInfoItemsCleaner(Job):
|
class DeployedServiceInfoItemsCleaner(Job):
|
||||||
frecuency = GlobalConfig.CLEANUP_CHECK.getInt() # Request run cache "info" cleaner every configured seconds. If config value is changed, it will be used at next reload
|
frecuency = GlobalConfig.CLEANUP_CHECK.getInt() # Request run cache "info" cleaner every configured seconds. If config value is changed, it will be used at next reload
|
||||||
friendly_name = 'Deployed Service Info Cleaner'
|
friendly_name = 'Deployed Service Info Cleaner'
|
||||||
|
|
||||||
def __init__(self, environment):
|
def __init__(self, environment):
|
||||||
super(DeployedServiceInfoItemsCleaner,self).__init__(environment)
|
super(DeployedServiceInfoItemsCleaner, self).__init__(environment)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
removeFrom = getSqlDatetime() - timedelta(seconds = GlobalConfig.KEEP_INFO_TIME.getInt())
|
removeFrom = getSqlDatetime() - timedelta(seconds=GlobalConfig.KEEP_INFO_TIME.getInt())
|
||||||
DeployedService.objects.filter(state__in=State.INFO_STATES, state_date__lt=removeFrom).delete()
|
DeployedService.objects.filter(state__in=State.INFO_STATES, state_date__lt=removeFrom).delete()
|
||||||
|
|
||||||
|
|
||||||
class DeployedServiceRemover(Job):
|
class DeployedServiceRemover(Job):
|
||||||
frecuency = GlobalConfig.REMOVAL_CHECK.getInt() # Request run publication "removal" every configued seconds. If config value is changed, it will be used at next reload
|
frecuency = GlobalConfig.REMOVAL_CHECK.getInt() # Request run publication "removal" every configued seconds. If config value is changed, it will be used at next reload
|
||||||
friendly_name = 'Deployed Service Cleaner'
|
friendly_name = 'Deployed Service Cleaner'
|
||||||
|
|
||||||
def __init__(self, environment):
|
def __init__(self, environment):
|
||||||
super(DeployedServiceRemover,self).__init__(environment)
|
super(DeployedServiceRemover, self).__init__(environment)
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def startRemovalOf(self, ds):
|
def startRemovalOf(self, ds):
|
||||||
# Get publications in course...., can be at most 1!!!
|
# Get publications in course...., can be at most 1!!!
|
||||||
logger.debug('Removal process of {0}'.format(ds))
|
logger.debug('Removal process of {0}'.format(ds))
|
||||||
|
|
||||||
publishing = ds.publications.filter(state=State.PREPARING)
|
publishing = ds.publications.filter(state=State.PREPARING)
|
||||||
for p in publishing:
|
for p in publishing:
|
||||||
p.cancel()
|
p.cancel()
|
||||||
@ -78,17 +79,16 @@ class DeployedServiceRemover(Job):
|
|||||||
ds.state = State.REMOVING
|
ds.state = State.REMOVING
|
||||||
ds.name = ds.name + ' (removed)'
|
ds.name = ds.name + ' (removed)'
|
||||||
ds.save()
|
ds.save()
|
||||||
|
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def continueRemovalOf(self, ds):
|
def continueRemovalOf(self, ds):
|
||||||
# First, we remove all publications and user services in "info_state"
|
# First, we remove all publications and user services in "info_state"
|
||||||
ds.userServices.select_for_update().filter(state__in=State.INFO_STATES).delete()
|
ds.userServices.select_for_update().filter(state__in=State.INFO_STATES).delete()
|
||||||
# Mark usable user services as removable
|
# Mark usable user services as removable
|
||||||
now = getSqlDatetime()
|
now = getSqlDatetime()
|
||||||
ds.userServices.select_for_update().filter(state=State.USABLE).update(state=State.REMOVABLE, state_date=now)
|
ds.userServices.select_for_update().filter(state=State.USABLE).update(state=State.REMOVABLE, state_date=now)
|
||||||
|
|
||||||
# When no service is at database, we start with publications
|
# When no service is at database, we start with publications
|
||||||
if ds.userServices.all().count() == 0:
|
if ds.userServices.all().count() == 0:
|
||||||
try:
|
try:
|
||||||
logger.debug('All services removed, checking active publication')
|
logger.debug('All services removed, checking active publication')
|
||||||
@ -99,10 +99,10 @@ class DeployedServiceRemover(Job):
|
|||||||
logger.debug('No active publication found, removing info states and checking if removal is done')
|
logger.debug('No active publication found, removing info states and checking if removal is done')
|
||||||
ds.publications.filter(state__in=State.INFO_STATES).delete()
|
ds.publications.filter(state__in=State.INFO_STATES).delete()
|
||||||
if ds.publications.count() is 0:
|
if ds.publications.count() is 0:
|
||||||
ds.removed() # Mark it as removed, clean later from database
|
ds.removed() # Mark it as removed, clean later from database
|
||||||
except Exception as e:
|
except Exception:
|
||||||
logger.exception('Cought unexpected exception at continueRemovalOf: ')
|
logger.exception('Cought unexpected exception at continueRemovalOf: ')
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
# First check if there is someone in "removable" estate
|
# First check if there is someone in "removable" estate
|
||||||
rems = DeployedService.objects.filter(state=State.REMOVABLE)[:10]
|
rems = DeployedService.objects.filter(state=State.REMOVABLE)[:10]
|
||||||
@ -115,5 +115,3 @@ class DeployedServiceRemover(Job):
|
|||||||
logger.debug('Found a deployed service in removing state, continuing removal of {0}'.format(rems))
|
logger.debug('Found a deployed service in removing state, continuing removal of {0}'.format(rems))
|
||||||
for rem in rems:
|
for rem in rems:
|
||||||
self.continueRemovalOf(rem)
|
self.continueRemovalOf(rem)
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -43,18 +43,19 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class HangedCleaner(Job):
|
|
||||||
|
class HangedCleaner(Job):
|
||||||
frecuency = GlobalConfig.MAX_INITIALIZING_TIME.getInt()
|
frecuency = GlobalConfig.MAX_INITIALIZING_TIME.getInt()
|
||||||
friendly_name = 'Hanged services checker'
|
friendly_name = 'Hanged services checker'
|
||||||
|
|
||||||
def __init__(self, environment):
|
def __init__(self, environment):
|
||||||
super(HangedCleaner,self).__init__(environment)
|
super(HangedCleaner, self).__init__(environment)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
since_state = getSqlDatetime() - timedelta( seconds = GlobalConfig.MAX_INITIALIZING_TIME.getInt() )
|
since_state = getSqlDatetime() - timedelta(seconds=GlobalConfig.MAX_INITIALIZING_TIME.getInt())
|
||||||
# Filter for locating machine not ready
|
# Filter for locating machine not ready
|
||||||
flt = Q(state_date__lt=since_state, state=State.PREPARING) | Q(state_date__lt=since_state, state=State.USABLE, os_state=State.PREPARING)
|
flt = Q(state_date__lt=since_state, state=State.PREPARING) | Q(state_date__lt=since_state, state=State.USABLE, os_state=State.PREPARING)
|
||||||
|
|
||||||
for ds in DeployedService.objects.exclude(osmanager=None, state__in=State.VALID_STATES):
|
for ds in DeployedService.objects.exclude(osmanager=None, state__in=State.VALID_STATES):
|
||||||
logger.debug('Searching for hanged services for {0}'.format(ds))
|
logger.debug('Searching for hanged services for {0}'.format(ds))
|
||||||
for us in ds.userServices.filter(flt):
|
for us in ds.userServices.filter(flt):
|
||||||
@ -62,4 +63,3 @@ class HangedCleaner(Job):
|
|||||||
log.doLog(us, log.ERROR, 'User Service seems to be hanged. Removing it.', log.INTERNAL)
|
log.doLog(us, log.ERROR, 'User Service seems to be hanged. Removing it.', log.INTERNAL)
|
||||||
log.doLog(ds, log.ERROR, 'Removing user service {0} because it seems to be hanged'.format(us.friendly_name))
|
log.doLog(ds, log.ERROR, 'Removing user service {0} because it seems to be hanged'.format(us.friendly_name))
|
||||||
us.removeOrCancel()
|
us.removeOrCancel()
|
||||||
|
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -45,28 +45,29 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class PublicationInfoItemsCleaner(Job):
|
class PublicationInfoItemsCleaner(Job):
|
||||||
frecuency = GlobalConfig.CLEANUP_CHECK.getInt() # Request run cache "info" cleaner every configured seconds. If config value is changed, it will be used at next reload
|
frecuency = GlobalConfig.CLEANUP_CHECK.getInt() # Request run cache "info" cleaner every configured seconds. If config value is changed, it will be used at next reload
|
||||||
friendly_name = 'Publications Info Cleaner'
|
friendly_name = 'Publications Info Cleaner'
|
||||||
now = getSqlDatetime()
|
|
||||||
def __init__(self, environment):
|
def __init__(self, environment):
|
||||||
super(PublicationInfoItemsCleaner,self).__init__(environment)
|
super(PublicationInfoItemsCleaner, self).__init__(environment)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
removeFrom = getSqlDatetime() - timedelta(seconds = GlobalConfig.KEEP_INFO_TIME.getInt(True))
|
removeFrom = getSqlDatetime() - timedelta(seconds=GlobalConfig.KEEP_INFO_TIME.getInt(True))
|
||||||
DeployedServicePublication.objects.filter(state__in=State.INFO_STATES, state_date__lt=removeFrom).delete()
|
DeployedServicePublication.objects.filter(state__in=State.INFO_STATES, state_date__lt=removeFrom).delete()
|
||||||
|
|
||||||
|
|
||||||
class PublicationCleaner(Job):
|
class PublicationCleaner(Job):
|
||||||
frecuency = GlobalConfig.REMOVAL_CHECK.getInt() # Request run publication "removal" every configued seconds. If config value is changed, it will be used at next reload
|
frecuency = GlobalConfig.REMOVAL_CHECK.getInt() # Request run publication "removal" every configued seconds. If config value is changed, it will be used at next reload
|
||||||
friendly_name = 'Publication Cleaner'
|
friendly_name = 'Publication Cleaner'
|
||||||
|
|
||||||
def __init__(self, environment):
|
def __init__(self, environment):
|
||||||
super(PublicationCleaner,self).__init__(environment)
|
super(PublicationCleaner, self).__init__(environment)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
removables = DeployedServicePublication.objects.filter(state=State.REMOVABLE)
|
removables = DeployedServicePublication.objects.filter(state=State.REMOVABLE)
|
||||||
for removable in removables:
|
for removable in removables:
|
||||||
try:
|
try:
|
||||||
PublicationManager.manager().unpublish(removable)
|
PublicationManager.manager().unpublish(removable)
|
||||||
except PublishException: # Can say that it cant be removed right now
|
except PublishException: # Can say that it cant be removed right now
|
||||||
logger.debug('Delaying removal')
|
logger.debug('Delaying removal')
|
||||||
pass
|
pass
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -46,7 +46,7 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ServiceCacheUpdater(Job):
|
class ServiceCacheUpdater(Job):
|
||||||
'''
|
'''
|
||||||
Cache updater is responsible of keeping up to date the cache for different deployed services configurations requested
|
Cache updater is responsible of keeping up to date the cache for different deployed services configurations requested
|
||||||
@ -54,37 +54,37 @@ class ServiceCacheUpdater(Job):
|
|||||||
if cache is not needed.
|
if cache is not needed.
|
||||||
This is included as a scheduled task that will run every X seconds, and scheduler will keep it so it will be only executed by one backend at a time
|
This is included as a scheduled task that will run every X seconds, and scheduler will keep it so it will be only executed by one backend at a time
|
||||||
'''
|
'''
|
||||||
frecuency = GlobalConfig.CACHE_CHECK_DELAY.getInt() # Request run cache manager every configured seconds (defaults to 20 seconds).
|
frecuency = GlobalConfig.CACHE_CHECK_DELAY.getInt() # Request run cache manager every configured seconds (defaults to 20 seconds).
|
||||||
# If config value is changed, it will be used at next reload
|
# If config value is changed, it will be used at next reload
|
||||||
friendly_name = 'Service Cache Updater'
|
friendly_name = 'Service Cache Updater'
|
||||||
|
|
||||||
def __init__(self, environment):
|
def __init__(self, environment):
|
||||||
super(ServiceCacheUpdater,self).__init__(environment)
|
super(ServiceCacheUpdater, self).__init__(environment)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def calcProportion(max, actual):
|
def calcProportion(max_, actual):
|
||||||
return actual * 10000 / max
|
return actual * 10000 / (max_ or 1)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __notifyRestrain(deployedService):
|
def __notifyRestrain(deployedService):
|
||||||
log.doLog(deployedService, log.WARN, 'Deployed service is restrained due to errors', log.INTERNAL)
|
log.doLog(deployedService, log.WARN, 'Deployed service is restrained due to errors', log.INTERNAL)
|
||||||
logger.info('Deployed service {0} is restrained, will check this later'.format(deployedService.name))
|
logger.info('Deployed service {0} is restrained, will check this later'.format(deployedService.name))
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def bestDeployedServiceNeedingCacheUpdate(self):
|
def bestDeployedServiceNeedingCacheUpdate(self):
|
||||||
# State filter for cached and inAssigned objects
|
# State filter for cached and inAssigned objects
|
||||||
# First we get all deployed services that could need cache generation
|
# First we get all deployed services that could need cache generation
|
||||||
DeployedService.objects.update()
|
DeployedService.objects.update()
|
||||||
# We start filtering out the deployed services that do not need caching at all.
|
# We start filtering out the deployed services that do not need caching at all.
|
||||||
whichNeedsCaching = DeployedService.objects.filter(Q(initial_srvs__gt=0) | Q(cache_l1_srvs__gt=0)).filter(max_srvs__gt=0,state=State.ACTIVE)
|
whichNeedsCaching = DeployedService.objects.filter(Q(initial_srvs__gt=0) | Q(cache_l1_srvs__gt=0)).filter(max_srvs__gt=0, state=State.ACTIVE)
|
||||||
|
|
||||||
# We will get the one that proportionally needs more cache
|
# We will get the one that proportionally needs more cache
|
||||||
selected = None
|
selected = None
|
||||||
cachedL1, cachedL2, assigned = 0,0,0
|
cachedL1, cachedL2, assigned = 0, 0, 0
|
||||||
toCacheL1 = False # Mark for prefering update L1 cache before L2 cache
|
toCacheL1 = False # Mark for prefering update L1 cache before L2 cache
|
||||||
prop = ServiceCacheUpdater.calcProportion(1,1)
|
prop = ServiceCacheUpdater.calcProportion(1, 1)
|
||||||
for ds in whichNeedsCaching:
|
for ds in whichNeedsCaching:
|
||||||
ds.userServices.update() # Cleans cached queries
|
ds.userServices.update() # Cleans cached queries
|
||||||
# If this deployedService don't have a publication active and needs it, ignore it
|
# If this deployedService don't have a publication active and needs it, ignore it
|
||||||
if ds.activePublication() == None and ds.service.getInstance().publicationType is not None:
|
if ds.activePublication() == None and ds.service.getInstance().publicationType is not None:
|
||||||
logger.debug('Needs publication but do not have one, cache test ignored')
|
logger.debug('Needs publication but do not have one, cache test ignored')
|
||||||
@ -93,11 +93,11 @@ class ServiceCacheUpdater(Job):
|
|||||||
if ds.publications.filter(state=State.PREPARING).count() > 0:
|
if ds.publications.filter(state=State.PREPARING).count() > 0:
|
||||||
logger.debug('Stopped cache generation for deployed service with publication running: {0}'.format(ds))
|
logger.debug('Stopped cache generation for deployed service with publication running: {0}'.format(ds))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if ds.isRestrained():
|
if ds.isRestrained():
|
||||||
ServiceCacheUpdater.__notifyRestrain(ds)
|
ServiceCacheUpdater.__notifyRestrain(ds)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Get data related to actual state of cache
|
# Get data related to actual state of cache
|
||||||
inCacheL1 = ds.cachedUserServices().filter(UserServiceManager.getCacheStateFilter(services.UserDeployment.L1_CACHE)).count()
|
inCacheL1 = ds.cachedUserServices().filter(UserServiceManager.getCacheStateFilter(services.UserDeployment.L1_CACHE)).count()
|
||||||
inCacheL2 = ds.cachedUserServices().filter(UserServiceManager.getCacheStateFilter(services.UserDeployment.L2_CACHE)).count()
|
inCacheL2 = ds.cachedUserServices().filter(UserServiceManager.getCacheStateFilter(services.UserDeployment.L2_CACHE)).count()
|
||||||
@ -118,15 +118,15 @@ class ServiceCacheUpdater(Job):
|
|||||||
cachedL1, cachedL2, assigned = inCacheL1, inCacheL2, inAssigned
|
cachedL1, cachedL2, assigned = inCacheL1, inCacheL2, inAssigned
|
||||||
selected = ds
|
selected = ds
|
||||||
break
|
break
|
||||||
|
|
||||||
# If we have more in L2 cache than needed, decrease L2 cache, but int this case, we continue checking cause L2 cache removal
|
# If we have more in L2 cache than needed, decrease L2 cache, but int this case, we continue checking cause L2 cache removal
|
||||||
# has less priority than l1 creations or removals, but higher. In this case, we will simply take last l2 oversized found and reduce it
|
# has less priority than l1 creations or removals, but higher. In this case, we will simply take last l2 oversized found and reduce it
|
||||||
if inCacheL2 > ds.cache_l2_srvs:
|
if inCacheL2 > ds.cache_l2_srvs:
|
||||||
if toCacheL1 == False:
|
if toCacheL1 == False:
|
||||||
logger.debug('We have more services in L2 cache than configured, decreasing it')
|
logger.debug('We have more services in L2 cache than configured, decreasing it')
|
||||||
cachedL1, cachedL2, assigned = inCacheL1, inCacheL2, inAssigned
|
cachedL1, cachedL2, assigned = inCacheL1, inCacheL2, inAssigned
|
||||||
selected = ds
|
selected = ds
|
||||||
prop = ServiceCacheUpdater.calcProportion(1,0)
|
prop = ServiceCacheUpdater.calcProportion(1, 0)
|
||||||
|
|
||||||
# If this service don't allows more starting user services, continue
|
# If this service don't allows more starting user services, continue
|
||||||
if UserServiceManager.manager().canInitiateServiceFromDeployedService(ds) is False:
|
if UserServiceManager.manager().canInitiateServiceFromDeployedService(ds) is False:
|
||||||
@ -143,11 +143,11 @@ class ServiceCacheUpdater(Job):
|
|||||||
cachedL1, cachedL2, assigned = inCacheL1, inCacheL2, inAssigned
|
cachedL1, cachedL2, assigned = inCacheL1, inCacheL2, inAssigned
|
||||||
selected = ds
|
selected = ds
|
||||||
prop = p
|
prop = p
|
||||||
|
|
||||||
# We skip it if already at max
|
# We skip it if already at max
|
||||||
if totalL1Assigned == ds.max_srvs:
|
if totalL1Assigned == ds.max_srvs:
|
||||||
continue;
|
continue
|
||||||
|
|
||||||
if totalL1Assigned < ds.initial_srvs:
|
if totalL1Assigned < ds.initial_srvs:
|
||||||
p = ServiceCacheUpdater.calcProportion(ds.initial_srvs, totalL1Assigned)
|
p = ServiceCacheUpdater.calcProportion(ds.initial_srvs, totalL1Assigned)
|
||||||
if p < prop or toCacheL1 == False:
|
if p < prop or toCacheL1 == False:
|
||||||
@ -164,14 +164,14 @@ class ServiceCacheUpdater(Job):
|
|||||||
selected = ds
|
selected = ds
|
||||||
cachedL1, cachedL2, assigned = inCacheL1, inCacheL2, inAssigned
|
cachedL1, cachedL2, assigned = inCacheL1, inCacheL2, inAssigned
|
||||||
prop = p
|
prop = p
|
||||||
|
|
||||||
# We also return calculated values so we can reuse then
|
# We also return calculated values so we can reuse then
|
||||||
return selected, cachedL1, cachedL2, assigned
|
return selected, cachedL1, cachedL2, assigned
|
||||||
|
|
||||||
def growL1Cache(self, ds, cacheL1, cacheL2, assigned):
|
def growL1Cache(self, ds, cacheL1, cacheL2, assigned):
|
||||||
'''
|
'''
|
||||||
This method tries to enlarge L1 cache.
|
This method tries to enlarge L1 cache.
|
||||||
|
|
||||||
If for some reason the number of deployed services (Counting all, ACTIVE
|
If for some reason the number of deployed services (Counting all, ACTIVE
|
||||||
and PREPARING, assigned, L1 and L2) is over max allowed service deployments,
|
and PREPARING, assigned, L1 and L2) is over max allowed service deployments,
|
||||||
this method will not grow the L1 cache
|
this method will not grow the L1 cache
|
||||||
@ -189,7 +189,7 @@ class ServiceCacheUpdater(Job):
|
|||||||
else:
|
else:
|
||||||
valid = n
|
valid = n
|
||||||
break
|
break
|
||||||
|
|
||||||
if valid is not None:
|
if valid is not None:
|
||||||
valid.moveToLevel(services.UserDeployment.L1_CACHE)
|
valid.moveToLevel(services.UserDeployment.L1_CACHE)
|
||||||
return
|
return
|
||||||
@ -200,11 +200,11 @@ class ServiceCacheUpdater(Job):
|
|||||||
# TODO: When alerts are ready, notify this
|
# TODO: When alerts are ready, notify this
|
||||||
except:
|
except:
|
||||||
logger.exception('Exception')
|
logger.exception('Exception')
|
||||||
|
|
||||||
def growL2Cache(self, ds, cacheL1, cacheL2, assigned):
|
def growL2Cache(self, ds, cacheL1, cacheL2, assigned):
|
||||||
'''
|
'''
|
||||||
Tries to grow L2 cache of service.
|
Tries to grow L2 cache of service.
|
||||||
|
|
||||||
If for some reason the number of deployed services (Counting all, ACTIVE
|
If for some reason the number of deployed services (Counting all, ACTIVE
|
||||||
and PREPARING, assigned, L1 and L2) is over max allowed service deployments,
|
and PREPARING, assigned, L1 and L2) is over max allowed service deployments,
|
||||||
this method will not grow the L1 cache
|
this method will not grow the L1 cache
|
||||||
@ -215,7 +215,7 @@ class ServiceCacheUpdater(Job):
|
|||||||
except MaxServicesReachedException as e:
|
except MaxServicesReachedException as e:
|
||||||
logger.error(str(e))
|
logger.error(str(e))
|
||||||
# TODO: When alerts are ready, notify this
|
# TODO: When alerts are ready, notify this
|
||||||
|
|
||||||
def reduceL1Cache(self, ds, cacheL1, cacheL2, assigned):
|
def reduceL1Cache(self, ds, cacheL1, cacheL2, assigned):
|
||||||
logger.debug("Reducing L1 cache erasing a service in cache for {0}".format(ds))
|
logger.debug("Reducing L1 cache erasing a service in cache for {0}".format(ds))
|
||||||
# We will try to destroy the newest cacheL1 element that is USABLE if the deployer can't cancel a new service creation
|
# We will try to destroy the newest cacheL1 element that is USABLE if the deployer can't cancel a new service creation
|
||||||
@ -223,7 +223,7 @@ class ServiceCacheUpdater(Job):
|
|||||||
if len(cacheItems) == 0:
|
if len(cacheItems) == 0:
|
||||||
logger.debug('There is more services than configured, but could not reduce cache cause its already empty')
|
logger.debug('There is more services than configured, but could not reduce cache cause its already empty')
|
||||||
return
|
return
|
||||||
|
|
||||||
if cacheL2 < ds.cache_l2_srvs:
|
if cacheL2 < ds.cache_l2_srvs:
|
||||||
valid = None
|
valid = None
|
||||||
for n in cacheItems:
|
for n in cacheItems:
|
||||||
@ -234,14 +234,14 @@ class ServiceCacheUpdater(Job):
|
|||||||
else:
|
else:
|
||||||
valid = n
|
valid = n
|
||||||
break
|
break
|
||||||
|
|
||||||
if valid is not None:
|
if valid is not None:
|
||||||
valid.moveToLevel(services.UserDeployment.L2_CACHE)
|
valid.moveToLevel(services.UserDeployment.L2_CACHE)
|
||||||
return
|
return
|
||||||
|
|
||||||
cache = cacheItems[0]
|
cache = cacheItems[0]
|
||||||
cache.removeOrCancel()
|
cache.removeOrCancel()
|
||||||
|
|
||||||
def reduceL2Cache(self, ds, cacheL1, cacheL2, assigned):
|
def reduceL2Cache(self, ds, cacheL1, cacheL2, assigned):
|
||||||
logger.debug("Reducing L2 cache erasing a service in cache for {0}".format(ds))
|
logger.debug("Reducing L2 cache erasing a service in cache for {0}".format(ds))
|
||||||
if cacheL2 > 0:
|
if cacheL2 > 0:
|
||||||
@ -249,7 +249,7 @@ class ServiceCacheUpdater(Job):
|
|||||||
# TODO: Look first for non finished cache items and cancel them
|
# TODO: Look first for non finished cache items and cancel them
|
||||||
cache = cacheItems[0]
|
cache = cacheItems[0]
|
||||||
cache.removeOrCancel()
|
cache.removeOrCancel()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
logger.debug('Starting cache checking')
|
logger.debug('Starting cache checking')
|
||||||
# We need to get
|
# We need to get
|
||||||
@ -257,10 +257,10 @@ class ServiceCacheUpdater(Job):
|
|||||||
# We have cache to update??
|
# We have cache to update??
|
||||||
if ds == None:
|
if ds == None:
|
||||||
logger.debug('Cache up to date')
|
logger.debug('Cache up to date')
|
||||||
return
|
return
|
||||||
logger.debug("Updating cache for {0}".format(ds))
|
logger.debug("Updating cache for {0}".format(ds))
|
||||||
totalL1Assigned = cacheL1 + assigned
|
totalL1Assigned = cacheL1 + assigned
|
||||||
|
|
||||||
# We try first to reduce cache before tring to increase it.
|
# We try first to reduce cache before tring to increase it.
|
||||||
# This means that if there is excesive number of user deployments
|
# This means that if there is excesive number of user deployments
|
||||||
# for L1 or L2 cache, this will be reduced untill they have good numbers.
|
# for L1 or L2 cache, this will be reduced untill they have good numbers.
|
||||||
@ -271,11 +271,11 @@ class ServiceCacheUpdater(Job):
|
|||||||
self.reduceL1Cache(ds, cacheL1, cacheL2, assigned)
|
self.reduceL1Cache(ds, cacheL1, cacheL2, assigned)
|
||||||
elif totalL1Assigned > ds.initial_srvs and cacheL1 > ds.cache_l1_srvs:
|
elif totalL1Assigned > ds.initial_srvs and cacheL1 > ds.cache_l1_srvs:
|
||||||
self.reduceL1Cache(ds, cacheL1, cacheL2, assigned)
|
self.reduceL1Cache(ds, cacheL1, cacheL2, assigned)
|
||||||
elif cacheL2 > ds.cache_l2_srvs: # We have excesives L2 items
|
elif cacheL2 > ds.cache_l2_srvs: # We have excesives L2 items
|
||||||
self.reduceL2Cache(ds, cacheL1, cacheL2, assigned)
|
self.reduceL2Cache(ds, cacheL1, cacheL2, assigned)
|
||||||
elif totalL1Assigned < ds.max_srvs and (totalL1Assigned < ds.initial_srvs or cacheL1 < ds.cache_l1_srvs): # We need more services
|
elif totalL1Assigned < ds.max_srvs and (totalL1Assigned < ds.initial_srvs or cacheL1 < ds.cache_l1_srvs): # We need more services
|
||||||
self.growL1Cache(ds, cacheL1, cacheL2, assigned)
|
self.growL1Cache(ds, cacheL1, cacheL2, assigned)
|
||||||
elif cacheL2 < ds.cache_l2_srvs: # We need more L2 items
|
elif cacheL2 < ds.cache_l2_srvs: # We need more L2 items
|
||||||
self.growL2Cache(ds, cacheL1, cacheL2, assigned)
|
self.growL2Cache(ds, cacheL1, cacheL2, assigned)
|
||||||
else:
|
else:
|
||||||
logger.info("We have more services than max requested for {0}, but can't erase any of then cause all of them are already assigned".format(ds))
|
logger.info("We have more services than max requested for {0}, but can't erase any of then cause all of them are already assigned".format(ds))
|
||||||
|
@ -3,27 +3,27 @@
|
|||||||
# Copyright (c) 2013 Virtual Cable S.L.
|
# Copyright (c) 2013 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -41,22 +41,22 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DeployedServiceStatsCollector(Job):
|
class DeployedServiceStatsCollector(Job):
|
||||||
'''
|
'''
|
||||||
This Job is responsible for collecting stats for every deployed service every ten minutes
|
This Job is responsible for collecting stats for every deployed service every ten minutes
|
||||||
'''
|
'''
|
||||||
|
|
||||||
frecuency = 599 # Once every ten minutes, 601 is prime, 599 also is prime
|
frecuency = 599 # Once every ten minutes, 601 is prime, 599 also is prime
|
||||||
friendly_name = 'Deployed Service Stats'
|
friendly_name = 'Deployed Service Stats'
|
||||||
|
|
||||||
def __init__(self, environment):
|
def __init__(self, environment):
|
||||||
super(DeployedServiceStatsCollector,self).__init__(environment)
|
super(DeployedServiceStatsCollector, self).__init__(environment)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
logger.debug('Starting Deployed service stats collector')
|
logger.debug('Starting Deployed service stats collector')
|
||||||
|
|
||||||
for ds in DeployedService.objects.filter(state = State.ACTIVE):
|
for ds in DeployedService.objects.filter(state=State.ACTIVE):
|
||||||
try:
|
try:
|
||||||
fltr = ds.assignedUserServices().exclude(state__in=State.INFO_STATES)
|
fltr = ds.assignedUserServices().exclude(state__in=State.INFO_STATES)
|
||||||
assigned = fltr.count()
|
assigned = fltr.count()
|
||||||
@ -65,32 +65,31 @@ class DeployedServiceStatsCollector(Job):
|
|||||||
counters.addCounter(ds, counters.CT_INUSE, inUse)
|
counters.addCounter(ds, counters.CT_INUSE, inUse)
|
||||||
except:
|
except:
|
||||||
logger.exception('Getting counters for deployed service {0}'.format(ds))
|
logger.exception('Getting counters for deployed service {0}'.format(ds))
|
||||||
|
|
||||||
|
|
||||||
logger.debug('Done Deployed service stats collector')
|
logger.debug('Done Deployed service stats collector')
|
||||||
|
|
||||||
|
|
||||||
class StatsCleaner(Job):
|
class StatsCleaner(Job):
|
||||||
'''
|
'''
|
||||||
This Job is responsible of housekeeping of stats tables.
|
This Job is responsible of housekeeping of stats tables.
|
||||||
This is done by:
|
This is done by:
|
||||||
* Deleting all records
|
* Deleting all records
|
||||||
* Optimize table
|
* Optimize table
|
||||||
'''
|
'''
|
||||||
|
|
||||||
frecuency = 3600*24*15 # Ejecuted just once every 15 days
|
frecuency = 3600 * 24 * 15 # Ejecuted just once every 15 days
|
||||||
friendly_name = 'Statistic housekeeping'
|
friendly_name = 'Statistic housekeeping'
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
logger.debug('Starting statistics cleanup')
|
logger.debug('Starting statistics cleanup')
|
||||||
try:
|
try:
|
||||||
statsManager().cleanupCounters()
|
statsManager().cleanupCounters()
|
||||||
except:
|
except:
|
||||||
logger.exception('Cleaning up counters')
|
logger.exception('Cleaning up counters')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
statsManager().cleanupEvents()
|
statsManager().cleanupEvents()
|
||||||
except:
|
except:
|
||||||
logger.exception('Cleaning up events')
|
logger.exception('Cleaning up events')
|
||||||
|
|
||||||
logger.debug('Donde statistics cleanup')
|
logger.debug('Donde statistics cleanup')
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -48,31 +48,30 @@ logger = logging.getLogger(__name__)
|
|||||||
# Look for non current cache items and mark them as removables.
|
# Look for non current cache items and mark them as removables.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class UserServiceInfoItemsCleaner(Job):
|
class UserServiceInfoItemsCleaner(Job):
|
||||||
frecuency = GlobalConfig.CLEANUP_CHECK.getInt() # Request run cache "info" cleaner every configured seconds. If config value is changed, it will be used at next reload
|
frecuency = GlobalConfig.CLEANUP_CHECK.getInt() # Request run cache "info" cleaner every configured seconds. If config value is changed, it will be used at next reload
|
||||||
friendly_name = 'User Service Info Cleaner'
|
friendly_name = 'User Service Info Cleaner'
|
||||||
|
|
||||||
def __init__(self, environment):
|
def __init__(self, environment):
|
||||||
super(UserServiceInfoItemsCleaner,self).__init__(environment)
|
super(UserServiceInfoItemsCleaner, self).__init__(environment)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
removeFrom = getSqlDatetime() - timedelta(seconds = GlobalConfig.KEEP_INFO_TIME.getInt(True))
|
removeFrom = getSqlDatetime() - timedelta(seconds=GlobalConfig.KEEP_INFO_TIME.getInt(True))
|
||||||
logger.debug('Removing information user services from {0}'.format(removeFrom))
|
logger.debug('Removing information user services from {0}'.format(removeFrom))
|
||||||
UserService.objects.select_for_update().filter(state__in=State.INFO_STATES, state_date__lt=removeFrom).delete()
|
UserService.objects.select_for_update().filter(state__in=State.INFO_STATES, state_date__lt=removeFrom).delete()
|
||||||
|
|
||||||
|
|
||||||
class UserServiceRemover(Job):
|
class UserServiceRemover(Job):
|
||||||
frecuency = GlobalConfig.REMOVAL_CHECK.getInt() # Request run cache "info" cleaner every configued seconds. If config value is changed, it will be used at next reload
|
frecuency = GlobalConfig.REMOVAL_CHECK.getInt() # Request run cache "info" cleaner every configued seconds. If config value is changed, it will be used at next reload
|
||||||
friendly_name = 'User Service Cleaner'
|
friendly_name = 'User Service Cleaner'
|
||||||
|
|
||||||
removeAtOnce = GlobalConfig.USER_SERVICE_CLEAN_NUMBER.getInt() # Same, it will work at reload
|
removeAtOnce = GlobalConfig.USER_SERVICE_CLEAN_NUMBER.getInt() # Same, it will work at reload
|
||||||
|
|
||||||
def __init__(self, environment):
|
def __init__(self, environment):
|
||||||
super(UserServiceRemover,self).__init__(environment)
|
super(UserServiceRemover, self).__init__(environment)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
removeFrom = getSqlDatetime() - timedelta(seconds=10) # We keep at least 30 seconds the machine before removing it, so we avoid connections errors
|
removeFrom = getSqlDatetime() - timedelta(seconds=10) # We keep at least 30 seconds the machine before removing it, so we avoid connections errors
|
||||||
removables = UserService.objects.filter(state=State.REMOVABLE, state_date__lt=removeFrom)[0:UserServiceRemover.removeAtOnce]
|
removables = UserService.objects.filter(state=State.REMOVABLE, state_date__lt=removeFrom)[0:UserServiceRemover.removeAtOnce]
|
||||||
for us in removables:
|
for us in removables:
|
||||||
UserServiceManager.manager().remove(us)
|
UserServiceManager.manager().remove(us)
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -32,26 +32,28 @@
|
|||||||
'''
|
'''
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
||||||
def __init__():
|
def __init__():
|
||||||
'''
|
'''
|
||||||
This imports all packages that are descendant of this package, and, after that,
|
This imports all packages that are descendant of this package, and, after that,
|
||||||
it register all subclases of service provider as
|
it register all subclases of service provider as
|
||||||
'''
|
'''
|
||||||
import os.path, pkgutil
|
import os.path
|
||||||
|
import pkgutil
|
||||||
import sys
|
import sys
|
||||||
from uds.core import jobs
|
from uds.core import jobs
|
||||||
from uds.core.managers.TaskManager import TaskManager
|
from uds.core.managers.TaskManager import TaskManager
|
||||||
|
|
||||||
# Dinamycally import children of this package.
|
# Dinamycally import children of this package.
|
||||||
pkgpath = os.path.dirname(sys.modules[__name__].__file__)
|
pkgpath = os.path.dirname(sys.modules[__name__].__file__)
|
||||||
for _, name, _ in pkgutil.iter_modules([pkgpath]):
|
for _, name, _ in pkgutil.iter_modules([pkgpath]):
|
||||||
__import__(name, globals(), locals(), [], -1)
|
__import__(name, globals(), locals(), [], -1)
|
||||||
|
|
||||||
p = jobs.Job
|
p = jobs.Job
|
||||||
# This is marked as error in IDE, but it's not (__subclasses__)
|
# This is marked as error in IDE, but it's not (__subclasses__)
|
||||||
for cls in p.__subclasses__():
|
for cls in p.__subclasses__():
|
||||||
# Limit to autoregister just workers jobs inside this module
|
# Limit to autoregister just workers jobs inside this module
|
||||||
if cls.__module__[0:16] == 'uds.core.workers':
|
if cls.__module__[0:16] == 'uds.core.workers':
|
||||||
TaskManager.registerJob(cls)
|
TaskManager.registerJob(cls)
|
||||||
|
|
||||||
__init__()
|
__init__()
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
@ -55,48 +55,48 @@ class TSNXTransport(Transport):
|
|||||||
typeName = _('NX Transport (tunneled)')
|
typeName = _('NX Transport (tunneled)')
|
||||||
typeType = 'TSNXTransport'
|
typeType = 'TSNXTransport'
|
||||||
typeDescription = _('NX Transport for tunneled connection')
|
typeDescription = _('NX Transport for tunneled connection')
|
||||||
iconFile = 'nx.png'
|
iconFile = 'nx.png'
|
||||||
needsJava = True # If this transport needs java for rendering
|
needsJava = True # If this transport needs java for rendering
|
||||||
supportedOss = ['Windows', 'Macintosh', 'Linux']
|
supportedOss = ['Windows', 'Macintosh', 'Linux']
|
||||||
|
|
||||||
tunnelServer = gui.TextField(label=_('Tunnel server'), order = 1, tooltip = _('IP or Hostname of tunnel server send to client device ("public" ip) and port. (use HOST:PORT format)'))
|
tunnelServer = gui.TextField(label=_('Tunnel server'), order=1, tooltip=_('IP or Hostname of tunnel server send to client device ("public" ip) and port. (use HOST:PORT format)'))
|
||||||
tunnelCheckServer = gui.TextField(label=_('Tunnel host check'), order = 2, tooltip = _('If not empty, this server will be used to check if service is running before assigning it to user. (use HOST:PORT format)'))
|
tunnelCheckServer = gui.TextField(label=_('Tunnel host check'), order=2, tooltip=_('If not empty, this server will be used to check if service is running before assigning it to user. (use HOST:PORT format)'))
|
||||||
|
|
||||||
useEmptyCreds = gui.CheckBoxField(label = _('Empty creds'), order = 3, tooltip = _('If checked, the credentials used to connect will be emtpy'))
|
useEmptyCreds = gui.CheckBoxField(label=_('Empty creds'), order=3, tooltip=_('If checked, the credentials used to connect will be emtpy'))
|
||||||
fixedName = gui.TextField(label=_('Username'), order = 4, tooltip = _('If not empty, this username will be always used as credential'))
|
fixedName = gui.TextField(label=_('Username'), order=4, tooltip=_('If not empty, this username will be always used as credential'))
|
||||||
fixedPassword = gui.PasswordField(label=_('Password'), order = 5, tooltip = _('If not empty, this password will be always used as credential'))
|
fixedPassword = gui.PasswordField(label=_('Password'), order=5, tooltip=_('If not empty, this password will be always used as credential'))
|
||||||
listenPort = gui.NumericField(label=_('Listen port'), length = 5, order = 6, tooltip = _('Listening port of NX (ssh) at client machine'), defvalue = '22')
|
listenPort = gui.NumericField(label=_('Listen port'), length=5, order=6, tooltip=_('Listening port of NX (ssh) at client machine'), defvalue='22')
|
||||||
connection = gui.ChoiceField(label=_('Connection'), order = 7, tooltip = _('Connection speed for this transport (quality)'), values = [
|
connection = gui.ChoiceField(label=_('Connection'), order=7, tooltip=_('Connection speed for this transport (quality)'), values=[
|
||||||
{'id' : 'modem', 'text' : 'modem'},
|
{'id' : 'modem', 'text' : 'modem'},
|
||||||
{'id' : 'isdn', 'text' : 'isdn'},
|
{'id' : 'isdn', 'text' : 'isdn'},
|
||||||
{'id' : 'adsl', 'text' : 'adsl'},
|
{'id' : 'adsl', 'text' : 'adsl'},
|
||||||
{'id' : 'wan', 'text' : 'wan'},
|
{'id' : 'wan', 'text' : 'wan'},
|
||||||
{'id' : 'lan', 'text' : 'lan'},
|
{'id' : 'lan', 'text' : 'lan'},
|
||||||
] )
|
])
|
||||||
session = gui.ChoiceField(label=_('Session'), order = 8, tooltip = _('Desktop session'), values = [
|
session = gui.ChoiceField(label=_('Session'), order=8, tooltip=_('Desktop session'), values=[
|
||||||
{'id' : 'gnome', 'text' : 'gnome'},
|
{'id' : 'gnome', 'text' : 'gnome'},
|
||||||
{'id' : 'kde', 'text' : 'kde'},
|
{'id' : 'kde', 'text' : 'kde'},
|
||||||
{'id' : 'cde', 'text' : 'cde'},
|
{'id' : 'cde', 'text' : 'cde'},
|
||||||
] )
|
])
|
||||||
cacheDisk = gui.ChoiceField(label=_('Disk Cache'), order = 9, tooltip = _('Cache size en Mb stored at disk'), values = [
|
cacheDisk = gui.ChoiceField(label=_('Disk Cache'), order=9, tooltip=_('Cache size en Mb stored at disk'), values=[
|
||||||
{'id' : '0', 'text' : '0 Mb'},
|
{'id' : '0', 'text' : '0 Mb'},
|
||||||
{'id' : '32', 'text' : '32 Mb'},
|
{'id' : '32', 'text' : '32 Mb'},
|
||||||
{'id' : '64', 'text' : '64 Mb'},
|
{'id' : '64', 'text' : '64 Mb'},
|
||||||
{'id' : '128', 'text' : '128 Mb'},
|
{'id' : '128', 'text' : '128 Mb'},
|
||||||
{'id' : '256', 'text' : '256 Mb'},
|
{'id' : '256', 'text' : '256 Mb'},
|
||||||
{'id' : '512', 'text' : '512 Mb'},
|
{'id' : '512', 'text' : '512 Mb'},
|
||||||
] )
|
])
|
||||||
cacheMem = gui.ChoiceField(label=_('Memory Cache'), order = 10, tooltip = _('Cache size en Mb keept at memory'), values = [
|
cacheMem = gui.ChoiceField(label=_('Memory Cache'), order=10, tooltip=_('Cache size en Mb keept at memory'), values=[
|
||||||
{'id' : '4', 'text' : '4 Mb'},
|
{'id' : '4', 'text' : '4 Mb'},
|
||||||
{'id' : '8', 'text' : '8 Mb'},
|
{'id' : '8', 'text' : '8 Mb'},
|
||||||
{'id' : '16', 'text' : '16 Mb'},
|
{'id' : '16', 'text' : '16 Mb'},
|
||||||
{'id' : '32', 'text' : '32 Mb'},
|
{'id' : '32', 'text' : '32 Mb'},
|
||||||
{'id' : '64', 'text' : '64 Mb'},
|
{'id' : '64', 'text' : '64 Mb'},
|
||||||
{'id' : '128', 'text' : '128 Mb'},
|
{'id' : '128', 'text' : '128 Mb'},
|
||||||
] )
|
])
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, environment, values = None):
|
def __init__(self, environment, values=None):
|
||||||
super(TSNXTransport, self).__init__(environment, values)
|
super(TSNXTransport, self).__init__(environment, values)
|
||||||
if values != None:
|
if values != None:
|
||||||
if values['tunnelServer'].find(':') == -1:
|
if values['tunnelServer'].find(':') == -1:
|
||||||
@ -122,26 +122,26 @@ class TSNXTransport(Transport):
|
|||||||
self._session = ''
|
self._session = ''
|
||||||
self._cacheDisk = ''
|
self._cacheDisk = ''
|
||||||
self._cacheMem = ''
|
self._cacheMem = ''
|
||||||
|
|
||||||
def marshal(self):
|
def marshal(self):
|
||||||
'''
|
'''
|
||||||
Serializes the transport data so we can store it in database
|
Serializes the transport data so we can store it in database
|
||||||
'''
|
'''
|
||||||
return str.join( '\t', [ 'v1', gui.boolToStr(self._useEmptyCreds), self._fixedName, self._fixedPassword, self._listenPort,
|
return str.join('\t', [ 'v1', gui.boolToStr(self._useEmptyCreds), self._fixedName, self._fixedPassword, self._listenPort,
|
||||||
self._connection, self._session, self._cacheDisk, self._cacheMem, self._tunnelServer, self._tunnelCheckServer ] )
|
self._connection, self._session, self._cacheDisk, self._cacheMem, self._tunnelServer, self._tunnelCheckServer ])
|
||||||
|
|
||||||
def unmarshal(self, string):
|
def unmarshal(self, string):
|
||||||
data = string.split('\t')
|
data = string.split('\t')
|
||||||
if data[0] == 'v1':
|
if data[0] == 'v1':
|
||||||
self._useEmptyCreds = gui.strToBool(data[1])
|
self._useEmptyCreds = gui.strToBool(data[1])
|
||||||
self._fixedName, self._fixedPassword, self._listenPort, self._connection, self._session, self._cacheDisk, self._cacheMem, self._tunnelServer, self._tunnelCheckServer = data[2:]
|
self._fixedName, self._fixedPassword, self._listenPort, self._connection, self._session, self._cacheDisk, self._cacheMem, self._tunnelServer, self._tunnelCheckServer = data[2:]
|
||||||
|
|
||||||
|
|
||||||
def valuesDict(self):
|
def valuesDict(self):
|
||||||
return { 'useEmptyCreds' : gui.boolToStr(self._useEmptyCreds), 'fixedName' : self._fixedName,
|
return { 'useEmptyCreds' : gui.boolToStr(self._useEmptyCreds), 'fixedName' : self._fixedName,
|
||||||
'fixedPassword' : self._fixedPassword, 'listenPort': self._listenPort,
|
'fixedPassword' : self._fixedPassword, 'listenPort': self._listenPort,
|
||||||
'connection' : self._connection, 'session' : self._session, 'cacheDisk' : self._cacheDisk,
|
'connection' : self._connection, 'session' : self._session, 'cacheDisk' : self._cacheDisk,
|
||||||
'cacheMem' : self._cacheMem, 'tunnelServer' : self._tunnelServer,
|
'cacheMem' : self._cacheMem, 'tunnelServer' : self._tunnelServer,
|
||||||
'tunnelCheckServer' : self._tunnelCheckServer }
|
'tunnelCheckServer' : self._tunnelCheckServer }
|
||||||
|
|
||||||
def isAvailableFor(self, ip):
|
def isAvailableFor(self, ip):
|
||||||
@ -159,11 +159,11 @@ class TSNXTransport(Transport):
|
|||||||
else:
|
else:
|
||||||
self.cache().put(ip, 'N', READY_CACHE_TIMEOUT)
|
self.cache().put(ip, 'N', READY_CACHE_TIMEOUT)
|
||||||
return ready == 'Y'
|
return ready == 'Y'
|
||||||
|
|
||||||
def renderForHtml(self, userService, idUserService, idTransport, ip, os, user, password):
|
def renderForHtml(self, userService, idUserService, idTransport, ip, os, user, password):
|
||||||
|
|
||||||
prefs = user.prefs('nx')
|
prefs = user.prefs('nx')
|
||||||
|
|
||||||
username = user.getUsernameForAuth()
|
username = user.getUsernameForAuth()
|
||||||
proc = username.split('@')
|
proc = username.split('@')
|
||||||
username = proc[0]
|
username = proc[0]
|
||||||
@ -172,33 +172,32 @@ class TSNXTransport(Transport):
|
|||||||
if self._fixedPassword is not '':
|
if self._fixedPassword is not '':
|
||||||
password = self._fixedPassword
|
password = self._fixedPassword
|
||||||
if self._useEmptyCreds is True:
|
if self._useEmptyCreds is True:
|
||||||
username, password = '',''
|
username, password = '', ''
|
||||||
|
|
||||||
width, height = CommonPrefs.getWidthHeight(prefs)
|
width, height = CommonPrefs.getWidthHeight(prefs)
|
||||||
cache = Cache('pam')
|
cache = Cache('pam')
|
||||||
|
|
||||||
|
|
||||||
tunuser = ''.join(random.choice(string.letters + string.digits) for i in xrange(12)) + ("%f" % time.time()).split('.')[1]
|
tunuser = ''.join(random.choice(string.letters + string.digits) for i in xrange(12)) + ("%f" % time.time()).split('.')[1]
|
||||||
tunpass = ''.join(random.choice(string.letters + string.digits) for i in xrange(12))
|
tunpass = ''.join(random.choice(string.letters + string.digits) for i in xrange(12))
|
||||||
cache.put(tunuser, tunpass, 60*10) # Credential valid for ten minutes, and for 1 use only
|
cache.put(tunuser, tunpass, 60 * 10) # Credential valid for ten minutes, and for 1 use only
|
||||||
|
|
||||||
sshHost, sshPort = self._tunnelServer.split(':')
|
sshHost, sshPort = self._tunnelServer.split(':')
|
||||||
|
|
||||||
logger.debug('Username generated: {0}, password: {1}'.format(tunuser, tunpass))
|
logger.debug('Username generated: {0}, password: {1}'.format(tunuser, tunpass))
|
||||||
tun = "{0} {1} {2} {3} {4} {5} {6}".format(tunuser, tunpass, sshHost, sshPort, ip, self._listenPort, '9')
|
tun = "{0} {1} {2} {3} {4} {5} {6}".format(tunuser, tunpass, sshHost, sshPort, ip, self._listenPort, '9')
|
||||||
|
|
||||||
# Extra data
|
# Extra data
|
||||||
extra = { 'width': width, 'height' : height,
|
extra = { 'width': width, 'height' : height,
|
||||||
'connection' : self._connection,
|
'connection' : self._connection,
|
||||||
'session' : self._session, 'cacheDisk': self._cacheDisk,
|
'session' : self._session, 'cacheDisk': self._cacheDisk,
|
||||||
'cacheMem' : self._cacheMem, 'tun' : tun }
|
'cacheMem' : self._cacheMem, 'tun' : tun }
|
||||||
|
|
||||||
# Fix username/password acording to os manager
|
# Fix username/password acording to os manager
|
||||||
username, password = userService.processUserPassword(username, password)
|
username, password = userService.processUserPassword(username, password)
|
||||||
|
|
||||||
return generateHtmlForNX(self, idUserService, idTransport, os, username, password, extra)
|
return generateHtmlForNX(self, idUserService, idTransport, os, username, password, extra)
|
||||||
|
|
||||||
def getHtmlComponent(self, theId, os, componentId):
|
def getHtmlComponent(self, theId, os, componentId):
|
||||||
# We use helper to keep this clean
|
# We use helper to keep this clean
|
||||||
return getHtmlComponent(self.__module__, componentId)
|
return getHtmlComponent(self.__module__, componentId)
|
||||||
|
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -32,6 +32,8 @@
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from uds.core.util.Config import Config
|
from uds.core.util.Config import Config
|
||||||
from uds.core.util import OsDetector
|
from uds.core.util import OsDetector
|
||||||
|
|
||||||
@ -48,16 +50,15 @@ def simpleScrambler(data):
|
|||||||
n = ord('M')
|
n = ord('M')
|
||||||
pos = 0
|
pos = 0
|
||||||
for c in data:
|
for c in data:
|
||||||
res.append( chr(ord(c) ^ n) )
|
res.append(chr(ord(c) ^ n))
|
||||||
n = n ^ pos
|
n = n ^ pos
|
||||||
pos = pos + 1
|
pos = pos + 1
|
||||||
return "".join(res).encode('hex')
|
return "".join(res).encode('hex')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def generateHtmlForNX(transport, idUserService, idTransport, os, user, password, extra):
|
def generateHtmlForNX(transport, idUserService, idTransport, os, user, password, extra):
|
||||||
isMac = os['OS'] == OsDetector.Macintosh
|
isMac = os['OS'] == OsDetector.Macintosh
|
||||||
applet = reverse('uds.web.views.transcomp', kwargs = { 'idTransport' : idTransport, 'componentId' : '1' })
|
applet = reverse('uds.web.views.transcomp', kwargs={'idTransport': idTransport, 'componentId': '1'})
|
||||||
# Gets the codebase, simply remove last char from applet
|
# Gets the codebase, simply remove last char from applet
|
||||||
codebase = applet[:-1]
|
codebase = applet[:-1]
|
||||||
# We generate the "data" parameter
|
# We generate the "data" parameter
|
||||||
@ -74,22 +75,22 @@ def generateHtmlForNX(transport, idUserService, idTransport, os, user, password,
|
|||||||
'tun:' + extra['tun'],
|
'tun:' + extra['tun'],
|
||||||
'is:' + idUserService
|
'is:' + idUserService
|
||||||
]
|
]
|
||||||
data = simpleScrambler( '\t'.join(data))
|
data = simpleScrambler('\t'.join(data))
|
||||||
if isMac is True:
|
if isMac is True:
|
||||||
msg = '<p>' + _('In order to use this transport, you need to install first OpenNX Client for mac') + '</p>'
|
msg = '<p>' + _('In order to use this transport, you need to install first OpenNX Client for mac') + '</p>'
|
||||||
msg += '<p>' + _('You can oibtain it from ') + '<a href="{0}">'.format(Config.section('NX').value('downloadUrlMACOS').get()) + _('OpenNx Website') + '</a></p>'
|
msg += '<p>' + _('You can oibtain it from ') + '<a href="{0}">'.format(Config.section('NX').value('downloadUrlMACOS').get()) + _('OpenNx Website') + '</a></p>'
|
||||||
else:
|
else:
|
||||||
msg = '<p>' + _('In order to use this transport, you need to install first Nomachine Nx Client version 3.5.x') + '</p>'
|
msg = '<p>' + _('In order to use this transport, you need to install first Nomachine Nx Client version 3.5.x') + '</p>'
|
||||||
msg +='<p>' + _('you can obtain it for your platform from') + '<a href="{0}">'.format(Config.section('NX').value('downloadUrl').get()) + _('nochamine web site') + '</a></p>'
|
msg += '<p>' + _('you can obtain it for your platform from') + '<a href="{0}">'.format(Config.section('NX').value('downloadUrl').get()) + _('nochamine web site') + '</a></p>'
|
||||||
|
|
||||||
res = '<div idTransport="applet"><applet code="NxTunTransportApplet.class" codebase="%s" archive="%s" width="165" height="22"><param name="data" value="%s"/><param name="permissions" value="all-permissions"/></applet></div>' % (codebase, '1', data )
|
res = '<div idTransport="applet"><applet code="NxTunTransportApplet.class" codebase="%s" archive="%s" width="165" height="22"><param name="data" value="%s"/><param name="permissions" value="all-permissions"/></applet></div>' % (codebase, '1', data)
|
||||||
res += '<div>' + msg + '</div>'
|
res += '<div>' + msg + '</div>'
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
def getHtmlComponent(module, componentId):
|
def getHtmlComponent(module, componentId):
|
||||||
dict = { '1' : ['nxtuntransport.jar', 'application/java-archive' ], '2' : ['launcher.jar', 'application/java-archive']}
|
dict = { '1' : ['nxtuntransport.jar', 'application/java-archive' ], '2' : ['launcher.jar', 'application/java-archive']}
|
||||||
|
|
||||||
if dict.has_key(componentId) == False:
|
if dict.has_key(componentId) == False:
|
||||||
return ['text/plain', 'no component']
|
return ['text/plain', 'no component']
|
||||||
fname = os.path.dirname(sys.modules[module].__file__) + '/applet/' + dict[componentId][0]
|
fname = os.path.dirname(sys.modules[module].__file__) + '/applet/' + dict[componentId][0]
|
||||||
@ -98,4 +99,4 @@ def getHtmlComponent(module, componentId):
|
|||||||
f = open(fname, 'rb')
|
f = open(fname, 'rb')
|
||||||
data = f.read()
|
data = f.read()
|
||||||
f.close()
|
f.close()
|
||||||
return [ dict[componentId][1], data ]
|
return [ dict[componentId][1], data ]
|
||||||
|
@ -4,33 +4,34 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
from uds.models import DeployedService, Service, OSManager, Transport, State, Group
|
from uds.models import DeployedService, Service, OSManager, Transport, State, Group
|
||||||
from ..auths.AdminAuth import needs_credentials
|
from ..auths.AdminAuth import needs_credentials
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError
|
||||||
@ -105,17 +106,17 @@ def getDeployedServices(credentials, all_):
|
|||||||
|
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
def getDeployedService(credentials, id):
|
def getDeployedService(credentials, id_):
|
||||||
'''
|
'''
|
||||||
Returns the available deployed services
|
Returns the available deployed services
|
||||||
'''
|
'''
|
||||||
logger.debug('Returning list of deployed services')
|
logger.debug('Returning list of deployed services')
|
||||||
ds = DeployedService.objects.get(pk=id)
|
ds = DeployedService.objects.get(pk=id_)
|
||||||
if ds.state == State.ACTIVE:
|
if ds.state == State.ACTIVE:
|
||||||
return dictFromDeployedService(ds)
|
return dictFromDeployedService(ds)
|
||||||
raise InsertException(_('Deployed Service does not exists'))
|
raise InsertException(_('Deployed Service does not exists'))
|
||||||
|
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
def createDeployedService(credentials, deployedService):
|
def createDeployedService(credentials, deployedService):
|
||||||
'''
|
'''
|
||||||
@ -134,9 +135,9 @@ def createDeployedService(credentials, deployedService):
|
|||||||
osManager = None
|
osManager = None
|
||||||
if serviceInstance.needsManager:
|
if serviceInstance.needsManager:
|
||||||
osManager = OSManager.objects.get(pk=deployedService['idOsManager'])
|
osManager = OSManager.objects.get(pk=deployedService['idOsManager'])
|
||||||
dps = DeployedService.objects.create(name = deployedService['name'], comments = deployedService['comments'], service = service,
|
dps = DeployedService.objects.create(name=deployedService['name'], comments=deployedService['comments'], service=service,
|
||||||
osmanager = osManager, state = State.ACTIVE, initial_srvs = initialServices, cache_l1_srvs = cacheL1,
|
osmanager=osManager, state=State.ACTIVE, initial_srvs=initialServices, cache_l1_srvs=cacheL1,
|
||||||
cache_l2_srvs = cacheL2, max_srvs = maxServices, current_pub_revision = 1)
|
cache_l2_srvs=cacheL2, max_srvs=maxServices, current_pub_revision=1)
|
||||||
# Now we add transports
|
# Now we add transports
|
||||||
addTransportsToDeployedService(dps, deployedService['transports'])
|
addTransportsToDeployedService(dps, deployedService['transports'])
|
||||||
except IntegrityError as e:
|
except IntegrityError as e:
|
||||||
@ -146,7 +147,8 @@ def createDeployedService(credentials, deployedService):
|
|||||||
logger.error("Exception adding deployed service {0}".format(deployedService))
|
logger.error("Exception adding deployed service {0}".format(deployedService))
|
||||||
raise InsertException(str(e))
|
raise InsertException(str(e))
|
||||||
return str(dps.id)
|
return str(dps.id)
|
||||||
|
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
def modifyDeployedService(credentials, deployedService):
|
def modifyDeployedService(credentials, deployedService):
|
||||||
'''
|
'''
|
||||||
@ -162,7 +164,7 @@ def modifyDeployedService(credentials, deployedService):
|
|||||||
maxServices = deployedService['maxServices']
|
maxServices = deployedService['maxServices']
|
||||||
if serviceInstance.usesCache == False:
|
if serviceInstance.usesCache == False:
|
||||||
initialServices = cacheL1 = cacheL2 = maxServices = 0
|
initialServices = cacheL1 = cacheL2 = maxServices = 0
|
||||||
|
|
||||||
dps.name = deployedService['name']
|
dps.name = deployedService['name']
|
||||||
dps.comments = deployedService['comments']
|
dps.comments = deployedService['comments']
|
||||||
dps.initial_srvs = initialServices
|
dps.initial_srvs = initialServices
|
||||||
@ -183,6 +185,7 @@ def modifyDeployedService(credentials, deployedService):
|
|||||||
raise InsertException(str(e))
|
raise InsertException(str(e))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
def getGroupsAssignedToDeployedService(credentials, deployedServiceId):
|
def getGroupsAssignedToDeployedService(credentials, deployedServiceId):
|
||||||
'''
|
'''
|
||||||
@ -199,6 +202,7 @@ def getGroupsAssignedToDeployedService(credentials, deployedServiceId):
|
|||||||
raise InsertException(_('Deployed Service does not exists'))
|
raise InsertException(_('Deployed Service does not exists'))
|
||||||
return grps
|
return grps
|
||||||
|
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
def assignGroupToDeployedService(credentials, deployedServiceId, groupId):
|
def assignGroupToDeployedService(credentials, deployedServiceId, groupId):
|
||||||
'''
|
'''
|
||||||
@ -215,6 +219,7 @@ def assignGroupToDeployedService(credentials, deployedServiceId, groupId):
|
|||||||
raise InsertException(_('Deployed Service does not exists'))
|
raise InsertException(_('Deployed Service does not exists'))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
def removeGroupsFromDeployedService(credentials, deployedServiceId, groupIds):
|
def removeGroupsFromDeployedService(credentials, deployedServiceId, groupIds):
|
||||||
'''
|
'''
|
||||||
@ -229,6 +234,7 @@ def removeGroupsFromDeployedService(credentials, deployedServiceId, groupIds):
|
|||||||
raise InsertException(_('Deployed Service does not exists'))
|
raise InsertException(_('Deployed Service does not exists'))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
def getTransportsAssignedToDeployedService(credentias, idDS):
|
def getTransportsAssignedToDeployedService(credentias, idDS):
|
||||||
'''
|
'''
|
||||||
@ -236,13 +242,14 @@ def getTransportsAssignedToDeployedService(credentias, idDS):
|
|||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
ds = DeployedService.objects.get(id=idDS)
|
ds = DeployedService.objects.get(id=idDS)
|
||||||
return [ dictFromTransport(t) for t in ds.transports.all() ]
|
return [dictFromTransport(t) for t in ds.transports.all()]
|
||||||
except DeployedService.DoesNotExist:
|
except DeployedService.DoesNotExist:
|
||||||
raise FindException(_('Can\'t find deployed service'))
|
raise FindException(_('Can\'t find deployed service'))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception("getTransportsForDeployedService: ")
|
logger.exception("getTransportsForDeployedService: ")
|
||||||
raise FindException(str(e))
|
raise FindException(str(e))
|
||||||
|
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
def assignTransportToDeployedService(credentials, deployedServiceId, transportId):
|
def assignTransportToDeployedService(credentials, deployedServiceId, transportId):
|
||||||
logger.debug('Assigning transport {0} to service {1}'.format(transportId, deployedServiceId))
|
logger.debug('Assigning transport {0} to service {1}'.format(transportId, deployedServiceId))
|
||||||
@ -254,9 +261,10 @@ def assignTransportToDeployedService(credentials, deployedServiceId, transportId
|
|||||||
raise InsertException(_('Transport does not exists'))
|
raise InsertException(_('Transport does not exists'))
|
||||||
except DeployedService.DoesNotExist:
|
except DeployedService.DoesNotExist:
|
||||||
raise InsertException(_('Deployed Service does not exists'))
|
raise InsertException(_('Deployed Service does not exists'))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
def removeTransportFromDeployedService(credentials, deployedServiceId, transportIds):
|
def removeTransportFromDeployedService(credentials, deployedServiceId, transportIds):
|
||||||
'''
|
'''
|
||||||
@ -270,7 +278,7 @@ def removeTransportFromDeployedService(credentials, deployedServiceId, transport
|
|||||||
raise InsertException(_('Deployed Service does not exists'))
|
raise InsertException(_('Deployed Service does not exists'))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
def removeDeployedService(credentials, deployedServiceId):
|
def removeDeployedService(credentials, deployedServiceId):
|
||||||
'''
|
'''
|
||||||
@ -285,6 +293,7 @@ def removeDeployedService(credentials, deployedServiceId):
|
|||||||
raise InsertException(_('Deployed service does not exists'))
|
raise InsertException(_('Deployed service does not exists'))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
# Registers XML RPC Methods
|
# Registers XML RPC Methods
|
||||||
def registerDeployedServicesFunctions(dispatcher):
|
def registerDeployedServicesFunctions(dispatcher):
|
||||||
dispatcher.register_function(getDeployedServices, 'getDeployedServices')
|
dispatcher.register_function(getDeployedServices, 'getDeployedServices')
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer.
|
# this list of conditions and the following disclaimer.
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
# and/or other materials provided with the distribution.
|
# and/or other materials provided with the distribution.
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -32,7 +32,7 @@
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError
|
||||||
from uds.models import Provider, Service
|
from uds.models import Provider, Service
|
||||||
from uds.xmlrpc.util.Helpers import dictFromData
|
from uds.xmlrpc.util.Helpers import dictFromData
|
||||||
from uds.xmlrpc.auths.AdminAuth import needs_credentials
|
from uds.xmlrpc.auths.AdminAuth import needs_credentials
|
||||||
@ -43,13 +43,14 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def infoDictFromServiceInstance(service):
|
def infoDictFromServiceInstance(service):
|
||||||
if service is not None:
|
if service is not None:
|
||||||
needsPublication = service.publicationType is not None
|
needsPublication = service.publicationType is not None
|
||||||
maxDeployed = service.maxDeployed
|
maxDeployed = service.maxDeployed
|
||||||
usesCache = service.usesCache
|
usesCache = service.usesCache
|
||||||
usesCache_L2 = service.usesCache_L2
|
usesCache_L2 = service.usesCache_L2
|
||||||
cacheTooltip = _(service.cacheTooltip)
|
cacheTooltip = _(service.cacheTooltip)
|
||||||
cacheTooltip_L2 = _(service.cacheTooltip_L2)
|
cacheTooltip_L2 = _(service.cacheTooltip_L2)
|
||||||
needsManager = service.needsManager
|
needsManager = service.needsManager
|
||||||
mustAssignManually = service.mustAssignManually
|
mustAssignManually = service.mustAssignManually
|
||||||
@ -59,26 +60,28 @@ def infoDictFromServiceInstance(service):
|
|||||||
maxDeployed = 0
|
maxDeployed = 0
|
||||||
usesCache = False
|
usesCache = False
|
||||||
usesCache_L2 = False
|
usesCache_L2 = False
|
||||||
cacheTooltip = ''
|
cacheTooltip = ''
|
||||||
cacheTooltip_L2 = ''
|
cacheTooltip_L2 = ''
|
||||||
needsManager = False
|
needsManager = False
|
||||||
mustAssignManually = False
|
mustAssignManually = False
|
||||||
typeName = ''
|
typeName = ''
|
||||||
|
|
||||||
|
|
||||||
return { 'needsPublication' : needsPublication, 'maxDeployed' : maxDeployed,
|
return { 'needsPublication' : needsPublication, 'maxDeployed' : maxDeployed,
|
||||||
'usesCache' : usesCache, 'usesCacheL2' : usesCache_L2,
|
'usesCache' : usesCache, 'usesCacheL2' : usesCache_L2,
|
||||||
'cacheTooltip' : cacheTooltip, 'cacheTooltipL2' : cacheTooltip_L2,
|
'cacheTooltip' : cacheTooltip, 'cacheTooltipL2' : cacheTooltip_L2,
|
||||||
'needsManager' : needsManager, 'mustAssignManually' : mustAssignManually,
|
'needsManager' : needsManager, 'mustAssignManually' : mustAssignManually,
|
||||||
'typeName' : typeName
|
'typeName' : typeName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def dictFromService(serv):
|
def dictFromService(serv):
|
||||||
service = serv.getInstance()
|
service = serv.getInstance()
|
||||||
return { 'idParent' : str(serv.provider_id), 'id' : str(serv.id), 'name' : serv.name,
|
return { 'idParent' : str(serv.provider_id), 'id' : str(serv.id), 'name' : serv.name,
|
||||||
'comments' : serv.comments, 'type' : serv.data_type, 'typeName' : _(service.name()), 'info' : infoDictFromServiceInstance(service)
|
'comments' : serv.comments, 'type' : serv.data_type, 'typeName' : _(service.name()), 'info' : infoDictFromServiceInstance(service)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
def getServices(credentials, idParent):
|
def getServices(credentials, idParent):
|
||||||
'''
|
'''
|
||||||
@ -94,6 +97,7 @@ def getServices(credentials, idParent):
|
|||||||
logger.debug(e)
|
logger.debug(e)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
def getAllServices(credentials):
|
def getAllServices(credentials):
|
||||||
'''
|
'''
|
||||||
@ -109,6 +113,7 @@ def getAllServices(credentials):
|
|||||||
logger.exception('getAllServices')
|
logger.exception('getAllServices')
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
def getServiceGui(credentials, idParent, type):
|
def getServiceGui(credentials, idParent, type):
|
||||||
'''
|
'''
|
||||||
@ -118,12 +123,13 @@ def getServiceGui(credentials, idParent, type):
|
|||||||
logger.debug('getServiceGui parameters: {0}, {1}'.format(idParent, type))
|
logger.debug('getServiceGui parameters: {0}, {1}'.format(idParent, type))
|
||||||
provider = Provider.objects.get(id=idParent).getInstance()
|
provider = Provider.objects.get(id=idParent).getInstance()
|
||||||
serviceType = provider.getServiceByType(type)
|
serviceType = provider.getServiceByType(type)
|
||||||
service = serviceType( Environment.getTempEnv(), provider) # Instantiate it so it has the opportunity to alter gui description based on parent
|
service = serviceType(Environment.getTempEnv(), provider) # Instantiate it so it has the opportunity to alter gui description based on parent
|
||||||
return service.guiDescription(service)
|
return service.guiDescription(service)
|
||||||
except:
|
except:
|
||||||
logger.exception('Exception at getServiceGui')
|
logger.exception('Exception at getServiceGui')
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
def getService(credentials, id):
|
def getService(credentials, id):
|
||||||
'''
|
'''
|
||||||
@ -131,7 +137,7 @@ def getService(credentials, id):
|
|||||||
'''
|
'''
|
||||||
logger.debug('getService parameters: {0}'.format(id))
|
logger.debug('getService parameters: {0}'.format(id))
|
||||||
srv = Service.objects.get(id=id)
|
srv = Service.objects.get(id=id)
|
||||||
res = [
|
res = [
|
||||||
{ 'name' : 'name', 'value' : srv.name },
|
{ 'name' : 'name', 'value' : srv.name },
|
||||||
{ 'name' : 'comments', 'value' : srv.comments },
|
{ 'name' : 'comments', 'value' : srv.comments },
|
||||||
]
|
]
|
||||||
@ -144,6 +150,7 @@ def getService(credentials, id):
|
|||||||
logger.debug('getService res: {0}'.format(res))
|
logger.debug('getService res: {0}'.format(res))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
def createService(credentials, idParent, type, data):
|
def createService(credentials, idParent, type, data):
|
||||||
'''
|
'''
|
||||||
@ -154,14 +161,14 @@ def createService(credentials, idParent, type, data):
|
|||||||
provider = Provider.objects.get(id=idParent)
|
provider = Provider.objects.get(id=idParent)
|
||||||
dic = dictFromData(data)
|
dic = dictFromData(data)
|
||||||
try:
|
try:
|
||||||
srv = provider.services.create(name = dic['name'], comments = dic['comments'], data_type = type)
|
srv = provider.services.create(name=dic['name'], comments=dic['comments'], data_type=type)
|
||||||
# Invoque serialization with correct environment
|
# Invoque serialization with correct environment
|
||||||
srv.data = srv.getInstance(dic).serialize()
|
srv.data = srv.getInstance(dic).serialize()
|
||||||
srv.save()
|
srv.save()
|
||||||
except services.Service.ValidationException as e:
|
except services.Service.ValidationException as e:
|
||||||
srv.delete()
|
srv.delete()
|
||||||
raise ValidationException(str(e))
|
raise ValidationException(str(e))
|
||||||
except IntegrityError: # Must be exception at creation
|
except IntegrityError: # Must be exception at creation
|
||||||
raise InsertException(_('Name %s already exists') % (dic['name']))
|
raise InsertException(_('Name %s already exists') % (dic['name']))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception('Unexpected exception')
|
logger.exception('Unexpected exception')
|
||||||
@ -185,12 +192,12 @@ def modifyService(credentials, id, data):
|
|||||||
serv.save()
|
serv.save()
|
||||||
except services.Service.ValidationException as e:
|
except services.Service.ValidationException as e:
|
||||||
raise ValidationException(str(e))
|
raise ValidationException(str(e))
|
||||||
except IntegrityError: # Must be exception at creation
|
except IntegrityError: # Must be exception at creation
|
||||||
raise InsertException(_('Name %s already exists') % (dic['name']))
|
raise InsertException(_('Name %s already exists') % (dic['name']))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception('Unexpected exception')
|
logger.exception('Unexpected exception')
|
||||||
raise ValidationException(str(e))
|
raise ValidationException(str(e))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@needs_credentials
|
@needs_credentials
|
||||||
|
Loading…
Reference in New Issue
Block a user