class trace:
    '''
    Provides caching method result by method input parameters.
    '''

    logger = logging.get_logger()

    def __init__(self, *args, **options):
        pass

    def wrapper(self, func, *args, **kwargs):
        '''
        Wraps the function.
        
        @param func: function
        @return: depends on function
        '''

        start_time = time.time()
        try:
            # Returning the result
            return func(*args, **kwargs)
        except Exception, error:
            self.logger.debug('Error on executing function[%s.%s]:%s' %
                              (func.__module__, func.__name__, error))
            raise
        finally:
Пример #2
0
class PyroListener(Listener):
    '''
    Pyro listener.
    '''

    logger = logging.get_logger(name='PYRO')

    communicator_logger = logging.get_logger(name='communicator')

    def __init__(self, communicator, name, params, client_request_class=None):
        Listener.__init__(self,
                          communicator,
                          name,
                          params,
                          client_request_class=client_request_class)

        if not params.has_key('service_name'):
            params['service_name'] = self.get_name()

        Pyro.config.PYRO_MULTITHREADED = 1
        Pyro.core.initServer()
        self._daemon = Pyro.core.Daemon(host=self.host, port=self.port)
        #self.__daemon.setNewConnectionValidator(ConnectionValidator())
        self.add_service(PyroDispatcher(self), name=params['service_name'])
        self._exception_manager = PyroExceptionManager()

    def login(self, ip, user_name, password, **options):
        '''
        Logins in application.
        
        @param ip: client IP address
        @param user_name: user name
        @param password: user password
        '''
        try:
            return Listener.login(self, ip, user_name, password, **options)
        except DeltaException, error:
            # As login method calls login_ex method of the communicator, the raised
            # exception is already formatted when it reaches this method; hence, no
            # reformatting is needed.
            raise error
        except Exception, error:
            raise error
Пример #3
0
class XmlrpcListener(Listener):

    logger = logging.get_logger(name='xmlrpc')

    def __init__(self, communicator, name, params, client_request_class=None):
        Listener.__init__(self,
                          communicator,
                          name,
                          params,
                          client_request_class=client_request_class)

        if not params.has_key('service_name'):
            params['service_name'] = self.get_name()

        host = params.get('host')
        port = int(params.get('port'))

        self._server = DocXMLRPCServer(addr=(host, port),
                                       allow_none=1,
                                       logRequests=0)

        self.add_service(XmlrpcDispatcher(self), name=params['service_name'])

    def __get_instance_methods__(self, instance, prefix=None):
        methods = {}
        for o in dir(instance):
            if not o.startswith('_'):
                method = getattr(instance, o)
                if method.__class__.__name__ == 'instancemethod':
                    if prefix:
                        methods["%s.%s" % (prefix, o)] = method
                    else:
                        methods[o] = method
        return methods

    def add_service(self, service, **kwargs):
        '''
        Add a service to listener.
        
        @param service: service object
        '''

        name = kwargs.get('name', None)
        methods = self.__get_instance_methods__(service, name)
        for method_name, method in methods.items():
            self._server.register_function(method, method_name)

    def start(self):
        self._server.serve_forever()

    def stop(self, force):
        try:
            self._server.shutdown()
        except Exception, error:
            XmlrpcListener.logger.warning(error)
class TransactionCoordinatorRequestProcessorManagerHook(
        RequestProcessorManagerHook):

    LOGGER = logging_services.get_logger(name='request.coordinator')

    def __init__(self):
        RequestProcessorManagerHook.__init__(
            self, 'request_processor_manager.hook.coordinator')

    def on_process(self, request, **options):
        '''
        It will be called when a request starts to be processed
        
        @param ClientRequest request: client request
        '''

        coordinator_services.record_request(request)
        logging_services.debug(
            'Request [{0}] for service [{1}] recorded.'.format(
                request.id, request.command_key))

    def on_process_completed(self, request, response, **options):
        '''
        It will be called when a request is completed.
        
        @param ClientRequest request: client request
        @param ServerResponse response: server response
        '''

        coordinator_services.set_completed(request)
        logging_services.debug(
            'Request [{0}] for service [{1}] completed.'.format(
                request.id, request.command_key))

    def on_process_failed(self, request, error, **options):
        '''
        It will be called when a request is failed.
        
        @param ClientRequest request: client request
        @param Exception error: error content
        '''

        coordinator_services.set_failed(request, error.message)
        logging_services.debug(
            'Request [{0}] for service [{1}] failed.'.format(
                request.id, request.command_key))
Пример #5
0
class TaskExecutor:
    logger = logging.get_logger(name = 'scheduler')
    
    def __init__(self, on_running_task):
        self.running_threads = {}
        self.on_running_task = on_running_task
        self.tasks_lock = Lock()
        
    def __run_task__(self,task):        
        try:
            self.tasks_lock.acquire()
            if self.on_running_task:
                self.on_running_task(task)        
            self.running_threads[task.task_id]= task        
            task.status = Task.RUNNING
            task.run()
            self.running_threads.pop(task.task_id)
        except Exception, e:
            TaskExecutor.logger.exception(e)
            raise
        finally:
Пример #6
0
class BatchProcessManager(DeltaObject):
    '''
    Provides management on process units.
    '''

    logger = logging.get_logger(name='batch')

    def __init__(self):
        DeltaObject.__init__(self)
        self.__process_units = {}

    def __get_process_unit_data__(self, name):
        '''
        Returns specific batch processor.
        
        @param name: name of batch processor.
        '''
        try:
            return self.__process_units[name]
        except KeyError:
            raise BatchProcessManagerException("Process unit[%s] not found." %
                                               name)

    def __get_parallel_executor__(self, process_unit_name):
        '''
        Returns parallel executor of a process unit.
        
        @param process_unit_name: process unit name
        @return: ParallelExecutor
        '''

        # Getting process unit data
        data = self.__get_process_unit_data__(process_unit_name)

        # data is a tuple of (process_unit, parallel_executor)
        return data[1]

    def get_process_units(self, status=None):
        '''
        Returns all process units by the given status
        
        @param status: status
            'Stopped'
            'InProgress'
            'Suspended'
            'Completed'
            'Ready'
            'NotReady'
            'Failed'
        @return: [ProcessUnit]
        '''

        process_units = []
        for process_unit, parallel_executor in self.__process_units.values():
            #Commented because batch.list command returned Empty Result.
            #if parallel_executor is not None:
            if not status or parallel_executor.get_status() == status:
                process_units.append(process_unit)
        return process_units

    def get_process_unit(self, name):
        '''
        Returns specific process unit.
        
        @param name: name of process unit.
        @return: ProcessUnit
        '''

        # Getting process unit data
        data = self.__get_process_unit_data__(name)

        # data is a tuple of (process_unit, parallel_executor)
        return data[0]

    def add_process_unit(self, process_unit, **options):
        '''
        Adds a process unit to batch processor.
        If a process unit with the same ID exists,
        it will override it.

        @param process_unit: process unit instance
        '''

        # Getting process unit name
        name = process_unit.get_name()

        # Adding process unit data as a tuple
        # (process unit instance, parallel executor instance)
        self.__process_units[name] = (process_unit, None)

    def __before_start_process_unit__(self, process_unit, parallel_executor,
                                      thread_count, params):
        # TODO: BatchProcessManager start hooks
        # Calling process unit to creating it's chunks

        process_unit_name = process_unit.get_name()

        BatchProcessManager.logger.info(
            "Process unit[%s] started it's chunks creation." %
            process_unit_name)
        chunks = process_unit.create_chunks()
        BatchProcessManager.logger.info(
            "Process unit[%s] finished it's chunks creation." %
            process_unit_name)

        if chunks is None or len(chunks) == 0:
            message = _(
                'Can not start process unit[{unit_name}] without chunks.')
            process_unit.get_message_stream().error(
                message.format(unit_name=process_unit_name))
            raise BatchProcessManagerException(
                message.format(unit_name=process_unit_name))

        message = _(
            'Process unit[{unit_name}] will be started by {chunk_count} chunks.'
        )
        BatchProcessManager.logger.info(
            message.format(unit_name=process_unit_name,
                           chunk_count=len(chunks)))

        # Adding created chunks as parallel executor parameters
        parallel_executor.add_parameters(chunks)

    def __after_finished_process_unit__(self, process_unit):
        process_unit.done()
        BatchProcessManager.logger.info('Process unit[%s] completed.' %
                                        process_unit.get_name())
        process_unit.get_message_stream().info('Process unit[%s] completed.' %
                                               process_unit.get_name())

        # TODO: BatchProcessManager complete hooks
    def __on_proccess_unit_failed__(self, process_unit, error, error_trace):
        try:
            BatchProcessManager.logger.error(
                'Process unit[%s] failed:%s.' %
                (process_unit.get_name(), error_trace))
            process_unit.get_message_stream().error(
                'Process unit[%s] failed:%s.' %
                (process_unit.get_name(), error_trace))
            process_unit.failed(error)
        except:
            BatchProcessManager.logger.error(
                'Process unit[%s] failed:%s.' %
                (process_unit.get_name(), traceback.format_exc()))
            process_unit.get_message_stream().error(
                'Process unit[%s] failed:%s.' %
                (process_unit.get_name(), traceback.format_exc()))

    def __before_start_process_unit_chunk__(self, process_unit, chunk):
        BatchProcessManager.logger.info(
            'Process unit[%s] is going to start chunk[%s].' %
            (process_unit.get_name(), chunk))
        process_unit.get_message_stream().info(
            'Process unit[%s] is going to start chunk[%s].' %
            (process_unit.get_name(), chunk))

    def __after_complete_process_unit_chunk__(self, process_unit, chunk,
                                              result):
        BatchProcessManager.logger.info(
            'Process unit[%s] finished chunk[%s].' %
            (process_unit.get_name(), chunk))
        process_unit.get_message_stream().info(
            'Process unit[%s] finished chunk[%s].' %
            (process_unit.get_name(), chunk))

    def __on_process_unit_chunk_failed__(self, process_unit, chunk, error):
        error_detail = traceback.format_exc()
        BatchProcessManager.logger.error(
            'Process unit[%s] failed on chunk[%s] : %s\n Trace: %s.' %
            (process_unit.get_name(), chunk, error, error_detail))
        process_unit.get_message_stream().error(
            'Process unit[%s] failed on chunk[%s] : %s\n Trace: %s.' %
            (process_unit.get_name(), chunk, error, error_detail))

    def __get_process_unit_config__(self, name):
        '''
        Returns process unit configuration from batch.config file.
        
        @param name: process unit name
        '''

        # Getting batch configuration store
        config_store = config.get_app_config_store('batch')

        # Getting default parameters from configuration file.
        if config_store.has_section(name):
            return config_store.get_section_data(name)
        return DynamicObject(thread_count=1)

    def start(self, process_unit_name, **options):
        '''
        Starts a process unit.
        
        @param process_unit_name: process unit name
        '''

        BatchProcessManager.logger.info('Loading process unit[%s]' %
                                        process_unit_name)
        process_unit = None
        try:
            parallel_executor = self.__get_parallel_executor__(
                process_unit_name)
            if parallel_executor is not None and not parallel_executor.can_run(
            ):
                raise BatchProcessManagerException(
                    'Process unit[%s] is %s.' %
                    (process_unit_name, self.get_status(process_unit_name)))

            # Getting process unit default parameters
            params = self.__get_process_unit_config__(process_unit_name)

            # Checking process unit enable flag
            enabled = bool(params.get('enabled', True))

            #TODO: it should be add to base of process unit and set_enable command
            # should be created.
            if enabled == False:
                raise BatchProcessManagerException(
                    'Process unit[%s] is disabled.' % (process_unit_name))

            # Updating default parameters with given options
            params.update(options)

            # Getting process unit instance
            process_unit = self.get_process_unit(process_unit_name)

            # Configuring the process unit with updated parameters
            process_unit.configure(**params)

            # Getting joining information
            joined_groups = process_unit.get_joined_groups()
            joined_units = process_unit.get_joined_units()

            # Joining to groups and units
            for joined_group in joined_groups:
                self.join_to_group(joined_group)
            for joined_unit in joined_units:
                self.join(joined_unit)

            # Getting thread count
            thread_count = int(params.get('thread_count', 1))

            # Creating a new parallel executor instance
            parallel_executor = ParallelExecutor(process_unit.get_name(),
                                                 process_unit.process,
                                                 thread_count)

            # Creating event handler functions
            before_start = lambda: self.__before_start_process_unit__(
                process_unit, parallel_executor, thread_count, params)
            after_finished = lambda: self.__after_finished_process_unit__(
                process_unit)
            on_failed = lambda error, error_trace: self.__on_proccess_unit_failed__(
                process_unit, error, error_trace)
            before_start_task = lambda chunk: self.__before_start_process_unit_chunk__(
                process_unit, chunk)
            after_complete_task = lambda chunk, result: self.__after_complete_process_unit_chunk__(
                process_unit, chunk, result)
            on_task_failed = lambda chunk, error: self.__on_process_unit_chunk_failed__(
                process_unit, chunk, error)

            # Setting parallel executor event handler functions
            parallel_executor.set_before_start(before_start)
            parallel_executor.set_after_finished(after_finished)
            parallel_executor.set_on_failed(on_failed)
            parallel_executor.set_before_start_task(before_start_task)
            parallel_executor.set_after_complete_task(after_complete_task)
            parallel_executor.set_on_task_failed(on_task_failed)

            # Updating process unit data with created new parallel executor
            self.__process_units[process_unit_name] = (process_unit,
                                                       parallel_executor)

            BatchProcessManager.logger.info(
                'Process unit[%s] is creating chunks, its may takes a several minutes...'
                % process_unit_name)

            # Truncating process unit message stream
            process_unit.get_message_stream().truncate()
            process_unit.get_message_stream().info(
                'Started with parameters[%s]' % params)

            # Starting parallel executor to running batch operation
            parallel_executor.start()

            BatchProcessManager.logger.info(
                'Process unit[%s] started with parameters[%s].' %
                (process_unit_name, params))

        except Exception, error:
            message = 'Starting process unit[{0}] failed:{1}'
            BatchProcessManager.logger.error(
                message.format(process_unit_name, traceback.format_exc()))
            if process_unit is not None:
                message = 'Starting failed:{0}'
                process_unit.get_message_stream().error(
                    message.format(str(error)))
                process_unit.failed(error)
            raise
class Communicator(DeltaObject):
    '''
    The communicator class which is for maintaining listeners.
    '''
    logger = logging.get_logger(name='communicator')

    def __init__(self):
        '''
        The constructor.
        '''

        DeltaObject.__init__(self)
        self.__factories = {}
        self.__listeners = {}
        self.__default_listener_name = None
        self.__hooks = []

    def register_factory(self, type_name, factory):
        '''
        Registers a listener.
        
        @param listener: listener object which inherited from the Listener class
        '''

        self.__factories[type_name] = factory

    def get_factory(self, type_name):
        '''
        Return broker factory by broker type name.
        
        @param type_name: type name
        @return: CommunicationFactory
        '''
        if type_name not in self.__factories:
            raise CommunicatorException('Factory[%s] not found.' % type_name)
        return self.__factories[type_name]

    def get_listener(self, name):
        '''
        Returns the listener by name.
        
        @param name: name of the listener in str
        @return: listener[Listener]
        '''

        # Looking for listener...
        if name not in self.__listeners:
            raise CommunicatorException('Listener[%s] is not registered.' %
                                        name)

        # Getting listener...
        listener, thread = self.__listeners[name]

        return listener

    def get_listeners(self):
        """
        Returns all listeners
        
        @return: list<Listener>
        """

        return [listener for listener, thread in self.__listeners.values()]

    def _get_listener_settings_(self, config_store=None):
        '''
        Returns listener settings.
        
        @return: dict
        '''
        listener_settings = {}
        if config_store is None:
            config_name = "%s.communication" % get_app().get_name()
            config_store = config.get_config_store(config_name)

        sections = config_store.get_sections()
        self.__default_listener_name = config_store.get(
            'global', 'default', None)
        for name in sections:
            if name != 'global':
                data = config_store.get_section_data(name)
                if not data.has_key('type'):
                    raise CommunicatorException('Listener[%s] has not type.' %
                                                name)
                listener_settings[name] = data
                if self.__default_listener_name is None:
                    self.__default_listener_name = name
        return listener_settings

    def start(self, config_store=None):
        '''
        Starts all listeners which is defined in communication configuration.
        '''
        Communicator.logger.info('Starting communicator.')

        try:
            listener_settings = self._get_listener_settings_(config_store)

            for listener_name in listener_settings:
                kwargs = listener_settings[listener_name]
                type_name = kwargs['type']
                factory = self.get_factory(type_name)
                listener = factory.create_listener(self, listener_name, kwargs)
                self.__listeners[listener_name] = listener, None
                Communicator.logger.info(
                    'Listener[{lname}] created with params[{lparam}].'.format(
                        lname=listener_name, lparam=kwargs))

            for listener_name in self.__listeners:
                listener, thread = self.__listeners[listener_name]
                Communicator.logger.info(
                    'Starting listener[{lname}]...'.format(
                        lname=listener_name))
                thread = run_in_thread(listener.start)
                self.__listeners[listener_name] = listener, thread
                Communicator.logger.info(
                    'Listener[{lname}] started.'.format(lname=listener_name))

            Communicator.logger.info('Communicator started successfully.')
        except Exception:
            Communicator.logger.error('Starting communicator failed:%s' %
                                      (traceback.format_exc()))
            raise

    def stop(self, force=False):
        '''
        Stops all listeners.
        
        @param force: 
        '''

        try:

            Communicator.logger.info('Stopping communicator started.')
            threads = []
            for listener_name in self.__listeners:
                listener, thread = self.__listeners[listener_name]
                Communicator.logger.info(
                    'Stopping listener[{lname}]...'.format(
                        lname=listener_name))
                listener.stop(force)
                Communicator.logger.info(
                    'Listener[{lname}] stopped.'.format(lname=listener_name))
                threads.append(thread)

            if not force:
                for t in threads:
                    t.join()

            Communicator.logger.info('Stopping request processor...')
        except Exception:
            Communicator.logger.error('Stopping communicator failed:%s' %
                                      (traceback.format_exc()))
            raise

    def create_proxy_by_ticket(self, ticket, user_name, **kwargs):
        '''
        Creates a proxy on the given broker type and returns it.
        
        @param ticket: security ticket
        @param user_name: user name
        @return: Proxy 
        '''

        type_name = kwargs.get('type')
        factory = self.get_factory(type_name)
        return factory.create_proxy_by_ticket(ticket, user_name, **kwargs)

    def create_proxy(self, user_name, password, **kwargs):
        '''
        Creates a proxy on the given broker type and returns it.
        
        @param user_name: user name
        @param password: password
        @return: Proxy 
        '''

        type_name = kwargs.get('type')
        factory = self.get_factory(type_name)
        return factory.create_proxy(user_name, password, **kwargs)

    def get_listener_params(self, name):
        '''
        Returns the listener parameters.
        
        @param name: listener name
        @return: dict 
        '''

        return self.get_listener(name).get_params()

    def get_default_listener(self):
        """
        Returns the default listener.
        
        @return: Listener
        """

        return self.get_listener(self.__default_listener_name)

    def login(self, listener, login_request):
        '''
        Logins in application.
        
        @param instance login_request: Client's login request.
        @type login_request: Instance of RawRequest.

        @return: dict<ticket,
                      login_date,
                      data>
        '''

        if not listener.is_enable():
            Communicator.logger.error('Listener[%s] is disabled.' %
                                      listener.get_name())
            raise CommunicatorException('Listener[%s] is disabled.' %
                                        listener.get_name())

        try:
            return request_processor.login(login_request)

        except Exception:
            Communicator.logger.error(traceback.format_exc())
            raise

    def logout(self, listener, logout_request):
        '''
        Log outs the user.
         
        @param instance logout_request: Client's logout request.
        @type logout_request: Instance of RawRequest.
        '''

        if not listener.is_enable():
            Communicator.logger.error('Listener[%s] is disabled.' %
                                      listener.get_name())
            raise CommunicatorException('Listener[%s] is disabled.' %
                                        listener.get_name())

        return request_processor.logout(logout_request)

    def execute(self, listener, request, **options):
        '''
        Executes the given request.
        
        @param listener: listener instance
        @param request: client request
        
        @return: object
        '''

        try:
            if not listener.is_enable():
                raise CommunicatorException('Listener[%s] is disabled.' %
                                            listener.get_name())

            # Processing the request.
            return request_processor.process(request, **options)

        except Exception:
            Communicator.logger.error(traceback.format_exc())
            raise

    def add_hook(self, hook):
        '''
        Sets communicator hook.
        
        @param hook: hook
        '''

        self.__hooks.append(hook)

    def get_hooks(self):
        '''
        Returns communicator hook.
        
        @return: CommunicatorHook
        '''

        return self.__hooks
import os
import sys
import time
import errno
import threading
import traceback
import multiprocessing
from datetime import datetime
from random import randint

from deltapy.core import DeltaException
from deltapy.multiprocessing.base import BasePool
from deltapy.logging.services import get_logger

LOGGER = get_logger(name='requestprocessor')


class DeltaError(DeltaException):
    def __init__(self, message, code=None, data={}, traceback=None):
        DeltaException.__init__(self, message)
        self._code = self.__class__.__name__
        if code is not None:
            self._code = code
        self._data = data
        self._traceback = traceback

    def get_code(self):
        return self._code

class TransactionCoordinatorCommandExecutionHook(CommandExecutionHook):
    '''
    Transaction Coordinator Command Execution Hook
    '''

    LOGGER = logging_services.get_logger(name='request.coordinator')

    def before_execute(self, commander, command, *args, **kargs):
        '''
        This method will be called before command execution.

        @param commander: commander
        @param command: command
        '''

        if not self._is_required_to_record_request(command):
            return

        request = session_services.get_current_session().get_client_request()
        coordinator_services.record_request(
            command.get_option('recorder_type'), request)
        logging_services.debug(
            'Request [{0}] for service [{1}] recorded.'.format(
                request.id, command.get_key()))

    def after_execute(self, commander, command, result, *args, **kargs):
        '''
        This method will be called after command execution.

        @param commander: commander
        @param command: command
        @param result: command execution result
        '''

        if not self._is_required_to_record_request(command):
            return

        request = session_services.get_current_session().get_client_request()
        coordinator_services.set_completed(command.get_option('recorder_type'),
                                           request, result)
        logging_services.debug(
            'Request [{0}] for service [{1}] completed.'.format(
                request.id, command.get_key()))

    def exception(self, commander, command, error, *args, **kargs):
        '''
        This method will be called whenever an exception occurred during executing a command.

        @param commander: commander
        @param command: command
        @param error: exception instance
        '''

        if not self._is_required_to_record_request(command):
            return

        request = session_services.get_current_session().get_client_request()
        coordinator_services.set_failed(command.get_option('recorder_type'),
                                        request, error)
        logging_services.debug(
            'Request [{0}] for service [{1}] failed.'.format(
                request.id, command.get_key()))

    def _is_required_to_record_request(self, command):
        '''
        Returns True if the request must be recorded.

        @param Command command: command instance

        @rtype: bool
        @return: True or False
        '''

        if not self.is_enable():
            return False

        recorder_type = command.get_option('recorder_type')
        return recorder_type not in (None, '')
Пример #10
0
class RequestProcessorManager(DeltaObject):
    '''
    Request processor manager.
    '''

    logger = logging.get_logger(name='requestprocessor')

    def __init__(self):
        DeltaObject.__init__(self)
        self._processors = {}
        self._hooks = []
        self._default_processor_name = None
        self._event = Event()
        self._event.clear()

    def register_request_processor_hook(self, hook):
        '''
        Registers the given hook for request processor manager.
        
        @param RequestProcessorManagerHook hook: hook instance
        '''

        index = 0
        for older_hook in self._hooks:
            if older_hook.get_name() == hook.get_name():
                self._hooks[index] = hook
                return
            index += 1

        self._hooks.append(hook)

    def get_request_processor_hooks(self):
        '''
        Returns all of the registered hooks.
        
        @rtype: list(RequestProcessorManagerHook)
        @return: request processor list
        '''

        return self._hooks

    def register_processor(self, processor):
        '''
        Registers given processor.
        @param processor:
        '''
        if self._default_processor_name is None:
            self.set_default_processor(processor.get_name())
        self._processors[processor.get_name()] = processor

    def set_default_processor(self, processor_name):
        '''
        Sets given processor as default processor.
        @param processor_name:
        '''
        self._default_processor_name = processor_name

    def get_processors(self):
        '''
        Returns all registered processors.
        '''
        return self._processors

    def get_processor(self, name=None):
        '''
        Returns registered processor using given name.
        '''
        key = self._default_processor_name
        if name is not None:
            key = name
        if key in self._processors:
            return self._processors[key]
        raise RequestProcessorManagerException(
            "Could'nt find processor[{name}] in registered processors.".format(
                name=key))

    def wait_for_ready(self):
        '''
        Waits for request processor until it's status be ready.
        '''

        self._event.wait()

    def start(self, **options):
        '''
        Starts request processor.

        @keyword processor_name: Processor to start. If it not provided,
           default processor in configs will be used.

        @note: Other options will directly pass to the processor.
        '''

        # Getting configuration store
        config_store = config.get_app_config_store('request_processor')
        default_processor_name = config_store.get('global', 'default', None)

        processor_name = options.get('processor_name')
        if processor_name is not None:
            self.set_default_processor(processor_name)
            options.pop('processor_name')

        elif default_processor_name is not None:
            self.set_default_processor(default_processor_name)

        params = config_store.get_section_data(self._default_processor_name)
        params.update(**options)

        processor = self.get_processor()
        processor.configure(params)
        self._event.set()

        RequestProcessorManager.logger.info('Request processor started.')

    def terminate(self, name=None):
        '''
        Terminates given processor.
        @param name:
        '''

        RequestProcessorManager.logger.info(
            'Terminating request processor [{name}]...'.format(name=name))
        processor = self.get_processor(name)
        processor.terminate()
        RequestProcessorManager.logger.info(
            'Request processor [{name}] terminated.'.format(name=name))

    def process(self, request, **options):
        '''
        Processes the request.
        
        @param request: client request
        
        @return: Response
        '''

        return self.get_processor().process(request, **options)

    def login(self, login_request):
        """
        Authenticates the given credentials and returns login information.

        @param instance login_request: Raw request recevied from client.

        @return: login data
        @rtype: instance
        """

        return self.get_processor().login(login_request)

    def logout(self, logout_request):
        '''
        Logout the user from application.
        
        @param instance logout_request: Raw request received from client.
        '''

        return self.get_processor().logout(logout_request)

    def get_info(self):
        '''
        Returns information about active request processor.
        
        @return: DynamicObject
        '''

        processor = self.get_processor()
        info = DynamicObject(mode=processor.get_name())
        info.update(processor.get_params())
        return info

    def set_timeout(self, timeout):
        '''
        Sets global timeout of request processor.
        
        @param timeout: timeout
        '''

        session = get_current_session()
        context = session.get_context()
        context['timeout'] = timeout
        session.update()

    def get_timeout(self):
        '''
        Returns get global timeout value.
        
        @rtype: int
        @return: timeout value
        '''

        session = get_current_session()
        timeout = session.get_context().get('timeout')

        if timeout is None:
            config_store = \
                config_services.get_app_config_store('request_processor')
            timeout = config_store.get('global', 'timeout')
            if timeout is not None:
                timeout = int(timeout)

        return timeout

    def reload(self):
        '''
        Re-reads configs from the config file and applying them.
        '''
        config_store = \
            config_services.get_app_config_store('request_processor')

        params = config_store.get_section_data(self._default_processor_name)
        processor = self.get_processor()
        processor.resize(int(params.get("max_processes")))
Пример #11
0
class ZMQRequestProcessor(RequestProcessorBase):
    '''
    This processor will process every request in current process.     
    '''

    LOGGER = logging_services.get_logger(name='requestprocessor')

    def __init__(self):
        RequestProcessorBase.__init__(self, 'zmq')

        # Process pool instance
        self._pool = None

        # ZMQ context
        self._context = None

        # Facing who sends a request
        self._frontend = None

        # Facing who processes a request
        self._backend = None

        # The distributer client
        self._dispatcher_pool = None

    def configure(self, params):
        '''
        Configures request processor.
        @param params:
        '''

        # Getting ZMQ parameters
        self._params = params

        # Getting max processes
        max_processes = int(params.get('max_processes', 4))
        max_threads = int(params.get('max_threads', 4))
        frontend_port = int(params.get('frontend_port'))
        backend_port = int(params.get('backend_port'))

        # Starting ZMQ Queue
        self._context = zmq.Context(1)

        self._frontend = self._context.socket(zmq.XREP)
        self._frontend.setsockopt(zmq.LINGER, 0)
        self._frontend.bind("tcp://*:{0}".format(frontend_port))

        self._backend = self._context.socket(zmq.XREQ)
        self._backend.setsockopt(zmq.LINGER, 0)
        self._backend.bind("tcp://*:{0}".format(backend_port))

        self._dispatcher_pool = Queue(max_threads * max_processes)
        for i in xrange(max_threads * max_processes):
            client = self._context.socket(zmq.REQ)
            client.setsockopt(zmq.LINGER, 0)
            client.connect("tcp://127.0.0.1:{0}".format(frontend_port))
            self._dispatcher_pool.put(client)

        def start_queue():
            zmq.device(zmq.QUEUE, self._frontend, self._backend)

        t = Greenlet(target=start_queue)
        t.start()
        #gevent.spawn(zmq.device, zmq.QUEUE, self._frontend, self._backend)

        # Initializing process pool
        self._pool =\
            ProcessPool(max_processes,
                        init_func = ZMQRequestProcessor.init_func)

    def process(self, request, **options):
        '''
        Processes the request.
        
        @param request: client request
        
        @return: Response
        '''

        client = self._dispatcher_pool.get()

        try:
            client.send(cPickle.dumps([request, options]))
            message = client.recv()
            obj = cPickle.loads(message)
            if isinstance(obj, Exception):
                raise obj
            return obj
        finally:
            self._dispatcher_pool.put(client)

    def resize(self, size):
        '''
        Resizes current process pool.
        @param int size: pool size
        '''
        if self._pool is not None:
            return self._pool.set_size(size)

    def terminate(self):
        '''
        Terminates current request processor.
        '''

        self._pool.terminate()
        self._frontend.close()
        self._backend.close()
        self._context.term()

    @staticmethod
    def init_func():
        settings = config_services.get_app_config_store('request_processor')
        backend_port = int(settings.get('zmq', 'backend_port'))
        max_threads = int(settings.get('zmq', 'max_threads'))
        if max_threads == 0:
            max_threads = 4
        io_threads = multiprocessing.cpu_count() - 1
        if io_threads < 2:
            io_threads = 2

        ZMQRequestProcessor.LOGGER.info(
            "Process [{0}] is started as a subscriber by [{1}] greenlets.".
            format(os.getpid(), max_threads))

        database_services.reset_pools()
        context = zmq.Context(io_threads)

        workers = [Worker(context, backend_port) for i in xrange(max_threads)]

        for worker in workers:
            worker.start()

        for worker in workers:
            worker.join()
'''
Created on Oct 12, 2009

@author: Abi.Mohammadi & Majid.Vesal
'''

import deltapy.caching.services as caching
from deltapy.utils.decorator import make_decorator
import deltapy.logging.services as logging
import time

logger = logging.get_logger()


@make_decorator
class trace:
    '''
    Provides caching method result by method input parameters.
    '''

    logger = logging.get_logger()

    def __init__(self, *args, **options):
        pass

    def wrapper(self, func, *args, **kwargs):
        '''
        Wraps the function.
        
        @param func: function
        @return: depends on function
Пример #13
0
class ZmqListener(Listener):
    '''
    ZMQ listener.
    '''
    
    logger = logging.get_logger(name = 'ZMQ')
    
    def __init__(self, communicator, name, params, client_request_class=None):
        '''
        '''
        
        Listener.__init__(self, communicator, name, params, client_request_class=client_request_class)
        
        # Configuring Zmq
        workers_count = params.get('workers')
        if workers_count is not None:
            workers_count = int(workers_count)
        else:
            workers_count = 16
        
        if not params.has_key('service_name'): 
            params['service_name'] = self.get_name()
            
        router_url = 'tcp://{0}:{1}'.format(params.get('host'), params.get('port'))
        dealer_url = 'inproc://workers'
        
        # Creating zmq context    
        io_threads = multiprocessing.cpu_count() - 1
        if io_threads < 2:
            io_threads = 2;
        self._context = zmq.Context(io_threads)
        
        # Creating router socket
        self._router = self._context.socket(zmq.ROUTER)
        self._router.setsockopt(zmq.LINGER, 0)
        self._router.bind(router_url)
        
        # Creating dealer socket
        self._dealer = self._context.socket(zmq.DEALER)
        self._dealer.setsockopt(zmq.LINGER, 0)
        self._dealer.bind(dealer_url)
        
        self._dispatchers = []
        for index in xrange(workers_count):
            dispatcher = ZmqDispatcher(self, self._context, dealer_url)
            self._dispatchers.append(dispatcher)
            
    def login(self, ip, user_name, password, **options):
        '''
        Logins in application.
        
        @param ip: client IP address
        @param user_name: user name
        @param password: user password
        '''
        
        return Listener.login(self, ip, user_name, password, **options)
   
    def login_ex(self, ip, user_name, password, **options):
        '''
        Logins in application.
        
        @param ip: client IP address
        @param user_name: user name
        @param password: user password
        '''
        
        try:
            return Listener.login_ex(self,ip, user_name, password, **options)
        except Exception, error:
            return make_error_result(self.get_type_convertor(), error)
Пример #14
0
class Scheduler(Thread):
    """
    Provides some functions for scheduling tasks.
    """
    
    logger = logging.get_logger(name = 'scheduler')
    
    def __init__(self):
        Thread.__init__(self)
        self.setDaemon(True)        

        self.tasks = {}        
        self.tasks_lock = Lock()
        self.halt_flag = Event()
        self.nonempty = Event()     
        self.on_running_task = lambda t:None   
    
    def create_task(self, 
                    name, 
                    start_time, 
                    calc_next_time_func, 
                    func, 
                    **func_kargs):
        task = Task(name, 
                    start_time, 
                    calc_next_time_func,
                    func,
                    **func_kargs)
        return task
    
    def schedule(self, 
                 name, 
                 start_time, 
                 calc_next_time_func, 
                 func, 
                 expire_time = None,
                 before_run = None,
                 after_run = None,
                 retry_count = 0, 
                 **func_args):
        
        task = Task(name, 
                    start_time, 
                    calc_next_time_func, 
                    func, 
                    **func_args)
        
        #task.priority = priority
        task.expire_time = expire_time
        task.retry_count = retry_count
        task.before_run = before_run
        task.after_run = after_run  
        
        return self.schedule_task(task)
    
    def schedule_task(self, task):
        
        receipt = task.get_id()
        try:
            self.tasks_lock.acquire()
            self.tasks[receipt] = task
            self.nonempty.set()
        finally:
            self.tasks_lock.release()
        
        return receipt
    
    def drop(self, task_receipt):
        try:
            self.tasks_lock.acquire()
            self.tasks[task_receipt].halt()
            del self.tasks[task_receipt]
            if len(self.tasks)==0:
                self.nonempty.clear()
        except KeyError:
            self.logger.error('Invalid task receipt: %s' % (task_receipt,))
        finally:
            self.tasks_lock.release()
        
    def halt(self):
        self.halt_flag.set()
        # Drop all active tasks
        map(self.drop, self.tasks.keys())
        # Exit the thread to kill the scheduler
        
    def __find_next_tasks__(self):
        try:
            self.tasks_lock.acquire()
            receipts = []
            
            items = self.tasks.items()
            
            by_time = lambda x: operator.getitem(x, 1).scheduled_time
                        
            items.sort(key = by_time)      
               
            for index in xrange(len(self.tasks)):
                receipt = items[index][0]
                task = self.tasks[receipt]
                task_time = task.scheduled_time
                now = datetime.datetime.now()
                time_to_wait = task_time - now
                secs_to_wait = 0.
                secs_to_wait = time_to_wait.seconds
                if secs_to_wait <= 0 and secs_to_wait >= -5:
                    if not task.status in (Task.RUNNING, Task.HALTED):
                        if task.scheduled_time >= datetime.datetime.now():
                            receipts.append(receipt)

            return receipts
                    
        finally:
            self.tasks_lock.release()
        
    def run(self):
        task_executor = TaskExecutor(self.on_running_task)
        
        while True:
            # Waiting for a second
            time.sleep(1)
           
            receipts = self.__find_next_tasks__()
            
            ignore_task = False
            
            for receipt in receipts:
                if receipt != None:
                    #self.halt_flag.wait(secs_to_wait)
                    ignore_task = False
                    try:
                        try:
                            self.tasks_lock.acquire()
                            task = self.tasks[receipt]                                              
    
                            if task.exec_count_limit > 0 and  task.exec_count > task.exec_count_limit:
                                self.logger.debug("Task %s execution count exceeded." % (task.name,))
                                self.tasks.pop(receipt)
                                ignore_task = True
                                    
                            #checking task expiration time                        
                            if task.expire_time and task.expire_time < datetime.datetime.now():
                                self.logger.debug("Task %s expired" % (task.name,))
                                self.tasks.pop(receipt)
                                ignore_task = True
                            
                            if not ignore_task:
                                task_executor.execute(task)
                                #task.run()                         
    
                        finally:
                            self.tasks_lock.release()
                    except Exception, e:
                        self.logger.exception(e)
                        self.logger.debug( self.tasks )
                else:
                    self.nonempty.wait()
Пример #15
0
class TransactionCoordinator(DeltaObject):
    
    LOGGER = logging_services.get_logger(name='request.coordinator')
    
    class StateEnum(DeltaEnum):
        RECEIVED = DeltaEnumValue(0, 'Received')
        COMPLETED = DeltaEnumValue(1, 'Completed')
        FAILED = DeltaEnumValue(2, 'Failed')
        REVERSED = DeltaEnumValue(3, 'Reversed')
        REVERSE_FAILED = DeltaEnumValue(4, 'Reversed Failed')
        
    def __init__(self):
        '''
        Initializes transaction coordinator.
        '''

        DeltaObject.__init__(self)

        add_hook(TransactionCoordinatorCommandExecutionHook())

    def get_request(self, request_id):
        '''
        Returns the specified request.

        @param str request_id: request ID

        @rtype: dict(str request_id: client request ID,
                     str transaction_id: client request transaction ID,
                     str user_name: client request user name,
                     str client_ip: client request IP,
                     str service_id: client request service ID,
                     datetime receieve_date: client request recieve date,
                     datetime request_date: client request request date,
                     str trace_id: client request trace ID,
                     int state: request state,
                     dict data: data)
        @type data: dict(dict request_header: request header,
                         dict command_args: command args,
                         dict command_kwargs: command kwargs,
                         dict call_context: call context,
                         dict response_data: response data
                         str error: error)
        @type request_header: dict(str recorder_type: recorder type,
                                   int version: version)
        @type response_data: dict(datetime send_date: client response send date,
                                  dict command_result: client response command result)
        @return: request info
        '''

        return request_recorder_services.get_by_request_id(request_id)

    def try_get_request(self, request_id, **options):
        '''
        Returns information of a particular request.

        @param str request_id: request ID

        @rtype: dict(str request_id: client request ID,
                     str transaction_id: client request transaction ID,
                     str user_name: client request user name,
                     str client_ip: client request IP,
                     str service_id: client request service ID,
                     datetime receieve_date: client request recieve date,
                     datetime request_date: client request request date,
                     str trace_id: client request trace ID,
                     int state: request state,
                     dict data: data)
        @type data: dict(dict request_header: request header,
                         dict command_args: command args,
                         dict command_kwargs: command kwargs,
                         dict call_context: call context,
                         dict response_data: response data
                         str error: error)
        @type request_header: dict(str recorder_type: recorder type,
                                   int version: version)
        @type response_data: dict(datetime send_date: client response send date,
                                  dict command_result: client response command result)
        @return: request info
        '''

        return request_recorder_services.try_get_by_request_id(request_id, **options)
                        
    def get_request_state(self, request_id):
        '''
        Returns state of specified request.

        @param str request_id: request ID

        @rtype: int
        @note:
            0: Received
            1: Completed
            2: Failed
            3: Reversed
        @return: request state
        '''
        
        return request_recorder_services.get_request_state(request_id)

    def get_transaction_detail(self, transaction_id):
        '''
        Returns detail information of the specified transaction.

        @param str transaction_id: transaction ID

        @rtype: dict(str transaction_id: transaction ID
                     datetime start_date: start date of transaction,
                     str user_id: user ID,
                     list(dict) requests: requests regarding to the transaction)
        @type request: dict(str request_id: client request ID,
                            str transaction_id: client request transaction ID,
                            str user_name: client request user name,
                            str client_ip: client request IP,
                            str service_id: client request service ID,
                            datetime receieve_date: client request recieve date,
                            datetime request_date: client request request date,
                            str trace_id: client request trace ID,
                            int state: request state,
                            dict data: data)
        @type data: dict(dict request_header: request header,
                         dict command_args: command args,
                         dict command_kwargs: command kwargs,
                         dict call_context: call context,
                         dict response_data: response data
                         str error: error)
        @type request_header: dict(str recorder_type: recorder type,
                                   int version: version)
        @type response_data: dict(datetime send_date: client response send date,
                                  dict command_result: client response command result)
        @return: transaction detail
        '''

        return request_recorder_services.get_detail_by_transaction_id(transaction_id)

    def record_request(self, recorder_type, client_request, **options):
        '''
        Records a request data using the given information.

        @param str recorder_type: recorder type
        @type client_request: dict(str id: request ID,
                               str transaction_id: transaction ID,
                               str user_name: user name,
                               str client_ip: client IP,
                               datetime receive_date: receive date,
                               datetime request_date: request date from client)
        @param dict client_request: request data
        '''

        request_recorder_services.record(recorder_type,
                                         client_request,
                                         **options)
        
    def set_completed(self, recorder_type, client_request, client_response, **options):
        '''
        Completes the state of the given request.

        @param str recorder_type: recorder type
        @param dict client_request: request data
        @type client_request: dict(str id: request ID,
                               str transaction_id: transaction ID,
                               str user_name: user name,
                               str client_ip: client IP,
                               datetime receive_date: receive date,
                               datetime request_date: request date from client)
        @param dict client_response: client response
        '''

        request_recorder_services.set_completed(recorder_type,
                                                client_request,
                                                client_response,
                                                **options)
        
    def set_failed(self, recorder_type, client_request, error, **options):
        '''
        Sets the state of the given request to failed.
        
        @param str recorder_type: recorder type
        @param dict client_request: request data
        @type client_request: dict(str id: request ID,
                               str transaction_id: transaction ID,
                               str user_name: user name,
                               str client_ip: client IP,
                               datetime receive_date: receive date,
                               datetime request_date: request date from client)
        @param duct error: error
        '''

        request_recorder_services.set_failed(recorder_type,
                                             client_request,
                                             error,
                                             **options)
Пример #16
0
class TransactionManager(DeltaObject):

    DEFAULT_TRANSACTION = 'default'
    LOGGER = get_logger(name='transaction')

    def __init__(self, database_manager):
        DeltaObject.__init__(self)

        self._database_manager = database_manager
        self._transactions = {}

    def get_database_manager(self):
        '''
        Returns database manager.
        
        @return: DatabaseManager 
        '''
        return self._database_manager

    def __add_root_transaction__(self, pool_name, trx):
        pool_stack = self._transactions.get(pool_name, [])
        pool_stack.append(weakref.ref(trx))
        self._transactions[pool_name] = pool_stack

    def __remove_root_transaction__(self, pool_name):
        pool_stack = self._transactions.get(pool_name, [])
        pool_stack.pop()

    def __get_current_root_transaction__(self, pool_name):
        pool_stack = self._transactions.get(pool_name, [])
        if len(pool_stack) > 0:
            return pool_stack[len(pool_stack) - 1]()
        return None

    def begin(self, **kargs):
        '''
        Begins a transaction and return it.
        
        @param auto_commit: auto commit flag
        @param pool_name: connection pool name
        @param is_root: root transaction flag 
        
        @return: Transaction
        '''

        auto_commit = kargs.get('auto_commit', False)
        pool_name = kargs.get('pool_name',
                              TransactionManager.DEFAULT_TRANSACTION)
        if not pool_name:
            pool_name = TransactionManager.DEFAULT_TRANSACTION

        is_root = kargs.get('is_root', False)

        parent_transaction = None
        connection = None
        timeout = None

        if not is_root:
            parent_transaction = self.__get_current_root_transaction__(
                pool_name)

        if not issubclass(type(parent_transaction), TwoPhaseCommitTransaction):
            if parent_transaction is not None:
                connection = parent_transaction.get_connection()
            else:
                connection = self._database_manager.open(pool_name)

        trx = Transaction(self, connection, auto_commit, parent_transaction)
        trx._pool_name = pool_name

        current_session = get_current_session()
        if current_session is not None:
            client_request = current_session.get_client_request()

            if client_request.timeout is not None and client_request.timeout > 0:
                timeout = client_request.timeout

        self.set_timeout(trx, timeout)

        if not parent_transaction:
            connection.transaction = trx
            self.__add_root_transaction__(pool_name, trx)

        return trx

    def _run_before_commit_triggers_(self, tx):
        '''
        '''
        triggers = tx.get_before_commit_triggers()
        if len(triggers) > 0:
            for trigger, params in triggers:
                trigger(*params)

    def _run_after_commit_triggers_(self, tx):
        '''
        '''
        triggers = tx.get_after_commit_triggers()
        if len(triggers) > 0:
            for trigger, params in triggers:
                trigger(*params)

    def commit(self, tx):
        try:
            if not tx.get_parent():
                tx.get_connection().transaction = None

                self._run_before_commit_triggers_(tx)
                tx.get_connection().commit()
                self._run_after_commit_triggers_(tx)

                self._database_manager.close(tx.get_connection())
                self.__remove_root_transaction__(tx._pool_name)

                return True
        except Exception:
            self.rollback(tx)
            raise
        return False

    def _run_before_rollback_triggers_(self, tx):
        '''
        '''
        triggers = tx.get_before_rollback_triggers()
        if len(triggers) > 0:
            for trigger, params in triggers:
                trigger(*params)

    def _run_after_rollback_triggers_(self, tx):
        '''
        '''
        triggers = tx.get_after_rollback_triggers()
        if len(triggers) > 0:
            for trigger, params in triggers:
                trigger(*params)

    def rollback(self, tx):
        try:
            if not tx.get_parent():
                tx.get_connection().transaction = None

                # Triggers should not interfere with rollback if they're erroneous.
                try:
                    self._run_before_rollback_triggers_(tx)
                except Exception as error:
                    TransactionManager.LOGGER.error(str(error))

                tx.get_connection().rollback()

                try:
                    self._run_after_rollback_triggers_(tx)
                except Exception as error:
                    TransactionManager.LOGGER.error(str(error))

                self._database_manager.close(tx.get_connection())
                self.__remove_root_transaction__(tx._pool_name)
                return True
        except Exception as error:
            TransactionManager.LOGGER.error(str(error))
            print str(error)
        return False

    def tpc_begin(self):
        return TwoPhaseCommitTransaction()

    def get_current_transaction(self, pool_name=None):
        if pool_name is None:
            pool_name = TransactionManager.DEFAULT_TRANSACTION

        parent_transaction = self.__get_current_root_transaction__(pool_name)

        return parent_transaction

    def cleanup(self):
        for pool_stack in self._transactions.values():
            for trx_proxy in pool_stack:
                if trx_proxy:
                    trx = trx_proxy()
                    if trx:
                        trx.finalize()
        self._transactions.clear()

    def set_timeout(self, tx, timeout):
        tx.set_timeout(timeout)

    def __str__(self):
        return "%s" % self._transactions.values()
Пример #17
0
class CommandManager(DeltaObject):
    '''
    Manages commands.
    '''

    logger = logging.get_logger(name='commander')

    def __init__(self):
        DeltaObject.__init__(self)
        self._commands = {}
        self._executor = CommandExecutor()
        self._hooks = []

    def get_executer(self):
        '''
        Returns defult executor.
        '''

        return self._executor

    def set_executor(self, executor):
        '''
        Registers a executor by the given name
        
        @param executor: executor instance
        '''

        self._executor = executor

    def execute(self, key, *args, **kargs):
        '''
        Executes a command by given key.
        
        @param key: command key or command name
        @return: object
        '''
        if key not in self._commands:
            raise CommandManagerException("Command[%s] does not exist." % key)
        # Getting command
        command = self._commands[key]

        try:
            self._before_execute_command_(command, *args, **kargs)

            # Executing the command
            result = self._executor.execute(command, *args, **kargs)

            self._after_execute_command_(command, result, *args, **kargs)

            # Returning the command result
            return result
        except DeltaException as error:
            self._exception_(command, error, *args, **kargs)

            error_stack = traceback.format_exc()
            error_message = "[{command_key}] Error:\n{error}".format(
                command_key=key, error=error_stack)
            CommandManager.logger.error(error_message)
            raise
        except Exception as error:
            self._exception_(command, error, *args, **kargs)

            error_stack = traceback.format_exc()
            error_message = "[{command_key}] Error:\n{error}".format(
                command_key=key, error=error_stack)
            CommandManager.logger.error(error_message)

            # If it's an standard error, there is no need to wrap it again,
            # because it can be pickled with no difficulty.
            if isinstance(error, StandardError):
                raise

            raise Exception("%s:%s" % (str(error), error_stack))

    def bulk_execute(self, commands, **options):
        '''
        Executes a command by given key.
        
        @param commands: command data list as dict<command_key, args, kwargs>:
            command_key: command key
            args: command arguments
            kwargs: command keyword arguments
        @param **options: 
        @return: object
        '''

        if len(commands) == 0:
            raise CommandManagerException('There is no command to execute.')

        results = []
        for command_data in commands:
            command_key = command_data['command_key']
            args = command_data.get('args', tuple())
            if not isinstance(args, (tuple, list)):
                args = (args, )
            kwargs = command_data.get('kwargs', dict())
            result = self.execute(command_key, *args, **kwargs)
            results.append(
                DynamicObject(command_key=command_key, command_result=result))
        return results

    def select(self, fields, command_key, *args, **kwargs):
        '''
        Executes a command and returns requested fields. 
        
        @param fields: list of requested fields 
        @param command_key: command key
        @param *args:
        @param **kwargs:
        
        @return: [DynamicObject<fields>]  
        '''

        result = self.execute(command_key, *args, **kwargs)
        results = result
        if not isinstance(result, list):
            results = [result]

        if fields is None or len(fields) == 0:
            return results

        selected_resultes = []
        for obj in results:
            record = DynamicObject()
            for field in fields:
                record[field] = obj.get(field)
            selected_resultes.append(record)
        return selected_resultes

    def __execute_async__(self, key, callback, *args, **kargs):
        result = self.execute(key, *args, **kargs)
        if callback:
            callback(key, result, *args, **kargs)
        return result

    def execute_async(self, key, callback, *args, **kargs):
        '''
        Executes a command by given key.
        
        @param key: command key or command name
        @param callback: callback function
        @return: None 
        '''

        return run_in_thread(
            self.__execute_async__(key, callback, *args, **kargs))

    def _before_execute_command_(self, command, *args, **kargs):
        '''
        Runs before execution method of all hooks.
        
        @param command: command
        '''

        # Setting start processing time in command manager
        current_session = get_current_session()
        internal_context = current_session.get_internal_context()
        internal_context['start_process_time'] = time.time()

        if len(self._hooks):
            for hook in self._hooks:
                if hook.is_enable():
                    hook.before_execute(self, command, *args, **kargs)

    def _after_execute_command_(self, command, result, *args, **kargs):
        '''
        Runs after execution method of all hooks.
        
        @param command: command
        @param result: command execution result
        '''

        if len(self._hooks):
            for index in xrange(len(self._hooks) - 1, -1, -1):
                hook = self._hooks[index]
                if hook.is_enable():
                    hook.after_execute(self, command, result, *args, **kargs)

    def _exception_(self, command, error, *args, **kargs):
        '''
        Runs exception method of all hooks.
        
        @param command: command
        @param error: exception instance
        '''

        if len(self._hooks):
            for index in xrange(len(self._hooks) - 1, -1, -1):
                hook = self._hooks[index]
                if hook.is_enable():
                    hook.exception(self, command, error, *args, **kargs)

    def add_command(self, command, **options):
        '''
        Adds a command.
        
        @param command: command instance
        '''

        replace = options.get('replace', False)

        if not replace and command.get_key() in self._commands:
            raise DeltaException("Command[%s] already exists." % command)

        command.attach(self)

        self._commands[command.get_key()] = command

    def get_commands(self,
                     parent=None,
                     name_filter=None,
                     description_filter=None,
                     exact_name=None):
        '''
        Returns all commands.
        If any filter specified, it filter those commands.

        @keyword str parent: only return commands that their parrents
            matches this string.
        @keyword str name_filter: only return commands that their names
            contain this string.
        @keyword str exact_name: only return command that its name
            is this string.
        @keyword str description_filter: only return commands that their
            description contain this string.

        @return: founded commands
        @rtype: list(dict(str name,
                          str description))
        '''
        commands = self._commands.values()
        results = []

        if (parent is None and name_filter is None
                and description_filter is None and exact_name is None):
            # If no filter provided.
            return commands

        for cmd in commands:
            filtered = False

            if parent is not None:
                if not cmd.get_location().startswith(parent):
                    filtered = True
            if name_filter is not None:
                if cmd.get_name().find(name_filter) < 0:
                    filtered = True
            if exact_name is not None:
                if cmd.get_name() != exact_name:
                    filtered = True
            if description_filter is not None:
                command_description = cmd.get_description()
                if (command_description is None
                        or command_description.find(description_filter) < 0):
                    filtered = True

            if not filtered:
                results.append(cmd)

        return results

    def remove_commands(self, parent):
        '''
        Removes all commands in the given parent domain.
        
        @param parent: parent name
        '''
        for cmd in self._commands.values():
            if cmd.location.find(parent) == 0:
                self.remove_command(cmd)

    def get_command(self, key):
        '''
        Returns the command by the given key.
        
        @param key: command key
        @return: command
        '''

        if key in self._commands:
            return self._commands[key]
        return None

    def remove_command(self, command):
        '''
        Removes the given command.
        
        @param command:
        '''

        if command.get_key() in self._commands:
            command = self._commands.pop(command.get_key())
            command.dettach(self)
            del command

    def add_hook(self, hook):
        '''
        Adds an execution hook to the commander.
        
        @param hook:
        '''

        self._hooks.append(hook)

    def get_hooks(self):
        '''
        Returns all execution hooks.
        
        @return: list<CommandExecutionHook>
        '''

        return self._hooks
Пример #18
0
class Task: 
    '''
    Task class.
    '''
    
    SUCCEEDED = 'succeeded'
    FAILED = 'failed'
    WAIT = 'wait'
    RUNNING = 'running'
    HALTED = 'halted'

    PRIORITY_LOW = -1
    PRIORITY_NORMAL = 0
    PRIORITY_HIGH = 1
    PRIORITY_VERY_HIGH = 2
             
    logger = logging.get_logger(name = 'scheduler')
    
    def __init__(self, 
                 name,
                 start_time, 
                 calc_next_time_func, 
                 action,
                 **kargs):
        """
        Initialize a Task.
        
        @param name: Name of task.
        @param start_time: First time for task to run
        @param calc_next_time_func: Function to calculate the time of next run, 
                              gets one argument, the last run time as a datetime.
                              Returns None when task should no longer be run
        @param action: A function to run
        
        """
       
        self.name = name
        self.start_time = start_time                
        self.scheduled_time = self.start_time
        self.calc_next_time_func = calc_next_time_func
        self.action = action
        self.action_kargs = kargs
        self.retry_count = 0
        self.expire_time = None
        self.exec_count = 0
        self.exec_count_limit = 0
        self.priority = Task.PRIORITY_NORMAL
        self.halt_flag = Event()
        self.task_id = get_uuid()
        self.status = Task.WAIT
        self.last_exec_time = None
        self.last_error = None
        self.before_run = lambda task : None
        self.after_run = lambda task : None
        while self.scheduled_time < datetime.datetime.now():
            self.scheduled_time = self.calc_next_time_func(self.scheduled_time)
        
    def run(self):
        
        self.logger.debug("Running Task [%s] , at: %s" % (self.name, 
                                                          datetime.datetime.now()))

        if self.before_run:
            self.before_run(self)
        
        retry_count = self.retry_count
        
        if not self.halt_flag.isSet():
            while retry_count + 1 > 0:
                try:
                    self.last_exec_time = time.time()
                    self.action(**self.action_kargs)
                    self.status = Task.SUCCEEDED
                    break
                except Exception, error:
                    self.last_error = error
                    self.status = Task.FAILED
                    retry_count -= 1
                    
        if self.after_run:
            self.after_run(self)
        
        self.exec_count += 1   
        
        if self.calc_next_time_func:
            self.scheduled_time = self.calc_next_time_func(self.scheduled_time)

        self.logger.debug("Scheduled next run of %s for: %s" % (self.name, 
                                                                self.scheduled_time,))            
Пример #19
0
class ChannelAuthenicator(DeltaObject):
    '''
    Handles channel authentication.
    '''
    
    LOGGER = logging_services.get_logger(name='channel')
    
    def _verify_channel(self, channel, **options):
        '''
        Verifies general conditions on the given channel
        
        @param channel: channel instance
        '''

        # Verifying channel
        if channel is None:
            raise ChannelAuthenicationException(_('Channel authentication failed. Please revise your certificate.'))
        if not channel.enabled:
            raise ChannelAuthenicationException(_('Channel authentication failed. Channel is disable.'))

    def authenticate(self, ticket, certificate, **options):
        '''
        Authenticates a certificate considering the given ticket.
        
        @param ticket: ticket
        @param certificate: certificate
        '''
        
        # Getting session
        session = session_services.get_session(ticket, False)
        
        # Getting current user
        current_user = session.get_user()

        if channel_services.is_enable():
            # Getting login parameters
            given_channel_id = options.get('channel')
            given_channel = None
            if given_channel_id is not None:
                given_channel = channel_services.get(given_channel_id)
                if not given_channel.certificate_required:
                    # Verifying channel
                    self._verify_channel(given_channel)
                    
                    # Setting channel ID
                    self._set_channel_to_session(ticket, given_channel_id)     
                    
                    message = 'User [{0}] authenticated through risky channel [{1}]'
                    ChannelAuthenicator.LOGGER.warning(message.format(current_user.id, given_channel_id))
                    
                    return
                    
            # Getting channel info using certificate
            channel = channel_services.try_get_by_certificate(certificate)

            # Verifying channel
            self._verify_channel(channel)

            # Logging
            message = 'Authenticating User [{0}] using certification [{1}]'
            ChannelAuthenicator.LOGGER.info(message.format(current_user.id, certificate))

            if given_channel is not None and given_channel.id != channel.id:
                raise ChannelAuthenicationException(_('Channel authentication failed. Channel mismatched.'))
            
            # Setting channel ID
            self._set_channel_to_session(ticket, channel.id)
                      
            message = 'User [{0}] authenticated with certified channel [{1}]'
            ChannelAuthenicator.LOGGER.warning(message.format(current_user.id, channel.id))
            
    def _set_channel_to_session(self, ticket, channel_id, **options):
        '''
        Sets channel to session using the given ticket.
        
        @param ticket: ticket
        @param channel_id: channel ID
        '''
        
        # Getting session
        session = session_services.get_session(ticket, False)
        
        # Getting session context to set user channel
        context = session.get_context()

        # Setting channel ID            
        context['channel'] = channel_id
        
        # Updating session to apply changes
        session.update()
from deltapy.core import DeltaObject, DynamicObject
from deltapy.security.authentication.services import authenticate
from deltapy.security.authentication.authenticator import IP_ADDRESS_OPTION_KEY
from deltapy.event_system.decorators import delta_event
from deltapy.request_processor.services import get_timeout
from deltapy.request_processor.response import Response
from deltapy.request_processor.services import get_request_processor_hooks
from deltapy.request_processor.request import ClientRequest
import deltapy.security.authentication.services as authentication_services
import deltapy.commander.services as commander_services
import deltapy.logging.services as logging_services
import deltapy.unique_id.services as unique_id_services
import deltapy.request_processor.helper.services as request_processor_helper_services


LOGGER = logging_services.get_logger(name='requestprocessor')

def handle_request(raw_request, **options):
    '''
    Processes the request.
    
    @param request: client request
    
    @return: Response
    '''
    request_dict = raw_request.get_request_dict()

    # Converting client request to the type we expected.
    type_converter = raw_request.get_converter()
    if type_converter is not None:
        request_dict = type_converter.to_internal(request_dict)
class BaseAuthenticator(DeltaObject):
    '''
    '''
    INCORRECT_PASSWORD_DELAY = 2
    logger = logging.get_logger(name = "authentication")
    
    def _check_password_(self, password, user, **options):
        '''
        Checks user password and return True if password is correct.
         
        @param password: given password
        @param user: user information
        @param **options: 
        
        @return: bool
        '''
        raise NotImplementedError()
    
    def _validate_user_(self, user_name, user, **options):
        '''
        Validates the user.
        
        @param user: user
        '''

        if not security_services.is_active(user.id):
            BaseAuthenticator.logger.error('User [{user_name}] is inactive.'.format(user_name = user_name))
            raise UserIsInactiveException(_('User [{user_name}] is inactive.').format(user_name = user_name))
            
        if security_services.is_expired(user.id):
            BaseAuthenticator.logger.error('User [{user_name}] is expired.'.format(user_name = user_name))
            raise UserIsExpiredException(_('User [{user_name}] is expired.').format(user_name = user_name))

    def internal_login(self, user_name, **options):
        '''
        Logins internally and returns security ticket
        
        @param user_name: user name
        @param **options:  
        
        @return: object
        '''

        user = None
        try:
            user = security_services.get_user(user_name)
        except:
            force = options.get('force', False)
            if force:
                user = security_services.create_internal_user(user_name)
            else:
                BaseAuthenticator.logger.error('User[%s] not found.' % user_name)
                message = 'User[{user_name}] not found.'
                raise AuthenticationException(message.format(user_name = user_name))
        
        session = session_services.create_internal_session(user)
        return session.get_ticket()

    def login(self, user_name, password, **options):
        '''
        Logins and returns security ticket
        
        @param user_name: user name
        @param password: user password
        @param **options:  
        
        @return: object
        '''

        try:
            user = security_services.get_user_by_id(user_name)

            if user is None:
                BaseAuthenticator.logger.error('User[{user_name}] not found.'.format(user_name = user_name))
                raise AuthenticationException(_('User or password is invalid.'))

            if not self._check_password_(password, user, **options):
                message = 'User[{user_name}] entered invalid password[{password}].'
                BaseAuthenticator.logger.error(message.format(user_name=user_name,
                                                              password=password))
                # Delay to prevent brute force.
                time.sleep(BaseAuthenticator.INCORRECT_PASSWORD_DELAY)
                raise AuthenticationException(_('User or password is invalid.'))

            #Checking the ip address received in options.
            self._check_recievied_ip_address(user_name, options)

            self._validate_user_(user_name, user, **options)

            session = \
                session_services.create_session(user,
                                                options.get('client_ip'),
                                                lifetime=options.get('lifetime'))

            message = '[{user_name}@{client_ip}] logged in.'
            BaseAuthenticator.logger.info(message.format(user_name = user_name, 
                                                         client_ip = options.get('client_ip')))
            return session.get_ticket()
        except UserNotFoundException:
            BaseAuthenticator.logger.error('User[{user_name}] not found.'.format(user_name = user_name))
            time.sleep(BaseAuthenticator.INCORRECT_PASSWORD_DELAY)
            raise AuthenticationException(_('User or password is invalid.'))
        except Exception as error:
            BaseAuthenticator.logger.exception('Exception : {error}'.format(error = error))
            raise AuthenticationException(str(error))
            

    def authenticate(self, ticket, user_name, **options):
        '''
        Authenticates user and ticket.
        
        @param ticket: security ticket
        @param user_name: user name
        @param **options:  
        
        @return: Session
        '''

        try:        
            session = session_services.get_session(ticket)

            # Checking session expiration
            session_services.check_expiration(session)

            user = session.get_user()
            client_ip = options.get('client_ip')

            if user.user_id != user_name:
                message = '[{user_name}], [{ip}] sent invalid ticket[{ticket}]'
                BaseAuthenticator.logger.error(message.format(user_name=user_name,
                                                              ip=client_ip,
                                                              ticket=ticket))
                raise AuthenticationException(_('The user or ticket is invalid'))

            # Checking the ip address received in options.
            self._check_recievied_ip_address(user_name, options)

            # Checking if ip of session is equal to ip of client.
            ip_in_session = session.get_client_ip()
            if client_ip != ip_in_session:
                if client_ip not in self.get_trusted_ips():
                    message = '[{user_name}], ticket [{ticket}], came from wrong ip. Session ip [{session_ip}], received ip [{received_ip}].'
                    BaseAuthenticator.logger.error(message.format(user_name=user_name,
                                                                  ticket=ticket,
                                                                  session_ip=ip_in_session,
                                                                  received_ip=client_ip))
                    raise AuthenticationException(_('The user or ticket is invalid'))
                else:
                    message = ('User [{user}] Ticket [{ticket}]'
                               ' Received IP [{trusted_ip}] Session IP [{session_ip}],'
                               ' trusted.')
                    BaseAuthenticator.logger.info(message.format(trusted_ip=client_ip,
                                                                 user=user_name,
                                                                 ticket=ticket,
                                                                 session_ip=ip_in_session))

            return session
        except Exception:
            # Delay to prevent brute force.
            time.sleep(BaseAuthenticator.INCORRECT_PASSWORD_DELAY)
            raise

    def logout(self, ticket, user_name, **options):
        '''
        Logs off given user.
        
        @param ticket: ticket
        @param user_name: user name
        @param **options:  

        '''
        
        try:
            message = 'User [{user_name}@{client_ip}] logged off.'
            BaseAuthenticator.logger.info(message.format(user_name = user_name, 
                                                         client_ip = options.get('client_ip')))
            session = self.authenticate(ticket, user_name, **options)
            session.close()
        except:
            import traceback
            BaseAuthenticator.logger.error(traceback.format_exc())
            raise

    @cache
    def get_trusted_ips(self):
        '''
        Returns a list of IPs that can be trusted.
        
        @return: List of trusted IPs.
        @rtype: list(str)
        '''
        result = set()
        configs = config_services.get_app_config_store()
        if configs.has_key('security', 'trusted_ips'):
            option_str = configs.get('security', 'trusted_ips')
            for trusted_ip in option_str.split(','):
                result.add(trusted_ip.strip())

        return result

    def _check_recievied_ip_address(self, user_name, options):
        '''
        Checks if the ip_address option passed from client is valid.
        If so, replaces the original ip with the received one in the options.
        '''
        client_ip = options.get('client_ip')
        if IP_ADDRESS_OPTION_KEY in options:
            if client_ip not in self.get_trusted_ips():
                message = 'User [{user_name}] with ip [{client_ip}], sends another ip [{ip_address}], but was not trusted.'
                BaseAuthenticator.logger.error(message.format(user_name=user_name,
                                                              client_ip=client_ip,
                                                              ip_address=options.get(IP_ADDRESS_OPTION_KEY)))
                raise AuthenticationException(_("User IP address is invalied."))

            message = 'User [{user}] came from trusted ip [{trusted_ip}]. True IP: [{true_ip}].'
            BaseAuthenticator.logger.info(message.format(user=user_name,
                                                         trusted_ip=client_ip,
                                                         true_ip=options.get(IP_ADDRESS_OPTION_KEY)))
            options.update(client_ip=options.pop(IP_ADDRESS_OPTION_KEY))
Пример #22
0
class ServerStatusReporter(object):

    LOGGER = get_logger(name='status_reporter')

    def run(self):
        '''
        Starts the reporter.
        '''
        run_in_thread(self._listen)

    def _listen(self):
        '''
        Listens on a socket.
        '''
        server_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        # For re-using a time-wait socket.
        server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server_socket.bind('/var/run/{0}/{1}.sid'.format(
            application_services.get_name(), os.getpid()))
        server_socket.listen(1)

        while True:
            try:
                connection, address = server_socket.accept()
                status_string = self._get_status()
                # Since we don't care how much data has been send before an
                # error happends, we use `sendall' instead of `send'.
                connection.sendall(status_string)
            except Exception as error:
                ServerStatusReporter.LOGGER.error(str(error))
                ServerStatusReporter.LOGGER.error(traceback.format_exc())
            finally:
                connection.close()

    def _get_status(self):
        '''
        Gets status of the system.
        
        @return: status of system as a string.
        @rtype: str
        '''
        # Gathering server status.

        status_string = ''

        status_string += 'Instance Name: {0}\n'.format(
            application_services.get_full_name())

        # Application name and version
        app_introduction = application_services.introduce()
        if 'name' in app_introduction:
            status_string += 'Name: {0}\n'.format(app_introduction['name'])
        if 'version' in app_introduction:
            status_string += 'Version: {0}\n'.format(
                app_introduction['version'])

        # Packages status
        loaded_packages_count = len(package_services.get_loaded_packages())
        disabled_packages = package_services.get_disabled_packages()

        status_string += 'Packages: Loaded={0}, Disabled={1}\n'.format(
            loaded_packages_count, len(disabled_packages))
        if len(disabled_packages) > 0:
            status_string += 'Disabled Packages: [{0}'.format(
                disabled_packages[0])
            for disabled_package in disabled_packages[1:]:
                status_string += ',\n'
                status_string += ' ' * 20
                status_string += disabled_package
            status_string += ']\n'

        # Request processor status
        info = request_processor_services.get_info()
        status_string += 'Request Processor Parameters: {0}\n'.format(
            str(info))

        # Threads/Processes
        current_pid = os.getpid()
        current_process_thread_count = None
        # Reading current process' thread count.
        with open('/proc/{0}/status'.format(current_pid), 'r') as status_file:
            while True:
                file_line = status_file.readline()
                if not file_line:
                    break
                if file_line.startswith('Threads:'):
                    current_process_thread_count = int(file_line[8:].strip())
                    break

        status_string += 'Master Process Threads: {0}\n'.format(
            current_process_thread_count)

        # Finding all child processes.
        total_threads = 0
        total_children = 0
        for process_dir in os.listdir('/proc/'):
            if process_dir.isdigit() and os.path.isdir(
                    '/proc/{0}'.format(process_dir)):
                with open('/proc/{0}/status'.format(process_dir),
                          'r') as status_file:
                    while True:
                        file_line = status_file.readline()
                        if not file_line:
                            break
                        if file_line.startswith('PPid:'):
                            if int(file_line[5:].strip()) == current_pid:
                                # It's our child.
                                total_children += 1
                                # Continue to find threads.
                                while True:
                                    file_line = status_file.readline()
                                    if not file_line:
                                        break
                                    if file_line.startswith('Threads:'):
                                        total_threads += int(
                                            file_line[8:].strip())
                                        break
                            break

        status_string += 'Child Processes: {0}\n'.format(total_children)
        status_string += 'Child Threads: {0}\n'.format(total_threads)

        # TODO: Add database connections here.

        # Sessions
        status_string += 'Sessions: {0}'.format(
            session_services.get_sessions_count())

        return status_string
Пример #23
0
class ChannelAuthorizer(DeltaObject):
    '''
    It is responsible to provide functionality to limit services on user channels.
    '''
    
    LOGGER = logging_services.get_logger(name='channel')
    GLOBAL_ALLOWED = ['app.introduce',
                      'command.list',
                      'command.doc',
                      'security.authenticate',
                      'request_processor.coordinator.request.state']
    
    def __init__(self):
        DeltaObject.__init__(self)
        
        commander_services.add_hook(ChannelAuthorizerCommandHook())

    def _get_commands(self, pattern, all_commands):
        '''
        Returns list of commands according to the given pattern.
        
        @param pattern: pattern
        
        @rtype: [str]
        @return: commands
        '''
        
        result = []
        for command in all_commands:
            if fnmatch.fnmatch(command, pattern.strip()):
                result.append(command)
        return result
    
    def _get_allowed_commands(self, channel_id):
        '''
        Returns allowed commands on the given channel.
        
        @param channel_id: channel ID
        
        @rtype: [str]
        @return: allowed commands 
        '''
        
        channel = channel_services.get(channel_id)
        
        if channel.allowed is None or len(channel.allowed.strip()) == 0:
            channel.allowed = '*'
            
        allowed_commands = channel.allowed.replace(';', ',').split(',')
        
        result = []
        for pattern in allowed_commands:
            result.extend(self._get_commands(pattern, self._get_all_commands()))
        return set(result)
        
    def _get_denied_commands(self, channel_id):
        '''
        Returns denied commands on the given channel.
        
        @param channel_id: channel ID
        
        @rtype: list<str>
        @return: denied commands 
        '''
        
        channel = channel_services.get(channel_id)
        
        if channel.denied is None or len(channel.denied.strip()) == 0:
            return set([])

        denied_commands = channel.denied.replace(';', ',').split(',')
        result = []
        for pattern in denied_commands:
            result.extend(self._get_commands(pattern, self._get_all_commands()))
        return set(result)

    def _get_all_commands(self):
        '''
        Returns all of application commands
        
        @rtype: [str]
        @return: command list
        '''

        result = []
        
        for command in commander_services.get_commands():
            result.append(command.get_key())
            
        return result
    
    @cache
    def get_channel_authorized_commands(self, channel_id):
        '''
        Returns all authorized command on the given channel.
        
        @param channel_id: channel ID
        '''
        
        allowed = set(self._get_allowed_commands(channel_id))
        #ChannelAuthorizer.LOGGER.debug('allowed:{0}'.format(allowed))
        denied = set(self._get_denied_commands(channel_id))
        #ChannelAuthorizer.LOGGER.debug('denied:{0}'.format(denied))
        return allowed.difference(denied).union(set(ChannelAuthorizer.GLOBAL_ALLOWED))
    
    def authorize(self, channel_id, command_key, **options):
        '''
        Authorizes the given command on the specified channel.
        
        @param channel_id: channel ID
        @param command_key: command key
        '''

        if channel_services.is_enable():
            # Getting command instance        
            command = commander_services.get_command(command_key)
            if command is None:
                message = _('Command [{0}] not found.')
                raise ChannelAuthorizerException(message.format(command_key))
            
            ChannelAuthorizer.LOGGER.debug('Authorizing command [{0}] on channel [{1}]'.format(command_key, channel_id))
            if command.get_key() not in self.get_channel_authorized_commands(channel_id):
                message = _('Channel [{0}] has not access on command [{1}].')
                raise ChannelAccessDenied(message.format(channel_id, command_key))
            ChannelAuthorizer.LOGGER.info('Command [{0}] authorized on channel [{1}]'.format(command_key, channel_id))
    
    def get_command_list(self, parent = None): 
        '''
        Returns available commands list.
        
        @param parent: parent command
        
        @rtype: [str]
        @return: command list
        '''
        
        result = []
        for command in commander_services.get_commands(parent):
            result.append(command.get_key())

        if not channel_services.is_enable():
            return result
        
        allowed = self.get_channel_authorized_commands(get_current_channel_id())
        return list(set(allowed).intersection(set(result)))
    
    def get_command_doc(self, key):
        '''
        Returns defined document for the specified command. 
        
        @param key: command key
        
        @rtype: str
        @return: command document
        '''
        
        # Getting command instance        
        command = commander_services.get_command(key)
        if command is None:
            message = _('Command [{0}] not found.')
            raise ChannelAuthorizerException(message.format(key))

        if channel_services.is_enable():
            # Authorizing the command
            self.authorize(get_current_channel_id(), key)
        
        return command.get_doc()
Пример #24
0
class TypeConvertor(NullTypeConvertor):
    '''
    Provides functionality for converting external types to internal types and vice versa
    '''

    LOGGER = get_logger(name='root')
    
    def __init__(self):
        '''
        Initializes type converter.
        '''

        NullTypeConvertor.__init__(self)
        
        self.__internal_traverser = ObjectTraverser(self.safe_internal_convert)
        self.__external_traverser = ObjectTraverser(self.safe_external_convert)

        self._invalid_phrases = \
            ['`', '^', '\\', 'script', 'html', 'xhtml', 'colon', 'base64',
             'import', 'exec', 'eval', 'compile', 'getattr', 'setattr',
             '__getattr__', '__getattribute__', '__setattr__', '__delattr__',
             '__class__', '__module__', 'BANNED_WORDS']
        self._invalid_regex = \
            [r'[\s\S]*<[\s\S]*>[\s\S]*',
             r'[\s\S]*[&#"\'][\s\S]*;[\s\S]*',
             r'([\s\"\'`;\/0-9\=]+on\w+\s*=)']
        self._combined_invalid_regex = \
            re.compile("(" + ")|(".join(self._invalid_regex) + ")")

    def _normalize(self, obj):
        return obj.lower().strip().replace('\n', '').replace('\r', '')

    def _validate(self, obj):
        if not isinstance(obj, (str, unicode)):
            return

        normalized_obj = self._normalize(obj)

        for invalid_phrase in self._invalid_phrases:
            if invalid_phrase in normalized_obj:
                raise TypeConverterException(_('Invalid phrase [{0}] got detected.'.format(invalid_phrase)))

        if re.match(self._combined_invalid_regex, normalized_obj):
            raise TypeConverterException(_('Invalid phrase [{0}] got detected.'.format(obj)))

    def safe_internal_convert(self, obj):
        #self._validate(obj)
        return self.internal_convert(obj)

    def safe_external_convert(self, obj):
        return self.external_convert(obj)
    
    def internal_convert(self, obj):
        return obj
    
    def external_convert(self, obj):
        return obj

    def to_internal(self, obj):
        '''
        Converts an extranal object type to internal type.
        
        @param obj: external object
        @return: object
        '''
        
        return self.__internal_traverser.update(obj)
    
    def to_external(self, obj):
        '''
        Converts an internal object type to external object type.
        
        @param obj: internal object
        @return: object
        '''

        return self.__external_traverser.update(obj)
Пример #25
0
class IceDispatcher(DeltaIce.IIceDispatcher, Dispatcher):

    logger = logging.get_logger(name='communicator')

    def __init__(self, listener):
        Dispatcher.__init__(self, listener)

    def _get_client_ip_(self, **options):
        current = options.get('current')
        if current is not None:
            ip_port = current.con.toString().split('remote address = ')[1]
            ip_address = ip_port.split(':')[0]
            return utils.object_to_dobject(ip_address)

    def login(self, userName, password, options, current=None):
        try:
            start = time.time()

            login_result = \
                self._listener.login(self._get_client_ip_(current=current),
                                     userName,
                                     password,
                                     **options)

            end = time.time()
            ticket = login_result.value['ticket'].value
            time_span = end - start
            IceDispatcher.logger.info("Ice [{0}] login [{1}]".format(
                ticket, time_span))

            return login_result
        except DeltaException as error:
            exception = DeltaIce.AuthenticationException()
            exception.code = error.get_code()
            exception.data = utils.object_to_dobject(error.get_data())
            exception.message = utils.str_to_external(str(error))

            # Getting the true trace back from the error itself.
            if error.get_traceback() is not None:
                exception.traceback = utils.str_to_external(
                    error.get_traceback())
            else:
                exception.traceback = utils.str_to_external(
                    traceback.format_exc())

            raise exception

        except Exception as error:
            exception = DeltaIce.GenericException()
            exception.message = utils.str_to_external(str(error))

            # Getting the true trace back from the error itself.
            if hasattr(error, 'traceback'):
                exception.traceback = getattr(error, 'traceback')
            else:
                exception.traceback = traceback.format_exc()
            raise exception

    def loginEx(self, userName, password, options, current=None):
        try:
            start = time.time()

            login_result = \
                self._listener.login_ex(self._get_client_ip_(current=current),
                                        userName,
                                        password,
                                        **options)

            end = time.time()
            ticket = login_result.value['ticket'].value
            time_span = end - start
            IceDispatcher.logger.info("Ice [{0}] login [{1}]".format(
                ticket, time_span))

            return login_result

        except DeltaException as error:
            exception = DeltaIce.AuthenticationException()
            exception.code = error.get_code()
            exception.data = utils.object_to_dobject(error.get_data())
            exception.message = utils.str_to_external(str(error))

            # Getting the true trace back from the error itself.
            if error.get_traceback() is not None:
                exception.traceback = utils.str_to_external(
                    error.get_traceback())
            else:
                exception.traceback = utils.str_to_external(
                    traceback.format_exc())

            raise exception

        except Exception as error:
            exception = DeltaIce.GenericException()
            exception.message = utils.str_to_external(str(error))

            # Getting the true trace back from the error itself.
            if hasattr(error, 'traceback'):
                exception.traceback = getattr(error, 'traceback')
            else:
                exception.traceback = traceback.format_exc()
            raise exception

    def logout(self, ticket, userName, current=None):
        try:
            start = time.time()

            logout_result = \
                self._listener.logout(self._get_client_ip_(current=current),
                                      ticket,
                                      userName)

            end = time.time()
            time_span = end - start
            IceDispatcher.logger.info("Ice [{0}] logout [{1}]".format(
                ticket.value, time_span))

            return logout_result

        except Exception as error:
            exception = DeltaIce.GenericException()
            exception.message = str(error)

            # Getting the true trace back from the error itself.
            if hasattr(error, 'traceback'):
                exception.traceback = getattr(error, 'traceback')
            else:
                exception.traceback = traceback.format_exc()
            raise exception

    def execute(self,
                ticket,
                userName,
                commandKey,
                args,
                kwargs,
                current=None):
        try:
            execute_result = \
                self._listener.execute(self._get_client_ip_(current=current),
                                       ticket,
                                       userName,
                                       commandKey,
                                       *args,
                                       **kwargs)

            return execute_result

        except DeltaException as error:
            exception = DeltaIce.GenericException()
            exception.code = error.get_code()
            exception.data = utils.object_to_dobject(error.get_data())
            exception.message = utils.str_to_external(str(error))

            # Getting the true trace back from the error itself.
            if error.get_traceback() is not None:
                exception.traceback = utils.str_to_external(
                    error.get_traceback())
            else:
                exception.traceback = utils.str_to_external(
                    traceback.format_exc())

            raise exception

        except Exception as error:
            exception = DeltaIce.GenericException()
            exception.message = utils.str_to_external(str(error))

            # Getting the true trace back from the error itself.
            if hasattr(error, 'traceback'):
                exception.traceback = getattr(error, 'traceback')
            else:
                exception.traceback = traceback.format_exc()
            raise exception

    def executeEx(self, request, current=None):
        try:
            start = time.time()

            request['ip'] = self._get_client_ip_(current=current)
            execute_result = \
                self._listener.execute_ex(request)

            end = time.time()
            request_id = execute_result.value['request_id'].value
            time_span = end - start
            IceDispatcher.logger.info("Ice [{0}] executed [{1}]".format(
                request_id, time_span))

            return execute_result

        except DeltaException, error:
            exception = DeltaIce.GenericException()
            exception.code = error.get_code()
            exception.data = utils.object_to_dobject(error.get_data())
            exception.message = utils.str_to_external(str(error))

            # Getting the true trace back from the error itself.
            if error.get_traceback() is not None:
                exception.traceback = utils.str_to_external(
                    error.get_traceback())
            else:
                exception.traceback = utils.str_to_external(
                    traceback.format_exc())

            raise exception

        except Exception, error:
            exception = DeltaIce.GenericException()
            exception.message = utils.str_to_external(str(error))

            # Getting the true trace back from the error itself.
            if hasattr(error, 'traceback'):
                exception.traceback = getattr(error, 'traceback')
            else:
                exception.traceback = traceback.format_exc()
            raise exception
Пример #26
0
class IceJsonListener(Listener):

    #logger = logging.get_logger(name = 'IceDispatcher')

    communicator_logger = logging.get_logger(name='communicator')

    def __init__(self, communicator, name, params, client_request_class=None):
        Listener.__init__(self,
                          communicator,
                          name,
                          params,
                          client_request_class=client_request_class)

        if not params.has_key('service_name'):
            params['service_name'] = self.get_name()

        host = params.get('host')
        port = int(params.get('port'))
        protocol = params.get('protocol')
        if protocol is None:
            protocol = 'tcp'

        ice_url = "%s -h %s -p %d" % (protocol, host, port)

        properties = Ice.createProperties()

        for property_name, property_value in params.iteritems():
            #Passing configs to Ice as properties. Ice will pick its
            #own configs and ignore others.
            properties.setProperty(property_name, property_value)

        data = Ice.InitializationData()
        data.properties = properties

        self._proxy = Ice.initialize(sys.argv, data)
        self._adapter = self._proxy.createObjectAdapterWithEndpoints(
            get_app().get_name(), ice_url)

        self.add_service(IceJsonDispatcher(self), name=params['service_name'])

    def add_service(self, service, **kwargs):
        '''
        Add a service to listener.
        
        @param service: service object
        '''

        name = kwargs.get('name', None)

        self._adapter.add(service, self._proxy.stringToIdentity(name))
        self._adapter.activate()

    def start(self):
        self._proxy.waitForShutdown()

    def stop(self, force):
        self._proxy.destroy()

    def login(self, ip, user_name, password, **options):
        '''
        Logins in application.
        
        @param ip: client IP address
        @param user_name: user name
        @param password: user password
        
        @note: This method is existed for backward compability.
            `login_ex' should be used instead.
        '''
        start = time.time()
        login_result = \
            super(IceJsonListener, self).login(ip, user_name, password, **options)

        end = time.time()
        time_span = end - start
        IceJsonListener.communicator_logger.info(
            "Ice-Json [{0}] login [{1}]".format(login_result, time_span))

        return login_result

    def logout(self, ip, ticket, user_name):
        '''
        Log outs the user.

        @param ip: client ip
        @param ticket: user ticket
        @param user_name: user name
        '''
        start = time.time()
        logout_result = \
            super(IceJsonListener, self).logout(ip, ticket, user_name)

        end = time.time()
        time_span = end - start
        IceJsonListener.communicator_logger.info(
            "Ice-Json [{0}] logout [{1}]".format(ticket, time_span))
        return logout_result

    def execute_ex(self, request, **options):
        '''
        Executes the given request.

        @param request: client request

        @return: object
        '''
        start = time.time()

        execute_result = \
            super(IceJsonListener, self).execute_ex(request, **options)

        end = time.time()
        request_id = execute_result["request_id"]
        time_span = end - start
        IceJsonListener.communicator_logger.info(
            "Ice-Json [{0}] executed [{1}]".format(request_id, time_span))

        return execute_result
Пример #27
0
class ChannelManager(DeltaObject):
    '''
    Provides basic functionality to manipulate channels.
    '''

    LOGGER = logging_services.get_logger(name='channel')

    def __init__(self):
        '''
        '''

        DeltaObject.__init__(self)

        self._channels = {}
        self._enabled = None

    def _get_certificate(self, channel_id, **options):
        '''
        Returns certificate content.
        
        @param channel_id: cannel id.
        @param **options:
            certificate_required: determines whether certificate verification is required. (Default is True)
         
        @rtype: string
        @return: certificate content.

        '''

        file_name = '{0}.cert'.format(channel_id).lower()
        settings_path = os.path.join(get_application_dir(), 'settings')
        certificate_path = os.path.join(settings_path, 'certificates')
        certificate_file = os.path.join(certificate_path, file_name)

        certificate_required = options.get('certificate_required')
        if certificate_required is None:
            certificate_required = True

        message = 'Loading certificate file [{0}]'
        ChannelManager.LOGGER.debug(message.format(certificate_file))
        if not os.path.exists(certificate_file):
            message = 'Checking certificate required flag is [{0}] for channel [{1}]'
            ChannelManager.LOGGER.debug(
                message.format(certificate_required, channel_id))
            if certificate_required:
                message = 'Certificate file [{0}] not found.'
                raise CertificateFileNotFoundException(
                    message.format(certificate_file))
            return unique_id_services.get_id('uuid')

        certificate = open(certificate_file, 'rb').read()
        return certificate

    def enable_channel(self, channel_id, flag):
        '''
        Enables or disables a channel. 
        
        @param channel_id: channel ID
        @param flag: True or False
        '''

        message = 'Trying to enable channel [{0}]'
        if not flag:
            message = 'Trying to disable channel [{0}]'
        ChannelManager.LOGGER.debug(message.format(channel_id))

        # Getting channel information
        channel = self.get(channel_id)

        # Setting flag
        channel.enabled = flag

        message = 'Channel [{0}] enabled successfully'
        if not flag:
            message = 'Channel [{0}] disabled successfully'
        ChannelManager.LOGGER.info(message.format(channel_id))

    def is_registered(self, channel_id):
        '''
        Returns True if the given channel is already registered.
        
        @param channel_id: channel ID
        
        @rtype: bool
        @return: True or False
        '''

        return channel_id in self._channels

    def get(self, channel_id):
        '''
        Returns channel information according to the given channel ID.
        
        @param channel_id: channel ID
        
        @rtype: DynamicObject<id,
                              description,
                              certificate,
                              certificate_required,
                              enabled>
        @return: channel information
        '''

        channel = self._channels.get(channel_id)

        if channel is None:
            message = _('Channel [{0}] is not registered.')
            raise ChannelIsNotRegisteredException(message.format(channel_id))

        return channel

    def try_get_by_certificate(self, certificate):
        '''
        Returns channel information corresponded to the given certificate.
        
        @param certificate: certificate
        
        @rtype: DynamicObject<id,
                              description,
                              certificate,
                              certificate_required,
                              enabled>
        @return: channel information
        '''

        for channel in self._channels.values():
            if certificate is not None and \
                channel.certificate.strip() == certificate.strip():
                return channel

        return None

    def get_all(self, **options):
        '''
        Returns information of all channels.
        
        @rtype: [DynamicObject<id,
                               description,
                               certificate,
                               certificate_required,
                               enabled>]
        @return: all channels
        '''

        return self._channels.values()

    @delta_event('register_channel')
    def register(self, channel_id, certificate, **options):
        '''
        Registers a new channel.
        
        @param channel_id: channel ID
        @param certificate: certificate content
        @param **options: 
            description: channel description
            enabled: channel enable flag
        '''

        message = 'Trying to register channel [{0}]'
        ChannelManager.LOGGER.debug(message.format(channel_id))

        # Checking channel existence
        if self.is_registered(channel_id):
            message = _('Channel {0} is already registered.')
            raise ChannelManagerException(message.format(channel_id))

        # Checking the previous channel with the same certificate
        registered_channel = \
            self.try_get_by_certificate(certificate)
        if registered_channel is not None:
            message = _('Certificate is in use.')
            raise ChannelManagerException(message)

        # Deciding on important parameters
        options['description'] = options.get('description')
        options['enabled'] = options.get('enabled')
        if options['enabled'] is None:
            options['enabled'] = True
        options['certificate_required'] = options.get('certificate_required')
        if options['certificate_required'] is None:
            options['certificate_required'] = True

        # Setting allowed and denied commands
        options['allowed'] = options.get('allowed')
        options['denied'] = options.get('denied')

        # Creating channel information
        channel = DynamicObject(id=channel_id, certificate=certificate)
        channel.update(options)

        # Registering channel
        self._channels[channel_id] = channel

        message = 'Channel [{0}] successfully registered'
        ChannelManager.LOGGER.info(message.format(channel_id))

    def unregister(self, channel_id, **options):
        '''
        Unregisters a channel.
        
        @param channel_id: channel ID
        '''

        message = 'Trying to unregister channel [{0}]'
        ChannelManager.LOGGER.debug(message.format(channel_id))

        # Getting channel information
        channel = self.get(channel_id)

        # Unregistering the channel
        self._channels.pop(channel.id)

        message = 'Channel [{0}] successfully unregistered'
        ChannelManager.LOGGER.info(message.format(channel_id))

    def get_current_channel_id(self):
        '''
        Returns current channel that user logged in with.
        
        @rtype: str
        @return: channel ID
        '''

        session = get_current_session()
        if session is not None:
            context = session.get_context()
            return context.get('channel')

        return None

    def load(self):
        '''
        Loads all channels.
        '''

        try:
            message = 'Loading channels'
            ChannelManager.LOGGER.debug(message)

            config_store = config_services.get_app_config_store('channel')
            self._enabled = config_store.get('global', 'enabled')
            if self._enabled is not None:
                self._enabled = eval(self._enabled)
            else:
                self._enabled = True

            if self._enabled:
                for section in config_store.get_sections():
                    if section != 'global':
                        section_data = config_store.get_section_data(section)
                        channel_id = section
                        for key in section_data:
                            section_data[key] = eval(str(section_data[key]))

                        certificate = self._get_certificate(
                            channel_id, **section_data)
                        self.register(channel_id, certificate, **section_data)
            else:
                message = 'Channel manager is disabled'
                ChannelManager.LOGGER.info(message)

        except ConfigFileNotFoundException:
            message = 'Channel settings not found and channel manager is disabled'
            ChannelManager.LOGGER.info(message)
            self._enabled = False

    def is_enable(self):
        '''
        Returns True if the channel manager is enable.
        
        @rtype: bool
        @return: True or False
        '''

        return self._enabled