vFW and vDNS support added to azure-plugin
[multicloud/azure.git] / azure / aria / aria-extension-cloudify / src / aria / aria / storage / core.py
diff --git a/azure/aria/aria-extension-cloudify/src/aria/aria/storage/core.py b/azure/aria/aria-extension-cloudify/src/aria/aria/storage/core.py
new file mode 100644 (file)
index 0000000..7e9b201
--- /dev/null
@@ -0,0 +1,160 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Storage API management.
+"""
+
+import copy
+from contextlib import contextmanager
+
+from aria.logger import LoggerMixin
+from . import sql_mapi
+
+__all__ = (
+    'Storage',
+    'ModelStorage',
+    'ResourceStorage'
+)
+
+
+class Storage(LoggerMixin):
+    """
+    Base class for storage managers.
+    """
+    def __init__(self,
+                 api_cls,
+                 api_kwargs=None,
+                 items=(),
+                 initiator=None,
+                 initiator_kwargs=None,
+                 **kwargs):
+        """
+        :param api_cls: API class for each entry
+        :param api_kwargs:
+        :param items: items to register
+        :param initiator: function which initializes the storage before the first use; this function
+         should return a dict, this dict would be passed in addition to the API kwargs; this enables
+         the creation of non-serializable objects
+        :param initiator_kwargs:
+        :param kwargs:
+        """
+        super(Storage, self).__init__(**kwargs)
+        self.api = api_cls
+        self.registered = {}
+        self._initiator = initiator
+        self._initiator_kwargs = initiator_kwargs or {}
+        self._api_kwargs = api_kwargs or {}
+        self._additional_api_kwargs = {}
+        if self._initiator:
+            self._additional_api_kwargs = self._initiator(**self._initiator_kwargs)
+        for item in items:
+            self.register(item)
+        self.logger.debug('{name} object is ready: {0!r}'.format(
+            self, name=self.__class__.__name__))
+
+    @property
+    def _all_api_kwargs(self):
+        kwargs = self._api_kwargs.copy()
+        kwargs.update(self._additional_api_kwargs)
+        return kwargs
+
+    def __repr__(self):
+        return '{name}(api={self.api})'.format(name=self.__class__.__name__, self=self)
+
+    def __getattr__(self, item):
+        try:
+            return self.registered[item]
+        except KeyError:
+            return super(Storage, self).__getattribute__(item)
+
+    @property
+    def serialization_dict(self):
+        return {
+            'api': self.api,
+            'api_kwargs': self._api_kwargs,
+            'initiator': self._initiator,
+            'initiator_kwargs': self._initiator_kwargs
+        }
+
+    def register(self, entry):
+        """
+        Register an API.
+
+        :param entry:
+        """
+        raise NotImplementedError('Subclass must implement abstract register method')
+
+
+class ResourceStorage(Storage):
+    """
+    Manages storage resource APIs ("RAPIs").
+    """
+    def register(self, name):
+        """
+        Register a storage resource API ("RAPI").
+
+        :param name: name
+        """
+        self.registered[name] = self.api(name=name, **self._all_api_kwargs)
+        self.registered[name].create()
+        self.logger.debug('setup {name} in storage {self!r}'.format(name=name, self=self))
+
+
+class ModelStorage(Storage):
+    """
+    Manages storage model APIs ("MAPIs").
+    """
+    def __init__(self, *args, **kwargs):
+        if kwargs.get('initiator', None) is None:
+            kwargs['initiator'] = sql_mapi.init_storage
+        super(ModelStorage, self).__init__(*args, **kwargs)
+
+    def register(self, model_cls):
+        """
+        Register a storage model API ("MAPI").
+
+        :param model_cls: model API to register
+        """
+        model_name = model_cls.__modelname__
+        if model_name in self.registered:
+            self.logger.debug('{name} already in storage {self!r}'.format(name=model_name,
+                                                                          self=self))
+            return
+        self.registered[model_name] = self.api(name=model_name,
+                                               model_cls=model_cls,
+                                               **self._all_api_kwargs)
+        self.registered[model_name].create()
+        self.logger.debug('setup {name} in storage {self!r}'.format(name=model_name, self=self))
+
+    def drop(self):
+        """
+        Drop all the tables.
+        """
+        for mapi in self.registered.itervalues():
+            mapi.drop()
+
+    @contextmanager
+    def instrument(self, *instrumentation):
+        original_instrumentation = {}
+
+        try:
+            for mapi in self.registered.itervalues():
+                original_instrumentation[mapi] = copy.copy(mapi._instrumentation)
+                mapi._instrumentation.extend(instrumentation)
+            yield self
+        finally:
+            for mapi in self.registered.itervalues():
+                mapi._instrumentation[:] = original_instrumentation[mapi]