vFW and vDNS support added to azure-plugin
[multicloud/azure.git] / azure / aria / aria-extension-cloudify / src / aria / aria / storage / core.py
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements.  See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License.  You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 """
17 Storage API management.
18 """
19
20 import copy
21 from contextlib import contextmanager
22
23 from aria.logger import LoggerMixin
24 from . import sql_mapi
25
26 __all__ = (
27     'Storage',
28     'ModelStorage',
29     'ResourceStorage'
30 )
31
32
33 class Storage(LoggerMixin):
34     """
35     Base class for storage managers.
36     """
37     def __init__(self,
38                  api_cls,
39                  api_kwargs=None,
40                  items=(),
41                  initiator=None,
42                  initiator_kwargs=None,
43                  **kwargs):
44         """
45         :param api_cls: API class for each entry
46         :param api_kwargs:
47         :param items: items to register
48         :param initiator: function which initializes the storage before the first use; this function
49          should return a dict, this dict would be passed in addition to the API kwargs; this enables
50          the creation of non-serializable objects
51         :param initiator_kwargs:
52         :param kwargs:
53         """
54         super(Storage, self).__init__(**kwargs)
55         self.api = api_cls
56         self.registered = {}
57         self._initiator = initiator
58         self._initiator_kwargs = initiator_kwargs or {}
59         self._api_kwargs = api_kwargs or {}
60         self._additional_api_kwargs = {}
61         if self._initiator:
62             self._additional_api_kwargs = self._initiator(**self._initiator_kwargs)
63         for item in items:
64             self.register(item)
65         self.logger.debug('{name} object is ready: {0!r}'.format(
66             self, name=self.__class__.__name__))
67
68     @property
69     def _all_api_kwargs(self):
70         kwargs = self._api_kwargs.copy()
71         kwargs.update(self._additional_api_kwargs)
72         return kwargs
73
74     def __repr__(self):
75         return '{name}(api={self.api})'.format(name=self.__class__.__name__, self=self)
76
77     def __getattr__(self, item):
78         try:
79             return self.registered[item]
80         except KeyError:
81             return super(Storage, self).__getattribute__(item)
82
83     @property
84     def serialization_dict(self):
85         return {
86             'api': self.api,
87             'api_kwargs': self._api_kwargs,
88             'initiator': self._initiator,
89             'initiator_kwargs': self._initiator_kwargs
90         }
91
92     def register(self, entry):
93         """
94         Register an API.
95
96         :param entry:
97         """
98         raise NotImplementedError('Subclass must implement abstract register method')
99
100
101 class ResourceStorage(Storage):
102     """
103     Manages storage resource APIs ("RAPIs").
104     """
105     def register(self, name):
106         """
107         Register a storage resource API ("RAPI").
108
109         :param name: name
110         """
111         self.registered[name] = self.api(name=name, **self._all_api_kwargs)
112         self.registered[name].create()
113         self.logger.debug('setup {name} in storage {self!r}'.format(name=name, self=self))
114
115
116 class ModelStorage(Storage):
117     """
118     Manages storage model APIs ("MAPIs").
119     """
120     def __init__(self, *args, **kwargs):
121         if kwargs.get('initiator', None) is None:
122             kwargs['initiator'] = sql_mapi.init_storage
123         super(ModelStorage, self).__init__(*args, **kwargs)
124
125     def register(self, model_cls):
126         """
127         Register a storage model API ("MAPI").
128
129         :param model_cls: model API to register
130         """
131         model_name = model_cls.__modelname__
132         if model_name in self.registered:
133             self.logger.debug('{name} already in storage {self!r}'.format(name=model_name,
134                                                                           self=self))
135             return
136         self.registered[model_name] = self.api(name=model_name,
137                                                model_cls=model_cls,
138                                                **self._all_api_kwargs)
139         self.registered[model_name].create()
140         self.logger.debug('setup {name} in storage {self!r}'.format(name=model_name, self=self))
141
142     def drop(self):
143         """
144         Drop all the tables.
145         """
146         for mapi in self.registered.itervalues():
147             mapi.drop()
148
149     @contextmanager
150     def instrument(self, *instrumentation):
151         original_instrumentation = {}
152
153         try:
154             for mapi in self.registered.itervalues():
155                 original_instrumentation[mapi] = copy.copy(mapi._instrumentation)
156                 mapi._instrumentation.extend(instrumentation)
157             yield self
158         finally:
159             for mapi in self.registered.itervalues():
160                 mapi._instrumentation[:] = original_instrumentation[mapi]