forked from shaba/openuds
BIG work on pep8 adaption (easier to read, easier to maintain, etc..)
This commit is contained in:
parent
06ff8e32be
commit
ddbcc5aec4
@ -150,8 +150,11 @@ encoding//src/uds/management/commands/taskManager.py=utf-8
|
||||
encoding//src/uds/management/commands/taskManager_enterprise.py=utf-8
|
||||
encoding//src/uds/migrations/0001_initial.py=utf-8
|
||||
encoding//src/uds/migrations/0002_auto__del_unique_userpreference_name_module.py=utf-8
|
||||
encoding//src/uds/migrations/0003_auto__del_field_deployedservice_authenticator.py=utf-8
|
||||
encoding//src/uds/migrations/0004_auto__add_field_deployedservice_state_date.py=utf-8
|
||||
encoding//src/uds/migrations/0005_auto__add_field_config_crypt.py=utf-8
|
||||
encoding//src/uds/migrations/0006_auto__chg_field_storage_data.py=utf-8
|
||||
encoding//src/uds/migrations/0007_auto__add_field_config_long.py=utf-8
|
||||
encoding//src/uds/migrations/0008_auto__add_userservicelog__add_field_userservice_src_hostname__add_fiel.py=utf-8
|
||||
encoding//src/uds/migrations/0009_auto__del_userservicelog__add_log.py=utf-8
|
||||
encoding//src/uds/migrations/0010_auto__add_field_log_owner_type.py=utf-8
|
||||
@ -159,6 +162,7 @@ encoding//src/uds/migrations/0011_auto__add_statscounters__add_statsevents__chg_
|
||||
encoding//src/uds/migrations/0012_auto__add_field_authenticator_small_name.py=utf-8
|
||||
encoding//src/uds/migrations/0013_auto__add_field_group_is_meta__add_field_uniqueid_stamp.py=utf-8
|
||||
encoding//src/uds/migrations/0014_auto__add_field_network_net_string.py=utf-8
|
||||
encoding//src/uds/migrations/0015_auto__add_field_user_parent.py=utf-8
|
||||
encoding//src/uds/migrations/0016_auto__add_field_userservice_cluster_node.py=utf-8
|
||||
encoding//src/uds/migrations/0017_change_tables.py=utf-8
|
||||
encoding//src/uds/migrations/0018_security_config.py=utf-8
|
||||
|
@ -3,27 +3,27 @@
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@ -44,28 +44,29 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__all__ = [ str(v) for v in ['Handler', 'Dispatcher'] ]
|
||||
__all__ = [str(v) for v in ['Handler', 'Dispatcher']]
|
||||
|
||||
AUTH_TOKEN_HEADER = 'X-Auth-Token'
|
||||
|
||||
|
||||
class Dispatcher(View):
|
||||
services = { '' : None } # Will include a default /rest handler, but rigth now this will be fine
|
||||
|
||||
services = {'': None} # Will include a default /rest handler, but rigth now this will be fine
|
||||
|
||||
@method_decorator(csrf_exempt)
|
||||
def dispatch(self, request, **kwargs):
|
||||
import processors
|
||||
|
||||
|
||||
# Remove session, so response middelwares do nothing with this
|
||||
del request.session
|
||||
# Now we extract method and posible variables from path
|
||||
path = kwargs['arguments'].split('/')
|
||||
del kwargs['arguments']
|
||||
|
||||
|
||||
# Transverse service nodes too look for path
|
||||
service = Dispatcher.services
|
||||
full_path = []
|
||||
# Last element will be
|
||||
do_break = False
|
||||
do_break = False
|
||||
cls = None
|
||||
while len(path) > 0 and not do_break:
|
||||
# .json, .xml, ... will break path recursion
|
||||
@ -84,8 +85,7 @@ class Dispatcher(View):
|
||||
cls = service['']
|
||||
if cls is None:
|
||||
return http.HttpResponseNotFound('method not found')
|
||||
|
||||
|
||||
|
||||
# Guess content type from content type header (post) or ".xxx" to method
|
||||
try:
|
||||
p = full_path.split('.')
|
||||
@ -93,13 +93,12 @@ class Dispatcher(View):
|
||||
except:
|
||||
# TODO: Extract processor from accept and/or content type?
|
||||
processor = processors.available_processors_mime_dict.get(request.META.get('CONTENT_TYPE', 'json'), processors.default_processor)(request)
|
||||
|
||||
|
||||
# Obtain method to be invoked
|
||||
http_method = request.method.lower()
|
||||
|
||||
|
||||
args = path
|
||||
|
||||
|
||||
# Inspect
|
||||
lang = None
|
||||
if len(args) > 0:
|
||||
@ -113,12 +112,12 @@ class Dispatcher(View):
|
||||
# Instantiate method handler and locate http_method dispatcher
|
||||
try:
|
||||
handler = cls(request, full_path, http_method, processor.processParameters(), *args, **kwargs)
|
||||
# If no lang on request, try to get the one from
|
||||
# If no lang on request, try to get the one from
|
||||
if lang is None:
|
||||
activate(handler.getValue('locale'))
|
||||
else:
|
||||
handler.setValue('locale', lang) # Update Locale if request had one
|
||||
|
||||
handler.setValue('locale', lang) # Update Locale if request had one
|
||||
|
||||
operation = getattr(handler, http_method)
|
||||
except processors.ParametersException as e:
|
||||
return http.HttpResponseServerError('Invalid parameters invoking {0}: {1}'.format(path[0], e))
|
||||
@ -134,15 +133,14 @@ class Dispatcher(View):
|
||||
logger.exception('error accessing attribute')
|
||||
logger.debug('Getting attribute {0} for {1}'.format(http_method, full_path))
|
||||
return http.HttpResponseServerError('Unexcepected error')
|
||||
|
||||
|
||||
|
||||
# Invokes the handler's operation, add headers to response and returns
|
||||
try:
|
||||
start = time.time();
|
||||
start = time.time()
|
||||
response = operation()
|
||||
logger.debug('Execution time for method: {0}'.format(time.time() - start))
|
||||
|
||||
if not handler.raw: # Raw handlers will return an HttpResponse Object
|
||||
|
||||
if not handler.raw: # Raw handlers will return an HttpResponse Object
|
||||
start = time.time()
|
||||
response = processor.getResponse(response)
|
||||
logger.debug('Execution time for encoding: {0}'.format(time.time() - start))
|
||||
@ -165,8 +163,8 @@ class Dispatcher(View):
|
||||
|
||||
@staticmethod
|
||||
def registerSubclasses(classes):
|
||||
for cls in classes:
|
||||
if len(cls.__subclasses__()) == 0: # Only classes that has not been inherited will be registered as Handlers
|
||||
for cls in classes:
|
||||
if len(cls.__subclasses__()) == 0: # Only classes that has not been inherited will be registered as Handlers
|
||||
logger.debug('Found class {0}'.format(cls))
|
||||
if cls.name is None:
|
||||
name = cls.__name__.lower()
|
||||
@ -177,15 +175,15 @@ class Dispatcher(View):
|
||||
if cls.path is not None:
|
||||
for k in cls.path.split('/'):
|
||||
if service_node.get(k) is None:
|
||||
service_node[k] = { '' : None }
|
||||
service_node[k] = {'': None}
|
||||
service_node = service_node[k]
|
||||
if service_node.get(name) is None:
|
||||
service_node[name] = { '' : None }
|
||||
|
||||
service_node[name] = {'': None}
|
||||
|
||||
service_node[name][''] = cls
|
||||
else:
|
||||
Dispatcher.registerSubclasses(cls.__subclasses__())
|
||||
|
||||
|
||||
# Initializes the dispatchers
|
||||
@staticmethod
|
||||
def initialize():
|
||||
@ -193,18 +191,19 @@ class Dispatcher(View):
|
||||
This imports all packages that are descendant of this package, and, after that,
|
||||
it register all subclases of Handler. (In fact, it looks for packages inside "methods" package, child of this)
|
||||
'''
|
||||
import os.path, pkgutil
|
||||
import os.path
|
||||
import pkgutil
|
||||
import sys
|
||||
|
||||
|
||||
logger.debug('Loading Handlers')
|
||||
|
||||
|
||||
# Dinamycally import children of this package. The __init__.py files must register, if needed, inside ServiceProviderFactory
|
||||
package = 'methods'
|
||||
|
||||
|
||||
pkgpath = os.path.join(os.path.dirname(sys.modules[__name__].__file__), package)
|
||||
for _, name, _ in pkgutil.iter_modules([pkgpath]):
|
||||
__import__(__name__ + '.' + package + '.' + name, globals(), locals(), [], -1)
|
||||
|
||||
__import__(__name__ + '.' + package + '.' + name, globals(), locals(), [], -1)
|
||||
|
||||
Dispatcher.registerSubclasses(Handler.__subclasses__()) # @UndefinedVariable
|
||||
|
||||
|
||||
Dispatcher.initialize()
|
||||
|
@ -4,33 +4,34 @@
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.contrib.sessions.backends.db import SessionStore
|
||||
from django.conf import settings
|
||||
|
||||
@ -42,38 +43,44 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
AUTH_TOKEN_HEADER = 'HTTP_X_AUTH_TOKEN'
|
||||
|
||||
|
||||
class HandlerError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class NotFound(HandlerError):
|
||||
pass
|
||||
|
||||
|
||||
class AccessDenied(HandlerError):
|
||||
pass
|
||||
|
||||
|
||||
class RequestError(HandlerError):
|
||||
pass
|
||||
|
||||
|
||||
class ResponseError(HandlerError):
|
||||
pass
|
||||
|
||||
|
||||
class Handler(object):
|
||||
raw = False # If true, Handler will return directly an HttpResponse Object
|
||||
name = None # If name is not used, name will be the class name in lower case
|
||||
path = None # Path for this method, so we can do /auth/login, /auth/logout, /auth/auths in a simple way
|
||||
authenticated = True # By default, all handlers needs authentication
|
||||
needs_admin = False # By default, the methods will be accessible by anyone if nothine else indicated
|
||||
needs_staff = False # By default, staff
|
||||
|
||||
raw = False # If true, Handler will return directly an HttpResponse Object
|
||||
name = None # If name is not used, name will be the class name in lower case
|
||||
path = None # Path for this method, so we can do /auth/login, /auth/logout, /auth/auths in a simple way
|
||||
authenticated = True # By default, all handlers needs authentication
|
||||
needs_admin = False # By default, the methods will be accessible by anyone if nothine else indicated
|
||||
needs_staff = False # By default, staff
|
||||
|
||||
# method names: 'get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'
|
||||
def __init__(self, request, path, operation, params, *args, **kwargs):
|
||||
|
||||
|
||||
if self.needs_admin:
|
||||
self.authenticated = True # If needs_admin, must also be authenticated
|
||||
|
||||
self.authenticated = True # If needs_admin, must also be authenticated
|
||||
|
||||
if self.needs_staff:
|
||||
self.authenticated = True # Same for staff members
|
||||
|
||||
self.authenticated = True # Same for staff members
|
||||
|
||||
self._request = request
|
||||
self._path = path
|
||||
self._operation = operation
|
||||
@ -82,54 +89,57 @@ class Handler(object):
|
||||
self._kwargs = kwargs
|
||||
self._headers = {}
|
||||
self._authToken = None
|
||||
if self.authenticated: # Only retrieve auth related data on authenticated handlers
|
||||
if self.authenticated: # Only retrieve auth related data on authenticated handlers
|
||||
try:
|
||||
self._authToken = self._request.META.get(AUTH_TOKEN_HEADER, '')
|
||||
self._session = SessionStore(session_key = self._authToken)
|
||||
if not self._session.has_key('REST'):
|
||||
raise Exception() # No valid session, so auth_token is also invalid
|
||||
self._session = SessionStore(session_key=self._authToken)
|
||||
if 'REST' not in self._session:
|
||||
raise Exception() # No valid session, so auth_token is also invalid
|
||||
except:
|
||||
self._authToken = None
|
||||
self._session = None
|
||||
|
||||
|
||||
if self._authToken is None:
|
||||
raise AccessDenied()
|
||||
|
||||
|
||||
if self.needs_admin and not self.getValue('is_admin'):
|
||||
raise AccessDenied()
|
||||
|
||||
|
||||
if self.needs_staff and not self.getValue('staff_member'):
|
||||
raise AccessDenied()
|
||||
|
||||
|
||||
def headers(self):
|
||||
return self._headers
|
||||
|
||||
|
||||
def header(self, header_):
|
||||
return self._headers.get(header_)
|
||||
|
||||
|
||||
def addHeader(self, header, value):
|
||||
self._headers[header] = value
|
||||
|
||||
|
||||
def removeHeader(self, header):
|
||||
try:
|
||||
del self._headers[header]
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
# Auth related
|
||||
def getAuthToken(self):
|
||||
return self._authToken
|
||||
|
||||
|
||||
@staticmethod
|
||||
def storeSessionAuthdata(session, id_auth, username, locale, is_admin, staff_member):
|
||||
if is_admin:
|
||||
staff_member = True # Make admins also staff members :-)
|
||||
|
||||
session['REST'] = { 'auth': id_auth, 'username': username,
|
||||
'locale': locale, 'is_admin': is_admin,
|
||||
'staff_member': staff_member }
|
||||
|
||||
|
||||
staff_member = True # Make admins also staff members :-)
|
||||
|
||||
session['REST'] = {
|
||||
'auth': id_auth,
|
||||
'username': username,
|
||||
'locale': locale,
|
||||
'is_admin': is_admin,
|
||||
'staff_member': staff_member
|
||||
}
|
||||
|
||||
def genAuthToken(self, id_auth, username, locale, is_admin, staf_member):
|
||||
session = SessionStore()
|
||||
session.set_expiry(GlobalConfig.ADMIN_IDLE_TIME.getInt())
|
||||
@ -138,20 +148,20 @@ class Handler(object):
|
||||
self._authToken = session.session_key
|
||||
self._session = session
|
||||
return self._authToken
|
||||
|
||||
|
||||
def cleanAuthToken(self):
|
||||
self._authToken = None
|
||||
if self._session:
|
||||
self._session.delete()
|
||||
self._session = None
|
||||
|
||||
|
||||
# Session related (from auth token)
|
||||
def getValue(self, key):
|
||||
try:
|
||||
return self._session['REST'].get(key)
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def setValue(self, key, value):
|
||||
try:
|
||||
self._session['REST'][key] = value
|
||||
@ -159,9 +169,9 @@ class Handler(object):
|
||||
self._session.save()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def is_admin(self):
|
||||
return self.getValue('is_admin') and True or False
|
||||
|
||||
|
||||
def is_staff_member(self):
|
||||
return self.getValue('staff_member') and True or False
|
||||
|
@ -4,27 +4,27 @@
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@ -41,10 +41,11 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# Enclosed methods under /auth path
|
||||
|
||||
|
||||
class Cache(Handler):
|
||||
authenticated = True # Public method
|
||||
needs_staff = True #
|
||||
|
||||
authenticated = True
|
||||
needs_staff = True
|
||||
|
||||
def get(self):
|
||||
'''
|
||||
This login uses parameters to generate auth token
|
||||
@ -61,14 +62,14 @@ class Cache(Handler):
|
||||
on success: { 'result': 'ok', 'auth': [auth_code] }
|
||||
on error: { 'result: 'error', 'error': [error string] }
|
||||
'''
|
||||
|
||||
|
||||
logger.debug('Params: {0}'.format(self._params))
|
||||
if len(self._args) == 0:
|
||||
return {}
|
||||
|
||||
|
||||
if len(self._args) != 1:
|
||||
raise RequestError('Invalid Request')
|
||||
|
||||
|
||||
|
||||
|
||||
uCache.purge()
|
||||
return 'done'
|
||||
|
@ -4,27 +4,27 @@
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@ -42,26 +42,30 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# Enclosed methods under /auth path
|
||||
|
||||
|
||||
class Config(Handler):
|
||||
needs_admin = True # By default, staff is lower level needed
|
||||
needs_admin = True # By default, staff is lower level needed
|
||||
|
||||
def get(self):
|
||||
res = {}
|
||||
addCrypt = self.is_admin()
|
||||
|
||||
|
||||
for cfg in cfgConfig.enumerate():
|
||||
if cfg.isCrypted() is True and addCrypt is False:
|
||||
continue
|
||||
# add section if it do not exists
|
||||
if res.has_key(cfg.section()) is False:
|
||||
if cfg.section() not in res:
|
||||
res[cfg.section()] = {}
|
||||
res[cfg.section()][cfg.key()] = { 'value' : cfg.get(), 'crypt': cfg.isCrypted(), 'longText': cfg.isLongText() }
|
||||
res[cfg.section()][cfg.key()] = {
|
||||
'value': cfg.get(),
|
||||
'crypt': cfg.isCrypted(),
|
||||
'longText': cfg.isLongText()
|
||||
}
|
||||
logger.debug('Configuration: {0}'.format(res))
|
||||
return res
|
||||
|
||||
|
||||
def put(self):
|
||||
for section, secDict in self._params.iteritems():
|
||||
for key, vals in secDict.iteritems():
|
||||
cfgConfig.update( section, key, vals['value'] )
|
||||
cfgConfig.update(section, key, vals['value'])
|
||||
return 'done'
|
||||
|
@ -4,27 +4,27 @@
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@ -41,17 +41,17 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# Enclosed methods under /auth path
|
||||
|
||||
|
||||
class Callback(Handler):
|
||||
path = 'gui'
|
||||
authenticated = True # Public method
|
||||
needs_staff = True #
|
||||
|
||||
path = 'gui'
|
||||
authenticated = True
|
||||
needs_staff = True
|
||||
|
||||
def get(self):
|
||||
if len(self._args) != 1:
|
||||
raise RequestError('Invalid Request')
|
||||
|
||||
if gui.callbacks.has_key(self._args[0]):
|
||||
|
||||
if self._args[0] in gui.callbacks:
|
||||
return gui.callbacks[self._args[0]](self._params)
|
||||
|
||||
|
||||
raise NotFound('callback {0} not found'.format(self._args[0]))
|
||||
|
@ -4,27 +4,27 @@
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@ -43,10 +43,11 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# Enclosed methods under /auth path
|
||||
|
||||
|
||||
class Login(Handler):
|
||||
path = 'auth'
|
||||
authenticated = False # Public method
|
||||
|
||||
path = 'auth'
|
||||
authenticated = False # Public method
|
||||
|
||||
def post(self):
|
||||
'''
|
||||
This login uses parameters to generate auth token
|
||||
@ -76,35 +77,40 @@ class Login(Handler):
|
||||
except Exception as e:
|
||||
logger.exception('exception')
|
||||
return {'result': 'error', 'error': unicode(e)}
|
||||
|
||||
|
||||
|
||||
|
||||
class Logout(Handler):
|
||||
path = 'auth'
|
||||
authenticated = True # By default, all handlers needs authentication
|
||||
|
||||
authenticated = True # By default, all handlers needs authentication
|
||||
|
||||
def get(self):
|
||||
# Remove auth token
|
||||
self.cleanAuthToken()
|
||||
return 'done'
|
||||
|
||||
return 'done'
|
||||
|
||||
def post(self):
|
||||
return self.get()
|
||||
|
||||
|
||||
|
||||
class Auths(Handler):
|
||||
path = 'auth'
|
||||
authenticated = False # By default, all handlers needs authentication
|
||||
|
||||
authenticated = False # By default, all handlers needs authentication
|
||||
|
||||
def auths(self):
|
||||
for a in Authenticator.all():
|
||||
if a.getType().isCustom() is False:
|
||||
yield { 'auth' : str(a.small_name), 'name' : a.name }
|
||||
|
||||
yield {
|
||||
'auth': str(a.small_name),
|
||||
'name': a.name
|
||||
}
|
||||
|
||||
def get(self):
|
||||
return list(self.auths())
|
||||
|
||||
|
||||
|
||||
class Locale(Handler):
|
||||
authenticated = True
|
||||
|
||||
|
||||
def get(self):
|
||||
if len(self._args) > 0:
|
||||
self.setValue('locale', self._args[1])
|
||||
|
@ -4,27 +4,27 @@
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@ -45,17 +45,18 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# Enclosed methods under /item path
|
||||
|
||||
|
||||
class Networks(ModelHandler):
|
||||
model = Network
|
||||
save_fields = ['name', 'net_string']
|
||||
|
||||
table_title = _('Current Networks')
|
||||
table_title = _('Current Networks')
|
||||
table_fields = [
|
||||
{ 'name': {'title': _('Name'), 'visible': True, 'type': 'icon', 'icon': 'fa fa-globe text-success' } },
|
||||
{ 'net_string': {'title': _('Range')}},
|
||||
{ 'networks_count': {'title': _('Used by'), 'type': 'numeric', 'width': '8em'}}
|
||||
{'name': {'title': _('Name'), 'visible': True, 'type': 'icon', 'icon': 'fa fa-globe text-success'}},
|
||||
{'net_string': {'title': _('Range')}},
|
||||
{'networks_count': {'title': _('Used by'), 'type': 'numeric', 'width': '8em'}}
|
||||
]
|
||||
|
||||
|
||||
def beforeSave(self, fields):
|
||||
logger.debug('Before {0}'.format(fields))
|
||||
try:
|
||||
@ -65,21 +66,21 @@ class Networks(ModelHandler):
|
||||
except Exception as e:
|
||||
raise SaveException(ugettext('Invalid network: ') + unicode(e))
|
||||
logger.debug('Processed {0}'.format(fields))
|
||||
|
||||
|
||||
def getGui(self, type_):
|
||||
return self.addField(self.addDefaultFields([], ['name']),{
|
||||
return self.addField(self.addDefaultFields([], ['name']), {
|
||||
'name': 'net_string',
|
||||
'value': '',
|
||||
'label': ugettext('Network range'),
|
||||
'tooltip': ugettext('Network range. Accepts most network definitions formats (range, subnet, host, etc...'),
|
||||
'type': gui.InputField.TEXT_TYPE,
|
||||
'order': 100, # At end
|
||||
'order': 100, # At end
|
||||
})
|
||||
|
||||
|
||||
def item_as_dict(self, item):
|
||||
return { 'id': item.id,
|
||||
'name': item.name,
|
||||
'net_string': item.net_string,
|
||||
'networks_count': item.transports.count(),
|
||||
return {
|
||||
'id': item.id,
|
||||
'name': item.name,
|
||||
'net_string': item.net_string,
|
||||
'networks_count': item.transports.count(),
|
||||
}
|
||||
|
||||
|
@ -4,27 +4,27 @@
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@ -34,7 +34,7 @@ from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
from uds.models import Provider, Service, UserService
|
||||
from services import Services as DetailServices
|
||||
from services import Services as DetailServices
|
||||
from uds.core import services
|
||||
|
||||
from uds.REST import NotFound, RequestError
|
||||
@ -47,55 +47,55 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class Providers(ModelHandler):
|
||||
model = Provider
|
||||
detail = { 'services': DetailServices }
|
||||
detail = {'services': DetailServices}
|
||||
custom_methods = [('allservices', False), ('service', False)]
|
||||
|
||||
|
||||
save_fields = ['name', 'comments']
|
||||
|
||||
|
||||
table_title = _('Service providers')
|
||||
|
||||
|
||||
# Table info fields
|
||||
table_fields = [
|
||||
{ 'name': {'title': _('Name'), 'type': 'iconType' } },
|
||||
{ 'comments': {'title': _('Comments')}},
|
||||
{ 'services_count': {'title': _('Services'), 'type': 'numeric', 'width': '5em'}},
|
||||
{ 'user_services_count': {'title': _('User Services'), 'type': 'numeric', 'width': '8em'}},
|
||||
{'name': {'title': _('Name'), 'type': 'iconType'}},
|
||||
{'comments': {'title': _('Comments')}},
|
||||
{'services_count': {'title': _('Services'), 'type': 'numeric', 'width': '5em'}},
|
||||
{'user_services_count': {'title': _('User Services'), 'type': 'numeric', 'width': '8em'}},
|
||||
]
|
||||
|
||||
|
||||
def item_as_dict(self, provider):
|
||||
type_ = provider.getType()
|
||||
|
||||
|
||||
# Icon can have a lot of data (1-2 Kbytes), but it's not expected to have a lot of services providers, and even so, this will work fine
|
||||
offers = [{
|
||||
'name' : ugettext(t.name()),
|
||||
'type' : t.type(),
|
||||
'description' : ugettext(t.description()),
|
||||
'icon' : t.icon().replace('\n', '') } for t in type_.getServicesTypes()]
|
||||
|
||||
return { 'id': provider.id,
|
||||
'name': provider.name,
|
||||
'services_count': provider.services.count(),
|
||||
'user_services_count': UserService.objects.filter(deployed_service__service__provider=provider).count(),
|
||||
'offers': offers,
|
||||
'type': type_.type(),
|
||||
'comments': provider.comments,
|
||||
offers = [{
|
||||
'name': ugettext(t.name()),
|
||||
'type': t.type(),
|
||||
'description': ugettext(t.description()),
|
||||
'icon': t.icon().replace('\n', '')} for t in type_.getServicesTypes()]
|
||||
|
||||
return {
|
||||
'id': provider.id,
|
||||
'name': provider.name,
|
||||
'services_count': provider.services.count(),
|
||||
'user_services_count': UserService.objects.filter(deployed_service__service__provider=provider).count(),
|
||||
'offers': offers,
|
||||
'type': type_.type(),
|
||||
'comments': provider.comments,
|
||||
}
|
||||
|
||||
def checkDelete(self, item):
|
||||
if item.services.count() > 0:
|
||||
raise RequestError('Can\'t delete providers with services already associated')
|
||||
|
||||
|
||||
# Types related
|
||||
def enum_types(self):
|
||||
return services.factory().providers().values()
|
||||
|
||||
|
||||
# Gui related
|
||||
def getGui(self, type_):
|
||||
try:
|
||||
return self.addDefaultFields(services.factory().lookup(type_).guiDescription(), ['name', 'comments'])
|
||||
except:
|
||||
raise NotFound('type not found')
|
||||
|
||||
|
||||
def allservices(self):
|
||||
for s in Service.objects.all():
|
||||
@ -103,7 +103,7 @@ class Providers(ModelHandler):
|
||||
yield DetailServices.serviceToDict(s, True)
|
||||
except:
|
||||
logger.exception('Passed service cause type is unknown')
|
||||
|
||||
|
||||
def service(self):
|
||||
try:
|
||||
return DetailServices.serviceToDict(Service.objects.get(pk=self._args[1]), True)
|
||||
|
@ -4,27 +4,27 @@
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@ -49,16 +49,16 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Services(DetailHandler):
|
||||
|
||||
|
||||
@staticmethod
|
||||
def serviceToDict(item, full=False):
|
||||
retVal = {
|
||||
'id':item.id,
|
||||
'name': item.name,
|
||||
'comments': item.comments,
|
||||
'type': item.data_type,
|
||||
'type_name' : _(item.getType().name()),
|
||||
'deployed_services_count' : item.deployedServices.count(),
|
||||
retVal = {
|
||||
'id': item.id,
|
||||
'name': item.name,
|
||||
'comments': item.comments,
|
||||
'type': item.data_type,
|
||||
'type_name': _(item.getType().name()),
|
||||
'deployed_services_count': item.deployedServices.count(),
|
||||
'user_services_count': UserService.objects.filter(deployed_service__service=item).count(),
|
||||
}
|
||||
if full:
|
||||
@ -74,14 +74,14 @@ class Services(DetailHandler):
|
||||
'needs_manager': info.needsManager,
|
||||
'must_assign_manually': info.mustAssignManually,
|
||||
}
|
||||
|
||||
|
||||
return retVal
|
||||
|
||||
|
||||
def getItems(self, parent, item):
|
||||
# Extract provider
|
||||
try:
|
||||
if item is None:
|
||||
return [Services.serviceToDict(k) for k in parent.services.all() ]
|
||||
return [Services.serviceToDict(k) for k in parent.services.all()]
|
||||
else:
|
||||
k = parent.services.get(pk=item)
|
||||
val = Services.serviceToDict(k)
|
||||
@ -89,85 +89,85 @@ class Services(DetailHandler):
|
||||
except:
|
||||
logger.exception('getItems')
|
||||
self.invalidItemException()
|
||||
|
||||
|
||||
def saveItem(self, parent, item):
|
||||
# Extract item db fields
|
||||
# We need this fields for all
|
||||
logger.debug('Saving service {0} / {1}'.format(parent, item))
|
||||
fields = self.readFieldsFromParams(['name', 'comments', 'data_type'])
|
||||
try:
|
||||
if item is None: # Create new
|
||||
if item is None: # Create new
|
||||
service = parent.services.create(**fields)
|
||||
else:
|
||||
service = parent.services.get(pk=item)
|
||||
service.__dict__.update(fields)
|
||||
|
||||
|
||||
service.data = service.getInstance(self._params).serialize()
|
||||
service.save()
|
||||
except Service.DoesNotExist:
|
||||
except Service.DoesNotExist:
|
||||
self.invalidItemException()
|
||||
except IntegrityError: # Duplicate key probably
|
||||
except IntegrityError: # Duplicate key probably
|
||||
raise RequestError('Element already exists (duplicate key error)')
|
||||
except Exception:
|
||||
logger.exception('Saving Service')
|
||||
raise RequestError('incorrect invocation to PUT')
|
||||
|
||||
|
||||
return self.getItems(parent, service.id)
|
||||
|
||||
|
||||
def deleteItem(self, parent, item):
|
||||
try:
|
||||
service = parent.services.get(pk=item)
|
||||
|
||||
|
||||
if service.deployedServices.count() != 0:
|
||||
raise RequestError('Item has associated deployed services')
|
||||
|
||||
|
||||
service.delete()
|
||||
except:
|
||||
self.invalidItemException()
|
||||
|
||||
|
||||
return 'deleted'
|
||||
|
||||
|
||||
def getTitle(self, parent):
|
||||
try:
|
||||
return _('Services of {0}').format(parent.name)
|
||||
except:
|
||||
return _('Current services')
|
||||
|
||||
|
||||
def getFields(self, parent):
|
||||
return [
|
||||
{ 'name': {'title': _('Service name'), 'visible': True, 'type': 'iconType' } },
|
||||
{ 'comments': { 'title': _('Comments') } },
|
||||
{ 'type_name': {'title': _('Type') } },
|
||||
{ 'deployed_services_count': {'title': _('Deployed services'), 'type': 'numeric', 'width': '7em'}},
|
||||
{ 'user_services_count': {'title': _('User services'), 'type': 'numeric', 'width': '7em'}},
|
||||
{'name': {'title': _('Service name'), 'visible': True, 'type': 'iconType'}},
|
||||
{'comments': {'title': _('Comments')}},
|
||||
{'type_name': {'title': _('Type')}},
|
||||
{'deployed_services_count': {'title': _('Deployed services'), 'type': 'numeric', 'width': '7em'}},
|
||||
{'user_services_count': {'title': _('User services'), 'type': 'numeric', 'width': '7em'}},
|
||||
]
|
||||
|
||||
|
||||
def getTypes(self, parent, forType):
|
||||
logger.debug('getTypes parameters: {0}, {1}'.format(parent, forType))
|
||||
if forType is None:
|
||||
offers = [{
|
||||
'name' : _(t.name()),
|
||||
'type' : t.type(),
|
||||
'description' : _(t.description()),
|
||||
'icon' : t.icon().replace('\n', '') } for t in parent.getType().getServicesTypes()]
|
||||
offers = [{
|
||||
'name': _(t.name()),
|
||||
'type': t.type(),
|
||||
'description': _(t.description()),
|
||||
'icon': t.icon().replace('\n', '')} for t in parent.getType().getServicesTypes()]
|
||||
else:
|
||||
offers = None # Do we really need to get one specific type?
|
||||
offers = None # Do we really need to get one specific type?
|
||||
for t in parent.getType().getServicesTypes():
|
||||
if forType == t.type():
|
||||
offers = t
|
||||
break
|
||||
if offers is None:
|
||||
raise NotFound('type not found')
|
||||
|
||||
return offers # Default is that details do not have types
|
||||
|
||||
|
||||
return offers # Default is that details do not have types
|
||||
|
||||
def getGui(self, parent, forType):
|
||||
try:
|
||||
logger.debug('getGui parameters: {0}, {1}'.format(parent, forType))
|
||||
parentInstance = parent.getInstance()
|
||||
serviceType = parentInstance.getServiceByType(forType)
|
||||
service = serviceType( Environment.getTempEnv(), parentInstance) # Instantiate it so it has the opportunity to alter gui description based on parent
|
||||
return self.addDefaultFields( service.guiDescription(service), ['name', 'comments'])
|
||||
service = serviceType(Environment.getTempEnv(), parentInstance) # Instantiate it so it has the opportunity to alter gui description based on parent
|
||||
return self.addDefaultFields(service.guiDescription(service), ['name', 'comments'])
|
||||
except Exception as e:
|
||||
logger.exception('getGui')
|
||||
raise ResponseError(unicode(e))
|
||||
@ -179,4 +179,3 @@ class Services(DetailHandler):
|
||||
return log.getLogs(item)
|
||||
except:
|
||||
self.invalidItemException()
|
||||
|
@ -4,27 +4,27 @@
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@ -48,105 +48,107 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ServicesPools(ModelHandler):
|
||||
model = DeployedService
|
||||
detail = {
|
||||
'services': AssignedService,
|
||||
detail = {
|
||||
'services': AssignedService,
|
||||
'cache': CachedService,
|
||||
'groups': Groups,
|
||||
'groups': Groups,
|
||||
'transports': Transports,
|
||||
'publications': Publications,
|
||||
}
|
||||
|
||||
save_fields = ['name', 'comments', 'service_id', 'osmanager_id', 'initial_srvs', 'cache_l1_srvs', 'cache_l2_srvs', 'max_srvs']
|
||||
|
||||
table_title = _('Deployed services')
|
||||
table_title = _('Deployed services')
|
||||
table_fields = [
|
||||
{ 'name': {'title': _('Name') } },
|
||||
{ 'parent': {'title': _('Parent Service') } }, # Will process this field on client in fact, not sent by server
|
||||
{ 'state': { 'title': _('state'), 'type': 'dict', 'dict': State.dictionary() } },
|
||||
{ 'comments': {'title': _('Comments')}},
|
||||
{'name': {'title': _('Name')}},
|
||||
{'parent': {'title': _('Parent Service')}}, # Will process this field on client in fact, not sent by server
|
||||
{'state': {'title': _('state'), 'type': 'dict', 'dict': State.dictionary()}},
|
||||
{'comments': {'title': _('Comments')}},
|
||||
]
|
||||
# Field from where to get "class" and prefix for that class, so this will generate "row-state-A, row-state-X, ....
|
||||
table_row_style = { 'field': 'state', 'prefix': 'row-state-' }
|
||||
|
||||
table_row_style = {'field': 'state', 'prefix': 'row-state-'}
|
||||
|
||||
def item_as_dict(self, item):
|
||||
val = { 'id': item.id,
|
||||
'name': item.name,
|
||||
val = {
|
||||
'id': item.id,
|
||||
'name': item.name,
|
||||
'comments': item.comments,
|
||||
'state' : item.state,
|
||||
'state': item.state,
|
||||
'service_id': item.service_id,
|
||||
'initial_srvs' : item.initial_srvs,
|
||||
'cache_l1_srvs' : item.cache_l1_srvs,
|
||||
'cache_l2_srvs' : item.cache_l2_srvs,
|
||||
'max_srvs' : item.max_srvs,
|
||||
'initial_srvs': item.initial_srvs,
|
||||
'cache_l1_srvs': item.cache_l1_srvs,
|
||||
'cache_l2_srvs': item.cache_l2_srvs,
|
||||
'max_srvs': item.max_srvs,
|
||||
'user_services_count': item.userServices.count(),
|
||||
'restrained': item.isRestrained(),
|
||||
}
|
||||
|
||||
|
||||
if item.osmanager is not None:
|
||||
val['osmanager_id'] = item.osmanager.id
|
||||
|
||||
return val
|
||||
|
||||
|
||||
# Gui related
|
||||
def getGui(self, type_):
|
||||
if OSManager.objects.count() < 1: # No os managers, can't create db
|
||||
if OSManager.objects.count() < 1: # No os managers, can't create db
|
||||
raise ResponseError(ugettext('Create at least one OS Manager before creating a new service pool'))
|
||||
if Service.objects.count() < 1:
|
||||
raise ResponseError(ugettext('Create at least a service before creating a new service pool'))
|
||||
|
||||
|
||||
g = self.addDefaultFields([], ['name', 'comments'])
|
||||
|
||||
|
||||
for f in [{
|
||||
'name': 'service_id',
|
||||
'values': [gui.choiceItem(-1, '')] + [ gui.choiceItem(v.id, v.name) for v in Service.objects.all() ],
|
||||
'values': [gui.choiceItem(-1, '')] + [gui.choiceItem(v.id, v.name) for v in Service.objects.all()],
|
||||
'label': ugettext('Base service'),
|
||||
'tooltip': ugettext('Service used as base of this service pool'),
|
||||
'type': gui.InputField.CHOICE_TYPE,
|
||||
'rdonly' : True,
|
||||
'order': 100, # At end
|
||||
},{
|
||||
'rdonly': True,
|
||||
'order': 100, # At end
|
||||
}, {
|
||||
'name': 'osmanager_id',
|
||||
'values': [gui.choiceItem(-1, '')] + [ gui.choiceItem(v.id, v.name) for v in OSManager.objects.all() ],
|
||||
'values': [gui.choiceItem(-1, '')] + [gui.choiceItem(v.id, v.name) for v in OSManager.objects.all()],
|
||||
'label': ugettext('OS Manager'),
|
||||
'tooltip': ugettext('OS Manager used as base of this service pool'),
|
||||
'type': gui.InputField.CHOICE_TYPE,
|
||||
'rdonly' : True,
|
||||
'order': 101, # At end
|
||||
},{
|
||||
'rdonly': True,
|
||||
'order': 101, # At end
|
||||
}, {
|
||||
'name': 'initial_srvs',
|
||||
'value': '0',
|
||||
'label': ugettext('Initial available services'),
|
||||
'tooltip': ugettext('Services created initially for this service pool'),
|
||||
'type': gui.InputField.NUMERIC_TYPE,
|
||||
'order': 102, # At end
|
||||
},{
|
||||
'order': 102, # At end
|
||||
}, {
|
||||
'name': 'cache_l1_srvs',
|
||||
'value': '0',
|
||||
'label': ugettext('Services to keep in cache'),
|
||||
'tooltip': ugettext('Services keeped in cache for improved user service assignation'),
|
||||
'type': gui.InputField.NUMERIC_TYPE,
|
||||
'order': 103, # At end
|
||||
},{
|
||||
'order': 103, # At end
|
||||
}, {
|
||||
'name': 'cache_l2_srvs',
|
||||
'value': '0',
|
||||
'label': ugettext('Services to keep in L2 cache'),
|
||||
'tooltip': ugettext('Services keeped in cache of level2 for improved service generation'),
|
||||
'type': gui.InputField.NUMERIC_TYPE,
|
||||
'order': 104, # At end
|
||||
},{
|
||||
'order': 104, # At end
|
||||
}, {
|
||||
'name': 'max_srvs',
|
||||
'value': '0',
|
||||
'label': ugettext('Maximum number of services to provide'),
|
||||
'tooltip': ugettext('Maximum number of service (assigned and L1 cache) that can be created for this service'),
|
||||
'type': gui.InputField.NUMERIC_TYPE,
|
||||
'order': 105, # At end
|
||||
'order': 105, # At end
|
||||
}]:
|
||||
self.addField(g, f)
|
||||
|
||||
|
||||
return g
|
||||
|
||||
|
||||
def beforeSave(self, fields):
|
||||
logger.debug('Before {0}'.format(fields))
|
||||
logger.debug(self._args)
|
||||
@ -157,7 +159,7 @@ class ServicesPools(ModelHandler):
|
||||
fields['service'] = service
|
||||
except:
|
||||
raise RequestError(ugettext('Base service does not exists anymore'))
|
||||
|
||||
|
||||
try:
|
||||
serviceType = service.getType()
|
||||
if serviceType.needsManager is True:
|
||||
@ -166,16 +168,15 @@ class ServicesPools(ModelHandler):
|
||||
del fields['osmanager_id']
|
||||
except:
|
||||
raise RequestError(ugettext('This service requires an os manager'))
|
||||
|
||||
|
||||
except (RequestError, ResponseError):
|
||||
raise
|
||||
except Exception as e:
|
||||
raise RequestError(str(e))
|
||||
|
||||
|
||||
def deleteItem(self, item):
|
||||
item.remove() # This will mark it for deletion, but in fact will not delete it directly
|
||||
|
||||
item.remove() # This will mark it for deletion, but in fact will not delete it directly
|
||||
|
||||
# Logs
|
||||
def getLogs(self, item):
|
||||
return log.getLogs(item)
|
||||
|
||||
|
@ -4,27 +4,27 @@
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@ -49,7 +49,7 @@ cache = Cache('StatsDispatcher')
|
||||
|
||||
# Enclosed methods under /syatem path
|
||||
POINTS = 365
|
||||
SINCE = 365 # Days
|
||||
SINCE = 365 # Days
|
||||
USE_MAX = True
|
||||
|
||||
|
||||
@ -57,39 +57,38 @@ def getServicesPoolsCounters(servicePool, counter_type):
|
||||
try:
|
||||
cacheKey = (servicePool and servicePool.id or 'all') + str(counter_type) + str(POINTS) + str(SINCE)
|
||||
to = getSqlDatetime()
|
||||
since = to - timedelta(days=SINCE)
|
||||
since = to - timedelta(days=SINCE)
|
||||
val = cache.get(cacheKey)
|
||||
if val is None:
|
||||
if servicePool is None:
|
||||
us = DeployedService()
|
||||
complete = True # Get all deployed services stats
|
||||
complete = True # Get all deployed services stats
|
||||
else:
|
||||
us = servicePool
|
||||
complete = False
|
||||
val = []
|
||||
for x in counters.getCounters(us, counter_type, since=since, to=to, limit=POINTS, use_max=USE_MAX, all=complete):
|
||||
val.append({ 'stamp': x[0], 'value': int(x[1]) })
|
||||
val.append({'stamp': x[0], 'value': int(x[1])})
|
||||
if len(val) > 2:
|
||||
cache.put(cacheKey, cPickle.dumps(val).encode('zip'), 600)
|
||||
else:
|
||||
val = [{'stamp':since, 'value':0 }, {'stamp':to, 'value':0}]
|
||||
val = [{'stamp':since, 'value': 0}, {'stamp':to, 'value':0}]
|
||||
else:
|
||||
val = cPickle.loads(val.decode('zip'))
|
||||
|
||||
|
||||
return val
|
||||
except:
|
||||
logger.exception('exception')
|
||||
raise ResponseError('can\'t create stats for objects!!!')
|
||||
|
||||
|
||||
|
||||
class System(Handler):
|
||||
needs_admin = True # By default, staff is lower level needed
|
||||
needs_admin = True # By default, staff is lower level needed
|
||||
|
||||
def get(self):
|
||||
logger.debug('args: {0}'.format(self._args))
|
||||
if len(self._args) == 1:
|
||||
if self._args[0] == 'overview': # System overview
|
||||
if self._args[0] == 'overview': # System overview
|
||||
users = User.objects.count()
|
||||
services = Service.objects.count()
|
||||
user_services = UserService.objects.count()
|
||||
@ -100,16 +99,15 @@ class System(Handler):
|
||||
'user_services': user_services,
|
||||
'restrained_services_pools': restrained_services_pools,
|
||||
}
|
||||
|
||||
|
||||
if len(self._args) == 2:
|
||||
if self._args[0] == 'stats':
|
||||
if self._args[1] == 'assigned':
|
||||
return getServicesPoolsCounters(None, counters.CT_ASSIGNED)
|
||||
if self._args[1] == 'inuse':
|
||||
return getServicesPoolsCounters(None, counters.CT_INUSE)
|
||||
|
||||
|
||||
raise RequestError('invalid request')
|
||||
|
||||
|
||||
def put(self):
|
||||
raise RequestError('todo')
|
||||
|
@ -4,27 +4,27 @@
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@ -36,7 +36,6 @@ from django.utils.translation import ugettext_lazy as _, ugettext
|
||||
from uds.models import Transport, Network
|
||||
from uds.core.transports import factory
|
||||
|
||||
from uds.REST import Handler, NotFound
|
||||
from uds.REST.model import ModelHandler
|
||||
|
||||
import logging
|
||||
@ -45,21 +44,22 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# Enclosed methods under /item path
|
||||
|
||||
|
||||
class Transports(ModelHandler):
|
||||
model = Transport
|
||||
save_fields = ['name', 'comments', 'priority', 'nets_positive']
|
||||
|
||||
table_title = _('Current Transports')
|
||||
table_title = _('Current Transports')
|
||||
table_fields = [
|
||||
{ 'priority': {'title': _('Priority'), 'type': 'numeric', 'width': '6em' }},
|
||||
{ 'name': {'title': _('Name'), 'visible': True, 'type': 'iconType' } },
|
||||
{ 'comments': {'title': _('Comments')}},
|
||||
{ 'deployed_count': {'title': _('Used by'), 'type': 'numeric', 'width': '8em'}}
|
||||
{'priority': {'title': _('Priority'), 'type': 'numeric', 'width': '6em'}},
|
||||
{'name': {'title': _('Name'), 'visible': True, 'type': 'iconType'}},
|
||||
{'comments': {'title': _('Comments')}},
|
||||
{'deployed_count': {'title': _('Used by'), 'type': 'numeric', 'width': '8em'}}
|
||||
]
|
||||
|
||||
def enum_types(self):
|
||||
return factory().providers().values()
|
||||
|
||||
|
||||
def getGui(self, type_):
|
||||
try:
|
||||
return self.addField(self.addField(self.addDefaultFields(factory().lookup(type_).guiDescription(), ['name', 'comments', 'priority']), {
|
||||
@ -68,11 +68,11 @@ class Transports(ModelHandler):
|
||||
'label': ugettext('Network access'),
|
||||
'tooltip': ugettext('If ACTIVE, the transport will be enabled for the selected networks.If INACTIVE, trans port will be disabled for selected networks'),
|
||||
'type': 'checkbox',
|
||||
'order': 100, # At end
|
||||
'order': 100, # At end
|
||||
}), {
|
||||
'name': 'networks',
|
||||
'value': [],
|
||||
'values': sorted([{'id': x.id, 'text': x.name} for x in Network.objects.all()], key=lambda x: x['text'].lower()), # TODO: We will fix this behavior after current admin client is fully removed
|
||||
'values': sorted([{'id': x.id, 'text': x.name} for x in Network.objects.all()], key=lambda x: x['text'].lower()), # TODO: We will fix this behavior after current admin client is fully removed
|
||||
'label': ugettext('Networks'),
|
||||
'tooltip': ugettext('Networks associated with this transport. If No network selected, will mean "all networks"'),
|
||||
'type': 'multichoice',
|
||||
@ -80,24 +80,25 @@ class Transports(ModelHandler):
|
||||
})
|
||||
except:
|
||||
self.invalidItemException()
|
||||
|
||||
|
||||
def item_as_dict(self, item):
|
||||
type_ = item.getType()
|
||||
return { 'id': item.id,
|
||||
'name': item.name,
|
||||
'comments': item.comments,
|
||||
'priority': item.priority,
|
||||
'nets_positive': item.nets_positive,
|
||||
'networks': [ { 'id': n.id } for n in item.networks.all() ],
|
||||
'deployed_count': item.deployedServices.count(),
|
||||
'type': type_.type(),
|
||||
return {
|
||||
'id': item.id,
|
||||
'name': item.name,
|
||||
'comments': item.comments,
|
||||
'priority': item.priority,
|
||||
'nets_positive': item.nets_positive,
|
||||
'networks': [{'id': n.id} for n in item.networks.all()],
|
||||
'deployed_count': item.deployedServices.count(),
|
||||
'type': type_.type(),
|
||||
}
|
||||
|
||||
|
||||
def afterSave(self, item):
|
||||
try:
|
||||
networks = self._params['networks']
|
||||
except: # No networks passed in, this is ok
|
||||
except: # No networks passed in, this is ok
|
||||
return
|
||||
|
||||
|
||||
logger.debug('Params: {0}'.format(networks))
|
||||
item.networks = Network.objects.filter(id__in=networks)
|
||||
|
@ -4,27 +4,27 @@
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@ -45,34 +45,35 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AssignedService(DetailHandler):
|
||||
|
||||
|
||||
@staticmethod
|
||||
def itemToDict(item, is_cache=False):
|
||||
val = {
|
||||
'id' : item.id,
|
||||
'id_deployed_service' : item.deployed_service_id,
|
||||
'unique_id' : item.unique_id,
|
||||
'friendly_name' : item.friendly_name,
|
||||
'state' : item.state,
|
||||
'os_state': item.os_state,
|
||||
'state_date' : item.state_date,
|
||||
'creation_date' : item.creation_date,
|
||||
'revision' : item.publication and item.publication.revision or '',
|
||||
'id': item.id,
|
||||
'id_deployed_service': item.deployed_service_id,
|
||||
'unique_id': item.unique_id,
|
||||
'friendly_name': item.friendly_name,
|
||||
'state': item.state,
|
||||
'os_state': item.os_state,
|
||||
'state_date': item.state_date,
|
||||
'creation_date': item.creation_date,
|
||||
'revision': item.publication and item.publication.revision or '',
|
||||
}
|
||||
|
||||
|
||||
if is_cache:
|
||||
val['cache_level'] = item.cache_level
|
||||
else:
|
||||
val.update({
|
||||
'owner': item.user.manager.name + "-" + item.user.name,
|
||||
'in_use': item.in_use,
|
||||
val.update({
|
||||
'owner': item.user.manager.name + "-" + item.user.name,
|
||||
'in_use': item.in_use,
|
||||
'in_use_date': item.in_use_date,
|
||||
'source_host' : item.src_hostname,
|
||||
'source_ip': item.src_ip
|
||||
'source_host': item.src_hostname,
|
||||
'source_ip': item.src_ip
|
||||
})
|
||||
return val
|
||||
|
||||
|
||||
def getItems(self, parent, item):
|
||||
# Extract provider
|
||||
try:
|
||||
@ -83,20 +84,20 @@ class AssignedService(DetailHandler):
|
||||
except:
|
||||
logger.exception('getItems')
|
||||
self.invalidItemException()
|
||||
|
||||
|
||||
def getTitle(self, parent):
|
||||
return _('Assigned services')
|
||||
|
||||
|
||||
def getFields(self, parent):
|
||||
return [
|
||||
{ 'creation_date': { 'title': _('Creation date'), 'type': 'datetime' } },
|
||||
{ 'revision': { 'title': _('Revision') } },
|
||||
{ 'unique_id': { 'title': 'Unique ID'} },
|
||||
{ 'friendly_name': {'title': _('Friendly name')} },
|
||||
{ 'state': { 'title': _('State'), 'type': 'dict', 'dict': State.dictionary() } },
|
||||
{ 'owner': { 'title': _('Owner') } },
|
||||
{'creation_date': {'title': _('Creation date'), 'type': 'datetime'}},
|
||||
{'revision': {'title': _('Revision')}},
|
||||
{'unique_id': {'title': 'Unique ID'}},
|
||||
{'friendly_name': {'title': _('Friendly name')}},
|
||||
{'state': {'title': _('State'), 'type': 'dict', 'dict': State.dictionary()}},
|
||||
{'owner': {'title': _('Owner')}},
|
||||
]
|
||||
|
||||
|
||||
def getLogs(self, parent, item):
|
||||
try:
|
||||
item = parent.assignedUserServices().get(pk=item)
|
||||
@ -104,15 +105,15 @@ class AssignedService(DetailHandler):
|
||||
return log.getLogs(item)
|
||||
except:
|
||||
self.invalidItemException()
|
||||
|
||||
|
||||
|
||||
|
||||
class CachedService(AssignedService):
|
||||
|
||||
|
||||
def getItems(self, parent, item):
|
||||
# Extract provider
|
||||
try:
|
||||
if item is None:
|
||||
return [AssignedService.itemToDict(k, True) for k in parent.cachedUserServices().all() ]
|
||||
return [AssignedService.itemToDict(k, True) for k in parent.cachedUserServices().all()]
|
||||
else:
|
||||
k = parent.cachedUserServices().get(pk=item)
|
||||
return AssignedService.itemToDict(k, True)
|
||||
@ -125,12 +126,12 @@ class CachedService(AssignedService):
|
||||
|
||||
def getFields(self, parent):
|
||||
return [
|
||||
{ 'creation_date': { 'title': _('Creation date'), 'type': 'datetime' } },
|
||||
{ 'revision': { 'title': _('Revision') } },
|
||||
{ 'unique_id': { 'title': 'Unique ID'} },
|
||||
{ 'friendly_name': {'title': _('Friendly name')} },
|
||||
{ 'state': { 'title': _('State'), 'type': 'dict', 'dict': State.dictionary() } },
|
||||
{ 'cache_level': { 'title': _('Cache level') } },
|
||||
{'creation_date': {'title': _('Creation date'), 'type': 'datetime'}},
|
||||
{'revision': {'title': _('Revision')}},
|
||||
{'unique_id': {'title': 'Unique ID'}},
|
||||
{'friendly_name': {'title': _('Friendly name')}},
|
||||
{'state': {'title': _('State'), 'type': 'dict', 'dict': State.dictionary()}},
|
||||
{'cache_level': {'title': _('Cache level')}},
|
||||
]
|
||||
|
||||
def getLogs(self, parent, item):
|
||||
@ -151,25 +152,26 @@ class Groups(DetailHandler):
|
||||
'type': i.is_meta and 'meta' or 'group',
|
||||
'auth_name': i.manager.name,
|
||||
} for i in parent.assignedGroups.all()]
|
||||
|
||||
|
||||
def getTitle(self, parent):
|
||||
return _('Assigned groups')
|
||||
|
||||
def getFields(self, parent):
|
||||
return [
|
||||
# Note that this field is "self generated" on client table
|
||||
{ 'group_name': { 'title': _('Name'), 'type': 'icon_dict', 'icon_dict': {'group' : 'fa fa-group text-success', 'meta' : 'fa fa-gears text-info' } } },
|
||||
{ 'comments': { 'title': _('comments') } },
|
||||
{ 'state': { 'title': _('State'), 'type': 'dict', 'dict': State.dictionary() } },
|
||||
{'group_name': {'title': _('Name'), 'type': 'icon_dict', 'icon_dict': {'group': 'fa fa-group text-success', 'meta': 'fa fa-gears text-info'}}},
|
||||
{'comments': {'title': _('comments')}},
|
||||
{'state': {'title': _('State'), 'type': 'dict', 'dict': State.dictionary()}},
|
||||
]
|
||||
|
||||
|
||||
def saveItem(self, parent, item):
|
||||
parent.assignedGroups.add(Group.objects.get(pk=self._params['id']))
|
||||
return self.success()
|
||||
|
||||
|
||||
def deleteItem(self, parent, item):
|
||||
parent.assignedGroups.remove(Group.objects.get(pk=self._args[0]))
|
||||
|
||||
|
||||
|
||||
class Transports(DetailHandler):
|
||||
def getItems(self, parent, item):
|
||||
return [{
|
||||
@ -179,42 +181,43 @@ class Transports(DetailHandler):
|
||||
'comments': i.comments,
|
||||
'priority': i.priority,
|
||||
} for i in parent.transports.all()]
|
||||
|
||||
|
||||
def getTitle(self, parent):
|
||||
return _('Assigned transports')
|
||||
|
||||
def getFields(self, parent):
|
||||
return [
|
||||
{ 'priority': {'title': _('Priority'), 'type': 'numeric', 'width': '6em' } },
|
||||
{ 'name': {'title': _('Name')} },
|
||||
{ 'trans_type': {'title': _('Type') } },
|
||||
{ 'comments': {'title': _('Comments')}},
|
||||
{'priority': {'title': _('Priority'), 'type': 'numeric', 'width': '6em'}},
|
||||
{'name': {'title': _('Name')}},
|
||||
{'trans_type': {'title': _('Type')}},
|
||||
{'comments': {'title': _('Comments')}},
|
||||
]
|
||||
|
||||
def saveItem(self, parent, item):
|
||||
parent.transports.add(Transport.objects.get(pk=self._params['id']))
|
||||
return self.success()
|
||||
|
||||
|
||||
def deleteItem(self, parent, item):
|
||||
parent.transports.remove(Transport.objects.get(pk=self._args[0]))
|
||||
|
||||
|
||||
|
||||
class Publications(DetailHandler):
|
||||
custom_methods=['publish', 'cancel']
|
||||
|
||||
custom_methods = ['publish', 'cancel']
|
||||
|
||||
def publish(self, parent):
|
||||
logger.debug('Custom "publish" invoked')
|
||||
parent.publish()
|
||||
return self.success()
|
||||
|
||||
def cancel(self, parent, id):
|
||||
|
||||
def cancel(self, parent, pk):
|
||||
try:
|
||||
ds = DeployedServicePublication.objects.get(pk=id)
|
||||
ds = DeployedServicePublication.objects.get(pk=pk)
|
||||
ds.cancel()
|
||||
except Exception as e:
|
||||
raise ResponseError(unicode(e))
|
||||
|
||||
return self.success()
|
||||
|
||||
|
||||
def getItems(self, parent, item):
|
||||
return [{
|
||||
'id': i.id,
|
||||
@ -224,18 +227,20 @@ class Publications(DetailHandler):
|
||||
'reason': State.isErrored(i.state) and i.getInstance().reasonOfError() or '',
|
||||
'state_date': i.state_date,
|
||||
} for i in parent.publications.all()]
|
||||
|
||||
|
||||
def getTitle(self, parent):
|
||||
return _('Publications')
|
||||
|
||||
def getFields(self, parent):
|
||||
return [
|
||||
{ 'revision': {'title': _('Revision'), 'type': 'numeric', 'width': '6em' } },
|
||||
{ 'publish_date': { 'title': _('Publish date'), 'type': 'datetime' } },
|
||||
{ 'state': { 'title': _('State'), 'type': 'dict', 'dict': State.dictionary() } },
|
||||
{ 'reason': {'title': _('Reason')}},
|
||||
{'revision': {'title': _('Revision'), 'type': 'numeric', 'width': '6em'}},
|
||||
{'publish_date': {'title': _('Publish date'), 'type': 'datetime'}},
|
||||
{'state': {'title': _('State'), 'type': 'dict', 'dict': State.dictionary()}},
|
||||
{'reason': {'title': _('Reason')}},
|
||||
]
|
||||
|
||||
def getRowStyle(self, parent):
|
||||
return { 'field': 'state', 'prefix': 'row-state-' }
|
||||
|
||||
return {
|
||||
'field': 'state',
|
||||
'prefix': 'row-state-'
|
||||
}
|
||||
|
@ -3,27 +3,27 @@
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@ -31,7 +31,7 @@
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
#import time
|
||||
# import time
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.forms.models import model_to_dict
|
||||
from uds.core.util.State import State
|
||||
@ -52,16 +52,17 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# Details of /auth
|
||||
|
||||
|
||||
class Users(DetailHandler):
|
||||
|
||||
|
||||
def getItems(self, parent, item):
|
||||
# Extract authenticator
|
||||
try:
|
||||
if item is None:
|
||||
return list(parent.users.all().values('id','name','real_name','comments','state','staff_member','is_admin','last_access','parent'))
|
||||
return list(parent.users.all().values('id', 'name', 'real_name', 'comments', 'state', 'staff_member', 'is_admin', 'last_access', 'parent'))
|
||||
else:
|
||||
u = parent.users.get(pk=item)
|
||||
res = model_to_dict(u, fields = ('id','name','real_name','comments','state','staff_member','is_admin','last_access','parent'))
|
||||
res = model_to_dict(u, fields=('id', 'name', 'real_name', 'comments', 'state', 'staff_member', 'is_admin', 'last_access', 'parent'))
|
||||
usr = aUser(u)
|
||||
res['groups'] = [g.dbGroup().id for g in usr.groups()]
|
||||
logger.debug('Item: {0}'.format(res))
|
||||
@ -69,87 +70,88 @@ class Users(DetailHandler):
|
||||
except:
|
||||
logger.exception('En users')
|
||||
self.invalidItemException()
|
||||
|
||||
|
||||
def getTitle(self, parent):
|
||||
try:
|
||||
return _('Users of {0}').format(Authenticator.objects.get(pk=self._kwargs['parent_id']).name)
|
||||
except:
|
||||
return _('Current users')
|
||||
|
||||
|
||||
def getFields(self, parent):
|
||||
return [
|
||||
{ 'name': {'title': _('Username'), 'visible': True, 'type': 'icon', 'icon': 'fa fa-user text-success' } },
|
||||
{ 'real_name': { 'title': _('Name') } },
|
||||
{ 'comments': { 'title': _('Comments') } },
|
||||
{ 'state': { 'title': _('state'), 'type': 'dict', 'dict': State.dictionary() } },
|
||||
{ 'last_access': { 'title': _('Last access'), 'type': 'datetime' } },
|
||||
{'name': {'title': _('Username'), 'visible': True, 'type': 'icon', 'icon': 'fa fa-user text-success'}},
|
||||
{'real_name': {'title': _('Name')}},
|
||||
{'comments': {'title': _('Comments')}},
|
||||
{'state': {'title': _('state'), 'type': 'dict', 'dict': State.dictionary()}},
|
||||
{'last_access': {'title': _('Last access'), 'type': 'datetime'}},
|
||||
]
|
||||
|
||||
|
||||
def getRowStyle(self, parent):
|
||||
return { 'field': 'state', 'prefix': 'row-state-' }
|
||||
|
||||
return {'field': 'state', 'prefix': 'row-state-'}
|
||||
|
||||
def getLogs(self, parent, item):
|
||||
try:
|
||||
user = parent.users.get(pk=item)
|
||||
except:
|
||||
self.invalidItemException()
|
||||
|
||||
|
||||
return log.getLogs(user)
|
||||
|
||||
def saveItem(self, parent, item):
|
||||
logger.debug('Saving user {0} / {1}'.format(parent, item))
|
||||
valid_fields = ['name', 'real_name', 'comments', 'state', 'staff_member', 'is_admin']
|
||||
if self._params.has_key('password'):
|
||||
if 'password' in self._params:
|
||||
valid_fields.append('password')
|
||||
self._params['password'] = cryptoManager().hash(self._params['password'])
|
||||
|
||||
|
||||
fields = self.readFieldsFromParams(valid_fields)
|
||||
try:
|
||||
auth = parent.getInstance()
|
||||
if item is None: # Create new
|
||||
auth.createUser(fields) # this throws an exception if there is an error (for example, this auth can't create users)
|
||||
if item is None: # Create new
|
||||
auth.createUser(fields) # this throws an exception if there is an error (for example, this auth can't create users)
|
||||
toSave = {}
|
||||
for k in valid_fields:
|
||||
toSave[k] = fields[k]
|
||||
user = parent.users.create(**toSave)
|
||||
else:
|
||||
auth.modifyUser(fields) # Notifies authenticator
|
||||
auth.modifyUser(fields) # Notifies authenticator
|
||||
toSave = {}
|
||||
for k in valid_fields:
|
||||
toSave[k] = fields[k]
|
||||
user = parent.users.get(pk=item)
|
||||
user.__dict__.update(toSave)
|
||||
|
||||
|
||||
if auth.isExternalSource == False and user.parent == -1:
|
||||
groups = self.readFieldsFromParams(['groups'])['groups']
|
||||
user.groups = Group.objects.filter(id__in=groups)
|
||||
|
||||
|
||||
user.save()
|
||||
|
||||
except User.DoesNotExist:
|
||||
|
||||
except User.DoesNotExist:
|
||||
self.invalidItemException()
|
||||
except IntegrityError: # Duplicate key probably
|
||||
except IntegrityError: # Duplicate key probably
|
||||
raise RequestError(_('User already exists (duplicate key error)'))
|
||||
except AuthenticatorException as e:
|
||||
raise RequestError(unicode(e))
|
||||
except Exception:
|
||||
logger.exception('Saving user')
|
||||
self.invalidRequestException()
|
||||
|
||||
|
||||
return self.getItems(parent, user.id)
|
||||
|
||||
|
||||
def deleteItem(self, parent, item):
|
||||
try:
|
||||
user = parent.users.get(pk=item)
|
||||
|
||||
|
||||
user.delete()
|
||||
except:
|
||||
self.invalidItemException()
|
||||
|
||||
|
||||
return 'deleted'
|
||||
|
||||
|
||||
class Groups(DetailHandler):
|
||||
|
||||
|
||||
def getItems(self, parent, item):
|
||||
# Extract authenticator
|
||||
try:
|
||||
@ -177,30 +179,31 @@ class Groups(DetailHandler):
|
||||
except:
|
||||
logger.exception('REST groups')
|
||||
self.invalidItemException()
|
||||
|
||||
|
||||
def getTitle(self, parent):
|
||||
try:
|
||||
return _('Groups of {0}').format(Authenticator.objects.get(pk=self._kwargs['parent_id']).name)
|
||||
except:
|
||||
return _('Current groups')
|
||||
|
||||
|
||||
def getFields(self, parent):
|
||||
return [
|
||||
{ 'name': {'title': _('Group'), 'visible': True, 'type': 'icon_dict', 'icon_dict': {'group' : 'fa fa-group text-success', 'meta' : 'fa fa-gears text-info' } } },
|
||||
{ 'comments': { 'title': _('Comments') } },
|
||||
{ 'state': { 'title': _('state'), 'type': 'dict', 'dict': State.dictionary() } },
|
||||
]
|
||||
|
||||
{'name': {'title': _('Group'), 'visible': True, 'type': 'icon_dict', 'icon_dict': {'group': 'fa fa-group text-success', 'meta': 'fa fa-gears text-info'}}},
|
||||
{'comments': {'title': _('Comments')}},
|
||||
{'state': {'title': _('state'), 'type': 'dict', 'dict': State.dictionary()}},
|
||||
]
|
||||
|
||||
def getTypes(self, parent, forType):
|
||||
tDct = {
|
||||
'group': { 'name': _('Group'), 'description': _('UDS Group') },
|
||||
'meta' : { 'name': _('Meta group'), 'description': _('UDS Meta Group') },
|
||||
'group': {'name': _('Group'), 'description': _('UDS Group')},
|
||||
'meta': {'name': _('Meta group'), 'description': _('UDS Meta Group')},
|
||||
}
|
||||
types = [{
|
||||
'name' : tDct[t]['name'],
|
||||
'type' : t,
|
||||
'description' : tDct[t]['description'],
|
||||
'icon' : '' } for t in tDct.keys()]
|
||||
types = [{
|
||||
'name': tDct[t]['name'],
|
||||
'type': t,
|
||||
'description': tDct[t]['description'],
|
||||
'icon': ''
|
||||
} for t in tDct.keys()]
|
||||
if forType is None:
|
||||
return types
|
||||
else:
|
||||
@ -216,9 +219,9 @@ class Groups(DetailHandler):
|
||||
valid_fields = ['name', 'comments', 'state']
|
||||
fields = self.readFieldsFromParams(valid_fields)
|
||||
auth = parent.getInstance()
|
||||
if item is None: # Create new
|
||||
if item is None: # Create new
|
||||
if not is_meta:
|
||||
auth.createGroup(fields) # this throws an exception if there is an error (for example, this auth can't create users)
|
||||
auth.createGroup(fields) # this throws an exception if there is an error (for example, this auth can't create users)
|
||||
toSave = {}
|
||||
for k in valid_fields:
|
||||
toSave[k] = fields[k]
|
||||
@ -230,32 +233,32 @@ class Groups(DetailHandler):
|
||||
toSave = {}
|
||||
for k in valid_fields:
|
||||
toSave[k] = fields[k]
|
||||
del toSave['name'] # Name can't be changed
|
||||
del toSave['name'] # Name can't be changed
|
||||
group = parent.groups.get(pk=item)
|
||||
group.__dict__.update(toSave)
|
||||
|
||||
|
||||
if is_meta:
|
||||
group.groups = self._params['groups']
|
||||
|
||||
|
||||
group.save()
|
||||
except Group.DoesNotExist:
|
||||
except Group.DoesNotExist:
|
||||
self.invalidItemException()
|
||||
except IntegrityError: # Duplicate key probably
|
||||
except IntegrityError: # Duplicate key probably
|
||||
raise RequestError(_('User already exists (duplicate key error)'))
|
||||
except AuthenticatorException as e:
|
||||
raise RequestError(unicode(e))
|
||||
except Exception:
|
||||
logger.exception('Saving group')
|
||||
self.invalidRequestException()
|
||||
|
||||
|
||||
return self.getItems(parent, group.id)
|
||||
|
||||
def deleteItem(self, parent, item):
|
||||
try:
|
||||
group = parent.groups.get(pk=item)
|
||||
|
||||
|
||||
group.delete()
|
||||
except:
|
||||
self.invalidItemException()
|
||||
|
||||
|
||||
return 'deleted'
|
||||
|
@ -4,27 +4,27 @@
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@ -37,7 +37,7 @@ from django.utils.translation import ugettext as _
|
||||
from django.db import IntegrityError
|
||||
|
||||
from uds.core.ui.UserInterface import gui as uiGui
|
||||
from uds.REST.handlers import Handler
|
||||
from uds.REST.handlers import Handler
|
||||
from uds.core.util import log
|
||||
|
||||
import logging
|
||||
@ -51,13 +51,15 @@ TABLEINFO = 'tableinfo'
|
||||
GUI = 'gui'
|
||||
LOG = 'log'
|
||||
|
||||
|
||||
# Exception to "rethrow" on save error
|
||||
class SaveException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
# Base for Gui Related mixins
|
||||
class BaseModelHandler(Handler):
|
||||
|
||||
|
||||
def addField(self, gui, field):
|
||||
gui.append({
|
||||
'name': field.get('name', ''),
|
||||
@ -77,7 +79,7 @@ class BaseModelHandler(Handler):
|
||||
}
|
||||
})
|
||||
return gui
|
||||
|
||||
|
||||
def addDefaultFields(self, gui, flds):
|
||||
if 'name' in flds:
|
||||
self.addField(gui, {
|
||||
@ -85,38 +87,38 @@ class BaseModelHandler(Handler):
|
||||
'required': True,
|
||||
'label': _('Name'),
|
||||
'tooltip': _('Name of this element'),
|
||||
'order': -100,
|
||||
'order':-100,
|
||||
})
|
||||
if 'comments' in flds:
|
||||
self.addField(gui, {
|
||||
'name': 'comments',
|
||||
'name': 'comments',
|
||||
'label': _('Comments'),
|
||||
'tooltip': _('Comments for this element'),
|
||||
'length': 256,
|
||||
'order': -99,
|
||||
'order':-99,
|
||||
})
|
||||
if 'priority' in flds:
|
||||
self.addField(gui, {
|
||||
'name': 'priority',
|
||||
'type': 'numeric',
|
||||
'type': 'numeric',
|
||||
'label': _('Priority'),
|
||||
'tooltip': _('Selects the priority of this element (lower number means higher priority)'),
|
||||
'required': True,
|
||||
'value': 1,
|
||||
'length': 4,
|
||||
'order': -98,
|
||||
'order':-98,
|
||||
})
|
||||
if 'small_name' in flds:
|
||||
self.addField(gui, {
|
||||
'name': 'small_name',
|
||||
'type': 'text',
|
||||
'type': 'text',
|
||||
'label': _('Short name'),
|
||||
'tooltip': _('Short name of this element'),
|
||||
'required': True,
|
||||
'length': 128,
|
||||
'order': -97,
|
||||
'order':-97,
|
||||
})
|
||||
|
||||
|
||||
return gui
|
||||
|
||||
def typeInfo(self, type_):
|
||||
@ -124,16 +126,21 @@ class BaseModelHandler(Handler):
|
||||
|
||||
def type_as_dict(self, type_):
|
||||
res = self.typeInfo(type_)
|
||||
res.update( { 'name' : _(type_.name()),
|
||||
'type' : type_.type(),
|
||||
'description' : _(type_.description()),
|
||||
'icon' : type_.icon().replace('\n', '')
|
||||
res.update({
|
||||
'name': _(type_.name()),
|
||||
'type': type_.type(),
|
||||
'description': _(type_.description()),
|
||||
'icon': type_.icon().replace('\n', '')
|
||||
})
|
||||
return res
|
||||
|
||||
|
||||
def processTableFields(self, title, fields, row_style):
|
||||
return { 'title': unicode(title), 'fields': fields, 'row-style': row_style };
|
||||
|
||||
return {
|
||||
'title': unicode(title),
|
||||
'fields': fields,
|
||||
'row-style': row_style
|
||||
}
|
||||
|
||||
def readFieldsFromParams(self, fldList):
|
||||
args = {}
|
||||
try:
|
||||
@ -142,32 +149,33 @@ class BaseModelHandler(Handler):
|
||||
del self._params[key]
|
||||
except KeyError as e:
|
||||
raise RequestError('needed parameter not found in data {0}'.format(unicode(e)))
|
||||
|
||||
|
||||
return args
|
||||
|
||||
def fillIntanceFields(self, item, res):
|
||||
if hasattr(item, 'getInstance'):
|
||||
for key, value in item.getInstance().valuesDict().iteritems():
|
||||
if type(value) in (unicode, str):
|
||||
value = {"true":True, "false":False}.get(value, value) # Translate "true" & "false" to True & False (booleans)
|
||||
value = {"true": True, "false": False}.get(value, value) # Translate "true" & "false" to True & False (booleans)
|
||||
logger.debug('{0} = {1}'.format(key, value))
|
||||
res[key] = value
|
||||
return res
|
||||
|
||||
|
||||
# Exceptions
|
||||
def invalidRequestException(self):
|
||||
raise RequestError(_('Invalid Request'))
|
||||
|
||||
|
||||
def invalidMethodException(self):
|
||||
raise NotFound(_('Method not found'))
|
||||
|
||||
|
||||
def invalidItemException(self):
|
||||
raise NotFound(_('Item not found'))
|
||||
|
||||
|
||||
# Success methods
|
||||
def success(self):
|
||||
return 'done'
|
||||
|
||||
|
||||
# Details do not have types at all
|
||||
# so, right now, we only process details petitions for Handling & tables info
|
||||
class DetailHandler(BaseModelHandler):
|
||||
@ -177,7 +185,7 @@ class DetailHandler(BaseModelHandler):
|
||||
Urls recognized for GET are:
|
||||
[path] --> get Items (all hopefully, this call is delegated to getItems)
|
||||
[path]/overview
|
||||
[path]/ID
|
||||
[path]/ID
|
||||
[path]/gui
|
||||
[path]/gui/TYPE
|
||||
[path]/types
|
||||
@ -188,17 +196,17 @@ class DetailHandler(BaseModelHandler):
|
||||
[path]/ID --> Modify existing item
|
||||
For DELETE:
|
||||
[path]/ID
|
||||
|
||||
Also accepts GET methods for "custom" methods
|
||||
|
||||
Also accepts GET methods for "custom" methods
|
||||
'''
|
||||
|
||||
|
||||
def __init__(self, parentHandler, path, params, *args, **kwargs):
|
||||
self._parent = parentHandler
|
||||
self._path = path
|
||||
self._params = params
|
||||
self._args = args
|
||||
self._kwargs = kwargs
|
||||
|
||||
|
||||
def __checkCustom(self, check, parent, arg=None):
|
||||
logger.debug('Checking custom method {0}'.format(check))
|
||||
for cm in self.custom_methods:
|
||||
@ -207,7 +215,7 @@ class DetailHandler(BaseModelHandler):
|
||||
operation = getattr(self, cm)
|
||||
except:
|
||||
self.invalidMethodException()
|
||||
|
||||
|
||||
if arg is None:
|
||||
return operation(parent)
|
||||
else:
|
||||
@ -220,12 +228,12 @@ class DetailHandler(BaseModelHandler):
|
||||
nArgs = len(self._args)
|
||||
parent = self._kwargs['parent']
|
||||
if nArgs == 0:
|
||||
return self.getItems(parent, None)
|
||||
return self.getItems(parent, None)
|
||||
|
||||
# if has custom methods, look for if this request matches any of them
|
||||
r = self.__checkCustom(self._args[0], parent)
|
||||
if r is not None:
|
||||
return r
|
||||
return r
|
||||
|
||||
if nArgs == 1:
|
||||
if self._args[0] == OVERVIEW:
|
||||
@ -237,14 +245,14 @@ class DetailHandler(BaseModelHandler):
|
||||
return self.getTypes(parent, None)
|
||||
elif self._args[0] == TABLEINFO:
|
||||
return self.processTableFields(self.getTitle(parent), self.getFields(parent), self.getRowStyle(parent))
|
||||
|
||||
|
||||
# try to get id
|
||||
return self.getItems(parent, self._args[0])
|
||||
|
||||
|
||||
if nArgs == 2:
|
||||
if self._args[0] == GUI:
|
||||
gui = self.getGui(parent, self._args[1])
|
||||
return sorted(gui, key=lambda f: f['gui']['order'])
|
||||
return sorted(gui, key=lambda f: f['gui']['order'])
|
||||
elif self._args[0] == TYPES:
|
||||
return self.getTypes(parent, self._args[1])
|
||||
elif self._args[1] == LOG:
|
||||
@ -252,19 +260,18 @@ class DetailHandler(BaseModelHandler):
|
||||
else:
|
||||
r = self.__checkCustom(self._args[1], parent, self._args[0])
|
||||
if r is not None:
|
||||
return r
|
||||
|
||||
|
||||
return r
|
||||
|
||||
return self.fallbackGet()
|
||||
|
||||
|
||||
def put(self):
|
||||
'''
|
||||
Put is delegated to specific implementation
|
||||
'''
|
||||
logger.debug("Detail args for PUT: {0}, {1}".format(self._args, self._params))
|
||||
|
||||
|
||||
parent = self._kwargs['parent']
|
||||
|
||||
|
||||
if len(self._args) == 0:
|
||||
# Create new
|
||||
item = None
|
||||
@ -272,80 +279,81 @@ class DetailHandler(BaseModelHandler):
|
||||
item = self._args[0]
|
||||
else:
|
||||
self.invalidRequestException()
|
||||
|
||||
|
||||
return self.saveItem(parent, item)
|
||||
|
||||
|
||||
def post(self):
|
||||
'''
|
||||
Post will be used for, for example, testing
|
||||
Post will be used for, for example, testing
|
||||
'''
|
||||
raise NotFound('TODO: do it :-)')
|
||||
|
||||
|
||||
def delete(self):
|
||||
'''
|
||||
Put is delegated to specific implementation
|
||||
'''
|
||||
logger.debug("Detail args for DELETE: {0}".format(self._args))
|
||||
|
||||
|
||||
parent = self._kwargs['parent']
|
||||
|
||||
|
||||
if len(self._args) != 1:
|
||||
self.invalidRequestException()
|
||||
|
||||
|
||||
return self.deleteItem(parent, self._args[0])
|
||||
|
||||
|
||||
# Invoked if default get can't process request
|
||||
def fallbackGet(self):
|
||||
raise self.invalidRequestException()
|
||||
|
||||
|
||||
# Override this to provide functionality
|
||||
# Default (as sample) getItems
|
||||
def getItems(self, parent, item):
|
||||
if item is None: # Returns ALL detail items
|
||||
if item is None: # Returns ALL detail items
|
||||
return []
|
||||
return {} # Returns one item
|
||||
|
||||
return {} # Returns one item
|
||||
|
||||
# Default save
|
||||
def saveItem(self, parent, item):
|
||||
logger.debug('Default saveItem handler caller for {0}'.format(self._path))
|
||||
self.invalidRequestException()
|
||||
|
||||
|
||||
# Default delete
|
||||
def deleteItem(self, parent, item):
|
||||
self.invalidRequestException()
|
||||
|
||||
|
||||
# A detail handler must also return title & fields for tables
|
||||
def getTitle(self, parent):
|
||||
return ''
|
||||
|
||||
|
||||
def getFields(self, parent):
|
||||
return []
|
||||
|
||||
|
||||
def getRowStyle(self, parent):
|
||||
return {}
|
||||
|
||||
|
||||
def getGui(self, parent, forType):
|
||||
raise RequestError('Gui not provided for this type of object')
|
||||
|
||||
|
||||
def getTypes(self, parent, forType):
|
||||
return [] # Default is that details do not have types
|
||||
|
||||
return [] # Default is that details do not have types
|
||||
|
||||
def getLogs(self, parent, item):
|
||||
self.invalidMethodException()
|
||||
|
||||
|
||||
class ModelHandler(BaseModelHandler):
|
||||
'''
|
||||
Basic Handler for a model
|
||||
Basically we will need same operations for all models, so we can
|
||||
take advantage of this fact to not repeat same code again and again...
|
||||
|
||||
|
||||
Urls treated are:
|
||||
[path] --> Returns all elements for this path (including INSTANCE variables if it has it). (example: .../providers)
|
||||
[path]/overview --> Returns all elements for this path, not including INSTANCE variables. (example: .../providers/overview)
|
||||
[path]/ID --> Returns an exact element for this path. (example: .../providers/4)
|
||||
[path/ID/DETAIL --> Delegates to Detail, if it has details. (example: .../providers/4/services/overview, .../providers/5/services/9/gui, ....
|
||||
|
||||
Note: Instance variables are the variables declared and serialized by modules.
|
||||
[path/ID/DETAIL --> Delegates to Detail, if it has details. (example: .../providers/4/services/overview, .../providers/5/services/9/gui, ....
|
||||
|
||||
Note: Instance variables are the variables declared and serialized by modules.
|
||||
The only detail that has types within is "Service", child of "Provider"
|
||||
'''
|
||||
# Authentication related
|
||||
@ -353,75 +361,75 @@ class ModelHandler(BaseModelHandler):
|
||||
needs_staff = True
|
||||
# Which model does this manage
|
||||
model = None
|
||||
custom_methods = [] # If this model respond to "custom" methods, we will declare them here
|
||||
custom_methods = [] # If this model respond to "custom" methods, we will declare them here
|
||||
# This is an array of tuples of two items, where first is method and second inticates if method needs parent id
|
||||
# For example ('services', True) -- > .../id_parent/services
|
||||
# ('services', False) --> ..../services
|
||||
# ('services', False) --> ..../services
|
||||
# If this model has details, which ones
|
||||
detail = None # Dictionary containing detail routing
|
||||
detail = None # Dictionary containing detail routing
|
||||
# Put needed fields
|
||||
save_fields = []
|
||||
# Table info needed fields and title
|
||||
table_fields = []
|
||||
table_row_style = {}
|
||||
table_title = ''
|
||||
|
||||
|
||||
# This methods must be override, depending on what is provided
|
||||
|
||||
|
||||
# Data related
|
||||
def item_as_dict(self, item):
|
||||
pass
|
||||
|
||||
|
||||
# types related
|
||||
def enum_types(self): # override this
|
||||
def enum_types(self): # override this
|
||||
return []
|
||||
|
||||
|
||||
def getTypes(self, *args, **kwargs):
|
||||
for type_ in self.enum_types():
|
||||
yield self.type_as_dict(type_)
|
||||
|
||||
|
||||
def getType(self, type_):
|
||||
found = None
|
||||
for v in self.getTypes():
|
||||
if v['type'] == type_:
|
||||
found = v
|
||||
break
|
||||
|
||||
|
||||
if found is None:
|
||||
raise NotFound('type not found')
|
||||
|
||||
logger.debug('Found type {0}'.format(v))
|
||||
return found
|
||||
|
||||
|
||||
# log related
|
||||
def getLogs(self, item):
|
||||
logger.debug('Default getLogs invoked')
|
||||
return log.getLogs(item)
|
||||
|
||||
|
||||
# gui related
|
||||
def getGui(self, type_):
|
||||
self.invalidRequestException()
|
||||
|
||||
|
||||
# Delete related, checks if the item can be deleted
|
||||
# If it can't be so, raises an exception
|
||||
def checkDelete(self, item):
|
||||
pass
|
||||
|
||||
|
||||
# Save related, checks if the item can be saved
|
||||
# If it can't be saved, raises an exception
|
||||
def checkSave(self, item):
|
||||
pass
|
||||
|
||||
|
||||
# Invoked to possibily fix fields (or add new one, or check
|
||||
def beforeSave(self, fields):
|
||||
pass
|
||||
|
||||
|
||||
# Invoked right after saved an item (no matter if new or edition)
|
||||
def afterSave(self, item):
|
||||
pass
|
||||
|
||||
# End overridable
|
||||
|
||||
|
||||
# End overridable
|
||||
|
||||
# Helper to process detail
|
||||
def processDetail(self):
|
||||
logger.debug('Processing detail {0}'.format(self._path))
|
||||
@ -430,22 +438,22 @@ class ModelHandler(BaseModelHandler):
|
||||
detailCls = self.detail[self._args[1]]
|
||||
args = list(self._args[2:])
|
||||
path = self._path + '/'.join(args[:2])
|
||||
detail = detailCls(self, path, self._params, *args, parent = item)
|
||||
detail = detailCls(self, path, self._params, *args, parent=item)
|
||||
method = getattr(detail, self._operation)
|
||||
except KeyError:
|
||||
self.invalidMethodException()
|
||||
except AttributeError:
|
||||
self.invalidMethodException()
|
||||
|
||||
|
||||
return method()
|
||||
|
||||
def getItems(self, *args, **kwargs):
|
||||
for item in self.model.objects.filter(*args, **kwargs):
|
||||
try:
|
||||
try:
|
||||
yield self.item_as_dict(item)
|
||||
except:
|
||||
logger.exception('Exception getting item from {0}'.format(self.model))
|
||||
|
||||
|
||||
def get(self):
|
||||
logger.debug('method GET for {0}, {1}'.format(self.__class__.__name__, self._args))
|
||||
nArgs = len(self._args)
|
||||
@ -456,26 +464,26 @@ class ModelHandler(BaseModelHandler):
|
||||
self.fillIntanceFields(val, res)
|
||||
result.append(res)
|
||||
return result
|
||||
|
||||
|
||||
# if has custom methods, look for if this request matches any of them
|
||||
for cm in self.custom_methods:
|
||||
if nArgs > 1 and cm[1] is True: # Method needs parent (existing item)
|
||||
if self._args[1] == cm[0]:
|
||||
if nArgs > 1 and cm[1] is True: # Method needs parent (existing item)
|
||||
if self._args[1] == cm[0]:
|
||||
try:
|
||||
operation = getattr(self, self._args[1])
|
||||
item = self.model.objects.get(pk=self._args[0])
|
||||
except:
|
||||
self.invalidMethodException()
|
||||
|
||||
|
||||
return operation(item)
|
||||
elif self._args[0] == cm[0]:
|
||||
try:
|
||||
operation = getattr(self, self._args[0])
|
||||
except:
|
||||
self.invalidMethodException()
|
||||
|
||||
|
||||
return operation()
|
||||
|
||||
|
||||
if nArgs == 1:
|
||||
if self._args[0] == OVERVIEW:
|
||||
return list(self.getItems())
|
||||
@ -485,7 +493,7 @@ class ModelHandler(BaseModelHandler):
|
||||
return self.processTableFields(self.table_title, self.table_fields, self.table_row_style)
|
||||
elif self._args[0] == GUI:
|
||||
return self.getGui(None)
|
||||
|
||||
|
||||
# get item ID
|
||||
try:
|
||||
val = self.model.objects.get(pk=self._args[0])
|
||||
@ -494,9 +502,9 @@ class ModelHandler(BaseModelHandler):
|
||||
return res
|
||||
except:
|
||||
self.invalidItemException()
|
||||
|
||||
|
||||
# nArgs > 1
|
||||
# Request type info or gui, or detail
|
||||
# Request type info or gui, or detail
|
||||
if self._args[0] == TYPES:
|
||||
if nArgs != 2:
|
||||
self.invalidRequestException()
|
||||
@ -504,7 +512,7 @@ class ModelHandler(BaseModelHandler):
|
||||
elif self._args[0] == GUI:
|
||||
if nArgs != 2:
|
||||
self.invalidRequestException()
|
||||
gui = self.getGui(self._args[1])
|
||||
gui = self.getGui(self._args[1])
|
||||
return sorted(gui, key=lambda f: f['gui']['order'])
|
||||
elif self._args[1] == LOG:
|
||||
if nArgs != 2:
|
||||
@ -515,41 +523,41 @@ class ModelHandler(BaseModelHandler):
|
||||
self.invalidItemException()
|
||||
return self.getLogs(item)
|
||||
|
||||
# If has detail and is requesting detail
|
||||
# If has detail and is requesting detail
|
||||
if self.detail is not None:
|
||||
return self.processDetail()
|
||||
|
||||
|
||||
self.invalidRequestException()
|
||||
|
||||
|
||||
def post(self):
|
||||
# right now
|
||||
# right now
|
||||
logger.debug('method POST for {0}, {1}'.format(self.__class__.__name__, self._args))
|
||||
if len(self._args) == 2:
|
||||
if self._args[0] == 'test':
|
||||
return 'tested'
|
||||
|
||||
|
||||
self.invalidMethodException()
|
||||
|
||||
|
||||
def put(self):
|
||||
logger.debug('method PUT for {0}, {1}'.format(self.__class__.__name__, self._args))
|
||||
|
||||
if len(self._args) > 1: # Detail?
|
||||
|
||||
if len(self._args) > 1: # Detail?
|
||||
return self.processDetail()
|
||||
try:
|
||||
# Extract fields
|
||||
args = self.readFieldsFromParams(self.save_fields)
|
||||
self.beforeSave(args)
|
||||
deleteOnError = False
|
||||
if len(self._args) == 0: # create new
|
||||
if len(self._args) == 0: # create new
|
||||
item = self.model.objects.create(**args)
|
||||
deleteOnError = True
|
||||
else: # Must have 1 arg
|
||||
else: # Must have 1 arg
|
||||
# We have to take care with this case, update will efectively update records on db
|
||||
item = self.model.objects.get(pk=self._args[0]);
|
||||
item.__dict__.update(args) # Update fields from args
|
||||
except self.model.DoesNotExist:
|
||||
item = self.model.objects.get(pk=self._args[0])
|
||||
item.__dict__.update(args) # Update fields from args
|
||||
except self.model.DoesNotExist:
|
||||
raise NotFound('Item not found')
|
||||
except IntegrityError: # Duplicate key probably
|
||||
except IntegrityError: # Duplicate key probably
|
||||
raise RequestError('Element already exists (duplicate key error)')
|
||||
except SaveException as e:
|
||||
raise RequestError(unicode(e))
|
||||
@ -559,44 +567,43 @@ class ModelHandler(BaseModelHandler):
|
||||
logger.exception('Exception on put')
|
||||
raise RequestError('incorrect invocation to PUT')
|
||||
|
||||
if not deleteOnError:
|
||||
self.checkSave(item) # Will raise an exception if item can't be saved (only for modify operations..)
|
||||
if not deleteOnError:
|
||||
self.checkSave(item) # Will raise an exception if item can't be saved (only for modify operations..)
|
||||
|
||||
# Store associated object if needed
|
||||
try:
|
||||
if self._params.has_key('data_type'): # Needs to store instance
|
||||
if 'data_type' in self._params: # Needs to store instance
|
||||
item.data_type = self._params['data_type']
|
||||
item.data = item.getInstance(self._params).serialize()
|
||||
|
||||
|
||||
item.save()
|
||||
|
||||
|
||||
res = self.item_as_dict(item)
|
||||
self.fillIntanceFields(item, res)
|
||||
except:
|
||||
if deleteOnError:
|
||||
item.delete()
|
||||
raise
|
||||
|
||||
|
||||
self.afterSave(item)
|
||||
|
||||
return res
|
||||
|
||||
return res
|
||||
|
||||
def delete(self):
|
||||
logger.debug('method DELETE for {0}, {1}'.format(self.__class__.__name__, self._args))
|
||||
if len(self._args) > 1:
|
||||
if len(self._args) > 1:
|
||||
return self.processDetail()
|
||||
|
||||
|
||||
if len(self._args) != 1:
|
||||
raise RequestError('Delete need one and only one argument')
|
||||
try:
|
||||
item = self.model.objects.get(pk=self._args[0]);
|
||||
item = self.model.objects.get(pk=self._args[0])
|
||||
self.checkDelete(item)
|
||||
self.deleteItem(item)
|
||||
except self.model.DoesNotExist:
|
||||
raise NotFound('Element do not exists')
|
||||
|
||||
|
||||
return 'deleted'
|
||||
|
||||
def deleteItem(self, item):
|
||||
item.delete()
|
||||
|
@ -193,7 +193,7 @@ class PublicationManager(object):
|
||||
|
||||
@transaction.atomic
|
||||
def cancel(self, dsp):
|
||||
dsp = DeployedServicePublication.objects.select_for_update().get(id=dsp.id)
|
||||
dsp = DeployedServicePublication.objects.select_for_update().get(pk=dsp.id)
|
||||
if dsp.state not in State.PUBLISH_STATES:
|
||||
raise PublishException(_('Can\'t cancel non running publication'))
|
||||
|
||||
|
@ -298,7 +298,7 @@ class UserServiceManager(object):
|
||||
Cancels a user service creation
|
||||
@return: the Uservice canceling
|
||||
'''
|
||||
uService = UserService.objects.select_for_update().get(id=uService.id)
|
||||
uService = UserService.objects.select_for_update().get(pk=uService.id)
|
||||
logger.debug('Canceling uService {0} creation'.format(uService))
|
||||
if uService.isPreparing() == False:
|
||||
logger.INFO(_('Cancel requested for a non running operation, doing remove instead'))
|
||||
|
@ -8,6 +8,7 @@
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
|
||||
@ -17,29 +18,30 @@ Service modules for uds are contained inside this package.
|
||||
To create a new service module, you will need to follow this steps:
|
||||
1.- Create the service module, probably based on an existing one
|
||||
2.- Insert the module package as child of this package
|
||||
3.- Import the class of your service module at __init__. For example::
|
||||
from Service import SimpleService
|
||||
3.- Import the class of your service module at __init__. For example::
|
||||
from Service import SimpleService
|
||||
4.- Done. At Server restart, the module will be recognized, loaded and treated
|
||||
|
||||
|
||||
The registration of modules is done locating subclases of :py:class:`uds.core.auths.Authentication`
|
||||
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
|
||||
|
||||
def __init__():
|
||||
'''
|
||||
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
|
||||
|
||||
|
||||
# Dinamycally import children of this package. The __init__.py files must register, if needed, inside ServiceProviderFactory
|
||||
pkgpath = os.path.dirname(sys.modules[__name__].__file__)
|
||||
for _, name, _ in pkgutil.iter_modules([pkgpath]):
|
||||
__import__(name, globals(), locals(), [], -1)
|
||||
|
||||
|
||||
|
||||
logger.debug('Dispatchers initialized')
|
||||
|
||||
|
||||
__init__()
|
||||
|
@ -4,30 +4,29 @@
|
||||
# Copyright (c) 2013 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
|
||||
|
@ -4,35 +4,37 @@
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf.urls import patterns
|
||||
|
||||
|
||||
urlpatterns = patterns(__package__,
|
||||
(r'^guacamole/(?P<tunnelId>.+)$', 'views.guacamole'),
|
||||
)
|
||||
|
@ -4,33 +4,32 @@
|
||||
# Copyright (c) 2013 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.http import HttpResponse
|
||||
@ -46,26 +45,28 @@ CONTENT_TYPE = 'text/plain'
|
||||
|
||||
# We will use the cache to "hold" the tickets valid for users
|
||||
|
||||
|
||||
def dict2resp(dct):
|
||||
return '\r'.join(( k + '\t' + v for k, v in dct.iteritems()))
|
||||
return '\r'.join((k + '\t' + v for k, v in dct.iteritems()))
|
||||
|
||||
|
||||
@auth.trustedSourceRequired
|
||||
def guacamole(request, tunnelId):
|
||||
logger.debug('Received credentials request for tunnel id {0}'.format(tunnelId))
|
||||
|
||||
try:
|
||||
try:
|
||||
cache = Cache('guacamole')
|
||||
|
||||
|
||||
val = cache.get(tunnelId, None)
|
||||
|
||||
|
||||
# Remove key from cache, just 1 use
|
||||
# Cache has a limit lifetime, so we will allow to "reload" the page
|
||||
# cache.remove(tunnelId)
|
||||
|
||||
#response = 'protocol\trdp\rhostname\tw7adolfo\rusername\tadmin\rpassword\ttemporal'
|
||||
# Cache has a limit lifetime, so we will allow to "reload" the page
|
||||
# cache.remove(tunnelId)
|
||||
|
||||
# response = 'protocol\trdp\rhostname\tw7adolfo\rusername\tadmin\rpassword\ttemporal'
|
||||
response = dict2resp(val)
|
||||
|
||||
except:
|
||||
return HttpResponse(ERROR, content_type=CONTENT_TYPE)
|
||||
|
||||
|
||||
return HttpResponse(response, content_type=CONTENT_TYPE)
|
||||
|
@ -4,36 +4,36 @@
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf.urls import patterns
|
||||
|
||||
urlpatterns = patterns(__package__,
|
||||
(r'^pam$', 'views.pam'),
|
||||
)
|
||||
|
@ -4,32 +4,33 @@
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.http import HttpResponseNotAllowed, HttpResponse
|
||||
from uds.core.util.Cache import Cache
|
||||
@ -40,27 +41,28 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# We will use the cache to "hold" the tickets valid for users
|
||||
|
||||
|
||||
@auth.trustedSourceRequired
|
||||
def pam(request):
|
||||
response = ''
|
||||
cache = Cache('pam')
|
||||
if request.method == 'POST':
|
||||
return HttpResponseNotAllowed(['GET'])
|
||||
if request.GET.has_key('id') & request.GET.has_key('pass'):
|
||||
if 'id' in request.GET and 'pass' in request.GET:
|
||||
# This is an "auth" request
|
||||
logger.debug("Auth request for user [{0}] and pass [{1}]".format(request.GET['id'], request.GET['pass']))
|
||||
password = cache.get(request.GET['id'])
|
||||
response = '0'
|
||||
if password == request.GET['pass']:
|
||||
response = '1'
|
||||
cache.remove(request.GET['id']) # Ticket valid for just 1 login
|
||||
|
||||
elif request.GET.has_key('uid'):
|
||||
cache.remove(request.GET['id']) # Ticket valid for just 1 login
|
||||
|
||||
elif 'uid' in request.GET:
|
||||
# This is an "get name for id" call
|
||||
logger.debug("NSS Request for id [{0}]".format(request.GET['uid']))
|
||||
response = '10000 udstmp'
|
||||
elif request.GET.has_key('name'):
|
||||
elif 'name' in request.GET:
|
||||
logger.debug("NSS Request for username [{0}]".format(request.GET['name']))
|
||||
response = '10000 udstmp'
|
||||
|
||||
|
||||
return HttpResponse(response, content_type='text/plain')
|
||||
|
@ -4,32 +4,33 @@
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from uds.core.util.Config import Config, GLOBAL_SECTION
|
||||
@ -37,6 +38,7 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
args = "<mod.name=value mod.name=value mod.name=value...>"
|
||||
help = "Updates configuration values. If mod is omitted, UDS will be used. Omit whitespaces betwen name, =, and value (they must be a single param)"
|
||||
@ -55,4 +57,3 @@ class Command(BaseCommand):
|
||||
Config.update(mod, name, value)
|
||||
except Exception:
|
||||
logger.exception("Error")
|
||||
|
||||
|
@ -4,51 +4,59 @@
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from optparse import make_option
|
||||
from server.settings import SITE_ROOT, LOGDIR
|
||||
from django.conf import settings
|
||||
|
||||
from django.utils.daemonize import become_daemon
|
||||
from uds.core.managers.TaskManager import TaskManager
|
||||
import logging, sys, os, signal, time
|
||||
import logging
|
||||
import sys
|
||||
import os
|
||||
import signal
|
||||
import time
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
PID_FILE = 'taskmanager.pid'
|
||||
|
||||
|
||||
def getPidFile():
|
||||
return SITE_ROOT + '/' + PID_FILE
|
||||
return settings.SITE_ROOT + '/' + PID_FILE
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
args = "None"
|
||||
help = "Executes the task manager as a daemon. No parameter show current status of task manager"
|
||||
|
||||
|
||||
option_list = BaseCommand.option_list + (
|
||||
make_option('--start',
|
||||
action='store_true',
|
||||
@ -61,35 +69,35 @@ class Command(BaseCommand):
|
||||
default=False,
|
||||
help='Stop any running daemon'),
|
||||
)
|
||||
|
||||
|
||||
def handle(self, *args, **options):
|
||||
logger.info("Running task manager command")
|
||||
|
||||
|
||||
start = options['start'] and True or False
|
||||
stop = options['stop'] and True or False
|
||||
|
||||
|
||||
pid = None
|
||||
try:
|
||||
pid = int(file(getPidFile(), 'r').readline())
|
||||
except Exception:
|
||||
pid = None
|
||||
|
||||
|
||||
if stop is True and pid is not None:
|
||||
try:
|
||||
logger.info('Stopping task manager. pid: {0}'.format(pid))
|
||||
os.kill( pid, signal.SIGTERM )
|
||||
os.kill(pid, signal.SIGTERM)
|
||||
time.sleep(1) # Wait a bit before running new one
|
||||
os.unlink(getPidFile())
|
||||
except Exception:
|
||||
logger.error("Could not stop task manager (maybe it's not runing?)")
|
||||
os.unlink(getPidFile())
|
||||
|
||||
|
||||
if start is True:
|
||||
logger.info('Starting task manager.')
|
||||
become_daemon(SITE_ROOT, LOGDIR + '/taskManagerStdout.log', LOGDIR + '/taskManagerStderr.log')
|
||||
become_daemon(settings.SITE_ROOT, settings.LOGDIR + '/taskManagerStdout.log', settings.LOGDIR + '/taskManagerStderr.log')
|
||||
pid = str(os.getpid())
|
||||
file(getPidFile() ,'w+').write("%s\n" % pid)
|
||||
|
||||
file(getPidFile(), 'w+').write("%s\n" % pid)
|
||||
|
||||
manager = TaskManager()
|
||||
manager.run()
|
||||
|
||||
@ -98,4 +106,3 @@ class Command(BaseCommand):
|
||||
sys.stdout.write("Task manager found running (pid file exists: {0})\n".format(pid))
|
||||
else:
|
||||
sys.stdout.write("Task manager not foud (pid file do not exits)\n")
|
||||
|
@ -1,23 +1,24 @@
|
||||
# encoding: utf-8
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
|
||||
# Removing unique constraint on 'UserPreference', fields ['name', 'module']
|
||||
db.delete_unique('uds_userpreference', ['name', 'module'])
|
||||
|
||||
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
|
||||
# Adding unique constraint on 'UserPreference', fields ['name', 'module']
|
||||
db.create_unique('uds_userpreference', ['name', 'module'])
|
||||
|
||||
|
||||
|
||||
|
||||
models = {
|
||||
'uds.authenticator': {
|
||||
'Meta': {'object_name': 'Authenticator'},
|
||||
@ -196,5 +197,5 @@ class Migration(SchemaMigration):
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'userServices'", 'null': 'True', 'blank': 'True', 'to': "orm['uds.User']"})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,23 +1,24 @@
|
||||
# encoding: utf-8
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
|
||||
# Deleting field 'DeployedService.authenticator'
|
||||
db.delete_column('uds__deployed_service', 'authenticator_id')
|
||||
|
||||
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
|
||||
# Adding field 'DeployedService.authenticator'
|
||||
db.add_column('uds__deployed_service', 'authenticator', self.gf('django.db.models.fields.related.ForeignKey')(related_name='deployedServices', null=True, to=orm['uds.Authenticator'], blank=True), keep_default=False)
|
||||
|
||||
|
||||
|
||||
|
||||
models = {
|
||||
'uds.authenticator': {
|
||||
'Meta': {'object_name': 'Authenticator'},
|
||||
@ -195,5 +196,5 @@ class Migration(SchemaMigration):
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'userServices'", 'null': 'True', 'blank': 'True', 'to': "orm['uds.User']"})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,23 +1,24 @@
|
||||
# encoding: utf-8
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
|
||||
# Adding field 'DeployedService.state_date'
|
||||
db.add_column('uds__deployed_service', 'state_date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime(1972, 7, 1, 0, 0)), keep_default=False)
|
||||
|
||||
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
|
||||
# Deleting field 'DeployedService.state_date'
|
||||
db.delete_column('uds__deployed_service', 'state_date')
|
||||
|
||||
|
||||
|
||||
|
||||
models = {
|
||||
'uds.authenticator': {
|
||||
'Meta': {'object_name': 'Authenticator'},
|
||||
@ -196,5 +197,5 @@ class Migration(SchemaMigration):
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'userServices'", 'null': 'True', 'blank': 'True', 'to': "orm['uds.User']"})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,23 +1,24 @@
|
||||
# encoding: utf-8
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
|
||||
# Adding field 'Config.crypt'
|
||||
db.add_column('uds_configuration', 'crypt', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)
|
||||
|
||||
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
|
||||
# Deleting field 'Config.crypt'
|
||||
db.delete_column('uds_configuration', 'crypt')
|
||||
|
||||
|
||||
|
||||
|
||||
models = {
|
||||
'uds.authenticator': {
|
||||
'Meta': {'object_name': 'Authenticator'},
|
||||
@ -197,5 +198,5 @@ class Migration(SchemaMigration):
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'userServices'", 'null': 'True', 'blank': 'True', 'to': "orm['uds.User']"})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,23 +1,24 @@
|
||||
# encoding: utf-8
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
|
||||
# Changing field 'Storage.data'
|
||||
db.alter_column('uds_storage', 'data', self.gf('django.db.models.fields.TextField')())
|
||||
|
||||
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
|
||||
# Changing field 'Storage.data'
|
||||
db.alter_column('uds_storage', 'data', self.gf('django.db.models.fields.CharField')(max_length=1024))
|
||||
|
||||
|
||||
|
||||
|
||||
models = {
|
||||
'uds.authenticator': {
|
||||
'Meta': {'object_name': 'Authenticator'},
|
||||
@ -197,5 +198,5 @@ class Migration(SchemaMigration):
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'userServices'", 'null': 'True', 'blank': 'True', 'to': "orm['uds.User']"})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
@ -200,4 +201,4 @@ class Migration(SchemaMigration):
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['uds']
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
@ -233,4 +234,4 @@ class Migration(SchemaMigration):
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['uds']
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
@ -215,4 +216,4 @@ class Migration(SchemaMigration):
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['uds']
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
@ -212,4 +213,4 @@ class Migration(SchemaMigration):
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['uds']
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
@ -43,7 +44,7 @@ class Migration(SchemaMigration):
|
||||
|
||||
# Adding index on 'Config', fields ['key']
|
||||
db.create_index('uds_configuration', ['key'])
|
||||
|
||||
|
||||
from uds.models import Config
|
||||
try:
|
||||
Config.objects.get(section='UDS', key='maxRemovinggServices').delete()
|
||||
@ -284,4 +285,4 @@ class Migration(SchemaMigration):
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['uds']
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
@ -235,4 +236,4 @@ class Migration(SchemaMigration):
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['uds']
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
@ -255,4 +256,4 @@ class Migration(SchemaMigration):
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['uds']
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
@ -240,4 +241,4 @@ class Migration(SchemaMigration):
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['uds']
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
@ -235,4 +236,4 @@ class Migration(SchemaMigration):
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['uds']
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
@ -236,4 +237,4 @@ class Migration(SchemaMigration):
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['uds']
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
@ -232,4 +233,4 @@ class Migration(SchemaMigration):
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['uds']
|
||||
complete_apps = ['uds']
|
||||
|
@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @PydevCodeAnalysisIgnore
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import DataMigration
|
||||
@ -12,15 +13,15 @@ class Migration(DataMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
"Write your forwards methods here."
|
||||
# Note: Don't use "from appname.models import ModelName".
|
||||
# Note: Don't use "from appname.models import ModelName".
|
||||
# Use orm.ModelName to refer to models in this application,
|
||||
# and orm['appname.ModelName'] for models in other applications.
|
||||
if not db.dry_run:
|
||||
# Remove existing secirity values if they exists before "migrating" global ones
|
||||
for k in configKeys:
|
||||
try:
|
||||
o = orm.Config.objects.get(section=GLOBAL_SECTION,key=k)
|
||||
orm.Config.objects.filter(section=SECURITY_SECTION,key=k).delete()
|
||||
o = orm.Config.objects.get(section=GLOBAL_SECTION, key=k)
|
||||
orm.Config.objects.filter(section=SECURITY_SECTION, key=k).delete()
|
||||
o.section = SECURITY_SECTION
|
||||
o.save()
|
||||
except:
|
||||
@ -31,8 +32,8 @@ class Migration(DataMigration):
|
||||
if not db.dry_run:
|
||||
for k in configKeys:
|
||||
try:
|
||||
o = orm.Config.objects.get(section=SECURITY_SECTION,key=k)
|
||||
orm.Config.objects.filter(section=GLOBAL_SECTION,key=k).delete()
|
||||
o = orm.Config.objects.get(section=SECURITY_SECTION, key=k)
|
||||
orm.Config.objects.filter(section=GLOBAL_SECTION, key=k).delete()
|
||||
o.section = GLOBAL_SECTION
|
||||
o.save()
|
||||
except:
|
||||
|
@ -7,21 +7,22 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Ensure tables that needs to be in InnoDB are so
|
||||
def modify_MySQL_storage(*args, **kwargs):
|
||||
from django.db import connection
|
||||
cursor = connection.cursor()
|
||||
logger.info('Converting tables')
|
||||
|
||||
innoDbTables = ( models.UserService, models.DeployedService, models.DeployedServicePublication,
|
||||
|
||||
innoDbTables = (models.UserService, models.DeployedService, models.DeployedServicePublication,
|
||||
models.Scheduler, models.DelayedTask, models.User, models.Group, models.Authenticator,
|
||||
models.Service, models.Provider, models.Storage)
|
||||
for model in innoDbTables:
|
||||
db_table=model._meta.db_table
|
||||
stmt = 'ALTER TABLE %s ENGINE=%s' % (db_table,'InnoDB')
|
||||
db_table = model._meta.db_table
|
||||
stmt = 'ALTER TABLE %s ENGINE=%s' % (db_table, 'InnoDB')
|
||||
cursor.execute(stmt)
|
||||
# sets charset to utf8
|
||||
stmt = 'ALTER TABLE %s CHARACTER SET \'utf8\' COLLATE \'utf8_general_ci\'' % db_table
|
||||
cursor.execute(stmt)
|
||||
|
||||
#signals.post_migrate.connect(modify_MySQL_storage)
|
||||
# signals.post_migrate.connect(modify_MySQL_storage)
|
||||
|
@ -4,32 +4,33 @@
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext_noop as _
|
||||
from uds.core.ui.UserInterface import gui
|
||||
@ -41,46 +42,51 @@ from uds.core.managers.UserServiceManager import UserServiceManager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LinuxOsManager(osmanagers.OSManager):
|
||||
typeName = _('Linux OS Manager')
|
||||
typeType = 'LinuxManager'
|
||||
typeDescription = _('Os Manager to control linux virtual machines (basically renames machine and notify state)')
|
||||
iconFile = 'losmanager.png'
|
||||
|
||||
|
||||
|
||||
onLogout = gui.ChoiceField( label = _('On Logout'), order = 10, rdonly = False, tooltip = _('What to do when user logout from service'),
|
||||
values = [ {'id' : 'keep', 'text' : _('Keep service assigned') },
|
||||
{'id' : 'remove', 'text' : _('Remove service') }
|
||||
], defvalue = 'keep' )
|
||||
onLogout = gui.ChoiceField(
|
||||
label=_('On Logout'),
|
||||
order=10,
|
||||
rdonly=False,
|
||||
tooltip=_('What to do when user logout from service'),
|
||||
values=[
|
||||
{'id': 'keep', 'text': _('Keep service assigned')},
|
||||
{'id': 'remove', 'text': _('Remove service')}
|
||||
],
|
||||
defvalue='keep')
|
||||
|
||||
def __setProcessUnusedMachines(self):
|
||||
self.processUnusedMachines = self._onLogout == 'remove'
|
||||
|
||||
def __init__(self,environment, values):
|
||||
def __init__(self, environment, values):
|
||||
super(LinuxOsManager, self).__init__(environment, values)
|
||||
if values is not None:
|
||||
self._onLogout = values['onLogout']
|
||||
else:
|
||||
self._onLogout = ''
|
||||
|
||||
self.__setProcessUnusedMachines()
|
||||
|
||||
self.__setProcessUnusedMachines()
|
||||
|
||||
def release(self, service):
|
||||
pass
|
||||
|
||||
|
||||
def getName(self, service):
|
||||
'''
|
||||
gets name from deployed
|
||||
'''
|
||||
return service.getName()
|
||||
|
||||
def infoVal(self,service):
|
||||
|
||||
def infoVal(self, service):
|
||||
return 'rename:' + self.getName(service)
|
||||
|
||||
def infoValue(self,service):
|
||||
def infoValue(self, service):
|
||||
return 'rename\r' + self.getName(service)
|
||||
|
||||
|
||||
def notifyIp(self, uid, si, data):
|
||||
# Notifies IP to deployed
|
||||
pairs = data.split(',')
|
||||
@ -89,14 +95,14 @@ class LinuxOsManager(osmanagers.OSManager):
|
||||
if key.lower() == uid.lower():
|
||||
si.setIp(val)
|
||||
break
|
||||
|
||||
def process(self,service,msg, data):
|
||||
|
||||
def process(self, service, msg, data):
|
||||
'''
|
||||
We understand this messages:
|
||||
* msg = info, data = None. Get information about name of machine (or domain, in derived WinDomainOsManager class), old method
|
||||
* msg = information, data = None. Get information about name of machine (or domain, in derived WinDomainOsManager class), new method
|
||||
* msg = logon, data = Username, Informs that the username has logged in inside the machine
|
||||
* msg = logoff, data = Username, Informs that the username has logged out of the machine
|
||||
* msg = logoff, data = Username, Informs that the username has logged out of the machine
|
||||
* msg = ready, data = None, Informs machine ready to be used
|
||||
'''
|
||||
logger.info("Invoked LinuxOsManager for {0} with params: {1},{2}".format(service, msg, data))
|
||||
@ -106,7 +112,7 @@ class LinuxOsManager(osmanagers.OSManager):
|
||||
notifyReady = False
|
||||
doRemove = False
|
||||
state = service.os_state
|
||||
|
||||
|
||||
# Old "info" state, will be removed in a near future
|
||||
if msg == "info":
|
||||
ret = self.infoVal(service)
|
||||
@ -137,10 +143,10 @@ class LinuxOsManager(osmanagers.OSManager):
|
||||
notifyReady = True
|
||||
self.notifyIp(service.unique_id, si, data)
|
||||
service.updateData(si)
|
||||
|
||||
|
||||
service.setInUse(inUse)
|
||||
service.setOsState(state)
|
||||
|
||||
|
||||
# If notifyReady is not true, save state, let UserServiceManager do it for us else
|
||||
if doRemove is True:
|
||||
service.remove()
|
||||
@ -151,7 +157,7 @@ class LinuxOsManager(osmanagers.OSManager):
|
||||
UserServiceManager.manager().notifyReadyFromOsManager(service, '')
|
||||
logger.debug('Returning {0}'.format(ret))
|
||||
return ret
|
||||
|
||||
|
||||
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
|
||||
@ -159,9 +165,8 @@ class LinuxOsManager(osmanagers.OSManager):
|
||||
'''
|
||||
if self._onLogout == 'remove':
|
||||
userService.remove()
|
||||
|
||||
|
||||
def checkState(self,service):
|
||||
|
||||
def checkState(self, service):
|
||||
logger.debug('Checking state for service {0}'.format(service))
|
||||
return State.RUNNING
|
||||
|
||||
@ -169,13 +174,13 @@ class LinuxOsManager(osmanagers.OSManager):
|
||||
'''
|
||||
Serializes the os manager data so we can store it in database
|
||||
'''
|
||||
return str.join( '\t', [ 'v1', self._onLogout ] )
|
||||
|
||||
return str.join('\t', ['v1', self._onLogout])
|
||||
|
||||
def unmarshal(self, s):
|
||||
data = s.split('\t')
|
||||
if data[0] == 'v1':
|
||||
self._onLogout = data[1]
|
||||
self.__setProcessUnusedMachines()
|
||||
|
||||
self.__setProcessUnusedMachines()
|
||||
|
||||
def valuesDict(self):
|
||||
return { 'onLogout' : self._onLogout }
|
||||
return {'onLogout': self._onLogout}
|
||||
|
@ -4,42 +4,44 @@
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext_noop as _
|
||||
from uds.core.osmanagers.OSManagersFactory import OSManagersFactory
|
||||
from uds.core.managers.DownloadsManager import DownloadsManager
|
||||
from uds.osmanagers.LinuxOsManager.LinuxOsManager import LinuxOsManager
|
||||
import os.path, sys
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
OSManagersFactory.factory().insert(LinuxOsManager)
|
||||
|
||||
DownloadsManager.manager().registerDownloadable('udsactor_1.0_all.deb',
|
||||
DownloadsManager.manager().registerDownloadable('udsactor_1.0_all.deb',
|
||||
_('UDS Actor for linux machines <b>(Requires python 2.6 or greater)'),
|
||||
os.path.dirname(sys.modules[__package__].__file__) + '/files/udsactor_1.0_all.deb',
|
||||
os.path.dirname(sys.modules[__package__].__file__) + '/files/udsactor_1.0_all.deb',
|
||||
'application/x-debian-package')
|
||||
|
@ -8,6 +8,7 @@
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext_noop as _
|
||||
from uds.core.ui.UserInterface import gui
|
||||
@ -22,21 +23,22 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class WinDomainOsManager(WindowsOsManager):
|
||||
typeName = _('Windows Domain OS Manager')
|
||||
typeType = 'WinDomainManager'
|
||||
typeDescription = _('Os Manager to control windows machines with domain. (Basically renames machine)')
|
||||
iconFile = 'wosmanager.png'
|
||||
|
||||
iconFile = 'wosmanager.png'
|
||||
|
||||
# Apart form data from windows os manager, we need also domain and credentials
|
||||
domain = gui.TextField(length=64, label = _('Domain'), order = 1, tooltip = _('Domain to join machines to (use FQDN form, netbios name not allowed)'), required = True)
|
||||
account = gui.TextField(length=64, label = _('Account'), order = 2, tooltip = _('Account with rights to add machines to domain'), required = True)
|
||||
password = gui.PasswordField(length=64, label = _('Password'), order = 3, tooltip = _('Password of the account'), required = True)
|
||||
ou = gui.TextField(length=64, label = _('OU'), order = 4, tooltip = _('Organizational unit where to add machines in domain (check it before using it)'))
|
||||
domain = gui.TextField(length=64, label=_('Domain'), order=1, tooltip=_('Domain to join machines to (use FQDN form, netbios name not allowed)'), required=True)
|
||||
account = gui.TextField(length=64, label=_('Account'), order=2, tooltip=_('Account with rights to add machines to domain'), required=True)
|
||||
password = gui.PasswordField(length=64, label=_('Password'), order=3, tooltip=_('Password of the account'), required=True)
|
||||
ou = gui.TextField(length=64, label=_('OU'), order=4, tooltip=_('Organizational unit where to add machines in domain (check it before using it)'))
|
||||
# Inherits base "onLogout"
|
||||
onLogout = WindowsOsManager.onLogout
|
||||
|
||||
def __init__(self,environment, values):
|
||||
|
||||
def __init__(self, environment, values):
|
||||
super(WinDomainOsManager, self).__init__(environment, values)
|
||||
if values != None:
|
||||
if values['domain'] == '':
|
||||
@ -58,20 +60,20 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
self._ou = ""
|
||||
self._account = ""
|
||||
self._password = ""
|
||||
|
||||
|
||||
self._ou = self._ou.replace(' ', '')
|
||||
if self._domain != '' and self._ou != '':
|
||||
lpath = 'dc=' + ',dc='.join(self._domain.split('.'))
|
||||
if self._ou.find(lpath) == -1:
|
||||
self._ou += ',' + lpath
|
||||
|
||||
|
||||
def __getLdapError(self, e):
|
||||
logger.debug('Ldap Error: {0} {1}'.format(e, e.message))
|
||||
_str = ''
|
||||
if type(e.message) == dict:
|
||||
#_str += e.message.has_key('info') and e.message['info'] + ',' or ''
|
||||
_str += e.message.has_key('desc') and e.message['desc'] or ''
|
||||
else :
|
||||
# _str += e.message.has_key('info') and e.message['info'] + ',' or ''
|
||||
_str += e.message.get('desc', '')
|
||||
else:
|
||||
_str += str(e)
|
||||
return _str
|
||||
|
||||
@ -82,61 +84,59 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
dns.resolver.NXDOMAIN
|
||||
ldap.LDAPError
|
||||
'''
|
||||
servers = reversed(sorted(dns.resolver.query('_ldap._tcp.'+self._domain, 'SRV'), key=lambda i: i.priority * 10000 + i.weight))
|
||||
|
||||
servers = reversed(sorted(dns.resolver.query('_ldap._tcp.' + self._domain, 'SRV'), key=lambda i: i.priority * 10000 + i.weight))
|
||||
|
||||
for server in servers:
|
||||
|
||||
_str = ''
|
||||
|
||||
|
||||
try:
|
||||
uri = "%s://%s:%d" % ('ldap', str(server.target)[:-1], server.port)
|
||||
logger.debug('URI: {0}'.format(uri))
|
||||
|
||||
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) # Disable certificate check
|
||||
|
||||
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) # Disable certificate check
|
||||
l = ldap.initialize(uri=uri)
|
||||
l.set_option(ldap.OPT_REFERRALS, 0)
|
||||
l.network_timeout = l.timeout = 5
|
||||
l.protocol_version = ldap.VERSION3
|
||||
|
||||
|
||||
account = self._account
|
||||
if account.find('@') == -1:
|
||||
account += '@' + self._domain
|
||||
|
||||
|
||||
logger.debug('Account data: {0}, {1}, {2}, {3}'.format(self._account, self._domain, account, self._password))
|
||||
|
||||
l.simple_bind_s(who = account, cred = self._password)
|
||||
|
||||
|
||||
l.simple_bind_s(who=account, cred=self._password)
|
||||
|
||||
return l
|
||||
except ldap.LDAPError as e:
|
||||
_str = self.__getLdapError(e)
|
||||
|
||||
|
||||
raise ldap.LDAPError(_str)
|
||||
|
||||
|
||||
def release(self, service):
|
||||
'''
|
||||
service is a db user service object
|
||||
'''
|
||||
super(WinDomainOsManager,self).release(service)
|
||||
|
||||
try:
|
||||
l = self.__connectLdap()
|
||||
except dns.resolver.NXDOMAIN: # No domain found, log it and pass
|
||||
logger.warn('Could not find _ldap._tcp.'+self._domain)
|
||||
log.doLog(service, log.WARN, "Could not remove machine from domain (_ldap._tcp.{0} not found)".format(self._domain), log.OSMANAGER);
|
||||
except ldap.LDAPError:
|
||||
logger.exception('Ldap Exception caught')
|
||||
log.doLog(service, log.WARN, "Could not remove machine from domain (invalid credentials for {0})".format(self._account), log.OSMANAGER);
|
||||
|
||||
#_filter = '(&(objectClass=computer)(sAMAccountName=%s$))' % service.friendly_name
|
||||
super(WinDomainOsManager, self).release(service)
|
||||
|
||||
try:
|
||||
# res = l.search_ext_s(base = self._ou, scope = ldap.SCOPE_SUBTREE,
|
||||
l = self.__connectLdap()
|
||||
except dns.resolver.NXDOMAIN: # No domain found, log it and pass
|
||||
logger.warn('Could not find _ldap._tcp.' + self._domain)
|
||||
log.doLog(service, log.WARN, "Could not remove machine from domain (_ldap._tcp.{0} not found)".format(self._domain), log.OSMANAGER)
|
||||
except ldap.LDAPError:
|
||||
logger.exception('Ldap Exception caught')
|
||||
log.doLog(service, log.WARN, "Could not remove machine from domain (invalid credentials for {0})".format(self._account), log.OSMANAGER)
|
||||
|
||||
# _filter = '(&(objectClass=computer)(sAMAccountName=%s$))' % service.friendly_name
|
||||
|
||||
try:
|
||||
# res = l.search_ext_s(base = self._ou, scope = ldap.SCOPE_SUBTREE,
|
||||
# filterstr = _filter)[0]
|
||||
l.delete('cn={0},{1}'.format(service.friendly_name, self._ou))
|
||||
except:
|
||||
logger.exception('Not found: ')
|
||||
|
||||
|
||||
def check(self):
|
||||
try:
|
||||
@ -152,10 +152,8 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
l.search_st(self._ou, ldap.SCOPE_BASE)
|
||||
except ldap.LDAPError as e:
|
||||
return _('Check error: {0}').format(self.__getLdapError(e))
|
||||
|
||||
|
||||
|
||||
return _('Server check was successful')
|
||||
|
||||
|
||||
@staticmethod
|
||||
def test(env, data):
|
||||
@ -167,15 +165,15 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
l = wd.__connectLdap()
|
||||
except ldap.LDAPError as e:
|
||||
return [False, _('Could not access AD using LDAP ({0})').format(wd.__getLdapError(e))]
|
||||
|
||||
|
||||
ou = wd._ou
|
||||
if ou == '':
|
||||
ou = 'cn=Computers,dc='+',dc='.join(wd._domain.split('.'))
|
||||
|
||||
logger.debug('Checking {0} with ou {1}'.format(wd._domain,ou))
|
||||
ou = 'cn=Computers,dc=' + ',dc='.join(wd._domain.split('.'))
|
||||
|
||||
logger.debug('Checking {0} with ou {1}'.format(wd._domain, ou))
|
||||
r = l.search_st(ou, ldap.SCOPE_BASE)
|
||||
logger.debug('Result of search: {0}'.format(r))
|
||||
|
||||
|
||||
except ldap.LDAPError:
|
||||
if wd._ou == '':
|
||||
return [False, _('The default path {0} for computers was not found!!!').format(ou)]
|
||||
@ -186,23 +184,22 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
except Exception as e:
|
||||
logger.exception('Exception ')
|
||||
return [False, str(e)]
|
||||
|
||||
|
||||
return [True, _("All parameters seems to work fine.")]
|
||||
|
||||
|
||||
def infoVal(self, service):
|
||||
return 'domain:{0}\t{1}\t{2}\t{3}\t{4}'.format( self.getName(service), self._domain, self._ou, self._account, self._password)
|
||||
return 'domain:{0}\t{1}\t{2}\t{3}\t{4}'.format(self.getName(service), self._domain, self._ou, self._account, self._password)
|
||||
|
||||
def infoValue(self, service):
|
||||
return 'domain\r{0}\t{1}\t{2}\t{3}\t{4}'.format( self.getName(service), self._domain, self._ou, self._account, self._password)
|
||||
|
||||
return 'domain\r{0}\t{1}\t{2}\t{3}\t{4}'.format(self.getName(service), self._domain, self._ou, self._account, self._password)
|
||||
|
||||
def marshal(self):
|
||||
base = super(WinDomainOsManager,self).marshal()
|
||||
base = super(WinDomainOsManager, self).marshal()
|
||||
'''
|
||||
Serializes the os manager data so we can store it in database
|
||||
'''
|
||||
return str.join( '\t', [ 'v1', self._domain, self._ou, self._account, CryptoManager.manager().encrypt(self._password), base.encode('hex') ] )
|
||||
|
||||
return str.join('\t', ['v1', self._domain, self._ou, self._account, CryptoManager.manager().encrypt(self._password), base.encode('hex')])
|
||||
|
||||
def unmarshal(self, s):
|
||||
data = s.split('\t')
|
||||
if data[0] == 'v1':
|
||||
@ -211,12 +208,11 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
self._account = data[3]
|
||||
self._password = CryptoManager.manager().decrypt(data[4])
|
||||
super(WinDomainOsManager, self).unmarshal(data[5].decode('hex'))
|
||||
|
||||
|
||||
def valuesDict(self):
|
||||
dct = super(WinDomainOsManager,self).valuesDict()
|
||||
dct = super(WinDomainOsManager, self).valuesDict()
|
||||
dct['domain'] = self._domain
|
||||
dct['ou'] = self._ou
|
||||
dct['account'] = self._account
|
||||
dct['password'] = self._password
|
||||
return dct
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext_noop as _
|
||||
from uds.core.ui.UserInterface import gui
|
||||
@ -19,20 +20,21 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class WinRandomPassManager(WindowsOsManager):
|
||||
typeName = _('Windows Random Password OS Manager')
|
||||
typeType = 'WinRandomPasswordManager'
|
||||
typeDescription = _('Os Manager to control windows machines, with user password set randomly.')
|
||||
iconFile = 'wosmanager.png'
|
||||
|
||||
iconFile = 'wosmanager.png'
|
||||
|
||||
# Apart form data from windows os manager, we need also domain and credentials
|
||||
userAccount = gui.TextField(length=64, label = _('Account'), order = 2, tooltip = _('User account to change password'), required = True)
|
||||
password = gui.PasswordField(length=64, label = _('Password'), order = 3, tooltip = _('Current (template) password of the user account'), required = True)
|
||||
userAccount = gui.TextField(length=64, label=_('Account'), order=2, tooltip=_('User account to change password'), required=True)
|
||||
password = gui.PasswordField(length=64, label=_('Password'), order=3, tooltip=_('Current (template) password of the user account'), required=True)
|
||||
|
||||
# Inherits base "onLogout"
|
||||
onLogout = WindowsOsManager.onLogout
|
||||
|
||||
def __init__(self,environment, values):
|
||||
|
||||
def __init__(self, environment, values):
|
||||
super(WinRandomPassManager, self).__init__(environment, values)
|
||||
if values != None:
|
||||
if values['userAccount'] == '':
|
||||
@ -44,15 +46,15 @@ class WinRandomPassManager(WindowsOsManager):
|
||||
else:
|
||||
self._userAccount = ''
|
||||
self._password = ""
|
||||
|
||||
|
||||
def release(self, service):
|
||||
super(WinRandomPassManager,self).release(service)
|
||||
|
||||
super(WinRandomPassManager, self).release(service)
|
||||
|
||||
def processUserPassword(self, service, username, password):
|
||||
if username == self._userAccount:
|
||||
return [username, service.recoverValue('winOsRandomPass')]
|
||||
return [username, password]
|
||||
|
||||
|
||||
def genPassword(self, service):
|
||||
import random
|
||||
import string
|
||||
@ -61,30 +63,29 @@ class WinRandomPassManager(WindowsOsManager):
|
||||
randomPass = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(16))
|
||||
service.storeValue('winOsRandomPass', randomPass)
|
||||
return randomPass
|
||||
|
||||
|
||||
def infoVal(self, service):
|
||||
return 'rename:{0}\t{1}\t{2}\t{3}'.format( self.getName(service), self._userAccount, self._password, self.genPassword(service))
|
||||
return 'rename:{0}\t{1}\t{2}\t{3}'.format(self.getName(service), self._userAccount, self._password, self.genPassword(service))
|
||||
|
||||
def infoValue(self, service):
|
||||
return 'rename\r{0}\t{1}\t{2}\t{3}'.format( self.getName(service), self._userAccount, self._password, self.genPassword(service))
|
||||
|
||||
return 'rename\r{0}\t{1}\t{2}\t{3}'.format(self.getName(service), self._userAccount, self._password, self.genPassword(service))
|
||||
|
||||
def marshal(self):
|
||||
base = super(WinRandomPassManager,self).marshal()
|
||||
base = super(WinRandomPassManager, self).marshal()
|
||||
'''
|
||||
Serializes the os manager data so we can store it in database
|
||||
'''
|
||||
return str.join( '\t', [ 'v1', self._userAccount, CryptoManager.manager().encrypt(self._password), base.encode('hex') ] )
|
||||
|
||||
return str.join('\t', ['v1', self._userAccount, CryptoManager.manager().encrypt(self._password), base.encode('hex')])
|
||||
|
||||
def unmarshal(self, s):
|
||||
data = s.split('\t')
|
||||
if data[0] == 'v1':
|
||||
self._userAccount = data[1]
|
||||
self._password = CryptoManager.manager().decrypt(data[2])
|
||||
super(WinRandomPassManager, self).unmarshal(data[3].decode('hex'))
|
||||
|
||||
|
||||
def valuesDict(self):
|
||||
dic = super(WinRandomPassManager,self).valuesDict()
|
||||
dic = super(WinRandomPassManager, self).valuesDict()
|
||||
dic['userAccount'] = self._userAccount
|
||||
dic['password'] = self._password
|
||||
return dic
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext_noop as _
|
||||
from uds.core.ui.UserInterface import gui
|
||||
@ -28,7 +29,7 @@ def scrambleMsg(data):
|
||||
res = []
|
||||
n = 0x32
|
||||
for c in data[::-1]:
|
||||
res.append( chr(ord(c) ^ n) )
|
||||
res.append(chr(ord(c) ^ n))
|
||||
n = (n + ord(c)) & 0xFF
|
||||
return "".join(res).encode('hex')
|
||||
|
||||
@ -37,14 +38,21 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
typeName = _('Windows Basic OS Manager')
|
||||
typeType = 'WindowsManager'
|
||||
typeDescription = _('Os Manager to control windows machines without domain. (Basically renames machine)')
|
||||
iconFile = 'wosmanager.png'
|
||||
|
||||
onLogout = gui.ChoiceField( label = _('On Logout'), order = 10, rdonly = False, tooltip = _('What to do when user logout from service'),
|
||||
values = [ {'id' : 'keep', 'text' : _('Keep service assigned') },
|
||||
{'id' : 'remove', 'text' : _('Remove service') }
|
||||
], defvalue = 'keep' )
|
||||
|
||||
|
||||
iconFile = 'wosmanager.png'
|
||||
|
||||
onLogout = gui.ChoiceField(
|
||||
label=_('On Logout'),
|
||||
order=10,
|
||||
rdonly=False,
|
||||
tooltip=_('What to do when user logout from service'),
|
||||
values=[
|
||||
{'id': 'keep', 'text': _('Keep service assigned')},
|
||||
{'id': 'remove', 'text': _('Remove service')}
|
||||
],
|
||||
defvalue='keep'
|
||||
)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def validateLen(len):
|
||||
try:
|
||||
@ -54,11 +62,11 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
if len > 6 or len < 1:
|
||||
raise osmanagers.OSManager.ValidationException(_('Length must be betwen 1 and six'))
|
||||
return len
|
||||
|
||||
|
||||
def __setProcessUnusedMachines(self):
|
||||
self.processUnusedMachines = self._onLogout == 'remove'
|
||||
|
||||
def __init__(self,environment, values):
|
||||
|
||||
def __init__(self, environment, values):
|
||||
super(WindowsOsManager, self).__init__(environment, values)
|
||||
if values is not None:
|
||||
self._onLogout = values['onLogout']
|
||||
@ -66,22 +74,22 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
self._onLogout = ''
|
||||
|
||||
self.__setProcessUnusedMachines()
|
||||
|
||||
|
||||
def release(self, service):
|
||||
pass
|
||||
|
||||
|
||||
def getName(self, service):
|
||||
'''
|
||||
gets name from deployed
|
||||
'''
|
||||
return service.getName()
|
||||
|
||||
def infoVal(self,service):
|
||||
|
||||
def infoVal(self, service):
|
||||
return 'rename:' + self.getName(service)
|
||||
|
||||
def infoValue(self,service):
|
||||
def infoValue(self, service):
|
||||
return 'rename\r' + self.getName(service)
|
||||
|
||||
|
||||
def notifyIp(self, uid, si, data):
|
||||
# Notifies IP to deployed
|
||||
pairs = data.split(',')
|
||||
@ -90,24 +98,24 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
if key.lower() == uid.lower():
|
||||
si.setIp(val)
|
||||
break
|
||||
|
||||
def doLog(self, service, data, origin = log.OSMANAGER):
|
||||
|
||||
def doLog(self, service, data, origin=log.OSMANAGER):
|
||||
# Stores a log associated with this service
|
||||
try:
|
||||
|
||||
|
||||
msg, level = data.split('\t')
|
||||
log.doLog(service, level, msg, origin)
|
||||
except:
|
||||
log.doLog(service, log.ERROR, "do not understand {0}".format(data), origin)
|
||||
|
||||
|
||||
def process(self,service,msg, data):
|
||||
|
||||
|
||||
def process(self, service, msg, data):
|
||||
'''
|
||||
We understand this messages:
|
||||
* msg = info, data = None. Get information about name of machine (or domain, in derived WinDomainOsManager class) (old method)
|
||||
* msg = information, data = None. Get information about name of machine (or domain, in derived WinDomainOsManager class) (new method)
|
||||
* msg = logon, data = Username, Informs that the username has logged in inside the machine
|
||||
* msg = logoff, data = Username, Informs that the username has logged out of the machine
|
||||
* msg = logoff, data = Username, Informs that the username has logged out of the machine
|
||||
* msg = ready, data = None, Informs machine ready to be used
|
||||
'''
|
||||
logger.info("Invoked WindowsOsManager for {0} with params: {1},{2}".format(service, msg, data))
|
||||
@ -153,10 +161,10 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
notifyReady = True
|
||||
self.notifyIp(service.unique_id, si, data)
|
||||
service.updateData(si)
|
||||
|
||||
|
||||
service.setInUse(inUse)
|
||||
service.setOsState(state)
|
||||
|
||||
|
||||
# If notifyReady is not true, save state, let UserServiceManager do it for us else
|
||||
if doRemove is True:
|
||||
service.remove()
|
||||
@ -167,7 +175,7 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
UserServiceManager.manager().notifyReadyFromOsManager(service, '')
|
||||
logger.debug('Returning {0}'.format(ret))
|
||||
return scrambleMsg(ret)
|
||||
|
||||
|
||||
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
|
||||
@ -175,8 +183,8 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
'''
|
||||
if self._onLogout == 'remove':
|
||||
userService.remove()
|
||||
|
||||
def checkState(self,service):
|
||||
|
||||
def checkState(self, service):
|
||||
logger.debug('Checking state for service {0}'.format(service))
|
||||
return State.RUNNING
|
||||
|
||||
@ -184,15 +192,14 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
'''
|
||||
Serializes the os manager data so we can store it in database
|
||||
'''
|
||||
return str.join( '\t', [ 'v1', self._onLogout ] )
|
||||
|
||||
return str.join('\t', [ 'v1', self._onLogout ])
|
||||
|
||||
def unmarshal(self, s):
|
||||
data = s.split('\t')
|
||||
if data[0] == 'v1':
|
||||
self._onLogout = data[1]
|
||||
|
||||
|
||||
self.__setProcessUnusedMachines()
|
||||
|
||||
|
||||
def valuesDict(self):
|
||||
return { 'onLogout' : self._onLogout }
|
||||
|
@ -4,27 +4,27 @@
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# 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:
|
||||
#
|
||||
# * 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.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * 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
|
||||
# * 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
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# 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
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@ -32,32 +32,33 @@ OS Manager modules for uds are contained inside this package.
|
||||
To create a new OS manager module, you will need to follow this steps:
|
||||
1.- Create the os manager module, probably based on an existing one
|
||||
2.- Insert the module package as child of this package
|
||||
3.- Import the class of your os manager module at __init__. For example::
|
||||
from OSManager import SimpleOSManager
|
||||
3.- Import the class of your os manager module at __init__. For example::
|
||||
from OSManager import SimpleOSManager
|
||||
4.- Done. At Server restart, the module will be recognized, loaded and treated
|
||||
|
||||
|
||||
The registration of modules is done locating subclases of :py:class:`uds.core.auths.Authentication`
|
||||
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
def __init__():
|
||||
'''
|
||||
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 sys
|
||||
from uds.core import osmanagers
|
||||
|
||||
|
||||
# Dinamycally import children of this package. The __init__.py files must register, if needed, inside ServiceProviderFactory
|
||||
pkgpath = os.path.dirname(sys.modules[__name__].__file__)
|
||||
for _, name, _ in pkgutil.iter_modules([pkgpath]):
|
||||
__import__(name, globals(), locals(), [], -1)
|
||||
|
||||
|
||||
p = osmanagers.OSManager
|
||||
# This is marked as error in IDE, but it's not (__subclasses__)
|
||||
for cls in p.__subclasses__():
|
||||
osmanagers.factory().insert(cls)
|
||||
|
||||
|
||||
__init__()
|
||||
|
Loading…
x
Reference in New Issue
Block a user