almahmoud 7 лет назад
Родитель
Сommit
0fc1901623

+ 77 - 1
cloudbridge/cloud/base/provider.py

@@ -11,7 +11,9 @@ except ImportError:  # Python 2
 import six
 
 from cloudbridge.cloud.interfaces import CloudProvider
+from cloudbridge.cloud.interfaces.exceptions import NoHandlerException
 from cloudbridge.cloud.interfaces.exceptions import ProviderConnectionException
+from cloudbridge.cloud.interfaces.provider import HandlerType
 from cloudbridge.cloud.interfaces.resources import Configuration
 
 log = logging.getLogger(__name__)
@@ -78,13 +80,83 @@ class BaseConfiguration(Configuration):
         """
         return self.get('cb_debug', os.environ.get('CB_DEBUG', False))
 
+class EventDispatcher(object):
+    def __init__(self):
+        self.__events = {}
+
+    def subscribe(self, event_name, priority, callback, result_callback=None):
+        """
+        Subscribe a handler by event name to the dispatcher.
+
+        :type event_name: str
+        :param event_name: The name of the event to which you are subscribing
+        the callback function.
+        :type priority: int
+        :param priority: The priority that this handler should be given.
+        When the event is emitted, all handlers will be run in order of
+        priority.
+        :type callback: function
+        :param callback: The callback function that should be called with
+        the parameters given at when the even is emitted.
+        :type result_callback: function
+        :param result_callback: The callback function that should be called
+        after the first callback function, using the return value of that
+        previous function as an argument. This function should accept a
+        `callback_result` parameter in addition to the parameters of the event.
+        :return:  The last return value that is not None from the callback
+        functions. i.e. It will return the `callback` function return value,
+        unless the `result_callback` function has a return value.
+        """
+        if result_callback:
+            handler = EventHandler(HandlerType.INTERCEPTION, callback, result_callback)
+        else:
+            handler = EventHandler(HandlerType.SUBSCRIPTION, callback)
+        if not self.__events.get(event_name):
+            self.__events[event_name] = list()
+        self.__events[event_name].append((priority, handler))
+
+    def emit(self, event_name, args):
+
+        def priority_sort(handler_list):
+            handler_list.sort(key=lambda x: x[0])
+            return handler_list
+
+        if not self.__events.get(event_name):
+            message = "Event '{}' has no subscribed handlers.".\
+                format(event_name)
+            raise NoHandlerException(message)
+
+        result = None
+        for (priority, handler) in priority_sort(self.__events[event_name]):
+            new_result = handler.invoke(args)
+            if new_result:
+                result = new_result
+        return result
+
+
+class EventHandler(object):
+    def __init__(self, handler_type, callback, result_callback=None):
+        self.handler_type = handler_type
+        self.callback = callback
+        self.result_callback = result_callback
+
+    def invoke(self, args):
+        if self.handler_type == HandlerType.SUBSCRIPTION:
+            return self.callback(**args)
+        if self.handler_type == HandlerType.INTERCEPTION:
+            result = self.callback(**args)
+            new_result = self.result_callback(result=result, **args)
+            if new_result:
+                result = new_result
+            return result
 
-class BaseCloudProvider(CloudProvider):
 
+class BaseCloudProvider(CloudProvider):
     def __init__(self, config):
         self._config = BaseConfiguration(config)
         self._config_parser = ConfigParser()
         self._config_parser.read(CloudBridgeConfigLocations)
+        self._events = EventDispatcher()
 
     @property
     def config(self):
@@ -94,6 +166,10 @@ class BaseCloudProvider(CloudProvider):
     def name(self):
         return str(self.__class__.__name__)
 
+    @property
+    def events(self):
+        return self._events
+
     def authenticate(self):
         """
         A basic implementation which simply runs a low impact command to

+ 9 - 0
cloudbridge/cloud/interfaces/exceptions.py

@@ -92,3 +92,12 @@ class DuplicateResourceException(CloudBridgeBaseException):
     result in a DuplicateResourceException.
     """
     pass
+
+
+class NoHandlerException(CloudBridgeBaseException):
+    """
+    Marker interface for object wait exceptions.
+    Thrown when a timeout or errors occurs waiting for an object does not reach
+    the expected state within a specified time limit.
+    """
+    pass

+ 9 - 0
cloudbridge/cloud/interfaces/provider.py

@@ -2,6 +2,7 @@
 Specification for a provider interface
 """
 from abc import ABCMeta, abstractmethod, abstractproperty
+from enum import Enum
 
 
 class CloudProvider(object):
@@ -245,3 +246,11 @@ class DeploymentProvider(object):
         Deploys on given target, where target is an Instance or Container
         """
         pass
+
+
+class HandlerType(Enum):
+    """
+    Handler Types.
+    """
+    SUBSCRIPTION = 'subscription'
+    INTERCEPTION = 'interception'