forked from di-unipi-socc/Sommelier
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtopologyvalidator.py
382 lines (307 loc) · 16.7 KB
/
topologyvalidator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
from toscaparser.elements.entity_type import EntityType
from toscaparser.tosca_template import ToscaTemplate
class TopologyValidator():
customDefinition = {}
toscaBaseTypes = {}
# Checks whether type1 is coherent with type2 (i.e., whether type1 is the same type or a sub-type of type2)
def checkTypeCoherence(self, type1, type2):
passed = (type1 == type2)
if self.customDefinition.has_key(type1):
type1def = self.customDefinition.get(type1)
else:
type1def = self.toscaBaseTypes.get(type1)
if type1def is not None:
while (passed == False and type1def.has_key('derived_from')):
type1 = type1def.get('derived_from')
if type1 == type2:
passed = True
type1 = type1def.get('derived_from')
if self.customDefinition.has_key(type1):
type1def = self.customDefinition.get(type1)
else:
type1def = self.toscaBaseTypes.get(type1)
return passed
# Returns the definition of the requirement "reqName" in the node type "nodeType" (if any)
def getRequirementDefinition(self, reqName, nodeType):
nodeTypeDef = self.getTypeDefinition(nodeType)
# check whether "nodeType" defines "reqName"
reqDef = None
if nodeTypeDef.has_key("requirements"):
reqDefinitions = nodeTypeDef.get('requirements')[0]
if reqName in reqDefinitions:
reqDef = reqDefinitions.get(reqName)
# if "reqName" has been found, returns the corresponding "reqDef"
if reqDef is not None:
return reqDef
# otherwise, looks for "capName" in the parent "nodeType"
if nodeTypeDef.has_key('derived_from'):
return self.getRequirementDefinition(reqName,nodeTypeDef.get('derived_from'))
# if there is no parent "nodeType", returns "None"
return None
# Returns the definition of the capability "capName" in the node type "nodeType" (if any)
def getCapabilityDefinition(self, capName, nodeType):
nodeTypeDef = self.getTypeDefinition(nodeType)
# check whether "nodeType" defines "capName"
capDef = None
if nodeTypeDef.has_key("capabilities"):
capDefinitions = nodeTypeDef.get('capabilities')
if capName in capDefinitions:
capDef = capDefinitions.get(capName)
# if "capName" has not been found, looks for "capName" in the parent "nodeType" (if any)
if capDef is None and nodeTypeDef.has_key('derived_from'):
return self.getCapabilityDefinition(capName,nodeTypeDef.get('derived_from'))
return capDef
# Returns the definition of the node with type "nodeType" (if any)
def getTypeDefinition(self, nodeType):
typeDef = None
if self.customDefinition.has_key(nodeType):
typeDef = self.customDefinition.get(nodeType)
elif self.toscaBaseTypes.has_key(nodeType):
typeDef = self.toscaBaseTypes.get(nodeType)
return typeDef
# Returns the node template of the node called "nodeName" (if any)
def getNode(self, nodeName, nodeTemplates):
# Assigns the type of "nodeTemplate" to "nodeType"
node = None
for n in nodeTemplates:
if n.name == nodeName:
node = n
return node
# Check whether the "node_type_name" of the requirement definition "reqDef" is coherent with "nodeType"
def checkNodeType(self, reqDef, nodeType):
if reqDef.has_key('node'):
reqDefNodeType = reqDef.get('node')
return self.checkTypeCoherence(nodeType, reqDefNodeType)
return True
# Returns the type of the capability "capability"
def getCapabilityType(self, capability, node):
capabilityType = None
if capability in self.toscaBaseTypes or capability in self.customDefinition:
capabilityType = capability
else:
if self.getCapabilityDefinition(capability, node.type) is not None:
if self.getCapabilityDefinition(capability, node.type).has_key('type'):
capabilityType = self.getCapabilityDefinition(capability, node.type).get('type')
return capabilityType
# Check whether the the type of the capability "capability" is coherent with the type of the capability defined from the requirement definition "reqDef"
def checkCapabilityType(self, reqDef, capability, node):
# Assigns the capability type of the requirement definition to "reqDefCap"
if reqDef.has_key('capability'):
reqDefCap = reqDef.get('capability')
capabilityType = self.getCapabilityType(capability, node)
return self.checkTypeCoherence(capabilityType, reqDefCap)
return True
# Check whether the type of the capabilities of "capabilityList" are coherent with the type of the capability defined from the requirement definition "reqDef"
def checkCapabilitiesType(self, reqDef, capabilityList, node):
for capability in capabilityList:
if self.checkCapabilityType(reqDef,capability,node) == True:
return True
return False
# Returns the type of the relationship "relationship"
def getRelationshipType(self, relationship, node):
if type(relationship) is dict:
if relationship.has_key('type'):
relationshipType = relationship.get('type')
else:
if relationship in self.toscaBaseTypes or relationship in self.customDefinition:
relationshipType = relationship
else:
for rt in node.get_relationship_template():
if rt.name == relationship:
relationshipType = rt.type
return relationshipType
# Check whether the type of the relationship "relationship" is coherent with the type defined from the relationship definition "reqDef"
def checkRelationshipType(self, reqDef, relationship, node):
# Assigns the relationship type of the requirement definition to "reqDefRel"
if reqDef.has_key('relationship'):
reqDefRel = reqDef.get('relationship')
if type(reqDefRel) is dict:
if reqDefRel.has_key('type'):
reqDefRel = reqDefRel.get('type')
# Assigns the relationship type to "relationshipType"
relationshipType = self.getRelationshipType(relationship,node)
# Check whether "reqDefRel" is coherent with "relationshipType"
return self.checkTypeCoherence(relationshipType, reqDefRel)
# Check whether the relationship is valid and return the type of the target capability or None
def checkRelationship(self, reqDef, relationship, targetNode, node, targetCapability):
# Assigns the relationship type of the requirement definition to "reqDefRel"
if reqDef.has_key('relationship'):
reqDefRel = reqDef.get('relationship')
if type(reqDefRel) is dict:
if reqDefRel.has_key('type'):
reqDefRel = reqDefRel.get('type')
# Assigns the relationship type to "relationshipType"
relationshipType = self.getRelationshipType(relationship,node)
######### CONTROLLI PUNTO 2 #########
# Assigns the valid_target_types of the relationship to "validTargetTypes"
validTargetTypes = self.getValidTargetTypes(relationshipType)
if validTargetTypes is not [] and validTargetTypes is not None: # PASSA LA VERIFICA
# Case 1 - the relationship_template of the target is a capability
if targetCapability is not None:
# Assigns the capability type of the "target capability" to "targetCapabilityType"
targetCapabilityType = self.getCapabilityType(targetCapability,targetNode)
# Check whether the capability type is coherent with the capabilities type of the valid_target_type
for validTargetType in validTargetTypes:
if self.checkTypeCoherence(targetCapabilityType,validTargetType) == True:
return targetCapabilityType
return None
# Case 2 - the relationship_template of the target is a node
else:
# Retrieves the capabilities of the target node
targetCapabilities = targetNode.get_capabilities()
# Check whether the capability type of the target node are coherent with the capabilities type of the valid_target_type
for cap in targetCapabilities:
capType = self.getCapabilityType(cap,targetNode)
for validTargetType in validTargetTypes:
if self.checkTypeCoherence(capType,validTargetType) == True:
return capType
return None
# Returns the field "valid_target_types" of the relationship with type "relationshipType"
def getValidTargetTypes(self, relationshipType):
relationshipTypeDef = self.getTypeDefinition(relationshipType)
validTargetTypes = None
if relationshipTypeDef.has_key("valid_target_types"):
validTargetTypes = relationshipTypeDef.get('valid_target_types')
# if "validTargetTypes" has been found, returns the "valid_target_types"
if validTargetTypes is not None:
return validTargetTypes
# otherwise, looks for "validTargetTypes" in the parent "relationshipType" (if any)
if relationshipTypeDef.has_key("derived_from"):
return self.getValidTargetTypes(relationshipTypeDef.get('derived_from'))
# if there is no parent "relationship", returns "None"
return None
# Returns the field "valid_source_types" of a node with type "nodeType"
def getValidSourceTypesNode(self, capabilityType, nodeType):
nodeTypeDef = self.getTypeDefinition(nodeType)
validSourceTypes = None
if nodeTypeDef.has_key("capabilities"):
capabilities = nodeTypeDef.get('capabilities')
for cap in capabilities.values():
if cap.get('type') == capabilityType:
validSourceTypes = cap.get('valid_source_types')
# if "validSourceTypes" has been found, returns the "valid_source_types"
if validSourceTypes is not None:
return validSourceTypes
# otherwise, looks for "validTargetTypes" in the parent "nodeType" (if any)
if nodeTypeDef.has_key("derived_from"):
return self.getValidSourceTypesNode(capabilityType,nodeTypeDef.get('derived_from'))
# if there is no parent "nodeType", returns "None"
return None
# Check whether the types of the nodes defined from the field "valid_source_types" of a "target node" are coherent with the type of a "source node"
def checkValidSourceTypesNode(self, targetCapabilityType, targetNode, node):
validSourceTypes = self.getValidSourceTypesNode(targetCapabilityType,targetNode.type)
if validSourceTypes is not None:
for elem in validSourceTypes:
if self.checkTypeCoherence(node.type,elem) is True:
return True
return False
return True
# Returns the field "valid_source_types" of a capability with type "capabilityType"
def getValidSourceTypesCapability(self, capabilityType):
capTypeDef = self.getTypeDefinition(capabilityType)
validSourceTypes = None
if capTypeDef.has_key("valid_source_types"):
validSourceTypes = capTypeDef.get('valid_source_types')
# if "validSourceTypes" has been found, returns the "valid_source_types"
if validSourceTypes is not None:
return validSourceTypes
# otherwise, looks for "validSourceTypes" in the parent "capType"
if capTypeDef.has_key("derived_from"):
return self.getValidSourceTypesCapability(capTypeDef.get('derived_from'))
# if there is no parent "nodeType", returns "None"
return None
# Check whether the types of the nodes defined from the field "valid_source_types" of a capability are coherent with the type of a "source node"
def checkValidSourceTypesCapability(self, capabilityType, node):
validSourceTypes = self.getValidSourceTypesCapability(capabilityType)
if validSourceTypes is not None:
for elem in validSourceTypes:
if self.checkTypeCoherence(node.type,elem) == True:
return True
return False
return True
# Returns a structure with the summarize of the validation
def validate(self, path):
serviceTemplate = ToscaTemplate(path, None, True)
self.toscaBaseTypes = EntityType.TOSCA_DEF
self.customDefinition = serviceTemplate._get_all_custom_defs()
validation = {}
if hasattr(serviceTemplate, 'nodetemplates'):
nodetemplates = serviceTemplate.nodetemplates
if nodetemplates:
for node in nodetemplates:
relationshipNode = []
capabilityNode = []
reqs = node.requirements
rName = None
validation[node.name] = {}
for r in reqs:
rName = r.keys()[0]
reqError = []
# Gets the requirement definition of "rName"
reqDef = self.getRequirementDefinition(rName,node.type)
if (reqDef is None):
reqError.append([1.1])
else:
# Isolates the names of the target node and capability
targetNode = None
targetCapability = None
relationship = None
if type(r.get(rName)) == str:
targetNode = r.get(rName)
else:
rProps = r.get(rName)
# If "node" is defined, assigns it to "targetNode"
if "node" in rProps:
targetNode = rProps.get("node")
# If "capability" is defined, assigns it to "targetCapability"
if "capability" in rProps:
targetCapability = rProps.get("capability")
# If "relationship" is defined, assigns it to ""
if "relationship" in rProps:
relationship = rProps.get("relationship")
# Retrieves the dictionary defining the target node
targetNode = self.getNode(targetNode,nodetemplates)
# Check if there is a target node
if targetNode is None:
reqError.append([1.1])
validation[node.name].update({rName: reqError})
break
# Checks whether the target node type is coherent with that declared in "reqDef"
if (self.checkNodeType(reqDef,targetNode.type) is False):
reqError.append([1.2, targetNode.type, targetNode.name])
# Assigns the capability type of the target node to "targetCapabilityType"
if targetCapability is not None:
# Checks whether the target node capability is coherent with that declared in "reqDef"
if self.checkCapabilityType(reqDef, targetCapability, targetNode) is False:
reqError.append([1.3])
else:
# Retrieves the capabilities of the target node
targetCapabilities = targetNode.get_capabilities()
# Checks whether at least a target node capability is coherent with that declared in "reqDef"
if self.checkCapabilitiesType(reqDef,targetCapabilities,targetNode) == False:
reqError.append([1.4, targetNode.name, reqDef.get("capability")])
# Assigns the relationship type of the target node to "relationshipType"
if relationship is not None:
# Check whether the type of the relationship is coherent with that declared in "reqDef"
if self.checkRelationshipType(reqDef,relationship,node) == False:
reqError.append([1.5, targetNode.name])
# Assigns the type of the target capability to "targetCapabilityType"
targetCapabilityType = self.checkRelationship(reqDef,relationship,targetNode,node,targetCapability)
# Case 1 - the "targetCapabilityType" is not valid
if targetCapabilityType is None:
# Case 1.1 - the targetCapability is defined, but its type is not valid with that required
if targetCapability is not None:
reqError.append([2.1, targetCapability])
# Case 1.2 - the targetCapability is not defined and the target node does not offer valid capabilities
else:
reqError.append([2.2, targetNode.name])
# Case 2 - the targetCapabilityType is defined
else:
# Case 2.1 - check whether the type of the target capability is coherent with that defined from the target capability definition
if self.checkValidSourceTypesCapability(targetCapabilityType,node) == False:
reqError.append([3.1, node.type])
# Case 2.2 - check whether the type of the target capability is coherent with that defined from the target node definition
if self.checkValidSourceTypesNode(targetCapabilityType,targetNode,node) == False:
reqError.append([3.2, node.type, targetNode.name])
validation[node.name].update({rName: reqError})
return validation