vFW and vDNS support added to azure-plugin
[multicloud/azure.git] / azure / aria / aria-extension-cloudify / src / aria / aria / modeling / service_changes.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 ARIA modeling service changes module
18 """
19
20 # pylint: disable=no-self-argument, no-member, abstract-method
21
22 from collections import namedtuple
23
24 from sqlalchemy import (
25     Column,
26     Text,
27     DateTime,
28     Enum,
29 )
30 from sqlalchemy.ext.declarative import declared_attr
31
32 from .types import (List, Dict)
33 from .mixins import ModelMixin
34 from . import relationship
35
36
37 class ServiceUpdateBase(ModelMixin):
38     """
39     Deployment update model representation.
40     """
41     __tablename__ = 'service_update'
42
43     __private_fields__ = ('service_fk',
44                           'execution_fk')
45
46     created_at = Column(DateTime, nullable=False, index=True)
47     service_plan = Column(Dict, nullable=False)
48     service_update_nodes = Column(Dict)
49     service_update_service = Column(Dict)
50     service_update_node_templates = Column(List)
51     modified_entity_ids = Column(Dict)
52     state = Column(Text)
53
54     # region association proxies
55
56     @declared_attr
57     def execution_name(cls):
58         return relationship.association_proxy('execution', cls.name_column_name())
59
60     @declared_attr
61     def service_name(cls):
62         return relationship.association_proxy('service', cls.name_column_name())
63
64     # endregion
65
66     # region one_to_one relationships
67
68     # endregion
69
70     # region one_to_many relationships
71
72     @declared_attr
73     def steps(cls):
74         return relationship.one_to_many(cls, 'service_update_step')
75
76     # endregion
77
78     # region many_to_one relationships
79
80     @declared_attr
81     def execution(cls):
82         return relationship.one_to_one(cls, 'execution', back_populates=relationship.NO_BACK_POP)
83
84     @declared_attr
85     def service(cls):
86         return relationship.many_to_one(cls, 'service', back_populates='updates')
87
88     # endregion
89
90     # region foreign keys
91
92     @declared_attr
93     def execution_fk(cls):
94         return relationship.foreign_key('execution', nullable=True)
95
96     @declared_attr
97     def service_fk(cls):
98         return relationship.foreign_key('service')
99
100     # endregion
101
102     def to_dict(self, suppress_error=False, **kwargs):
103         dep_update_dict = super(ServiceUpdateBase, self).to_dict(suppress_error)     #pylint: disable=no-member
104         # Taking care of the fact the DeploymentSteps are _BaseModels
105         dep_update_dict['steps'] = [step.to_dict() for step in self.steps]
106         return dep_update_dict
107
108
109 class ServiceUpdateStepBase(ModelMixin):
110     """
111     Deployment update step model representation.
112     """
113
114     __tablename__ = 'service_update_step'
115
116     __private_fields__ = ('service_update_fk',)
117
118     _action_types = namedtuple('ACTION_TYPES', 'ADD, REMOVE, MODIFY')
119     ACTION_TYPES = _action_types(ADD='add', REMOVE='remove', MODIFY='modify')
120
121     _entity_types = namedtuple(
122         'ENTITY_TYPES',
123         'NODE, RELATIONSHIP, PROPERTY, OPERATION, WORKFLOW, OUTPUT, DESCRIPTION, GROUP, PLUGIN')
124     ENTITY_TYPES = _entity_types(
125         NODE='node',
126         RELATIONSHIP='relationship',
127         PROPERTY='property',
128         OPERATION='operation',
129         WORKFLOW='workflow',
130         OUTPUT='output',
131         DESCRIPTION='description',
132         GROUP='group',
133         PLUGIN='plugin'
134     )
135
136     action = Column(Enum(*ACTION_TYPES, name='action_type'), nullable=False)
137     entity_id = Column(Text, nullable=False)
138     entity_type = Column(Enum(*ENTITY_TYPES, name='entity_type'), nullable=False)
139
140     # region association proxies
141
142     @declared_attr
143     def service_update_name(cls):
144         return relationship.association_proxy('service_update', cls.name_column_name())
145
146     # endregion
147
148     # region one_to_one relationships
149
150     # endregion
151
152     # region one_to_many relationships
153
154     # endregion
155
156     # region many_to_one relationships
157
158     @declared_attr
159     def service_update(cls):
160         return relationship.many_to_one(cls, 'service_update', back_populates='steps')
161
162     # endregion
163
164     # region foreign keys
165
166     @declared_attr
167     def service_update_fk(cls):
168         return relationship.foreign_key('service_update')
169
170     # endregion
171
172     def __hash__(self):
173         return hash((getattr(self, self.id_column_name()), self.entity_id))
174
175     def __lt__(self, other):
176         """
177         the order is 'remove' < 'modify' < 'add'
178         :param other:
179         :return:
180         """
181         if not isinstance(other, self.__class__):
182             return not self >= other
183
184         if self.action != other.action:
185             if self.action == 'remove':
186                 return_value = True
187             elif self.action == 'add':
188                 return_value = False
189             else:
190                 return_value = other.action == 'add'
191             return return_value
192
193         if self.action == 'add':
194             return self.entity_type == 'node' and other.entity_type == 'relationship'
195         if self.action == 'remove':
196             return self.entity_type == 'relationship' and other.entity_type == 'node'
197         return False
198
199
200 class ServiceModificationBase(ModelMixin):
201     """
202     Deployment modification model representation.
203     """
204
205     __tablename__ = 'service_modification'
206
207     __private_fields__ = ('service_fk',)
208
209     STARTED = 'started'
210     FINISHED = 'finished'
211     ROLLEDBACK = 'rolledback'
212
213     STATES = [STARTED, FINISHED, ROLLEDBACK]
214     END_STATES = [FINISHED, ROLLEDBACK]
215
216     context = Column(Dict)
217     created_at = Column(DateTime, nullable=False, index=True)
218     ended_at = Column(DateTime, index=True)
219     modified_node_templates = Column(Dict)
220     nodes = Column(Dict)
221     status = Column(Enum(*STATES, name='service_modification_status'))
222
223     # region association proxies
224
225     @declared_attr
226     def service_name(cls):
227         return relationship.association_proxy('service', cls.name_column_name())
228
229     # endregion
230
231     # region one_to_one relationships
232
233     # endregion
234
235     # region one_to_many relationships
236
237     # endregion
238
239     # region many_to_one relationships
240
241     @declared_attr
242     def service(cls):
243         return relationship.many_to_one(cls, 'service', back_populates='modifications')
244
245     # endregion
246
247     # region foreign keys
248
249     @declared_attr
250     def service_fk(cls):
251         return relationship.foreign_key('service')
252
253     # endregion